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.
This commit is contained in:
nethack.rankin
2006-10-13 04:03:36 +00:00
parent 951e0d87fa
commit 93eccebe84
6 changed files with 75 additions and 26 deletions

View File

@@ -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) fix some unreachable messages (either make then reachable or remove them)
can quiver coins when GOLDOBJ is defined can quiver coins when GOLDOBJ is defined
grammar, spelling and other typos grammar, spelling and other typos
oracle and rumor regarding priestly donations
keep various delayed killers separate to avoid mixed up messages keep various delayed killers separate to avoid mixed up messages
don't place randomly-placed aquatic monsters in lava on special levels don't place randomly-placed aquatic monsters in lava on special levels
hiding monsters don't hide under cockatrice/chickatrice corpses 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 nurses are affected if player is polymorphed as a cockatrice
getting a particular rotten food result can't make attempting to eat a getting a particular rotten food result can't make attempting to eat a
corpse of one of the Riders be survivable 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 Platform- and/or Interface-Specific Fixes
@@ -248,6 +248,7 @@ add Malcolm Ryan's Statue Glyphs patch
lembas and cram never rot unless cursed lembas and cram never rot unless cursed
multiple squeaks for squeaky boards multiple squeaks for squeaky boards
include time, user ID, and play mode in paniclog entries include time, user ID, and play mode in paniclog entries
add oracle and rumor regarding priestly donations
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features

View File

@@ -2101,6 +2101,7 @@ E void NDECL(exercise_steed);
E void NDECL(kick_steed); E void NDECL(kick_steed);
E void FDECL(dismount_steed, (int)); E void FDECL(dismount_steed, (int));
E void FDECL(place_monster, (struct monst *,int,int)); E void FDECL(place_monster, (struct monst *,int,int));
E boolean FDECL(stucksteed, (BOOLEAN_P));
#endif #endif
/* ### teleport.c ### */ /* ### teleport.c ### */

View File

@@ -755,13 +755,9 @@ dodown()
} }
#ifdef STEED #ifdef STEED
if (u.usteed && !u.usteed->mcanmove) { if (stucksteed(TRUE)) {
pline("%s won't move!", Monnam(u.usteed)); return 0;
return(0); }
} else if (u.usteed && u.usteed->meating) {
pline("%s is still eating.", Monnam(u.usteed));
return(0);
} else
#endif #endif
if (Levitation) { if (Levitation) {
if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) { if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
@@ -875,13 +871,9 @@ doup()
return(0); return(0);
} }
#ifdef STEED #ifdef STEED
if (u.usteed && !u.usteed->mcanmove) { if (stucksteed(TRUE)) {
pline("%s won't move!", Monnam(u.usteed));
return(0); return(0);
} else if (u.usteed && u.usteed->meating) { }
pline("%s is still eating.", Monnam(u.usteed));
return(0);
} else
#endif #endif
if(u.ustuck) { if(u.ustuck) {
You("are %s, and cannot go up.", You("are %s, and cannot go up.",

View File

@@ -1221,11 +1221,10 @@ domove()
} }
/* not attacking an animal, so we try to move */ /* not attacking an animal, so we try to move */
#ifdef STEED #ifdef STEED
if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { if ((u.dx || u.dy) && stucksteed(FALSE)) {
pline("%s won't move!", upstart(y_monnam(u.usteed)));
nomul(0); nomul(0);
return; return;
} else }
#endif #endif
if(!youmonst.data->mmove) { if(!youmonst.data->mmove) {
You("are rooted %s.", You("are rooted %s.",

View File

@@ -1277,7 +1277,7 @@ int amt, how;
(how >= 0 && resist(mon, (char)how, 0, NOTELL))) { (how >= 0 && resist(mon, (char)how, 0, NOTELL))) {
shieldeff(mon->mx, mon->my); shieldeff(mon->mx, mon->my);
} else if (mon->mcanmove) { } else if (mon->mcanmove) {
mon->meating = 0; /* terminate any meal-in-progress */ finish_meating(mon); /* terminate any meal-in-progress */
amt += (int) mon->mfrozen; amt += (int) mon->mfrozen;
if (amt > 0) { /* sleep for N turns */ if (amt > 0) { /* sleep for N turns */
mon->mcanmove = 0; mon->mcanmove = 0;

View File

@@ -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. */ /* Copyright (c) Kevin Hugo, 1998-1999. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 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 */ /* caller has decided that hero can't reach something while mounted */
void void
@@ -136,6 +137,9 @@ use_saddle(otmp)
if (otmp->cursed) if (otmp->cursed)
chance -= 50; chance -= 50;
/* [intended] steed becomes alert if possible */
maybewakesteed(mtmp);
/* Make the attempt */ /* Make the attempt */
if (rn2(100) < chance) { if (rn2(100) < chance) {
You("put the saddle on %s.", mon_nam(mtmp)); You("put the saddle on %s.", mon_nam(mtmp));
@@ -172,16 +176,17 @@ doride()
{ {
boolean forcemount = FALSE; boolean forcemount = FALSE;
if (u.usteed) if (u.usteed) {
dismount_steed(DISMOUNT_BYCHOICE); 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 #ifdef WIZARD
if (wizard && yn("Force the mount to succeed?") == 'y') if (wizard && yn("Force the mount to succeed?") == 'y')
forcemount = TRUE; forcemount = TRUE;
#endif #endif
return (mount_steed(m_at(u.ux+u.dx, u.uy+u.dy), forcemount)); return (mount_steed(m_at(u.ux+u.dx, u.uy+u.dy), forcemount));
} else } else {
return 0; return 0;
}
return 1; return 1;
} }
@@ -329,10 +334,11 @@ mount_steed(mtmp, force)
} }
/* Success */ /* Success */
maybewakesteed(mtmp);
if (!force) { if (!force) {
if (Levitation && !is_floater(ptr) && !is_flyer(ptr)) if (Levitation && !is_floater(ptr) && !is_flyer(ptr))
/* Must have Lev_at_will at this point */ /* Must have Lev_at_will at this point */
pline("%s magically floats up!", Monnam(mtmp)); pline("%s magically floats up!", Monnam(mtmp));
You("mount %s.", mon_nam(mtmp)); You("mount %s.", mon_nam(mtmp));
} }
/* setuwep handles polearms differently when you're mounted */ /* setuwep handles polearms differently when you're mounted */
@@ -620,6 +626,56 @@ dismount_steed(reason)
return; 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 void
place_monster(mon, x, y) place_monster(mon, x, y)
struct monst *mon; struct monst *mon;