From: PatR Date: Sun, 17 Apr 2022 20:36:38 +0000 (-0700) Subject: more queued commands X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=54189e795b58f7ce4af118221552dcac9458537c;p=nethack more queued commands This attempts to make item-actions, #herecmd, and #therecmd be more robust. When rhack() or yn_function() take queued input off cmdq and get something unexpected, discard the rest of the queue. It also fixes the two crash cases that entrez reported. There are bound to be others though. I think a lot of actions that can be executed by queued input are going to need nomul(0) calls to handle repeat counts that should be ended early if something unexpected happens or something expected fails to happen. But that clears cmdq so may be tricky to decide where to use. --- diff --git a/src/cmd.c b/src/cmd.c index d5723435c..5ada7c8be 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -3969,9 +3969,10 @@ reset_cmd_vars(boolean reset_cmdq) void rhack(char *cmd) { + char queuedkeystroke[2]; int spkey = NHKF_ESC; boolean bad_command, firsttime = (cmd == 0); - struct _cmd_queue *cmdq = NULL; + struct _cmd_queue cq, *cmdq = NULL; const struct ext_func_tab *cmdq_ec = 0, *prefix_seen = 0; boolean was_m_prefix = FALSE; @@ -3983,19 +3984,16 @@ rhack(char *cmd) #endif if ((cmdq = cmdq_pop()) != 0) { /* doing queued commands */ - if (cmdq->typ == CMDQ_KEY) { - static char commandline[2]; - - if (!cmd) - cmd = commandline; - cmd[0] = cmdq->key; - cmd[1] = '\0'; - } else if (cmdq->typ == CMDQ_EXTCMD) { - cmdq_ec = cmdq->ec_entry; - } + cq = *cmdq; free(cmdq); - if (cmdq_ec) + if (cq.typ == CMDQ_EXTCMD && (cmdq_ec = cq.ec_entry) != 0) goto do_cmdq_extcmd; + cmd = queuedkeystroke; + /* already handled a queued command (goto do_cmdq_extcmd); + if something other than a key is queued, we'll drop down + to the !*cmd handling which clears out the command-queue */ + cmd[0] = (cq.typ == CMDQ_KEY) ? cq.key : '\0'; + cmd[1] = '\0'; } else if (firsttime) { cmd = parse(); /* parse() pushed a cmd but didn't return any key */ @@ -4003,21 +4001,17 @@ rhack(char *cmd) goto got_prefix_input; } - if (*cmd == g.Cmd.spkeys[NHKF_ESC]) { + /* if there's no command, there's nothing to do except reset */ + if (!cmd || !*cmd || *cmd == (char) 0377 + || *cmd == g.Cmd.spkeys[NHKF_ESC]) { + if (!cmd || *cmd != g.Cmd.spkeys[NHKF_ESC]) + nhbell(); reset_cmd_vars(TRUE); return; } - /* Special case of *cmd == ' ' handled better below */ - if (!*cmd || *cmd == (char) 0377) { - nhbell(); - reset_cmd_vars(TRUE); - return; /* probably we just had an interrupt */ - } - /* handle most movement commands */ g.context.travel = g.context.travel1 = 0; - { register const struct ext_func_tab *tlist; int res, (*func)(void); @@ -4117,7 +4111,7 @@ rhack(char *cmd) } else if ((res & ECMD_TIME) != 0) { g.context.move = TRUE; } else { /* ECMD_OK */ - reset_cmd_vars(FALSE); + reset_cmd_vars(g.multi < 0); } return; } @@ -4911,6 +4905,8 @@ there_cmd_menu(int x, int y, int mod) cmdq_add_dir(dx, dy, 0); break; case MCMD_REMOVE_SADDLE: + /* m-prefix for #loot: skip any floor containers */ + cmdq_add_ec(do_reqmenu); cmdq_add_ec(doloot); cmdq_add_dir(dx, dy, 0); cmdq_add_key('y'); /* "Do you want to remove the saddle ..." */ @@ -4918,6 +4914,7 @@ there_cmd_menu(int x, int y, int mod) case MCMD_APPLY_SADDLE: { struct obj *otmp = carrying(SADDLE); + if (otmp) { cmdq_add_ec(doapply); cmdq_add_key(otmp->invlet); @@ -5466,7 +5463,7 @@ doclicklook(void) char yn_function(const char *query, const char *resp, char def) { - char res, qbuf[QBUFSZ]; + char res = '\033', qbuf[QBUFSZ]; struct _cmd_queue *cmdq = cmdq_pop(); #ifdef DUMPLOG unsigned idx = g.saved_pline_index; @@ -5484,8 +5481,11 @@ yn_function(const char *query, const char *resp, char def) Strcpy(&qbuf[QBUFSZ - 1 - 3], "..."); query = qbuf; } - if (cmdq && cmdq->typ == CMDQ_KEY) { - res = cmdq->key; + if (cmdq) { + if (cmdq->typ == CMDQ_KEY) + res = cmdq->key; + else + cmdq_clear(); /* 'res' is ESC */ } else { res = (*windowprocs.win_yn_function)(query, resp, def); } diff --git a/src/pickup.c b/src/pickup.c index 759f0926d..7ef599045 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1817,8 +1817,9 @@ container_at(int x, int y, boolean countem) } static boolean -able_to_loot(int x, int y, - boolean looting) /* loot vs tip */ +able_to_loot( + int x, int y, + boolean looting) /* loot vs tip */ { const char *verb = looting ? "loot" : "tip"; struct trap *t = t_at(x, y); @@ -2045,21 +2046,20 @@ doloot_core(void) if (!get_adjacent_loc("Loot in what direction?", "Invalid loot location", u.ux, u.uy, &cc)) return ECMD_OK; - if (u_at(cc.x, cc.y)) { - underfoot = TRUE; - if (container_at(cc.x, cc.y, FALSE)) - goto lootcont; - } else - underfoot = FALSE; + underfoot = u_at(cc.x, cc.y); + if (underfoot && container_at(cc.x, cc.y, FALSE)) + goto lootcont; if (u.dz < 0) { You("%s to loot on the %s.", dont_find_anything, ceiling(cc.x, cc.y)); - timepassed = 1; - return (timepassed ? ECMD_TIME : ECMD_OK); + return ECMD_TIME; } mtmp = m_at(cc.x, cc.y); - if (mtmp) + if (mtmp) { timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot); + if (timepassed) + underfoot = 1; /* not true but skips dont_find_anything */ + } /* always use a turn when choosing a direction is impaired, even if you've successfully targetted a saddled creature and then answered "no" to the "remove its saddle?" prompt */ @@ -2201,6 +2201,9 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot) return 1; } extract_from_minvent(mtmp, otmp, TRUE, FALSE); + if (flags.verbose) + You("take %s off of %s.", + thesimpleoname(otmp), mon_nam(mtmp)); otmp = hold_another_object(otmp, "You drop %s!", doname(otmp), (const char *) 0); nhUse(otmp);