fix #H5462 - failed F-attack gives misleading msg

Report was for 'F' followed by '.' reporting "cmdassist: Invalid
direction key!" and then by a direction grid (which happened to
include '.' for self).  That behavior applied for all the movement
prefix keys ('m', 'G', &c).  When 'cmdassist' was off, "F." would
yield "Unknown command 'F.'." instead.

Now you'll get "You can't fight yourself.", either instead of the
"invalid direction key" part of cmdassist feedback (followed by a
direction grid which excludes up, down, and self since they aren't
applicable for prefix keys) or of the "unknown command" result.
Likewise, "You can't run upward." or "You can't rush downward."
for "G<" and "g>", respectively.
This commit is contained in:
PatR
2017-05-16 16:22:43 -07:00
parent 4ed0e5fd6d
commit 9b3587204a
2 changed files with 141 additions and 43 deletions

View File

@@ -380,6 +380,8 @@ levitation vs encumbrance message sequencing issues: putting on boots of
of encumbrance until player took another action
removing a blindfold with 'A' took two turns, with 'R' (and 'T') only one,
and could result in a panic if the blindfold was stolen during removal
cmdassist help for movement prefix followed by invalid direction was strange
when the direction was up, down, or self disallowed for that prefix
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository

182
src/cmd.c
View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 cmd.c $NHDT-Date: 1494034344 2017/05/06 01:32:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.256 $ */
/* NetHack 3.6 cmd.c $NHDT-Date: 1494976933 2017/05/16 23:22:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.257 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -184,8 +184,8 @@ static const char *readchar_queue = "";
static coord clicklook_cc;
STATIC_DCL char *NDECL(parse);
STATIC_DCL void FDECL(show_direction_keys, (winid, BOOLEAN_P));
STATIC_DCL boolean FDECL(help_dir, (CHAR_P, const char *));
STATIC_DCL void FDECL(show_direction_keys, (winid, CHAR_P, BOOLEAN_P));
STATIC_DCL boolean FDECL(help_dir, (CHAR_P, int, const char *));
STATIC_PTR int
doprev_message(VOID_ARGS)
@@ -3073,7 +3073,11 @@ dokeylist(VOID_ARGS)
boolean keys_used[256] = {0};
winid datawin;
int i;
const struct {
static const char
run_desc[] = "Prefix: run until something very interesting is seen",
forcefight_desc[] =
"Prefix: force fight even if you don't see a monster";
static const struct {
int nhkf;
const char *desc;
boolean numpad;
@@ -3081,22 +3085,18 @@ dokeylist(VOID_ARGS)
{ NHKF_ESC, "escape from the current query/action", FALSE },
{ NHKF_RUSH,
"Prefix: rush until something interesting is seen", FALSE },
{ NHKF_RUN,
"Prefix: run until something extremely interesting is seen", FALSE },
{ NHKF_RUN2,
"Prefix: run until something extremely interesting is seen", TRUE },
{ NHKF_FIGHT,
"Prefix: force fight even if you don't see a monster", FALSE },
{ NHKF_FIGHT2,
"Prefix: force fight even if you don't see a monster", 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/fighting", FALSE },
{ NHKF_RUN_NOPICKUP,
"Prefix: run without picking up objects/fighting", FALSE },
{ NHKF_DOINV, "inventory (same as #inventory)", TRUE },
{ NHKF_DOINV, "view inventory", TRUE },
{ NHKF_REQMENU, "Prefix: request a menu", FALSE },
#ifdef REDO
{ NHKF_DOAGAIN , "redo the previous command", FALSE },
{ NHKF_DOAGAIN , "re-do: perform the previous command again", FALSE },
#endif
{ 0, (const char *) 0, FALSE }
};
@@ -3108,7 +3108,7 @@ dokeylist(VOID_ARGS)
/* directional keys */
putstr(datawin, 0, "");
putstr(datawin, 0, "Directional keys:");
show_direction_keys(datawin, FALSE);
show_direction_keys(datawin, '.', FALSE); /* '.'==self in direction grid */
keys_used[(uchar) Cmd.move_NW] = keys_used[(uchar) Cmd.move_N]
= keys_used[(uchar) Cmd.move_NE] = keys_used[(uchar) Cmd.move_W]
@@ -3942,11 +3942,12 @@ int NDECL((*cmd_func));
}
int
ch2spkeys(c, start,end)
ch2spkeys(c, start, end)
char c;
int start,end;
{
int i;
for (i = start; i <= end; i++)
if (Cmd.spkeys[i] == c)
return i;
@@ -3957,6 +3958,7 @@ void
rhack(cmd)
register char *cmd;
{
int spkey;
boolean do_walk, do_rush, prefix_seen, bad_command,
firsttime = (cmd == 0);
@@ -3990,7 +3992,9 @@ register char *cmd;
/* handle most movement commands */
do_walk = do_rush = prefix_seen = FALSE;
context.travel = context.travel1 = 0;
switch (ch2spkeys(*cmd, NHKF_RUN,NHKF_CLICKLOOK)) {
spkey = ch2spkeys(*cmd, NHKF_RUN, NHKF_CLICKLOOK);
switch (spkey) {
case NHKF_RUSH:
if (movecmd(cmd[1])) {
context.run = 2;
@@ -4161,14 +4165,13 @@ register char *cmd;
if (bad_command) {
char expcmd[20]; /* we expect 'cmd' to point to 1 or 2 chars */
register char c;
char c, c1 = cmd[1];
expcmd[0] = '\0';
while ((c = *cmd++) != '\0')
Strcat(expcmd, visctrl(c)); /* add 1..4 chars plus terminator */
if (!prefix_seen || !iflags.cmdassist
|| !help_dir(0, "Invalid direction key!"))
if (!prefix_seen || !help_dir(c1, spkey, "Invalid direction key!"))
Norep("Unknown command '%s'.", expcmd);
}
/* didn't move */
@@ -4319,7 +4322,8 @@ retry:
if (!index(quitchars, dirsym)) {
help_requested = (dirsym == Cmd.spkeys[NHKF_GETDIR_HELP]);
if (help_requested || iflags.cmdassist) {
did_help = help_dir((s && *s == '^') ? dirsym : 0,
did_help = help_dir((s && *s == '^') ? dirsym : '\0',
NHKF_ESC,
help_requested ? (const char *) 0
: "Invalid direction key!");
if (help_requested)
@@ -4339,61 +4343,141 @@ retry:
}
STATIC_OVL void
show_direction_keys(win, nodiag)
winid win;
show_direction_keys(win, centerchar, nodiag)
winid win; /* should specify a window which is using a fixed-width font... */
char centerchar; /* '.' or '@' or ' ' */
boolean nodiag;
{
char buf[BUFSZ];
if (!centerchar)
centerchar = ' ';
if (nodiag) {
Sprintf(buf, " %c ", Cmd.move_N);
putstr(win, 0, buf);
putstr(win, 0, " | ");
Sprintf(buf, " %c- . -%c", Cmd.move_W, Cmd.move_E);
Sprintf(buf, " %c- %c -%c",
Cmd.move_W, centerchar, Cmd.move_E);
putstr(win, 0, buf);
putstr(win, 0, " | ");
Sprintf(buf, " %c ", Cmd.move_S);
putstr(win, 0, buf);
} else {
Sprintf(buf, " %c %c %c", Cmd.move_NW, Cmd.move_N,
Cmd.move_NE);
Sprintf(buf, " %c %c %c",
Cmd.move_NW, Cmd.move_N, Cmd.move_NE);
putstr(win, 0, buf);
putstr(win, 0, " \\ | / ");
Sprintf(buf, " %c- . -%c", Cmd.move_W, Cmd.move_E);
Sprintf(buf, " %c- %c -%c",
Cmd.move_W, centerchar, Cmd.move_E);
putstr(win, 0, buf);
putstr(win, 0, " / | \\ ");
Sprintf(buf, " %c %c %c", Cmd.move_SW, Cmd.move_S,
Cmd.move_SE);
Sprintf(buf, " %c %c %c",
Cmd.move_SW, Cmd.move_S, Cmd.move_SE);
putstr(win, 0, buf);
};
}
/* explain choices if player has asked for getdir() help or has given
an invalid direction after a prefix key ('F', 'g', 'm', &c), which
might be bogus but could be up, down, or self when not applicable */
STATIC_OVL boolean
help_dir(sym, msg)
help_dir(sym, spkey, msg)
char sym;
int spkey; /* NHKF_ code for prefix key, if one was used, or for ESC */
const char *msg;
{
static const char wiz_only_list[] = "EFGIVW";
char ctrl;
winid win;
char buf[BUFSZ], buf2[BUFSZ], *explain;
const char *dothat, *how;
boolean prefixhandling, viawindow;
/* NHKF_ESC indicates that player asked for help at getdir prompt */
viawindow = (spkey == NHKF_ESC || iflags.cmdassist);
prefixhandling = (spkey != NHKF_ESC);
/*
* Handling for prefix keys that don't want special directions.
* Delivered via pline if 'cmdassist' is off, or instead of the
* general message if it's on.
*/
dothat = "do that";
how = " at"; /* for "<action> at yourself"; not used for up/down */
switch (spkey) {
case NHKF_NOPICKUP:
dothat = "move";
break;
case NHKF_RUSH:
dothat = "rush";
break;
case NHKF_RUN2:
if (!Cmd.num_pad)
break; /* else FALLTHRU */
case NHKF_RUN:
case NHKF_RUN_NOPICKUP:
dothat = "run";
break;
case NHKF_FIGHT2:
if (!Cmd.num_pad)
break; /* else FALLTHRU */
case NHKF_FIGHT:
dothat = "fight";
how = ""; /* avoid "fight at yourself" */
break;
default:
prefixhandling = FALSE;
break;
}
buf[0] = '\0';
/* for movement prefix followed by '.' or (numpad && 's') to mean 'self';
note: '-' for hands (inventory form of 'self') is not handled here */
if (prefixhandling
&& (sym == Cmd.spkeys[NHKF_GETDIR_SELF]
|| (Cmd.num_pad && sym == Cmd.spkeys[NHKF_GETDIR_SELF2]))) {
Sprintf(buf, "You can't %s%s yourself.", dothat, how);
/* for movement prefix followed by up or down */
} else if (prefixhandling && (sym == '<' || sym == '>')) {
Sprintf(buf, "You can't %s %s.", dothat,
/* was "upwards" and "downwards", but they're considered
to be variants of canonical "upward" and "downward" */
(sym == '<') ? "upward" : "downward");
}
/* if 'cmdassist', display via pline() and we're done (note: asking
for help at getdir() prompt forces cmdassist for this operation) */
if (!viawindow) {
if (*buf) {
pline("%s", buf);
return TRUE;
}
/* when 'cmdassist' is off and caller doesn't insist, do nothing */
return FALSE;
}
win = create_nhwindow(NHW_TEXT);
if (!win)
return FALSE;
if (msg) {
if (*buf) {
/* show bad-prefix message instead of general invalid-direction one */
putstr(win, 0, buf);
putstr(win, 0, "");
} else if (msg) {
Sprintf(buf, "cmdassist: %s", msg);
putstr(win, 0, buf);
putstr(win, 0, "");
}
if (letter(sym) || sym == '[') { /* 'dat/cmdhelp' shows ESC as ^[ */
if (!prefixhandling && (letter(sym) || sym == '[')) {
/* '[': old 'cmdhelp' showed ESC as ^[ */
sym = highc(sym); /* @A-Z[ (note: letter() accepts '@') */
ctrl = (sym - 'A') + 1; /* 0-27 (note: 28-31 aren't applicable) */
if ((explain = dowhatdoes_core(ctrl, buf2)) != 0
&& (!index(wiz_only_list, sym) || wizard)) {
Sprintf(buf, "Are you trying to use ^%c%s?", sym,
index(wiz_only_list, sym)
? ""
index(wiz_only_list, sym) ? ""
: " as specified in the Guidebook");
putstr(win, 0, buf);
putstr(win, 0, "");
@@ -4407,17 +4491,29 @@ const char *msg;
}
}
Sprintf(buf, "Valid direction keys %sare:",
NODIAG(u.umonnum) ? "in your current form " : "");
Sprintf(buf, "Valid direction keys%s%s%s are:",
prefixhandling ? " to " : "", prefixhandling ? dothat : "",
NODIAG(u.umonnum) ? " in your current form" : "");
putstr(win, 0, buf);
show_direction_keys(win, NODIAG(u.umonnum));
show_direction_keys(win, !prefixhandling ? '.' : ' ', NODIAG(u.umonnum));
if (!prefixhandling || spkey == NHKF_NOPICKUP) {
/* 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;
self is excluded as a viable direction for every prefix */
putstr(win, 0, "");
putstr(win, 0, " < up");
putstr(win, 0, " > down");
if (!prefixhandling) {
int selfi = Cmd.num_pad ? NHKF_GETDIR_SELF2 : NHKF_GETDIR_SELF;
Sprintf(buf, " %4s direct at yourself",
visctrl(Cmd.spkeys[selfi]));
putstr(win, 0, buf);
}
}
putstr(win, 0, "");
putstr(win, 0, " < up");
putstr(win, 0, " > down");
Sprintf(buf, " %4s direct at yourself",
visctrl(Cmd.spkeys[NHKF_GETDIR_SELF]));
putstr(win, 0, buf);
if (msg) {
/* non-null msg means that this wasn't an explicit user request */
putstr(win, 0, "");