OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / steed.c
1 /* NetHack 3.6  steed.c $NHDT-Date: 1445906867 2015/10/27 00:47:47 $  $NHDT-Branch: master $:$NHDT-Revision: 1.47 $ */
2 /* Copyright (c) Kevin Hugo, 1998-1999. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 /* Monsters that might be ridden */
8 static NEARDATA const char steeds[] = { S_QUADRUPED, S_UNICORN, S_ANGEL,
9                                         S_CENTAUR,   S_DRAGON,  S_JABBERWOCK,
10                                         '\0' };
11
12 STATIC_DCL boolean FDECL(landing_spot, (coord *, int, int));
13 STATIC_DCL void FDECL(maybewakesteed, (struct monst *));
14
15 /* caller has decided that hero can't reach something while mounted */
16 void
17 rider_cant_reach()
18 {
19     You("aren't skilled enough to reach from %s.", y_monnam(u.usteed));
20 }
21
22 /*** Putting the saddle on ***/
23
24 /* Can this monster wear a saddle? */
25 boolean
26 can_saddle(mtmp)
27 struct monst *mtmp;
28 {
29     struct permonst *ptr = mtmp->data;
30
31     return (index(steeds, ptr->mlet) && (ptr->msize >= MZ_MEDIUM)
32             && (!humanoid(ptr) || ptr->mlet == S_CENTAUR) && !amorphous(ptr)
33             && !noncorporeal(ptr) && !is_whirly(ptr) && !unsolid(ptr));
34 }
35
36 int
37 use_saddle(otmp)
38 struct obj *otmp;
39 {
40     struct monst *mtmp;
41     struct permonst *ptr;
42     int chance;
43     const char *s;
44
45     if (!u_handsy())
46         return 0;
47
48     /* Select an animal */
49     if (u.uswallow || Underwater || !getdir((char *) 0)) {
50         pline1(Never_mind);
51         return 0;
52     }
53     if (!u.dx && !u.dy) {
54         pline("Saddle yourself?  Very funny...");
55         return 0;
56     }
57     if (!isok(u.ux + u.dx, u.uy + u.dy)
58         || !(mtmp = m_at(u.ux + u.dx, u.uy + u.dy)) || !canspotmon(mtmp)) {
59         pline("I see nobody there.");
60         return 1;
61     }
62
63     /* Is this a valid monster? */
64     if (mtmp->misc_worn_check & W_SADDLE || which_armor(mtmp, W_SADDLE)) {
65         pline("%s doesn't need another one.", Monnam(mtmp));
66         return 1;
67     }
68     ptr = mtmp->data;
69     if (touch_petrifies(ptr) && !uarmg && !Stone_resistance) {
70         char kbuf[BUFSZ];
71
72         You("touch %s.", mon_nam(mtmp));
73         if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
74             Sprintf(kbuf, "attempting to saddle %s", an(mtmp->data->mname));
75             instapetrify(kbuf);
76         }
77     }
78     if (ptr == &mons[PM_INCUBUS] || ptr == &mons[PM_SUCCUBUS]) {
79         pline("Shame on you!");
80         exercise(A_WIS, FALSE);
81         return 1;
82     }
83     if (mtmp->isminion || mtmp->isshk || mtmp->ispriest || mtmp->isgd
84         || mtmp->iswiz) {
85         pline("I think %s would mind.", mon_nam(mtmp));
86         return 1;
87     }
88     if (!can_saddle(mtmp)) {
89         You_cant("saddle such a creature.");
90         return 1;
91     }
92
93     /* Calculate your chance */
94     chance = ACURR(A_DEX) + ACURR(A_CHA) / 2 + 2 * mtmp->mtame;
95     chance += u.ulevel * (mtmp->mtame ? 20 : 5);
96     if (!mtmp->mtame)
97         chance -= 10 * mtmp->m_lev;
98     if (Role_if(PM_KNIGHT))
99         chance += 20;
100     switch (P_SKILL(P_RIDING)) {
101     case P_ISRESTRICTED:
102     case P_UNSKILLED:
103     default:
104         chance -= 20;
105         break;
106     case P_BASIC:
107         break;
108     case P_SKILLED:
109         chance += 15;
110         break;
111     case P_EXPERT:
112         chance += 30;
113         break;
114     }
115     if (Confusion || Fumbling || Glib)
116         chance -= 20;
117     else if (uarmg && (s = OBJ_DESCR(objects[uarmg->otyp])) != (char *) 0
118              && !strncmp(s, "riding ", 7))
119         /* Bonus for wearing "riding" (but not fumbling) gloves */
120         chance += 10;
121     else if (uarmf && (s = OBJ_DESCR(objects[uarmf->otyp])) != (char *) 0
122              && !strncmp(s, "riding ", 7))
123         /* ... or for "riding boots" */
124         chance += 10;
125     if (otmp->cursed)
126         chance -= 50;
127
128     /* [intended] steed becomes alert if possible */
129     maybewakesteed(mtmp);
130
131     /* Make the attempt */
132     if (rn2(100) < chance) {
133         You("put the saddle on %s.", mon_nam(mtmp));
134         if (otmp->owornmask)
135             remove_worn_item(otmp, FALSE);
136         freeinv(otmp);
137         /* mpickobj may free otmp it if merges, but we have already
138            checked for a saddle above, so no merger should happen */
139         (void) mpickobj(mtmp, otmp);
140         mtmp->misc_worn_check |= W_SADDLE;
141         otmp->owornmask = W_SADDLE;
142         otmp->leashmon = mtmp->m_id;
143         update_mon_intrinsics(mtmp, otmp, TRUE, FALSE);
144     } else
145         pline("%s resists!", Monnam(mtmp));
146     return 1;
147 }
148
149 /*** Riding the monster ***/
150
151 /* Can we ride this monster?  Caller should also check can_saddle() */
152 boolean
153 can_ride(mtmp)
154 struct monst *mtmp;
155 {
156     return (mtmp->mtame && humanoid(youmonst.data)
157             && !verysmall(youmonst.data) && !bigmonst(youmonst.data)
158             && (!Underwater || is_swimmer(mtmp->data)));
159 }
160
161 int
162 doride()
163 {
164     boolean forcemount = FALSE;
165
166     if (u.usteed) {
167         dismount_steed(DISMOUNT_BYCHOICE);
168     } else if (getdir((char *) 0) && isok(u.ux + u.dx, u.uy + u.dy)) {
169         if (wizard && yn("Force the mount to succeed?") == 'y')
170             forcemount = TRUE;
171         return (mount_steed(m_at(u.ux + u.dx, u.uy + u.dy), forcemount));
172     } else {
173         return 0;
174     }
175     return 1;
176 }
177
178 /* Start riding, with the given monster */
179 boolean
180 mount_steed(mtmp, force)
181 struct monst *mtmp; /* The animal */
182 boolean force;      /* Quietly force this animal */
183 {
184     struct obj *otmp;
185     char buf[BUFSZ];
186     struct permonst *ptr;
187
188     /* Sanity checks */
189     if (u.usteed) {
190         You("are already riding %s.", mon_nam(u.usteed));
191         return (FALSE);
192     }
193
194     /* Is the player in the right form? */
195     if (Hallucination && !force) {
196         pline("Maybe you should find a designated driver.");
197         return (FALSE);
198     }
199     /* While riding Wounded_legs refers to the steed's,
200      * not the hero's legs.
201      * That opens up a potential abuse where the player
202      * can mount a steed, then dismount immediately to
203      * heal leg damage, because leg damage is always
204      * healed upon dismount (Wounded_legs context switch).
205      * By preventing a hero with Wounded_legs from
206      * mounting a steed, the potential for abuse is
207      * reduced.  However, dismounting still immediately
208      * heals the steed's wounded legs.  [In 3.4.3 and
209      * earlier, that unintentionally made the hero's
210      * temporary 1 point Dex loss become permanent.]
211      */
212     if (Wounded_legs) {
213         Your("%s are in no shape for riding.", makeplural(body_part(LEG)));
214         if (force && wizard && yn("Heal your legs?") == 'y')
215             HWounded_legs = EWounded_legs = 0;
216         else
217             return (FALSE);
218     }
219
220     if (Upolyd && (!humanoid(youmonst.data) || verysmall(youmonst.data)
221                    || bigmonst(youmonst.data) || slithy(youmonst.data))) {
222         You("won't fit on a saddle.");
223         return (FALSE);
224     }
225     if (!force && (near_capacity() > SLT_ENCUMBER)) {
226         You_cant("do that while carrying so much stuff.");
227         return (FALSE);
228     }
229
230     /* Can the player reach and see the monster? */
231     if (!mtmp || (!force && ((Blind && !Blind_telepat) || mtmp->mundetected
232                              || mtmp->m_ap_type == M_AP_FURNITURE
233                              || mtmp->m_ap_type == M_AP_OBJECT))) {
234         pline("I see nobody there.");
235         return (FALSE);
236     }
237     if (u.uswallow || u.ustuck || u.utrap || Punished
238         || !test_move(u.ux, u.uy, mtmp->mx - u.ux, mtmp->my - u.uy,
239                       TEST_MOVE)) {
240         if (Punished || !(u.uswallow || u.ustuck || u.utrap))
241             You("are unable to swing your %s over.", body_part(LEG));
242         else
243             You("are stuck here for now.");
244         return (FALSE);
245     }
246
247     /* Is this a valid monster? */
248     otmp = which_armor(mtmp, W_SADDLE);
249     if (!otmp) {
250         pline("%s is not saddled.", Monnam(mtmp));
251         return (FALSE);
252     }
253     ptr = mtmp->data;
254     if (touch_petrifies(ptr) && !Stone_resistance) {
255         char kbuf[BUFSZ];
256
257         You("touch %s.", mon_nam(mtmp));
258         Sprintf(kbuf, "attempting to ride %s", an(mtmp->data->mname));
259         instapetrify(kbuf);
260     }
261     if (!mtmp->mtame || mtmp->isminion) {
262         pline("I think %s would mind.", mon_nam(mtmp));
263         return (FALSE);
264     }
265     if (mtmp->mtrapped) {
266         struct trap *t = t_at(mtmp->mx, mtmp->my);
267
268         You_cant("mount %s while %s's trapped in %s.", mon_nam(mtmp),
269                  mhe(mtmp), an(defsyms[trap_to_defsym(t->ttyp)].explanation));
270         return (FALSE);
271     }
272
273     if (!force && !Role_if(PM_KNIGHT) && !(--mtmp->mtame)) {
274         /* no longer tame */
275         newsym(mtmp->mx, mtmp->my);
276         pline("%s resists%s!", Monnam(mtmp),
277               mtmp->mleashed ? " and its leash comes off" : "");
278         if (mtmp->mleashed)
279             m_unleash(mtmp, FALSE);
280         return (FALSE);
281     }
282     if (!force && Underwater && !is_swimmer(ptr)) {
283         You_cant("ride that creature while under water.");
284         return (FALSE);
285     }
286     if (!can_saddle(mtmp) || !can_ride(mtmp)) {
287         You_cant("ride such a creature.");
288         return (0);
289     }
290
291     /* Is the player impaired? */
292     if (!force && !is_floater(ptr) && !is_flyer(ptr) && Levitation
293         && !Lev_at_will) {
294         You("cannot reach %s.", mon_nam(mtmp));
295         return (FALSE);
296     }
297     if (!force && uarm && is_metallic(uarm) && greatest_erosion(uarm)) {
298         Your("%s armor is too stiff to be able to mount %s.",
299              uarm->oeroded ? "rusty" : "corroded", mon_nam(mtmp));
300         return (FALSE);
301     }
302     if (!force
303         && (Confusion || Fumbling || Glib || Wounded_legs || otmp->cursed
304             || (u.ulevel + mtmp->mtame < rnd(MAXULEV / 2 + 5)))) {
305         if (Levitation) {
306             pline("%s slips away from you.", Monnam(mtmp));
307             return FALSE;
308         }
309         You("slip while trying to get on %s.", mon_nam(mtmp));
310
311         Sprintf(buf, "slipped while mounting %s",
312                 /* "a saddled mumak" or "a saddled pony called Dobbin" */
313                 x_monnam(mtmp, ARTICLE_A, (char *) 0,
314                          SUPPRESS_IT | SUPPRESS_INVISIBLE
315                              | SUPPRESS_HALLUCINATION,
316                          TRUE));
317         losehp(Maybe_Half_Phys(rn1(5, 10)), buf, NO_KILLER_PREFIX);
318         return (FALSE);
319     }
320
321     /* Success */
322     maybewakesteed(mtmp);
323     if (!force) {
324         if (Levitation && !is_floater(ptr) && !is_flyer(ptr))
325             /* Must have Lev_at_will at this point */
326             pline("%s magically floats up!", Monnam(mtmp));
327         You("mount %s.", mon_nam(mtmp));
328     }
329     /* setuwep handles polearms differently when you're mounted */
330     if (uwep && is_pole(uwep))
331         unweapon = FALSE;
332     u.usteed = mtmp;
333     remove_monster(mtmp->mx, mtmp->my);
334     teleds(mtmp->mx, mtmp->my, TRUE);
335     return (TRUE);
336 }
337
338 /* You and your steed have moved */
339 void
340 exercise_steed()
341 {
342     if (!u.usteed)
343         return;
344
345     /* It takes many turns of riding to exercise skill */
346     if (u.urideturns++ >= 100) {
347         u.urideturns = 0;
348         use_skill(P_RIDING, 1);
349     }
350     return;
351 }
352
353 /* The player kicks or whips the steed */
354 void
355 kick_steed()
356 {
357     char He[4];
358     if (!u.usteed)
359         return;
360
361     /* [ALI] Various effects of kicking sleeping/paralyzed steeds */
362     if (u.usteed->msleeping || !u.usteed->mcanmove) {
363         /* We assume a message has just been output of the form
364          * "You kick <steed>."
365          */
366         Strcpy(He, mhe(u.usteed));
367         *He = highc(*He);
368         if ((u.usteed->mcanmove || u.usteed->mfrozen) && !rn2(2)) {
369             if (u.usteed->mcanmove)
370                 u.usteed->msleeping = 0;
371             else if (u.usteed->mfrozen > 2)
372                 u.usteed->mfrozen -= 2;
373             else {
374                 u.usteed->mfrozen = 0;
375                 u.usteed->mcanmove = 1;
376             }
377             if (u.usteed->msleeping || !u.usteed->mcanmove)
378                 pline("%s stirs.", He);
379             else
380                 pline("%s rouses %sself!", He, mhim(u.usteed));
381         } else
382             pline("%s does not respond.", He);
383         return;
384     }
385
386     /* Make the steed less tame and check if it resists */
387     if (u.usteed->mtame)
388         u.usteed->mtame--;
389     if (!u.usteed->mtame && u.usteed->mleashed)
390         m_unleash(u.usteed, TRUE);
391     if (!u.usteed->mtame
392         || (u.ulevel + u.usteed->mtame < rnd(MAXULEV / 2 + 5))) {
393         newsym(u.usteed->mx, u.usteed->my);
394         dismount_steed(DISMOUNT_THROWN);
395         return;
396     }
397
398     pline("%s gallops!", Monnam(u.usteed));
399     u.ugallop += rn1(20, 30);
400     return;
401 }
402
403 /*
404  * Try to find a dismount point adjacent to the steed's location.
405  * If all else fails, try enexto().  Use enexto() as a last resort because
406  * enexto() chooses its point randomly, possibly even outside the
407  * room's walls, which is not what we want.
408  * Adapted from mail daemon code.
409  */
410 STATIC_OVL boolean
411 landing_spot(spot, reason, forceit)
412 coord *spot; /* landing position (we fill it in) */
413 int reason;
414 int forceit;
415 {
416     int i = 0, x, y, distance, min_distance = -1;
417     boolean found = FALSE;
418     struct trap *t;
419
420     /* avoid known traps (i == 0) and boulders, but allow them as a backup */
421     if (reason != DISMOUNT_BYCHOICE || Stunned || Confusion || Fumbling)
422         i = 1;
423     for (; !found && i < 2; ++i) {
424         for (x = u.ux - 1; x <= u.ux + 1; x++)
425             for (y = u.uy - 1; y <= u.uy + 1; y++) {
426                 if (!isok(x, y) || (x == u.ux && y == u.uy))
427                     continue;
428
429                 if (accessible(x, y) && !MON_AT(x, y)) {
430                     distance = distu(x, y);
431                     if (min_distance < 0 || distance < min_distance
432                         || (distance == min_distance && rn2(2))) {
433                         if (i > 0 || (((t = t_at(x, y)) == 0 || !t->tseen)
434                                       && (!sobj_at(BOULDER, x, y)
435                                           || throws_rocks(youmonst.data)))) {
436                             spot->x = x;
437                             spot->y = y;
438                             min_distance = distance;
439                             found = TRUE;
440                         }
441                     }
442                 }
443             }
444     }
445
446     /* If we didn't find a good spot and forceit is on, try enexto(). */
447     if (forceit && min_distance < 0
448         && !enexto(spot, u.ux, u.uy, youmonst.data))
449         return FALSE;
450
451     return found;
452 }
453
454 /* Stop riding the current steed */
455 void
456 dismount_steed(reason)
457 int reason; /* Player was thrown off etc. */
458 {
459     struct monst *mtmp;
460     struct obj *otmp;
461     coord cc;
462     const char *verb = "fall";
463     boolean repair_leg_damage = (Wounded_legs != 0L);
464     unsigned save_utrap = u.utrap;
465     boolean have_spot = landing_spot(&cc, reason, 0);
466
467     mtmp = u.usteed; /* make a copy of steed pointer */
468     /* Sanity check */
469     if (!mtmp) /* Just return silently */
470         return;
471
472     /* Check the reason for dismounting */
473     otmp = which_armor(mtmp, W_SADDLE);
474     switch (reason) {
475     case DISMOUNT_THROWN:
476         verb = "are thrown";
477     case DISMOUNT_FELL:
478         You("%s off of %s!", verb, mon_nam(mtmp));
479         if (!have_spot)
480             have_spot = landing_spot(&cc, reason, 1);
481         losehp(Maybe_Half_Phys(rn1(10, 10)), "riding accident", KILLED_BY_AN);
482         set_wounded_legs(BOTH_SIDES, (int) HWounded_legs + rn1(5, 5));
483         repair_leg_damage = FALSE;
484         break;
485     case DISMOUNT_POLY:
486         You("can no longer ride %s.", mon_nam(u.usteed));
487         if (!have_spot)
488             have_spot = landing_spot(&cc, reason, 1);
489         break;
490     case DISMOUNT_ENGULFED:
491         /* caller displays message */
492         break;
493     case DISMOUNT_BONES:
494         /* hero has just died... */
495         break;
496     case DISMOUNT_GENERIC:
497         /* no messages, just make it so */
498         break;
499     case DISMOUNT_BYCHOICE:
500     default:
501         if (otmp && otmp->cursed) {
502             You("can't.  The saddle %s cursed.",
503                 otmp->bknown ? "is" : "seems to be");
504             otmp->bknown = TRUE;
505             return;
506         }
507         if (!have_spot) {
508             You("can't. There isn't anywhere for you to stand.");
509             return;
510         }
511         if (!has_mname(mtmp)) {
512             pline("You've been through the dungeon on %s with no name.",
513                   an(mtmp->data->mname));
514             if (Hallucination)
515                 pline("It felt good to get out of the rain.");
516         } else
517             You("dismount %s.", mon_nam(mtmp));
518     }
519     /* While riding, Wounded_legs refers to the steed's legs;
520        after dismounting, it reverts to the hero's legs. */
521     if (repair_leg_damage) {
522         /* [TODO: make heal_legs() take a parameter to handle this] */
523         in_steed_dismounting = TRUE;
524         heal_legs();
525         in_steed_dismounting = FALSE;
526     }
527
528     /* Release the steed and saddle */
529     u.usteed = 0;
530     u.ugallop = 0L;
531
532     /* Set player and steed's position.  Try moving the player first
533        unless we're in the midst of creating a bones file. */
534     if (reason == DISMOUNT_BONES) {
535         /* move the steed to an adjacent square */
536         if (enexto(&cc, u.ux, u.uy, mtmp->data))
537             rloc_to(mtmp, cc.x, cc.y);
538         else /* evidently no room nearby; move steed elsewhere */
539             (void) rloc(mtmp, FALSE);
540         return;
541     }
542     if (mtmp->mhp > 0) {
543         place_monster(mtmp, u.ux, u.uy);
544         if (!u.uswallow && !u.ustuck && have_spot) {
545             struct permonst *mdat = mtmp->data;
546
547             /* The steed may drop into water/lava */
548             if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) {
549                 if (is_pool(u.ux, u.uy)) {
550                     if (!Underwater)
551                         pline("%s falls into the %s!", Monnam(mtmp),
552                               surface(u.ux, u.uy));
553                     if (!is_swimmer(mdat) && !amphibious(mdat)) {
554                         killed(mtmp);
555                         adjalign(-1);
556                     }
557                 } else if (is_lava(u.ux, u.uy)) {
558                     pline("%s is pulled into the lava!", Monnam(mtmp));
559                     if (!likes_lava(mdat)) {
560                         killed(mtmp);
561                         adjalign(-1);
562                     }
563                 }
564             }
565             /* Steed dismounting consists of two steps: being moved to another
566              * square, and descending to the floor.  We have functions to do
567              * each of these activities, but they're normally called
568              * individually and include an attempt to look at or pick up the
569              * objects on the floor:
570              * teleds() --> spoteffects() --> pickup()
571              * float_down() --> pickup()
572              * We use this kludge to make sure there is only one such attempt.
573              *
574              * Clearly this is not the best way to do it.  A full fix would
575              * involve having these functions not call pickup() at all,
576              * instead
577              * calling them first and calling pickup() afterwards.  But it
578              * would take a lot of work to keep this change from having any
579              * unforeseen side effects (for instance, you would no longer be
580              * able to walk onto a square with a hole, and autopickup before
581              * falling into the hole).
582              */
583             /* [ALI] No need to move the player if the steed died. */
584             if (mtmp->mhp > 0) {
585                 /* Keep steed here, move the player to cc;
586                  * teleds() clears u.utrap
587                  */
588                 in_steed_dismounting = TRUE;
589                 teleds(cc.x, cc.y, TRUE);
590                 in_steed_dismounting = FALSE;
591
592                 /* Put your steed in your trap */
593                 if (save_utrap)
594                     (void) mintrap(mtmp);
595             }
596             /* Couldn't... try placing the steed */
597         } else if (enexto(&cc, u.ux, u.uy, mtmp->data)) {
598             /* Keep player here, move the steed to cc */
599             rloc_to(mtmp, cc.x, cc.y);
600             /* Player stays put */
601             /* Otherwise, kill the steed */
602         } else {
603             killed(mtmp);
604             adjalign(-1);
605         }
606     }
607
608     /* Return the player to the floor */
609     if (reason != DISMOUNT_ENGULFED) {
610         in_steed_dismounting = TRUE;
611         (void) float_down(0L, W_SADDLE);
612         in_steed_dismounting = FALSE;
613         context.botl = 1;
614         (void) encumber_msg();
615         vision_full_recalc = 1;
616     } else
617         context.botl = 1;
618     /* polearms behave differently when not mounted */
619     if (uwep && is_pole(uwep))
620         unweapon = TRUE;
621     return;
622 }
623
624 /* when attempting to saddle or mount a sleeping steed, try to wake it up
625    (for the saddling case, it won't be u.usteed yet) */
626 STATIC_OVL void
627 maybewakesteed(steed)
628 struct monst *steed;
629 {
630     int frozen = (int) steed->mfrozen;
631     boolean wasimmobile = steed->msleeping || !steed->mcanmove;
632
633     steed->msleeping = 0;
634     if (frozen) {
635         frozen = (frozen + 1) / 2; /* half */
636         /* might break out of timed sleep or paralysis */
637         if (!rn2(frozen)) {
638             steed->mfrozen = 0;
639             steed->mcanmove = 1;
640         } else {
641             /* didn't awake, but remaining duration is halved */
642             steed->mfrozen = frozen;
643         }
644     }
645     if (wasimmobile && !steed->msleeping && steed->mcanmove)
646         pline("%s wakes up.", Monnam(steed));
647     /* regardless of waking, terminate any meal in progress */
648     finish_meating(steed);
649 }
650
651 /* decide whether hero's steed is able to move;
652    doesn't check for holding traps--those affect the hero directly */
653 boolean
654 stucksteed(checkfeeding)
655 boolean checkfeeding;
656 {
657     struct monst *steed = u.usteed;
658
659     if (steed) {
660         /* check whether steed can move */
661         if (steed->msleeping || !steed->mcanmove) {
662             pline("%s won't move!", upstart(y_monnam(steed)));
663             return TRUE;
664         }
665         /* optionally check whether steed is in the midst of a meal */
666         if (checkfeeding && steed->meating) {
667             pline("%s is still eating.", upstart(y_monnam(steed)));
668             return TRUE;
669         }
670     }
671     return FALSE;
672 }
673
674 void
675 place_monster(mon, x, y)
676 struct monst *mon;
677 int x, y;
678 {
679     if (mon == u.usteed
680         /* special case is for convoluted vault guard handling */
681         || (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) {
682         impossible("placing %s onto map?",
683                    (mon == u.usteed) ? "steed" : "defunct monster");
684         return;
685     }
686     mon->mx = x, mon->my = y;
687     level.monsters[x][y] = mon;
688 }
689
690 /*steed.c*/