/* File: cmd4.c */
/*
* Copyright (c) 1997 Ben Harrison, 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. Other copyrights may also apply.
*/
#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.
*
* This command is also used to "instantiate" the results of the user
* selecting various things, such as graphics mode, so it must call
* the "TERM_XTRA_REACT" hook before redrawing the windows.
*/
void do_cmd_redraw(void)
{
int j;
term *old = Term;
/* Low level flush */
Term_flush();
/* Reset "inkey()" */
flush();
/* Hack -- React to changes */
Term_xtra(TERM_XTRA_REACT, 0);
/* 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);
/* Fully update the visuals */
p_ptr->update |= (PU_FORGET_VIEW | PU_UPDATE_VIEW | PU_MONSTERS);
/* Redraw everything */
p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
/* Window stuff */
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0 | PW_PLAYER_1);
/* Window stuff */
p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_MONSTER | PW_OBJECT);
/* Clear screen */
Term_clear();
/* Hack -- update */
handle_stuff();
/* Redraw every window */
for (j = 0; j < 8; j++)
{
/* Dead window */
if (!angband_term[j]) continue;
/* Activate */
Term_activate(angband_term[j]);
/* Redraw */
Term_redraw();
/* Refresh */
Term_fresh();
/* Restore */
Term_activate(old);
}
}
/*
* Hack -- change name
*/
void do_cmd_change_name(void)
{
char c;
int mode = 0;
cptr p;
/* Prompt */
p = "['c' to change name, 'f' to file, 'h' to change mode, or ESC]";
/* Save screen */
screen_save();
/* Forever */
while (1)
{
/* Display the player */
display_player(mode);
/* Prompt */
Term_putstr(2, 23, -1, TERM_WHITE, p);
/* Query */
c = inkey();
/* Exit */
if (c == ESCAPE) break;
/* Change name */
if (c == 'c')
{
get_name();
}
/* File dump */
else if (c == 'f')
{
char tmp[81];
sprintf(tmp, "%s.txt", op_ptr->base_name);
if (get_string("File name: ", tmp, 80))
{
if (tmp[0] && (tmp[0] != ' '))
{
file_character(tmp, FALSE);
}
}
}
/* Toggle mode */
else if (c == 'h')
{
mode = !mode;
}
/* Oops */
else
{
bell("Illegal command for change name!");
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}
/*
* 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
*
* 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.
*
* Note that messages may be longer than 80 characters, but they are
* displayed using "infinite" length, with a special sub-command to
* "slide" the virtual display to the left or right.
*
* Attempt to only hilite the matching portions of the string.
*/
void do_cmd_messages(void)
{
int i, j, k, n, q;
char shower[81];
char finder[81];
/* Wipe finder */
strcpy(finder, "");
/* Wipe shower */
strcpy(shower, "");
/* Total messages */
n = message_num();
/* Start on first message */
i = 0;
/* Start at leftmost edge */
q = 0;
/* Save screen */
screen_save();
/* Process requests until done */
while (1)
{
/* Clear screen */
Term_clear();
/* Dump up to 20 lines of messages */
for (j = 0; (j < 20) && (i + j < n); j++)
{
cptr msg = message_str(i+j);
/* Apply horizontal scroll */
msg = (strlen(msg) >= q) ? (msg + q) : "";
/* Dump the messages, bottom to top */
Term_putstr(0, 21-j, -1, TERM_WHITE, msg);
/* Hilite "shower" */
if (shower[0])
{
cptr str = msg;
/* Display matches */
while ((str = strstr(str, shower)) != NULL)
{
int len = strlen(shower);
/* Display the match */
Term_putstr(str-msg, 21-j, len, TERM_YELLOW, shower);
/* Advance */
str += len;
}
}
}
/* Display header XXX XXX XXX */
prt(format("Message Recall (%d-%d of %d), Offset %d",
i, i+j-1, n, q), 0, 0);
/* Display prompt (not very informative) */
prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", 23, 0);
/* Get a command */
k = inkey();
/* Exit on Escape */
if (k == ESCAPE) break;
/* Hack -- Save the old index */
j = i;
/* Horizontal scroll */
if (k == '4')
{
/* Scroll left */
q = (q >= 40) ? (q - 40) : 0;
/* Success */
continue;
}
/* Horizontal scroll */
if (k == '6')
{
/* Scroll right */
q = q + 40;
/* Success */
continue;
}
/* Hack -- handle show */
if (k == '=')
{
/* Prompt */
prt("Show: ", 23, 0);
/* Get a "shower" string, or continue */
if (!askfor_aux(shower, 80)) continue;
/* Okay */
continue;
}
/* Hack -- handle find */
if (k == '/')
{
int z;
/* Prompt */
prt("Find: ", 23, 0);
/* Get a "finder" string, or continue */
if (!askfor_aux(finder, 80)) continue;
/* Show it */
strcpy(shower, finder);
/* Scan messages */
for (z = i + 1; z < n; z++)
{
cptr msg = message_str(z);
/* Search for it */
if (strstr(msg, finder))
{
/* New location */
i = z;
/* Done */
break;
}
}
}
/* Recall 1 older message */
if ((k == '8') || (k == '\n') || (k == '\r'))
{
/* Go newer if legal */
if (i + 1 < n) i += 1;
}
/* Recall 10 older messages */
if (k == '+')
{
/* Go older if legal */
if (i + 10 < n) i += 10;
}
/* Recall 20 older messages */
if ((k == 'p') || (k == KTRL('P')) || (k == ' '))
{
/* Go older if legal */
if (i + 20 < n) i += 20;
}
/* Recall 20 newer messages */
if ((k == 'n') || (k == KTRL('N')))
{
/* Go newer (if able) */
i = (i >= 20) ? (i - 20) : 0;
}
/* Recall 10 newer messages */
if (k == '-')
{
/* Go newer (if able) */
i = (i >= 10) ? (i - 10) : 0;
}
/* Recall 1 newer messages */
if (k == '2')
{
/* Go newer (if able) */
i = (i >= 1) ? (i - 1) : 0;
}
/* Hack -- Error of some kind */
if (i == j) bell(NULL);
}
/* Load screen */
screen_load();
}
/*
* Cheating options -- textual names
*/
cptr cheating_text[CHEAT_MAX] =
{
"cheat_peek",
"cheat_hear",
"cheat_room",
"cheat_xtra",
"cheat_know",
"cheat_live"
};
/*
* Cheating options -- descriptions
*/
cptr cheating_desc[CHEAT_MAX] =
{
"Peek into object creation",
"Peek into monster creation",
"Peek into dungeon creation",
"Peek into something else",
"Know complete monster info",
"Allow player to avoid death"
};
/*
* Interact with some options
*/
static void do_cmd_options_cheat(cptr info)
{
char ch;
int i, k = 0, n = CHEAT_MAX;
char buf[80];
/* Clear screen */
Term_clear();
/* Interact with the player */
while (TRUE)
{
/* 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++)
{
byte a = TERM_WHITE;
/* Color current option */
if (i == k) a = TERM_L_BLUE;
/* Display the option text */
sprintf(buf, "%-48s: %s (%s)",
cheating_desc[i],
p_ptr->cheat[i] ? "yes" : "no ",
cheating_text[i]);
c_prt(a, buf, i + 2, 0);
}
/* Hilite current option */
move_cursor(k + 2, 50);
/* Get a key */
ch = inkey();
/* Analyze */
switch (ch)
{
case ESCAPE:
{
return;
}
case '-':
case '8':
{
k = (n + k - 1) % n;
break;
}
case ' ':
case '\n':
case '\r':
case '2':
{
k = (k + 1) % n;
break;
}
case 't':
case '5':
{
if (p_ptr->cheat[k])
{
p_ptr->cheat[k] = FALSE;
}
else
{
/* Mark player as a cheater */
p_ptr->noscore |= (0x0100 << k);
p_ptr->cheat[k] = TRUE;
}
break;
}
case 'y':
case '6':
{
/* Mark player as a cheater */
p_ptr->noscore |= (0x0100 << k);
p_ptr->cheat[k] = TRUE;
k = (k + 1) % n;
break;
}
case 'n':
case '4':
{
p_ptr->cheat[k] = FALSE;
k = (k + 1) % n;
break;
}
default:
{
bell("Illegal command for cheat options!");
break;
}
}
}
}
/*
* Interact with some options
*/
static void do_cmd_options_aux(int page, cptr info)
{
char ch;
int i, k = 0, n = 0;
int opt[16];
char buf[80];
/* Scan the options */
for (i = 0; i < 16; i++)
{
/* Collect options on this "page" */
if (option_page[page][i] != 255)
{
opt[n++] = option_page[page][i];
}
}
/* Clear screen */
Term_clear();
/* Interact with the player */
while (TRUE)
{
/* 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++)
{
byte a = TERM_WHITE;
/* Color current option */
if (i == k) a = TERM_L_BLUE;
/* Display the option text */
sprintf(buf, "%-48s: %s (%s)",
option_desc[opt[i]],
op_ptr->opt[opt[i]] ? "yes" : "no ",
option_text[opt[i]]);
c_prt(a, buf, i + 2, 0);
}
/* Hilite current option */
move_cursor(k + 2, 50);
/* Get a key */
ch = inkey();
/* Analyze */
switch (ch)
{
case ESCAPE:
{
return;
}
case '-':
case '8':
{
k = (n + k - 1) % n;
break;
}
case ' ':
case '\n':
case '\r':
case '2':
{
k = (k + 1) % n;
break;
}
case 't':
case '5':
{
op_ptr->opt[opt[k]] = !op_ptr->opt[opt[k]];
break;
}
case 'y':
case '6':
{
op_ptr->opt[opt[k]] = TRUE;
k = (k + 1) % n;
break;
}
case 'n':
case '4':
{
op_ptr->opt[opt[k]] = FALSE;
k = (k + 1) % n;
break;
}
default:
{
bell("Illegal command for normal options!");
break;
}
}
}
}
/*
* Modify the "window" options
*/
static void do_cmd_options_win(void)
{
int i, j, d;
int y = 0;
int x = 0;
char ch;
u32b old_flag[8];
/* Memorize old flags */
for (j = 0; j < 8; j++)
{
/* Acquire current flags */
old_flag[j] = op_ptr->window_flag[j];
}
/* Clear screen */
Term_clear();
/* Interact */
while (1)
{
/* Prompt */
prt("Window flags (
to move, 't' to toggle, or ESC)", 0, 0);
/* Display the windows */
for (j = 0; j < 8; j++)
{
byte a = TERM_WHITE;
cptr s = angband_term_name[j];
/* Use color */
if (j == x) a = TERM_L_BLUE;
/* Window name, staggered, centered */
Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s);
}
/* Display the options */
for (i = 0; i < 16; i++)
{
byte a = TERM_WHITE;
cptr str = window_flag_desc[i];
/* Use color */
if (i == y) a = TERM_L_BLUE;
/* Unused option */
if (!str) str = "(Unused option)";
/* Flag name */
Term_putstr(0, i + 5, -1, a, str);
/* Display the windows */
for (j = 0; j < 8; j++)
{
byte a = TERM_WHITE;
char c = '.';
/* Use color */
if ((i == y) && (j == x)) a = TERM_L_BLUE;
/* Active flag */
if (op_ptr->window_flag[j] & (1L << i)) c = 'X';
/* Flag value */
Term_putch(35 + j * 5, i + 5, a, c);
}
}
/* Place Cursor */
Term_gotoxy(35 + x * 5, y + 5);
/* Get key */
ch = inkey();
/* Allow escape */
if ((ch == ESCAPE) || (ch == 'q')) break;
/* Toggle */
if ((ch == '5') || (ch == 't'))
{
/* Hack -- ignore the main window */
if (x == 0)
{
bell("Cannot set main window flags!");
}
/* Toggle flag (off) */
else if (op_ptr->window_flag[x] & (1L << y))
{
op_ptr->window_flag[x] &= ~(1L << y);
}
/* Toggle flag (on) */
else
{
op_ptr->window_flag[x] |= (1L << y);
}
/* Continue */
continue;
}
/* Extract direction */
d = target_dir(ch);
/* Move */
if (d != 0)
{
x = (x + ddx[d] + 8) % 8;
y = (y + ddy[d] + 16) % 16;
}
/* Oops */
else
{
bell("Illegal command for window options!");
}
}
/* Notice changes */
for (j = 0; j < 8; j++)
{
term *old = Term;
/* Dead window */
if (!angband_term[j]) continue;
/* Ignore non-changes */
if (op_ptr->window_flag[j] == old_flag[j]) continue;
/* Activate */
Term_activate(angband_term[j]);
/* Erase */
Term_clear();
/* Refresh */
Term_fresh();
/* Restore */
Term_activate(old);
}
}
/*
* Set or unset various options.
*
* After using this command, a complete redraw is performed,
* whether or not it is technically required.
*/
void do_cmd_options(void)
{
int k;
/* Save screen */
screen_save();
/* Interact */
while (1)
{
/* Clear screen */
Term_clear();
/* 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) Game-Play Options", 6, 5);
prt("(4) Efficiency Options", 7, 5);
/* Cheating */
prt("(C) Cheating Options", 9, 5);
/* Window flags */
prt("(W) Window flags", 11, 5);
/* Special choices */
prt("(D) Base Delay Factor", 13, 5);
prt("(H) Hitpoint Warning", 14, 5);
/* Prompt */
prt("Command: ", 18, 0);
/* Get command */
k = inkey();
/* Exit */
if (k == ESCAPE) break;
/* Analyze */
switch (k)
{
/* General Options */
case '1':
{
/* Process the general options */
do_cmd_options_aux(0, "User Interface Options");
break;
}
/* Disturbance Options */
case '2':
{
/* Spawn */
do_cmd_options_aux(1, "Disturbance Options");
break;
}
/* Inventory Options */
case '3':
{
/* Spawn */
do_cmd_options_aux(2, "Game-Play Options");
break;
}
/* Efficiency Options */
case '4':
{
/* Spawn */
do_cmd_options_aux(3, "Efficiency Options");
break;
}
/* Cheating Options */
case 'C':
{
/* Spawn */
do_cmd_options_cheat("Cheaters never win (seriously!)");
break;
}
/* Window flags */
case 'W':
case 'w':
{
/* Spawn */
do_cmd_options_win();
break;
}
/* Hack -- Delay Speed */
case 'D':
case 'd':
{
/* Prompt */
prt("Command: Base Delay Factor", 18, 0);
/* Get a new value */
while (1)
{
int msec = op_ptr->delay_factor * op_ptr->delay_factor;
prt(format("Current base delay factor: %d (%d msec)",
op_ptr->delay_factor, msec), 22, 0);
prt("Delay Factor (0-9 or ESC to accept): ", 20, 0);
k = inkey();
if (k == ESCAPE) break;
if (isdigit(k)) op_ptr->delay_factor = D2I(k);
else bell("Illegal delay factor!");
}
break;
}
/* Hack -- hitpoint warning factor */
case 'H':
case 'h':
{
/* Prompt */
prt("Command: Hitpoint Warning", 18, 0);
/* Get a new value */
while (1)
{
prt(format("Current hitpoint warning: %2d%%",
op_ptr->hitpoint_warn * 10), 22, 0);
prt("Hitpoint Warning (0-9 or ESC to accept): ", 20, 0);
k = inkey();
if (k == ESCAPE) break;
if (isdigit(k)) op_ptr->hitpoint_warn = D2I(k);
else bell("Illegal hitpoint warning!");
}
break;
}
/* Unknown option */
default:
{
/* Oops */
bell("Illegal command for options!");
break;
}
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}
/*
* Ask for a "user pref line" and process it
*
* XXX XXX XXX Allow absolute file names?
*/
void do_cmd_pref(void)
{
char tmp[81];
/* Default */
strcpy(tmp, "");
/* Ask for a "user pref command" */
if (!get_string("Pref: ", tmp, 80)) return;
/* Process that pref command */
(void)process_pref_file_aux(tmp);
}
#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 */
path_build(buf, 1024, ANGBAND_DIR_USER, fname);
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* 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 normal macros */
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 "util.c".
*
* Note that both "flush()" calls are extremely important. This may
* no longer be true, since "util.c" is much simpler now. XXX XXX XXX
*/
static void do_cmd_macro_aux(char *buf)
{
int i, n = 0;
char tmp[1024];
/* Flush */
flush();
/* Do not process macros */
inkey_base = TRUE;
/* First key */
i = inkey();
/* Read the pattern */
while (i)
{
/* Save the key */
buf[n++] = i;
/* Do not process macros */
inkey_base = TRUE;
/* Do not wait for keys */
inkey_scan = TRUE;
/* Attempt to read a key */
i = inkey();
}
/* Terminate */
buf[n] = '\0';
/* Flush */
flush();
/* Convert the trigger */
ascii_to_text(tmp, buf);
/* Hack -- display the trigger */
Term_addstr(-1, TERM_WHITE, tmp);
}
/*
* Hack -- ask for a keymap "trigger" (see below)
*
* Note that both "flush()" calls are extremely important. This may
* no longer be true, since "util.c" is much simpler now. XXX XXX XXX
*/
static void do_cmd_macro_aux_keymap(char *buf)
{
char tmp[1024];
/* Flush */
flush();
/* Get a key */
buf[0] = inkey();
buf[1] = '\0';
/* Convert to ascii */
ascii_to_text(tmp, buf);
/* Hack -- display the trigger */
Term_addstr(-1, TERM_WHITE, tmp);
/* Flush */
flush();
}
/*
* Hack -- append all keymaps to the given file
*/
static errr keymap_dump(cptr fname)
{
int i;
FILE *fff;
char key[1024];
char buf[1024];
int mode;
/* Roguelike */
if (rogue_like_commands)
{
mode = KEYMAP_MODE_ROGUE;
}
/* Original */
else
{
mode = KEYMAP_MODE_ORIG;
}
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, fname);
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* 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 keymap dump\n\n");
/* Dump them */
for (i = 0; i < 256; i++)
{
cptr act;
/* Loop up the keymap */
act = keymap_act[mode][i];
/* Skip empty keymaps */
if (!act) continue;
/* Encode the key */
buf[0] = i;
buf[1] = '\0';
ascii_to_text(key, buf);
/* Encode the action */
ascii_to_text(buf, act);
/* Dump the macro */
fprintf(fff, "M:%d %2s %s\n", mode, key, buf);
}
/* Start dumping */
fprintf(fff, "\n\n\n");
/* Close */
my_fclose(fff);
/* Success */
return (0);
}
#endif
/*
* Interact with "macros"
*
* Note that the macro "action" must be defined before the trigger.
*
* Could use some helpful instructions on this page. XXX XXX XXX
*/
void do_cmd_macros(void)
{
int i;
char tmp[1024];
char buf[1024];
int mode;
/* Roguelike */
if (rogue_like_commands)
{
mode = KEYMAP_MODE_ROGUE;
}
/* Original */
else
{
mode = KEYMAP_MODE_ORIG;
}
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* Save screen */
screen_save();
/* Process requests until done */
while (1)
{
/* Clear screen */
Term_clear();
/* Describe */
prt("Interact with Macros", 2, 0);
/* Describe that action */
prt("Current action (if any) shown below:", 20, 0);
/* Analyze the current action */
ascii_to_text(buf, macro_buffer);
/* Display the current action */
prt(buf, 22, 0);
/* Selections */
prt("(1) Load a user pref file", 4, 5);
#ifdef ALLOW_MACROS
prt("(2) Append macros to a file", 5, 5);
prt("(3) Query a macro", 6, 5);
prt("(4) Create a macro", 7, 5);
prt("(5) Remove a macro", 8, 5);
prt("(6) Append keymaps to a file", 9, 5);
prt("(7) Query a keymap", 10, 5);
prt("(8) Create a keymap", 11, 5);
prt("(9) Remove a keymap", 12, 5);
prt("(0) Enter a new action", 13, 5);
#endif /* ALLOW_MACROS */
/* Prompt */
prt("Command: ", 16, 0);
/* Get a command */
i = inkey();
/* Leave */
if (i == ESCAPE) break;
/* Load a 'macro' file */
else if (i == '1')
{
/* Prompt */
prt("Command: Load a user pref file", 16, 0);
/* Prompt */
prt("File: ", 18, 0);
/* Default filename */
sprintf(tmp, "%s.prf", op_ptr->base_name);
/* Ask for a file */
if (!askfor_aux(tmp, 80)) continue;
/* Process the given filename */
if (0 != process_pref_file(tmp))
{
/* Prompt */
msg_print("Could not load file!");
}
}
#ifdef ALLOW_MACROS
/* Save macros */
else if (i == '2')
{
/* Prompt */
prt("Command: Append macros to a file", 16, 0);
/* Prompt */
prt("File: ", 18, 0);
/* Default filename */
sprintf(tmp, "%s.prf", op_ptr->base_name);
/* Ask for a file */
if (!askfor_aux(tmp, 80)) continue;
/* Drop priv's */
safe_setuid_drop();
/* Dump the macros */
(void)macro_dump(tmp);
/* Grab priv's */
safe_setuid_grab();
/* Prompt */
msg_print("Appended macros.");
}
/* Query a macro */
else if (i == '3')
{
int k;
/* Prompt */
prt("Command: Query a macro", 16, 0);
/* Prompt */
prt("Trigger: ", 18, 0);
/* Get a macro trigger */
do_cmd_macro_aux(buf);
/* Acquire action */
k = macro_find_exact(buf);
/* Nothing found */
if (k < 0)
{
/* Prompt */
msg_print("Found no macro.");
}
/* Found one */
else
{
/* Obtain the action */
strcpy(macro_buffer, macro__act[k]);
/* Analyze the current action */
ascii_to_text(buf, macro_buffer);
/* Display the current action */
prt(buf, 22, 0);
/* Prompt */
msg_print("Found a macro.");
}
}
/* Create a macro */
else if (i == '4')
{
/* Prompt */
prt("Command: Create a macro", 16, 0);
/* Prompt */
prt("Trigger: ", 18, 0);
/* Get a macro trigger */
do_cmd_macro_aux(buf);
/* Clear */
clear_from(20);
/* Prompt */
prt("Action: ", 20, 0);
/* Convert to text */
ascii_to_text(tmp, macro_buffer);
/* Get an encoded action */
if (askfor_aux(tmp, 80))
{
/* Convert to ascii */
text_to_ascii(macro_buffer, tmp);
/* Link the macro */
macro_add(buf, macro_buffer);
/* Prompt */
msg_print("Added a macro.");
}
}
/* Remove a macro */
else if (i == '5')
{
/* Prompt */
prt("Command: Remove a macro", 16, 0);
/* Prompt */
prt("Trigger: ", 18, 0);
/* Get a macro trigger */
do_cmd_macro_aux(buf);
/* Link the macro */
macro_add(buf, buf);
/* Prompt */
msg_print("Removed a macro.");
}
/* Save keymaps */
else if (i == '6')
{
/* Prompt */
prt("Command: Append keymaps to a file", 16, 0);
/* Prompt */
prt("File: ", 18, 0);
/* Default filename */
sprintf(tmp, "%s.prf", op_ptr->base_name);
/* Ask for a file */
if (!askfor_aux(tmp, 80)) continue;
/* Drop priv's */
safe_setuid_drop();
/* Dump the macros */
(void)keymap_dump(tmp);
/* Grab priv's */
safe_setuid_grab();
/* Prompt */
msg_print("Appended keymaps.");
}
/* Query a keymap */
else if (i == '7')
{
cptr act;
/* Prompt */
prt("Command: Query a keymap", 16, 0);
/* Prompt */
prt("Keypress: ", 18, 0);
/* Get a keymap trigger */
do_cmd_macro_aux_keymap(buf);
/* Look up the keymap */
act = keymap_act[mode][(byte)(buf[0])];
/* Nothing found */
if (!act)
{
/* Prompt */
msg_print("Found no keymap.");
}
/* Found one */
else
{
/* Obtain the action */
strcpy(macro_buffer, act);
/* Analyze the current action */
ascii_to_text(buf, macro_buffer);
/* Display the current action */
prt(buf, 22, 0);
/* Prompt */
msg_print("Found a keymap.");
}
}
/* Create a keymap */
else if (i == '8')
{
/* Prompt */
prt("Command: Create a keymap", 16, 0);
/* Prompt */
prt("Keypress: ", 18, 0);
/* Get a keymap trigger */
do_cmd_macro_aux_keymap(buf);
/* Clear */
clear_from(20);
/* Prompt */
prt("Action: ", 20, 0);
/* Convert to text */
ascii_to_text(tmp, macro_buffer);
/* Get an encoded action */
if (askfor_aux(tmp, 80))
{
/* Convert to ascii */
text_to_ascii(macro_buffer, tmp);
/* Free old keymap */
string_free(keymap_act[mode][(byte)(buf[0])]);
/* Make new keymap */
keymap_act[mode][(byte)(buf[0])] = string_make(macro_buffer);
/* Prompt */
msg_print("Added a keymap.");
}
}
/* Remove a keymap */
else if (i == '9')
{
/* Prompt */
prt("Command: Remove a keymap", 16, 0);
/* Prompt */
prt("Keypress: ", 18, 0);
/* Get a keymap trigger */
do_cmd_macro_aux_keymap(buf);
/* Free old keymap */
string_free(keymap_act[mode][(byte)(buf[0])]);
/* Make new keymap */
keymap_act[mode][(byte)(buf[0])] = NULL;
/* Prompt */
msg_print("Removed a keymap.");
}
/* Enter a new action */
else if (i == '0')
{
/* Prompt */
prt("Command: Enter a new action", 16, 0);
/* Go to the correct location */
Term_gotoxy(0, 22);
/* Hack -- limit the value */
tmp[80] = '\0';
/* Get an encoded action */
if (!askfor_aux(buf, 80)) continue;
/* Extract an action */
text_to_ascii(macro_buffer, buf);
}
#endif /* ALLOW_MACROS */
/* Oops */
else
{
/* Oops */
bell("Illegal command for macros!");
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}
/*
* Interact with "visuals"
*/
void do_cmd_visuals(void)
{
int i;
FILE *fff;
char tmp[160];
char buf[1024];
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* Save screen */
screen_save();
/* Interact until done */
while (1)
{
/* Clear screen */
Term_clear();
/* 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, "%s.prf", op_ptr->base_name);
/* Query */
if (!askfor_aux(tmp, 80)) 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, "%s.prf", op_ptr->base_name);
/* Get a filename */
if (!askfor_aux(tmp, 80)) continue;
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, 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->x_attr), (byte)(r_ptr->x_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, "%s.prf", op_ptr->base_name);
/* Get a filename */
if (!askfor_aux(tmp, 80)) continue;
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, 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, "%s.prf", op_ptr->base_name);
/* Get a filename */
if (!askfor_aux(tmp, 80)) continue;
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, 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->x_attr), (byte)(f_ptr->x_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->d_attr);
int dc = (byte)(r_ptr->d_char);
int ca = (byte)(r_ptr->x_attr);
int cc = (byte)(r_ptr->x_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->x_attr = (byte)(ca + 1);
if (i == 'A') r_ptr->x_attr = (byte)(ca - 1);
if (i == 'c') r_ptr->x_char = (byte)(cc + 1);
if (i == 'C') r_ptr->x_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->d_attr;
int dc = (byte)k_ptr->d_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->d_attr;
int dc = (byte)f_ptr->d_char;
int ca = (byte)f_ptr->x_attr;
int cc = (byte)f_ptr->x_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].x_attr = (byte)(ca + 1);
if (i == 'A') f_info[f].x_attr = (byte)(ca - 1);
if (i == 'c') f_info[f].x_char = (byte)(cc + 1);
if (i == 'C') f_info[f].x_char = (byte)(cc - 1);
}
}
#endif
/* Reset visuals */
else if (i == '0')
{
/* Reset */
reset_visuals(TRUE);
/* Message */
msg_print("Visual attr/char tables reset.");
}
/* Unknown option */
else
{
bell("Illegal command for visuals!");
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}
/*
* Interact with "colors"
*/
void do_cmd_colors(void)
{
int i;
FILE *fff;
char tmp[160];
char buf[1024];
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* Save screen */
screen_save();
/* Interact until done */
while (1)
{
/* Clear screen */
Term_clear();
/* 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, "%s.prf", op_ptr->base_name);
/* Query */
if (!askfor_aux(tmp, 80)) 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, "%s.prf", op_ptr->base_name);
/* Get a filename */
if (!askfor_aux(tmp, 80)) continue;
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, 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 = angband_color_table[i][0];
int rv = angband_color_table[i][1];
int gv = angband_color_table[i][2];
int bv = angband_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",
angband_color_table[a][0],
angband_color_table[a][1],
angband_color_table[a][2],
angband_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') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1);
if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1);
if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1);
if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1);
if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1);
if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1);
if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1);
if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1);
/* Hack -- react to changes */
Term_xtra(TERM_XTRA_REACT, 0);
/* Hack -- redraw */
Term_redraw();
}
}
#endif
/* Unknown option */
else
{
bell("Illegal command for colors!");
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}
/*
* Note something in the message recall
*/
void do_cmd_note(void)
{
char tmp[81];
/* Default */
strcpy(tmp, "");
/* Input */
if (!get_string("Note: ", tmp, 80)) return;
/* Ignore empty notes */
if (!tmp[0] || (tmp[0] == ' ')) return;
/* Add the note to the message recall */
msg_format("Note: %s", tmp);
}
/*
* Mention the current version
*/
void do_cmd_version(void)
{
/* Silly message */
msg_format("You are playing Angband %d.%d.%d. Type '?' for more info.",
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
}
/*
* 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(void)
{
/* Verify the feeling */
if (feeling < 0) feeling = 0;
if (feeling > 10) feeling = 10;
/* No useful feeling in town */
if (!p_ptr->depth)
{
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 filename */
path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt");
/* Append to the file */
fff = my_fopen(buf, "r");
/* Oops */
if (!fff) return;
/* Save screen */
screen_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);
/* Load screen */
screen_load();
}
/*
* 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 filename */
path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt");
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* 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;
/* Save screen */
screen_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);
/* Load screen */
screen_load();
}
/*
* Display known artifacts
*/
static void do_cmd_knowledge_artifacts(void)
{
int i, k, z, x, y;
FILE *fff;
char file_name[1024];
char o_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 < DUNGEON_HGT; y++)
{
for (x = 0; x < DUNGEON_WID; x++)
{
s16b this_o_idx, next_o_idx = 0;
/* Scan all objects in the grid */
for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx)
{
object_type *o_ptr;
/* Acquire object */
o_ptr = &o_list[this_o_idx];
/* Acquire next object */
next_o_idx = o_ptr->next_o_idx;
/* Ignore non-artifacts */
if (!artifact_p(o_ptr)) continue;
/* Ignore known items */
if (object_known_p(o_ptr)) continue;
/* Note the artifact */
okay[o_ptr->name1] = FALSE;
}
}
}
/* Check the inventory and equipment */
for (i = 0; i < INVEN_TOTAL; i++)
{
object_type *o_ptr = &inventory[i];
/* Ignore non-objects */
if (!o_ptr->k_idx) continue;
/* Ignore non-artifacts */
if (!artifact_p(o_ptr)) continue;
/* Ignore known items */
if (object_known_p(o_ptr)) continue;
/* Note the artifact */
okay[o_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(o_name, "Unknown Artifact");
/* Obtain the base object type */
z = lookup_kind(a_ptr->tval, a_ptr->sval);
/* Real object */
if (z)
{
object_type *i_ptr;
object_type object_type_body;
/* Get local object */
i_ptr = &object_type_body;
/* Create fake object */
object_prep(i_ptr, z);
/* Make it an artifact */
i_ptr->name1 = k;
/* Describe the artifact */
object_desc_store(o_name, i_ptr, FALSE, 0);
}
/* Hack -- Build the artifact name */
fprintf(fff, " The %s\n", o_name);
}
/* Close the file */
my_fclose(fff);
/* Display the file contents */
show_file(file_name, "Known artifacts", 0, 0);
/* Remove the file */
fd_kill(file_name);
}
/*
* Display known uniques
*
* Note that the player ghosts are ignored. XXX XXX XXX
*/
static void do_cmd_knowledge_uniques(void)
{
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", 0, 0);
/* Remove the file */
fd_kill(file_name);
}
/*
* Display known objects
*/
static void do_cmd_knowledge_objects(void)
{
int k;
FILE *fff;
char o_name[80];
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 object kinds */
for (k = 1; k < MAX_K_IDX; k++)
{
object_kind *k_ptr = &k_info[k];
/* Hack -- skip artifacts */
if (k_ptr->flags3 & (TR3_INSTA_ART)) continue;
/* List known flavored objects */
if (k_ptr->flavor && k_ptr->aware)
{
object_type *i_ptr;
object_type object_type_body;
/* Get local object */
i_ptr = &object_type_body;
/* Create fake object */
object_prep(i_ptr, k);
/* Describe the object */
object_desc_store(o_name, i_ptr, FALSE, 0);
/* Print a message */
fprintf(fff, " %s\n", o_name);
}
}
/* Close the file */
my_fclose(fff);
/* Display the file contents */
show_file(file_name, "Known Objects", 0, 0);
/* Remove the file */
fd_kill(file_name);
}
/*
* Interact with "knowledge"
*/
void do_cmd_knowledge(void)
{
int i;
/* File type is "TEXT" */
FILE_TYPE(FILE_TYPE_TEXT);
/* Save screen */
screen_save();
/* Interact until done */
while (1)
{
/* Clear screen */
Term_clear();
/* Ask for a choice */
prt("Display current knowledge", 2, 0);
/* Give some choices */
prt("(1) Display known artifacts", 4, 5);
prt("(2) Display known uniques", 5, 5);
prt("(3) Display known objects", 6, 5);
/* Prompt */
prt("Command: ", 8, 0);
/* Prompt */
i = inkey();
/* Done */
if (i == ESCAPE) break;
/* Artifacts */
if (i == '1')
{
/* Spawn */
do_cmd_knowledge_artifacts();
}
/* Uniques */
else if (i == '2')
{
/* Spawn */
do_cmd_knowledge_uniques();
}
/* Objects */
else if (i == '3')
{
/* Spawn */
do_cmd_knowledge_objects();
}
/* Unknown option */
else
{
bell("Illegal command for knowledge!");
}
/* Flush messages */
msg_print(NULL);
}
/* Load screen */
screen_load();
}