static int dotravel_target(void);
static int doclicklook(void);
static int doterrain(void);
+static void set_move_cmd(int, int);
static int wiz_wish(void);
static int wiz_identify(void);
static int wiz_map(void);
static void show_direction_keys(winid, char, boolean);
static boolean help_dir(char, int, const char *);
+static boolean bind_key_fn(uchar, int (*)(void));
static void commands_init(void);
static boolean keylist_func_has_key(const struct ext_func_tab *, boolean *);
static int keylist_putcmds(winid, boolean, int, int, boolean *);
-static int ch2spkeys(char, int, int);
-static boolean prefix_cmd(char);
static const char *spkey_name(int);
static int (*timed_occ_fn)(void);
return 0;
if (iflags.menu_requested && !accept_menu_prefix(&extcmdlist[idx])) {
pline("'%s' prefix has no effect for the %s command.",
- visctrl(g.Cmd.spkeys[NHKF_REQMENU]),
+ visctrl(cmd_from_func(do_reqmenu)),
extcmdlist[idx].ef_txt);
iflags.menu_requested = FALSE;
}
add_menu(menuwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
"[A] Command autocompletes", MENU_ITEMFLAGS_NONE);
Sprintf(qbuf, "[m] Command accepts '%s' prefix",
- visctrl(g.Cmd.spkeys[NHKF_REQMENU]));
+ visctrl(cmd_from_func(do_reqmenu)));
add_menu(menuwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE, qbuf,
MENU_ITEMFLAGS_NONE);
return (char *) 0;
return ECMD_OK; /* no time elapses */
}
+static void
+set_move_cmd(int dir, int run)
+{
+ /* #reqmenu -prefix disables autopickup during movement */
+ if (iflags.menu_requested)
+ g.context.nopick = 1;
+ g.context.travel = g.context.travel1 = 0;
+ if (!g.domove_attempting) {
+ g.context.run = run;
+ g.domove_attempting |= (!run ? DOMOVE_WALK : DOMOVE_RUSH);
+ }
+ u.dz = zdir[dir];
+ u.dx = xdir[dir];
+ u.dy = ydir[dir];
+}
+
+/* move or attack */
+int
+do_move_west(void)
+{
+ set_move_cmd(DIR_W, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_northwest(void)
+{
+ set_move_cmd(DIR_NW, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_north(void)
+{
+ set_move_cmd(DIR_N, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_northeast(void)
+{
+ set_move_cmd(DIR_NE, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_east(void)
+{
+ set_move_cmd(DIR_E, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_southeast(void)
+{
+ set_move_cmd(DIR_SE, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_south(void)
+{
+ set_move_cmd(DIR_S, 0);
+ return ECMD_TIME;
+}
+
+int
+do_move_southwest(void)
+{
+ set_move_cmd(DIR_SW, 0);
+ return ECMD_TIME;
+}
+
+/* rush */
+int
+do_rush_west(void)
+{
+ set_move_cmd(DIR_W, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_northwest(void)
+{
+ set_move_cmd(DIR_NW, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_north(void)
+{
+ set_move_cmd(DIR_N, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_northeast(void)
+{
+ set_move_cmd(DIR_NE, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_east(void)
+{
+ set_move_cmd(DIR_E, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_southeast(void)
+{
+ set_move_cmd(DIR_SE, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_south(void)
+{
+ set_move_cmd(DIR_S, 1);
+ return ECMD_TIME;
+}
+
+int
+do_rush_southwest(void)
+{
+ set_move_cmd(DIR_SW, 1);
+ return ECMD_TIME;
+}
+
+/* run */
+int
+do_run_west(void)
+{
+ set_move_cmd(DIR_W, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_northwest(void)
+{
+ set_move_cmd(DIR_NW, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_north(void)
+{
+ set_move_cmd(DIR_N, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_northeast(void)
+{
+ set_move_cmd(DIR_NE, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_east(void)
+{
+ set_move_cmd(DIR_E, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_southeast(void)
+{
+ set_move_cmd(DIR_SE, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_south(void)
+{
+ set_move_cmd(DIR_S, 3);
+ return ECMD_TIME;
+}
+
+int
+do_run_southwest(void)
+{
+ set_move_cmd(DIR_SW, 3);
+ return ECMD_TIME;
+}
+
+/* #reqmenu, prefix command to modify some others */
+int
+do_reqmenu(void)
+{
+ iflags.menu_requested = TRUE;
+ return ECMD_OK;
+}
+
+/* #rush */
+int
+do_rush(void)
+{
+ g.context.run = 2;
+ g.domove_attempting |= DOMOVE_RUSH;
+ return ECMD_OK;
+}
+
+/* #run */
+int
+do_run(void)
+{
+ g.context.run = 3;
+ g.domove_attempting |= DOMOVE_RUSH;
+ return ECMD_OK;
+}
+
+/* #fight */
+int
+do_fight(void)
+{
+ g.context.forcefight = 1;
+ g.domove_attempting |= DOMOVE_WALK;
+ return ECMD_OK;
+}
+
/* extcmdlist: full command list, ordered by command name;
commands with no keystroke or with only a meta keystroke generally
need to be flagged as autocomplete and ones with a regular keystroke
impact frequently used #enhance by making #e become ambiguous */
{ M('X'), "exploremode", "enter explore (discovery) mode",
enter_explore_mode, IFBURIED | GENERALCMD | NOFUZZERCMD, NULL },
+ { 'F', "fight", "prefix: force fight even if you don't see a monster",
+ do_fight, PREFIXCMD, NULL },
{ 'f', "fire", "fire ammunition from quiver",
dofire, 0, NULL },
{ M('f'), "force", "force a lock",
doredraw, IFBURIED | GENERALCMD, NULL },
{ 'R', "remove", "remove an accessory (ring, amulet, etc)",
doremring, 0, NULL },
+ { 'm', "reqmenu", "prefix: request menu or modify command",
+ do_reqmenu, PREFIXCMD, NULL },
{ C('_'), "retravel", "travel to previously selected travel location",
dotravel_target, 0, NULL },
{ M('R'), "ride", "mount or dismount a saddled steed",
doride, AUTOCOMPLETE, NULL },
{ M('r'), "rub", "rub a lamp or a stone",
dorub, AUTOCOMPLETE, NULL },
+ { 'G', "run", "prefix: run until something interesting is seen",
+ do_run, PREFIXCMD, NULL },
+ { 'g', "rush", "prefix: rush until something interesting is seen",
+ do_rush, PREFIXCMD, NULL },
{ 'S', "save", "save the game and exit",
dosave, IFBURIED | GENERALCMD | NOFUZZERCMD, NULL },
{ 's', "search", "search for traps and secret doors",
wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL },
{ 'z', "zap", "zap a wand",
dozap, 0, NULL },
+ /* movement commands will be bound by reset_commands() */
+ /* move or attack */
+ { '\0', "movewest", "move west (screen left)",
+ do_move_west, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movenorthwest", "move northwest (screen upper left)",
+ do_move_northwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movenorth", "move north (screen up)",
+ do_move_north, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movenortheast", "move northeast (screen upper right)",
+ do_move_northeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "moveeast", "move east (screen right)",
+ do_move_east, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movesoutheast", "move southeast (screen lower right)",
+ do_move_southeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movesouth", "move south (screen down)",
+ do_move_south, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "movesouthwest", "move southwest (screen lower left)",
+ do_move_southwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ /* rush */
+ { '\0', "rushwest", "rush west (screen left)",
+ do_rush_west, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushnorthwest", "rush northwest (screen upper left)",
+ do_rush_northwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushnorth", "rush north (screen up)",
+ do_rush_north, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushnortheast", "rush northeast (screen upper right)",
+ do_rush_northeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rusheast", "rush east (screen right)",
+ do_rush_east, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushsoutheast", "rush southeast (screen lower right)",
+ do_rush_southeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushsouth", "rush south (screen down)",
+ do_rush_south, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "rushsouthwest", "rush southwest (screen lower left)",
+ do_rush_southwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ /* run */
+ { '\0', "runwest", "run west (screen left)",
+ do_run_west, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runnorthwest", "run northwest (screen upper left)",
+ do_run_northwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runnorth", "run north (screen up)",
+ do_run_north, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runnortheast", "run northeast (screen upper right)",
+ do_run_northeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runeast", "run east (screen right)",
+ do_run_east, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runsoutheast", "run southeast (screen lower right)",
+ do_run_southeast, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runsouth", "run south (screen down)",
+ do_run_south, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+ { '\0', "runsouthwest", "run southwest (screen lower left)",
+ do_run_southwest, MOVEMENTCMD | CMD_M_PREFIX, NULL },
+
/* internal commands: only used by game core, not available for user */
{ '\0', "clicklook", NULL, doclicklook, INTERNALCMD, NULL },
{ '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */
};
-/* used by dokeylist() and by key2extcmdesc() for dowhatdoes() */
-static const char
- run_desc[] = "Prefix: run until something very interesting is seen",
- rush_desc[] = "Prefix: rush until something interesting is seen",
- forcefight_desc[] = "Prefix: force fight even if you don't see a monster";
+/* mapping direction and move mode to extended command function */
+static int (*move_funcs[N_DIRS_Z][N_MOVEMODES])(void) = {
+ { do_move_west, do_run_west, do_rush_west },
+ { do_move_northwest, do_run_northwest, do_rush_northwest },
+ { do_move_north, do_run_north, do_rush_north },
+ { do_move_northeast, do_run_northeast, do_rush_northeast },
+ { do_move_east, do_run_east, do_rush_east },
+ { do_move_southeast, do_run_southeast, do_rush_southeast },
+ { do_move_south, do_run_south, do_rush_south },
+ { do_move_southwest, do_run_southwest, do_rush_southwest },
+ { dodown, dodown, dodown },
+ { doup, doup, doup },
+};
+/* used by dokeylist() and by key2extcmdesc() for dowhatdoes() */
static const struct {
int nhkf;
const char *desc;
boolean numpad;
} misc_keys[] = {
{ NHKF_ESC, "cancel current prompt or pending prefix", FALSE },
- { NHKF_RUSH, rush_desc, FALSE },
- { NHKF_RUSH2, rush_desc, TRUE },
- { NHKF_RUN, run_desc, FALSE },
- { NHKF_RUN2, run_desc, TRUE },
- { NHKF_FIGHT, forcefight_desc, FALSE },
- { NHKF_FIGHT2, forcefight_desc, TRUE } ,
- { NHKF_NOPICKUP,
- "Prefix: move without picking up objects or fighting", FALSE },
- { NHKF_RUN_NOPICKUP,
- "Prefix: run without picking up objects or fighting", FALSE },
- { NHKF_REQMENU,
- "Prefix: request a menu (for some non-movement commands)", FALSE },
{ NHKF_COUNT,
"Prefix: for digits when preceding a command with a count", TRUE },
{ NHKF_DOAGAIN , "repeat: perform the previous command again", FALSE },
{ 0, (const char *) 0, FALSE }
};
-/* for key2extcmddesc() to support dowhatdoes() */
-struct movcmd {
- uchar k1, k2, k3, k4; /* 'normal', 'qwertz', 'numpad', 'phone' */
- const char *txt, *alt; /* compass direction, screen direction */
-};
-static const struct movcmd movtab[] = {
- { 'h', 'h', '4', '4', "west", "left" },
- { 'j', 'j', '2', '8', "south", "down" },
- { 'k', 'k', '8', '2', "north", "up" },
- { 'l', 'l', '6', '6', "east", "right" },
- { 'b', 'b', '1', '7', "southwest", "lower left" },
- { 'n', 'n', '3', '9', "southeast", "lower right" },
- { 'u', 'u', '9', '3', "northeast", "upper right" },
- { 'y', 'z', '7', '1', "northwest", "upper left" },
- { 0, 0, 0, 0, (char *) 0, (char *) 0 }
-};
-
int extcmdlist_length = SIZE(extcmdlist) - 1;
const char *
key2extcmddesc(uchar key)
{
static char key2cmdbuf[QBUFSZ];
- const struct movcmd *mov;
- int k, c, i, j;
+ int k, i, j;
uchar M_5 = (uchar) M('5'), M_0 = (uchar) M('0');
/* need to check for movement commands before checking the extended
Strcpy(key2cmdbuf, "rush");
else if (movecmd(k = key, MV_RUN))
Strcpy(key2cmdbuf, "run");
- if (*key2cmdbuf) {
- for (mov = &movtab[0]; mov->k1; ++mov) {
- c = !g.Cmd.num_pad ? (!g.Cmd.swap_yz ? mov->k1 : mov->k2)
- : (!g.Cmd.phone_layout ? mov->k3 : mov->k4);
- if (c == k) {
- Sprintf(eos(key2cmdbuf), " %s (screen %s)",
- mov->txt, mov->alt);
- return key2cmdbuf;
- }
- }
- } else if (digit(key) || (g.Cmd.num_pad && digit(unmeta(key)))) {
+ if (digit(key) || (g.Cmd.num_pad && digit(unmeta(key)))) {
key2cmdbuf[0] = '\0';
if (!g.Cmd.num_pad)
Strcpy(key2cmdbuf, "start of, or continuation of, a count");
return FALSE;
}
+/* bind key by ext cmd function */
+static boolean
+bind_key_fn(uchar key, int (*fn)(void))
+{
+ struct ext_func_tab *extcmd;
+
+ for (extcmd = extcmdlist; extcmd->ef_txt; extcmd++) {
+ if (extcmd->ef_funct != fn)
+ continue;
+ if ((extcmd->flags & INTERNALCMD) != 0)
+ continue;
+ g.Cmd.commands[key] = extcmd;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* initialize all keyboard commands */
static void
commands_init(void)
if (extcmd->key)
g.Cmd.commands[extcmd->key] = extcmd;
- (void) bind_key(C('l'), "redraw"); /* if number_pad is set */
- /* 'b', 'B' : go sw */
- /* 'F' : fight (one time) */
- /* 'g', 'G' : multiple go */
- /* 'h', 'H' : go west */
- (void) bind_key('h', "help"); /* if number_pad is set */
- (void) bind_key('j', "jump"); /* if number_pad is on */
- /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' move commands */
- (void) bind_key('k', "kick"); /* if number_pad is on */
- (void) bind_key('l', "loot"); /* if number_pad is on */
- (void) bind_key(C('n'), "annotate"); /* if number_pad is on */
- (void) bind_key(M('n'), "name");
- (void) bind_key(M('N'), "name");
- (void) bind_key('u', "untrap"); /* if number_pad is on */
+ /* number_pad */
+ (void) bind_key(C('l'), "redraw");
+ (void) bind_key('h', "help");
+ (void) bind_key('j', "jump");
+ (void) bind_key('k', "kick");
+ (void) bind_key('l', "loot");
+ (void) bind_key(C('n'), "annotate");
+ (void) bind_key('u', "untrap");
+ (void) bind_key('5', "run");
+ (void) bind_key(M('5'), "rush");
+ (void) bind_key('-', "fight");
/* alt keys: */
(void) bind_key(M('O'), "overview");
(void) bind_key(M('2'), "twoweapon");
+ (void) bind_key(M('n'), "name");
+ (void) bind_key(M('N'), "name");
/* wait_on_space */
(void) bind_key(' ', "wait");
(void) memset((genericptr_t) keys_used, 0, sizeof keys_used);
(void) memset((genericptr_t) pfx_seen, 0, sizeof pfx_seen);
- for (i = 0; i < N_DIRS; i++) {
- keys_used[(uchar) g.Cmd.move[i]] = TRUE;
- keys_used[(uchar) g.Cmd.rush[i]] = TRUE;
- keys_used[(uchar) g.Cmd.run[i]] = TRUE;
- }
#ifndef NO_SIGNAL
/* this is actually ambiguous; tty raw mode will override SIGINT;
when enabled, treat it like a movement command since assigning
continue;
j = misc_keys[i].nhkf;
key = (uchar) g.Cmd.spkeys[j];
- if (key && !mov_seen[key] && (!pfx_seen[key] || j == NHKF_REQMENU)) {
+ if (key && !mov_seen[key] && !pfx_seen[key]) {
keys_used[key] = TRUE;
- if (j != NHKF_REQMENU)
- pfx_seen[key] = j;
+ pfx_seen[key] = j;
} else
spkey_gap = TRUE;
}
j = misc_keys[i].nhkf;
key = (uchar) g.Cmd.spkeys[j];
if (key && !mov_seen[key]
- && (pfx_seen[key] == j || j == NHKF_REQMENU)) {
+ && (pfx_seen[key] == j)) {
Sprintf(buf, "%-7s %s", key2txt(key, buf2), misc_keys[i].desc);
putstr(datawin, 0, buf);
}
continue;
j = misc_keys[i].nhkf;
key = (uchar) g.Cmd.spkeys[j];
- if (!key || (pfx_seen[key] != j && j != NHKF_REQMENU)) {
+ if (!key || (pfx_seen[key] != j)) {
Sprintf(buf2, "[%s]", spkey_name(j));
/* lines up with the other unassigned commands which use
"#%-20s ", but not with the other special keys */
}
}
+#define IGNORECMD (WIZMODECMD | INTERNALCMD | MOVEMENTCMD)
+
putstr(datawin, 0, "");
show_menu_controls(datawin, TRUE);
- if (keylist_putcmds(datawin, TRUE, GENERALCMD,
- WIZMODECMD | INTERNALCMD, keys_used)) {
+ if (keylist_putcmds(datawin, TRUE, GENERALCMD, IGNORECMD, keys_used)) {
putstr(datawin, 0, "");
putstr(datawin, 0, "General commands:");
(void) keylist_putcmds(datawin, FALSE, GENERALCMD,
- WIZMODECMD | INTERNALCMD,
- keys_used);
+ IGNORECMD, keys_used);
}
- if (keylist_putcmds(datawin, TRUE, 0,
- GENERALCMD | WIZMODECMD | INTERNALCMD, keys_used)) {
+ if (keylist_putcmds(datawin, TRUE, 0, GENERALCMD | IGNORECMD, keys_used)) {
putstr(datawin, 0, "");
putstr(datawin, 0, "Game commands:");
(void) keylist_putcmds(datawin, FALSE, 0,
- GENERALCMD | WIZMODECMD | INTERNALCMD,
+ GENERALCMD | IGNORECMD,
keys_used);
}
display_nhwindow(datawin, FALSE);
destroy_nhwindow(datawin);
+#undef IGNORECMD
}
const struct ext_func_tab *
return NULL;
}
+/* returns the key bound to a movement command for given DIR_ and MV_ mode */
+char
+cmd_from_dir(int dir, int mode)
+{
+ return cmd_from_func(move_funcs[dir][mode]);
+}
+
char
cmd_from_func(int (*fn)(void))
{
} const spkeys_binds[] = {
{ NHKF_ESC, '\033', (char *) 0 }, /* no binding */
{ NHKF_DOAGAIN, DOAGAIN, "repeat" },
- { NHKF_REQMENU, 'm', "reqmenu" },
- { NHKF_RUN, 'G', "run" },
- { NHKF_RUN2, '5', "run.numpad" },
- { NHKF_RUSH, 'g', "rush" },
- { NHKF_RUSH2, M('5'), "rush.numpad" },
- { NHKF_FIGHT, 'F', "fight" },
- { NHKF_FIGHT2, '-', "fight.numpad" },
- { NHKF_NOPICKUP, 'm', "nopickup" },
- { NHKF_RUN_NOPICKUP, 'M', "run.nopickup" },
- { NHKF_REDRAW, C('r'), "redraw" },
- { NHKF_REDRAW2, C('l'), "redraw.numpad" },
{ NHKF_GETDIR_SELF, '.', "getdir.self" },
{ NHKF_GETDIR_SELF2, 's', "getdir.self2" },
{ NHKF_GETDIR_HELP, '?', "getdir.help" },
static const int ylist[] = {
'y', 'Y', C('y'), M('y'), M('Y'), M(C('y'))
};
- static struct ext_func_tab *back_dir_cmd[N_DIRS];
+ static struct ext_func_tab *back_dir_cmd[N_DIRS_Z][N_MOVEMODES];
+ static uchar back_dir_key[N_DIRS_Z][N_MOVEMODES];
static boolean backed_dir_cmd = FALSE;
const struct ext_func_tab *cmdtmp;
boolean flagtemp;
int c, i, updated = 0;
+ int dir, mode;
if (initial) {
updated = 1;
commands_init();
} else {
if (backed_dir_cmd) {
- for (i = 0; i < N_DIRS; i++) {
- g.Cmd.commands[(uchar) g.Cmd.dirchars[i]] = back_dir_cmd[i];
+ for (dir = 0; dir < N_DIRS_Z; dir++) {
+ for (mode = 0; mode < N_MOVEMODES; mode++) {
+ g.Cmd.commands[back_dir_key[dir][mode]] = back_dir_cmd[dir][mode];
+ }
}
}
cmdtmp = g.Cmd.commands['5'];
g.Cmd.commands['5'] = g.Cmd.commands[c];
g.Cmd.commands[c] = cmdtmp;
-#else
- c = g.Cmd.spkeys[NHKF_RUN2];
- g.Cmd.spkeys[NHKF_RUN2] = g.Cmd.spkeys[NHKF_RUSH2];
- g.Cmd.spkeys[NHKF_RUSH2] = c;
#endif
/* FIXME: NHKF_DOINV2 ought to be implemented instead of this */
c = M('0') & 0xff;
}
} /*?initial*/
+ /* choose updated movement keys */
if (updated)
g.Cmd.serialno++;
g.Cmd.dirchars = !g.Cmd.num_pad
: (!g.Cmd.phone_layout ? ndir : ndir_phone_layout);
g.Cmd.alphadirchars = !g.Cmd.num_pad ? g.Cmd.dirchars : sdir;
- for (i = 0; i < N_DIRS; i++) {
- g.Cmd.move[i] = g.Cmd.dirchars[i];
- if (!g.Cmd.num_pad) {
- g.Cmd.run[i] = highc(g.Cmd.move[i]);
- g.Cmd.rush[i] = C(g.Cmd.move[i]);
- } else {
- g.Cmd.run[i] = M(g.Cmd.move[i]);
- g.Cmd.rush[i] = M(g.Cmd.move[i]);
+ /* back up the commands & keys overwritten by new movement keys */
+ for (dir = 0; dir < N_DIRS_Z; dir++) {
+ for (mode = MV_WALK; mode < N_MOVEMODES; mode++) {
+ uchar di = (uchar) g.Cmd.dirchars[dir];
+
+ if (!g.Cmd.num_pad) {
+ if (mode == MV_RUN) di = highc(di);
+ else if (mode == MV_RUSH) di = C(di);
+ } else {
+ if (mode == MV_RUN) di = M(di);
+ else if (mode == MV_RUSH) di = M(di);
+ }
+ back_dir_key[dir][mode] = di;
+ back_dir_cmd[dir][mode] = (struct ext_func_tab *) g.Cmd.commands[di];
+ g.Cmd.commands[di] = (struct ext_func_tab *) 0;
}
}
+ backed_dir_cmd = TRUE;
- if (!initial) {
- for (i = 0; i < N_DIRS; i++) {
- uchar di = (uchar) g.Cmd.dirchars[i];
-
- back_dir_cmd[i] = (struct ext_func_tab *) g.Cmd.commands[di];
- g.Cmd.commands[di] = (struct ext_func_tab *) 0;
+ /* bind the new keys to movement commands */
+ for (i = 0; i < N_DIRS; i++) {
+ (void) bind_key_fn(g.Cmd.dirchars[i], move_funcs[i][MV_WALK]);
+ if (!g.Cmd.num_pad) {
+ (void) bind_key_fn(highc(g.Cmd.dirchars[i]), move_funcs[i][MV_RUN]);
+ (void) bind_key_fn(C(g.Cmd.dirchars[i]), move_funcs[i][MV_RUSH]);
+ } else {
+ (void) bind_key_fn(M(g.Cmd.dirchars[i]), move_funcs[i][MV_RUN]);
+ (void) bind_key_fn(M(g.Cmd.dirchars[i]), move_funcs[i][MV_RUSH]);
}
- backed_dir_cmd = TRUE;
- for (i = 0; i < N_DIRS; i++)
- (void) bind_key(g.Cmd.dirchars[i], "nothing");
}
}
-/* non-movement commands which accept 'm' prefix to request menu operation */
+/* commands which accept 'm' prefix to request menu operation */
static boolean
accept_menu_prefix(const struct ext_func_tab *ec)
{
case 12:
{
int d = rn2(N_DIRS);
- if (!rn2(7))
- c = !rn2(3) ? g.Cmd.rush[d] : g.Cmd.run[d];
- else
- c = g.Cmd.move[d];
+ int m = rn2(7) ? MV_WALK : (!rn2(3) ? MV_RUSH : MV_RUN);
+
+ c = cmd_from_dir(d, m);
}
break;
case 13:
return rn2(extcmdlist_length + 1) - 1;
}
-static int
-ch2spkeys(char c, int start, int end)
-{
- int i;
-
- for (i = start; i <= end; i++)
- if (g.Cmd.spkeys[i] == c)
- return i;
- return NHKF_ESC;
-}
-
void
rhack(char *cmd)
{
const struct ext_func_tab *cmdq_ec = NULL;
iflags.menu_requested = FALSE;
+ prefix_seen = FALSE;
+ g.context.nopick = 0;
+got_prefix_input:
#ifdef SAFERHANGUP
if (g.program_state.done_hup)
end_of_input();
if (cmdq_ec)
goto do_cmdq_extcmd;
} else if (firsttime) {
- g.context.nopick = 0;
cmd = parse();
}
+
if (*cmd == g.Cmd.spkeys[NHKF_ESC]) {
g.context.move = FALSE;
+ iflags.menu_requested = FALSE;
return;
}
/* DOAGAIN might be '\0'; if so, don't execute it even if *cmd is too */
g.stail = 0;
rhack((char *) 0); /* read and execute command */
g.in_doagain = FALSE;
+ iflags.menu_requested = FALSE;
return;
}
/* Special case of *cmd == ' ' handled better below */
if (!*cmd || *cmd == (char) 0377) {
nhbell();
g.context.move = FALSE;
+ iflags.menu_requested = FALSE;
return; /* probably we just had an interrupt */
}
/* handle most movement commands */
- prefix_seen = FALSE;
g.context.travel = g.context.travel1 = 0;
- spkey = ch2spkeys(*cmd, NHKF_RUN, NHKF_RUN_NOPICKUP);
-
- switch (spkey) {
- case NHKF_RUSH2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- case NHKF_RUSH:
- if (movecmd(cmd[1], MV_ANY)) {
- g.context.run = 2;
- g.domove_attempting |= DOMOVE_RUSH;
- } else
- prefix_seen = TRUE;
- break;
- case NHKF_RUN2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- case NHKF_RUN:
- if (movecmd(cmd[1], MV_ANY)) {
- g.context.run = 3;
- g.domove_attempting |= DOMOVE_RUSH;
- } else
- prefix_seen = TRUE;
- break;
- case NHKF_FIGHT2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- /* Effects of movement commands and invisible monsters:
- * m: always move onto space (even if 'I' remembered)
- * F: always attack space (even if 'I' not remembered)
- * normal movement: attack if 'I', move otherwise.
- */
- case NHKF_FIGHT:
- if (movecmd(cmd[1], MV_ANY)) {
- g.context.forcefight = 1;
- g.domove_attempting |= DOMOVE_WALK;
- } else
- prefix_seen = TRUE;
- break;
- case NHKF_NOPICKUP:
- if (movecmd(cmd[1], MV_ANY) || u.dz) {
- g.context.run = 0;
- g.context.nopick = 1;
- if (!u.dz)
- g.domove_attempting |= DOMOVE_WALK;
- else
- cmd[0] = cmd[1]; /* "m<" or "m>" */
- } else
- prefix_seen = TRUE;
- break;
- case NHKF_RUN_NOPICKUP:
- if (movecmd(cmd[1], MV_ANY)) {
- g.context.run = 1;
- g.context.nopick = 1;
- g.domove_attempting |= DOMOVE_RUSH;
- } else
- prefix_seen = TRUE;
- break;
- default:
- if (movecmd(*cmd, MV_WALK)) { /* ordinary movement */
- g.context.run = 0; /* only matters here if it was 8 */
- g.domove_attempting |= DOMOVE_WALK;
- } else if (movecmd(*cmd, MV_RUN)) {
- g.context.run = 1;
- g.domove_attempting |= DOMOVE_RUSH;
- } else if (movecmd(*cmd, MV_RUSH)) {
- g.context.run = 3;
- g.domove_attempting |= DOMOVE_RUSH;
- }
- break;
- }
- /* after movement--if reqmenu duplicates a prefix, movement takes
- precedence; "request a menu" (default 'm') */
- if (cmd[0] == g.Cmd.spkeys[NHKF_REQMENU]) {
- /* (for func_tab cast, see below) */
- const struct ext_func_tab *ft = g.Cmd.commands[cmd[1] & 0xff];
- int (*func)(void) = ft ? ((struct ext_func_tab *) ft)->ef_funct : 0;
-
- if (func && accept_menu_prefix(ft)) {
- iflags.menu_requested = TRUE;
- ++cmd;
- prefix_seen = FALSE;
- } else {
- prefix_seen = TRUE;
- }
- }
-
- if (((g.domove_attempting & (DOMOVE_RUSH | DOMOVE_WALK)) != 0L)
- && !g.context.travel && !dxdy_moveok()) {
- /* trying to move diagonally as a grid bug;
- this used to be treated by movecmd() as not being
- a movement attempt, but that didn't provide for any
- feedback and led to strangeness if the key pressed
- ('u' in particular) was overloaded for num_pad use */
- You_cant("get there from here...");
- g.context.run = 0;
- g.context.nopick = g.context.forcefight = FALSE;
- g.context.move = g.context.mv = FALSE;
- g.multi = 0;
- return;
- }
-
- if ((g.domove_attempting & DOMOVE_WALK) != 0L) {
- if (g.multi)
- g.context.mv = TRUE;
- domove();
- g.context.forcefight = 0;
- return;
- } else if ((g.domove_attempting & DOMOVE_RUSH) != 0L) {
- if (firsttime) {
- if (!g.multi)
- g.multi = max(COLNO, ROWNO);
- u.last_str_turn = 0;
- }
- g.context.mv = TRUE;
- domove();
- return;
- } else if (prefix_seen) {
- if (cmd[1] == g.Cmd.spkeys[NHKF_ESC]) {
- /* <prefix><escape> */
- /* don't report "unknown command" for change of heart... */
- bad_command = FALSE;
- } else { /* prefix followed by non-movement command */
- bad_command = TRUE; /* skip cmdlist[] loop */
- }
- } else if (*cmd == ' ' && !flags.rest_on_space) {
- bad_command = TRUE; /* skip cmdlist[] loop */
-
- /* handle all other commands */
- } else {
+ {
register const struct ext_func_tab *tlist;
int res, (*func)(void);
if (!can_do_extcmd(tlist)) {
res = ECMD_OK;
cmdq_clear();
+ } else if (prefix_seen && !accept_menu_prefix(tlist)
+ && !(tlist->flags & PREFIXCMD)) {
+ /* we got a prefix previously, can this command accept one? */
+ res = ECMD_OK;
+ cmdq_clear();
} else {
/* we discard 'const' because some compilers seem to have
trouble with the pointer passed to set_occupation() */
if (tlist->f_text && !g.occupation && g.multi)
set_occupation(func, tlist->f_text, g.multi);
res = (*func)(); /* perform the command */
+
+ if ((tlist->flags & PREFIXCMD)) {
+ /* it was a prefix command, mark and get another command */
+ prefix_seen = TRUE;
+ bad_command = FALSE;
+ goto got_prefix_input;
+ } else if (((g.domove_attempting & (DOMOVE_RUSH | DOMOVE_WALK)) != 0L)
+ && !g.context.travel && !dxdy_moveok()) {
+ /* trying to move diagonally as a grid bug */
+ You_cant("get there from here...");
+ g.context.run = 0;
+ g.context.nopick = g.context.forcefight = FALSE;
+ g.context.move = g.context.mv = FALSE;
+ g.multi = 0;
+ iflags.menu_requested = FALSE;
+ return;
+ } else if ((g.domove_attempting & DOMOVE_WALK) != 0L) {
+ if (g.multi)
+ g.context.mv = TRUE;
+ domove();
+ g.context.forcefight = 0;
+ iflags.menu_requested = FALSE;
+ return;
+ } else if ((g.domove_attempting & DOMOVE_RUSH) != 0L) {
+ if (firsttime) {
+ if (!g.multi)
+ g.multi = max(COLNO, ROWNO);
+ u.last_str_turn = 0;
+ }
+ g.context.mv = TRUE;
+ domove();
+ iflags.menu_requested = FALSE;
+ return;
+ }
+ prefix_seen = FALSE;
}
if ((res & ECMD_CANCEL)) {
/* command was canceled by user, maybe they declined to
pick an object to act on. */
+ iflags.menu_requested = FALSE;
cmdq_clear();
}
if (!(res & ECMD_TIME)) {
+ iflags.menu_requested = FALSE;
g.context.move = FALSE;
g.multi = 0;
}
{
int d = DIR_ERR;
- if (g.Cmd.commands[(uchar)sym]
- && g.Cmd.commands[(uchar)sym]->ef_funct == dodown) {
- d = DIR_DOWN;
- } else if (g.Cmd.commands[(uchar)sym]
- && g.Cmd.commands[(uchar)sym]->ef_funct == doup) {
- d = DIR_UP;
- } else {
- char *mvkeys = (mode == MV_WALK) ? g.Cmd.move :
- ((mode == MV_RUN) ? g.Cmd.run : g.Cmd.rush);
-
- for (d = N_DIRS - 1; d > DIR_ERR; d--) {
- if (mode == MV_ANY) {
- if (sym == g.Cmd.move[d]
- || sym == g.Cmd.rush[d]
- || sym == g.Cmd.run[d])
+ if (g.Cmd.commands[(uchar)sym]) {
+ int (*fnc)(void) = g.Cmd.commands[(uchar)sym]->ef_funct;
+
+ if (mode == MV_ANY) {
+ for (d = N_DIRS_Z - 1; d > DIR_ERR; d--)
+ if (fnc == move_funcs[d][MV_WALK]
+ || fnc == move_funcs[d][MV_RUN]
+ || fnc == move_funcs[d][MV_RUSH])
+ break;
+ } else {
+ for (d = N_DIRS_Z - 1; d > DIR_ERR; d--)
+ if (fnc == move_funcs[d][mode])
break;
- } else if (sym == mvkeys[d])
- break;
}
}
+
if (d != DIR_ERR) {
u.dx = xdir[d];
u.dy = ydir[d];
boolean
redraw_cmd(char c)
{
- return (boolean) (c == g.Cmd.spkeys[NHKF_REDRAW]
- || (g.Cmd.num_pad && c == g.Cmd.spkeys[NHKF_REDRAW2]));
-}
-
-static boolean
-prefix_cmd(char c)
-{
- return (c == g.Cmd.spkeys[NHKF_REQMENU]
- || c == g.Cmd.spkeys[NHKF_RUSH]
- || c == g.Cmd.spkeys[NHKF_RUN]
- || c == g.Cmd.spkeys[NHKF_NOPICKUP]
- || c == g.Cmd.spkeys[NHKF_RUN_NOPICKUP]
- || c == g.Cmd.spkeys[NHKF_FIGHT]
- || (g.Cmd.num_pad && (c == g.Cmd.spkeys[NHKF_RUN2]
- || c == g.Cmd.spkeys[NHKF_RUSH2]
- || c == g.Cmd.spkeys[NHKF_FIGHT2])));
+ return (boolean) (g.Cmd.commands[(uchar)c]
+ && g.Cmd.commands[(uchar)c]->ef_funct == doredraw);
}
/*
centerchar = ' ';
if (nodiag) {
- Sprintf(buf, " %c ", g.Cmd.move[DIR_N]);
+ Sprintf(buf, " %s ",
+ visctrl(cmd_from_func(do_move_north)));
putstr(win, 0, buf);
putstr(win, 0, " | ");
- Sprintf(buf, " %c- %c -%c",
- g.Cmd.move[DIR_W], centerchar, g.Cmd.move[DIR_E]);
+ Sprintf(buf, " %s- %c -%s",
+ visctrl(cmd_from_func(do_move_west)),
+ centerchar,
+ visctrl(cmd_from_func(do_move_east)));
putstr(win, 0, buf);
putstr(win, 0, " | ");
- Sprintf(buf, " %c ", g.Cmd.move[DIR_S]);
+ Sprintf(buf, " %s ",
+ visctrl(cmd_from_func(do_move_south)));
putstr(win, 0, buf);
} else {
- Sprintf(buf, " %c %c %c",
- g.Cmd.move[DIR_NW], g.Cmd.move[DIR_N], g.Cmd.move[DIR_NE]);
+ Sprintf(buf, " %s %s %s",
+ visctrl(cmd_from_func(do_move_northwest)),
+ visctrl(cmd_from_func(do_move_north)),
+ visctrl(cmd_from_func(do_move_northeast)));
putstr(win, 0, buf);
putstr(win, 0, " \\ | / ");
- Sprintf(buf, " %c- %c -%c",
- g.Cmd.move[DIR_W], centerchar, g.Cmd.move[DIR_E]);
+ Sprintf(buf, " %s- %c -%s",
+ visctrl(cmd_from_func(do_move_west)),
+ centerchar,
+ visctrl(cmd_from_func(do_move_east)));
putstr(win, 0, buf);
putstr(win, 0, " / | \\ ");
- Sprintf(buf, " %c %c %c",
- g.Cmd.move[DIR_SW], g.Cmd.move[DIR_S], g.Cmd.move[DIR_SE]);
+ Sprintf(buf, " %s %s %s",
+ visctrl(cmd_from_func(do_move_southwest)),
+ visctrl(cmd_from_func(do_move_south)),
+ visctrl(cmd_from_func(do_move_southeast)));
putstr(win, 0, buf);
};
}
*/
dothat = "do that";
how = " at"; /* for "<action> at yourself"; not used for up/down */
- switch (spkey) {
- case NHKF_NOPICKUP:
- dothat = "move";
- break;
- case NHKF_RUSH2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- case NHKF_RUSH:
- dothat = "rush";
- break;
- case NHKF_RUN2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- case NHKF_RUN:
- case NHKF_RUN_NOPICKUP:
- dothat = "run";
- break;
- case NHKF_FIGHT2:
- if (!g.Cmd.num_pad)
- break;
- /*FALLTHRU*/
- case NHKF_FIGHT:
- dothat = "fight";
- how = ""; /* avoid "fight at yourself" */
- break;
- default:
- prefixhandling = FALSE;
- break;
- }
+ prefixhandling = FALSE;
buf[0] = '\0';
/* for movement prefix followed by '.' or (numpad && 's') to mean 'self';
putstr(win, 0, buf);
show_direction_keys(win, !prefixhandling ? '.' : ' ', NODIAG(u.umonnum));
- if (!prefixhandling || spkey == NHKF_NOPICKUP) {
+ if (!prefixhandling) {
/* NOPICKUP: unlike the other prefix keys, 'm' allows up/down for
stair traversal; we won't get here when "m<" or "m>" has been
given but we include up and down for 'm'+invalid_direction;
dir = xytod(x, y);
if (!m_at(u.ux + x, u.uy + y)
&& !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
- cmd[1] = g.Cmd.move[dir];
+ cmd[1] = cmd_from_func(move_funcs[dir][MV_WALK]);
cmd[2] = '\0';
if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
/* move, attack, etc. */
cmd[1] = 0;
if (mod == CLICK_1) {
- cmd[0] = g.Cmd.move[dir];
+ cmd[0] = cmd_from_func(move_funcs[dir][MV_WALK]);
} else {
- cmd[0] = g.Cmd.run[dir];
+ cmd[0] = cmd_from_func(move_funcs[dir][MV_RUN]);
}
return cmd;
if (g.multi)
g.multi--;
- /* in 3.4.3 this was in rhack(), where it was too late to handle M-5 */
- if (g.Cmd.pcHack_compat) {
- /* This handles very old inconsistent DOS/Windows behaviour
- in a different way: earlier, the keyboard handler mapped
- these, which caused counts to be strange when entered
- from the number pad. Now do not map them until here. */
- switch (foo) {
- case '5':
- foo = g.Cmd.spkeys[NHKF_RUSH];
- break;
- case M('5'):
- foo = g.Cmd.spkeys[NHKF_RUN];
- break;
- default:
- break; /* as is */
- }
- }
-
g.command_line[0] = foo;
g.command_line[1] = '\0';
- if (prefix_cmd(foo)) {
- foo = readchar();
- savech((char) foo);
- g.command_line[1] = foo;
- g.command_line[2] = 0;
- }
clear_nhwindow(WIN_MESSAGE);
iflags.in_parse = FALSE;