From: Pasi Kallinen Date: Sat, 15 Jan 2022 23:22:17 +0000 (+0200) Subject: Change special keys into extended commands X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7fa065203558f44666f53debe6cbdfd9b2596a1;p=nethack Change special keys into extended commands Changes most of the special keys used in the main input loop into extended commands: - movement keys are now bound to extended commands, eg. #movewest and so on. - m-prefix is now #reqmenu extended command, still bound to the 'm' key. - run, rush, and fight are now extended commands, still bound to the same keys as previously. - nopickup and runnopickup keys are removed. Nopickup was using 'm' key, the same as the m-prefix, so allow #reqmenu to modify movement commands to disable pickup. - multiple prefix commands are allowed. This lets user to use #reqmenu, followed by #run, followed by movement to simulate runnopickup behaviour. (If necessary, adding runnopickup back as an extended command would be easy) --- diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 10acbf05c..2058f33a5 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1245,6 +1245,11 @@ To really switch to explore mode, respond with \f(CRy\fP. You can set the .op paranoid_confirmation:quit option to require a response of \f(CRyes\fP instead. +.lp "#fight " +Prefix key to force fight a direction, even if you see nothing +to fight there. +Default key is \(oqF\(cq, or \(oq\-\(cq with +.op number_pad .lp "#fire " Fire ammunition from quiver, possibly autowielding a launcher, or hit with a wielded polearm. @@ -1439,6 +1444,10 @@ is on. .lp "#remove " Remove an accessory (ring, amulet, etc). Default key is \(oqR\(cq. +.lp "#reqmenu " +Prefix key to modify the behaviour or request menu from some commands. +Prevents autopickup when used with movement commands. +Default key is \(oqm\(cq. .lp "#retravel" Travel to a previously selected travel destination. Default key is \(oqC-_\(cq. @@ -1451,6 +1460,24 @@ Default key is \(oqM-R\(cq. Rub a lamp or a stone. Autocompletes. Default key is \(oqM-r\(cq. +.lp "#run " +Prefix key to run towards a direction. +Default key is \(oqG\(cq when +.op number_pad +is off, +\(oq5\(cq when +.op number_pad +is set to 1 or 3, +otherwise \(oqM-5\(cq when it is set to 2 or 4. +.lp "#rush " +Prefix key to rush towards a direction. +Default is \(oqg\(cq when +.op number_pad +is off, +\(oqM-5\(cq when +.op number_pad +is set to 1 or 3, +otherwise \(oq5\(cq when it is set to 2 or 4. .lp "#save " Save the game and exit the program. Default key is \(oqS\(cq. @@ -4775,15 +4802,6 @@ With .op number_pad only. Default is \(oqn\(cq. -.lp fight -Prefix key to force fight a direction. -Default is \(oqF\(cq. -.lp fight.numpad -Prefix key to force fight a direction. -With -.op number_pad -only. -Default is \(oq\-\(cq. .lp getdir.help When asked for a direction, the key to show the help. Default is \(oq?\(cq. @@ -4874,49 +4892,9 @@ Default is \(oqz\(cq. .lp getpos.valid.prev When asked for a location, the key to go to previous closest valid location. Default is \(oqZ\(cq. -.lp nopickup -Prefix key to move without picking up items. -Default is \(oqm\(cq. -.lp redraw -Key to redraw the screen. -Default is \(oq\(haR\(cq. -.lp redraw.numpad -Key to redraw the screen. -With -.op number_pad -only. -Default is \(oq\(haL\(cq. .lp repeat Key to repeat previous command. Default is \(oq\(haA\(cq. -.lp reqmenu -Prefix key to request menu from some commands. -Default is \(oqm\(cq. -.lp run -Prefix key to run towards a direction. -Default is \(oqG\(cq. -.lp run.nopickup -Prefix key to run towards a direction without picking up items on the way. -Default is \(oqM\(cq. -.lp run.numpad -Prefix key to run towards a direction. -With -.op number_pad -only. -.lp "" -Default is \(oq5\(cq when number_pad is set to 1 or 3, -otherwise \(oqM-5\(cq when it is set to 2 or 4. -.lp rush -Prefix key to rush towards a direction. -Default is \(oqg\(cq. -.lp rush.numpad -Prefix key to rush towards a direction. -With -.op number_pad -only. -.lp "" -Default is \(oqM-5\(cq when number_pad is set to 1 or 3, -otherwise \(oq5\(cq when it is set to 2 or 4. .hn 2 Configuring Message Types .pg diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 5b7d7a6a3..84fde4b6e 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -1349,6 +1349,12 @@ You can set the {\it paranoid\verb+_+confirmation:quit\/} option to require a response of ``{\tt yes}'' instead. %.lp +\item[\tb{\#fight}] +Prefix key to force fight a direction, even if you see nothing +to fight there. +Default key is `{\tt F}', or `{\tt -}' with +{\it number\verb+_+pad\/} +%.lp \item[\tb{\#fire}] Fire ammunition from quiver, possibly autowielding a launcher, or hit with a wielded polearm. @@ -1546,6 +1552,11 @@ and also `{\tt \^{}L}' if {\it number\verb+_+pad\/} is on. \item[\tb{\#remove}] Remove an accessory (ring, amulet, etc). Default key is `{\tt R}'. %.lp +\item[\tb{\#reqmenu}] +Prefix key to modify the behaviour or request menu from some commands. +Prevents autopickup when used with movement commands. +Default key is `{\tt m}'. +%.lp \item[\tb{\#retravel}] Travel to a previously selected travel destination. Default key is `{\tt C-_}'. @@ -1558,6 +1569,26 @@ Default key is `{\tt M-R}'. \item[\tb{\#rub}] Rub a lamp or a stone. Autocompletes. Default key is `{\tt M-r}'. %.lp +\item[\tb{\#run}] +Prefix key to run towards a direction. +Default key is `{\tt G}' when +{\it number\verb+_+pad\/} +is off, +`{\tt 5}' when +{\it number\verb+_+pad\/} +is set to 1~or~3, +otherwise `{\tt M-5}' when it is set to 2~or~4. +%.lp +\item[\tb{\#rush}] +Prefix key to rush towards a direction. +Default key is `{\tt g}' when +{\it number\verb+_+pad\/} +is off, +`{\tt M-5}' when +{\it number\verb+_+pad\/} +is set to 1~or~3, +otherwise `{\tt 5}' when it is set to 2~or~4. +%.lp \item[\tb{\#save}] Save the game and exit the program. Default key is `{\tt S}'. @@ -5265,13 +5296,6 @@ can only be bound to a single key. Prefix key to start a count, to repeat a command this many times. With {\it number\verb+_+pad\/} only. Default is~`{\tt n}'. %.lp -\item[{\bb{fight}}] -Prefix key to force fight a direction. Default is~`{\tt F}'. -%.lp -\item[{\bb{fight.numpad}}] -Prefix key to force fight a direction. With {\it number\verb+_+pad\/} only. -Default is~`{\tt -}'. -%.lp \item[{\bb{getdir.help}}] When asked for a direction, the key to show the help. Default is~`{\tt ?}'. %.lp @@ -5375,47 +5399,8 @@ Default is~`{\tt z}'. When asked for a location, the key to go to previous closest valid location. Default is~`{\tt Z}'. %.lp -\item[{\bb{nopickup}}] -Prefix key to move without picking up items. Default is~`{\tt m}'. -%.lp -\item[{\bb{redraw}}] -Key to redraw the screen. Default is~`{\tt \^{}R}'. -%.lp -\item[{\bb{redraw.numpad}}] -Key to redraw the screen. With {\it number\verb+_+pad\/} only. -Default is~`{\tt \^{}L}'. -%.lp \item[{\bb{repeat}}] Key to repeat previous command. Default is~`{\tt \^{}A}'. -%.lp -\item[{\bb{reqmenu}}] -Prefix key to request menu from some commands. Default is~`{\tt m}'. -%.lp -\item[{\bb{run}}] -Prefix key to run towards a direction. Default is~`{\tt G}'. -%.lp -\item[{\bb{run.nopickup}}] -Prefix key to run towards a direction without picking up items on the way. -Default is~`{\tt M}'. -%.lp -\item[{\bb{run.numpad}}] -Prefix key to run towards a direction. -With {\it number\verb+_+pad\/} only. - -%.lp "" -Default is `{\tt 5}' when number_pad is set to 1~or~3, -otherwise `{\tt M-5}' when it is set to 2~or~4. -%.lp -\item[{\bb{rush}}] -Prefix key to rush towards a direction. Default is~`{\tt g}'. -%.lp -\item[{\bb{rush.numpad}}] -Prefix key to rush towards a direction. -With {\it number\verb+_+pad\/} only. - -.lp "" -Default is `{\tt M-5}' when number_pad is set to 1~or~3, -otherwise `{\tt 5}' when it is set to 2~or~4. \elist diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 852e277be..03e2e3212 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -747,6 +747,7 @@ when two or more shops share a wall and hero uses Passes_walls to carry an unpaid item from the first shop wasn't noticed redo the unpaid_cost fix to handle shop items inside hero-owned container flyers shouldn't fall on arrival when going down holes or trap doors +change movement keys and some special keys into extended commands Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/decl.h b/include/decl.h index 392c64fef..36aa590e9 100644 --- a/include/decl.h +++ b/include/decl.h @@ -445,20 +445,6 @@ enum nh_keyfunc { NHKF_ESC = 0, NHKF_DOAGAIN, - NHKF_REQMENU, - - /* run ... clicklook need to be in a continuous block */ - NHKF_RUN, /* 'G' */ - NHKF_RUN2, /* '5' or M-5 */ - NHKF_RUSH, /* 'g' */ - NHKF_RUSH2, /* M-5 or '5' */ - NHKF_FIGHT, /* 'F' */ - NHKF_FIGHT2, /* '-' */ - NHKF_NOPICKUP, /* 'm' */ - NHKF_RUN_NOPICKUP, /* 'M' */ - - NHKF_REDRAW, - NHKF_REDRAW2, NHKF_GETDIR_SELF, NHKF_GETDIR_SELF2, NHKF_GETDIR_HELP, @@ -503,9 +489,6 @@ struct cmd { boolean pcHack_compat; /* for numpad: affects 5, M-5, and M-0 */ boolean phone_layout; /* inverted keypad: 1,2,3 above, 7,8,9 below */ boolean swap_yz; /* QWERTZ keyboards; use z to move NW, y to zap */ - char move[N_DIRS]; /* char used for moving one step in direction */ - char rush[N_DIRS]; - char run[N_DIRS]; const char *dirchars; /* current movement/direction characters */ const char *alphadirchars; /* same as dirchars if !numpad */ const struct ext_func_tab *commands[256]; /* indexed by input character */ diff --git a/include/extern.h b/include/extern.h index f890f7d84..9bcc56ae9 100644 --- a/include/extern.h +++ b/include/extern.h @@ -199,12 +199,41 @@ extern boolean status_hilite_menu(void); /* ### cmd.c ### */ +extern int do_move_west(void); +extern int do_move_northwest(void); +extern int do_move_north(void); +extern int do_move_northeast(void); +extern int do_move_east(void); +extern int do_move_southeast(void); +extern int do_move_south(void); +extern int do_move_southwest(void); +extern int do_rush_west(void); +extern int do_rush_northwest(void); +extern int do_rush_north(void); +extern int do_rush_northeast(void); +extern int do_rush_east(void); +extern int do_rush_southeast(void); +extern int do_rush_south(void); +extern int do_rush_southwest(void); +extern int do_run_west(void); +extern int do_run_northwest(void); +extern int do_run_north(void); +extern int do_run_northeast(void); +extern int do_run_east(void); +extern int do_run_southeast(void); +extern int do_run_south(void); +extern int do_run_southwest(void); +extern int do_reqmenu(void); +extern int do_rush(void); +extern int do_run(void); +extern int do_fight(void); extern char randomkey(void); extern void random_response(char *, int); extern int rnd_extcmd_idx(void); extern int domonability(void); extern const struct ext_func_tab *ext_func_tab_from_func(int(*)(void)); extern char cmd_from_func(int(*)(void)); +extern char cmd_from_dir(int, int); extern const char *cmdname_from_func(int(*)(void), char *, boolean); extern boolean redraw_cmd(char); extern const char *levltyp_to_name(int); diff --git a/include/func_tab.h b/include/func_tab.h index ca2c07c3d..da2b3cca9 100644 --- a/include/func_tab.h +++ b/include/func_tab.h @@ -15,6 +15,8 @@ #define NOFUZZERCMD 0x20 /* fuzzer cannot execute this command */ #define INTERNALCMD 0x40 /* only for internal use, not for user */ #define CMD_M_PREFIX 0x80 /* accepts menu prefix */ +#define PREFIXCMD 0x100 /* prefix command, requires another one after it */ +#define MOVEMENTCMD 0x200 /* used to move hero/cursor */ struct ext_func_tab { uchar key; diff --git a/src/cmd.c b/src/cmd.c index 4fbb6b2a6..703af9bc7 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -106,6 +106,7 @@ static int dotravel(void); 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); @@ -156,11 +157,10 @@ static char *parse(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); @@ -389,7 +389,7 @@ doextcmd(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; } @@ -416,7 +416,7 @@ doc_extcmd_flagstr(winid menuwin, 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; @@ -1845,6 +1845,228 @@ doterrain(void) 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 @@ -1893,6 +2115,8 @@ struct ext_func_tab extcmdlist[] = { 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", @@ -1975,12 +2199,18 @@ struct ext_func_tab extcmdlist[] = { 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", @@ -2116,66 +2346,98 @@ struct ext_func_tab extcmdlist[] = { 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 @@ -2188,17 +2450,7 @@ key2extcmddesc(uchar key) 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"); @@ -2261,6 +2513,24 @@ bind_key(uchar key, const char *command) 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) @@ -2271,24 +2541,23 @@ 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"); @@ -2381,11 +2650,6 @@ dokeylist(void) (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 @@ -2404,10 +2668,9 @@ dokeylist(void) 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; } @@ -2455,7 +2718,7 @@ dokeylist(void) 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); } @@ -2479,7 +2742,7 @@ dokeylist(void) 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 */ @@ -2490,24 +2753,23 @@ dokeylist(void) } } +#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); } @@ -2521,6 +2783,7 @@ dokeylist(void) display_nhwindow(datawin, FALSE); destroy_nhwindow(datawin); +#undef IGNORECMD } const struct ext_func_tab * @@ -2535,6 +2798,13 @@ ext_func_tab_from_func(int (*fn)(void)) 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)) { @@ -3036,17 +3306,6 @@ static struct { } 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" }, @@ -3182,11 +3441,13 @@ reset_commands(boolean initial) 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; @@ -3197,8 +3458,10 @@ reset_commands(boolean initial) 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]; + } } } @@ -3235,10 +3498,6 @@ reset_commands(boolean initial) 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; @@ -3263,6 +3522,7 @@ reset_commands(boolean initial) } } /*?initial*/ + /* choose updated movement keys */ if (updated) g.Cmd.serialno++; g.Cmd.dirchars = !g.Cmd.num_pad @@ -3270,31 +3530,39 @@ reset_commands(boolean initial) : (!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) { @@ -3340,10 +3608,9 @@ randomkey(void) 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: @@ -3384,17 +3651,6 @@ rnd_extcmd_idx(void) 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) { @@ -3405,6 +3661,9 @@ 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(); @@ -3425,11 +3684,12 @@ rhack(char *cmd) 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 */ @@ -3439,151 +3699,21 @@ rhack(char *cmd) 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]) { - /* */ - /* 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); @@ -3598,6 +3728,11 @@ rhack(char *cmd) 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() */ @@ -3605,13 +3740,50 @@ rhack(char *cmd) 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; } @@ -3667,26 +3839,22 @@ movecmd(char sym, int mode) { 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]; @@ -3710,22 +3878,8 @@ dxdy_moveok(void) 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); } /* @@ -3822,26 +3976,36 @@ show_direction_keys(winid win, /* should specify a window which is 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); }; } @@ -3871,37 +4035,7 @@ help_dir(char sym, */ dothat = "do that"; how = " at"; /* for " 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'; @@ -3973,7 +4107,7 @@ help_dir(char sym, 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; @@ -4359,7 +4493,7 @@ click_to_cmd(int x, int y, int mod) 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)) { @@ -4403,9 +4537,9 @@ click_to_cmd(int x, int y, int mod) /* 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; @@ -4511,32 +4645,8 @@ parse(void) 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; diff --git a/src/dig.c b/src/dig.c index dcd4e3f79..e6a12c902 100644 --- a/src/dig.c +++ b/src/dig.c @@ -987,13 +987,8 @@ use_pick_axe(struct obj *obj) downok = !!can_reach_floor(FALSE); dsp = dirsyms; for (dir = 0; dir < N_DIRS_Z; dir++) { - char dirch; - if (dir == DIR_DOWN) - dirch = cmd_from_func(dodown); - else if (dir == DIR_UP) - dirch = cmd_from_func(doup); - else - dirch = g.Cmd.move[dir]; + char dirch = cmd_from_dir(dir, MV_WALK); + /* filter out useless directions */ if (u.uswallow) { ; /* all directions are viable when swallowed */ diff --git a/src/do.c b/src/do.c index 3f9bf05ef..d3a472b05 100644 --- a/src/do.c +++ b/src/do.c @@ -1120,6 +1120,8 @@ dodown(void) if (trap && Is_stronghold(&u.uz)) { goto_hell(FALSE, TRUE); } else { + if (!trap) + u.dz = 1; g.at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER); next_level(!trap); g.at_ladder = FALSE; @@ -1173,6 +1175,7 @@ doup(void) return ECMD_OK; } g.at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER); + u.dz = -1; prev_level(TRUE); g.at_ladder = FALSE; return ECMD_TIME; @@ -2046,7 +2049,7 @@ cmd_safety_prevention(const char *cmddesc, const char *act, int *flagcounter) buf[0] = '\0'; if (iflags.cmdassist || !(*flagcounter)++) Sprintf(buf, " Use '%s' prefix to force %s.", - visctrl(g.Cmd.spkeys[NHKF_REQMENU]), cmddesc); + visctrl(cmd_from_func(do_reqmenu)), cmddesc); Norep("%s%s", act, buf); return TRUE; } diff --git a/src/do_name.c b/src/do_name.c index 64f4ebcc1..84a96eb89 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -108,22 +108,25 @@ getpos_help(boolean force, const char *goal) char sbuf[BUFSZ]; boolean doing_what_is; winid tmpwin = create_nhwindow(NHW_MENU); - int runkey = iflags.num_pad ? NHKF_RUN2 : NHKF_RUN; - int rushkey = iflags.num_pad ? NHKF_RUSH2 : NHKF_RUSH; Sprintf(sbuf, "Use '%s', '%s', '%s', '%s' to move the cursor to %s.", /* hjkl */ - visctrl(g.Cmd.move[DIR_W]), visctrl(g.Cmd.move[DIR_S]), - visctrl(g.Cmd.move[DIR_N]), visctrl(g.Cmd.move[DIR_E]), goal); + visctrl(cmd_from_func(do_move_west)), + visctrl(cmd_from_func(do_move_south)), + visctrl(cmd_from_func(do_move_north)), + visctrl(cmd_from_func(do_move_east)), goal); putstr(tmpwin, 0, sbuf); Sprintf(sbuf, "Use '%s', '%s', '%s', '%s' to fast-move the cursor, %s.", - visctrl(g.Cmd.run[DIR_W]), visctrl(g.Cmd.run[DIR_S]), - visctrl(g.Cmd.run[DIR_N]), visctrl(g.Cmd.run[DIR_E]), + visctrl(cmd_from_func(do_run_west)), + visctrl(cmd_from_func(do_run_south)), + visctrl(cmd_from_func(do_run_north)), + visctrl(cmd_from_func(do_run_east)), fastmovemode[iflags.getloc_moveskip]); putstr(tmpwin, 0, sbuf); Sprintf(sbuf, "(or prefix normal move with '%s' or '%s' to fast-move)", - visctrl(g.Cmd.spkeys[runkey]), visctrl(g.Cmd.spkeys[rushkey])); + visctrl(cmd_from_func(do_run)), + visctrl(cmd_from_func(do_rush))); putstr(tmpwin, 0, sbuf); putstr(tmpwin, 0, "Or enter a background symbol (ex. '<')."); Sprintf(sbuf, "Use '%s' to move the cursor on yourself.", @@ -698,8 +701,6 @@ getpos(coord *ccp, boolean force, const char *goal) schar udx = u.dx, udy = u.dy, udz = u.dz; int dx, dy; boolean rushrun = FALSE; - int runkey = iflags.num_pad ? NHKF_RUN2 : NHKF_RUN; - int rushkey = iflags.num_pad ? NHKF_RUSH2 : NHKF_RUSH; for (i = 0; i < SIZE(pick_chars_def); i++) pick_chars[i] = g.Cmd.spkeys[pick_chars_def[i].nhkf]; @@ -757,7 +758,7 @@ getpos(coord *ccp, boolean force, const char *goal) result = -1; break; } - if (c == g.Cmd.spkeys[runkey] || c == g.Cmd.spkeys[rushkey]) { + if (c == cmd_from_func(do_run) || c == cmd_from_func(do_rush)) { c = readchar_poskey(&tx, &ty, &sidx); rushrun = TRUE; } @@ -974,9 +975,11 @@ getpos(coord *ccp, boolean force, const char *goal) if (!force) Strcpy(note, "aborted"); else /* hjkl */ - Sprintf(note, "use '%c', '%c', '%c', '%c' or '%s'", - g.Cmd.move[DIR_W], g.Cmd.move[DIR_S], - g.Cmd.move[DIR_N], g.Cmd.move[DIR_E], + Sprintf(note, "use '%s', '%s', '%s', '%s' or '%s'", + visctrl(cmd_from_func(do_move_west)), + visctrl(cmd_from_func(do_move_south)), + visctrl(cmd_from_func(do_move_north)), + visctrl(cmd_from_func(do_move_east)), visctrl(g.Cmd.spkeys[NHKF_GETPOS_PICK])); pline("Unknown direction: '%s' (%s).", visctrl((char) c), note);