1 /* SCCS Id: @(#)steed.c 3.4 2003/01/10 */
2 /* Copyright (c) Kevin Hugo, 1998-1999. */
3 /* NetHack may be freely redistributed. See license for details. */
8 /* Monsters that might be ridden */
9 static NEARDATA
const char steeds
[] = {
10 S_QUADRUPED
, S_UNICORN
, S_ANGEL
, S_DEMON
, S_CENTAUR
, S_DRAGON
, S_JABBERWOCK
, S_COCKATRICE
, S_HUMANOID
, S_NYMPH
,
11 S_SPIDER
, S_ZOUTHERN
, S_BAT
, S_GIANT
, S_KOP
, S_LICH
, S_MUMMY
, S_NAGA
, S_VAMPIRE
, S_WRAITH
, S_YETI
, S_ZOMBIE
, S_GOLEM
,
12 S_HUMAN
, S_EEL
, S_LIZARD
, S_BAD_FOOD
, S_BAD_COINS
, S_FLYFISH
, '\0'
13 /* added demons and some other stuff --Amy */
16 STATIC_DCL boolean
landing_spot(coord
*, int, int);
18 /* caller has decided that hero can't reach something while mounted */
22 You("aren't skilled enough to reach from %s.", y_monnam(u
.usteed
));
25 /* to check for your current steed's saddle, because we might be looking for a specific artifact --Amy */
30 if (!u
.usteed
) return FALSE
;
32 struct obj
*osaeddle
= which_armor(u
.usteed
, W_SADDLE
);
33 if ((osaeddle
= which_armor(u
.usteed
, W_SADDLE
)) && osaeddle
->oartifact
== artid
) return TRUE
;
39 /* to check for your current steed's saddle, when looking for a specific base type of saddle --Amy */
44 if (!u
.usteed
) return FALSE
;
46 struct obj
*osaeddle
= which_armor(u
.usteed
, W_SADDLE
);
47 if ((osaeddle
= which_armor(u
.usteed
, W_SADDLE
)) && osaeddle
->otyp
== saddleid
) return TRUE
;
53 /* to check for some random monster's saddle, because we might be looking for a specific artifact --Amy */
55 mercedesride(artid
, mtmp
)
59 if (!mtmp
) return FALSE
;
61 struct obj
*osaeddle
= which_armor(mtmp
, W_SADDLE
);
62 if ((osaeddle
= which_armor(mtmp
, W_SADDLE
)) && osaeddle
->oartifact
== artid
) return TRUE
;
68 /* to check for some random monster's saddle, when looking for a specific base type of saddle --Amy */
70 fordride(saddleid
, mtmp
)
74 if (!mtmp
) return FALSE
;
76 struct obj
*osaeddle
= which_armor(mtmp
, W_SADDLE
);
77 if ((osaeddle
= which_armor(mtmp
, W_SADDLE
)) && osaeddle
->otyp
== saddleid
) return TRUE
;
83 /* is the monster mtmp a dedicated steed (gives better speed returns, see allmain.c)? --Amy */
88 if (mercedesride(ART_MOUNT_OF_THE_MAD_POTATO
, mtmp
)) return TRUE
;
89 if (index(steeds
, mtmp
->data
->mlet
)) return TRUE
;
90 if (mtmp
->egotype_steed
) return TRUE
;
91 if (mtmp
->data
->msound
== MS_NEIGH
|| mtmp
->data
->msound
== MS_SHOE
|| mtmp
->data
->msound
== MS_CAR
) return TRUE
;
96 /* is the monster mtmp not suitable for riding (makes you very slow if you attempt to ride, see allmain.c)? --Amy */
101 if (mtmp
->data
->msound
== MS_BULLETATOR
) return TRUE
;
106 /*** Putting the saddle on ***/
108 /* Can this monster wear a saddle? */
113 if (!issoviet
) return 1; /* just remove all those annoying restrictions and allow everything to be saddled --Amy */
114 struct permonst
*ptr
= mtmp
->data
;
116 return (index(steeds
, ptr
->mlet
) && (ptr
->msize
>= MZ_MEDIUM
) &&
117 (!humanoid(ptr
) || ptr
->mlet
== S_CENTAUR
) &&
118 !amorphous(ptr
) && !noncorporeal(ptr
) &&
119 !is_whirly(ptr
) && !unsolid(ptr
));
122 /* high skill should allow the player to have a saving throw against falling off --Amy
123 * not all instances of falling off the steed will allow you to do this though, and since I follow the rule that no skills
124 * may make things harder for you, you'll always have a chance of falling off anyway just in case you specifically WANT
125 * to be thrown off the steed (hint: cursed saddle and player would want to unmount but cannot).
126 * returns 0 if the player failed the check and will fall off, 1 if the saving throw was successful and you stay mounted */
130 int ridesavingthrow
= 0;
131 int spcsavingthrow
= 0;
134 if (opelride(SEATBELT_SADDLE
)) {
136 if (bmwride(ART_RULES_MAKE_SENSE
)) spcsavingthrow
= 90;
137 if (bmwride(ART_CAR_SAFETY
) && u
.usteed
&& u
.usteed
->data
->msound
== MS_CAR
) spcsavingthrow
= 100;
140 if (!PlayerCannotUseSkills
) {
141 if (Race_if(PM_PERVERT
)) {
142 switch (P_SKILL(P_RIDING
)) {
143 case P_SKILLED
: ridesavingthrow
= 56; break;
144 case P_EXPERT
: ridesavingthrow
= 67; break;
145 case P_MASTER
: ridesavingthrow
= 89; break;
146 case P_GRAND_MASTER
: ridesavingthrow
= 96; break;
147 case P_SUPREME_MASTER
: ridesavingthrow
= 101; break;
150 switch (P_SKILL(P_RIDING
)) {
151 case P_SKILLED
: ridesavingthrow
= 11; break;
152 case P_EXPERT
: ridesavingthrow
= 34; break;
153 case P_MASTER
: ridesavingthrow
= 76; break;
154 case P_GRAND_MASTER
: ridesavingthrow
= 91; break;
155 case P_SUPREME_MASTER
: ridesavingthrow
= 101; break;
162 if (Role_if(PM_JOCKEY
)) ridesavingthrow
+= ((100 - ridesavingthrow
) / 2);
164 if ((ridesavingthrow
> 0) || (spcsavingthrow
> 0)) {
165 getlin ("Uh-oh! You're about to fall off your steed! Attempt a saving throw? [y/yes/no]",buf
);
167 if (!(strcmp (buf
, "yes")) || !(strcmp (buf
, "y")) || !(strcmp (buf
, "ye")) || !(strcmp (buf
, "ys"))) {
168 if ((ridesavingthrow
> rnd(100)) || (spcsavingthrow
> rnd(100)) ) {
169 pline("Success! You've managed to stay mounted.");
172 pline("Unfortunately your saving throw failed...");
182 /* it was SOOOOOOO annoying that a confused steed would always walk randomly, when a confused player would only be
183 * subjected to random-direction walking some of the time. Change that, and make it use riding skill. --Amy
184 * Returns TRUE if you will walk randomly, FALSE otherwise */
188 if (PlayerCannotUseSkills
) return rn2(Race_if(PM_PERVERT
) ? 2 : 4);
189 if (!Race_if(PM_PERVERT
)) {
190 switch (P_SKILL(P_RIDING
)) {
192 default: return rn2(4);
193 case P_BASIC
: return rn2(2);
194 case P_SKILLED
: return !rn2(3);
195 case P_EXPERT
: return !rn2(4);
196 case P_MASTER
: return !rn2(5);
197 case P_GRAND_MASTER
: return !rn2(7);
198 case P_SUPREME_MASTER
: return !rn2(10);
201 switch (P_SKILL(P_RIDING
)) {
202 default: return rn2(2);
203 case P_BASIC
: return !rn2(4);
204 case P_SKILLED
: return !rn2(6);
205 case P_EXPERT
: return !rn2(10);
206 case P_MASTER
: return !rn2(15);
207 case P_GRAND_MASTER
: return !rn2(25);
208 case P_SUPREME_MASTER
: return !rn2(50);
219 struct permonst
*ptr
;
224 /* Can you use it? */
225 if (nohands(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) ) {
226 You("have no hands!"); /* not `body_part(HAND)' */
227 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
229 if (yn("Try to use the saddle with another part of your body instead?") == 'y') {
230 if (rn2(3) && !polyskillchance()) {
231 make_blinded(Blinded
+ rnd(50),TRUE
);
232 pline("You got something in your face!");
233 if (!rn2(20)) badeffect();
234 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
240 } else if (!freehandX()) {
241 You("have no free %s.", body_part(HAND
));
242 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
246 /* Select an animal */
247 if (u
.uswallow
|| Underwater
|| !getdir((char *)0)) {
248 pline("%s", Never_mind
);
249 if (FailureEffects
|| u
.uprops
[FAILURE_EFFECTS
].extrinsic
|| have_failurestone()) {
250 pline("Oh wait, actually I do mind...");
255 if (!u
.dx
&& !u
.dy
) {
256 pline("Saddle yourself? Very funny...");
259 if (!isok(u
.ux
+u
.dx
, u
.uy
+u
.dy
) ||
260 !(mtmp
= m_at(u
.ux
+u
.dx
, u
.uy
+u
.dy
)) ||
262 pline("I see nobody there.");
266 /* Is this a valid monster? */
267 if (mtmp
->misc_worn_check
& W_SADDLE
||
268 which_armor(mtmp
, W_SADDLE
)) {
269 pline("%s doesn't need another one.", Monnam(mtmp
));
273 if (touch_petrifies(ptr
) && (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) )) {
274 static char kbuf
[BUFSZ
];
276 You("touch %s.", mon_nam(mtmp
));
277 if (!(poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))) {
278 sprintf(kbuf
, "attempting to saddle a petrifying monster");
282 if (ptr
== &mons
[PM_INCUBUS
] || ptr
== &mons
[PM_SUCCUBUS
]) {
283 pline("Shame on you!");
284 exercise(A_WIS
, FALSE
);
285 /*return 1;*/ /* removed that stupid restriction --Amy */
287 if (mtmp
->isminion
|| mtmp
->isshk
|| mtmp
->ispriest
||
288 mtmp
->isgd
|| mtmp
->iswiz
) {
289 pline("I think %s would mind.", mon_nam(mtmp
));
292 if (!can_saddle(mtmp
)) {
293 if (!issoviet
) You_cant("saddle such a creature.");
294 else pline("Ublyudka, kotoryy nazyvayet sebya sovetskiy ne khochet, chtoby vy yezdit' eto sushchestvo.");
298 /* Calculate your chance */
299 chance
= ACURR(A_DEX
) + ACURR(A_CHA
)/2 + 2*mtmp
->mtame
;
300 chance
+= GushLevel
* (mtmp
->mtame
? 20 : 5);
301 if (!mtmp
->mtame
) { /* humpers and steed egotypes should be easier... --Amy */
303 if (mtmp
->egotype_steed
|| canalwaysride(mtmp
->data
) || ((mercedesride(ART_GRAND_THEFT_AUTO
, mtmp
)) && (mtmp
->data
->msound
== MS_CAR
) ) || ((mercedesride(ART_UTTER_USELESSNESS
, mtmp
)) && (mtmp
->data
->msound
== MS_FART_NORMAL
|| mtmp
->data
->msound
== MS_FART_QUIET
|| mtmp
->data
->msound
== MS_FART_LOUD
|| mtmp
->data
->msound
== MS_STENCH
|| mtmp
->data
->msound
== MS_SUPERMAN
) ) ) {
304 if (mtmp
->mpeaceful
) chance
-= mtmp
->m_lev
;
305 else chance
-= 2*mtmp
->m_lev
;
307 if (mtmp
->mpeaceful
) chance
-= 5*mtmp
->m_lev
;
308 else chance
-= 10*mtmp
->m_lev
;
312 if (Role_if(PM_KNIGHT
) || Role_if(PM_CHEVALIER
))
314 if (Role_if(PM_JOCKEY
))
316 if (Role_if(PM_TRANSVESTITE
) || Role_if(PM_TOPMODEL
))
319 if (FemtrapActiveSabrina
&& mtmp
->data
== &mons
[PM_SABRINA_S_PLATEAU_BOOT
]) {
323 if (otmp
&& otmp
->otyp
== INKA_SADDLE
) chance
+= 100;
325 if (PlayerCannotUseSkills
) chance
-= 20;
328 switch (P_SKILL(P_RIDING
)) {
342 chance
+= 100; break;
343 case P_SUPREME_MASTER
:
344 chance
+= 150; break;
349 if ( (Confusion
&& !Conf_resist
) || Fumbling
|| IsGlib
)
351 /*else */if (uarmg
&&
352 (s
= OBJ_DESCR(objects
[uarmg
->otyp
])) != (char *)0 &&
353 ( !strcmp(s
, "riding gloves") || !strcmp(s
, "yezda perchatki") || !strcmp(s
, "kopgina qo'lqop") ) )
354 /* Bonus for wearing "riding" (but not fumbling) gloves */
356 /*else */if (uarmf
&&
357 (s
= OBJ_DESCR(objects
[uarmf
->otyp
])) != (char *)0 &&
358 ( !strcmp(s
, "riding boots") || !strcmp(s
, "sapogi dlya verkhovoy yezdy") || !strcmp(s
, "kopgina chizilmasin") ) )
359 /* ... or for "riding boots" */
360 chance
+= 10; /* Amy edit: allowed those bonuses to stack. */
361 if (otmp
->cursed
&& otmp
->otyp
== LEATHER_SADDLE
)
364 /* Make the attempt */
365 if (rn2(100) < chance
) {
366 You("put the saddle on %s.", mon_nam(mtmp
));
367 if (otmp
&& otmp
->oartifact
== ART_SADDLE_OF_REFLECTION
) {
368 You("reflect upon your life choices when applying the saddle.");
369 adjattrib(A_WIS
, -1, FALSE
, TRUE
);
371 if (otmp
->owornmask
) remove_worn_item(otmp
, FALSE
);
373 /* mpickobj may free otmp it if merges, but we have already
374 checked for a saddle above, so no merger should happen */
375 (void) mpickobj(mtmp
, otmp
, FALSE
);
376 mtmp
->misc_worn_check
|= W_SADDLE
;
377 otmp
->owornmask
= W_SADDLE
;
378 otmp
->leashmon
= mtmp
->m_id
;
379 update_mon_intrinsics(mtmp
, otmp
, TRUE
, FALSE
);
381 pline("%s resists!", Monnam(mtmp
));
386 /*** Riding the monster ***/
388 /* Can we ride this monster? Caller should also check can_saddle() */
393 if (!issoviet
) return (mtmp
->mtame
|| mtmp
->egotype_steed
|| (FemtrapActiveLarissa
&& mtmp
->data
->msound
== MS_SHOE
) || canalwaysride(mtmp
->data
) || ((mercedesride(ART_GRAND_THEFT_AUTO
, mtmp
)) && (mtmp
->data
->msound
== MS_CAR
) ) || ((mercedesride(ART_UTTER_USELESSNESS
, mtmp
)) && (mtmp
->data
->msound
== MS_FART_NORMAL
|| mtmp
->data
->msound
== MS_FART_QUIET
|| mtmp
->data
->msound
== MS_FART_LOUD
|| mtmp
->data
->msound
== MS_STENCH
|| mtmp
->data
->msound
== MS_SUPERMAN
) ) || (Race_if(PM_SHOE
) && mtmp
->data
->msound
== MS_SHOE
) );
395 return ((mtmp
->mtame
|| mtmp
->egotype_steed
|| (FemtrapActiveLarissa
&& mtmp
->data
->msound
== MS_SHOE
) || canalwaysride(mtmp
->data
) || ((mercedesride(ART_GRAND_THEFT_AUTO
, mtmp
)) && (mtmp
->data
->msound
== MS_CAR
) ) || ((mercedesride(ART_UTTER_USELESSNESS
, mtmp
)) && (mtmp
->data
->msound
== MS_FART_NORMAL
|| mtmp
->data
->msound
== MS_FART_QUIET
|| mtmp
->data
->msound
== MS_FART_LOUD
|| mtmp
->data
->msound
== MS_STENCH
|| mtmp
->data
->msound
== MS_SUPERMAN
) ) || (Race_if(PM_SHOE
) && mtmp
->data
->msound
== MS_SHOE
)) && humanoid(youmonst
.data
) &&
396 !verysmall(youmonst
.data
) && !bigmonst(youmonst
.data
) &&
397 (!Underwater
|| is_swimmer(mtmp
->data
)) );
400 /* Removed a lot of annoying restrictions that don't serve any purpose anyway other than annoying the player. --Amy */
401 /* In Soviet Russia, you cannot ride freely because seriously, the player isn't supposed to be able to ride. --Amy */
406 boolean forcemount
= FALSE
;
409 dismount_steed(DISMOUNT_BYCHOICE
);
410 else if (getdir((char *)0) && isok(u
.ux
+u
.dx
, u
.uy
+u
.dy
)) {
412 if (wizard
&& yn("Force the mount to succeed?") == 'y')
415 return (mount_steed(m_at(u
.ux
+u
.dx
, u
.uy
+u
.dy
), forcemount
));
422 /* Start riding, with the given monster */
424 mount_steed(mtmp
, force
)
425 struct monst
*mtmp
; /* The animal */
426 boolean force
; /* Quietly force this animal */
430 struct permonst
*ptr
;
434 You("are already riding %s.", mon_nam(u
.usteed
));
438 /* Is the player in the right form? */
439 if (FunnyHallu
&& !force
) {
440 pline("Maybe you should find a designated driver.");
441 /*return (FALSE); well, if the horse is saddled, a hallucinating player should be able to ride it --Amy*/
443 /* While riding Wounded_legs refers to the steed's,
444 * not the hero's legs.
445 * That opens up a potential abuse where the player
446 * can mount a steed, then dismount immediately to
447 * heal leg damage, because leg damage is always
448 * healed upon dismount (Wounded_legs context switch).
449 * By preventing a hero with Wounded_legs from
450 * mounting a steed, the potential for abuse is
451 * minimized, if not eliminated altogether.
454 Your("%s are in no shape for riding.", makeplural(body_part(LEG
)));
456 if (force
&& wizard
&& yn("Heal your legs?") == 'y')
460 if (yn("But you can try to get on your steed anyway. Do it?") == 'y') {
462 losehp(rn1(10,20), "trying an illegal ride", KILLED_BY
);
463 pline("Ouch! You slip and hurt yourself a lot!");
465 pline("Due to your leg injury, you don't manage to swing yourself onto your steed.");
473 if (Upolyd
&& !Race_if(PM_TRANSFORMER
) && (!humanoid(youmonst
.data
) || verysmall(youmonst
.data
) ||
474 bigmonst(youmonst
.data
) || slithy(youmonst
.data
))) {
475 You("won't fit on a saddle.");
477 if (yn("But you can try to get on your steed anyway. Do it?") == 'y') {
478 if (rn2(3) && !polyskillchance()) { losehp(rn1(10,20), "trying an illegal ride", NO_KILLER_PREFIX
);
479 pline("Ouch! You slip and hurt yourself a lot!");
480 if (!rn2(20)) badeffect();
483 else {return(FALSE
);}
486 if(!force
&& (near_capacity() > SLT_ENCUMBER
)) {
487 You_cant("do that while carrying so much stuff.");
491 /* Can the player reach and see the monster? */
492 /* Amy edit: boah the vanilla code for that was really shitty... permamimics should be rideable :P */
493 if (!mtmp
|| (!force
&& !canspotmon(mtmp
))) {
494 pline("I see nobody there.");
497 if (u
.uswallow
|| u
.ustuck
|| u
.utrap
||
498 !test_move(u
.ux
, u
.uy
, mtmp
->mx
-u
.ux
, mtmp
->my
-u
.uy
, TEST_MOVE
)) {
499 if (!(u
.uswallow
|| u
.ustuck
|| u
.utrap
))
500 You("are unable to swing your %s over.", body_part(LEG
));
502 You("are stuck here for now.");
507 You("are unable to swing your %s over.", body_part(LEG
));
508 if (yn("But you can try to get on your steed anyway. Do it?") == 'y') {
510 losehp(rn1(10,20), "trying an illegal ride", NO_KILLER_PREFIX
);
511 pline("Ouch! You slip and hurt yourself a lot!");
519 /* Is this a valid monster? */
520 otmp
= which_armor(mtmp
, W_SADDLE
);
522 pline("%s is not saddled.", Monnam(mtmp
));
526 /* Amy edit: you should be able to ride a cockatrice as long as your body is sufficiently covered in clothing
527 * or also if you're highly skilled (making high riding skill more useful in the process) */
528 if (touch_petrifies(ptr
) && (PlayerCannotUseSkills
|| (P_SKILL(P_RIDING
) < P_EXPERT
)) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && !(uarmg
&& !FingerlessGloves
&& uarmu
&& uarm
&& uarmc
) ) {
529 static char kbuf
[BUFSZ
];
531 You("touch %s.", mon_nam(mtmp
));
532 sprintf(kbuf
, "attempting to ride a petrifying monster");
535 if (!(mtmp
->mtame
|| mtmp
->egotype_steed
|| (FemtrapActiveLarissa
&& mtmp
->data
->msound
== MS_SHOE
) || canalwaysride(mtmp
->data
) || ((mercedesride(ART_GRAND_THEFT_AUTO
, mtmp
)) && (mtmp
->data
->msound
== MS_CAR
) ) || ((mercedesride(ART_UTTER_USELESSNESS
, mtmp
)) && (mtmp
->data
->msound
== MS_FART_NORMAL
|| mtmp
->data
->msound
== MS_FART_QUIET
|| mtmp
->data
->msound
== MS_FART_LOUD
|| mtmp
->data
->msound
== MS_STENCH
|| mtmp
->data
->msound
== MS_SUPERMAN
) ) || (Race_if(PM_SHOE
) && mtmp
->data
->msound
== MS_SHOE
)) || mtmp
->isminion
) {
536 pline("I think %s would mind.", mon_nam(mtmp
));
539 if (mtmp
->mtrapped
) {
540 struct trap
*t
= t_at(mtmp
->mx
, mtmp
->my
);
542 You_cant("mount %s while %s's trapped in %s.",
543 mon_nam(mtmp
), mhe(mtmp
),
544 an(defsyms
[trap_to_defsym(t
->ttyp
)].explanation
));
548 if (!force
&& !(otmp
&& otmp
->otyp
== INKA_SADDLE
) && !(FemtrapActiveSabrina
&& mtmp
->data
== &mons
[PM_SABRINA_S_PLATEAU_BOOT
]) && !(Role_if(PM_JOCKEY
) && !rn2(5)) && !(uwep
&& uwep
->oartifact
== ART_DARK_CLAYMORE
) && !Role_if(PM_KNIGHT
) && !Role_if(PM_CHEVALIER
) && mtmp
->mtame
&& !(--mtmp
->mtame
)) {
550 newsym(mtmp
->mx
, mtmp
->my
);
551 pline("%s resists%s!", Monnam(mtmp
),
552 mtmp
->mleashed
? " and its leash comes off" : "");
553 if (mtmp
->mleashed
) m_unleash(mtmp
, FALSE
);
556 if (!force
&& Underwater
&& !is_swimmer(ptr
)) {
557 You_cant("ride that creature while under water.");
560 if (!can_saddle(mtmp
) || !can_ride(mtmp
)) {
561 if (!issoviet
) You_cant("ride such a creature.");
562 else pline("Ublyudka, kotoryy nazyvayet sebya sovetskiy ne khochet, chtoby vy yezdit' eto sushchestvo.");
566 /* Is the player impaired? */
567 if (!force
&& !is_floater(ptr
) && !is_flyer(ptr
) &&
568 Levitation
&& !Lev_at_will
) {
569 You("cannot reach %s.", mon_nam(mtmp
));
572 if (!force
&& !(otmp
&& otmp
->otyp
== INKA_SADDLE
) && uarm
&& is_metallic(uarm
) &&
573 greatest_erosionX(uarm
)) {
574 Your("%s armor is too stiff to be able to mount %s.",
575 uarm
->oeroded
? "rusty" : "corroded",
579 if (!force
&& !(otmp
&& otmp
->otyp
== INKA_SADDLE
) && ((Confusion
&& !Conf_resist
&& rn2(3)) || (Fumbling
&& rn2(4)) || (IsGlib
&& rn2(2)) || (Wounded_legs
&& rn2(3)) ||
580 otmp
->cursed
|| (GushLevel
+mtmp
->mtame
< rnd(MAXULEV
/2+5) && ( (!Role_if(PM_KNIGHT
) || !rn2(5)) && (!Role_if(PM_CHEVALIER
) || !rn2(5)) && (!Role_if(PM_JOCKEY
) || !rn2(5)) && (!Role_if(PM_YEOMAN
) || !rn2(5)) && ((!Role_if(PM_TRANSVESTITE
) && !Role_if(PM_TOPMODEL
)) || !rn2(5)) ) ) )) {
582 pline("%s slips away from you.", Monnam(mtmp
));
585 You("slip while trying to get on %s.", mon_nam(mtmp
));
587 sprintf(buf
, "slipped while mounting a monster (%s)",
588 /* "a saddled mumak" or "a saddled pony called Dobbin" */
589 x_monnam(mtmp
, ARTICLE_A
, (char *)0,
590 SUPPRESS_IT
|SUPPRESS_INVISIBLE
|SUPPRESS_HALLUCINATION
,
592 losehp(rn1(5,10), buf
, NO_KILLER_PREFIX
);
598 if (Levitation
&& !is_floater(ptr
) && !is_flyer(ptr
))
599 /* Must have Lev_at_will at this point */
600 pline("%s magically floats up!", Monnam(mtmp
));
601 You("mount %s.", mon_nam(mtmp
));
603 if (nogoodsteed(mtmp
)) pline("This creature is too weak to carry you.");
604 else if (dedicatedsteed(mtmp
)) You_feel("comfortable.");
606 if (otmp
&& otmp
->oartifact
== ART_SADDLE_OF_REFLECTION
) {
607 You("reflect upon your life choices when climbing the saddle.");
608 adjattrib(A_WIS
, -1, FALSE
, TRUE
);
612 /* setuwep handles polearms differently when you're mounted */
613 if (uwep
&& is_applypole(uwep
)) unweapon
= FALSE
;
615 remove_monster(mtmp
->mx
, mtmp
->my
);
616 teleds(mtmp
->mx
, mtmp
->my
, TRUE
);
621 /* You and your steed have moved */
628 /* It takes many turns of riding to exercise skill */
629 /* but not THAT godawfully many - used to be 100, now it's 33 --Amy */
630 if (u
.urideturns
++ >= 33) {
632 use_skill(P_RIDING
, 1);
638 * Try to find a dismount point adjacent to the steed's location.
639 * If all else fails, try enexto(). Use enexto() as a last resort because
640 * enexto() chooses its point randomly, possibly even outside the
641 * room's walls, which is not what we want.
642 * Adapted from mail daemon code.
645 landing_spot(spot
, reason
, forceit
)
646 coord
*spot
; /* landing position (we fill it in) */
650 int i
= 0, x
, y
, distance
, min_distance
= -1;
651 boolean found
= FALSE
;
654 /* avoid known traps (i == 0) and boulders, but allow them as a backup */
655 if (reason
!= DISMOUNT_BYCHOICE
|| Stunned
|| Numbed
|| Feared
|| Confusion
|| Fumbling
) i
= 1;
656 for (; !found
&& i
< 2; ++i
) {
657 for (x
= u
.ux
-1; x
<= u
.ux
+1; x
++)
658 for (y
= u
.uy
-1; y
<= u
.uy
+1; y
++) {
659 if (!isok(x
, y
) || (x
== u
.ux
&& y
== u
.uy
)) continue;
661 if (ACCESSIBLE(levl
[x
][y
].typ
) &&
662 !MON_AT(x
,y
) && !closed_door(x
,y
)) {
663 distance
= distu(x
,y
);
664 if (min_distance
< 0 || distance
< min_distance
||
665 (distance
== min_distance
&& rn2(2))) {
666 if (i
> 0 || (((t
= t_at(x
, y
)) == 0 || !t
->tseen
) &&
667 (!sobj_at(BOULDER
, x
, y
) ||
668 throws_rocks(youmonst
.data
) || (uarmg
&& uarmg
->oartifact
== ART_MOUNTAIN_FISTS
) ))) {
671 min_distance
= distance
;
679 /* If we didn't find a good spot and forceit is on, try enexto(). */
680 if (forceit
&& min_distance
< 0 &&
681 !enexto(spot
, u
.ux
, u
.uy
, youmonst
.data
))
687 /* The player kicks or whips the steed */
696 /* [ALI] Various effects of kicking sleeping/paralyzed steeds */
697 if (u
.usteed
->msleeping
|| !u
.usteed
->mcanmove
) {
698 /* We assume a message has just been output of the form
699 * "You kick <steed>."
701 strcpy(He
, mhe(u
.usteed
));
703 if ((u
.usteed
->mcanmove
|| u
.usteed
->mfrozen
) && !rn2(2)) {
704 if (u
.usteed
->mcanmove
)
705 u
.usteed
->msleeping
= 0;
706 else if (u
.usteed
->mfrozen
> 2)
707 u
.usteed
->mfrozen
-= 2;
709 u
.usteed
->mfrozen
= 0;
710 u
.usteed
->mcanmove
= 1;
711 u
.usteed
->masleep
= 0;
713 if (u
.usteed
->msleeping
|| !u
.usteed
->mcanmove
)
714 pline("%s stirs.", He
);
716 pline("%s rouses %sself!", He
, mhim(u
.usteed
));
718 pline("%s does not respond.", He
);
722 /* Make the steed less tame and check if it resists */
723 if (u
.usteed
->mtame
&& (!Role_if(PM_JOCKEY
) || !rn2(3)) ) u
.usteed
->mtame
--;
724 if (!u
.usteed
->mtame
&& u
.usteed
->mleashed
) m_unleash(u
.usteed
, TRUE
);
725 if (!u
.usteed
->mtame
|| (u
.ulevel
+u
.usteed
->mtame
< rnd(MAXULEV
/2+5))) {
727 if (!mayfalloffsteed()) {
728 newsym(u
.usteed
->mx
, u
.usteed
->my
);
729 dismount_steed(DISMOUNT_THROWN
);
734 pline("%s gallops!", Monnam(u
.usteed
));
735 /* here's another thing that should IMHO be better if you have more skill; in vanilla, high riding skill is
736 * borderline useless, but I decided that high skill will make your horse gallop for a loooooong time --Amy */
738 gallopamount
= rn1(20, 30);
739 if (!PlayerCannotUseSkills
) {
740 switch (P_SKILL(P_RIDING
)) {
741 case P_SKILLED
: gallopamount
*= 2; break;
742 case P_EXPERT
: gallopamount
*= 4; break;
743 case P_MASTER
: gallopamount
*= 6; break;
744 case P_GRAND_MASTER
: gallopamount
*= 8; break;
745 case P_SUPREME_MASTER
: gallopamount
*= 10; break;
748 if (uarmf
&& uarmf
->oartifact
== ART_ARVOGENIA_S_BIKER_HEELS
) gallopamount
*= 2;
750 u
.ugallop
+= gallopamount
;
754 /* Stop riding the current steed */
756 dismount_steed(reason
)
757 int reason
; /* Player was thrown off etc. */
762 const char *verb
= "fall";
763 boolean repair_leg_damage
= TRUE
;
764 unsigned save_utrap
= u
.utrap
;
765 boolean have_spot
= landing_spot(&cc
,reason
,0);
766 register struct trap
*ttmp
;
768 mtmp
= u
.usteed
; /* make a copy of steed pointer */
770 if (!mtmp
) /* Just return silently */
773 /* Check the reason for dismounting */
774 otmp
= which_armor(mtmp
, W_SADDLE
);
776 case DISMOUNT_THROWN
:
779 You("%s off of %s!", verb
, mon_nam(mtmp
));
780 if (!have_spot
) have_spot
= landing_spot(&cc
,reason
,1);
781 losehp(rn1(10,10), "riding accident", KILLED_BY_AN
);
782 set_wounded_legs(BOTH_SIDES
, HWounded_legs
+ (int)HWounded_legs
+ rn1(5,5));
783 repair_leg_damage
= FALSE
;
786 You("can no longer ride %s.", mon_nam(u
.usteed
));
787 if (!have_spot
) have_spot
= landing_spot(&cc
,reason
,1);
789 case DISMOUNT_ENGULFED
:
790 /* caller displays message */
793 /* hero has just died... */
795 case DISMOUNT_GENERIC
:
796 /* no messages, just make it so */
798 case DISMOUNT_BYCHOICE
:
800 if (u
.utrap
&& (ttmp
= t_at(u
.ux
, u
.uy
)) && ttmp
&& ttmp
->ttyp
== FARTING_WEB
) {
801 You("can't escape from the farting web.");
804 if (otmp
&& otmp
->cursed
) {
805 You("can't. The saddle %s cursed.",
806 otmp
->bknown
? "is" : "seems to be");
811 You("can't. There isn't anywhere for you to stand.");
814 if (!mtmp
->mnamelth
) {
815 pline("You've been through the dungeon on %s with no name.",
816 an(mtmp
->data
->mname
));
818 pline("It felt good to get out of the rain.");
820 You("dismount %s.", mon_nam(mtmp
));
822 if (otmp
&& otmp
->otyp
== INKA_SADDLE
) {
823 pline("The inka saddle tries unsuccessfully to prevent you from getting off your steed, and rips off your skin in the process...");
824 pline("You and your steed are severely hurt!");
825 losehp(rnd(u
.ulevel
* 5), "inka saddle", KILLED_BY_AN
);
826 if (mtmp
&& mtmp
->mhp
> 1) mtmp
->mhp
/= 2;
829 /* While riding these refer to the steed's legs
830 * so after dismounting they refer to the player's
833 if (repair_leg_damage
) HWounded_legs
= 0;
835 /* Release the steed and saddle */
839 /* Set player and steed's position. Try moving the player first
840 unless we're in the midst of creating a bones file. */
841 if (reason
== DISMOUNT_BONES
) {
842 /* move the steed to an adjacent square */
843 if (enexto(&cc
, u
.ux
, u
.uy
, mtmp
->data
))
844 rloc_to(mtmp
, cc
.x
, cc
.y
);
845 else /* evidently no room nearby; move steed elsewhere */
846 (void) rloc(mtmp
, FALSE
);
849 if (!DEADMONSTER(mtmp
)) {
850 place_monster(mtmp
, u
.ux
, u
.uy
);
851 if (!u
.uswallow
&& !u
.ustuck
&& have_spot
) {
852 struct permonst
*mdat
= mtmp
->data
;
854 /* The steed may drop into water/lava */
855 if (!is_flyer(mdat
) && (!mtmp
->egotype_flying
) && !is_floater(mdat
) && !is_clinger(mdat
)) {
856 if (is_waterypool(u
.ux
, u
.uy
) || is_watertunnel(u
.ux
, u
.uy
)) {
858 pline("%s falls into the %s!", Monnam(mtmp
),
859 surface(u
.ux
, u
.uy
));
860 if (!is_swimmer(mdat
) && !mtmp
->egotype_watersplasher
&& !amphibious(mdat
)) {
864 } else if (is_lava(u
.ux
, u
.uy
)) {
865 pline("%s is pulled into the lava!", Monnam(mtmp
));
866 if (!likes_lava(mdat
)) {
872 /* Steed dismounting consists of two steps: being moved to another
873 * square, and descending to the floor. We have functions to do
874 * each of these activities, but they're normally called
875 * individually and include an attempt to look at or pick up the
876 * objects on the floor:
877 * teleds() --> spoteffects() --> pickup()
878 * float_down() --> pickup()
879 * We use this kludge to make sure there is only one such attempt.
881 * Clearly this is not the best way to do it. A full fix would
882 * involve having these functions not call pickup() at all, instead
883 * calling them first and calling pickup() afterwards. But it
884 * would take a lot of work to keep this change from having any
885 * unforseen side effects (for instance, you would no longer be
886 * able to walk onto a square with a hole, and autopickup before
887 * falling into the hole).
889 /* [ALI] No need to move the player if the steed died. */
890 if (!DEADMONSTER(mtmp
)) {
891 /* Keep steed here, move the player to cc;
892 * teleds() clears u.utrap
894 in_steed_dismounting
= TRUE
;
895 teleds(cc
.x
, cc
.y
, TRUE
);
896 in_steed_dismounting
= FALSE
;
898 /* Put your steed in your trap */
900 (void) mintrap(mtmp
);
902 /* Couldn't... try placing the steed */
903 } else if (enexto(&cc
, u
.ux
, u
.uy
, mtmp
->data
)) {
904 /* Keep player here, move the steed to cc */
905 rloc_to(mtmp
, cc
.x
, cc
.y
);
906 /* Player stays put */
907 /* Otherwise, kill the steed */
914 /* Return the player to the floor */
915 if (reason
!= DISMOUNT_ENGULFED
) {
916 in_steed_dismounting
= TRUE
;
917 (void) float_down(0L, W_SADDLE
);
918 in_steed_dismounting
= FALSE
;
920 (void)encumber_msg();
921 vision_full_recalc
= 1;
924 /* polearms behave differently when not mounted */
925 if (uwep
&& is_pole(uwep
)) unweapon
= TRUE
;
930 place_monster(mon
, x
, y
)
935 impossible("place_monster: no monster?");
938 if (mon
&& mon
== u
.usteed
||
939 /* special case is for convoluted vault guard handling */
940 (DEADMONSTER(mon
) && !(mon
->isgd
&& x
== 0 && y
== 0))) {
941 /*impossible("placing bugged monster onto map?");*/
944 mon
->mx
= x
, mon
->my
= y
;
945 level
.monsters
[x
][y
] = mon
;
948 /* will something hit your steed instead of you? --Amy */
952 /* if your steed is low on health, attacks should be redirected to it much less often, otherwise they die constantly */
953 if (u
.usteed
&& (u
.usteed
->mhp
< 5 || (u
.usteed
->mhp
<= (u
.usteed
->mhpmax
/ 5) ) ) && rn2(5)) return FALSE
;
957 if (bmwride(ART_NO_DAMAGE
)) return FALSE
;
961 if (rn2(100) < u
.steedhitchance
) return TRUE
;
965 /* does your steed have the saddle that lets you fly? --Amy */
971 if (bmwride(ART_CLOWN_CAR
)) return TRUE
;