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)
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

View File

@@ -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 ### */

View File

@@ -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.",

View File

@@ -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.",

View File

@@ -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;

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. */
/* 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;