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

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

    1: /*      $NetBSD: hack.potion.c,v 1.6 2003/04/02 18:36:39 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.potion.c,v 1.6 2003/04/02 18:36:39 jsm Exp $");
   67: #endif                          /* not lint */
   68: 
   69: #include "hack.h"
   70: #include "extern.h"
   71: 
   72: int
   73: dodrink()
   74: {
   75:         struct obj     *otmp, *objs;
   76:         struct monst   *mtmp;
   77:         int             unkn = 0, nothing = 0;
   78: 
   79:         otmp = getobj("!", "drink");
   80:         if (!otmp)
   81:                 return (0);
   82:         if (!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) {
   83:                 ghost_from_bottle();
   84:                 goto use_it;
   85:         }
   86:         switch (otmp->otyp) {
   87:         case POT_RESTORE_STRENGTH:
   88:                 unkn++;
   89:                 pline("Wow!  This makes you feel great!");
   90:                 if (u.ustr < u.ustrmax) {
   91:                         u.ustr = u.ustrmax;
   92:                         flags.botl = 1;
   93:                 }
   94:                 break;
   95:         case POT_BOOZE:
   96:                 unkn++;
   97:                 pline("Ooph!  This tastes like liquid fire!");
   98:                 Confusion += d(3, 8);
   99:                 /* the whiskey makes us feel better */
  100:                 if (u.uhp < u.uhpmax)
  101:                         losehp(-1, "bottle of whiskey");
  102:                 if (!rn2(4)) {
  103:                         pline("You pass out.");
  104:                         multi = -rnd(15);
  105:                         nomovemsg = "You awake with a headache.";
  106:                 }
  107:                 break;
  108:         case POT_INVISIBILITY:
  109:                 if (Invis || See_invisible)
  110:                         nothing++;
  111:                 else {
  112:                         if (!Blind)
  113:                                 pline("Gee!  All of a sudden, you can't see yourself.");
  114:                         else
  115:                                 pline("You feel rather airy."), unkn++;
  116:                         newsym(u.ux, u.uy);
  117:                 }
  118:                 Invis += rn1(15, 31);
  119:                 break;
  120:         case POT_FRUIT_JUICE:
  121:                 pline("This tastes like fruit juice.");
  122:                 lesshungry(20);
  123:                 break;
  124:         case POT_HEALING:
  125:                 pline("You begin to feel better.");
  126:                 flags.botl = 1;
  127:                 u.uhp += rnd(10);
  128:                 if (u.uhp > u.uhpmax)
  129:                         u.uhp = ++u.uhpmax;
  130:                 if (Blind)
  131:                         Blind = 1;   /* see on next move */
  132:                 if (Sick)
  133:                         Sick = 0;
  134:                 break;
  135:         case POT_PARALYSIS:
  136:                 if (Levitation)
  137:                         pline("You are motionlessly suspended.");
  138:                 else
  139:                         pline("Your feet are frozen to the floor!");
  140:                 nomul(-(rn1(10, 25)));
  141:                 break;
  142:         case POT_MONSTER_DETECTION:
  143:                 if (!fmon) {
  144:                         strange_feeling(otmp, "You feel threatened.");
  145:                         return (1);
  146:                 } else {
  147:                         cls();
  148:                         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  149:                                 if (mtmp->mx > 0)
  150:                                         at(mtmp->mx, mtmp->my, mtmp->data->mlet);
  151:                         prme();
  152:                         pline("You sense the presence of monsters.");
  153:                         more();
  154:                         docrt();
  155:                 }
  156:                 break;
  157:         case POT_OBJECT_DETECTION:
  158:                 if (!fobj) {
  159:                         strange_feeling(otmp, "You feel a pull downward.");
  160:                         return (1);
  161:                 } else {
  162:                         for (objs = fobj; objs; objs = objs->nobj)
  163:                                 if (objs->ox != u.ux || objs->oy != u.uy)
  164:                                         goto outobjmap;
  165:                         pline("You sense the presence of objects close nearby.");
  166:                         break;
  167:         outobjmap:
  168:                         cls();
  169:                         for (objs = fobj; objs; objs = objs->nobj)
  170:                                 at(objs->ox, objs->oy, objs->olet);
  171:                         prme();
  172:                         pline("You sense the presence of objects.");
  173:                         more();
  174:                         docrt();
  175:                 }
  176:                 break;
  177:         case POT_SICKNESS:
  178:                 pline("Yech! This stuff tastes like poison.");
  179:                 if (Poison_resistance)
  180:                         pline("(But in fact it was biologically contaminated orange juice.)");
  181:                 losestr(rn1(4, 3));
  182:                 losehp(rnd(10), "contaminated potion");
  183:                 break;
  184:         case POT_CONFUSION:
  185:                 if (!Confusion)
  186:                         pline("Huh, What?  Where am I?");
  187:                 else
  188:                         nothing++;
  189:                 Confusion += rn1(7, 16);
  190:                 break;
  191:         case POT_GAIN_STRENGTH:
  192:                 pline("Wow do you feel strong!");
  193:                 if (u.ustr >= 118)
  194:                         break;       /* > 118 is impossible */
  195:                 if (u.ustr > 17)
  196:                         u.ustr += rnd(118 - u.ustr);
  197:                 else
  198:                         u.ustr++;
  199:                 if (u.ustr > u.ustrmax)
  200:                         u.ustrmax = u.ustr;
  201:                 flags.botl = 1;
  202:                 break;
  203:         case POT_SPEED:
  204:                 if (Wounded_legs) {
  205:                         heal_legs();
  206:                         unkn++;
  207:                         break;
  208:                 }
  209:                 if (!(Fast & ~INTRINSIC))
  210:                         pline("You are suddenly moving much faster.");
  211:                 else
  212:                         pline("Your legs get new energy."), unkn++;
  213:                 Fast += rn1(10, 100);
  214:                 break;
  215:         case POT_BLINDNESS:
  216:                 if (!Blind)
  217:                         pline("A cloud of darkness falls upon you.");
  218:                 else
  219:                         nothing++;
  220:                 Blind += rn1(100, 250);
  221:                 seeoff(0);
  222:                 break;
  223:         case POT_GAIN_LEVEL:
  224:                 pluslvl();
  225:                 break;
  226:         case POT_EXTRA_HEALING:
  227:                 pline("You feel much better.");
  228:                 flags.botl = 1;
  229:                 u.uhp += d(2, 20) + 1;
  230:                 if (u.uhp > u.uhpmax)
  231:                         u.uhp = (u.uhpmax += 2);
  232:                 if (Blind)
  233:                         Blind = 1;
  234:                 if (Sick)
  235:                         Sick = 0;
  236:                 break;
  237:         case POT_LEVITATION:
  238:                 if (!Levitation)
  239:                         float_up();
  240:                 else
  241:                         nothing++;
  242:                 Levitation += rnd(100);
  243:                 u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
  244:                 break;
  245:         default:
  246:                 impossible("What a funny potion! (%u)", otmp->otyp);
  247:                 return (0);
  248:         }
  249:         if (nothing) {
  250:                 unkn++;
  251:                 pline("You have a peculiar feeling for a moment, then it passes.");
  252:         }
  253:         if (otmp->dknown && !objects[otmp->otyp].oc_name_known) {
  254:                 if (!unkn) {
  255:                         objects[otmp->otyp].oc_name_known = 1;
  256:                         more_experienced(0, 10);
  257:                 } else if (!objects[otmp->otyp].oc_uname)
  258:                         docall(otmp);
  259:         }
  260: use_it:
  261:         useup(otmp);
  262:         return (1);
  263: }
  264: 
  265: void
  266: pluslvl()
  267: {
  268:         int num;
  269: 
  270:         pline("You feel more experienced.");
  271:         num = rnd(10);
  272:         u.uhpmax += num;
  273:         u.uhp += num;
  274:         if (u.ulevel < 14) {
  275:                 u.uexp = newuexp() + 1;
  276:                 pline("Welcome to experience level %u.", ++u.ulevel);
  277:         }
  278:         flags.botl = 1;
  279: }
  280: 
  281: void
  282: strange_feeling(obj, txt)
  283:         struct obj     *obj;
  284:         const char           *txt;
  285: {
  286:         if (flags.beginner)
  287:                 pline("You have a strange feeling for a moment, then it passes.");
  288:         else
  289:                 pline(txt);
  290:         if (!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
  291:                 docall(obj);
  292:         useup(obj);
  293: }
  294: 
  295: const char           *const bottlenames[] = {
  296:         "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
  297: };
  298: 
  299: void
  300: potionhit(mon, obj)
  301:         struct monst   *mon;
  302:         struct obj     *obj;
  303: {
  304:         const char           *botlnam = bottlenames[rn2(SIZE(bottlenames))];
  305:         boolean         uclose, isyou = (mon == &youmonst);
  306: 
  307:         if (isyou) {
  308:                 uclose = TRUE;
  309:                 pline("The %s crashes on your head and breaks into shivers.",
  310:                       botlnam);
  311:                 losehp(rnd(2), "thrown potion");
  312:         } else {
  313:                 uclose = (dist(mon->mx, mon->my) < 3);
  314:                 /* perhaps 'E' and 'a' have no head? */
  315:                 pline("The %s crashes on %s's head and breaks into shivers.",
  316:                       botlnam, monnam(mon));
  317:                 if (rn2(5) && mon->mhp > 1)
  318:                         mon->mhp--;
  319:         }
  320:         pline("The %s evaporates.", xname(obj));
  321: 
  322:         if (!isyou && !rn2(3))
  323:                 switch (obj->otyp) {
  324: 
  325:                 case POT_RESTORE_STRENGTH:
  326:                 case POT_GAIN_STRENGTH:
  327:                 case POT_HEALING:
  328:                 case POT_EXTRA_HEALING:
  329:                         if (mon->mhp < mon->mhpmax) {
  330:                                 mon->mhp = mon->mhpmax;
  331:                                 pline("%s looks sound and hale again!", Monnam(mon));
  332:                         }
  333:                         break;
  334:                 case POT_SICKNESS:
  335:                         if (mon->mhpmax > 3)
  336:                                 mon->mhpmax /= 2;
  337:                         if (mon->mhp > 2)
  338:                                 mon->mhp /= 2;
  339:                         break;
  340:                 case POT_CONFUSION:
  341:                 case POT_BOOZE:
  342:                         mon->mconf = 1;
  343:                         break;
  344:                 case POT_INVISIBILITY:
  345:                         unpmon(mon);
  346:                         mon->minvis = 1;
  347:                         pmon(mon);
  348:                         break;
  349:                 case POT_PARALYSIS:
  350:                         mon->mfroz = 1;
  351:                         break;
  352:                 case POT_SPEED:
  353:                         mon->mspeed = MFAST;
  354:                         break;
  355:                 case POT_BLINDNESS:
  356:                         mon->mblinded |= 64 + rn2(64);
  357:                         break;
  358:                         /*
  359:                          * case POT_GAIN_LEVEL: case POT_LEVITATION: case
  360:                          * POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case
  361:                          * POT_OBJECT_DETECTION: break;
  362:                          */
  363:                 }
  364:         if (uclose && rn2(5))
  365:                 potionbreathe(obj);
  366:         obfree(obj, Null(obj));
  367: }
  368: 
  369: void
  370: potionbreathe(obj)
  371:         struct obj     *obj;
  372: {
  373:         switch (obj->otyp) {
  374:         case POT_RESTORE_STRENGTH:
  375:         case POT_GAIN_STRENGTH:
  376:                 if (u.ustr < u.ustrmax)
  377:                         u.ustr++, flags.botl = 1;
  378:                 break;
  379:         case POT_HEALING:
  380:         case POT_EXTRA_HEALING:
  381:                 if (u.uhp < u.uhpmax)
  382:                         u.uhp++, flags.botl = 1;
  383:                 break;
  384:         case POT_SICKNESS:
  385:                 if (u.uhp <= 5)
  386:                         u.uhp = 1;
  387:                 else
  388:                         u.uhp -= 5;
  389:                 flags.botl = 1;
  390:                 break;
  391:         case POT_CONFUSION:
  392:         case POT_BOOZE:
  393:                 if (!Confusion)
  394:                         pline("You feel somewhat dizzy.");
  395:                 Confusion += rnd(5);
  396:                 break;
  397:         case POT_INVISIBILITY:
  398:                 pline("For an instant you couldn't see your right hand.");
  399:                 break;
  400:         case POT_PARALYSIS:
  401:                 pline("Something seems to be holding you.");
  402:                 nomul(-rnd(5));
  403:                 break;
  404:         case POT_SPEED:
  405:                 Fast += rnd(5);
  406:                 pline("Your knees seem more flexible now.");
  407:                 break;
  408:         case POT_BLINDNESS:
  409:                 if (!Blind)
  410:                         pline("It suddenly gets dark.");
  411:                 Blind += rnd(5);
  412:                 seeoff(0);
  413:                 break;
  414:                 /*
  415:                  * case POT_GAIN_LEVEL: case POT_LEVITATION: case
  416:                  * POT_FRUIT_JUICE: case POT_MONSTER_DETECTION: case
  417:                  * POT_OBJECT_DETECTION: break;
  418:                  */
  419:         }
  420:         /* note: no obfree() */
  421: }
  422: 
  423: /*
  424:  * -- rudimentary -- to do this correctly requires much more work
  425:  * -- all sharp weapons get one or more qualities derived from the potions
  426:  * -- texts on scrolls may be (partially) wiped out; do they become blank?
  427:  * --   or does their effect change, like under Confusion?
  428:  * -- all objects may be made invisible by POT_INVISIBILITY
  429:  * -- If the flask is small, can one dip a large object? Does it magically
  430:  * --   become a jug? Etc.
  431:  */
  432: int
  433: dodip()
  434: {
  435:         struct obj     *potion, *obj;
  436: 
  437:         if (!(obj = getobj("#", "dip")))
  438:                 return (0);
  439:         if (!(potion = getobj("!", "dip into")))
  440:                 return (0);
  441:         pline("Interesting...");
  442:         if (obj->otyp == ARROW || obj->otyp == DART ||
  443:             obj->otyp == CROSSBOW_BOLT) {
  444:                 if (potion->otyp == POT_SICKNESS) {
  445:                         useup(potion);
  446:                         if (obj->spe < 7)
  447:                                 obj->spe++; /* %% */
  448:                 }
  449:         }
  450:         return (1);
  451: }
  452: 
  453: void
  454: ghost_from_bottle()
  455: {
  456:         struct monst   *mtmp;
  457: 
  458:         if (!(mtmp = makemon(PM_GHOST, u.ux, u.uy))) {
  459:                 pline("This bottle turns out to be empty.");
  460:                 return;
  461:         }
  462:         mnexto(mtmp);
  463:         pline("As you open the bottle, an enormous ghost emerges!");
  464:         pline("You are frightened to death, and unable to move.");
  465:         nomul(-3);
  466: }
Syntax (Markdown)