From 93eccebe84f4f653c6eafaf405df20236d60c984 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Fri, 13 Oct 2006 04:03:36 +0000 Subject: [PATCH] sleeping steeds (trunk only) From the newsgroup: it was possible to saddle, mount, and ride on a sleeping jabberwork without it ever waking up. Movement was checking for timed sleep (!mon->mcanmove, set when mon->mfrozen contains a timer count for either sleep or paralysis) but not indefinite sleep (mon->msleeping). This moves the checking into its own routine which handles both types. And it gives monsters a chance to wake up when they get saddled or mounted. --- doc/fixes35.0 | 5 ++-- include/extern.h | 1 + src/do.c | 18 ++++--------- src/hack.c | 5 ++-- src/mhitm.c | 2 +- src/steed.c | 70 +++++++++++++++++++++++++++++++++++++++++++----- 6 files changed, 75 insertions(+), 26 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 497058b1f..8ac0e3f9e 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -31,7 +31,6 @@ internals: use Is_box rather than explicitly checking what it checks fix some unreachable messages (either make then reachable or remove them) can quiver coins when GOLDOBJ is defined grammar, spelling and other typos -oracle and rumor regarding priestly donations keep various delayed killers separate to avoid mixed up messages don't place randomly-placed aquatic monsters in lava on special levels hiding monsters don't hide under cockatrice/chickatrice corpses @@ -163,7 +162,8 @@ bugles affect all monsters to some extent nurses are affected if player is polymorphed as a cockatrice getting a particular rotten food result can't make attempting to eat a corpse of one of the Riders be survivable -pad rumors to improve distribution of delivered rumors +pad shortest rumors to improve distribution of delivered rumors +wake up sleeping steed when putting on saddle or mounting Platform- and/or Interface-Specific Fixes @@ -248,6 +248,7 @@ add Malcolm Ryan's Statue Glyphs patch lembas and cram never rot unless cursed multiple squeaks for squeaky boards include time, user ID, and play mode in paniclog entries +add oracle and rumor regarding priestly donations Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 739f2aa90..d7040a0e1 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2101,6 +2101,7 @@ E void NDECL(exercise_steed); E void NDECL(kick_steed); E void FDECL(dismount_steed, (int)); E void FDECL(place_monster, (struct monst *,int,int)); +E boolean FDECL(stucksteed, (BOOLEAN_P)); #endif /* ### teleport.c ### */ diff --git a/src/do.c b/src/do.c index b3330c149..de8380b17 100644 --- a/src/do.c +++ b/src/do.c @@ -755,13 +755,9 @@ dodown() } #ifdef STEED - if (u.usteed && !u.usteed->mcanmove) { - pline("%s won't move!", Monnam(u.usteed)); - return(0); - } else if (u.usteed && u.usteed->meating) { - pline("%s is still eating.", Monnam(u.usteed)); - return(0); - } else + if (stucksteed(TRUE)) { + return 0; + } #endif if (Levitation) { if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) { @@ -875,13 +871,9 @@ doup() return(0); } #ifdef STEED - if (u.usteed && !u.usteed->mcanmove) { - pline("%s won't move!", Monnam(u.usteed)); + if (stucksteed(TRUE)) { return(0); - } else if (u.usteed && u.usteed->meating) { - pline("%s is still eating.", Monnam(u.usteed)); - return(0); - } else + } #endif if(u.ustuck) { You("are %s, and cannot go up.", diff --git a/src/hack.c b/src/hack.c index a689aa9a1..826be5e06 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1221,11 +1221,10 @@ domove() } /* not attacking an animal, so we try to move */ #ifdef STEED - if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { - pline("%s won't move!", upstart(y_monnam(u.usteed))); + if ((u.dx || u.dy) && stucksteed(FALSE)) { nomul(0); return; - } else + } #endif if(!youmonst.data->mmove) { You("are rooted %s.", diff --git a/src/mhitm.c b/src/mhitm.c index 702174c39..fbc35a5a4 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1277,7 +1277,7 @@ int amt, how; (how >= 0 && resist(mon, (char)how, 0, NOTELL))) { shieldeff(mon->mx, mon->my); } else if (mon->mcanmove) { - mon->meating = 0; /* terminate any meal-in-progress */ + finish_meating(mon); /* terminate any meal-in-progress */ amt += (int) mon->mfrozen; if (amt > 0) { /* sleep for N turns */ mon->mcanmove = 0; diff --git a/src/steed.c b/src/steed.c index 670bf480f..091c708f2 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)steed.c 3.5 2006/04/14 */ +/* SCCS Id: @(#)steed.c 3.5 2006/10/11 */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,6 +13,7 @@ static NEARDATA const char steeds[] = { }; STATIC_DCL boolean FDECL(landing_spot, (coord *, int, int)); +STATIC_DCL void FDECL(maybewakesteed, (struct monst *)); /* caller has decided that hero can't reach something while mounted */ void @@ -136,6 +137,9 @@ use_saddle(otmp) if (otmp->cursed) chance -= 50; + /* [intended] steed becomes alert if possible */ + maybewakesteed(mtmp); + /* Make the attempt */ if (rn2(100) < chance) { You("put the saddle on %s.", mon_nam(mtmp)); @@ -172,16 +176,17 @@ doride() { boolean forcemount = FALSE; - if (u.usteed) + if (u.usteed) { dismount_steed(DISMOUNT_BYCHOICE); - else if (getdir((char *)0) && isok(u.ux+u.dx, u.uy+u.dy)) { + } else if (getdir((char *)0) && isok(u.ux+u.dx, u.uy+u.dy)) { #ifdef WIZARD - if (wizard && yn("Force the mount to succeed?") == 'y') + if (wizard && yn("Force the mount to succeed?") == 'y') forcemount = TRUE; #endif return (mount_steed(m_at(u.ux+u.dx, u.uy+u.dy), forcemount)); - } else + } else { return 0; + } return 1; } @@ -329,10 +334,11 @@ mount_steed(mtmp, force) } /* Success */ + maybewakesteed(mtmp); if (!force) { if (Levitation && !is_floater(ptr) && !is_flyer(ptr)) - /* Must have Lev_at_will at this point */ - pline("%s magically floats up!", Monnam(mtmp)); + /* Must have Lev_at_will at this point */ + pline("%s magically floats up!", Monnam(mtmp)); You("mount %s.", mon_nam(mtmp)); } /* setuwep handles polearms differently when you're mounted */ @@ -620,6 +626,56 @@ dismount_steed(reason) return; } +/* when attempting to saddle or mount a sleeping steed, try to wake it up + (for the saddling case, it won't be u.usteed yet) */ +STATIC_OVL void +maybewakesteed(steed) +struct monst *steed; +{ + int frozen = (int) steed->mfrozen; + boolean wasimmobile = steed->msleeping || !steed->mcanmove; + + steed->msleeping = 0; + if (frozen) { + frozen = (frozen + 1) / 2; /* half */ + /* might break out of timed sleep or paralysis */ + if (!rn2(frozen)) { + steed->mfrozen = 0; + steed->mcanmove = 1; + } else { + /* didn't awake, but remaining duration is halved */ + steed->mfrozen = frozen; + } + } + if (wasimmobile && !steed->msleeping && steed->mcanmove) + pline("%s wakes up.", Monnam(steed)); + /* regardless of waking, terminate any meal in progress */ + finish_meating(steed); +} + +/* decide whether hero's steed is able to move; + doesn't check for holding traps--those affect the hero directly */ +boolean +stucksteed(checkfeeding) +boolean checkfeeding; +{ + struct monst *steed = u.usteed; + + if (steed) { + /* check whether steed can move */ + if (steed->msleeping || !steed->mcanmove) { + pline("%s won't move!", upstart(y_monnam(steed))); + return TRUE; + } + /* optionally check whether steed is in the midst of a meal */ + if (checkfeeding && steed->meating) { + pline("%s is still eating.", upstart(y_monnam(steed))); + return TRUE; + } + } + return FALSE; +} + void place_monster(mon, x, y) struct monst *mon;