home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d190 / nethack.lha / NetHack / twee.zoo / mon.c < prev    next >
C/C++ Source or Header  |  1988-07-23  |  21KB  |  837 lines

  1. /*    SCCS Id: @(#)mon.c      2.3     87/12/12
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include "hack.h"
  5. #include "mfndpos.h"
  6. extern struct monst *makemon(), *mkmon_at();
  7. extern struct trap *maketrap();
  8. extern struct obj *mkobj_at(), *mksobj_at();
  9. extern char *hcolor();
  10. #ifdef KAA
  11. extern boolean    stoned;
  12. extern char mlarge[];
  13. #endif
  14. #ifdef RPH
  15. extern struct obj *mk_named_obj_at();
  16. #endif
  17.  
  18. int warnlevel;        /* used by movemon and dochugw */
  19. long lastwarntime;
  20. int lastwarnlev;
  21. char    *warnings[] = { "white", "pink", "red", "ruby", "purple", "black"  };
  22.  
  23. movemon()
  24. {
  25.     register struct monst *mtmp;
  26.     register int fr;
  27.  
  28.     warnlevel = 0;
  29.  
  30.     while(1) {
  31.         /* find a monster that we haven't treated yet */
  32.         /* note that mtmp or mtmp->nmon might get killed
  33.            while mtmp moves, so we cannot just walk down the
  34.            chain (even new monsters might get created!) */
  35.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  36.             if(mtmp->mlstmv < moves) goto next_mon;
  37.         /* treated all monsters */
  38.         break;
  39.  
  40.     next_mon:
  41.         mtmp->mlstmv = moves;
  42.  
  43.         /* most monsters drown in pools */
  44.         { boolean inpool,infountain,iseel,isgremlin;
  45.           extern struct permonst pm_gremlin;
  46.  
  47.           inpool = (RM_TYP(levl[mtmp->mx][mtmp->my]) == POOL);
  48.           iseel = (mtmp->data->mlet == ';');
  49.           isgremlin = (mtmp->data->mlet == 'G' && mtmp->isgremlin);
  50.           infountain = (RM_TYP(levl[mtmp->mx][mtmp->my]) == FOUNTAIN);
  51.           if((inpool || infountain) && isgremlin && rn2(3)) {
  52.             coord mm;
  53.             enexto(&mm, mtmp->mx, mtmp->my);
  54.             if(cansee(mtmp->mx,mtmp->my) &&
  55.                makemon(PM_GREMLIN, mm.x, mm.y))
  56.                 pline("%s multiplies.", Monnam(mtmp));
  57.             if (infountain) dryup();
  58.           }
  59.           if(inpool && !iseel && !isgremlin) {
  60.             if(cansee(mtmp->mx,mtmp->my))
  61.                 pline("%s drowns.", Monnam(mtmp));
  62.             mondead(mtmp);
  63.             continue;
  64.           }
  65.         /* but eels have a difficult time outside */
  66.           if(iseel && !inpool) {
  67.             if(mtmp->mhp > 1) mtmp->mhp--;
  68.             mtmp->mflee = 1;
  69.             mtmp->mfleetim += 2;
  70.           }
  71.         }
  72.         if(mtmp->mblinded && !--mtmp->mblinded)
  73.             mtmp->mcansee = 1;
  74.         if(mtmp->mfleetim && !--mtmp->mfleetim)
  75.             mtmp->mflee = 0;
  76. #ifdef HARD
  77.         /* unwatched mimics and piercers may hide again  [MRS] */
  78.         if(restrap(mtmp))       continue;
  79. #endif
  80.         if(mtmp->mimic) continue;
  81.         if(mtmp->mspeed != MSLOW || !(moves%2)){
  82.             /* continue if the monster died fighting */
  83.             fr = -1;
  84.             if(Conflict && cansee(mtmp->mx,mtmp->my)
  85.                 && (fr = fightm(mtmp)) == 2)
  86.                 continue;
  87. #ifdef STOOGES
  88.             if((mtmp->isstooge) && cansee(mtmp->mx,mtmp->my)
  89.                 && (fr = fightm(mtmp)) == 2)
  90.                 continue;
  91. #endif
  92.             if(fr<0 && dochugw(mtmp))
  93.                 continue;
  94.         }
  95.         if(mtmp->mspeed == MFAST && dochugw(mtmp))
  96.             continue;
  97.     }
  98.  
  99.     warnlevel -= u.ulevel;
  100.     if(warnlevel >= SIZE(warnings))
  101.         warnlevel = SIZE(warnings)-1;
  102.     if(warnlevel >= 0)
  103.     if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
  104.         register char *rr;
  105.         switch((int) (Warning & (LEFT_RING | RIGHT_RING))){
  106.         case LEFT_RING:
  107.         rr = "Your left ring glows";
  108.         break;
  109.         case RIGHT_RING:
  110.         rr = "Your right ring glows";
  111.         break;
  112.         case LEFT_RING | RIGHT_RING:
  113.         rr = "Both your rings glow";
  114.         break;
  115.         default:
  116.         rr = "Your fingertips glow";
  117.         break;
  118.         }
  119.         pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
  120.         lastwarntime = moves;
  121.         lastwarnlev = warnlevel;
  122.     }
  123.  
  124.     dmonsfree();    /* remove all dead monsters */
  125. }
  126.  
  127. justswld(mtmp,name)
  128. register struct monst *mtmp;
  129. char *name;
  130. {
  131.  
  132.     mtmp->mx = u.ux;
  133.     mtmp->my = u.uy;
  134.     u.ustuck = mtmp;
  135.     pmon(mtmp);
  136.     kludge("%s swallows you!",name);
  137.     more();
  138.     seeoff(1);
  139.     u.uswallow = 1;
  140.     u.uswldtim = 0;
  141.     swallowed();
  142. }
  143.  
  144. youswld(mtmp,dam,die,name)
  145. register struct monst *mtmp;
  146. register dam,die;
  147. char *name;
  148. {
  149.     if(mtmp != u.ustuck) return;
  150.     kludge("%s digests you!",name);
  151.     u.uhp -= dam;
  152.     if(u.uswldtim++ >= die){        /* a3 */
  153.         pline("It totally digests you!");
  154.         u.uhp = -1;
  155.     }
  156.     if(u.uhp < 1) done_in_by(mtmp);
  157.     /* flags.botlx = 1;        /* should we show status line ? */
  158. }
  159.  
  160. #ifdef ROCKMOLE
  161. meatgold(mtmp) register struct monst *mtmp; {
  162. register struct gold *gold;
  163. register int pile;
  164. register struct obj *otmp;
  165. #ifdef KJSMODS
  166.     if(dlevel < 4) return;
  167. #endif
  168.     /* Eats gold if it is there */
  169.     while(gold = g_at(mtmp->mx, mtmp->my)){
  170.         freegold(gold);
  171.         /* Left behind a pile? */
  172.         pile = rnd(25);
  173.         if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my);
  174.         newsym(mtmp->mx, mtmp->my);
  175.     }
  176.     /* Eats armor if it is there */
  177.     otmp = o_at(mtmp->mx,mtmp->my);
  178.     if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){
  179.         freeobj(otmp);
  180.         /* Left behind a pile? */
  181.         pile = rnd(25);
  182.         if(pile < 3)  mksobj_at(ROCK, mtmp->mx, mtmp->my);
  183.         newsym(mtmp->mx, mtmp->my);
  184.     }
  185. }
  186. #endif /* ROCKMOLE /**/
  187.  
  188. mpickgold(mtmp) register struct monst *mtmp; {
  189. register struct gold *gold;
  190.     while(gold = g_at(mtmp->mx, mtmp->my)){
  191.         mtmp->mgold += gold->amount;
  192.         freegold(gold);
  193.         if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM)
  194.             newsym(mtmp->mx, mtmp->my);
  195.     }
  196. }
  197.  
  198. /* Now includes giants which pick up enormous rocks.  KAA */
  199. mpickgems(mtmp) register struct monst *mtmp; {
  200. register struct obj *otmp;
  201.     for(otmp = fobj; otmp; otmp = otmp->nobj)
  202.       if(otmp->olet ==
  203. #ifdef KAA
  204.                (mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM))
  205. #else
  206.                GEM_SYM)
  207. #endif
  208.         if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
  209.           if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){
  210.         freeobj(otmp);
  211.         mpickobj(mtmp, otmp);
  212. #ifndef KAA
  213.         if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)
  214. #endif
  215.             newsym(mtmp->mx, mtmp->my);     /* %% */
  216.         return; /* pick only one object */
  217.           }
  218. }
  219.  
  220. /* return number of acceptable neighbour positions */
  221. mfndpos(mon,poss,info,flag)
  222. register struct monst *mon;
  223. coord poss[9];
  224. long info[9], flag;
  225. {
  226.     register int x,y,nx,ny,cnt = 0,ntyp;
  227.     register struct monst *mtmp;
  228.     int nowtyp;
  229.     boolean pool;
  230.  
  231.     x = mon->mx;
  232.     y = mon->my;
  233.     nowtyp = RM_TYP(levl[x][y]);
  234.  
  235.     pool = (mon->data->mlet == ';');
  236. nexttry:    /* eels prefer the water, but if there is no water nearby,
  237.            they will crawl over land */
  238.     if(mon->mconf) {
  239.         flag |= ALLOW_ALL;
  240.         flag &= ~NOTONL;
  241.     }
  242.     for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++)
  243.     if(nx != x || ny != y) if(isok(nx,ny))
  244. #ifdef ROCKMOLE
  245.     if(!IS_ROCK(ntyp = RM_TYP(levl[nx][ny])) || (flag & ALLOW_WALL))
  246. #else
  247.     if(!IS_ROCK(ntyp = RM_TYP(levl[nx][ny])))
  248. #endif
  249.     if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR)))
  250.     if((ntyp == POOL) == pool) {
  251.         info[cnt] = 0;
  252.         if(nx == u.ux && ny == u.uy){
  253.             if(!(flag & ALLOW_U)) continue;
  254.             info[cnt] = ALLOW_U;
  255.         } else if(mtmp = m_at(nx,ny)){
  256.             if(!(flag & ALLOW_M)) continue;
  257.             info[cnt] = ALLOW_M;
  258.             if(mtmp->mtame){
  259.                 if(!(flag & ALLOW_TM)) continue;
  260.                 info[cnt] |= ALLOW_TM;
  261.             }
  262.         }
  263.         if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
  264.             if(flag & NOGARLIC) continue;
  265.             info[cnt] |= NOGARLIC;
  266.         }
  267.         if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||
  268.            (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) {
  269.             if(!(flag & ALLOW_SSM)) continue;
  270.             info[cnt] |= ALLOW_SSM;
  271.         }
  272.         if(sobj_at(ENORMOUS_ROCK, nx, ny)) {
  273.             if(!(flag & ALLOW_ROCK)) continue;
  274.             info[cnt] |= ALLOW_ROCK;
  275.         }
  276.         if(!Invis && online(nx,ny)){
  277.             if(flag & NOTONL) continue;
  278.             info[cnt] |= NOTONL;
  279.         }
  280.         /* we cannot avoid traps of an unknown kind */
  281.         { register struct trap *ttmp = t_at(nx, ny);
  282.           register long tt;
  283.             if(ttmp) {
  284. /*                tt = 1L << ttmp->ttyp;*/
  285. /* why don't we just have code look like what it's supposed to do? then it
  286. /* might start working for every case. try this instead: -sac */
  287.                 tt = (ttmp->ttyp < TRAPNUM && ttmp->ttyp > 0);
  288.                 /* below if added by GAN 02/06/87 to avoid
  289.                  * traps out of range
  290.                  */
  291.                 if(!(tt & ALLOW_TRAPS))  {
  292.                     impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
  293.                     continue;
  294.                 }
  295.                 if(mon->mtrapseen & tt){
  296.                     if(!(flag & tt)) continue;
  297.                     info[cnt] |= tt;
  298.                 }
  299.             }
  300.         }
  301.         poss[cnt].x = nx;
  302.         poss[cnt].y = ny;
  303.         cnt++;
  304.     }
  305.     if(!cnt && pool && nowtyp != POOL) {
  306.         pool = FALSE;
  307.         goto nexttry;
  308.     }
  309.     return(cnt);
  310. }
  311.  
  312. dist(x,y) int x,y; {
  313.     return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy));
  314. }
  315.  
  316. poisoned(string, pname)
  317. register char *string, *pname;
  318. {
  319.     register i, plural;
  320.  
  321.     plural = (string[strlen(string) - 1] == 's')? 1 : 0;
  322.     if(Blind) {
  323.         if (plural)     pline("They were poisoned.");
  324.         else        pline("It was poisoned.");
  325.     } else    {
  326.         if (plural)     pline("The %s were poisoned!", string);
  327.         else        pline("The %s was poisoned!", string);
  328.     }
  329.  
  330.     if(Poison_resistance) {
  331.         pline("The poison doesn't seem to affect you.");
  332.         return;
  333.     }
  334.     i = rn2(10);
  335.     if(i == 0) {
  336.         u.uhp = -1;
  337.         pline("I am afraid the poison was deadly ...");
  338.     } else if(i <= 5) {
  339.         losestr(rn1(3,3));
  340.     } else {
  341.         losehp(rn1(10,6), pname);
  342.     }
  343.     if(u.uhp < 1) {
  344.         killer = pname;
  345.         done("died");
  346.     }
  347. }
  348.  
  349. mondead(mtmp)
  350. register struct monst *mtmp;
  351. {
  352.     relobj(mtmp,1);
  353.     unpmon(mtmp);
  354.     relmon(mtmp);
  355.     unstuck(mtmp);
  356. #ifdef KOPS
  357.        if(mtmp->data->mlet == 'K' &&
  358.       !strcmp(mtmp->data->mname,"Keystone Kop")) {
  359.        /* When a Kop dies, he probably comes back. */
  360.        switch(rnd(3)) {
  361.  
  362.         case 1:      /* returns near the stairs */
  363.             mkmon_at('K',xdnstair,ydnstair);
  364.             break;
  365.         case 2:      /* randomly */
  366.             mkmon_at('K',0,0);
  367.             break;
  368.         default:
  369.             break;
  370.        }
  371.       }
  372. #endif
  373.     if(mtmp->isshk) shkdead(mtmp);
  374.     if(mtmp->isgd) gddead();
  375. #ifndef NOWORM
  376.     if(mtmp->wormno) wormdead(mtmp);
  377. #endif
  378. #ifdef HARD
  379.     if(mtmp->data->mlet == '1') wizdead(mtmp);
  380. #endif
  381.     monfree(mtmp);
  382. }
  383.  
  384. /* called when monster is moved to larger structure */
  385. replmon(mtmp,mtmp2)
  386. register struct monst *mtmp, *mtmp2;
  387. {
  388.     relmon(mtmp);
  389.     monfree(mtmp);
  390.     mtmp2->nmon = fmon;
  391.     fmon = mtmp2;
  392.     if(u.ustuck == mtmp) u.ustuck = mtmp2;
  393.     if(mtmp2->isshk) replshk(mtmp,mtmp2);
  394.     if(mtmp2->isgd) replgd(mtmp,mtmp2);
  395. }
  396.  
  397. relmon(mon)
  398. register struct monst *mon;
  399. {
  400.     register struct monst *mtmp;
  401.  
  402.     if (fmon == 0)  panic ("relmon: no fmon available.");
  403.  
  404.     if(mon == fmon) fmon = fmon->nmon;
  405.     else {
  406.         for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
  407.         mtmp->nmon = mon->nmon;
  408.     }
  409. }
  410.  
  411. /* we do not free monsters immediately, in order to have their name
  412.    available shortly after their demise */
  413. struct monst *fdmon;    /* chain of dead monsters, need not to be saved */
  414.  
  415. monfree(mtmp) register struct monst *mtmp; {
  416.     mtmp->nmon = fdmon;
  417.     fdmon = mtmp;
  418. }
  419.  
  420. dmonsfree(){
  421. register struct monst *mtmp;
  422.     while(mtmp = fdmon){
  423.         fdmon = mtmp->nmon;
  424.         free((char *) mtmp);
  425.     }
  426. }
  427.  
  428. unstuck(mtmp)
  429. register struct monst *mtmp;
  430. {
  431.     if(u.ustuck == mtmp) {
  432.         if(u.uswallow){
  433.             u.ux = mtmp->mx;
  434.             u.uy = mtmp->my;
  435.             u.uswallow = 0;
  436.             setsee();
  437.             docrt();
  438.         }
  439.         u.ustuck = 0;
  440.     }
  441. }
  442.  
  443. killed(mtmp)
  444. register struct monst *mtmp;
  445. {
  446.     xkilled(mtmp, 1);
  447. }
  448.  
  449. xkilled(mtmp, dest)
  450. register struct monst *mtmp;
  451. int    dest;
  452. /* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
  453.    either; dest=3, message but no corpse */
  454. {
  455. #ifdef LINT
  456. #define NEW_SCORING
  457. #endif
  458.     register int tmp,tmp2,nk,x,y;
  459.     register struct permonst *mdat = mtmp->data;
  460.     extern long newuexp();
  461. #ifdef RPH
  462.     int old_nlth;
  463.     char old_name[BUFSZ];
  464. #endif
  465.  
  466.     if(mtmp->cham) mdat = PM_CHAMELEON;
  467.     if (dest & 1) {
  468.         if(Blind) pline("You destroy it!");
  469.         else {
  470.         pline("You destroy %s!",
  471.             mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp));
  472.         }
  473.     }
  474.     if(u.umconf) {
  475.         if(!Blind)
  476.         {
  477.             pline("Your hands stop glowing %s.",
  478.             Hallucination ? hcolor() : "blue");
  479.         }
  480.         u.umconf = 0;
  481.     }
  482.  
  483.     /* count killed monsters */
  484. #define MAXMONNO    100
  485.     nk = 1;           /* in case we cannot find it in mons */
  486.     tmp = mdat - mons;    /* index in mons array (if not 'd', '@', ...) */
  487.     if(tmp >= 0 && tmp < CMNUM+2) {
  488.         extern char fut_geno[];
  489.         u.nr_killed[tmp]++;
  490.         if((nk = u.nr_killed[tmp]) > MAXMONNO &&
  491. #ifdef HARD
  492. # ifdef KOPS
  493.         !index("KkO&", mdat->mlet) &&
  494. # else
  495.         !index("kO&", mdat->mlet) &&
  496. # endif
  497. #endif
  498.         !index(fut_geno, mdat->mlet))
  499.             charcat(fut_geno,  mdat->mlet);
  500.     }
  501.  
  502.     /* punish bad behaviour */
  503.     if(mdat->mlet == '@') {
  504.         HTelepat = 0;
  505.         change_luck(-2);
  506.     }
  507.     if(mtmp->mpeaceful || mtmp->mtame)      change_luck(-1);
  508.     if(mdat->mlet == 'u')                   change_luck(-5);
  509.  
  510.     /* give experience points */
  511.     tmp = 1 + mdat->mlevel * mdat->mlevel;
  512.     if(mdat->ac < 3) tmp += 2*(7 - mdat->ac);
  513.     if(index("AcsSDXaeRTVWU&In:P389",mdat->mlet)) tmp += 2*mdat->mlevel;
  514.     if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel);
  515.     if(mdat->mlevel > 6) tmp += 50;
  516.     if(mdat->mlet == ';') tmp += 1000;
  517.  
  518. #ifdef NEW_SCORING
  519.     /* ------- recent addition: make nr of points decrease
  520.            when this is not the first of this kind */
  521.     { int ul = u.ulevel;
  522.       int ml = mdat->mlevel;
  523.  
  524.     if(ul < 14)    /* points are given based on present and future level */
  525.         for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++)
  526.         if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk
  527.             >= 10*pow((unsigned)(ul-1)))
  528.             if(++ul == 14) break;
  529.  
  530.     tmp2 = ml - ul -1;
  531.     tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk;
  532.     if(!tmp) tmp = 1;
  533.     }
  534.     /* note: ul is not necessarily the future value of u.ulevel */
  535.     /* ------- end of recent valuation change ------- */
  536. #endif /* NEW_SCORING /**/
  537.  
  538.     more_experienced(tmp,0);
  539.     flags.botl = 1;
  540.     while(u.ulevel < 14 && u.uexp >= newuexp()){
  541. #ifdef RPH
  542.         /* make experience gaining simiar to d&d, whereby you */
  543.         /* can at most go up by one level at a time, extra expr */
  544.         /* possibly helping you along. Afterall, how much real */
  545.         /* experience does one get shooting a wand of death at */
  546.         /* a dragon created w/ a poymorph?? */
  547.         u.ulevel++;
  548.         if (u.uexp >= newuexp())
  549.             u.uexp = newuexp() - 1;
  550.         pline("Welcome to experience level %u.", u.ulevel);
  551. #else
  552.         pline("Welcome to experience level %u.", ++u.ulevel);
  553. #endif
  554.         tmp = rnd(10);
  555.         if(tmp < 3) tmp = rnd(10);
  556.         u.uhpmax += tmp;
  557.         u.uhp += tmp;
  558. #ifdef SPELLS
  559.         tmp = rnd(u.ulevel/2+1) + 1;    /* M. Stephenson */
  560.         u.uenmax += tmp;
  561.         u.uen += tmp;
  562. #endif
  563.         flags.botl = 1;
  564.     }
  565.  
  566.     /* dispose of monster and make cadaver */
  567.     x = mtmp->mx;    y = mtmp->my;
  568. #ifdef RPH
  569.     old_nlth = mtmp->mnamelth;
  570.     if (old_nlth > 0)  (void) strcpy (old_name, NAME(mtmp));
  571. #endif
  572.     if (mdat->mlet == '&' && mtmp->isdjinni) { /* no djinni corpse */
  573.         mondead(mtmp);
  574.         return;
  575.     }
  576.     if (mdat->mlet == 'G' && mtmp->isgremlin) { /* no gremlin corpse */
  577.         mondead(mtmp);
  578.         return;
  579.     }
  580.     mondead(mtmp);
  581.     tmp = mdat->mlet;
  582.     if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */
  583.             /* note: the dead minotaur will be on top of it! */
  584.         mksobj_at(WAN_DIGGING, x, y);
  585.         /* if(cansee(x,y)) atl(x,y,fobj->olet); */
  586.         stackobj(fobj);
  587.     } else
  588. #ifndef NOWORM
  589.     if(tmp == 'w') {
  590.         mksobj_at(WORM_TOOTH, x, y);
  591.         stackobj(fobj);
  592.     } else
  593. #endif
  594. #ifdef KJSMODS
  595.     if(tmp == 'N') {
  596.         mksobj_at(POT_OBJECT_DETECTION, x, y);
  597.         stackobj(fobj);
  598.     } else
  599. #endif
  600. #ifdef SAC
  601.     if(tmp == '3') {
  602.         ; /* don't do anything special- keep it from failing on */
  603.           /* call to letter(tmp) */
  604.     } else
  605. #endif /* SAC */
  606. #ifdef KAA
  607.     if(tmp == '&') (void) mkobj_at(0, x, y);
  608.     else
  609.     if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0;
  610.         if(dest & 2) {
  611.         newsym(x,y);
  612.         return;
  613.         }
  614. #else
  615.     if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0;
  616. #endif
  617.     tmp2 = rn2(5);
  618. #ifdef KJSMODS
  619.     /* if a kobold or a giant rat does not become treasure, do
  620.      *  not make a corpse. */
  621. # ifdef KOPS
  622.     if(mdat->mlet == 'K'
  623.        && !strcmp(mdat->mname,"kobold") && tmp) tmp2 = 0;
  624. # endif
  625. # ifdef ROCKMOLE
  626.     if((mdat->mlet == 'r' && dlevel < 4) && tmp) tmp2 = 0;
  627. # endif
  628. #endif
  629.     if(!ACCESSIBLE(RM_TYP(levl[x][y]))) {
  630.         /* might be mimic in wall or dead eel*/
  631.         newsym(x,y);
  632.     } else if(x != u.ux || y != u.uy) {
  633.         /* might be here after swallowed */
  634. #ifdef KAA
  635.         if(stoned) {
  636.             register int typetmp;
  637.             if(index(mlarge, tmp))  typetmp = ENORMOUS_ROCK;
  638.             else            typetmp = ROCK;
  639.             mksobj_at(typetmp, x, y);
  640.             if(cansee(x,y))
  641.                 atl(x, y, Hallucination ? rndobjsym() :
  642.                       objects[typetmp].oc_olet);
  643.         } else
  644. #endif
  645.         if(index("NTVm&w",mdat->mlet) || tmp2) {
  646. #ifndef RPH
  647.             register struct obj *obj2 = mkobj_at(tmp,x,y);
  648. #else
  649.             register struct obj *obj2;
  650.             if (letter(tmp))
  651.                 obj2 = mk_named_obj_at(tmp, x, y,
  652.                            old_name, old_nlth);
  653. # ifdef KOPS
  654.             else if (mdat->mlet == 'K')
  655.                 obj2 = mksobj_at((rn2(2) ? CLUB :
  656.                    (rn2(2)) ? WHISTLE : BADGE), x, y);
  657. # endif
  658.             else
  659.                 obj2 = mkobj_at(tmp,x,y);
  660. #endif     /* RPH /**/
  661.             if(cansee(x,y))
  662.                 atl(x, y, Hallucination ? rndobjsym() : obj2->olet);
  663.             stackobj(obj2);
  664.         }
  665.     }
  666. }
  667.  
  668. kludge(str,arg)
  669. register char *str,*arg;
  670. {
  671.     if(Blind) {
  672.         if(*str == '%') pline(str,"It");
  673.         else pline(str,"it");
  674.     } else pline(str,arg);
  675. }
  676.  
  677. rescham()       /* force all chameleons to become normal */
  678. {
  679.     register struct monst *mtmp;
  680.  
  681.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  682.         if(mtmp->cham) {
  683.             mtmp->cham = 0;
  684.             (void) newcham(mtmp, PM_CHAMELEON);
  685.         }
  686. }
  687.  
  688. #ifdef DGKMOD
  689. /* Let the chameleons change again -dgk */
  690. restartcham()
  691. {
  692.     register struct monst *mtmp;
  693.  
  694.     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  695.         if (mtmp->data->mlet == ':')
  696.             mtmp->cham = 1;
  697. }
  698. #endif
  699.  
  700. newcham(mtmp,mdat)      /* make a chameleon look like a new monster */
  701.             /* returns 1 if the monster actually changed */
  702. register struct monst *mtmp;
  703. register struct permonst *mdat;
  704. {
  705.     register mhp, hpn, hpd;
  706.  
  707. #ifdef RPH
  708.     /* mdat = 0 -> caller wants a random monster shape */
  709.     if (mdat == 0) {
  710.         /* ie. minimum shape is mons[15], minimum random range */
  711.         /* is 3, and randomness tails off as you descend into the */
  712.         /* depths max shape is mons[CMNUM-1] */
  713.     mdat = &mons[CMNUM-1-rn2((CMNUM-17) - (CMNUM-20)*dlevel/MAXLEVEL)];
  714.     }
  715. #endif
  716.     if(mdat == mtmp->data) return(0);       /* still the same monster */
  717. #ifndef NOWORM
  718.     if(mtmp->wormno) wormdead(mtmp);        /* throw tail away */
  719. #endif
  720.     hpn = mtmp->mhp;
  721.     hpd = (mtmp->data->mlevel)*8;   if(!hpd) hpd = 4;
  722.     mhp = (mdat->mlevel)*8;         if(!mhp) mhp = 4;
  723.  
  724.     /* new hp: same fraction of max as before */
  725.     mtmp->mhp = (hpn*mhp)/hpd;
  726.     if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127;
  727. /* Not totally foolproof.  A 2HD monster with 80 HP that changes into a 6HD
  728.    monster that really should have 240 and actually should have 127, the
  729.    maximum possible, will wind up having 113.  */
  730.     if (!mtmp->mhp) mtmp->mhp = 1;
  731. /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
  732.    0HD creature will require this statement */
  733.     mtmp->data = mdat;
  734. /* and the same for maximum hit points */
  735.     hpn = mtmp->mhpmax;
  736.     mtmp->mhpmax = (hpn*mhp)/hpd;
  737.     if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127;
  738.     if (!mtmp->mhp) mtmp->mhp = 1;
  739.  
  740.     mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0;
  741.     /* only snakes and scorpions can hide under things -dgk */
  742.     /* also generated by GAN */
  743.     mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0;
  744.     if (!mtmp->mhide) mtmp->mundetected = 0;
  745. #ifndef NOWORM
  746.     if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp);
  747.             /* perhaps we should clear mtmp->mtame here? */
  748. #endif
  749.     unpmon(mtmp);   /* necessary for 'I' and to force pmon */
  750.     pmon(mtmp);
  751.     return(1);
  752. }
  753.  
  754. mnexto(mtmp)    /* Make monster mtmp next to you (if possible) */
  755. struct monst *mtmp;
  756. {
  757.     coord mm;
  758.     enexto(&mm, u.ux, u.uy);
  759.     mtmp->mx = mm.x;
  760.     mtmp->my = mm.y;
  761.     pmon(mtmp);
  762. }
  763.  
  764. ishuman(mtmp) register struct monst *mtmp; {
  765.     return(mtmp->data->mlet == '@');
  766. }
  767.  
  768. setmangry(mtmp) register struct monst *mtmp; {
  769.     if(!mtmp->mpeaceful) return;
  770.     if(mtmp->mtame) return;
  771.     mtmp->mpeaceful = 0;
  772.     if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp));
  773. }
  774.  
  775. /* not one hundred procent correct: now a snake may hide under an
  776.    invisible object */
  777. canseemon(mtmp)
  778. register struct monst *mtmp;
  779. {
  780.     return((!mtmp->minvis || See_invisible)
  781.         && (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my))
  782.         && cansee(mtmp->mx, mtmp->my));
  783. }
  784.  
  785. disturb(mtmp)           /* awaken monsters while in the same room.
  786.              * return a 1 if they have been woken.
  787.              */
  788. register struct monst *mtmp;
  789. {
  790.     /* wake up, or get out of here. */
  791.     /* ettins are hard to surprise */
  792.     /* Nymphs and Leprechauns do not easily wake up */
  793.     if(cansee(mtmp->mx,mtmp->my) &&
  794.         (!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) &&
  795.         (!index("NL",mtmp->data->mlet) || !rn2(50)) &&
  796. #ifdef RPH
  797.         (Aggravate_monster || index("8d1", mtmp->data->mlet)
  798. #else
  799.         (Aggravate_monster || index("d1", mtmp->data->mlet)
  800. #endif
  801.             || (!rn2(7) && !mtmp->mimic))) {
  802.         mtmp->msleep = 0;
  803.         return(1);
  804.     }
  805.     if(Hallucination) pmon(mtmp);
  806.     return(0);
  807. }
  808.  
  809. #ifdef HARD
  810. restrap(mtmp)           /* unwatched mimics and piercers may hide again,
  811.              * if so, a 1 is returned.
  812.              */
  813. register struct monst *mtmp;
  814. {
  815.     if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham
  816.        && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
  817.        && !rn2(3)) {
  818.         mtmp->mimic = 1;
  819.         mtmp->mappearance = (RM_TYP(levl[mtmp->mx][mtmp->my]) == DOOR) ? DOOR_SYM : GOLD_SYM;
  820.         return(1);
  821.        }
  822.  
  823.     if(mtmp->data->mlet == 'p' && !mtmp->cham
  824.        && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
  825.        && !rn2(3))  {
  826.  
  827.         if(RM_TYP(levl[mtmp->mx][mtmp->my]) == ROOM)  {
  828.  
  829.             maketrap(mtmp->mx, mtmp->my, PIERC);
  830.             mondead(mtmp);
  831.             return(1);
  832.         }
  833.        }
  834.     return(0);
  835. }
  836. #endif
  837.