home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 1 / src / hack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-07-26  |  17.9 KB  |  799 lines

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