fix issue #1377 - Forcefight vs displacer beasts

Issue reported by elunna:  Using the 'F' prefix against a displacer
beast prevented swapping places.

This doesn't use the suggested fix.  It is quite short but there is
a large diff due to change in indentation and reformatting several
comments because of that.

Attacking a displacer beast either with or without 'F' might miss,
hit, or swap places.  It won't "harmlessly attack thin air."

Fixes #1377
This commit is contained in:
PatR
2025-03-10 09:17:41 -07:00
parent 0a180c52ef
commit 719166f9ec
2 changed files with 108 additions and 101 deletions
+2
View File
@@ -2098,6 +2098,8 @@ when walking into/against a locked closed door, 'autounlock'==kick didn't
having a 1% chance of creating rideable monsters with worn saddle gave knights having a 1% chance of creating rideable monsters with worn saddle gave knights
a 1% chance of creating an extra saddle for starting pony; it wasn't a 1% chance of creating an extra saddle for starting pony; it wasn't
tracked with other objects so produced a trivial memory leak tracked with other objects so produced a trivial memory leak
hen attacking a displacer beast, using the 'F' forcefight prefix prevented it
from swapping places with the hero
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
+22 -17
View File
@@ -1956,10 +1956,12 @@ domove_attackmon_at(
&& bad_rock(gy.youmonst.data, x, u.uy0)))) && bad_rock(gy.youmonst.data, x, u.uy0))))
&& goodpos(u.ux0, u.uy0, mtmp, GP_ALLOW_U)); && goodpos(u.ux0, u.uy0, mtmp, GP_ALLOW_U));
/* if not displacing, try to attack; note that it might evade; /* if not displacing, try to attack; note that it might evade;
also, we don't attack tame when _safepet_ */ also, we don't attack tame or peaceful when safemon() */
if (!*displaceu && do_attack(mtmp)) if (!*displaceu) {
if (do_attack(mtmp))
return TRUE; return TRUE;
} }
}
return FALSE; return FALSE;
} }
@@ -2696,6 +2698,8 @@ domove_core(void)
return; return;
} }
if (!displaceu) {
if (domove_fight_ironbars(x, y)) if (domove_fight_ironbars(x, y))
return; return;
@@ -2718,9 +2722,9 @@ domove_core(void)
/* treat entering a visible gas cloud region like entering a trap; /* treat entering a visible gas cloud region like entering a trap;
there could be a known trap as well as a region at the target spot; there could be a known trap as well as a region at the target spot;
if so, ask about entring the region first; even though this could if so, ask about entring the region first; even though this could
lead to two consecutive confirmation prompts, the situation seems to lead to two consecutive confirmation prompts, the situation seems
be too uncommon to warrant a separate case with combined trap+region to be too uncommon to warrant a separate case with combined
confirmation */ trap+region confirmation */
if (ParanoidTrap && !Blind && !Stunned && !Confusion && !Hallucination if (ParanoidTrap && !Blind && !Stunned && !Confusion && !Hallucination
/* skip if player used 'm' prefix or is moving recklessly */ /* skip if player used 'm' prefix or is moving recklessly */
&& (!svc.context.nopick || svc.context.run) && (!svc.context.nopick || svc.context.run)
@@ -2729,12 +2733,14 @@ domove_core(void)
&& ((oldreg = visible_region_at(u.ux, u.uy)) == 0 && ((oldreg = visible_region_at(u.ux, u.uy)) == 0
/* if moving from one region into another, only ask for /* if moving from one region into another, only ask for
confirmation if the one potentially being entered inflicts confirmation if the one potentially being entered inflicts
damage (poison gas) and the one being exited doesn't (vapor) */ damage (poison gas) and the one being exited doesn't
(vapor) */
|| (reg_damg(newreg) > 0 && reg_damg(oldreg) == 0)) || (reg_damg(newreg) > 0 && reg_damg(oldreg) == 0))
/* check whether attempted move will be viable */ /* check whether attempted move will be viable */
&& test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE) && test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE)
/* we don't override confirmation for poison resistance since the /* we don't override confirmation for poison resistance since
region also hinders hero's vision even if/when no damage is done */ the region also hinders hero's vision even if/when no damage
is done */
) { ) {
char qbuf[QBUFSZ]; char qbuf[QBUFSZ];
@@ -2747,18 +2753,13 @@ domove_core(void)
return; return;
} }
} }
/* maybe ask player for confirmation before walking into known traps */ /* maybe ask player for confirmation before walking into known trap */
if (ParanoidTrap && !Stunned && !Confusion if (ParanoidTrap && !Stunned && !Confusion
/* skip if player used 'm' prefix or is moving recklessly */ /* skip if player used 'm' prefix or is moving recklessly */
&& (!svc.context.nopick || svc.context.run) && (!svc.context.nopick || svc.context.run)
/* check for discovered trap */ /* check for discovered trap */
&& (trap = t_at(x, y)) != 0 && trap->tseen && (trap = t_at(x, y)) != 0 && trap->tseen
/* check whether attempted move will be viable */ /* check whether attempted move will be viable */
/*
* FIXME:
* this will result in "Really step into trap?" if there is a
* peaceful or tame monster already there.
*/
&& test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE) && test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE)
/* override confirmation if the trap is harmless to the hero */ /* override confirmation if the trap is harmless to the hero */
&& (immune_to_trap(&gy.youmonst, trap->ttyp) != TRAP_CLEARLY_IMMUNE && (immune_to_trap(&gy.youmonst, trap->ttyp) != TRAP_CLEARLY_IMMUNE
@@ -2766,7 +2767,8 @@ domove_core(void)
hero can't tell what they are, so treat as dangerous */ hero can't tell what they are, so treat as dangerous */
|| Hallucination)) { || Hallucination)) {
char qbuf[QBUFSZ]; char qbuf[QBUFSZ];
int traptype = (Hallucination ? rnd(TRAPNUM - 1) : (int) trap->ttyp); int traptype = (Hallucination ? rnd(TRAPNUM - 1)
: (int) trap->ttyp);
boolean into = into_vs_onto(traptype); boolean into = into_vs_onto(traptype);
Snprintf(qbuf, sizeof qbuf, "Really %s %s that %s?", Snprintf(qbuf, sizeof qbuf, "Really %s %s that %s?",
@@ -2783,14 +2785,15 @@ domove_core(void)
} }
} }
if (u.utrap) { if (u.utrap) { /* when u.utrap is True, displaceu is False */
boolean moved = trapmove(x, y, trap); boolean moved = trapmove(x, y, trap);
if (!u.utrap) { if (!u.utrap) {
disp.botl = TRUE; disp.botl = TRUE;
reset_utrap(TRUE); /* might resume levitation or flight */ reset_utrap(TRUE); /* might resume levitation or flight */
} }
/* might not have escaped, or did escape but remain in same spot */ /* might not have escaped, or did escape but remain in the same
spot */
if (!moved) if (!moved)
return; return;
} }
@@ -2810,6 +2813,8 @@ domove_core(void)
return; return;
} }
} /* !dislacedu */
/* Move ball and chain. */ /* Move ball and chain. */
if (Punished) if (Punished)
if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy, if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,