/* File: cmd4.c */ /* Purpose: Interface commands */ /* * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke * * This software may be copied and distributed for educational, research, and * not for profit purposes provided that this copyright and statement are * included in all such copies. */ #include "angband.h" /* * Hack -- redraw the screen * * This command performs various low level updates, clears all the "extra" * windows, does a total redraw of the main window, and requests all of the * interesting updates and redraws that I can think of. */ void do_cmd_redraw(void) { /* Hack -- react to changes */ Term_xtra(TERM_XTRA_REACT, 0); /* Verify the keymap */ keymap_init(); #ifdef GRAPHIC_RECALL /* Hack -- erase the "recall" window */ if (term_recall) { Term_activate(term_recall); Term_clear(); Term_fresh(); } #endif #ifdef GRAPHIC_CHOICE /* Hack -- erase the "choice" window */ if (term_choice) { Term_activate(term_choice); Term_clear(); Term_fresh(); } #endif #ifdef GRAPHIC_MIRROR /* Hack -- erase the "mirror" window */ if (term_mirror) { Term_activate(term_mirror); Term_clear(); Term_fresh(); } #endif /* Activate the main screen */ Term_activate(term_screen); /* Actual redraw */ Term_redraw(); /* Combine and Reorder the pack (later) */ p_ptr->notice |= PN_COMBINE | PN_REORDER; /* Update torch */ p_ptr->update |= PU_TORCH; /* Update stuff */ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS); /* Forget lite/view */ p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE); /* Update lite/view */ p_ptr->update |= (PU_VIEW | PU_LITE); /* Update monsters */ p_ptr->update |= (PU_MONSTERS); /* Redraw everything */ p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA); /* Redraw map */ p_ptr->redraw |= (PR_MAP | PR_AROUND); /* Redraw the recall window */ p_ptr->redraw |= (PR_RECENT); /* Redraw the choice window */ p_ptr->redraw |= (PR_CHOOSE); /* Hack -- update */ handle_stuff(); /* Hack -- refresh */ Term_fresh(); } /* * Hack -- change name */ void do_cmd_change_name(void) { char c; bool flag; bool history = FALSE; char tmp[160]; /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Get command */ for (flag = FALSE; !flag; ) { /* Display the player */ display_player(history, FALSE); /* Prompt */ prt("['C' to change name, 'F' to dump file, 'H' for history, or ESCAPE]", 21, 2); /* Query */ c = inkey(); /* Handle */ switch (c) { case 'C': case 'c': get_name(); flag = TRUE; break; case 'F': case 'f': sprintf(tmp, "%s.txt", player_base); if (get_string("File name: ", tmp, 80)) { if (tmp[0] && (tmp[0] != ' ')) { file_character(tmp, FALSE); } } break; case 'H': case 'h': history = !history; break; case ESCAPE: case ' ': case '\n': case '\r': flag = TRUE; break; default: bell(); break; } /* Flush messages */ msg_print(NULL); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Recall the most recent message */ void do_cmd_message_one(void) { /* Recall one message XXX XXX XXX */ prt(format("> %s", message_str(0)), 0, 0); } /* * Show previous messages to the user -BEN- * * The screen format uses line 0 and 23 for headers and prompts, * skips line 1 and 22, and uses line 2 thru 21 for old messages. * * This command shows you which commands you are viewing, and allows * you to "search" for strings in the recall. */ void do_cmd_messages(void) { int i, j, k, n; char finder[80] = ""; /* Total messages */ n = message_num(); /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Start on first message */ i = 0; /* Process requests until done */ while (1) { /* Clear the screen */ clear_screen(); /* Dump up to 20 lines of messages */ for (j = 0; (j < 20) && (i + j < n); j++) { byte a = TERM_WHITE; cptr str = message_str(i+j); /* Handle searches XXX XXX XXX */ if (finder[0] && strstr(str, finder)) a = TERM_YELLOW; /* Dump the messages, bottom to top */ Term_putstr(0, 21-j, -1, a, str); } /* Display header XXX XXX XXX */ prt(format("Message Recall (%d-%d of %d)", i, i+j-1, n), 0, 0); /* Display prompt */ prt("[Press 'p' for older, 'n' for newer, '/' for search, or ESCAPE]", 23, 0); /* Get a command */ k = inkey(); /* Exit on Escape */ if (k == ESCAPE) break; /* Hack -- Save the old index */ j = i; /* Hack -- handle search */ if (k == '/') { /* Prompt */ prt("Find: ", 23, 0); /* Get a search string, or cancel search */ if (!askfor_aux(finder, 80)) finder[0] = '\0'; /* Okay */ continue; } /* Recall more older messages */ if ((k == 'p') || (k == KTRL('P'))) { /* Go older if legal */ if (i + 20 < n) i += 20; } /* Recall more newer messages */ if ((k == 'n') || (k == KTRL('N'))) { /* Go newer if legal */ if (i >= 20) i -= 20; } /* Hack -- Error of some kind */ if (i == j) bell(); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Interact with some options */ static void do_cmd_options_aux(int page, cptr info) { char ch; int i, n = 0; int opt[24]; char buf[80]; /* Lookup the options */ for (i = 0; i < 24; i++) opt[i] = 0; /* Scan the options */ for (i = 0; options[i].o_desc; i++) { /* Notice options on this "page" */ if (options[i].o_page == page) opt[n++] = i; } /* Clear the screen */ clear_screen(); /* Prompt XXX XXX XXX */ sprintf(buf, "%s (RET to advance, y/n to set, ESC to accept) ", info); prt(buf, 0, 0); /* Display the options */ for (i = 0; i < n; i++) { sprintf(buf, "[%c] %-48s ", (*options[opt[i]].o_var) ? 'X' : ' ', options[opt[i]].o_desc); prt(buf, i + 2, 0); } /* Start at the first option */ i = 0; /* Interact with the player */ while (TRUE) { move_cursor(i + 2, 1); ch = inkey(); switch (ch) { case ESCAPE: return; case '-': case '8': i = (n + i - 1) % n; break; case ' ': case '\n': case '\r': case '2': i = (i + 1) % n; break; case 'y': case 'Y': case '6': put_str("X", i + 2, 1); (*options[opt[i]].o_var) = TRUE; break; case 'n': case 'N': case '4': put_str(" ", i + 2, 1); (*options[opt[i]].o_var) = FALSE; break; default: bell(); break; } } } /* * Set or unset various options. * * The user must use the "Ctrl-R" command to "adapt" to changes * in any options which control "visual" aspects of the game. */ void do_cmd_options(void) { int k; /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Interact */ while (1) { /* Clear screen */ clear_screen(); /* Why are we here */ prt("Angband options", 2, 0); /* Give some choices */ prt("(1) User Interface Options", 4, 5); prt("(2) Disturbance Options", 5, 5); prt("(3) Inventory Options", 6, 5); prt("(4) Game-Play Options", 7, 5); prt("(5) Efficiency Options", 8, 5); prt("(6) Special Options", 9, 5); /* Cheating */ if (can_be_wizard) prt("(C) Cheating Options", 10, 5); /* Special choices */ prt("(D) Base Delay Speed", 11, 5); prt("(H) Hitpoint Warning", 12, 5); /* Prompt */ prt("Command: ", 14, 0); /* Get command */ k = inkey(); /* Exit */ if (k == ESCAPE) break; /* General Options */ if (k == '1') { /* Process the general options */ do_cmd_options_aux(1, "User Interface Options"); } /* Disturbance Options */ else if (k == '2') { /* Process the running options */ do_cmd_options_aux(2, "Disturbance Options"); } /* Inventory Options */ else if (k == '3') { /* Process the running options */ do_cmd_options_aux(3, "Inventory Options"); } /* Gameplay Options */ else if (k == '4') { /* Process the game-play options */ do_cmd_options_aux(4, "Game-Play Options"); } /* Efficiency Options */ else if (k == '5') { /* Process the efficiency options */ do_cmd_options_aux(5, "Efficiency Options"); } /* Efficiency Options */ else if (k == '6') { /* Process the efficiency options */ do_cmd_options_aux(6, "Special Options"); } /* Cheating Options XXX XXX XXX */ else if (((k == 'C') || (k == 'c')) && can_be_wizard) { /* Process the cheating options */ do_cmd_options_aux(255, "Cheating Options"); /* Hack -- note use of "cheat" options */ if (cheat_peek) noscore |= 0x0100; if (cheat_hear) noscore |= 0x0200; if (cheat_room) noscore |= 0x0400; if (cheat_xtra) noscore |= 0x0800; if (cheat_know) noscore |= 0x1000; if (cheat_live) noscore |= 0x2000; } /* Hack -- Delay Speed */ else if ((k == 'D') || (k == 'd')) { /* Prompt */ prt("Command: Base Delay Speed", 14, 0); /* Get a new value */ while (1) { prt(format("Current delay speed: %d milliseconds", delay_spd), 18, 0); prt("Delay Speed (0-9 or ESC to accept): ", 16, 0); k = inkey(); if (k == ESCAPE) break; if (isdigit(k)) delay_spd = D2I(k); else bell(); } } /* Hack -- hitpoint warning factor */ else if ((k == 'H') || (k == 'h')) { /* Prompt */ prt("Command: Hitpoint Warning", 14, 0); /* Get a new value */ while (1) { prt(format("Current hitpoint warning: %d%%", hitpoint_warn*10), 18, 0); prt("Hitpoint Warning (0-9 or ESC to accept): ", 16, 0); k = inkey(); if (k == ESCAPE) break; if (isdigit(k)) hitpoint_warn = D2I(k); else bell(); } } /* Unknown option */ else { /* Oops */ bell(); } /* Flush messages */ msg_print(NULL); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; /* Verify the keymap */ keymap_init(); } /* * Ask for a "user pref line" and process it * * XXX XXX XXX Allow absolute file names? */ void do_cmd_pref(void) { char buf[80]; /* Default */ strcpy(buf, ""); /* Ask for a "user pref command" */ if (!get_string("Pref: ", buf, 80)) return; /* Process that pref command */ (void)process_pref_file_aux(buf); } #ifdef ALLOW_MACROS /* * Hack -- append all current macros to the given file */ static errr macro_dump(cptr fname) { int i; FILE *fff; char buf[1024]; /* Build the filename */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, fname); #if defined(MACINTOSH) && !defined(applec) /* Global -- "text file" */ _feate = 'TEXT'; #endif /* Append to the file */ fff = my_fopen(buf, "a"); /* Failure */ if (!fff) return (-1); /* Skip space */ fprintf(fff, "\n\n"); /* Start dumping */ fprintf(fff, "# Automatic macro dump\n\n"); /* Dump them */ for (i = 0; i < macro__num; i++) { /* Start the macro */ fprintf(fff, "# Macro '%d'\n\n", i); /* Extract the action */ ascii_to_text(buf, macro__act[i]); /* Dump the macro */ fprintf(fff, "A:%s\n", buf); /* Extract the action */ ascii_to_text(buf, macro__pat[i]); /* Dump command macros */ if (macro__cmd[i]) fprintf(fff, "C:%s\n", buf); /* Dump normal macros */ else fprintf(fff, "P:%s\n", buf); /* End the macro */ fprintf(fff, "\n\n"); } /* Start dumping */ fprintf(fff, "\n\n\n\n"); /* Close */ my_fclose(fff); /* Success */ return (0); } /* * Hack -- ask for a "trigger" (see below) * * Note the complex use of the "inkey()" function from "io.c". * * The "trigger" must be entered with less than 10 milliseconds * between keypresses, as in "inkey_aux()". */ static void do_cmd_macro_aux(char *buf) { int i, n = 0, w = 0; bool skipping = FALSE; char tmp[1024]; /* Important -- Flush input */ flush(); /* Do not process macros */ inkey_base = TRUE; /* Attempt to read a key */ i = inkey(); /* Save the key */ buf[n++] = i; /* Read the pattern */ while (TRUE) { /* Do not process macros */ inkey_base = TRUE; /* Do not wait for keys */ inkey_scan = TRUE; /* Attempt to read a key */ i = inkey(); /* If a key is ready, acquire it */ if (i) { /* Reset delay */ w = 0; /* Hack -- process "ascii 28" */ if (i == 28) { /* Toggle the "skipping" flag */ skipping = !skipping; } /* Save usable keys */ else if (!skipping) { /* Save the key */ buf[n++] = i; } /* Next */ continue; } /* Excessive delay */ if (w > 30) break; /* Increment and delay */ delay(++w); } /* Terminate */ buf[n] = '\0'; /* Important -- Flush the input */ flush(); /* Convert the trigger */ ascii_to_text(tmp, buf); /* Hack -- display the trigger */ Term_addstr(-1, TERM_WHITE, tmp); } #endif /* * Interact with "macros" * * Note that the macro "action" must be defined before the trigger. * * XXX XXX XXX Need messages for success, plus "helpful" info */ void do_cmd_macros(void) { int i; char tmp[160]; char buf[1024]; #if defined(MACINTOSH) && !defined(applec) _feate = 'TEXT'; #endif /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Process requests until done */ while (1) { /* Clear the screen */ clear_screen(); /* Describe */ Term_putstr(0, 2, -1, TERM_WHITE, "Interact with Macros"); /* Describe that action */ Term_putstr(0, 18, -1, TERM_WHITE, "Current action (if any) shown below:"); /* Analyze the current action */ ascii_to_text(buf, macro__buf); /* Display the current action */ Term_putstr(0, 20, -1, TERM_WHITE, buf); /* Selections */ Term_putstr(5, 4, -1, TERM_WHITE, "(1) Load a user pref file"); #ifdef ALLOW_MACROS Term_putstr(5, 5, -1, TERM_WHITE, "(2) Dump macros"); Term_putstr(5, 6, -1, TERM_WHITE, "(3) Enter a new action"); Term_putstr(5, 7, -1, TERM_WHITE, "(4) Query a macro action"); Term_putstr(5, 8, -1, TERM_WHITE, "(5) Create a command macro"); Term_putstr(5, 9, -1, TERM_WHITE, "(6) Create a normal macro"); Term_putstr(5, 10, -1, TERM_WHITE, "(7) Create an identity macro"); Term_putstr(5, 11, -1, TERM_WHITE, "(8) Create an empty macro"); Term_putstr(5, 12, -1, TERM_WHITE, "(9) Define a special keymap"); #endif /* ALLOW_MACROS */ /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: "); /* Get a command */ i = inkey(); /* Leave */ if (i == ESCAPE) break; /* Load a 'macro' file */ else if (i == '1') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Load a user pref file"); /* Get a filename, handle ESCAPE */ Term_putstr(0, 16, -1, TERM_WHITE, "File: "); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Ask for a file */ if (!askfor_aux(tmp, 70)) continue; /* Process the given filename */ (void)process_pref_file(tmp); } #ifdef ALLOW_MACROS /* Save a 'macro' file */ else if (i == '2') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Save a macro file"); /* Get a filename, handle ESCAPE */ Term_putstr(0, 16, -1, TERM_WHITE, "File: "); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Ask for a file */ if (!askfor_aux(tmp, 70)) continue; /* Drop priv's */ safe_setuid_drop(); /* Dump the macros */ (void)macro_dump(tmp); /* Grab priv's */ safe_setuid_grab(); } /* Enter a new action */ else if (i == '3') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Enter a new action"); /* Go to the correct location */ Term_gotoxy(0, 20); /* Hack -- limit the value */ tmp[80] = '\0'; /* Get an encoded action */ if (!askfor_aux(buf, 80)) continue; /* Extract an action */ text_to_ascii(macro__buf, buf); } /* Query a macro action */ else if (i == '4') { #if 0 /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Query a macro action"); /* Prompt */ Term_putstr(0, 16, -1, TERM_WHITE, "Enter a macro trigger: "); /* Get a macro trigger */ do_cmd_macro_aux(buf); #endif /* XXX XXX XXX */ msg_print("Command not ready."); } /* Create a command macro */ else if (i == '5') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Create a command macro"); /* Prompt */ Term_putstr(0, 16, -1, TERM_WHITE, "Trigger: "); /* Get a macro trigger */ do_cmd_macro_aux(buf); /* Link the macro */ macro_add(buf, macro__buf, TRUE); /* Message */ msg_print("Created a new command macro."); } /* Create a normal macro */ else if (i == '6') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Create a normal macro"); /* Prompt */ Term_putstr(0, 16, -1, TERM_WHITE, "Trigger: "); /* Get a macro trigger */ do_cmd_macro_aux(buf); /* Link the macro */ macro_add(buf, macro__buf, FALSE); /* Message */ msg_print("Created a new normal macro."); } /* Create an identity macro */ else if (i == '7') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Create an identity macro"); /* Prompt */ Term_putstr(0, 16, -1, TERM_WHITE, "Trigger: "); /* Get a macro trigger */ do_cmd_macro_aux(buf); /* Link the macro */ macro_add(buf, buf, FALSE); /* Message */ msg_print("Created a new identity macro."); } /* Create an empty macro */ else if (i == '8') { /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command: Create an empty macro"); /* Prompt */ Term_putstr(0, 16, -1, TERM_WHITE, "Trigger: "); /* Get a macro trigger */ do_cmd_macro_aux(buf); /* Link the macro */ macro_add(buf, "", FALSE); /* Message */ msg_print("Created a new empty macro."); } /* Define a keymap */ else if (i == '9') { char i1, i2, i3; /* Flush the input */ flush(); /* Get the trigger */ if (get_com("Type the trigger keypress: ", &i1) && get_com("Type the resulting keypress: ", &i2) && get_com("Type a direction (or space): ", &i3)) { /* Acquire the array index */ int k = (byte)(i1) % 128; int r = (byte)(i2) % 128; int d = (byte)(i3) % 128; /* Analyze the result key */ keymap_cmds[k] = r; /* Hack -- Analyze the "direction" (always allow numbers) */ keymap_dirs[k] = (isdigit(d) ? (d - '0') : keymap_dirs[d]); /* Success */ msg_format("Keypress 0x%02x mapped to 0x%02x/%d", k, keymap_cmds[k], keymap_dirs[k]); } } #endif /* ALLOW_MACROS */ /* Oops */ else { /* Oops */ bell(); } /* Flush messages */ msg_print(NULL); } /* Load the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Interact with "visuals" */ void do_cmd_visuals(void) { int i; FILE *fff; char tmp[160]; char buf[1024]; #if defined(MACINTOSH) && !defined(applec) _feate = 'TEXT'; #endif /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Interact until done */ while (1) { /* Clear the screen */ clear_screen(); /* Ask for a choice */ prt("Interact with Visuals", 2, 0); /* Give some choices */ prt("(1) Load a user pref file", 4, 5); #ifdef ALLOW_VISUALS prt("(2) Dump monster attr/chars", 5, 5); prt("(3) Dump object attr/chars", 6, 5); prt("(4) Dump feature attr/chars", 7, 5); prt("(5) (unused)", 8, 5); prt("(6) Change monster attr/chars", 9, 5); prt("(7) Change object attr/chars", 10, 5); prt("(8) Change feature attr/chars", 11, 5); prt("(9) (unused)", 12, 5); #endif prt("(0) Reset visuals", 13, 5); /* Prompt */ prt("Command: ", 15, 0); /* Prompt */ i = inkey(); /* Done */ if (i == ESCAPE) break; /* Load a 'pref' file */ else if (i == '1') { /* Prompt */ prt("Command: Load a user pref file", 15, 0); /* Prompt */ prt("File: ", 17, 0); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Query */ if (!askfor_aux(tmp, 70)) continue; /* Process the given filename */ (void)process_pref_file(tmp); } #ifdef ALLOW_VISUALS /* Dump monster attr/chars */ else if (i == '2') { /* Prompt */ prt("Command: Dump monster attr/chars", 15, 0); /* Prompt */ prt("File: ", 17, 0); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Get a filename */ if (!askfor_aux(tmp, 70)) continue; /* Build the filename */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, tmp); /* Drop priv's */ safe_setuid_drop(); /* Append to the file */ fff = my_fopen(buf, "a"); /* Grab priv's */ safe_setuid_grab(); /* Failure */ if (!fff) continue; /* Start dumping */ fprintf(fff, "\n\n"); fprintf(fff, "# Monster attr/char definitions\n\n"); /* Dump monsters */ for (i = 0; i < MAX_R_IDX; i++) { monster_race *r_ptr = &r_info[i]; /* Skip non-entries */ if (!r_ptr->name) continue; /* Dump a comment */ fprintf(fff, "# %s\n", (r_name + r_ptr->name)); /* Dump the monster attr/char info */ fprintf(fff, "R:%d:0x%02X:0x%02X\n\n", i, (byte)(r_ptr->l_attr), (byte)(r_ptr->l_char)); } /* All done */ fprintf(fff, "\n\n\n\n"); /* Close */ my_fclose(fff); /* Message */ msg_print("Dumped monster attr/chars."); } /* Dump object attr/chars */ else if (i == '3') { /* Prompt */ prt("Command: Dump object attr/chars", 15, 0); /* Prompt */ prt("File: ", 17, 0); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Get a filename */ if (!askfor_aux(tmp, 70)) continue; /* Build the filename */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, tmp); /* Drop priv's */ safe_setuid_drop(); /* Append to the file */ fff = my_fopen(buf, "a"); /* Grab priv's */ safe_setuid_grab(); /* Failure */ if (!fff) continue; /* Start dumping */ fprintf(fff, "\n\n"); fprintf(fff, "# Object attr/char definitions\n\n"); /* Dump objects */ for (i = 0; i < MAX_K_IDX; i++) { object_kind *k_ptr = &k_info[i]; /* Skip non-entries */ if (!k_ptr->name) continue; /* Dump a comment */ fprintf(fff, "# %s\n", (k_name + k_ptr->name)); /* Dump the object attr/char info */ fprintf(fff, "K:%d:0x%02X:0x%02X\n\n", i, (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); } /* All done */ fprintf(fff, "\n\n\n\n"); /* Close */ my_fclose(fff); /* Message */ msg_print("Dumped object attr/chars."); } /* Dump feature attr/chars */ else if (i == '4') { /* Prompt */ prt("Command: Dump feature attr/chars", 15, 0); /* Prompt */ prt("File: ", 17, 0); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Get a filename */ if (!askfor_aux(tmp, 70)) continue; /* Build the filename */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, tmp); /* Drop priv's */ safe_setuid_drop(); /* Append to the file */ fff = my_fopen(buf, "a"); /* Grab priv's */ safe_setuid_grab(); /* Failure */ if (!fff) continue; /* Start dumping */ fprintf(fff, "\n\n"); fprintf(fff, "# Feature attr/char definitions\n\n"); /* Dump features */ for (i = 0; i < MAX_F_IDX; i++) { feature_type *f_ptr = &f_info[i]; /* Skip non-entries */ if (!f_ptr->name) continue; /* Dump a comment */ fprintf(fff, "# %s\n", (f_name + f_ptr->name)); /* Dump the feature attr/char info */ fprintf(fff, "F:%d:0x%02X:0x%02X\n\n", i, (byte)(f_ptr->z_attr), (byte)(f_ptr->z_char)); } /* All done */ fprintf(fff, "\n\n\n\n"); /* Close */ my_fclose(fff); /* Message */ msg_print("Dumped feature attr/chars."); } /* Modify monster attr/chars */ else if (i == '6') { static int r = 0; /* Prompt */ prt("Command: Change monster attr/chars", 15, 0); /* Hack -- query until done */ while (1) { monster_race *r_ptr = &r_info[r]; int da = (byte)(r_ptr->r_attr); int dc = (byte)(r_ptr->r_char); int ca = (byte)(r_ptr->l_attr); int cc = (byte)(r_ptr->l_char); /* Label the object */ Term_putstr(5, 17, -1, TERM_WHITE, format("Monster = %d, Name = %-40.40s", r, (r_name + r_ptr->name))); /* Label the Default values */ Term_putstr(10, 19, -1, TERM_WHITE, format("Default attr/char = %3u / %3u", da, dc)); Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 19, da, dc); /* Label the Current values */ Term_putstr(10, 20, -1, TERM_WHITE, format("Current attr/char = %3u / %3u", ca, cc)); Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 20, ca, cc); /* Prompt */ Term_putstr(0, 22, -1, TERM_WHITE, "Command (n/N/a/A/c/C): "); /* Get a command */ i = inkey(); /* All done */ if (i == ESCAPE) break; /* Analyze */ if (i == 'n') r = (r + MAX_R_IDX + 1) % MAX_R_IDX; if (i == 'N') r = (r + MAX_R_IDX - 1) % MAX_R_IDX; if (i == 'a') r_ptr->l_attr = (byte)(ca + 1); if (i == 'A') r_ptr->l_attr = (byte)(ca - 1); if (i == 'c') r_ptr->l_char = (byte)(cc + 1); if (i == 'C') r_ptr->l_char = (byte)(cc - 1); } } /* Modify object attr/chars */ else if (i == '7') { static int k = 0; /* Prompt */ prt("Command: Change object attr/chars", 15, 0); /* Hack -- query until done */ while (1) { object_kind *k_ptr = &k_info[k]; int da = (byte)k_ptr->k_attr; int dc = (byte)k_ptr->k_char; int ca = (byte)k_ptr->x_attr; int cc = (byte)k_ptr->x_char; /* Label the object */ Term_putstr(5, 17, -1, TERM_WHITE, format("Object = %d, Name = %-40.40s", k, (k_name + k_ptr->name))); /* Label the Default values */ Term_putstr(10, 19, -1, TERM_WHITE, format("Default attr/char = %3d / %3d", da, dc)); Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 19, da, dc); /* Label the Current values */ Term_putstr(10, 20, -1, TERM_WHITE, format("Current attr/char = %3d / %3d", ca, cc)); Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 20, ca, cc); /* Prompt */ Term_putstr(0, 22, -1, TERM_WHITE, "Command (n/N/a/A/c/C): "); /* Get a command */ i = inkey(); /* All done */ if (i == ESCAPE) break; /* Analyze */ if (i == 'n') k = (k + MAX_K_IDX + 1) % MAX_K_IDX; if (i == 'N') k = (k + MAX_K_IDX - 1) % MAX_K_IDX; if (i == 'a') k_info[k].x_attr = (byte)(ca + 1); if (i == 'A') k_info[k].x_attr = (byte)(ca - 1); if (i == 'c') k_info[k].x_char = (byte)(cc + 1); if (i == 'C') k_info[k].x_char = (byte)(cc - 1); } } /* Modify feature attr/chars */ else if (i == '8') { static int f = 0; /* Prompt */ prt("Command: Change feature attr/chars", 15, 0); /* Hack -- query until done */ while (1) { feature_type *f_ptr = &f_info[f]; int da = (byte)f_ptr->f_attr; int dc = (byte)f_ptr->f_char; int ca = (byte)f_ptr->z_attr; int cc = (byte)f_ptr->z_char; /* Label the object */ Term_putstr(5, 17, -1, TERM_WHITE, format("Terrain = %d, Name = %-40.40s", f, (f_name + f_ptr->name))); /* Label the Default values */ Term_putstr(10, 19, -1, TERM_WHITE, format("Default attr/char = %3d / %3d", da, dc)); Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 19, da, dc); /* Label the Current values */ Term_putstr(10, 20, -1, TERM_WHITE, format("Current attr/char = %3d / %3d", ca, cc)); Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); Term_putch(43, 20, ca, cc); /* Prompt */ Term_putstr(0, 22, -1, TERM_WHITE, "Command (n/N/a/A/c/C): "); /* Get a command */ i = inkey(); /* All done */ if (i == ESCAPE) break; /* Analyze */ if (i == 'n') f = (f + MAX_F_IDX + 1) % MAX_F_IDX; if (i == 'N') f = (f + MAX_F_IDX - 1) % MAX_F_IDX; if (i == 'a') f_info[f].z_attr = (byte)(ca + 1); if (i == 'A') f_info[f].z_attr = (byte)(ca - 1); if (i == 'c') f_info[f].z_char = (byte)(cc + 1); if (i == 'C') f_info[f].z_char = (byte)(cc - 1); } } #endif /* Reset visuals */ else if (i == '0') { /* Reset */ reset_visuals(); /* Message */ msg_print("Visual attr/char tables reset."); } /* Unknown option */ else { bell(); } /* Flush messages */ msg_print(NULL); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Interact with "colors" */ void do_cmd_colors(void) { int i; FILE *fff; char tmp[160]; char buf[1024]; #if defined(MACINTOSH) && !defined(applec) _feate = 'TEXT'; #endif /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Interact until done */ while (1) { /* Clear the screen */ clear_screen(); /* Ask for a choice */ prt("Interact with Colors", 2, 0); /* Give some choices */ prt("(1) Load a user pref file", 4, 5); #ifdef ALLOW_COLORS prt("(2) Dump colors", 5, 5); prt("(3) Modify colors", 6, 5); #endif /* Prompt */ prt("Command: ", 8, 0); /* Prompt */ i = inkey(); /* Done */ if (i == ESCAPE) break; /* Load a 'pref' file */ if (i == '1') { /* Prompt */ prt("Command: Load a user pref file", 8, 0); /* Prompt */ prt("File: ", 10, 0); /* Default file */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Query */ if (!askfor_aux(tmp, 70)) continue; /* Process the given filename */ (void)process_pref_file(tmp); /* Mega-Hack -- react to changes */ Term_xtra(TERM_XTRA_REACT, 0); /* Mega-Hack -- redraw */ Term_redraw(); } #ifdef ALLOW_COLORS /* Dump colors */ else if (i == '2') { /* Prompt */ prt("Command: Dump colors", 8, 0); /* Prompt */ prt("File: ", 10, 0); /* Default filename */ sprintf(tmp, "user-%s.prf", ANGBAND_SYS); /* Get a filename */ if (!askfor_aux(tmp, 70)) continue; /* Build the filename */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, tmp); /* Drop priv's */ safe_setuid_drop(); /* Append to the file */ fff = my_fopen(buf, "a"); /* Grab priv's */ safe_setuid_grab(); /* Failure */ if (!fff) continue; /* Start dumping */ fprintf(fff, "\n\n"); fprintf(fff, "# Color redefinitions\n\n"); /* Dump colors */ for (i = 0; i < 256; i++) { int kv = color_table[i][0]; int rv = color_table[i][1]; int gv = color_table[i][2]; int bv = color_table[i][3]; cptr name = "unknown"; /* Skip non-entries */ if (!kv && !rv && !gv && !bv) continue; /* Extract the color name */ if (i < 16) name = color_names[i]; /* Dump a comment */ fprintf(fff, "# Color '%s'\n", name); /* Dump the monster attr/char info */ fprintf(fff, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", i, kv, rv, gv, bv); } /* All done */ fprintf(fff, "\n\n\n\n"); /* Close */ my_fclose(fff); /* Message */ msg_print("Dumped color redefinitions."); } /* Edit colors */ else if (i == '3') { static int a = 0; /* Prompt */ prt("Command: Modify colors", 8, 0); /* Hack -- query until done */ while (1) { cptr name; /* Clear */ clear_from(10); /* Exhibit the normal colors */ for (i = 0; i < 16; i++) { /* Exhibit this color */ Term_putstr(i*4, 20, -1, a, "###"); /* Exhibit all colors */ Term_putstr(i*4, 22, -1, i, format("%3d", i)); } /* Describe the color */ name = ((a < 16) ? color_names[a] : "undefined"); /* Describe the color */ Term_putstr(5, 10, -1, TERM_WHITE, format("Color = %d, Name = %s", a, name)); /* Label the Current values */ Term_putstr(5, 12, -1, TERM_WHITE, format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", color_table[a][0], color_table[a][1], color_table[a][2], color_table[a][3])); /* Prompt */ Term_putstr(0, 14, -1, TERM_WHITE, "Command (n/N/k/K/r/R/g/G/b/B): "); /* Get a command */ i = inkey(); /* All done */ if (i == ESCAPE) break; /* Analyze */ if (i == 'n') a = (byte)(a + 1); if (i == 'N') a = (byte)(a - 1); if (i == 'k') color_table[a][0] = (byte)(color_table[a][0] + 1); if (i == 'K') color_table[a][0] = (byte)(color_table[a][0] - 1); if (i == 'r') color_table[a][1] = (byte)(color_table[a][1] + 1); if (i == 'R') color_table[a][1] = (byte)(color_table[a][1] - 1); if (i == 'g') color_table[a][2] = (byte)(color_table[a][2] + 1); if (i == 'G') color_table[a][2] = (byte)(color_table[a][2] - 1); if (i == 'b') color_table[a][3] = (byte)(color_table[a][3] + 1); if (i == 'B') color_table[a][3] = (byte)(color_table[a][3] - 1); /* Hack -- react to changes */ Term_xtra(TERM_XTRA_REACT, 0); /* Hack -- redraw */ Term_redraw(); } } #endif /* Unknown option */ else { bell(); } /* Flush messages */ msg_print(NULL); } /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Note something in the message recall */ void do_cmd_note(void) { char buf[80]; /* Default */ strcpy(buf, ""); /* Input */ if (!get_string("Note: ", buf, 60)) return; /* Ignore empty notes */ if (!buf[0] || (buf[0] == ' ')) return; /* Add the note to the message recall */ msg_format("Note: %s", buf); } /* * Mention the current version */ void do_cmd_version(void) { msg_format("You are playing Utumno %s. Type '?' for more info.", VERSION_STRING); } /* * Array of feeling strings */ static cptr do_cmd_feeling_text[11] = { "Looks like any other level.", "You feel there is something special about this level.", "You have a superb feeling about this level.", "You have an excellent feeling...", "You have a very good feeling...", "You have a good feeling...", "You feel strangely lucky...", "You feel your luck is turning...", "You like the look of this place...", "This level can't be all bad...", "What a boring place..." }; /* * Note that "feeling" is set to zero unless some time has passed. * Note that this is done when the level is GENERATED, not entered. */ void do_cmd_feeling() { /* Verify the feeling */ if (feeling < 0) feeling = 0; if (feeling > 10) feeling = 10; /* No useful feeling in town */ if (!dun_level) { msg_print("Looks like a typical town."); return; } /* Display the feeling */ msg_print(do_cmd_feeling_text[feeling]); } /* * Encode the screen colors */ static char hack[17] = "dwsorgbuDWvyRGBU"; /* * Hack -- load a screen dump from a file */ void do_cmd_load_screen(void) { int i, y, x; byte a = 0; char c = ' '; bool okay = TRUE; FILE *fff; char buf[1024]; /* Build the path name */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, "dump.txt"); /* Append to the file */ fff = my_fopen(buf, "r"); /* Oops */ if (!fff) return; /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Clear the screen */ Term_clear(); /* Load the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (my_fgets(fff, buf, 1024)) okay = FALSE; /* Show each row */ for (x = 0; x < 79; x++) { /* Put the attr/char */ Term_draw(x, y, TERM_WHITE, buf[x]); } } /* Get the blank line */ if (my_fgets(fff, buf, 1024)) okay = FALSE; /* Dump the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (my_fgets(fff, buf, 1024)) okay = FALSE; /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Look up the attr */ for (i = 0; i < 16; i++) { /* Use attr matches */ if (hack[i] == buf[x]) a = i; } /* Put the attr/char */ Term_draw(x, y, a, c); } /* End the row */ fprintf(fff, "\n"); } /* Get the blank line */ if (my_fgets(fff, buf, 1024)) okay = FALSE; /* Close it */ my_fclose(fff); /* Message */ msg_print("Screen dump loaded."); msg_print(NULL); /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Hack -- save a screen dump to a file */ void do_cmd_save_screen(void) { int y, x; byte a = 0; char c = ' '; FILE *fff; char buf[1024]; /* Build the path name */ strcpy(buf, ANGBAND_DIR_USER); strcat(buf, "dump.txt"); #if defined(MACINTOSH) && !defined(applec) _feate = 'TEXT'; #endif /* Hack -- drop permissions */ safe_setuid_drop(); /* Append to the file */ fff = my_fopen(buf, "w"); /* Hack -- grab permissions */ safe_setuid_grab(); /* Oops */ if (!fff) return; /* Enter "icky" mode */ character_icky = TRUE; /* Save the screen */ Term_save(); /* Dump the screen */ for (y = 0; y < 24; y++) { /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = c; } /* Terminate */ buf[x] = '\0'; /* End the row */ fprintf(fff, "%s\n", buf); } /* Skip a line */ fprintf(fff, "\n"); /* Dump the screen */ for (y = 0; y < 24; y++) { /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = hack[a&0x0F]; } /* Terminate */ buf[x] = '\0'; /* End the row */ fprintf(fff, "%s\n", buf); } /* Skip a line */ fprintf(fff, "\n"); /* Close it */ my_fclose(fff); /* Message */ msg_print("Screen dump saved."); msg_print(NULL); /* Restore the screen */ Term_load(); /* Leave "icky" mode */ character_icky = FALSE; } /* * Check the status of "artifacts" * * XXX Consider use of "term_mirror" */ void do_cmd_check_artifacts(void) { int i, k, z, x, y; FILE *fff; char file_name[1024]; char base_name[80]; bool okay[MAX_A_IDX]; /* Temporary file */ if (path_temp(file_name, 1024)) return; /* Open a new file */ fff = my_fopen(file_name, "w"); /* Scan the artifacts */ for (k = 0; k < MAX_A_IDX; k++) { artifact_type *a_ptr = &a_info[k]; /* Default */ okay[k] = FALSE; /* Skip "empty" artifacts */ if (!a_ptr->name) continue; /* Skip "uncreated" artifacts */ if (!a_ptr->cur_num) continue; /* Assume okay */ okay[k] = TRUE; } /* Check the dungeon */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave_type *c_ptr = &cave[y][x]; /* Process objects */ if (c_ptr->i_idx) { object_type *i_ptr = &i_list[c_ptr->i_idx]; /* Ignore non-artifacts */ if (!i_ptr->is_artifact()) continue; /* Ignore known items */ if (i_ptr->is_known()) continue; /* Note the artifact */ okay[i_ptr->name1] = FALSE; } } } /* Check the inventory */ for (i = 0; i < INVEN_TOTAL; i++) { object_type *i_ptr = &inventory[i]; /* Ignore non-objects */ if (!i_ptr->exists()) continue; /* Ignore non-artifacts */ if (!i_ptr->is_artifact()) continue; /* Ignore known items */ if (i_ptr->is_known()) continue; /* Note the artifact */ okay[i_ptr->name1] = FALSE; } /* Scan the artifacts */ for (k = 0; k < MAX_A_IDX; k++) { artifact_type *a_ptr = &a_info[k]; /* List "dead" ones */ if (!okay[k]) continue; /* Paranoia */ strcpy(base_name, "Unknown Artifact"); /* Obtain the base object type */ z = lookup_kind(a_ptr->tval, a_ptr->sval); /* Real object */ if (z) { object_type forge; /* Create the object */ forge.invcopy(z); /* Create the artifact */ forge.set_name1(k); /* Describe the artifact */ object_desc_store(base_name, &forge, FALSE, 0); } /* Hack -- Build the artifact name */ fprintf(fff, " The %s\n", base_name); } /* Close the file */ my_fclose(fff); /* Display the file contents */ show_file(file_name, "Artifacts Seen"); /* Remove the file */ fd_kill(file_name); } /* * Check the status of "uniques" * * XXX Consider use of "term_mirror" * * Note that the player ghosts are ignored. XXX XXX XXX */ void do_cmd_check_uniques() { int k; FILE *fff; char file_name[1024]; /* Temporary file */ if (path_temp(file_name, 1024)) return; /* Open a new file */ fff = my_fopen(file_name, "w"); /* Scan the monster races */ for (k = 1; k < MAX_R_IDX-1; k++) { monster_race *r_ptr = &r_info[k]; /* Only print Uniques */ if (r_ptr->flags1 & RF1_UNIQUE) { bool dead = (r_ptr->max_num == 0); /* Only display "known" uniques */ if (dead || cheat_know || r_ptr->r_sights) { /* Print a message */ fprintf(fff, " %s is %s.\n", (r_name + r_ptr->name), (dead ? "dead" : "alive")); } } } /* Close the file */ my_fclose(fff); /* Display the file contents */ show_file(file_name, "Known Uniques"); /* Remove the file */ fd_kill(file_name); }