]> granicus.if.org Git - nethack/commitdiff
Movement key reworking
authorPasi Kallinen <paxed@alt.org>
Sat, 3 Jul 2021 12:19:53 +0000 (15:19 +0300)
committerPasi Kallinen <paxed@alt.org>
Sat, 3 Jul 2021 15:20:24 +0000 (18:20 +0300)
Put the rush and run movement keys into g.Cmd instead of bit twiddling
the normal walk keys in multiple places to get the run and rush keys.

Allow meta keys in getpos. Use the normal running keys to fast-move
in getpos, instead of explicit HJKL - I polled couple places online,
and number_pad users did not use the HJKL keys in getpos.

Make meta keys work even after a prefix key.

doc/fixes37.0
include/decl.h
include/extern.h
src/cmd.c
src/dig.c
src/do_name.c

index ebaa48d672e9ad3cce297ad23b8654fab1b8cc40..09ac5687f909b18251fe9cfcc74024881cd814ce 100644 (file)
@@ -553,6 +553,8 @@ shopkeepers can remove pits and webs
 perm_invent: when buying shop goods using itemized purchasing while persistent
        inventory window was enabled, the prices of unpaid items went away as
        soon as any item was bought (actual item-by-item purchase worked ok)
+change getloc fastmove keys in number_pad mode from hardcoded HJKL to the
+       run/rush movement keys (meta+number)
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 446d4937b88847f4963907e99f87e89cc1355823..ab803d0a977ff3d06e577503ed31658072a6aba9 100644 (file)
@@ -173,6 +173,15 @@ struct kinfo {
     char name[BUFSZ]; /* actual killer name */
 };
 
+enum movemodes {
+    MV_ANY = -1,
+    MV_WALK,
+    MV_RUN,
+    MV_RUSH,
+
+    N_MOVEMODES
+};
+
 enum movementdirs {
     DIR_ERR = -1,
     DIR_W,
@@ -500,6 +509,8 @@ struct cmd {
     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 */
index 15480b6d445732bc4446fb86732cff076600aa0d..3f0db893e453785517488e71d952b5cd18be577d 100644 (file)
@@ -225,7 +225,7 @@ extern boolean bind_key(uchar, const char *);
 extern void dokeylist(void);
 extern int xytod(schar, schar);
 extern void dtoxy(coord *, int);
-extern int movecmd(char);
+extern int movecmd(char, int);
 extern int dxdy_moveok(void);
 extern int getdir(const char *);
 extern void confdir(void);
@@ -239,6 +239,7 @@ extern void hangup(int);
 extern void end_of_input(void);
 #endif
 extern char readchar(void);
+extern char readchar_poskey(int *, int *, int *);
 extern void sanity_check(void);
 extern char* key2txt(uchar, char *);
 extern char yn_function(const char *, const char *, char);
index 5b5cd9d4592ef8acb8d434d1a6e22490d6102baa..998495179578c5e8fa42f5210c2d0174cd4a48c7 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -6,10 +6,6 @@
 #include "hack.h"
 #include "func_tab.h"
 
-#ifdef ALTMETA
-static boolean alt_esc = FALSE;
-#endif
-
 #ifdef UNIX
 /*
  * Some systems may have getchar() return EOF for various reasons, and
@@ -154,6 +150,7 @@ static boolean accept_menu_prefix(int (*)(void));
 static void add_herecmd_menuitem(winid, int (*)(void), const char *);
 static char here_cmd_menu(boolean);
 static char there_cmd_menu(boolean, int, int);
+static char readchar_core(int *, int *, int *);
 static char *parse(void);
 static void show_direction_keys(winid, char, boolean);
 static boolean help_dir(char, int, const char *);
@@ -2194,11 +2191,11 @@ key2extcmddesc(uchar key)
        commands table because it contains entries for number_pad commands
        that match !number_pad movement (like 'j' for "jump") */
     key2cmdbuf[0] = '\0';
-    if (movecmd(k = key))
+    if (movecmd(k = key, MV_WALK))
         Strcpy(key2cmdbuf, "move"); /* "move or attack"? */
-    else if (movecmd(k = unctrl(key)))
+    else if (movecmd(k = key, MV_RUSH))
         Strcpy(key2cmdbuf, "rush");
-    else if (movecmd(k = (g.Cmd.num_pad ? unmeta(key) : lowc(key))))
+    else if (movecmd(k = key, MV_RUN))
         Strcpy(key2cmdbuf, "run");
     if (*key2cmdbuf) {
         for (mov = &movtab[0]; mov->k1; ++mov) {
@@ -2391,19 +2388,10 @@ 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++)
+    for (i = 0; i < N_DIRS; i++) {
         keys_used[(uchar) g.Cmd.move[i]] = TRUE;
-    if (!iflags.num_pad) {
-        for (i = 0; i < N_DIRS; i++) {
-            keys_used[(uchar) highc(g.Cmd.move[i])] = TRUE;
-            keys_used[(uchar) C(g.Cmd.move[i])] = TRUE;
-        }
-    } else {
-        /* num_pad */
-        keys_used[(uchar) M('1')] = keys_used[(uchar) M('2')]
-            = keys_used[(uchar) M('3')] = keys_used[(uchar) M('4')]
-            = keys_used[(uchar) M('6')] = keys_used[(uchar) M('7')]
-            = keys_used[(uchar) M('8')] = keys_used[(uchar) M('9')] = 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;
@@ -3274,8 +3262,16 @@ 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++)
+    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]);
+        }
+    }
 
     if (!initial) {
         for (i = 0; i < N_DIRS; i++) {
@@ -3353,9 +3349,13 @@ randomkey(void)
     case 10:
     case 11:
     case 12:
-        c = g.Cmd.dirchars[rn2(N_DIRS)];
-        if (!rn2(7))
-            c = !g.Cmd.num_pad ? (!rn2(3) ? C(c) : (c + 'A' - 'a')) : M(c);
+        {
+            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];
+        }
         break;
     case 13:
         c = (char) rn1('9' - '0' + 1, '0');
@@ -3469,7 +3469,7 @@ rhack(char *cmd)
             break;
         /*FALLTHRU*/
     case NHKF_RUSH:
-        if (movecmd(cmd[1])) {
+        if (movecmd(cmd[1], MV_ANY)) {
             g.context.run = 2;
             g.domove_attempting |= DOMOVE_RUSH;
         } else
@@ -3480,7 +3480,7 @@ rhack(char *cmd)
             break;
         /*FALLTHRU*/
     case NHKF_RUN:
-        if (movecmd(lowc(cmd[1]))) {
+        if (movecmd(cmd[1], MV_ANY)) {
             g.context.run = 3;
             g.domove_attempting |= DOMOVE_RUSH;
         } else
@@ -3496,14 +3496,14 @@ rhack(char *cmd)
      * normal movement: attack if 'I', move otherwise.
      */
     case NHKF_FIGHT:
-        if (movecmd(cmd[1])) {
+        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]) || u.dz) {
+        if (movecmd(cmd[1], MV_ANY) || u.dz) {
             g.context.run = 0;
             g.context.nopick = 1;
             if (!u.dz)
@@ -3514,7 +3514,7 @@ rhack(char *cmd)
             prefix_seen = TRUE;
         break;
     case NHKF_RUN_NOPICKUP:
-        if (movecmd(lowc(cmd[1]))) {
+        if (movecmd(cmd[1], MV_ANY)) {
             g.context.run = 1;
             g.context.nopick = 1;
             g.domove_attempting |= DOMOVE_RUSH;
@@ -3542,13 +3542,13 @@ rhack(char *cmd)
         g.domove_attempting |= DOMOVE_RUSH;
         break;
     default:
-        if (movecmd(*cmd)) { /* ordinary movement */
+        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(g.Cmd.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
+        } else if (movecmd(*cmd, MV_RUN)) {
             g.context.run = 1;
             g.domove_attempting |= DOMOVE_RUSH;
-        } else if (movecmd(unctrl(*cmd))) {
+        } else if (movecmd(*cmd, MV_RUSH)) {
             g.context.run = 3;
             g.domove_attempting |= DOMOVE_RUSH;
         }
@@ -3693,26 +3693,41 @@ dtoxy(coord *cc, int dd)
 
 /* also sets u.dz, but returns false for <> */
 int
-movecmd(char sym)
+movecmd(char sym, int mode)
 {
-    register const char *dp = index(g.Cmd.dirchars, sym);
-
-    u.dz = 0;
-    if (!dp || !*dp)
-        return 0;
-    u.dx = xdir[dp - g.Cmd.dirchars];
-    u.dy = ydir[dp - g.Cmd.dirchars];
-    u.dz = zdir[dp - g.Cmd.dirchars];
-#if 0 /* now handled elsewhere */
-    if (u.dx && u.dy && NODIAG(u.umonnum)) {
-        u.dx = u.dy = 0;
-        return 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 = 0; d < N_DIRS; d++) {
+            if (mode == MV_ANY) {
+                if (sym == g.Cmd.move[d]
+                    || sym == g.Cmd.rush[d]
+                    || sym == g.Cmd.run[d])
+                    break;
+            } else if (sym == mvkeys[d])
+                break;
+        }
     }
-#endif
-    return !u.dz;
+    if (d != DIR_ERR) {
+        u.dx = xdir[d];
+        u.dy = ydir[d];
+        u.dz = zdir[d];
+        return !u.dz;
+    }
+    u.dz = 0;
+    return 0;
 }
 
-/* grid bug handling which used to be in movecmd() */
+/* grid bug handling */
 int
 dxdy_moveok(void)
 {
@@ -3799,7 +3814,7 @@ getdir(const char *s)
     if (dirsym == g.Cmd.spkeys[NHKF_GETDIR_SELF]
         || dirsym == g.Cmd.spkeys[NHKF_GETDIR_SELF2]) {
         u.dx = u.dy = u.dz = 0;
-    } else if (!(is_mov = movecmd(dirsym)) && !u.dz) {
+    } else if (!(is_mov = movecmd(dirsym, MV_ANY)) && !u.dz) {
         boolean did_help = FALSE, help_requested;
 
         if (!index(quitchars, dirsym)) {
@@ -4297,7 +4312,7 @@ here_cmd_menu(boolean doit)
 }
 
 /*
- * convert a MAP window position into a movecmd
+ * convert a MAP window position into a movement key usable with movecmd()
  */
 const char *
 click_to_cmd(int x, int y, int mod)
@@ -4374,7 +4389,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.dirchars[dir];
+            cmd[1] = g.Cmd.move[dir];
             cmd[2] = '\0';
 
             if (IS_DOOR(levl[u.ux + x][u.uy + y].typ)) {
@@ -4418,11 +4433,9 @@ click_to_cmd(int x, int y, int mod)
     /* move, attack, etc. */
     cmd[1] = 0;
     if (mod == CLICK_1) {
-        cmd[0] = g.Cmd.dirchars[dir];
+        cmd[0] = g.Cmd.move[dir];
     } else {
-        cmd[0] = (g.Cmd.num_pad
-                     ? M(g.Cmd.dirchars[dir])
-                     : (g.Cmd.dirchars[dir] - 'a' + 'A')); /* run command */
+        cmd[0] = g.Cmd.run[dir];
     }
 
     return cmd;
@@ -4499,16 +4512,10 @@ parse(void)
     g.context.move = 1;
     flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
 
-#ifdef ALTMETA
-    alt_esc = iflags.altmeta; /* readchar() hack */
-#endif
     if (!g.Cmd.num_pad || (foo = readchar()) == g.Cmd.spkeys[NHKF_COUNT]) {
         foo = get_count((char *) 0, '\0', LARGEST_INT, &g.command_count, FALSE);
         g.last_command_count = g.command_count;
     }
-#ifdef ALTMETA
-    alt_esc = FALSE; /* readchar() reset */
-#endif
 
     if (iflags.debug_fuzzer /* if fuzzing, override '!' and ^Z */
         && (g.Cmd.commands[foo & 0x0ff]
@@ -4627,18 +4634,17 @@ end_of_input(void)
 }
 #endif /* HANGUPHANDLING */
 
-char
-readchar(void)
+static char
+readchar_core(int *x, int *y, int *mod)
 {
     register int sym;
-    int x = u.ux, y = u.uy, mod = 0;
 
     if (iflags.debug_fuzzer)
         return randomkey();
     if (*readchar_queue)
         sym = *readchar_queue++;
     else
-        sym = g.in_doagain ? pgetchar() : nh_poskey(&x, &y, &mod);
+        sym = g.in_doagain ? pgetchar() : nh_poskey(x, y, mod);
 
 #ifdef NR_OF_EOFS
     if (sym == EOF) {
@@ -4661,7 +4667,7 @@ readchar(void)
 #endif
         sym = '\033';
 #ifdef ALTMETA
-    } else if (sym == '\033' && alt_esc) {
+    } else if (sym == '\033' && iflags.altmeta) {
         /* iflags.altmeta: treat two character ``ESC c'' as single `M-c' */
         sym = *readchar_queue ? *readchar_queue++ : pgetchar();
         if (sym == EOF || sym == 0)
@@ -4671,12 +4677,31 @@ readchar(void)
 #endif /*ALTMETA*/
     } else if (sym == 0) {
         /* click event */
-        readchar_queue = click_to_cmd(x, y, mod);
+        readchar_queue = click_to_cmd(*x, *y, *mod);
         sym = *readchar_queue++;
     }
     return (char) sym;
 }
 
+char
+readchar(void)
+{
+    char ch;
+    int x = u.ux, y = u.uy, mod = 0;
+
+    ch = readchar_core(&x, &y, &mod);
+    return ch;
+}
+
+char
+readchar_poskey(int *x, int *y, int *mod)
+{
+    char ch;
+
+    ch = readchar_core(x, y, mod);
+    return ch;
+}
+
 /* '_' command, #travel, via keyboard rather than mouse click */
 static int
 dotravel(void)
index 26a77d62628c8a0b6bb223f5177417b419e7afc5..1c21f7e4e8eedb2226bc73ff240dc65e81cfe0ea 100644 (file)
--- a/src/dig.c
+++ b/src/dig.c
@@ -959,10 +959,11 @@ dig_up_grave(coord *cc)
 int
 use_pick_axe(struct obj *obj)
 {
-    const char *sdp, *verb;
+    const char *verb;
     char *dsp, dirsyms[12], qbuf[BUFSZ];
     boolean ispick;
     int rx, ry, downok, res = 0;
+    int dir;
 
     /* Check tool */
     if (obj != uwep) {
@@ -985,13 +986,19 @@ use_pick_axe(struct obj *obj)
     /* construct list of directions to show player for likely choices */
     downok = !!can_reach_floor(FALSE);
     dsp = dirsyms;
-    for (sdp = g.Cmd.dirchars; *sdp; ++sdp) {
+    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];
         /* filter out useless directions */
         if (u.uswallow) {
             ; /* all directions are viable when swallowed */
-        } else if (movecmd(*sdp)) {
-            /* normal direction, within plane of the level map;
-               movecmd() sets u.dx, u.dy, u.dz and returns !u.dz */
+        } else if (movecmd(dirch, MV_WALK)) {
+            /* normal direction, within plane of the level map */
             if (!dxdy_moveok())
                 continue; /* handle NODIAG */
             rx = u.ux + u.dx;
@@ -1008,7 +1015,7 @@ use_pick_axe(struct obj *obj)
                 continue;
         }
         /* include this direction */
-        *dsp++ = *sdp;
+        *dsp++ = dirch;
     }
     *dsp = 0;
     Sprintf(qbuf, "In what direction do you want to %s? [%s]", verb, dirsyms);
index 4ab872d6fdb1a2a07f53253a960824d52f29d716..48a6a0bac4181f007078c67be6f0535f10f06175 100644 (file)
@@ -110,12 +110,14 @@ getpos_help(boolean force, const char *goal)
     winid tmpwin = create_nhwindow(NHW_MENU);
 
     Sprintf(sbuf,
-            "Use '%c', '%c', '%c', '%c' to move the cursor to %s.", /* hjkl */
-            g.Cmd.move[DIR_W], g.Cmd.move[DIR_S],
-            g.Cmd.move[DIR_N], g.Cmd.move[DIR_E], goal);
+            "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);
     putstr(tmpwin, 0, sbuf);
     Sprintf(sbuf,
-            "Use 'H', 'J', 'K', 'L' to fast-move the cursor, %s.",
+            "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]),
             fastmovemode[iflags.getloc_moveskip]);
     putstr(tmpwin, 0, sbuf);
     putstr(tmpwin, 0, "Or enter a background symbol (ex. '<').");
@@ -684,6 +686,8 @@ getpos(coord *ccp, boolean force, const char *goal)
     coord *garr[NUM_GLOCS] = DUMMY;
     int gcount[NUM_GLOCS] = DUMMY;
     int gidx[NUM_GLOCS] = DUMMY;
+    schar udx = u.dx, udy = u.dy, udz = u.dz;
+    int dx, dy;
 
     for (i = 0; i < SIZE(pick_chars_def); i++)
         pick_chars[i] = g.Cmd.spkeys[pick_chars_def[i].nhkf];
@@ -720,7 +724,7 @@ getpos(coord *ccp, boolean force, const char *goal)
             auto_describe(cx, cy);
         }
 
-        c = nh_poskey(&tx, &ty, &sidx);
+        c = readchar_poskey(&tx, &ty, &sidx);
 
         if (hilite_state) {
             (*getpos_hilitefunc)(2);
@@ -750,38 +754,31 @@ getpos(coord *ccp, boolean force, const char *goal)
             /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */
             result = pick_chars_def[(int) (cp - pick_chars)].ret;
             break;
-        }
-        for (i = 0; i < N_DIRS; i++) {
-            int dx, dy;
-
-            if (g.Cmd.dirchars[i] == c) {
-                /* a normal movement letter or digit */
-                dx = xdir[i];
-                dy = ydir[i];
-            } else if (g.Cmd.alphadirchars[i] == lowc((char) c)
-                       || (g.Cmd.num_pad && g.Cmd.dirchars[i] == (c & 0177))) {
-                /* a shifted movement letter or Meta-digit */
-                if (iflags.getloc_moveskip) {
-                    /* skip same glyphs */
-                    int glyph = glyph_at(cx, cy);
-
-                    dx = xdir[i];
-                    dy = ydir[i];
-                    while (isok(cx + dx, cy + dy)
-                           && glyph == glyph_at(cx + dx, cy + dy)
-                           && isok(cx + dx + xdir[i], cy + dy + ydir[i])
-                           && glyph == glyph_at(cx + dx + xdir[i],
-                                                cy + dy + ydir[i])) {
-                        dx += xdir[i];
-                        dy += ydir[i];
-                    }
-                } else {
-                    dx = 8 * xdir[i];
-                    dy = 8 * ydir[i];
-                }
-            } else
-                continue;
+        } else if (movecmd(c, MV_WALK)) {
+            dx = u.dx;
+            dy = u.dy;
+            truncate_to_map(&cx, &cy, dx, dy);
+            goto nxtc;
+        } else if (movecmd(c, MV_RUSH) || movecmd(c, MV_RUN)) {
+            if (iflags.getloc_moveskip) {
+                /* skip same glyphs */
+                int glyph = glyph_at(cx, cy);
+
+                dx = u.dx;
+                dy = u.dy;
+                while (isok(cx + dx, cy + dy)
+                       && glyph == glyph_at(cx + dx, cy + dy)
+                       && isok(cx + dx + xdir[i], cy + dy + ydir[i])
+                       && glyph == glyph_at(cx + dx + xdir[i],
+                                            cy + dy + ydir[i])) {
+                    dx += u.dx;
+                    dy += u.dy;
 
+                }
+            } else {
+                dx = 8 * u.dx;
+                dy = 8 * u.dy;
+            }
             truncate_to_map(&cx, &cy, dx, dy);
             goto nxtc;
         }
@@ -994,6 +991,7 @@ getpos(coord *ccp, boolean force, const char *goal)
             free((genericptr_t) garr[i]);
     getpos_hilitefunc = (void (*)(int)) 0;
     getpos_getvalid = (boolean (*)(int, int)) 0;
+    u.dx = udx, u.dy = udy, u.dz = udz;
     return result;
 }