From 04e8fbf2495cf852a463d915c363aa4f8db04488 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 22 Jul 2022 14:11:16 -0700 Subject: [PATCH] finding level's vault guard Extend findgd() to bring a migrating guard back 'early' if there is one and an active guard is wanted but none is present on the level. It the level is full then the found guard is likely to be sent into limbo (scheduled to migrate back), so one can end up moving back and forth. Unlikely to occur during normal play. Also, when a guard is needed and there's a dead one parked at <0,0>, revive it. The dead guard has temporary corridor info in its mon->mextra->egd that a new one won't have. (This might introduce unexpected changes in vault behavior but if so, the old behavior was probably buggy.) When the hero is in a vault, don't find a guard unless u.uinvault is ready to bring it into play. It was finding one every turn and then ignoring the result for 29 turns out of 30. Change guard appearance timing: the first appearance is still after 30 turns, but if it goes away, bring it back after 15 more turns rather than another 30 and repeat as needed. --- src/dog.c | 2 +- src/vault.c | 59 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/dog.c b/src/dog.c index 9ed76097e..ecf40a3c5 100644 --- a/src/dog.c +++ b/src/dog.c @@ -347,7 +347,7 @@ mon_arrive(struct monst *mtmp, int when) /* some monsters might need to do something special upon arrival _after_ the current level has been fully set up; see dochug() */ mtmp->mstrategy |= STRAT_ARRIVE; - mtmp->mstate &= ~MON_MIGRATING; + mtmp->mstate &= ~(MON_MIGRATING | MON_LIMBO); /* make sure mnexto(rloc_to(set_apparxy())) doesn't use stale data */ mtmp->mux = u.ux, mtmp->muy = u.uy; diff --git a/src/vault.c b/src/vault.c index eda5b47e3..063130025 100644 --- a/src/vault.c +++ b/src/vault.c @@ -159,12 +159,13 @@ parkguard(struct monst *grd) if (grd->mx) { remove_monster(grd->mx, grd->my); newsym(grd->mx, grd->my); - place_monster(grd, 0, 0); - /* [grd->mx,my just got set to 0,0 by place_monster(), so this - just sets EGD(grd)->ogx,ogy to 0,0 too; is that what we want?] */ - EGD(grd)->ogx = grd->mx; - EGD(grd)->ogy = grd->my; } + if (m_at(0, 0) != grd) + place_monster(grd, 0, 0); + /* [grd->mx,my just got set to 0,0 by place_monster(), so this + just sets EGD(grd)->ogx,ogy to 0,0 too; is that what we want?] */ + EGD(grd)->ogx = grd->mx; + EGD(grd)->ogy = grd->my; } /* called in mon.c */ @@ -200,13 +201,30 @@ in_fcorridor(struct monst *grd, coordxy x, coordxy y) struct monst * findgd(void) { - register struct monst *mtmp; + struct monst *mtmp, **mprev; + /* this might find a guard parked at <0,0> since it'll be on fmon list */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { - if (DEADMONSTER(mtmp)) - continue; - if (mtmp->isgd && on_level(&(EGD(mtmp)->gdlevel), &u.uz)) + if (mtmp->isgd && on_level(&EGD(mtmp)->gdlevel, &u.uz)) { + if (!mtmp->mx && !EGD(mtmp)->gddone) + mtmp->mhp = mtmp->mhpmax; return mtmp; + } + } + /* if not on fmon, look for a guard waiting to migrate to this level */ + for (mprev = &g.migrating_mons; (mtmp = *mprev) != 0; + mprev = &mtmp->nmon) { + if (mtmp->isgd && on_level(&EGD(mtmp)->gdlevel, &u.uz)) { + /* take out of migrating_mons and place at <0,0> */ + *mprev = mtmp->nmon; + /* simplified mon_arrive(); avoid that because it would send + mtmp into limbo if no regular map spot is available */ + mon_track_clear(mtmp); + mtmp->mux = u.ux, mtmp->muy = u.uy; + mtmp->mx = mtmp->my = 0; /* not on map (note: mx is already 0) */ + parkguard(mtmp); + return mtmp; + } } return (struct monst *) 0; } @@ -303,10 +321,13 @@ invault(void) u.uinvault = 0; return; } - vaultroom -= ROOMOFFSET; + ++u.uinvault; + if (u.uinvault < VAULT_GUARD_TIME + || (u.uinvault % (VAULT_GUARD_TIME / 2)) != 0) + return; guard = findgd(); - if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) { + if (!guard) { /* if time ok and no guard now. */ char buf[BUFSZ]; int x, y, gx, gy, typ; @@ -314,9 +335,10 @@ invault(void) long umoney; /* first find the goal for the guard */ - if (!find_guard_dest((struct monst *)0, &rx, &ry)) + if (!find_guard_dest((struct monst *) 0, &rx, &ry)) return; gx = rx, gy = ry; + vaultroom -= ROOMOFFSET; /* next find a good place for a door in the wall */ x = u.ux; @@ -895,11 +917,11 @@ gd_move(struct monst *grd) n = grd->my; if (!Deaf) verbalize("You've been warned, knave!"); + grd->mpeaceful = 0; mnexto(grd, RLOC_NOMSG); levl[m][n].typ = egrd->fakecorr[0].ftyp; levl[m][n].flags = egrd->fakecorr[0].flags; newsym(m, n); - grd->mpeaceful = 0; return -1; } /* not fair to get mad when (s)he's fainted or paralyzed */ @@ -1117,7 +1139,7 @@ gd_move(struct monst *grd) void paygd(boolean silently) { - register struct monst *grd = findgd(); + struct monst *grd = findgd(); long umoney = money_cnt(g.invent); struct obj *coins, *nextcoins; int gx, gy; @@ -1184,12 +1206,7 @@ hidden_gold(boolean even_if_unknown) boolean gd_sound(void) { - struct monst *grd = findgd(); - - if (vault_occupied(u.urooms)) - return FALSE; - else - return (boolean) (grd == (struct monst *) 0); + return !(vault_occupied(u.urooms) || findgd()); } void @@ -1197,7 +1214,7 @@ vault_gd_watching(unsigned int activity) { struct monst *guard = findgd(); - if (guard && guard->mcansee && m_canseeu(guard)) { + if (guard && guard->mx && guard->mcansee && m_canseeu(guard)) { if (activity == GD_EATGOLD || activity == GD_DESTROYGOLD) EGD(guard)->witness = activity; }