diff --git a/doc/fixes37.0 b/doc/fixes37.0 index ebaa48d67..09ac5687f 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/decl.h b/include/decl.h index 446d4937b..ab803d0a9 100644 --- a/include/decl.h +++ b/include/decl.h @@ -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 */ diff --git a/include/extern.h b/include/extern.h index 15480b6d4..3f0db893e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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); diff --git a/src/cmd.c b/src/cmd.c index 5b5cd9d45..998495179 100644 --- 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); + int d = DIR_ERR; - 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; + 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) diff --git a/src/dig.c b/src/dig.c index 26a77d626..1c21f7e4e 100644 --- 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); diff --git a/src/do_name.c b/src/do_name.c index 4ab872d6f..48a6a0bac 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -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; + } 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); - 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 = 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; - 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 { + 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; }