home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / muse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  38.0 KB  |  1,403 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)muse.c    3.1    93/05/25    */
  2. /* Monster item usage routine.  Copyright (C) 1990 by Ken Arromdee */
  3. /* NetHack may be freely redistributed.  See license for details.  */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef MUSE
  8.  
  9. extern int monstr[];
  10.  
  11. boolean m_using = FALSE;
  12.  
  13. /* Let monsters use magic items.  Arbitrary assumptions: Monsters only use
  14.  * scrolls when they can see, monsters know when wands have 0 charges, monsters
  15.  * cannot recognize if items are cursed are not, monsters which are confused
  16.  * don't know not to read scrolls, etc....
  17.  */
  18.  
  19. static int FDECL(precheck, (struct monst *,struct obj *));
  20. static void FDECL(mzapmsg, (struct monst *,struct obj *,BOOLEAN_P));
  21. static void FDECL(mreadmsg, (struct monst *,struct obj *));
  22. static void FDECL(mquaffmsg, (struct monst *,struct obj *));
  23. static int FDECL(mbhitm, (struct monst *,struct obj *));
  24. static void FDECL(mbhit,
  25.     (struct monst *,int,int FDECL((*),(MONST_P,OBJ_P)),
  26.     int FDECL((*),(OBJ_P,OBJ_P)),struct obj *));
  27. static void FDECL(you_aggravate, (struct monst *));
  28.  
  29. static struct musable {
  30.     struct obj *offensive;
  31.     struct obj *defensive;
  32.     struct obj *misc;
  33.     int has_offense, has_defense, has_misc;
  34.     /* =0, no capability; otherwise, different numbers.
  35.      * If it's an object, the object is also set (it's 0 otherwise).
  36.      */
  37. } m;
  38. static int trapx, trapy;
  39. static boolean zap_oseen;
  40.     /* for wands which use mbhitm and are zapped at players.  We usually
  41.      * want an oseen local to the function, but this is impossible since the
  42.      * function mbhitm has to be compatible with the normal zap routines,
  43.      * and those routines don't remember who zapped the wand.
  44.      */
  45.  
  46. /* Any preliminary checks which may result in the monster being unable to use
  47.  * the item.  Returns 0 if nothing happened, 2 if the monster can't do anything
  48.  * (i.e. it teleported) and 1 if it's dead.
  49.  */
  50. static int
  51. precheck(mon, obj)
  52. struct monst *mon;
  53. struct obj *obj;
  54. {
  55.     boolean vis = cansee(mon->mx, mon->my);
  56.  
  57.     if (!obj) return 0;
  58.     if (obj->oclass == POTION_CLASS) {
  59.         coord cc;
  60.         static const char *empty = "The potion turns out to be empty.";
  61.         const char * potion_descr ;
  62.         struct monst *mtmp;
  63.  
  64.         potion_descr = OBJ_DESCR(objects[obj->otyp]);
  65.         if (potion_descr && !strcmp(potion_descr, "milky") && !rn2(13)) {
  66.         if (!enexto(&cc, mon->mx, mon->my, &mons[PM_GHOST])) return 0;
  67.         mquaffmsg(mon, obj);
  68.         m_useup(mon, obj);
  69.         mtmp = makemon(&mons[PM_GHOST], cc.x, cc.y);
  70.         if (!mtmp) {
  71.             if (vis) pline(empty);
  72.         } else {
  73.             if (vis) {
  74.             pline("As %s opens the bottle, an enormous %s emerges!",
  75.                mon_nam(mon),
  76.                Hallucination ? rndmonnam() : (const char *)"ghost");
  77.             pline("%s is frightened to death, and unable to move.",
  78.                 Monnam(mon));
  79.             }
  80.             mon->mcanmove = 0;
  81.             mon->mfrozen = 3;
  82.         }
  83.         return 2;
  84.         }
  85.         if (potion_descr && !strcmp(potion_descr, "smoky") && !rn2(13)) {
  86.         if (!enexto(&cc, mon->mx, mon->my, &mons[PM_DJINNI])) return 0;
  87.         mquaffmsg(mon, obj);
  88.         m_useup(mon, obj);
  89.         mtmp = makemon(&mons[PM_DJINNI], cc.x, cc.y);
  90.         if (!mtmp) {
  91.             if (vis) pline(empty);
  92.         } else {
  93.             if (vis)
  94.             pline("In a cloud of smoke, %s emerges!",
  95.                             a_monnam(mtmp));
  96.             pline("%s speaks.", vis ? Monnam(mtmp) : "Something");
  97.         /* I suspect few players will be upset that monsters */
  98.         /* can't wish for wands of death here.... */
  99.             if (rn2(2)) {
  100.             verbalize("You freed me!");
  101.             mtmp->mpeaceful = 1;
  102.             set_malign(mtmp);
  103.             } else {
  104.             verbalize("It is about time.");
  105.             if (vis) pline("%s vanishes.", Monnam(mtmp));
  106.             mongone(mtmp);
  107.             }
  108.         }
  109.         return 2;
  110.         }
  111.     }
  112.     if (obj->oclass == WAND_CLASS && obj->cursed && !rn2(100)) {
  113.         int dam = d(obj->spe+2, 6);
  114.  
  115. #ifdef SOUNDS
  116.         if (flags.soundok)
  117. #endif
  118.                 {
  119.         if (vis) pline("%s zaps %s, which suddenly explodes!",
  120.             Monnam(mon), an(xname(obj)));
  121.         else You("hear a zap and an explosion in the distance.");
  122.         }
  123.         m_useup(mon, obj);
  124.         if (mon->mhp <= dam) {
  125.         monkilled(mon, "", AD_RBRE);
  126.         return 1;
  127.         }
  128.         else mon->mhp -= dam;
  129.         m.has_defense = m.has_offense = m.has_misc = 0;
  130.         /* Only one needed to be set to 0 but the others are harmless */
  131.     }
  132.     return 0;
  133. }
  134.  
  135. static void
  136. mzapmsg(mtmp, otmp, self)
  137. struct monst *mtmp;
  138. struct obj *otmp;
  139. boolean self;
  140. {
  141.     if (!canseemon(mtmp)) {
  142. #ifdef SOUNDS
  143.         if (flags.soundok)
  144. #endif
  145.             You("hear a distant zap.");
  146.     } else if (self)
  147.         pline("%s zaps %sself with %s!",
  148.               Monnam(mtmp), him[pronoun_gender(mtmp)], doname(otmp));
  149.     else {
  150.         pline("%s zaps %s!", Monnam(mtmp), an(xname(otmp)));
  151.         stop_occupation();
  152.     }
  153. }
  154.  
  155. static void
  156. mreadmsg(mtmp, otmp)
  157. struct monst *mtmp;
  158. struct obj *otmp;
  159. {
  160.     boolean vismon = (canseemon(mtmp));
  161. #ifdef SOUNDS
  162.     if (flags.soundok)
  163. #endif
  164.         otmp->dknown = 1;
  165.     if (!vismon) {
  166. #ifdef SOUNDS
  167.         if (flags.soundok)
  168. #endif
  169.             You("hear %s reading %s.",
  170.             an(Hallucination ? rndmonnam() : mtmp->data->mname),
  171.             singular(otmp, doname));
  172.     } else pline("%s reads %s!", Monnam(mtmp), singular(otmp,doname));
  173.     if (mtmp->mconf
  174. #ifdef SOUNDS
  175.         && (vismon || flags.soundok)
  176. #endif
  177.                     )
  178.         pline("Being confused, %s mispronounces the magic words...",
  179.               vismon ? mon_nam(mtmp) : he[pronoun_gender(mtmp)]);
  180. }
  181.  
  182. static void
  183. mquaffmsg(mtmp, otmp)
  184. struct monst *mtmp;
  185. struct obj *otmp;
  186. {
  187.     if (canseemon(mtmp)) {
  188.         otmp->dknown = 1;
  189.         pline("%s drinks %s!", Monnam(mtmp), singular(otmp, doname));
  190.     } else
  191. #ifdef SOUNDS
  192.         if (flags.soundok)
  193. #endif
  194.             You("hear a chugging sound.");
  195. }
  196.  
  197. /* Defines for various types of stuff.  The order in which monsters prefer
  198.  * to use them is determined by the order of the code logic, not the
  199.  * numerical order in which they are defined.
  200.  */
  201. #define MUSE_SCR_TELEPORTATION 1
  202. #define MUSE_WAN_TELEPORTATION_SELF 2
  203. #define MUSE_POT_HEALING 3
  204. #define MUSE_POT_EXTRA_HEALING 4
  205. #define MUSE_WAN_DIGGING 5
  206. #define MUSE_TRAPDOOR 6
  207. #define MUSE_TELEPORT_TRAP 7
  208. #define MUSE_UPSTAIRS 8
  209. #define MUSE_DOWNSTAIRS 9
  210. #define MUSE_WAN_CREATE_MONSTER 10
  211. #define MUSE_SCR_CREATE_MONSTER 11
  212. #define MUSE_UP_LADDER 12
  213. #define MUSE_DN_LADDER 13
  214. #define MUSE_SSTAIRS 14
  215. #define MUSE_WAN_TELEPORTATION 15
  216. #ifdef ARMY
  217. # define MUSE_BUGLE 16
  218. #endif
  219. /*
  220. #define MUSE_INNATE_TPT 9999
  221.  * We cannot use this.  Since monsters get unlimited teleportation, if they
  222.  * were allowed to teleport at will you could never catch them.  Instead,
  223.  * assume they only teleport at random times, despite the inconsistency that if
  224.  * you polymorph into one you teleport at will.
  225.  */
  226.  
  227. /* Select a defensive item/action for a monster.  Returns TRUE iff one is
  228.  * found.
  229.  */
  230. boolean
  231. find_defensive(mtmp)
  232. struct monst *mtmp;
  233. {
  234.     register struct obj *obj;
  235.     struct trap *t;
  236.     int x=mtmp->mx, y=mtmp->my;
  237.     boolean stuck = (mtmp == u.ustuck);
  238.     boolean immobile = (mtmp->data->mmove == 0);
  239.     int fraction;
  240.  
  241.     if (mtmp->mpeaceful || is_animal(mtmp->data) || mindless(mtmp->data))
  242.         return 0;
  243.     if (u.uswallow && stuck) return 0;
  244.     if(dist2(x, y, mtmp->mux, mtmp->muy) > 25)
  245.         return 0;
  246.  
  247.     fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
  248.     if(mtmp->mhp >= mtmp->mhpmax ||
  249.             (mtmp->mhp >= 10 && mtmp->mhp*fraction >= mtmp->mhpmax))
  250.         return 0;
  251.  
  252.     m.defensive = (struct obj *)0;
  253.     m.has_defense = 0;
  254.  
  255.     if (levl[x][y].typ == STAIRS && !stuck && !immobile) {
  256.         if (x == xdnstair && y == ydnstair)
  257.             m.has_defense = MUSE_DOWNSTAIRS;
  258.         if (x == xupstair && y == yupstair && ledger_no(&u.uz) != 1)
  259.     /* Unfair to let the monsters leave the dungeon with the Amulet */
  260.     /* (or go to the endlevel since you also need it, to get there) */
  261.             m.has_defense = MUSE_UPSTAIRS;
  262.     } else if (levl[x][y].typ == LADDER && !stuck && !immobile) {
  263.         if (x == xupladder && y == yupladder)
  264.             m.has_defense = MUSE_UP_LADDER;
  265.         if (x == xdnladder && y == ydnladder)
  266.             m.has_defense = MUSE_DN_LADDER;
  267.     } else if (sstairs.sx && sstairs.sx == x && sstairs.sy == y) {
  268.         m.has_defense = MUSE_SSTAIRS;
  269.     } else if (!stuck && !immobile) {
  270.     /* Note: trapdoors take precedence over teleport traps. */
  271.         int xx, yy;
  272.  
  273.         for(xx = x-1; xx <= x+1; xx++) for(yy = y-1; yy <= y+1; yy++)
  274.         if (isok(xx,yy))
  275.         if (xx != u.ux && yy != u.uy)
  276.         if (mtmp->data != &mons[PM_GRID_BUG] || xx == x || yy == y)
  277.         if ((xx==x && yy==y) || !level.monsters[xx][yy])
  278.         if ((t = t_at(xx,yy)) != 0) {
  279.             if (t->ttyp == TRAPDOOR
  280.                 && !is_floater(mtmp->data)
  281.                 && !mtmp->isshk && !mtmp->isgd
  282.                 && !mtmp->ispriest
  283.                 && Can_fall_thru(&u.uz)
  284.                         ) {
  285.                 trapx = xx;
  286.                 trapy = yy;
  287.                 m.has_defense = MUSE_TRAPDOOR;
  288.             } else if (t->ttyp == TELEP_TRAP && m.has_defense != MUSE_TRAPDOOR) {
  289.                 trapx = xx;
  290.                 trapy = yy;
  291.                 m.has_defense = MUSE_TELEPORT_TRAP;
  292.             }
  293.         }
  294.     }
  295.  
  296.     if (nohands(mtmp->data))    /* can't use objects */
  297.         goto botm;
  298.  
  299. #ifdef ARMY
  300.     if (is_mercenary(mtmp->data) && (obj = m_carrying(mtmp, BUGLE))) {
  301.         int xx, yy;
  302.         struct monst *mon;
  303.  
  304.         /* Distance is arbitrary.  What we really want to do is
  305.          * have the soldier play the bugle when it sees or
  306.          * remembers soldiers nearby...
  307.          */
  308.         for(xx = x-3; xx <= x+3; xx++) for(yy = y-3; yy <= y+3; yy++)
  309.         if (isok(xx,yy))
  310.         if ((mon = m_at(xx,yy)) && is_mercenary(mon->data) &&
  311.                 mon->data != &mons[PM_GUARD] &&
  312.                 (mon->msleep || (!mon->mcanmove))) {
  313.             m.defensive = obj;
  314.             m.has_defense = MUSE_BUGLE;
  315.         }
  316.     }
  317. #endif
  318.     /* use immediate physical escape prior to attempting magic */
  319.     if (m.has_defense)    /* stairs, trapdoor or tele-trap, bugle alert */
  320.         goto botm;
  321.  
  322.     /* kludge to cut down on trap destruction (particularly portals) */
  323.     t = t_at(x,y);
  324.     if (t && (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
  325.           t->ttyp == WEB || t->ttyp == BEAR_TRAP))
  326.         t = 0;        /* ok for monster to dig here */
  327.  
  328. #define nomore(x) if(m.has_defense==x) continue;
  329.     for (obj = mtmp->minvent; obj; obj = obj->nobj) {
  330.         /* don't always use the same selection pattern */
  331.         if (m.has_defense && !rn2(3)) break;
  332.  
  333.         /* nomore(MUSE_WAN_DIGGING); */
  334.         if (m.has_defense == MUSE_WAN_DIGGING) break;
  335.         if (obj->otyp == WAN_DIGGING && obj->spe > 0 && !stuck && !t
  336.             && !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest
  337.             && !is_floater(mtmp->data)
  338.             /* digging wouldn't be effective; assume they know that */
  339.             && !(Is_botlevel(&u.uz) || In_endgame(&u.uz))
  340.             && !(is_ice(x,y) || is_pool(x,y) || is_lava(x,y))) {
  341.             m.defensive = obj;
  342.             m.has_defense = MUSE_WAN_DIGGING;
  343.         }
  344.         nomore(MUSE_WAN_TELEPORTATION_SELF);
  345.         nomore(MUSE_WAN_TELEPORTATION);
  346.         if(obj->otyp == WAN_TELEPORTATION && obj->spe > 0) {
  347.             m.defensive = obj;
  348.             m.has_defense = (mon_has_amulet(mtmp))
  349.                 ? MUSE_WAN_TELEPORTATION
  350.                 : MUSE_WAN_TELEPORTATION_SELF;
  351.         }
  352.         nomore(MUSE_SCR_TELEPORTATION);
  353.         if(obj->otyp == SCR_TELEPORTATION && mtmp->mcansee
  354.            && haseyes(mtmp->data)
  355.            && (!obj->cursed ||
  356.                (!(mtmp->isshk && inhishop(mtmp)) 
  357.                 && !mtmp->isgd && !mtmp->ispriest))) {
  358.             m.defensive = obj;
  359.             m.has_defense = MUSE_SCR_TELEPORTATION;
  360.         }
  361.         nomore(MUSE_POT_EXTRA_HEALING);
  362.         if(obj->otyp == POT_EXTRA_HEALING) {
  363.             m.defensive = obj;
  364.             m.has_defense = MUSE_POT_EXTRA_HEALING;
  365.         }
  366.         nomore(MUSE_WAN_CREATE_MONSTER);
  367.         if(obj->otyp == WAN_CREATE_MONSTER && obj->spe > 0) {
  368.             m.defensive = obj;
  369.             m.has_defense = MUSE_WAN_CREATE_MONSTER;
  370.         }
  371.         nomore(MUSE_POT_HEALING);
  372.         if(obj->otyp == POT_HEALING) {
  373.             m.defensive = obj;
  374.             m.has_defense = MUSE_POT_HEALING;
  375.         }
  376.         nomore(MUSE_SCR_CREATE_MONSTER);
  377.         if(obj->otyp == SCR_CREATE_MONSTER) {
  378.             m.defensive = obj;
  379.             m.has_defense = MUSE_SCR_CREATE_MONSTER;
  380.         }
  381.     }
  382. botm:    return((boolean)(!!m.has_defense));
  383. #undef nomore
  384. }
  385.  
  386. /* Perform a defensive action for a monster.  Must be called immediately
  387.  * after find_defensive().  Return values are 0: did something, 1: died,
  388.  * 2: did something and can't attack again (i.e. teleported).
  389.  */
  390. int
  391. use_defensive(mtmp)
  392. struct monst *mtmp;
  393. {
  394.     int i;
  395.     struct obj *otmp = m.defensive;
  396.     boolean vis = cansee(mtmp->mx, mtmp->my);
  397.     boolean vismon = canseemon(mtmp);
  398.     boolean oseen = otmp && vismon;
  399.  
  400.     if ((i = precheck(mtmp, otmp)) != 0) return i;
  401.     switch(m.has_defense) {
  402. #ifdef ARMY
  403.     case MUSE_BUGLE:
  404.         if (canseemon(mtmp))
  405.             pline("%s plays %s!", Monnam(mtmp), doname(otmp));
  406.         else if (flags.soundok)
  407.             You("hear a bugle playing reveille!");
  408.         awaken_soldiers();
  409.         return 2;
  410. #endif
  411.     case MUSE_WAN_TELEPORTATION_SELF:
  412.         if ((mtmp->isshk && inhishop(mtmp)) 
  413.                || mtmp->isgd || mtmp->ispriest) return 2;
  414.         mzapmsg(mtmp, otmp, TRUE);
  415.         otmp->spe--;
  416.         if (oseen) makeknown(WAN_TELEPORTATION);
  417. mon_tele:
  418.         if (tele_restrict(mtmp))
  419.             return 2;
  420.         if((/*mon_has_amulet(mtmp)||*/ Is_wiz1_level(&u.uz) ||
  421.               Is_wiz2_level(&u.uz) || Is_wiz3_level(&u.uz))
  422.                                 && !rn2(3)) {
  423.             if (vismon)
  424.             pline("%s seems disoriented for a moment.",
  425.                 Monnam(mtmp));
  426.             return 2;
  427.         }
  428.         rloc(mtmp);
  429.         return 2;
  430.     case MUSE_WAN_TELEPORTATION:
  431.         zap_oseen = oseen;
  432.         mzapmsg(mtmp, otmp, FALSE);
  433.         otmp->spe--;
  434.         m_using = TRUE;
  435.         mbhit(mtmp,rn1(8,6),mbhitm,bhito,otmp);
  436.         m_using = FALSE;
  437.         return 2;
  438.     case MUSE_SCR_TELEPORTATION:
  439.         {
  440.         int obj_is_cursed = otmp->cursed;
  441.  
  442.         if (mtmp->isshk || mtmp->isgd || mtmp->ispriest) return 2;
  443.         mreadmsg(mtmp, otmp);
  444.         m_useup(mtmp, otmp);    /* otmp might be free'ed */
  445.         if (oseen) makeknown(SCR_TELEPORTATION);
  446.         if (obj_is_cursed) {
  447.             if (mon_has_amulet(mtmp) || In_endgame(&u.uz)) {
  448.                 if (vismon)
  449.                 pline("%s seems very disoriented for a moment.",
  450.                     Monnam(mtmp));
  451.                 return 2;
  452.             }
  453.             if (Is_botlevel(&u.uz)) goto mon_tele;
  454.             else {
  455.                 int dpth = depth(&u.uz);
  456.                 int nlev = max(dpth, 0);
  457.                 d_level flev;
  458.  
  459.                 if (rn2(5)) nlev = rnd(nlev + 3);
  460.                 else {
  461.                 pline("%s shudders for a moment.",
  462.                             Monnam(mtmp));
  463.                 return 2; 
  464.                 }
  465.                 if (nlev == depth(&u.uz)) {
  466.                 if (u.uz.dlevel == 1) nlev++;
  467.                 else if (In_hell(&u.uz)) nlev--;
  468.                 else nlev++;
  469.                 }
  470.                 get_level(&flev, nlev);
  471.                 migrate_to_level(mtmp, ledger_no(&flev), 0);
  472.             }
  473.         } else goto mon_tele;
  474.         return 2;
  475.         }
  476.     case MUSE_WAN_DIGGING:
  477.         {    struct trap *ttmp;
  478.  
  479.         mzapmsg(mtmp, otmp, FALSE);
  480.         otmp->spe--;
  481.         if (oseen) makeknown(WAN_DIGGING);
  482.         if(IS_FURNITURE(levl[mtmp->mx][mtmp->my].typ)
  483.            || (sstairs.sx && sstairs.sx == mtmp->mx &&
  484.                 sstairs.sy == mtmp->my)) {
  485.             pline("The digging ray is ineffective.");
  486.             return 2;
  487.         }
  488.         if (!Can_dig_down(&u.uz)) {
  489.             if(canseemon(mtmp))
  490.             pline("The floor here is too hard to dig in.");
  491.             return 2;
  492.         }
  493.         ttmp = maketrap(mtmp->mx, mtmp->my, TRAPDOOR);
  494.         if (!ttmp) return 2;
  495.         seetrap(ttmp);
  496.         if (vis) {
  497.             pline("%s's made a hole in the floor.", Monnam(mtmp));
  498.             pline("%s falls through...", Monnam(mtmp));
  499.         } else
  500. # ifdef SOUNDS
  501.             if (flags.soundok)
  502. # endif
  503.             You("hear something crash through the floor.");
  504.         /* we made sure that there is a level for mtmp to go to */
  505.         migrate_to_level(mtmp, ledger_no(&u.uz)+1, 0);
  506.         return 2;
  507.         }
  508.     case MUSE_WAN_CREATE_MONSTER:
  509.         {    coord cc;
  510.         struct permonst *pm=rndmonst();
  511.  
  512.         if (!enexto(&cc, mtmp->mx, mtmp->my, pm)) return 0;
  513.         mzapmsg(mtmp, otmp, FALSE);
  514.         otmp->spe--;
  515.         if (oseen) makeknown(WAN_CREATE_MONSTER);
  516.         (void) makemon(pm, cc.x, cc.y);
  517.         return 2;
  518.         }
  519.     case MUSE_SCR_CREATE_MONSTER:
  520.         {    coord cc;
  521.         struct permonst *pm=rndmonst();
  522.         int cnt = 1;
  523.  
  524.         if (!rn2(73)) cnt += rnd(4);
  525.         if (mtmp->mconf || otmp->cursed) cnt += 12;
  526.         mreadmsg(mtmp, otmp);
  527.         while(cnt--) {
  528.             struct monst *mon;
  529.  
  530.             if (!enexto(&cc, mtmp->mx, mtmp->my, pm)) continue;
  531.             mon = makemon(mtmp->mconf ? &mons[PM_ACID_BLOB]
  532.                 : rndmonst(), cc.x, cc.y);
  533.             if (mon) newsym(mon->mx,mon->my);
  534.         }
  535.         /* flush monsters before asking for identification */
  536.         flush_screen(0);
  537.         if (oseen && !objects[SCR_CREATE_MONSTER].oc_name_known
  538.               && !objects[SCR_CREATE_MONSTER].oc_uname)
  539.             docall(otmp); /* not makeknown(); be consistent */
  540.         m_useup(mtmp, otmp);
  541.         return 2;
  542.         }
  543.     case MUSE_TRAPDOOR:
  544.         /* trapdoors on "bottom" levels of dungeons are rock-drop
  545.          * trapdoors, not holes in the floor.  We check here for
  546.          * safety.
  547.          */
  548.         if (Is_botlevel(&u.uz)) return 0;
  549.         if (vis) pline("%s %s into a trapdoor!", Monnam(mtmp),
  550.             makeplural(locomotion(mtmp->data, "jump")));
  551.         seetrap(t_at(trapx,trapy));
  552.  
  553.         /*  don't use rloc_to() because worm tails must "move" */
  554.         remove_monster(mtmp->mx, mtmp->my);
  555.         newsym(mtmp->mx, mtmp->my);    /* update old location */
  556.         place_monster(mtmp, trapx, trapy);
  557.         if (mtmp->wormno) worm_move(mtmp);
  558.         newsym(trapx, trapy);
  559.  
  560.         migrate_to_level(mtmp, ledger_no(&u.uz)+1, 0);
  561.         return 2;
  562.     case MUSE_UPSTAIRS:
  563.         /* Monsters without amulets escape the dungeon and are
  564.          * gone for good when they leave up the up stairs.
  565.          * Monsters with amulets would reach the endlevel,
  566.          * which we cannot allow since that would leave the
  567.          * player stranded.
  568.          */
  569.         if (ledger_no(&u.uz) == 1) {
  570.             if (mon_has_special(mtmp))
  571.                 return 0;
  572.             if (vismon) pline("%s escapes the dungeon!",
  573.                 Monnam(mtmp));
  574.             mongone(mtmp);
  575.             return 2;
  576.         }
  577.         if (vismon) pline("%s escapes upstairs!", Monnam(mtmp));
  578.         migrate_to_level(mtmp, ledger_no(&u.uz)-1, 2);
  579.         return 2;
  580.     case MUSE_DOWNSTAIRS:
  581.         if (vismon) pline("%s escapes downstairs!", Monnam(mtmp));
  582.         migrate_to_level(mtmp, ledger_no(&u.uz)+1, 1);
  583.         return 2;
  584.     case MUSE_UP_LADDER:
  585.         if (vismon) pline("%s escapes up the ladder!", Monnam(mtmp));
  586.         migrate_to_level(mtmp, ledger_no(&u.uz)-1, 4);
  587.         return 2;
  588.     case MUSE_DN_LADDER:
  589.         if (vismon) pline("%s escapes down the ladder!", Monnam(mtmp));
  590.         migrate_to_level(mtmp, ledger_no(&u.uz)+1, 3);
  591.         return 2;
  592.     case MUSE_SSTAIRS:
  593.         /* the stairs leading up from the 1st level are */
  594.         /* regular stairs, not sstairs.            */
  595.         if (sstairs.up) {
  596.             if (vismon)
  597.                 pline("%s escapes upstairs!", Monnam(mtmp));
  598.             if(Inhell) {
  599.                 migrate_to_level(mtmp,
  600.                      ledger_no(&sstairs.tolev), 0);
  601.                 return 2;
  602.             }
  603.         } else    if (vismon)
  604.             pline("%s escapes downstairs!", Monnam(mtmp));
  605.         migrate_to_level(mtmp, ledger_no(&sstairs.tolev), 5);
  606.         return 2;
  607.     case MUSE_TELEPORT_TRAP:
  608.         if (vis) pline("%s %s onto a teleport trap!", Monnam(mtmp),
  609.             makeplural(locomotion(mtmp->data, "jump")));
  610.         seetrap(t_at(trapx,trapy));
  611.  
  612.         /*  don't use rloc_to() because worm tails must "move" */
  613.         remove_monster(mtmp->mx, mtmp->my);
  614.         newsym(mtmp->mx, mtmp->my);    /* update old location */
  615.         place_monster(mtmp, trapx, trapy);
  616.         if (mtmp->wormno) worm_move(mtmp);
  617.         newsym(trapx, trapy);
  618.  
  619.         goto mon_tele;
  620.     case MUSE_POT_HEALING:
  621.         mquaffmsg(mtmp, otmp);
  622.         i = d(5,2) + 5 * !!bcsign(otmp);
  623.         mtmp->mhp += i;
  624.         if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = ++mtmp->mhpmax;
  625.         if (!otmp->cursed) mtmp->mcansee = 1;
  626.         if (vismon) pline("%s begins to look better.", Monnam(mtmp));
  627.         if (oseen) makeknown(POT_HEALING);
  628.         m_useup(mtmp, otmp);
  629.         return 2;
  630.     case MUSE_POT_EXTRA_HEALING:
  631.         mquaffmsg(mtmp, otmp);
  632.         i = d(5,4) + 5 * !!bcsign(otmp);
  633.         mtmp->mhp += i;
  634.         if (mtmp->mhp > mtmp->mhpmax)
  635.             mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
  636.         mtmp->mcansee = 1;
  637.         if (vismon) pline("%s looks much better.", Monnam(mtmp));
  638.         if (oseen) makeknown(POT_EXTRA_HEALING);
  639.         m_useup(mtmp, otmp);
  640.         return 2;
  641.     case 0: return 0; /* i.e. an exploded wand */
  642.     default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
  643.             m.has_defense);
  644.         break;
  645.     }
  646.     return 0;
  647. }
  648.  
  649. int
  650. rnd_defensive_item(mtmp)
  651. struct monst *mtmp;
  652. {
  653.     struct permonst *pm = mtmp->data;
  654.     int difficulty = monstr[(monsndx(pm))];
  655.  
  656.     if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
  657.             || pm->mlet == S_GHOST
  658. # ifdef KOPS
  659.             || pm->mlet == S_KOP
  660. # endif
  661.         ) return 0;
  662.     switch (rn2(8 + (difficulty > 3) + (difficulty > 6) +
  663.                 (difficulty > 8))) {
  664.         case 6: case 9:
  665.             if (!rn2(3)) return WAN_TELEPORTATION;
  666.             /* else FALLTHRU */
  667.         case 0: case 1:
  668.             return SCR_TELEPORTATION;
  669.         case 8: case 10:
  670.             if (!rn2(3)) return WAN_CREATE_MONSTER;
  671.             /* else FALLTHRU */
  672.         case 2: return SCR_CREATE_MONSTER;
  673.         case 3: case 4:
  674.             return POT_HEALING;
  675.         case 5: return POT_EXTRA_HEALING;
  676.         case 7: if (is_floater(pm) || mtmp->isshk || mtmp->isgd
  677.                         || mtmp->ispriest
  678.                                     )
  679.                 return 0;
  680.             else
  681.                 return WAN_DIGGING;
  682.     }
  683.     /*NOTREACHED*/
  684.     return 0;
  685. }
  686.  
  687. #define MUSE_WAN_DEATH 1
  688. #define MUSE_WAN_SLEEP 2
  689. #define MUSE_WAN_FIRE 3
  690. #define MUSE_WAN_COLD 4
  691. #define MUSE_WAN_LIGHTNING 5
  692. #define MUSE_WAN_MAGIC_MISSILE 6
  693. #define MUSE_WAN_STRIKING 7
  694. #define MUSE_SCR_FIRE 8
  695. #define MUSE_POT_PARALYSIS 9
  696. #define MUSE_POT_BLINDNESS 10
  697. #define MUSE_POT_CONFUSION 11
  698.  
  699. /* Select an offensive item/action for a monster.  Returns TRUE iff one is
  700.  * found.
  701.  */
  702. boolean
  703. find_offensive(mtmp)
  704. struct monst *mtmp;
  705. {
  706.     register struct obj *obj;
  707.     boolean ranged_stuff = lined_up(mtmp);
  708.  
  709.     m.offensive = (struct obj *)0;
  710.     m.has_offense = 0;
  711.     if (mtmp->mpeaceful || is_animal(mtmp->data) ||
  712.                 mindless(mtmp->data) || nohands(mtmp->data))
  713.         return 0;
  714.     if (u.uswallow) return 0;
  715.     if (in_your_sanctuary(mtmp->mx, mtmp->my)) return 0;
  716.     if (dmgtype(mtmp->data, AD_HEAL) && !uwep
  717. #ifdef TOURIST
  718.         && !uarmu
  719. #endif
  720.         && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf)
  721.         return 0;
  722.  
  723.     if (!ranged_stuff) return 0;
  724. #define nomore(x) if(m.has_offense==x) continue;
  725.     for(obj=mtmp->minvent; obj; obj=obj->nobj) {
  726.         /* nomore(MUSE_WAN_DEATH); */
  727.         if (m.has_defense == WAN_DEATH) break;
  728.         if(obj->otyp == WAN_DEATH && obj->spe > 0) {
  729.             m.offensive = obj;
  730.             m.has_offense = MUSE_WAN_DEATH;
  731.         }
  732.         nomore(MUSE_WAN_SLEEP);
  733.         if(obj->otyp == WAN_SLEEP && obj->spe > 0 && multi >= 0) {
  734.             m.offensive = obj;
  735.             m.has_offense = MUSE_WAN_SLEEP;
  736.         }
  737.         nomore(MUSE_WAN_FIRE);
  738.         if(obj->otyp == WAN_FIRE && obj->spe > 0) {
  739.             m.offensive = obj;
  740.             m.has_offense = MUSE_WAN_FIRE;
  741.         }
  742.         nomore(MUSE_WAN_COLD);
  743.         if(obj->otyp == WAN_COLD && obj->spe > 0) {
  744.             m.offensive = obj;
  745.             m.has_offense = MUSE_WAN_COLD;
  746.         }
  747.         nomore(MUSE_WAN_LIGHTNING);
  748.         if(obj->otyp == WAN_LIGHTNING && obj->spe > 0) {
  749.             m.offensive = obj;
  750.             m.has_offense = MUSE_WAN_LIGHTNING;
  751.         }
  752.         nomore(MUSE_WAN_MAGIC_MISSILE);
  753.         if(obj->otyp == WAN_MAGIC_MISSILE && obj->spe > 0) {
  754.             m.offensive = obj;
  755.             m.has_offense = MUSE_WAN_MAGIC_MISSILE;
  756.         }
  757.         nomore(MUSE_WAN_STRIKING);
  758.         if(obj->otyp == WAN_STRIKING && obj->spe > 0) {
  759.             m.offensive = obj;
  760.             m.has_offense = MUSE_WAN_STRIKING;
  761.         }
  762.         nomore(MUSE_POT_PARALYSIS);
  763.         if(obj->otyp == POT_PARALYSIS && multi >= 0) {
  764.             m.offensive = obj;
  765.             m.has_offense = MUSE_POT_PARALYSIS;
  766.         }
  767.         nomore(MUSE_POT_BLINDNESS);
  768.         if(obj->otyp == POT_BLINDNESS) {
  769.             m.offensive = obj;
  770.             m.has_offense = MUSE_POT_BLINDNESS;
  771.         }
  772.         nomore(MUSE_POT_CONFUSION);
  773.         if(obj->otyp == POT_CONFUSION) {
  774.             m.offensive = obj;
  775.             m.has_offense = MUSE_POT_CONFUSION;
  776.         }
  777. #if 0
  778.         nomore(MUSE_SCR_FIRE);
  779.         /* even more restrictive than ranged_stuff */
  780.         if(obj->otyp == SCR_FIRE && resists_fire(mtmp->data)
  781.            && distu(mtmp->mx,mtmp->my)==1
  782.            && mtmp->mcansee && haseyes(mtmp->data)) {
  783.             m.offensive = obj;
  784.             m.has_offense = MUSE_SCR_FIRE;
  785.         }
  786. #endif
  787.     }
  788.     return((boolean)(!!m.has_offense));
  789. #undef nomore
  790. }
  791.  
  792. static int
  793. mbhitm(mtmp, otmp)
  794. register struct monst *mtmp;
  795. register struct obj *otmp;
  796. {
  797.     int tmp;
  798.  
  799.     if (mtmp != &youmonst) {
  800.         mtmp->msleep = 0;
  801.         if (mtmp->m_ap_type) seemimic(mtmp);
  802.     }
  803.     switch(otmp->otyp) {
  804.     case WAN_STRIKING:
  805.         if (mtmp == &youmonst) {
  806.             if (zap_oseen) makeknown(WAN_STRIKING);
  807.             if (rnd(20) < 10 + u.uac) {
  808.                 pline("The wand hits you!");
  809.                 tmp = d(2,12);
  810.                 if(Half_spell_damage) tmp = (tmp+1) / 2;
  811.                 losehp(tmp, "wand", KILLED_BY_AN);
  812.             } else pline("The wand misses you.");
  813.             stop_occupation();
  814.             nomul(0);
  815.         } else if (rnd(20) < 10+find_mac(mtmp)) {
  816.             tmp = d(2,12);
  817.             if(Half_spell_damage) tmp = (tmp+1) / 2;
  818.             hit("wand", mtmp, exclam(tmp));
  819.             (void) resist(mtmp, otmp->oclass, tmp, TELL);
  820.             if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
  821.                 makeknown(WAN_STRIKING);
  822.         } else {
  823.             miss("wand", mtmp);
  824.             if (cansee(mtmp->mx, mtmp->my) && zap_oseen)
  825.                 makeknown(WAN_STRIKING);
  826.         }
  827.         break;
  828.     case WAN_TELEPORTATION:
  829.         if (mtmp == &youmonst) {
  830.             if (zap_oseen) makeknown(WAN_TELEPORTATION);
  831.             tele();
  832.         } else {
  833.             /* for consistency with zap.c, don't identify */
  834.             if (mtmp->ispriest &&
  835.                 *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
  836.                 if (cansee(mtmp->mx, mtmp->my))
  837.                 pline("%s resists the magic!", Monnam(mtmp));
  838.                 mtmp->msleep = 0;
  839.                 if(mtmp->m_ap_type) seemimic(mtmp);
  840.             } else
  841.                 rloc(mtmp);
  842.         }
  843.         break;
  844.     case WAN_CANCELLATION:
  845.     case SPE_CANCELLATION:
  846.         cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
  847.         break;
  848.     }
  849.     return 0;
  850. }
  851.  
  852. /* A modified bhit() for monsters.  Based on bhit() in zap.c.  Unlike
  853.  * buzz(), bhit() doesn't take into account the possibility of a monster
  854.  * zapping you, so we need a special function for it.  (Unless someone wants
  855.  * to merge the two functions...)
  856.  */
  857. static void
  858. mbhit(mon,range,fhitm,fhito,obj)
  859. struct monst *mon;            /* monster shooting the wand */
  860. register int range;            /* direction and range */
  861. int FDECL((*fhitm),(MONST_P,OBJ_P));
  862. int FDECL((*fhito),(OBJ_P,OBJ_P));    /* fns called when mon/obj hit */
  863. struct obj *obj;            /* 2nd arg to fhitm/fhito */
  864. {
  865.     register struct monst *mtmp;
  866.     register struct obj *otmp;
  867.     register uchar typ;
  868.     int ddx, ddy;
  869.  
  870.     bhitpos.x = mon->mx;
  871.     bhitpos.y = mon->my;
  872.     ddx = sgn(mon->mux - mon->mx);
  873.     ddy = sgn(mon->muy - mon->my);
  874.  
  875.     while(range-- > 0) {
  876.         int x,y;
  877.  
  878.         bhitpos.x += ddx;
  879.         bhitpos.y += ddy;
  880.         x = bhitpos.x; y = bhitpos.y;
  881.  
  882.         if (!isok(x,y)) {
  883.             bhitpos.x -= ddx;
  884.             bhitpos.y -= ddy;
  885.             break;
  886.         }
  887.         if (find_drawbridge(&x,&y))
  888.             switch (obj->otyp) {
  889.             case WAN_STRIKING:
  890.                 destroy_drawbridge(x,y);
  891.             }
  892.         if(bhitpos.x==u.ux && bhitpos.y==u.uy) {
  893.             (*fhitm)(&youmonst, obj);
  894.             range -= 3;
  895.         } else if(MON_AT(bhitpos.x, bhitpos.y)){
  896.             mtmp = m_at(bhitpos.x,bhitpos.y);
  897.             (*fhitm)(mtmp, obj);
  898.             range -= 3;
  899.         }
  900.         /* modified by GAN to hit all objects */
  901.         if(fhito){
  902.             int hitanything = 0;
  903.             register struct obj *next_obj;
  904.  
  905.             for(otmp = level.objects[bhitpos.x][bhitpos.y];
  906.                             otmp; otmp = next_obj) {
  907.             /* Fix for polymorph bug, Tim Wright */
  908.             next_obj = otmp->nexthere;
  909.             hitanything += (*fhito)(otmp, obj);
  910.             }
  911.             if(hitanything)    range--;
  912.         }
  913.         typ = levl[bhitpos.x][bhitpos.y].typ;
  914.         if(IS_DOOR(typ) || typ == SDOOR) {
  915.             switch (obj->otyp) {
  916.             case WAN_STRIKING:
  917.                 if (doorlock(obj, bhitpos.x, bhitpos.y))
  918.                 makeknown(obj->otyp);
  919.                 break;
  920.             }
  921.         }
  922.         if(!ZAP_POS(typ) || (IS_DOOR(typ) &&
  923.            (levl[bhitpos.x][bhitpos.y].doormask & (D_LOCKED | D_CLOSED)))
  924.           ) {
  925.             bhitpos.x -= ddx;
  926.             bhitpos.y -= ddy;
  927.             break;
  928.         }
  929.     }
  930. }
  931.  
  932. /* Perform an offensive action for a monster.  Must be called immediately
  933.  * after find_offensive().  Return values are same as use_defensive().
  934.  */
  935. int
  936. use_offensive(mtmp)
  937. struct monst *mtmp;
  938. {
  939.     int i;
  940.     struct obj *otmp = m.offensive;
  941.     boolean oseen = otmp && canseemon(mtmp);
  942.  
  943.     if ((i = precheck(mtmp, otmp)) != 0) return i;
  944.     switch(m.has_offense) {
  945.     case MUSE_WAN_DEATH:
  946.     case MUSE_WAN_SLEEP:
  947.     case MUSE_WAN_FIRE:
  948.     case MUSE_WAN_COLD:
  949.     case MUSE_WAN_LIGHTNING:
  950.     case MUSE_WAN_MAGIC_MISSILE:
  951.         mzapmsg(mtmp, otmp, FALSE);
  952.         otmp->spe--;
  953.         if (oseen) makeknown(otmp->otyp);
  954.         m_using = TRUE;
  955.         buzz((int)(-30 - (otmp->otyp - WAN_MAGIC_MISSILE)),
  956.             (otmp->otyp == WAN_MAGIC_MISSILE) ? 2 : 6,
  957.             mtmp->mx, mtmp->my,
  958.             sgn(mtmp->mux-mtmp->mx), sgn(mtmp->muy-mtmp->my));
  959.         m_using = FALSE;
  960.         return (mtmp->mhp <= 0) ? 1 : 2;
  961.     case MUSE_WAN_TELEPORTATION:
  962.     case MUSE_WAN_STRIKING:
  963.         zap_oseen = oseen;
  964.         mzapmsg(mtmp, otmp, FALSE);
  965.         otmp->spe--;
  966.         m_using = TRUE;
  967.         mbhit(mtmp,rn1(8,6),mbhitm,bhito,otmp);
  968.         m_using = FALSE;
  969.         return 2;
  970. #if 0
  971.     case MUSE_SCR_FIRE:
  972.           {
  973.         boolean vis = cansee(mtmp->mx, mtmp->my);
  974.  
  975.         mreadmsg(mtmp, otmp);
  976.         if (mtmp->mconf) {
  977.             if (vis)
  978.                 pline("Oh, what a pretty fire!");
  979.         } else {
  980.             struct monst *mtmp2;
  981.             int num;
  982.  
  983.             if (vis)
  984.                 pline("The scroll erupts in a tower of flame!");
  985.             shieldeff(mtmp->mx, mtmp->my);
  986.             pline("%s is uninjured.", Monnam(mtmp));
  987.             (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
  988.             (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
  989.             (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
  990.             num = (2*(rn1(3, 3) + 2 * bcsign(otmp)) + 1)/3;
  991.             if (Fire_resistance)
  992.                 You("are not affected.");
  993.             if (Half_spell_damage) num = (num+1) / 2;
  994.             else losehp(num, "scroll of fire", KILLED_BY_AN);
  995.             for(mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
  996.                if(mtmp == mtmp2) continue;
  997.                if(dist2(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < 3){
  998.                 if (resists_fire(mtmp2->data)) continue;
  999.                 mtmp2->mhp -= num;
  1000.                 if(resists_cold(mtmp2->data))
  1001.                     mtmp2->mhp -= 3*num;
  1002.                 if(mtmp2->mhp < 1) {
  1003.                     mondied(mtmp2);
  1004.                     break;
  1005.                 }
  1006.                 }
  1007.             }
  1008.         }
  1009.         return 2;
  1010.           }
  1011. #endif
  1012.     case MUSE_POT_PARALYSIS:
  1013.     case MUSE_POT_BLINDNESS:
  1014.     case MUSE_POT_CONFUSION:
  1015.         /* Note: this setting of dknown doesn't suffice.  A monster
  1016.          * which is out of sight might throw and it hits something _in_
  1017.          * sight, a problem not existing with wands because wand rays
  1018.          * are not objects.  Also set dknown in mthrowu.c.
  1019.          */
  1020.         if (cansee(mtmp->mx, mtmp->my)) {
  1021.             otmp->dknown = 1;
  1022.             pline("%s hurls %s!", Monnam(mtmp),
  1023.                         singular(otmp, doname));
  1024.         }
  1025.         m_throw(mtmp, mtmp->mx, mtmp->my, sgn(mtmp->mux-mtmp->mx),
  1026.             sgn(mtmp->muy-mtmp->my),
  1027.             distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
  1028.         return 2;
  1029.     case 0: return 0; /* i.e. an exploded wand */
  1030.     default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
  1031.             m.has_offense);
  1032.         break;
  1033.     }
  1034.     return 0;
  1035. }
  1036.  
  1037. int
  1038. rnd_offensive_item(mtmp)
  1039. struct monst *mtmp;
  1040. {
  1041.     struct permonst *pm = mtmp->data;
  1042.     int difficulty = monstr[(monsndx(pm))];
  1043.  
  1044.     if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
  1045.             || pm->mlet == S_GHOST
  1046. # ifdef KOPS
  1047.             || pm->mlet == S_KOP
  1048. # endif
  1049.         ) return 0;
  1050.     if (difficulty > 7 && !rn2(35)) return WAN_DEATH;
  1051.     switch (rn2(7 - (difficulty < 4) + 4 * (difficulty > 6))) {
  1052.         case 0: case 1:
  1053.             return WAN_STRIKING;
  1054.         case 2: return POT_CONFUSION;
  1055.         case 3: return POT_BLINDNESS;
  1056.         case 4: return POT_PARALYSIS;
  1057.         case 5: case 6:
  1058.             return WAN_MAGIC_MISSILE;
  1059.         case 7: return WAN_SLEEP;
  1060.         case 8: return WAN_FIRE;
  1061.         case 9: return WAN_COLD;
  1062.         case 10: return WAN_LIGHTNING;
  1063.     }
  1064.     /*NOTREACHED*/
  1065.     return 0;
  1066. }
  1067.  
  1068. #define MUSE_POT_GAIN_LEVEL 1
  1069. #define MUSE_WAN_MAKE_INVISIBLE 2
  1070. #define MUSE_POT_INVISIBILITY 3
  1071. #define MUSE_POLY_TRAP 4
  1072. #define MUSE_WAN_POLYMORPH 5
  1073. #define MUSE_POT_SPEED 6
  1074. #define MUSE_WAN_SPEED_MONSTER 7
  1075. boolean
  1076. find_misc(mtmp)
  1077. struct monst *mtmp;
  1078. {
  1079.     register struct obj *obj;
  1080.     int x=mtmp->mx, y=mtmp->my;
  1081. #ifdef POLYSELF
  1082.     struct trap *t;
  1083.     int xx, yy;
  1084.     boolean immobile = (mtmp->data->mmove == 0);
  1085. #endif
  1086.     boolean stuck = (mtmp == u.ustuck);
  1087.  
  1088.     m.misc = (struct obj *)0;
  1089.     m.has_misc = 0;
  1090.     if (is_animal(mtmp->data) || mindless(mtmp->data))
  1091.         return 0;
  1092.     if (u.uswallow && stuck) return 0;
  1093.  
  1094.     /* We arbitrarily limit to times when a player is nearby for the
  1095.      * same reason as Junior Pac-Man doesn't have energizers eaten until
  1096.      * you can see them...
  1097.      */
  1098.     if(dist2(x, y, mtmp->mux, mtmp->muy) > 36)
  1099.         return 0;
  1100.  
  1101. #ifdef POLYSELF
  1102.     if (!stuck && !immobile &&
  1103.             !mtmp->cham && monstr[(monsndx(mtmp->data))] < 6)
  1104.       for(xx = x-1; xx <= x+1; xx++)
  1105.         for(yy = y-1; yy <= y+1; yy++)
  1106.         if (isok(xx,yy) && (xx != u.ux || yy != u.uy))
  1107.             if (mtmp->data != &mons[PM_GRID_BUG] || xx == x || yy == y)
  1108.             if (/* (xx==x && yy==y) || */ !level.monsters[xx][yy])
  1109.                 if ((t = t_at(xx,yy)) != 0) {
  1110.                 if (t->ttyp == POLY_TRAP) {
  1111.                     trapx = xx;
  1112.                     trapy = yy;
  1113.                     m.has_misc = MUSE_POLY_TRAP;
  1114.                     return TRUE;
  1115.                 }
  1116.                 }
  1117. #endif
  1118.     if (nohands(mtmp->data))
  1119.         return 0;
  1120.  
  1121. #define nomore(x) if(m.has_misc==x) continue;
  1122.     for(obj=mtmp->minvent; obj; obj=obj->nobj) {
  1123.         /* Monsters shouldn't recognize cursed items; this kludge is */
  1124.         /* necessary to prevent serious problems though... */
  1125.         if(obj->otyp == POT_GAIN_LEVEL && (!obj->cursed ||
  1126.                 (!mtmp->isgd && !mtmp->isshk && !mtmp->ispriest))) {
  1127.             m.misc = obj;
  1128.             m.has_misc = MUSE_POT_GAIN_LEVEL;
  1129.         }
  1130.         /* Note: peaceful/tame monsters won't make themselves
  1131.          * invisible unless you can see them.  Not really right, but...
  1132.          */
  1133.         nomore(MUSE_WAN_MAKE_INVISIBLE);
  1134.         if(obj->otyp == WAN_MAKE_INVISIBLE && obj->spe > 0 &&
  1135.              !mtmp->minvis && (!mtmp->mpeaceful || See_invisible)
  1136.             && (mtmp->data != &mons[PM_MEDUSA] || mtmp->mcan)) {
  1137.             m.misc = obj;
  1138.             m.has_misc = MUSE_WAN_MAKE_INVISIBLE;
  1139.         }
  1140.         nomore(MUSE_POT_INVISIBILITY);
  1141.         if(obj->otyp == POT_INVISIBILITY &&
  1142.              !mtmp->minvis && (!mtmp->mpeaceful || See_invisible)) {
  1143.             m.misc = obj;
  1144.             m.has_misc = MUSE_POT_INVISIBILITY;
  1145.         }
  1146.         nomore(MUSE_WAN_SPEED_MONSTER);
  1147.         if(obj->otyp == WAN_SPEED_MONSTER && obj->spe > 0
  1148.                 && mtmp->mspeed != MFAST && !mtmp->isgd) {
  1149.             m.misc = obj;
  1150.             m.has_misc = MUSE_WAN_SPEED_MONSTER;
  1151.         }
  1152.         nomore(MUSE_POT_SPEED);
  1153.         if(obj->otyp == POT_SPEED && mtmp->mspeed != MFAST
  1154.                             && !mtmp->isgd) {
  1155.             m.misc = obj;
  1156.             m.has_misc = MUSE_POT_SPEED;
  1157.         }
  1158.         nomore(MUSE_WAN_POLYMORPH);
  1159.         if(obj->otyp == WAN_POLYMORPH && !mtmp->cham
  1160.                 && monstr[(monsndx(mtmp->data))] < 6) {
  1161.             m.misc = obj;
  1162.             m.has_misc = MUSE_WAN_POLYMORPH;
  1163.         }
  1164.     }
  1165.     return((boolean)(!!m.has_misc));
  1166. #undef nomore
  1167. }
  1168.  
  1169. int
  1170. use_misc(mtmp)
  1171. struct monst *mtmp;
  1172. {
  1173.     int i;
  1174.     struct obj *otmp = m.misc;
  1175.     boolean vis = cansee(mtmp->mx, mtmp->my);
  1176.     boolean vismon = canseemon(mtmp);
  1177.     boolean oseen = otmp && vismon;
  1178.  
  1179.     if ((i = precheck(mtmp, otmp)) != 0) return i;
  1180.     switch(m.has_misc) {
  1181.     case MUSE_POT_GAIN_LEVEL:
  1182.         mquaffmsg(mtmp, otmp);
  1183.         if (otmp->cursed) {
  1184.             if (Can_rise_up(&u.uz)) {
  1185.             register int tolev = depth(&u.uz)-1;
  1186.             d_level tolevel;
  1187.  
  1188.             get_level(&tolevel, tolev);
  1189.             /* insurance against future changes... */
  1190.             if(on_level(&tolevel, &u.uz)) goto skipmsg;
  1191.             if (vismon) {
  1192.                 pline("%s rises up, through the ceiling!",
  1193.                 Monnam(mtmp));
  1194.                 if(!objects[POT_GAIN_LEVEL].oc_name_known
  1195.                   && !objects[POT_GAIN_LEVEL].oc_uname)
  1196.                 docall(otmp);
  1197.             }
  1198.             m_useup(mtmp, otmp);
  1199.             migrate_to_level(mtmp, ledger_no(&tolevel), 0);
  1200.             return 2;
  1201.             } else {
  1202. skipmsg:
  1203.             if (vismon) {
  1204.                 pline("%s looks uneasy.", Monnam(mtmp));
  1205.                 if(!objects[POT_GAIN_LEVEL].oc_name_known
  1206.                   && !objects[POT_GAIN_LEVEL].oc_uname)
  1207.                 docall(otmp);
  1208.             }
  1209.             m_useup(mtmp, otmp);
  1210.             return 2;
  1211.             }
  1212.         }
  1213.         if (vismon) pline("%s seems more experienced.", Monnam(mtmp));
  1214.         if (oseen) makeknown(POT_GAIN_LEVEL);
  1215.         m_useup(mtmp, otmp);
  1216.         if (!grow_up(mtmp,(struct monst *)0)) return 1;
  1217.             /* grew into genocided monster */
  1218.         return 2;
  1219.     case MUSE_WAN_MAKE_INVISIBLE:
  1220.         mzapmsg(mtmp, otmp, TRUE);
  1221.         otmp->spe--;
  1222.         mtmp->minvis = 1;
  1223.         newsym(mtmp->mx,mtmp->my);
  1224.         if (mtmp->wormno) see_wsegs(mtmp);
  1225.         return 2;
  1226.     case MUSE_POT_INVISIBILITY:
  1227.         mquaffmsg(mtmp, otmp);
  1228.         if (vis) pline("Gee, all of a sudden %s can't see %sself.",
  1229.                    mon_nam(mtmp), him[pronoun_gender(mtmp)]);
  1230.         if (oseen) makeknown(POT_INVISIBILITY);
  1231.         mtmp->minvis = 1;
  1232.         newsym(mtmp->mx,mtmp->my);
  1233.         if (mtmp->wormno) see_wsegs(mtmp);
  1234.         if (otmp->cursed) {
  1235.             mtmp->minvis = 0;
  1236.             pline("For some reason, %s presence is known to you.",
  1237.                 s_suffix(mon_nam(mtmp)));
  1238.             you_aggravate(mtmp);
  1239.             mtmp->minvis = 1;
  1240.             newsym(mtmp->mx,mtmp->my);
  1241.         }
  1242.         m_useup(mtmp, otmp);
  1243.         return 2;
  1244.     case MUSE_WAN_SPEED_MONSTER:
  1245.         mzapmsg(mtmp, otmp, TRUE);
  1246.         otmp->spe--;
  1247.         if (mtmp->mspeed == MSLOW) mtmp->mspeed = 0;
  1248.         else mtmp->mspeed = MFAST;
  1249.         return 2;
  1250.     case MUSE_POT_SPEED:
  1251.         mquaffmsg(mtmp, otmp);
  1252.         if (vismon) pline("%s is suddenly moving much faster.",
  1253.             Monnam(mtmp));
  1254.         if (oseen) makeknown(POT_SPEED);
  1255.         if (mtmp->mspeed == MSLOW) mtmp->mspeed = 0;
  1256.         else mtmp->mspeed = MFAST;
  1257.         m_useup(mtmp, otmp);
  1258.         return 2;
  1259.     case MUSE_WAN_POLYMORPH:
  1260.         mzapmsg(mtmp, otmp, TRUE);
  1261.         otmp->spe--;
  1262.         (void) newcham(mtmp, rndmonst());
  1263.         if (oseen) makeknown(WAN_POLYMORPH);
  1264.         return 2;
  1265. #ifdef POLYSELF
  1266.     case MUSE_POLY_TRAP:
  1267.         if (vismon)
  1268.             pline("%s deliberately goes onto a polymorph trap!",
  1269.               Monnam(mtmp));
  1270.         seetrap(t_at(trapx,trapy));
  1271.  
  1272.         /*  don't use rloc() due to worms */
  1273.         remove_monster(mtmp->mx, mtmp->my);
  1274.         newsym(mtmp->mx, mtmp->my);
  1275.         place_monster(mtmp, trapx, trapy);
  1276.         if (mtmp->wormno) worm_move(mtmp);
  1277.         newsym(trapx, trapy);
  1278.  
  1279.         (void) newcham(mtmp, (struct permonst *)0);
  1280.         return 2;
  1281. #endif
  1282.     case 0: return 0; /* i.e. an exploded wand */
  1283.     default: impossible("%s wanted to perform action %d?", Monnam(mtmp),
  1284.             m.has_misc);
  1285.         break;
  1286.     }
  1287.     return 0;
  1288. }
  1289.  
  1290. static void
  1291. you_aggravate(mtmp)
  1292. struct monst *mtmp;
  1293. {
  1294.     cls();
  1295.     show_glyph(mtmp->mx, mtmp->my, mon_to_glyph(mtmp));
  1296.     display_self();
  1297.     You("feel aggravated at %s.", mon_nam(mtmp));
  1298.     display_nhwindow(WIN_MAP, TRUE);
  1299.     docrt();
  1300.     if (unconscious()) {
  1301.         multi = -1;
  1302.         nomovemsg =
  1303.               "Aggravated, you are jolted into full consciousness.";
  1304.     }
  1305. }
  1306.  
  1307. int
  1308. rnd_misc_item(mtmp)
  1309. struct monst *mtmp;
  1310. {
  1311.     struct permonst *pm = mtmp->data;
  1312.     int difficulty = monstr[(monsndx(pm))];
  1313.  
  1314.     if(is_animal(pm) || attacktype(pm, AT_EXPL) || mindless(mtmp->data)
  1315.             || pm->mlet == S_GHOST
  1316. # ifdef KOPS
  1317.             || pm->mlet == S_KOP
  1318. # endif
  1319.         ) return 0;
  1320.     /* Unlike other rnd_item functions, we only allow _weak_ monsters
  1321.      * to have this item; after all, the item will be used to strengthen
  1322.      * the monster and strong monsters won't use it at all...
  1323.      */
  1324.     if (difficulty < 6 && !rn2(30)) return WAN_POLYMORPH;
  1325.     
  1326.     if (!rn2(40)) return AMULET_OF_LIFE_SAVING;
  1327.  
  1328.     switch (rn2(3)) {
  1329.         case 0:
  1330.             if (mtmp->isgd) return 0;
  1331.             return rn2(6) ? POT_SPEED : WAN_SPEED_MONSTER;
  1332.         case 1:
  1333.             if (mtmp->mpeaceful && !See_invisible) return 0;
  1334.             return rn2(6) ? POT_INVISIBILITY : WAN_MAKE_INVISIBLE;
  1335.         case 2:
  1336.             return POT_GAIN_LEVEL;
  1337.     }
  1338.     /*NOTREACHED*/
  1339.     return 0;
  1340. }
  1341.  
  1342. boolean
  1343. searches_for_item(mon, obj)
  1344. struct monst *mon;
  1345. struct obj *obj;
  1346. {
  1347.     int typ = obj->otyp;
  1348.  
  1349.     if (is_animal(mon->data) || mindless(mon->data)) return FALSE;
  1350.     return((boolean)((obj->oclass == WAND_CLASS && objects[typ].oc_dir == RAY)
  1351.         || typ == WAN_STRIKING
  1352.         || (!mon->minvis &&
  1353.             (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY))
  1354.         || (mon->mspeed != MFAST &&
  1355.             (typ == WAN_SPEED_MONSTER || typ == POT_SPEED))
  1356.         || typ == POT_HEALING
  1357.         || typ == POT_EXTRA_HEALING
  1358.         || typ == POT_GAIN_LEVEL
  1359.         || (monstr[monsndx(mon->data)] < 6 && typ == WAN_POLYMORPH)
  1360.         || (!is_floater(mon->data) && typ == WAN_DIGGING)
  1361.         || typ == WAN_TELEPORTATION
  1362.         || typ == SCR_TELEPORTATION
  1363.         || typ == WAN_CREATE_MONSTER
  1364.         || typ == SCR_CREATE_MONSTER
  1365.         || typ == POT_PARALYSIS
  1366.         || typ == POT_BLINDNESS
  1367.         || typ == POT_CONFUSION
  1368.         || (typ == PICK_AXE && needspick(mon->data))
  1369.         || typ == AMULET_OF_REFLECTION
  1370.         || typ == AMULET_OF_LIFE_SAVING
  1371.         || ((mon->misc_worn_check & W_ARMG) && typ == CORPSE
  1372.             && obj->corpsenm == PM_COCKATRICE)
  1373.     ));
  1374. }
  1375.  
  1376. boolean
  1377. mon_reflects(mon,str)
  1378. struct monst *mon;
  1379. const char *str;
  1380. {
  1381.     struct obj *orefl = which_armor(mon, W_ARMS);
  1382.  
  1383.     if (orefl && orefl->otyp == SHIELD_OF_REFLECTION) {
  1384.         if (str) {
  1385.         pline(str, s_suffix(mon_nam(mon)), "shield");
  1386.         makeknown(SHIELD_OF_REFLECTION);
  1387.         }
  1388.         return TRUE;
  1389.     } else if ((orefl = which_armor(mon, W_AMUL)) &&
  1390.                 orefl->otyp == AMULET_OF_REFLECTION) {
  1391.         if (str) {
  1392.         pline(str, s_suffix(mon_nam(mon)), "amulet");
  1393.         makeknown(AMULET_OF_REFLECTION);
  1394.         }
  1395.         return TRUE;
  1396.     }
  1397.     return FALSE;
  1398. }
  1399.  
  1400. #endif    /* MUSE */
  1401.  
  1402. /*muse.c*/
  1403.