context-sensitive inventory - action sequencing

rhack() normally calls parse(), parse() sets context.move to True
assuming that the player's next action will take game time, then
when it returns, rhack() sets context.move back to False if the
assumption turned out to be incorrect.  But when performing actions
after picking something in inventory, rhack() doesn't call parse()
so context.move is left at False.

This was hidden by making the inventory command take game time if
the player picked an item and set up an action to be done with it
even though the action hadn't taken place yet.  So time was being
accounted for but if the hero didn't get consecutive moves then
monsters got their turn between the shouldn't-take-time inventory
command and the ought-to-behave-like-normal-command queued action.

My initial attempt to fix this (before figuring out how context.move
works) by stopping inventory from taking time didn't work because
queued item-actions stopped taking time too, or rather the fact that
they took no time became exposed.  This second attempt doesn't have
that problem and I think it is correct.
This commit is contained in:
PatR
2022-04-12 14:56:38 -07:00
parent d20b2772eb
commit 60c504dd40
3 changed files with 20 additions and 21 deletions

View File

@@ -1141,6 +1141,9 @@ taking off yellow dragon scales/mail or having temporary stoning resistance
corpse safely wielded instead of petrifying the hero
special level loading wasn't honoring gender specified in lua code
add '#tip' for containers to context-sensitive invent handling
sequencing confusion: picking an item when viewing inventory and picking an
action to do with it caused the inventory command to use time, then
on next turn the action was performed without taking any time
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support

View File

@@ -4009,11 +4009,11 @@ rhack(char *cmd)
doextcmd() notifies us what that was via ext_tlist;
other commands leave it Null */
if (g.ext_tlist)
tlist = g.ext_tlist;
tlist = g.ext_tlist, g.ext_tlist = NULL;
if ((tlist->flags & PREFIXCMD)) {
if ((tlist->flags & PREFIXCMD) != 0) {
/* it was a prefix command, mark and get another cmd */
if ((res & ECMD_CANCEL)) {
if ((res & ECMD_CANCEL) != 0) {
/* prefix commands cancel if pressed twice */
reset_cmd_vars(TRUE);
return;
@@ -4056,17 +4056,14 @@ rhack(char *cmd)
prefix_seen = 0;
was_m_prefix = FALSE;
}
if ((res & (ECMD_CANCEL|ECMD_FAIL))) {
if ((res & (ECMD_CANCEL | ECMD_FAIL)) != 0) {
/* command was canceled by user, maybe they declined to
pick an object to act on, or command failed to finish */
reset_cmd_vars(TRUE);
prefix_seen = 0;
cmdq_ec = NULL;
}
if (!(res & ECMD_TIME)) {
} else if ((res & ECMD_TIME) != 0) {
g.context.move = TRUE;
} else { /* ECMD_OK */
reset_cmd_vars(FALSE);
prefix_seen = 0;
cmdq_ec = NULL;
}
return;
}
@@ -5143,7 +5140,7 @@ parse(void)
iflags.in_parse = TRUE;
g.command_count = 0;
g.context.move = 1;
g.context.move = TRUE; /* assume next command will take game time */
flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
g.program_state.getting_a_command = 1; /* affects readchar() behavior for

View File

@@ -2539,7 +2539,6 @@ static int
itemactions(struct obj *otmp)
{
int n, act = IA_NONE;
int ret = ECMD_TIME;
winid win;
char buf[BUFSZ];
menu_item *selected;
@@ -2902,11 +2901,12 @@ itemactions(struct obj *otmp)
cmdq_add_key(otmp->invlet);
break;
}
} else
ret = !n ? ECMD_CANCEL : ECMD_OK; /* cancelled */
}
destroy_nhwindow(win);
return ret;
/* finish the 'i' command: no time elapses and cancelling without
selecting an action doesn't matter */
return ECMD_OK;
}
@@ -2917,12 +2917,11 @@ ddoinv(void)
struct obj *otmp;
char c = display_inventory((char *) 0, TRUE);
if (!c)
return ECMD_OK;
for (otmp = g.invent; otmp; otmp = otmp->nobj)
if (otmp->invlet == c)
return itemactions(otmp);
if (c && c != '\033') {
for (otmp = g.invent; otmp; otmp = otmp->nobj)
if (otmp->invlet == c)
return itemactions(otmp);
}
return ECMD_OK;
}