(linenum→info "unix/slp.c:2238")

bsd-games/2.17/hack/hack.apply.c

    1: /*      $NetBSD: hack.apply.c,v 1.8 2004/01/27 20:30:29 jsm Exp $    */
    2: 
    3: /*
    4:  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
    5:  * Amsterdam
    6:  * All rights reserved.
    7:  *
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions are
   10:  * met:
   11:  *
   12:  * - Redistributions of source code must retain the above copyright notice,
   13:  * this list of conditions and the following disclaimer.
   14:  *
   15:  * - Redistributions in binary form must reproduce the above copyright
   16:  * notice, this list of conditions and the following disclaimer in the
   17:  * documentation and/or other materials provided with the distribution.
   18:  *
   19:  * - Neither the name of the Stichting Centrum voor Wiskunde en
   20:  * Informatica, nor the names of its contributors may be used to endorse or
   21:  * promote products derived from this software without specific prior
   22:  * written permission.
   23:  *
   24:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
   25:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   27:  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   28:  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   29:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   30:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   31:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   32:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35:  */
   36: 
   37: /*
   38:  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
   39:  * All rights reserved.
   40:  *
   41:  * Redistribution and use in source and binary forms, with or without
   42:  * modification, are permitted provided that the following conditions
   43:  * are met:
   44:  * 1. Redistributions of source code must retain the above copyright
   45:  *    notice, this list of conditions and the following disclaimer.
   46:  * 2. Redistributions in binary form must reproduce the above copyright
   47:  *    notice, this list of conditions and the following disclaimer in the
   48:  *    documentation and/or other materials provided with the distribution.
   49:  * 3. The name of the author may not be used to endorse or promote products
   50:  *    derived from this software without specific prior written permission.
   51:  *
   52:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   53:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   54:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   55:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   56:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   57:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   58:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   59:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   60:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   61:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   62:  */
   63: 
   64: #include <sys/cdefs.h>
   65: #ifndef lint
   66: __RCSID("$NetBSD: hack.apply.c,v 1.8 2004/01/27 20:30:29 jsm Exp $");
   67: #endif                          /* not lint */
   68: 
   69: #include        "hack.h"
   70: #include        "extern.h"
   71: #include        "def.edog.h"
   72: #include        "def.mkroom.h"
   73: 
   74: static void use_camera(struct obj *);
   75: static int in_ice_box(struct obj *);
   76: static int ck_ice_box(struct obj *);
   77: static int out_ice_box(struct obj *);
   78: static void use_ice_box(struct obj *);
   79: static struct monst *bchit(int, int , int , int);
   80: static void use_whistle(struct obj *);
   81: static void use_magic_whistle(struct obj *);
   82: static int dig(void);
   83: static int use_pick_axe(struct obj *);
   84: 
   85: int
   86: doapply()
   87: {
   88:         struct obj *obj;
   89:         int    res = 1;
   90: 
   91:         obj = getobj("(", "use or apply");
   92:         if (!obj)
   93:                 return (0);
   94: 
   95:         switch (obj->otyp) {
   96:         case EXPENSIVE_CAMERA:
   97:                 use_camera(obj);
   98:                 break;
   99:         case ICE_BOX:
  100:                 use_ice_box(obj);
  101:                 break;
  102:         case PICK_AXE:
  103:                 res = use_pick_axe(obj);
  104:                 break;
  105: 
  106:         case MAGIC_WHISTLE:
  107:                 if (pl_character[0] == 'W' || u.ulevel > 9) {
  108:                         use_magic_whistle(obj);
  109:                         break;
  110:                 }
  111:                 /* fall into next case */
  112:         case WHISTLE:
  113:                 use_whistle(obj);
  114:                 break;
  115: 
  116:         case CAN_OPENER:
  117:                 if (!carrying(TIN)) {
  118:                         pline("You have no can to open.");
  119:                         goto xit;
  120:                 }
  121:                 pline("You cannot open a tin without eating its contents.");
  122:                 pline("In order to eat, use the 'e' command.");
  123:                 if (obj != uwep)
  124:                         pline("Opening the tin will be much easier if you wield the can-opener.");
  125:                 goto xit;
  126: 
  127:         default:
  128:                 pline("Sorry, I don't know how to use that.");
  129: xit:
  130:                 nomul(0);
  131:                 return (0);
  132:         }
  133:         nomul(0);
  134:         return (res);
  135: }
  136: 
  137: /* ARGSUSED */
  138: static void
  139: use_camera(obj) /* */ 
  140:         struct obj     *obj __attribute__((__unused__));
  141: {
  142:         struct monst *mtmp;
  143:         if (!getdir(1)) {      /* ask: in what direction? */
  144:                 flags.move = multi = 0;
  145:                 return;
  146:         }
  147:         if (u.uswallow) {
  148:                 pline("You take a picture of %s's stomach.", monnam(u.ustuck));
  149:                 return;
  150:         }
  151:         if (u.dz) {
  152:                 pline("You take a picture of the %s.",
  153:                       (u.dz > 0) ? "floor" : "ceiling");
  154:                 return;
  155:         }
  156:         if ((mtmp = bchit(u.dx, u.dy, COLNO, '!')) != NULL) {
  157:                 if (mtmp->msleep) {
  158:                         mtmp->msleep = 0;
  159:                         pline("The flash awakens %s.", monnam(mtmp));        /* a3 */
  160:                 } else if (mtmp->data->mlet != 'y')
  161:                         if (mtmp->mcansee || mtmp->mblinded) {
  162:                                 int    tmp = dist(mtmp->mx, mtmp->my);
  163:                                 int    tmp2;
  164:                                 if (cansee(mtmp->mx, mtmp->my))
  165:                                         pline("%s is blinded by the flash!", Monnam(mtmp));
  166:                                 setmangry(mtmp);
  167:                                 if (tmp < 9 && !mtmp->isshk && rn2(4)) {
  168:                                         mtmp->mflee = 1;
  169:                                         if (rn2(4))
  170:                                                 mtmp->mfleetim = rnd(100);
  171:                                 }
  172:                                 if (tmp < 3)
  173:                                         mtmp->mcansee = mtmp->mblinded = 0;
  174:                                 else {
  175:                                         tmp2 = mtmp->mblinded;
  176:                                         tmp2 += rnd(1 + 50 / tmp);
  177:                                         if (tmp2 > 127)
  178:                                                 tmp2 = 127;
  179:                                         mtmp->mblinded = tmp2;
  180:                                         mtmp->mcansee = 0;
  181:                                 }
  182:                         }
  183:         }
  184: }
  185: 
  186: static
  187: struct obj     *current_ice_box;/* a local variable of use_ice_box, to be
  188:                                  * used by its local procedures in/ck_ice_box */
  189: static int
  190: in_ice_box(obj)
  191:         struct obj *obj;
  192: {
  193:         if (obj == current_ice_box ||
  194:             (Punished && (obj == uball || obj == uchain))) {
  195:                 pline("You must be kidding.");
  196:                 return (0);
  197:         }
  198:         if (obj->owornmask & (W_ARMOR | W_RING)) {
  199:                 pline("You cannot refrigerate something you are wearing.");
  200:                 return (0);
  201:         }
  202:         if (obj->owt + current_ice_box->owt > 70) {
  203:                 pline("It won't fit.");
  204:                 return (1);   /* be careful! */
  205:         }
  206:         if (obj == uwep) {
  207:                 if (uwep->cursed) {
  208:                         pline("Your weapon is welded to your hand!");
  209:                         return (0);
  210:                 }
  211:                 setuwep((struct obj *) 0);
  212:         }
  213:         current_ice_box->owt += obj->owt;
  214:         freeinv(obj);
  215:         obj->o_cnt_id = current_ice_box->o_id;
  216:         obj->nobj = fcobj;
  217:         fcobj = obj;
  218:         obj->age = moves - obj->age;   /* actual age */
  219:         return (1);
  220: }
  221: 
  222: static int
  223: ck_ice_box(obj)
  224:         struct obj *obj;
  225: {
  226:         return (obj->o_cnt_id == current_ice_box->o_id);
  227: }
  228: 
  229: static int
  230: out_ice_box(obj)
  231:         struct obj *obj;
  232: {
  233:         struct obj *otmp;
  234:         if (obj == fcobj)
  235:                 fcobj = fcobj->nobj;
  236:         else {
  237:                 for (otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj)
  238:                         if (!otmp->nobj)
  239:                                 panic("out_ice_box");
  240:                 otmp->nobj = obj->nobj;
  241:         }
  242:         current_ice_box->owt -= obj->owt;
  243:         obj->age = moves - obj->age;   /* simulated point of time */
  244:         (void) addinv(obj);
  245:         return 0;
  246: }
  247: 
  248: static void
  249: use_ice_box(obj)
  250:         struct obj *obj;
  251: {
  252:         int    cnt = 0;
  253:         struct obj *otmp;
  254:         current_ice_box = obj; /* for use by in/out_ice_box */
  255:         for (otmp = fcobj; otmp; otmp = otmp->nobj)
  256:                 if (otmp->o_cnt_id == obj->o_id)
  257:                         cnt++;
  258:         if (!cnt)
  259:                 pline("Your ice-box is empty.");
  260:         else {
  261:                 pline("Do you want to take something out of the ice-box? [yn] ");
  262:                 if (readchar() == 'y')
  263:                         if (askchain(fcobj, (char *) 0, 0, out_ice_box, ck_ice_box, 0))
  264:                                 return;
  265:                 pline("That was all. Do you wish to put something in? [yn] ");
  266:                 if (readchar() != 'y')
  267:                         return;
  268:         }
  269:         /* call getobj: 0: allow cnt; #: allow all types; %: expect food */
  270:         otmp = getobj("0#%", "put in");
  271:         if (!otmp || !in_ice_box(otmp))
  272:                 flags.move = multi = 0;
  273: }
  274: 
  275: static struct monst *
  276: bchit(ddx, ddy, range, sym)
  277:         int    ddx, ddy, range;
  278:         char            sym;
  279: {
  280:         struct monst *mtmp = (struct monst *) 0;
  281:         int    bchx = u.ux, bchy = u.uy;
  282: 
  283:         if (sym)
  284:                 Tmp_at(-1, sym);/* open call */
  285:         while (range--) {
  286:                 bchx += ddx;
  287:                 bchy += ddy;
  288:                 if ((mtmp = m_at(bchx, bchy)) != NULL)
  289:                         break;
  290:                 if (!ZAP_POS(levl[bchx][bchy].typ)) {
  291:                         bchx -= ddx;
  292:                         bchy -= ddy;
  293:                         break;
  294:                 }
  295:                 if (sym)
  296:                         Tmp_at(bchx, bchy);
  297:         }
  298:         if (sym)
  299:                 Tmp_at(-1, -1);
  300:         return (mtmp);
  301: }
  302: 
  303: /* ARGSUSED */
  304: static void
  305: use_whistle(obj)
  306:         struct obj     *obj __attribute__((__unused__));
  307: {
  308:         struct monst *mtmp = fmon;
  309:         pline("You produce a high whistling sound.");
  310:         while (mtmp) {
  311:                 if (dist(mtmp->mx, mtmp->my) < u.ulevel * 20) {
  312:                         if (mtmp->msleep)
  313:                                 mtmp->msleep = 0;
  314:                         if (mtmp->mtame)
  315:                                 EDOG(mtmp)->whistletime = moves;
  316:                 }
  317:                 mtmp = mtmp->nmon;
  318:         }
  319: }
  320: 
  321: /* ARGSUSED */
  322: static void
  323: use_magic_whistle(obj)
  324:         struct obj     *obj __attribute__((__unused__));
  325: {
  326:         struct monst *mtmp = fmon;
  327:         pline("You produce a strange whistling sound.");
  328:         while (mtmp) {
  329:                 if (mtmp->mtame)
  330:                         mnexto(mtmp);
  331:                 mtmp = mtmp->nmon;
  332:         }
  333: }
  334: 
  335: static int      dig_effort;     /* effort expended on current pos */
  336: static uchar    dig_level;
  337: static coord    dig_pos;
  338: static boolean  dig_down;
  339: 
  340: static int
  341: dig()
  342: {
  343:         struct rm *lev;
  344:         int dpx = dig_pos.x, dpy = dig_pos.y;
  345: 
  346:         /* perhaps a nymph stole his pick-axe while he was busy digging */
  347:         /* or perhaps he teleported away */
  348:         if (u.uswallow || !uwep || uwep->otyp != PICK_AXE ||
  349:             dig_level != dlevel ||
  350:             ((dig_down && (dpx != u.ux || dpy != u.uy)) ||
  351:              (!dig_down && dist(dpx, dpy) > 2)))
  352:                 return (0);
  353: 
  354:         dig_effort += 10 + abon() + uwep->spe + rn2(5);
  355:         if (dig_down) {
  356:                 if (!xdnstair) {
  357:                         pline("The floor here seems too hard to dig in.");
  358:                         return (0);
  359:                 }
  360:                 if (dig_effort > 250) {
  361:                         dighole();
  362:                         return (0);  /* done with digging */
  363:                 }
  364:                 if (dig_effort > 50) {
  365:                         struct trap *ttmp = t_at(dpx, dpy);
  366: 
  367:                         if (!ttmp) {
  368:                                 ttmp = maketrap(dpx, dpy, PIT);
  369:                                 ttmp->tseen = 1;
  370:                                 pline("You have dug a pit.");
  371:                                 u.utrap = rn1(4, 2);
  372:                                 u.utraptype = TT_PIT;
  373:                                 return (0);
  374:                         }
  375:                 }
  376:         } else if (dig_effort > 100) {
  377:                 const char  *digtxt;
  378:                 struct obj *obj;
  379: 
  380:                 lev = &levl[dpx][dpy];
  381:                 if ((obj = sobj_at(ENORMOUS_ROCK, dpx, dpy)) != NULL) {
  382:                         fracture_rock(obj);
  383:                         digtxt = "The rock falls apart.";
  384:                 } else if (!lev->typ || lev->typ == SCORR) {
  385:                         lev->typ = CORR;
  386:                         digtxt = "You succeeded in cutting away some rock.";
  387:                 } else if (lev->typ == HWALL || lev->typ == VWALL
  388:                            || lev->typ == SDOOR) {
  389:                         lev->typ = xdnstair ? DOOR : ROOM;
  390:                         digtxt = "You just made an opening in the wall.";
  391:                 } else
  392:                         digtxt = "Now what exactly was it that you were digging in?";
  393:                 mnewsym(dpx, dpy);
  394:                 prl(dpx, dpy);
  395:                 pline(digtxt);        /* after mnewsym & prl */
  396:                 return (0);
  397:         } else {
  398:                 if (IS_WALL(levl[dpx][dpy].typ)) {
  399:                         int    rno = inroom(dpx, dpy);
  400: 
  401:                         if (rno >= 0 && rooms[rno].rtype >= 8) {
  402:                                 pline("This wall seems too hard to dig into.");
  403:                                 return (0);
  404:                         }
  405:                 }
  406:                 pline("You hit the rock with all your might.");
  407:         }
  408:         return (1);
  409: }
  410: 
  411: /* When will hole be finished? Very rough indication used by shopkeeper. */
  412: int
  413: holetime()
  414: {
  415:         return ((occupation == dig) ? (250 - dig_effort) / 20 : -1);
  416: }
  417: 
  418: void
  419: dighole()
  420: {
  421:         struct trap *ttmp = t_at(u.ux, u.uy);
  422: 
  423:         if (!xdnstair) {
  424:                 pline("The floor here seems too hard to dig in.");
  425:         } else {
  426:                 if (ttmp)
  427:                         ttmp->ttyp = TRAPDOOR;
  428:                 else
  429:                         ttmp = maketrap(u.ux, u.uy, TRAPDOOR);
  430:                 ttmp->tseen = 1;
  431:                 pline("You've made a hole in the floor.");
  432:                 if (!u.ustuck) {
  433:                         if (inshop())
  434:                                 shopdig(1);
  435:                         pline("You fall through ...");
  436:                         if (u.utraptype == TT_PIT) {
  437:                                 u.utrap = 0;
  438:                                 u.utraptype = 0;
  439:                         }
  440:                         goto_level(dlevel + 1, FALSE);
  441:                 }
  442:         }
  443: }
  444: 
  445: static int
  446: use_pick_axe(obj)
  447:         struct obj     *obj;
  448: {
  449:         char            dirsyms[12];
  450:         char  *dsp = dirsyms, *sdp = sdir;
  451:         struct monst *mtmp;
  452:         struct rm *lev;
  453:         int    rx, ry, res = 0;
  454: 
  455:         if (obj != uwep) {
  456:                 if (uwep && uwep->cursed) {
  457:                         /* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */
  458:                         pline("Since your weapon is welded to your hand,");
  459:                         pline("you cannot use that pick-axe.");
  460:                         return (0);
  461:                 }
  462:                 pline("You now wield %s.", doname(obj));
  463:                 setuwep(obj);
  464:                 res = 1;
  465:         }
  466:         while (*sdp) {
  467:                 (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */
  468:                 rx = u.ux + u.dx;
  469:                 ry = u.uy + u.dy;
  470:                 if (u.dz > 0 || (u.dz == 0 && isok(rx, ry) &&
  471:                                  (IS_ROCK(levl[rx][ry].typ)
  472:                                   || sobj_at(ENORMOUS_ROCK, rx, ry))))
  473:                         *dsp++ = *sdp;
  474:                 sdp++;
  475:         }
  476:         *dsp = 0;
  477:         pline("In what direction do you want to dig? [%s] ", dirsyms);
  478:         if (!getdir(0))                /* no txt */
  479:                 return (res);
  480:         if (u.uswallow && attack(u.ustuck))    /* return(1) */
  481:                 ;
  482:         else if (u.dz < 0)
  483:                 pline("You cannot reach the ceiling.");
  484:         else if (u.dz == 0) {
  485:                 if (Confusion)
  486:                         confdir();
  487:                 rx = u.ux + u.dx;
  488:                 ry = u.uy + u.dy;
  489:                 if ((mtmp = m_at(rx, ry)) && attack(mtmp))
  490:                         return (1);
  491:                 if (!isok(rx, ry)) {
  492:                         pline("Clash!");
  493:                         return (1);
  494:                 }
  495:                 lev = &levl[rx][ry];
  496:                 if (lev->typ == DOOR)
  497:                         pline("Your %s against the door.",
  498:                               aobjnam(obj, "clang"));
  499:                 else if (!IS_ROCK(lev->typ)
  500:                          && !sobj_at(ENORMOUS_ROCK, rx, ry)) {
  501:                         /* ACCESSIBLE or POOL */
  502:                         pline("You swing your %s through thin air.",
  503:                               aobjnam(obj, (char *) 0));
  504:                 } else {
  505:                         if (dig_pos.x != rx || dig_pos.y != ry
  506:                             || dig_level != dlevel || dig_down) {
  507:                                 dig_down = FALSE;
  508:                                 dig_pos.x = rx;
  509:                                 dig_pos.y = ry;
  510:                                 dig_level = dlevel;
  511:                                 dig_effort = 0;
  512:                                 pline("You start digging.");
  513:                         } else
  514:                                 pline("You continue digging.");
  515:                         occupation = dig;
  516:                         occtxt = "digging";
  517:                 }
  518:         } else if (Levitation) {
  519:                 pline("You cannot reach the floor.");
  520:         } else {
  521:                 if (dig_pos.x != u.ux || dig_pos.y != u.uy
  522:                     || dig_level != dlevel || !dig_down) {
  523:                         dig_down = TRUE;
  524:                         dig_pos.x = u.ux;
  525:                         dig_pos.y = u.uy;
  526:                         dig_level = dlevel;
  527:                         dig_effort = 0;
  528:                         pline("You start digging in the floor.");
  529:                         if (inshop())
  530:                                 shopdig(0);
  531:                 } else
  532:                         pline("You continue digging in the floor.");
  533:                 occupation = dig;
  534:                 occtxt = "digging";
  535:         }
  536:         return (1);
  537: }
1