home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HACKSRC.ZIP / HACK.C < prev    next >
C/C++ Source or Header  |  1985-10-16  |  21KB  |  892 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.c - version 1.0.3 */
  3.  
  4. #include <stdio.h>
  5. #include "hack.h"
  6.  
  7. extern char news0();
  8. extern char *nomovemsg;
  9. extern char *exclam();
  10. extern struct obj *addinv();
  11. extern boolean hmon();
  12.  
  13. /* called on movement:
  14.     1. when throwing ball+chain far away
  15.     2. when teleporting
  16.     3. when walking out of a lit room
  17.  */
  18. unsee() {
  19.     register x,y;
  20.     register struct rm *lev;
  21.  
  22. /*
  23.     if(u.udispl){
  24.         u.udispl = 0;
  25.         newsym(u.udisx, u.udisy);
  26.     }
  27. */
  28. #ifndef QUEST
  29.     if(seehx){
  30.         seehx = 0;
  31.     } else
  32. #endif QUEST
  33.     for(x = u.ux-1; x < u.ux+2; x++)
  34.       for(y = u.uy-1; y < u.uy+2; y++) {
  35.         if(!isok(x, y)) continue;
  36.         lev = &levl[x][y];
  37. #ifdef DGK
  38.         if(!lev->lit && lev->scrsym == symbol.room) {
  39. #else
  40.         if(!lev->lit && lev->scrsym == '.') {
  41. #endif DGK
  42.             lev->scrsym =' ';
  43.             lev->new = 1;
  44.             on_scr(x,y);
  45.         }
  46.     }
  47. }
  48.  
  49. /* called:
  50.     in eat.c: seeoff(0) - blind after eating rotten food
  51.     in mon.c: seeoff(0) - blinded by a yellow light
  52.     in mon.c: seeoff(1) - swallowed
  53.     in do.c:  seeoff(0) - blind after drinking potion
  54.     in do.c:  seeoff(1) - go up or down the stairs
  55.     in trap.c:seeoff(1) - fall through trapdoor
  56.  */
  57. seeoff(mode)    /* 1 to redo @, 0 to leave them */
  58. {    /* 1 means misc movement, 0 means blindness */
  59.     register x,y;
  60.     register struct rm *lev;
  61.  
  62.     if(u.udispl && mode){
  63.         u.udispl = 0;
  64.         levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy);
  65.     }
  66. #ifndef QUEST
  67.     if(seehx) {
  68.         seehx = 0;
  69.     } else
  70. #endif QUEST
  71.     if(!mode) {
  72.         for(x = u.ux-1; x < u.ux+2; x++)
  73.             for(y = u.uy-1; y < u.uy+2; y++) {
  74.                 if(!isok(x, y)) continue;
  75.                 lev = &levl[x][y];
  76. #ifdef DGK
  77.                 if(!lev->lit && lev->scrsym == symbol.room)
  78. #else
  79.                 if(!lev->lit && lev->scrsym == '.')
  80. #endif DGK
  81.                     lev->seen = 0;
  82.             }
  83.     }
  84. }
  85.  
  86. domove()
  87. {
  88.     xchar oldx,oldy;
  89.     register struct monst *mtmp;
  90.     register struct rm *tmpr,*ust;
  91.     struct trap *trap;
  92.     register struct obj *otmp;
  93.  
  94.     u_wipe_engr(rnd(5));
  95.  
  96.     if(inv_weight() > 0){
  97.         pline("You collapse under your load.");
  98.         nomul(0);
  99.         return;
  100.     }
  101.     if(u.uswallow) {
  102.         u.dx = u.dy = 0;
  103.         u.ux = u.ustuck->mx;
  104.         u.uy = u.ustuck->my;
  105.     } else {
  106.         if(Confusion) {
  107.             do {
  108.                 confdir();
  109.             } while(!isok(u.ux+u.dx, u.uy+u.dy) ||
  110.                 IS_ROCK(levl[u.ux+u.dx][u.uy+u.dy].typ));
  111.         }
  112.         if(!isok(u.ux+u.dx, u.uy+u.dy)){
  113.             nomul(0);
  114.             return;
  115.         }
  116.     }
  117.  
  118.     ust = &levl[u.ux][u.uy];
  119.     oldx = u.ux;
  120.     oldy = u.uy;
  121.     if(!u.uswallow && (trap = t_at(u.ux+u.dx, u.uy+u.dy)) && trap->tseen)
  122.         nomul(0);
  123.     if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx ||
  124.         u.uy+u.dy != u.ustuck->my)) {
  125.         if(dist(u.ustuck->mx, u.ustuck->my) > 2){
  126.             /* perhaps it fled (or was teleported or ... ) */
  127.             u.ustuck = 0;
  128.         } else {
  129.             if(Blind) pline("You cannot escape from it!");
  130.             else pline("You cannot escape from %s!",
  131.                 monnam(u.ustuck));
  132.             nomul(0);
  133.             return;
  134.         }
  135.     }
  136.     if(u.uswallow || (mtmp = m_at(u.ux+u.dx,u.uy+u.dy))) {
  137.     /* attack monster */
  138.  
  139.         nomul(0);
  140.         gethungry();
  141.         if(multi < 0) return;    /* we just fainted */
  142.  
  143.         /* try to attack; note that it might evade */
  144.         if(attack(u.uswallow ? u.ustuck : mtmp))
  145.             return;
  146.     }
  147.     /* not attacking an animal, so we try to move */
  148.     if(u.utrap) {
  149.         if(u.utraptype == TT_PIT) {
  150.             pline("You are still in a pit.");
  151.             u.utrap--;
  152.         } else {
  153.             pline("You are caught in a beartrap.");
  154.             if((u.dx && u.dy) || !rn2(5)) u.utrap--;
  155.         }
  156.         return;
  157.     }
  158.     tmpr = &levl[u.ux+u.dx][u.uy+u.dy];
  159.     if(IS_ROCK(tmpr->typ) ||
  160.        (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){
  161.         flags.move = 0;
  162.         nomul(0);
  163.         return;
  164.     }
  165.     if (moverock() < 0) return;
  166.     if(u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy+u.dy].typ) &&
  167.         IS_ROCK(levl[u.ux+u.dx][u.uy].typ) &&
  168.         invent && inv_weight()+40 > 0) {
  169.         pline("You are carrying too much to get through.");
  170.         nomul(0);
  171.         return;
  172.     }
  173.     if(Punished &&
  174.        DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){
  175.         if(carried(uball)) {
  176.             movobj(uchain, u.ux, u.uy);
  177.             goto nodrag;
  178.         }
  179.  
  180.         if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){
  181.             /* leave ball, move chain under/over ball */
  182.             movobj(uchain, uball->ox, uball->oy);
  183.             goto nodrag;
  184.         }
  185.  
  186.         if(inv_weight() + (int) uball->owt/2 > 0) {
  187.             pline("You cannot %sdrag the heavy iron ball.",
  188.             invent ? "carry all that and also " : "");
  189.             nomul(0);
  190.             return;
  191.         }
  192.  
  193.         movobj(uball, uchain->ox, uchain->oy);
  194.         unpobj(uball);        /* BAH %% */
  195.         uchain->ox = u.ux;
  196.         uchain->oy = u.uy;
  197.         nomul(-2);
  198.         nomovemsg = "";
  199.     nodrag:    ;
  200.     }
  201.     u.ux += u.dx;
  202.     u.uy += u.dy;
  203.     if(flags.run) {
  204.         if(tmpr->typ == DOOR ||
  205.         (xupstair == u.ux && yupstair == u.uy) ||
  206.         (xdnstair == u.ux && ydnstair == u.uy))
  207.             nomul(0);
  208.     }
  209.  
  210.     if(tmpr->typ == POOL && !Levitation)
  211.         drown();    /* not necessarily fatal */
  212.  
  213. /*
  214.     if(u.udispl) {
  215.         u.udispl = 0;
  216.         newsym(oldx,oldy);
  217.     }
  218. */
  219.     if(!Blind) {
  220. #ifdef QUEST
  221.         setsee();
  222. #else
  223.         if(ust->lit) {
  224.             if(tmpr->lit) {
  225.                 if(tmpr->typ == DOOR)
  226.                     prl1(u.ux+u.dx,u.uy+u.dy);
  227.                 else if(ust->typ == DOOR)
  228.                     nose1(oldx-u.dx,oldy-u.dy);
  229.             } else {
  230.                 unsee();
  231.                 prl1(u.ux+u.dx,u.uy+u.dy);
  232.             }
  233.         } else {
  234.             if(tmpr->lit) setsee();
  235.             else {
  236.                 prl1(u.ux+u.dx,u.uy+u.dy);
  237.                 if(tmpr->typ == DOOR) {
  238.                     if(u.dy) {
  239.                         prl(u.ux-1,u.uy);
  240.                         prl(u.ux+1,u.uy);
  241.                     } else {
  242.                         prl(u.ux,u.uy-1);
  243.                         prl(u.ux,u.uy+1);
  244.                     }
  245.                 }
  246.             }
  247.             nose1(oldx-u.dx,oldy-u.dy);
  248.         }
  249. #endif QUEST
  250.     } else {
  251.         pru();
  252.     }
  253.     if(!flags.nopick) pickup(1);
  254.     if(trap) dotrap(trap);        /* fall into pit, arrow trap, etc. */
  255.     (void) inshop();
  256.     if(!Blind) read_engr_at(u.ux,u.uy);
  257. }
  258.  
  259. static
  260. moverock() {
  261.     register xchar rx, ry;
  262.     register struct obj *otmp;
  263.     register struct trap *ttmp;
  264.  
  265.     while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) {
  266.         rx = u.ux+2*u.dx;
  267.         ry = u.uy+2*u.dy;
  268.         nomul(0);
  269.         if(isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
  270.             (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) &&
  271.             !sobj_at(ENORMOUS_ROCK, rx, ry)) {
  272.             if(m_at(rx,ry)) {
  273.                 pline("You hear a monster behind the rock.");
  274.                 pline("Perhaps that's why you cannot move it.");
  275.                 goto cannot_push;
  276.             }
  277.             if(ttmp = t_at(rx,ry))
  278.                 switch(ttmp->ttyp) {
  279.                 case PIT:
  280.                 pline("You push the rock into a pit!");
  281.                 deltrap(ttmp);
  282.                 delobj(otmp);
  283.                 pline("It completely fills the pit!");
  284.                 continue;
  285.                 case TELEP_TRAP:
  286.                 pline("You push the rock and suddenly it disappears!");
  287.                 delobj(otmp);
  288.                 continue;
  289.                 }
  290.             if(levl[rx][ry].typ == POOL) {
  291.                 levl[rx][ry].typ = ROOM;
  292.                 mnewsym(rx,ry);
  293.                 prl(rx,ry);
  294.                 pline("You push the rock into the water.");
  295.                 pline("Now you can cross the water!");
  296.                 delobj(otmp);
  297.                 continue;
  298.             }
  299.             otmp->ox = rx;
  300.             otmp->oy = ry;
  301.             /* pobj(otmp); */
  302.             if(cansee(rx,ry)) atl(rx,ry,otmp->olet);
  303.             if(Invisible) newsym(u.ux+u.dx, u.uy+u.dy);
  304.  
  305.             { static long lastmovetime;
  306.             /* note: this var contains garbage initially and
  307.                after a restore */
  308.             if(moves > lastmovetime+2 || moves < lastmovetime)
  309.             pline("With great effort you move the enormous rock.");
  310.             lastmovetime = moves;
  311.             }
  312.         } else {
  313.             pline("You try to move the enormous rock, but in vain.");
  314.         cannot_push:
  315.             if((!invent || inv_weight()+90 <= 0) &&
  316.             (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
  317.                     && IS_ROCK(levl[u.ux+u.dx][u.uy].typ)))){
  318.             pline("However, you can squeeze yourself into a small opening.");
  319.             break;
  320.             } else
  321.             return (-1);
  322.         }
  323.     }
  324.     return (0);
  325. }
  326.  
  327. movobj(obj, ox, oy)
  328. register struct obj *obj;
  329. register int ox, oy;
  330. {
  331.     /* Some dirty programming to get display right */
  332.     freeobj(obj);
  333.     unpobj(obj);
  334.     obj->nobj = fobj;
  335.     fobj = obj;
  336.     obj->ox = ox;
  337.     obj->oy = oy;
  338. }
  339.  
  340. dopickup(){
  341.     if(!g_at(u.ux,u.uy) && !o_at(u.ux,u.uy)) {
  342.         pline("There is nothing here to pick up.");
  343.         return(0);
  344.     }
  345.     if(Levitation) {
  346.         pline("You cannot reach the floor.");
  347.         return(1);
  348.     }
  349.     pickup(0);
  350.     return(1);
  351. }
  352.  
  353. pickup(all)
  354. {
  355.     register struct gold *gold;
  356.     register struct obj *obj, *obj2;
  357.     register int wt;
  358.  
  359.     if(Levitation) return;
  360. #ifdef DGK
  361.     if (all && !flags.pickup) {
  362.         int ct = 0;
  363.  
  364.         for (obj = fobj; obj; obj = obj->nobj)
  365.             if (obj->ox == u.ux && obj->oy == u.uy)
  366.                 if (!Punished || obj != uchain)
  367.                     ct++;
  368.         /* If there are any objects here, or if there is some gold
  369.          * here, stop running and take a look.
  370.          */
  371.         if (ct || g_at(u.ux, u.uy)) {
  372.             if (flags.run)
  373.                  nomul(0);
  374.             /* Show my position (but monsters haven't moved yet)
  375.              */
  376.             nscr();
  377.             dolook();
  378.         }
  379.         return;
  380.     }
  381. #endif DGK
  382.     while(gold = g_at(u.ux,u.uy)) {
  383.         pline("%ld gold piece%s.", gold->amount, plur(gold->amount));
  384.         u.ugold += gold->amount;
  385.         flags.botl = 1;
  386.         freegold(gold);
  387.         if(flags.run) nomul(0);
  388.         if(Invisible) newsym(u.ux,u.uy);
  389.     }
  390.     /* check for more than one object */
  391.     if(!all) {
  392.         register int ct = 0;
  393.  
  394.         for(obj = fobj; obj; obj = obj->nobj)
  395.             if(obj->ox == u.ux && obj->oy == u.uy)
  396.                 if(!Punished || obj != uchain)
  397.                     ct++;
  398.         if(ct < 2)
  399.             all++;
  400.         else
  401.             pline("There are several objects here.");
  402.     }
  403.  
  404.     for(obj = fobj; obj; obj = obj2) {
  405.         obj2 = obj->nobj;    /* perhaps obj will be picked up */
  406.         if(obj->ox == u.ux && obj->oy == u.uy) {
  407.         if(flags.run) nomul(0);
  408.  
  409.         /* do not pick up uchain */
  410.         if(Punished && obj == uchain)
  411.             continue;
  412.  
  413.         if(!all) {
  414.             char c;
  415.  
  416.             pline("Pick up %s ? [ynaq]", doname(obj));
  417.             while(!index("ynaq ", (c = readchar())))
  418.                 bell();
  419.             if(c == 'q') return;
  420.             if(c == 'n') continue;
  421.             if(c == 'a') all = 1;
  422.         }
  423.  
  424.         if(obj->otyp == DEAD_COCKATRICE && !uarmg){
  425.             pline("Touching the dead cockatrice is a fatal mistake.");
  426.             pline("You turn to stone.");
  427.             killer = "cockatrice cadaver";
  428.             done("died");
  429.         }
  430.  
  431.         if(obj->otyp == SCR_SCARE_MONSTER){
  432.           if(!obj->spe) obj->spe = 1;
  433.           else {
  434.             /* Note: perhaps the 1st pickup failed: you cannot
  435.             carry anymore, and so we never dropped it -
  436.             let's assume that treading on it twice also
  437.             destroys the scroll */
  438.             pline("The scroll turns to dust as you pick it up.");
  439.             delobj(obj);
  440.             continue;
  441.           }
  442.         }
  443.  
  444.         wt = inv_weight() + obj->owt;
  445.         if(wt > 0) {
  446.             if(obj->quan > 1) {
  447.                 /* see how many we can lift */
  448.                 extern struct obj *splitobj();
  449.                 int savequan = obj->quan;
  450.                 int iw = inv_weight();
  451.                 int qq;
  452.                 for(qq = 1; qq < savequan; qq++){
  453.                     obj->quan = qq;
  454.                     if(iw + weight(obj) > 0)
  455.                         break;
  456.                 }
  457.                 obj->quan = savequan;
  458.                 qq--;
  459.                 /* we can carry qq of them */
  460.                 if(!qq) goto too_heavy;
  461.             pline("You can only carry %s of the %s lying here.",
  462.                     (qq == 1) ? "one" : "some",
  463.                     doname(obj));
  464.                 (void) splitobj(obj, qq);
  465.                 /* note: obj2 is set already, so we'll never
  466.                  * encounter the other half; if it should be
  467.                  * otherwise then write
  468.                  *    obj2 = splitobj(obj,qq);
  469.                  */
  470.                 goto lift_some;
  471.             }
  472.         too_heavy:
  473.             pline("There %s %s here, but %s.",
  474.                 (obj->quan == 1) ? "is" : "are",
  475.                 doname(obj),
  476.                 !invent ? "it is too heavy for you to lift"
  477.                     : "you cannot carry anymore");
  478.             break;
  479.         }
  480.     lift_some:
  481.         if(inv_cnt() >= 52) {
  482.             pline("Your knapsack cannot accomodate anymore items.");
  483.             break;
  484.         }
  485.         if(wt > -5) pline("You have a little trouble lifting");
  486.         freeobj(obj);
  487.         if(Invisible) newsym(u.ux,u.uy);
  488.         addtobill(obj);       /* sets obj->unpaid if necessary */
  489.         { int pickquan = obj->quan;
  490.           int mergquan;
  491.         if(!Blind) obj->dknown = 1;    /* this is done by prinv(),
  492.                  but addinv() needs it already for merging */
  493.         obj = addinv(obj);    /* might merge it with other objects */
  494.           mergquan = obj->quan;
  495.           obj->quan = pickquan;    /* to fool prinv() */
  496.         prinv(obj);
  497.           obj->quan = mergquan;
  498.         }
  499.         }
  500.     }
  501. }
  502.  
  503. /* stop running if we see something interesting */
  504. /* turn around a corner if that is the only way we can proceed */
  505. /* do not turn left or right twice */
  506. lookaround(){
  507. register x,y,i,x0,y0,m0,i0 = 9;
  508. register int corrct = 0, noturn = 0;
  509. register struct monst *mtmp;
  510. #ifdef lint
  511.     /* suppress "used before set" message */
  512.     x0 = y0 = 0;
  513. #endif lint
  514.     if(Blind || flags.run == 0) return;
  515.     if(flags.run == 1 && levl[u.ux][u.uy].typ == ROOM) return;
  516. #ifdef QUEST
  517.     if(u.ux0 == u.ux+u.dx && u.uy0 == u.uy+u.dy) goto stop;
  518. #endif QUEST
  519.     for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){
  520.         if(x == u.ux && y == u.uy) continue;
  521.         if(!levl[x][y].typ) continue;
  522.         if((mtmp = m_at(x,y)) && !mtmp->mimic &&
  523.             (!mtmp->minvis || See_invisible)){
  524.             if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy))
  525.                 goto stop;
  526.         } else mtmp = 0; /* invisible M cannot influence us */
  527.         if(x == u.ux-u.dx && y == u.uy-u.dy) continue;
  528. #ifdef DGK
  529.         {
  530.         register uchar sym = levl[x][y].scrsym;
  531.  
  532.         if (sym == symbol.vwall || sym == symbol.hwall
  533.             || sym == symbol.room || sym == ' ' || IS_CORNER(sym))
  534.             continue;
  535.         else if (sym == symbol.door) {
  536.             if(x != u.ux && y != u.uy) continue;
  537.             if(flags.run != 1) goto stop;
  538.             goto corr;
  539.         } else if (sym == symbol.corr) {
  540.         corr:
  541.             if(flags.run == 1 || flags.run == 3) {
  542.                 i = DIST(x,y,u.ux+u.dx,u.uy+u.dy);
  543.                 if(i > 2) continue;
  544.                 if(corrct == 1 && DIST(x,y,x0,y0) != 1)
  545.                     noturn = 1;
  546.                 if(i < i0) {
  547.                     i0 = i;
  548.                     x0 = x;
  549.                     y0 = y;
  550.                     m0 = mtmp ? 1 : 0;
  551.                 }
  552.             }
  553.             corrct++;
  554.             continue;
  555.         } else if (sym == '^') {
  556.             if(flags.run == 1) goto corr;    /* if you must */
  557.              if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  558.             continue;
  559.         } else {        /* e.g. objects or trap or stairs */
  560.             if(flags.run == 1) goto corr;
  561.             if(mtmp) continue;        /* d */
  562.         }
  563.         stop:
  564.             nomul(0);
  565.             return;
  566.         }
  567. #else
  568.         switch(levl[x][y].scrsym){
  569.         case '|':
  570.         case '-':
  571.         case '.':
  572.         case ' ':
  573.             break;
  574.         case '+':
  575.             if(x != u.ux && y != u.uy) break;
  576.             if(flags.run != 1) goto stop;
  577.             /* fall into next case */
  578.         case CORR_SYM:
  579.         corr:
  580.             if(flags.run == 1 || flags.run == 3) {
  581.                 i = DIST(x,y,u.ux+u.dx,u.uy+u.dy);
  582.                 if(i > 2) break;
  583.                 if(corrct == 1 && DIST(x,y,x0,y0) != 1)
  584.                     noturn = 1;
  585.                 if(i < i0) {
  586.                     i0 = i;
  587.                     x0 = x;
  588.                     y0 = y;
  589.                     m0 = mtmp ? 1 : 0;
  590.                 }
  591.             }
  592.             corrct++;
  593.             break;
  594.         case '^':
  595.             if(flags.run == 1) goto corr;    /* if you must */
  596.              if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  597.             break;
  598.         default:    /* e.g. objects or trap or stairs */
  599.             if(flags.run == 1) goto corr;
  600.             if(mtmp) break;        /* d */
  601.         stop:
  602.             nomul(0);
  603.             return;
  604.         }
  605. #endif DGK
  606.     }
  607. #ifdef QUEST
  608.     if(corrct > 0 && (flags.run == 4 || flags.run == 5)) goto stop;
  609. #endif QUEST
  610.     if(corrct > 1 && flags.run == 2) goto stop;
  611.     if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
  612.         (corrct == 1 || (corrct == 2 && i0 == 1))) {
  613.         /* make sure that we do not turn too far */
  614.         if(i0 == 2) {
  615.             if(u.dx == y0-u.uy && u.dy == u.ux-x0)
  616.             i = 2;        /* straight turn right */
  617.             else
  618.             i = -2;        /* straight turn left */
  619.         } else if(u.dx && u.dy) {
  620.             if((u.dx == u.dy && y0 == u.uy) ||
  621.             (u.dx != u.dy && y0 != u.uy))
  622.             i = -1;        /* half turn left */
  623.             else
  624.             i = 1;        /* half turn right */
  625.         } else {
  626.             if((x0-u.ux == y0-u.uy && !u.dy) ||
  627.             (x0-u.ux != y0-u.uy && u.dy))
  628.             i = 1;        /* half turn right */
  629.             else
  630.             i = -1;        /* half turn left */
  631.         }
  632.         i += u.last_str_turn;
  633.         if(i <= 2 && i >= -2) {
  634.             u.last_str_turn = i;
  635.             u.dx = x0-u.ux, u.dy = y0-u.uy;
  636.         }
  637.     }
  638. }
  639.  
  640. /* something like lookaround, but we are not running */
  641. /* react only to monsters that might hit us */
  642. monster_nearby() {
  643. register int x,y;
  644. register struct monst *mtmp;
  645.     if(!Blind)
  646.     for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){
  647.         if(x == u.ux && y == u.uy) continue;
  648.         if((mtmp = m_at(x,y)) && !mtmp->mimic && !mtmp->mtame &&
  649.             !mtmp->mpeaceful && !index("Ea", mtmp->data->mlet) &&
  650.             !mtmp->mfroz && !mtmp->msleep &&  /* aplvax!jcn */
  651.             (!mtmp->minvis || See_invisible))
  652.             return(1);
  653.     }
  654.     return(0);
  655. }
  656.  
  657. #ifdef QUEST
  658. cansee(x,y) xchar x,y; {
  659. register int dx,dy,adx,ady,sdx,sdy,dmax,d;
  660.     if(Blind) return(0);
  661.     if(!isok(x,y)) return(0);
  662.     d = dist(x,y);
  663.     if(d < 3) return(1);
  664.     if(d > u.uhorizon*u.uhorizon) return(0);
  665.     if(!levl[x][y].lit)
  666.         return(0);
  667.     dx = x - u.ux;    adx = abs(dx);    sdx = sgn(dx);
  668.     dy = y - u.uy;  ady = abs(dy);    sdy = sgn(dy);
  669.     if(dx == 0 || dy == 0 || adx == ady){
  670.         dmax = (dx == 0) ? ady : adx;
  671.         for(d = 1; d <= dmax; d++)
  672.             if(!rroom(sdx*d,sdy*d))
  673.                 return(0);
  674.         return(1);
  675.     } else if(ady > adx){
  676.         for(d = 1; d <= ady; d++){
  677.             if(!rroom(sdx*( (d*adx)/ady ), sdy*d) ||
  678.                !rroom(sdx*( (d*adx-1)/ady+1 ), sdy*d))
  679.                 return(0);
  680.         }
  681.         return(1);
  682.     } else {
  683.         for(d = 1; d <= adx; d++){
  684.             if(!rroom(sdx*d, sdy*( (d*ady)/adx )) ||
  685.                !rroom(sdx*d, sdy*( (d*ady-1)/adx+1 )))
  686.                 return(0);
  687.         }
  688.         return(1);
  689.     }
  690. }
  691.  
  692. rroom(x,y) register int x,y; {
  693.     return(IS_ROOM(levl[u.ux+x][u.uy+y].typ));
  694. }
  695.  
  696. #else
  697.  
  698. cansee(x,y) xchar x,y; {
  699.     if(Blind || u.uswallow) return(0);
  700.     if(dist(x,y) < 3) return(1);
  701.     if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
  702.         y <= seehy) return(1);
  703.     return(0);
  704. }
  705. #endif QUEST
  706.  
  707. sgn(a) register int a; {
  708.     return((a > 0) ? 1 : (a == 0) ? 0 : -1);
  709. }
  710.  
  711. #ifdef QUEST
  712. setsee()
  713. {
  714.     register x,y;
  715.  
  716.     if(Blind) {
  717.         pru();
  718.         return;
  719.     }
  720.     for(y = u.uy-u.uhorizon; y <= u.uy+u.uhorizon; y++)
  721.         for(x = u.ux-u.uhorizon; x <= u.ux+u.uhorizon; x++) {
  722.             if(cansee(x,y))
  723.                 prl(x,y);
  724.     }
  725. }
  726.  
  727. #else
  728.  
  729. setsee()
  730. {
  731.     register x,y;
  732.  
  733.     if(Blind) {
  734.         pru();
  735.         return;
  736.     }
  737.     if(!levl[u.ux][u.uy].lit) {
  738.         seelx = u.ux-1;
  739.         seehx = u.ux+1;
  740.         seely = u.uy-1;
  741.         seehy = u.uy+1;
  742.     } else {
  743.         for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--);
  744.         for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++);
  745.         for(seely = u.uy; levl[u.ux][seely-1].lit; seely--);
  746.         for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++);
  747.     }
  748.     for(y = seely; y <= seehy; y++)
  749.         for(x = seelx; x <= seehx; x++) {
  750.             prl(x,y);
  751.     }
  752.     if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */
  753.     else {
  754.         if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1);
  755.         if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1);
  756.         if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y);
  757.         if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y);
  758.     }
  759. }
  760. #endif QUEST
  761.  
  762. #ifdef DGK
  763.     /* This is a bug fix by ab@unido
  764.      */
  765. nomul(nval)
  766. register nval;
  767. {
  768.     if(multi < nval) return;
  769.     multi = nval;
  770.     flags.mv = flags.run = 0;
  771. }
  772.  
  773. #else
  774. nomul(nval)
  775. register nval;
  776. {
  777.     if(multi < 0) return;
  778.     multi = nval;
  779.     flags.mv = flags.run = 0;
  780. }
  781. #endif DGK
  782.  
  783. abon()
  784. {
  785.     if(u.ustr == 3) return(-3);
  786.     else if(u.ustr < 6) return(-2);
  787.     else if(u.ustr < 8) return(-1);
  788.     else if(u.ustr < 17) return(0);
  789.     else if(u.ustr < 69) return(1);    /* up to 18/50 */
  790.     else if(u.ustr < 118) return(2);
  791.     else return(3);
  792. }
  793.  
  794. dbon()
  795. {
  796.     if(u.ustr < 6) return(-1);
  797.     else if(u.ustr < 16) return(0);
  798.     else if(u.ustr < 18) return(1);
  799.     else if(u.ustr == 18) return(2);    /* up to 18 */
  800.     else if(u.ustr < 94) return(3);        /* up to 18/75 */
  801.     else if(u.ustr < 109) return(4);    /* up to 18/90 */
  802.     else if(u.ustr < 118) return(5);    /* up to 18/99 */
  803.     else return(6);
  804. }
  805.  
  806. losestr(num)    /* may kill you; cause may be poison or monster like 'A' */
  807. register num;
  808. {
  809.     u.ustr -= num;
  810.     while(u.ustr < 3) {
  811.         u.ustr++;
  812.         u.uhp -= 6;
  813.         u.uhpmax -= 6;
  814.     }
  815.     flags.botl = 1;
  816. }
  817.  
  818. losehp(n,knam)
  819. register n;
  820. register char *knam;
  821. {
  822.     u.uhp -= n;
  823.     if(u.uhp > u.uhpmax)
  824.         u.uhpmax = u.uhp;    /* perhaps n was negative */
  825.     flags.botl = 1;
  826.     if(u.uhp < 1) {
  827.         killer = knam;    /* the thing that killed you */
  828.         done("died");
  829.     }
  830. }
  831.  
  832. losehp_m(n,mtmp)
  833. register n;
  834. register struct monst *mtmp;
  835. {
  836.     u.uhp -= n;
  837.     flags.botl = 1;
  838.     if(u.uhp < 1)
  839.         done_in_by(mtmp);
  840. }
  841.  
  842. losexp()    /* hit by V or W */
  843. {
  844.     register num;
  845.     extern long newuexp();
  846.  
  847.     if(u.ulevel > 1)
  848.         pline("Goodbye level %u.", u.ulevel--);
  849.     else
  850.         u.uhp = -1;
  851.     num = rnd(10);
  852.     u.uhp -= num;
  853.     u.uhpmax -= num;
  854.     u.uexp = newuexp();
  855.     flags.botl = 1;
  856. }
  857.  
  858. inv_weight(){
  859. register struct obj *otmp = invent;
  860. register int wt = (u.ugold + 500)/1000;
  861. register int carrcap;
  862.     if(Levitation)            /* pugh@cornell */
  863.         carrcap = MAX_CARR_CAP;
  864.     else {
  865.         carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel);
  866.         if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
  867.         if(Wounded_legs & LEFT_SIDE) carrcap -= 10;
  868.         if(Wounded_legs & RIGHT_SIDE) carrcap -= 10;
  869.     }
  870.     while(otmp){
  871.         wt += otmp->owt;
  872.         otmp = otmp->nobj;
  873.     }
  874.     return(wt - carrcap);
  875. }
  876.  
  877. inv_cnt(){
  878. register struct obj *otmp = invent;
  879. register int ct = 0;
  880.     while(otmp){
  881.         ct++;
  882.         otmp = otmp->nobj;
  883.     }
  884.     return(ct);
  885. }
  886.  
  887. long
  888. newuexp()
  889. {
  890.     return(10*(1L << (u.ulevel-1)));
  891. }
  892.