refine PR #1139 - m_move() and postmov()

Remove a stale comment and update one or two others.
Remove several trailing spaces.
Change the data type of a couple of variables from schar to int and a
couple others from int to coordxy.
Redo a nested 'if' sequence to un-nest; results in a bloated diff due
to reducing indentation for a big chunk of code.
Change monster movement to use u_on_newpos() when swallowed hero's
location moves along with engulfer so that a clipped map will be kept
up to date.
This commit is contained in:
PatR
2023-12-01 04:53:20 -08:00
parent f3bcec6c53
commit eb212c1676

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 monmove.c $NHDT-Date: 1684621592 2023/05/20 22:26:32 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.218 $ */
/* NetHack 3.7 monmove.c $NHDT-Date: 1701435190 2023/12/01 12:53:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.229 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -16,10 +16,10 @@ static void mind_blast(struct monst *);
static boolean holds_up_web(coordxy, coordxy);
static int count_webbing_walls(coordxy, coordxy);
static boolean soko_allow_web(struct monst *);
static boolean m_search_items(struct monst *, coordxy *, coordxy *, schar *,
static boolean m_search_items(struct monst *, coordxy *, coordxy *, int *,
int *);
static int postmov(struct monst *, struct permonst *, int, int, schar, boolean,
boolean, boolean, boolean);
static int postmov(struct monst *, struct permonst *, coordxy, coordxy, int,
boolean, boolean, boolean, boolean);
static boolean leppie_avoidance(struct monst *);
static void leppie_stash(struct monst *);
static boolean m_balks_at_approaching(struct monst *);
@@ -1164,7 +1164,7 @@ static boolean
m_search_items(
struct monst *mtmp,
coordxy *ggx, coordxy *ggy,
schar *mmoved,
int *mmoved,
int *appr)
{
register int minr = SQSRCHRADIUS; /* not too far away */
@@ -1289,72 +1289,66 @@ static int
postmov(
struct monst *mtmp,
struct permonst *ptr,
int omx,
int omy,
schar mmoved,
coordxy omx, coordxy omy,
int mmoved,
boolean sawmon,
boolean can_tunnel,
boolean can_unlock,
boolean can_open)
{
coordxy nix, niy;
int etmp;
int etmp, trapret;
boolean canseeit = cansee(mtmp->mx, mtmp->my),
didseeit = canseeit;
if (mmoved == MMOVE_MOVED || mmoved == MMOVE_DONE) {
boolean canseeit = cansee(mtmp->mx, mtmp->my),
didseeit = canseeit;
if (mmoved == MMOVE_MOVED) {
int trapret;
/* normal monster move will already have <nix,niy>,
but pet dog_move() with 'goto postmov' won't */
nix = mtmp->mx, niy = mtmp->my;
/* sequencing issue: when monster movement decides that a
monster can move to a door location, it moves the monster
there before dealing with the door rather than after;
so a vampire/bat that is going to shift to fog cloud and
pass under the door is already there but transformation
into fog form--and its message, when in sight--has not
happened yet; we have to move monster back to previous
location before performing the vamp_shift() to make the
message happen at right time, then back to the door again
[if we did the shift above, before moving the monster,
we would need to duplicate it in dog_move()...] */
if (is_vampshifter(mtmp) && !amorphous(mtmp->data)
&& IS_DOOR(levl[nix][niy].typ)
&& ((levl[nix][niy].doormask & (D_LOCKED | D_CLOSED)) != 0)
&& can_fog(mtmp)) {
if (sawmon) {
remove_monster(nix, niy);
place_monster(mtmp, omx, omy);
newsym(nix, niy), newsym(omx, omy);
}
if (vamp_shift(mtmp, &mons[PM_FOG_CLOUD], sawmon)) {
ptr = mtmp->data; /* update cached value */
}
if (sawmon) {
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
newsym(omx, omy), newsym(nix, niy);
}
if (mmoved == MMOVE_MOVED) {
nix = mtmp->mx, niy = mtmp->my;
/* sequencing issue: when monster movement decides that a
monster can move to a door location, it moves the monster
there before dealing with the door rather than after;
so a vampire/bat that is going to shift to fog cloud and
pass under the door is already there but transformation
into fog form--and its message, when in sight--has not
happened yet; we have to move monster back to previous
location before performing the vamp_shift() to make the
message happen at right time, then back to the door again
[if we did the shift sooner, before moving the monster,
we would need to duplicate it in dog_move()...] */
if (is_vampshifter(mtmp) && !amorphous(mtmp->data)
&& IS_DOOR(levl[nix][niy].typ)
&& ((levl[nix][niy].doormask & (D_LOCKED | D_CLOSED)) != 0)
&& can_fog(mtmp)) {
if (sawmon) {
remove_monster(nix, niy);
place_monster(mtmp, omx, omy);
newsym(nix, niy), newsym(omx, omy);
}
newsym(omx, omy); /* update the old position */
trapret = mintrap(mtmp, NO_TRAP_FLAGS);
if (trapret == Trap_Killed_Mon || trapret == Trap_Moved_Mon) {
if (mtmp->mx)
newsym(mtmp->mx, mtmp->my);
return MMOVE_DIED; /* it died */
if (vamp_shift(mtmp, &mons[PM_FOG_CLOUD], sawmon)) {
ptr = mtmp->data; /* update cached value */
}
ptr = mtmp->data; /* in case mintrap() caused polymorph */
if (sawmon) {
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
newsym(omx, omy), newsym(nix, niy);
}
}
newsym(omx, omy); /* update the old position */
trapret = mintrap(mtmp, NO_TRAP_FLAGS);
if (trapret == Trap_Killed_Mon || trapret == Trap_Moved_Mon) {
if (mtmp->mx)
newsym(mtmp->mx, mtmp->my);
return MMOVE_DIED; /* it died */
}
ptr = mtmp->data; /* in case mintrap() caused polymorph */
/* open a door, or crash through it, if 'mtmp' can */
if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
&& !passes_walls(ptr) /* doesn't need to open doors */
&& !can_tunnel) { /* taken care of below */
struct rm *here = &levl[mtmp->mx][mtmp->my];
boolean btrapped = (here->doormask & D_TRAPPED) != 0;
/* open a door, or crash through it, if 'mtmp' can */
if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
&& !passes_walls(ptr) /* doesn't need to open doors */
&& !can_tunnel) { /* taken care of below */
struct rm *here = &levl[mtmp->mx][mtmp->my];
boolean btrapped = (here->doormask & D_TRAPPED) != 0;
/* used after monster 'who' has been moved to closed door spot 'where'
which will now be changed to door state 'what' with map update */
#define UnblockDoor(where,who,what) \
@@ -1367,126 +1361,130 @@ postmov(
canseeit = didseeit || cansee((who)->mx, (who)->my); \
} while (0)
/* if mon has MKoT, disarm door trap; no message given */
if (btrapped && has_magic_key(mtmp)) {
/* BUG: this lets a vampire or blob or a doorbuster
holding the Key disarm the trap even though it isn't
using that Key when squeezing under or smashing the
door. Not significant enough to worry about; perhaps
the Key's magic is more powerful for monsters? */
here->doormask &= ~D_TRAPPED;
btrapped = FALSE;
}
if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
&& amorphous(ptr)) {
if (flags.verbose && canseemon(mtmp))
pline("%s %s under the door.", Monnam(mtmp),
(ptr == &mons[PM_FOG_CLOUD]
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
} else if (here->doormask & D_LOCKED && can_unlock) {
/* like the vampshift hack above, there are sequencing
issues when the monster is moved to the door's spot
first then door handling plus feedback comes after */
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s unlocks and opens a door.",
Monnam(mtmp));
} else if (canseeit) {
You_see("a door unlock and open.");
} else if (!Deaf) {
Soundeffect(se_door_unlock_and_open, 50);
You_hear("a door unlock and open.");
}
}
}
} else if (here->doormask == D_CLOSED && can_open) {
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s opens a door.", Monnam(mtmp));
} else if (canseeit) {
You_see("a door open.");
} else if (!Deaf) {
Soundeffect(se_door_open, 100);
You_hear("a door open.");
}
}
}
} else if (here->doormask & (D_LOCKED | D_CLOSED)) {
/* mfndpos guarantees this must be a doorbuster */
unsigned mask;
mask = ((btrapped || ((here->doormask & D_LOCKED) != 0
&& !rn2(2))) ? D_NODOOR
: D_BROKEN);
UnblockDoor(here, mtmp, mask);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s smashes down a door.",
Monnam(mtmp));
} else if (canseeit) {
You_see("a door crash open.");
} else if (!Deaf) {
Soundeffect(se_door_crash_open, 50);
You_hear("a door crash open.");
}
}
}
/* if it's a shop door, schedule repair */
if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
add_damage(mtmp->mx, mtmp->my, 0L);
}
} else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
/* 3.6.2: was using may_dig() but that doesn't handle bars;
AD_RUST catches rust monsters but metallivorous() is
needed for xorns and rock moles */
if (!(levl[mtmp->mx][mtmp->my].wall_info & W_NONDIGGABLE)
&& (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR)
|| metallivorous(ptr))) {
if (canseemon(mtmp))
pline("%s eats through the iron bars.", Monnam(mtmp));
dissolve_bars(mtmp->mx, mtmp->my);
return MMOVE_DONE;
} else if (flags.verbose && canseemon(mtmp))
Norep("%s %s %s the iron bars.", Monnam(mtmp),
/* pluralization fakes verb conjugation */
makeplural(locomotion(ptr, "pass")),
passes_walls(ptr) ? "through" : "between");
/* if mon has MKoT, disarm door trap; no message given */
if (btrapped && has_magic_key(mtmp)) {
/* BUG: this lets a vampire or blob or a doorbuster
holding the Key disarm the trap even though it isn't
using that Key when squeezing under or smashing the
door. Not significant enough to worry about; perhaps
the Key's magic is more powerful for monsters? */
here->doormask &= ~D_TRAPPED;
btrapped = FALSE;
}
if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
&& amorphous(ptr)) {
if (flags.verbose && canseemon(mtmp))
pline("%s %s under the door.", Monnam(mtmp),
(ptr == &mons[PM_FOG_CLOUD]
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
} else if (here->doormask & D_LOCKED && can_unlock) {
/* like the vampshift hack, there are sequencing
issues when the monster is moved to the door's spot
first then door handling plus feedback comes after */
/* possibly dig */
if (can_tunnel && may_dig(mtmp->mx, mtmp->my)
&& mdig_tunnel(mtmp))
return MMOVE_DIED; /* mon died (position already updated) */
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (!Deaf)
Soundeffect(se_door_unlock_and_open, 50);
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s unlocks and opens a door.",
Monnam(mtmp));
} else if (canseeit) {
You_see("a door unlock and open.");
} else if (!Deaf) {
You_hear("a door unlock and open.");
}
}
}
} else if (here->doormask == D_CLOSED && can_open) {
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (!Deaf)
Soundeffect(se_door_open, 100);
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s opens a door.", Monnam(mtmp));
} else if (canseeit) {
You_see("a door open.");
} else if (!Deaf) {
You_hear("a door open.");
}
}
}
} else if (here->doormask & (D_LOCKED | D_CLOSED)) {
/* mfndpos guarantees this must be a doorbuster */
unsigned mask;
/* set also in domove(), hack.c */
if (engulfing_u(mtmp)
&& (mtmp->mx != omx || mtmp->my != omy)) {
/* If the monster moved, then update */
u.ux0 = u.ux;
u.uy0 = u.uy;
u.ux = mtmp->mx;
u.uy = mtmp->my;
swallowed(0);
} else {
newsym(mtmp->mx, mtmp->my);
mask = ((btrapped
|| ((here->doormask & D_LOCKED) != 0 && !rn2(2)))
? D_NODOOR
: D_BROKEN);
UnblockDoor(here, mtmp, mask);
if (btrapped) {
if (mb_trapped(mtmp, canseeit))
return MMOVE_DIED;
} else {
if (!Deaf)
Soundeffect(se_door_crash_open, 50);
if (flags.verbose) {
if (canseeit && canspotmon(mtmp)) {
pline("%s smashes down a door.", Monnam(mtmp));
} else if (canseeit) {
You_see("a door crash open.");
} else if (!Deaf) {
You_hear("a door crash open.");
}
}
}
/* if it's a shop door, schedule repair */
if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
add_damage(mtmp->mx, mtmp->my, 0L);
}
#undef UnblockDoor
} else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
/* 3.6.2: was using may_dig() but that doesn't handle bars;
AD_RUST catches rust monsters but metallivorous() is
needed for xorns and rock moles */
if (!(levl[mtmp->mx][mtmp->my].wall_info & W_NONDIGGABLE)
&& (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR)
|| metallivorous(ptr))) {
if (canseemon(mtmp))
pline("%s eats through the iron bars.", Monnam(mtmp));
dissolve_bars(mtmp->mx, mtmp->my);
return MMOVE_DONE;
} else if (flags.verbose && canseemon(mtmp))
Norep("%s %s %s the iron bars.", Monnam(mtmp),
/* pluralization fakes verb conjugation */
makeplural(locomotion(ptr, "pass")),
passes_walls(ptr) ? "through" : "between");
} /* doors and bars */
/* possibly dig */
if (can_tunnel && may_dig(mtmp->mx, mtmp->my)
&& mdig_tunnel(mtmp))
return MMOVE_DIED; /* mon died (position already updated) */
/* set also in domove(), hack.c */
if (engulfing_u(mtmp) && (mtmp->mx != omx || mtmp->my != omy)) {
/* If the monster moved, then update */
u.ux0 = u.ux;
u.uy0 = u.uy;
u_on_newpos(mtmp->mx, mtmp->my);
swallowed(0);
} else {
newsym(mtmp->mx, mtmp->my);
}
} /* mmoved==MMOVE_MOVED */
if (mmoved == MMOVE_MOVED || mmoved == MMOVE_DONE) {
if (OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
/* Maybe a rock mole just ate some metal object */
@@ -1521,9 +1519,8 @@ postmov(
if (hides_under(ptr) || ptr->mlet == S_EEL) {
/* Always set--or reset--mundetected if it's already hidden
(just in case the object it was hiding under went away);
usually set mundetected unless monster can't move. */
if (mtmp->mundetected
|| (!helpless(mtmp) && rn2(5)))
usually set mundetected unless monster can't move. */
if (mtmp->mundetected || (!helpless(mtmp) && rn2(5)))
(void) hideunder(mtmp);
newsym(mtmp->mx, mtmp->my);
}
@@ -1534,11 +1531,11 @@ postmov(
return mmoved;
}
/* Handles the movement of a standard monster. */
/* Return values:
* 0: did not move, but can still attack and do other stuff.
* 1: moved, possibly can attack.
* 2: monster died.
/* Handles the movement of a standard monster.
* Return values:
* 0: did not move, but can still attack and do other stuff;
* 1: moved, possibly can attack;
* 2: monster died;
* 3: did not move, and can't do anything else either.
*/
int
@@ -1547,7 +1544,6 @@ m_move(register struct monst *mtmp, int after)
int appr;
coordxy ggx, ggy, nix, niy;
xint16 chcnt;
int chi; /* could be schar except for stupid Sun-2 compiler */
boolean can_tunnel = 0;
boolean can_open = 0, can_unlock = 0 /*, doorbuster = 0 */;
boolean getitems = FALSE;
@@ -1555,10 +1551,10 @@ m_move(register struct monst *mtmp, int after)
boolean better_with_displacing = FALSE;
boolean sawmon = canspotmon(mtmp); /* before it moved */
struct permonst *ptr;
schar mmoved = MMOVE_NOTHING; /* not strictly nec.: chi >= 0 will do */
int chi, mmoved = MMOVE_NOTHING; /* not strictly nec.: chi >= 0 will do */
long info[9];
long flag;
int omx = mtmp->mx, omy = mtmp->my;
coordxy omx = mtmp->mx, omy = mtmp->my;
if (mtmp->mtrapped) {
int i = mintrap(mtmp, NO_TRAP_FLAGS);
@@ -1596,8 +1592,8 @@ m_move(register struct monst *mtmp, int after)
goto not_special;
/* my dog gets special treatment */
if (mtmp->mtame) {
return postmov(mtmp, ptr, omx, omy, dog_move(mtmp, after), sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy, dog_move(mtmp, after),
sawmon, can_tunnel, can_unlock, can_open);
}
/* and the acquisitive monsters get special treatment */
@@ -1625,8 +1621,8 @@ m_move(register struct monst *mtmp, int after)
} else {
mmoved = MMOVE_NOTHING;
}
return postmov(mtmp, ptr, omx, omy, mmoved, sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
}
/* likewise for shopkeeper, guard, or priest */
@@ -1641,15 +1637,14 @@ m_move(register struct monst *mtmp, int after)
case -1:
mmoved = MMOVE_NOTHING; /* shk follow hero outside shop */
break;
default:
impossible("unknown shk/gd/pri_move return value (%d)", xm);
/*FALLTHRU*/
case 0:
return postmov(mtmp, ptr, omx, omy, MMOVE_NOTHING, sawmon,
can_tunnel, can_unlock, can_open);
case 1:
return postmov(mtmp, ptr, omx, omy, MMOVE_MOVED, sawmon,
can_tunnel, can_unlock, can_open);
default: impossible("unknown shk/gd/pri_move return value (%i)", xm);
return postmov(mtmp, ptr, omx, omy, MMOVE_NOTHING, sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy,
(xm != 1) ? MMOVE_NOTHING : MMOVE_MOVED,
sawmon, can_tunnel, can_unlock, can_open);
}
}
@@ -1671,8 +1666,8 @@ m_move(register struct monst *mtmp, int after)
(void) rloc(mtmp, RLOC_MSG);
else
mnexto(mtmp, RLOC_MSG);
return postmov(mtmp, ptr, omx, omy, MMOVE_MOVED, sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy, MMOVE_MOVED,
sawmon, can_tunnel, can_unlock, can_open);
}
not_special:
if (u.uswallow && !mtmp->mflee && u.ustuck != mtmp)
@@ -1731,8 +1726,8 @@ m_move(register struct monst *mtmp, int after)
}
if (getitems && m_search_items(mtmp, &ggx, &ggy, &mmoved, &appr))
return postmov(mtmp, ptr, omx, omy, mmoved, sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
/* don't tunnel if hostile and close enough to prefer a weapon */
if (can_tunnel && needspick(ptr)
@@ -1887,8 +1882,8 @@ m_move(register struct monst *mtmp, int after)
if (mtmp->wormno)
worm_nomove(mtmp);
}
return postmov(mtmp, ptr, omx, omy, mmoved, sawmon,
can_tunnel, can_unlock, can_open);
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
}
/* The part of m_move that deals with a monster attacking another monster (and