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

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

    1: /*      $NetBSD: hack.eat.c,v 1.6 2003/04/02 18:36:36 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.eat.c,v 1.6 2003/04/02 18:36:36 jsm Exp $");
   67: #endif                          /* not lint */
   68: 
   69: #include "hack.h"
   70: #include "extern.h"
   71: char            POISONOUS[] = "ADKSVabhks";
   72: 
   73: /* hunger texts used on bottom line (each 8 chars long) */
   74: #define SATIATED        0
   75: #define NOT_HUNGRY      1
   76: #define HUNGRY          2
   77: #define WEAK            3
   78: #define FAINTING        4
   79: #define FAINTED         5
   80: #define STARVED         6
   81: 
   82: const char           *const hu_stat[] = {
   83:         "Satiated",
   84:         "        ",
   85:         "Hungry  ",
   86:         "Weak    ",
   87:         "Fainting",
   88:         "Fainted ",
   89:         "Starved "
   90: };
   91: 
   92: void
   93: init_uhunger()
   94: {
   95:         u.uhunger = 900;
   96:         u.uhs = NOT_HUNGRY;
   97: }
   98: 
   99: #define TTSZ    SIZE(tintxts)
  100: const struct {
  101:         const char           *txt;
  102:         int             nut;
  103: }               tintxts[] = {
  104:         { "It contains first quality peaches - what a surprise!", 40 },
  105:         { "It contains salmon - not bad!", 60 },
  106:         { "It contains apple juice - perhaps not what you hoped for.", 20 },
  107:         { "It contains some nondescript substance, tasting awfully.", 500 },
  108:         { "It contains rotten meat. You vomit.", -50 },
  109:         { "It turns out to be empty.", 0 }
  110: };
  111: 
  112: static struct {
  113:         struct obj     *tin;
  114:         int             usedtime, reqtime;
  115: }               tin;
  116: 
  117: int
  118: opentin()
  119: {
  120:         int             r;
  121: 
  122:         if (!carried(tin.tin)) /* perhaps it was stolen? */
  123:                 return (0);   /* %% probably we should use tinoid */
  124:         if (tin.usedtime++ >= 50) {
  125:                 pline("You give up your attempt to open the tin.");
  126:                 return (0);
  127:         }
  128:         if (tin.usedtime < tin.reqtime)
  129:                 return (1);   /* still busy */
  130: 
  131:         pline("You succeed in opening the tin.");
  132:         useup(tin.tin);
  133:         r = rn2(2 * TTSZ);
  134:         if (r < TTSZ) {
  135:                 pline(tintxts[r].txt);
  136:                 lesshungry(tintxts[r].nut);
  137:                 if (r == 1) { /* SALMON */
  138:                         Glib = rnd(15);
  139:                         pline("Eating salmon made your fingers very slippery.");
  140:                 }
  141:         } else {
  142:                 pline("It contains spinach - this makes you feel like Popeye!");
  143:                 lesshungry(600);
  144:                 if (u.ustr < 118)
  145:                         u.ustr += rnd(((u.ustr < 17) ? 19 : 118) - u.ustr);
  146:                 if (u.ustr > u.ustrmax)
  147:                         u.ustrmax = u.ustr;
  148:                 flags.botl = 1;
  149:         }
  150:         return (0);
  151: }
  152: 
  153: int
  154: Meatdone()
  155: {
  156:         u.usym = '@';
  157:         prme();
  158:         return 0;
  159: }
  160: 
  161: int
  162: doeat()
  163: {
  164:         struct obj     *otmp;
  165:         struct objclass *ftmp;
  166:         int tmp;
  167: 
  168:         /* Is there some food (probably a heavy corpse) here on the ground? */
  169:         if (!Levitation)
  170:                 for (otmp = fobj; otmp; otmp = otmp->nobj) {
  171:                         if (otmp->ox == u.ux && otmp->oy == u.uy &&
  172:                             otmp->olet == FOOD_SYM) {
  173:                                 pline("There %s %s here; eat %s? [ny] ",
  174:                                       (otmp->quan == 1) ? "is" : "are",
  175:                                       doname(otmp),
  176:                                       (otmp->quan == 1) ? "it" : "one");
  177:                                 if (readchar() == 'y') {
  178:                                         if (otmp->quan != 1)
  179:                                                 (void) splitobj(otmp, 1);
  180:                                         freeobj(otmp);
  181:                                         otmp = addinv(otmp);
  182:                                         addtobill(otmp);
  183:                                         goto gotit;
  184:                                 }
  185:                         }
  186:                 }
  187:         otmp = getobj("%", "eat");
  188:         if (!otmp)
  189:                 return (0);
  190: gotit:
  191:         if (otmp->otyp == TIN) {
  192:                 if (uwep) {
  193:                         switch (uwep->otyp) {
  194:                         case CAN_OPENER:
  195:                                 tmp = 1;
  196:                                 break;
  197:                         case DAGGER:
  198:                         case CRYSKNIFE:
  199:                                 tmp = 3;
  200:                                 break;
  201:                         case PICK_AXE:
  202:                         case AXE:
  203:                                 tmp = 6;
  204:                                 break;
  205:                         default:
  206:                                 goto no_opener;
  207:                         }
  208:                         pline("Using your %s you try to open the tin.",
  209:                               aobjnam(uwep, (char *) 0));
  210:                 } else {
  211:         no_opener:
  212:                         pline("It is not so easy to open this tin.");
  213:                         if (Glib) {
  214:                                 pline("The tin slips out of your hands.");
  215:                                 if (otmp->quan > 1) {
  216:                                         struct obj     *obj;
  217: 
  218:                                         obj = splitobj(otmp, 1);
  219:                                         if (otmp == uwep)
  220:                                                 setuwep(obj);
  221:                                 }
  222:                                 dropx(otmp);
  223:                                 return (1);
  224:                         }
  225:                         tmp = 10 + rn2(1 + 500 / ((int) (u.ulevel + u.ustr)));
  226:                 }
  227:                 tin.reqtime = tmp;
  228:                 tin.usedtime = 0;
  229:                 tin.tin = otmp;
  230:                 occupation = opentin;
  231:                 occtxt = "opening the tin";
  232:                 return (1);
  233:         }
  234:         ftmp = &objects[otmp->otyp];
  235:         multi = -ftmp->oc_delay;
  236:         if (otmp->otyp >= CORPSE && eatcorpse(otmp))
  237:                 goto eatx;
  238:         if (!rn2(7) && otmp->otyp != FORTUNE_COOKIE) {
  239:                 pline("Blecch!  Rotten food!");
  240:                 if (!rn2(4)) {
  241:                         pline("You feel rather light headed.");
  242:                         Confusion += d(2, 4);
  243:                 } else if (!rn2(4) && !Blind) {
  244:                         pline("Everything suddenly goes dark.");
  245:                         Blind = d(2, 10);
  246:                         seeoff(0);
  247:                 } else if (!rn2(3)) {
  248:                         if (Blind)
  249:                                 pline("The world spins and you slap against the floor.");
  250:                         else
  251:                                 pline("The world spins and goes dark.");
  252:                         nomul(-rnd(10));
  253:                         nomovemsg = "You are conscious again.";
  254:                 }
  255:                 lesshungry(ftmp->nutrition / 4);
  256:         } else {
  257:                 if (u.uhunger >= 1500) {
  258:                         pline("You choke over your food.");
  259:                         pline("You die...");
  260:                         killer = ftmp->oc_name;
  261:                         done("choked");
  262:                 }
  263:                 switch (otmp->otyp) {
  264:                 case FOOD_RATION:
  265:                         if (u.uhunger <= 200)
  266:                                 pline("That food really hit the spot!");
  267:                         else if (u.uhunger <= 700)
  268:                                 pline("That satiated your stomach!");
  269:                         else {
  270:                                 pline("You're having a hard time getting all that food down.");
  271:                                 multi -= 2;
  272:                         }
  273:                         lesshungry(ftmp->nutrition);
  274:                         if (multi < 0)
  275:                                 nomovemsg = "You finished your meal.";
  276:                         break;
  277:                 case TRIPE_RATION:
  278:                         pline("Yak - dog food!");
  279:                         more_experienced(1, 0);
  280:                         flags.botl = 1;
  281:                         if (rn2(2)) {
  282:                                 pline("You vomit.");
  283:                                 morehungry(20);
  284:                                 if (Sick) {
  285:                                         Sick = 0;  /* David Neves */
  286:                                         pline("What a relief!");
  287:                                 }
  288:                         } else
  289:                                 lesshungry(ftmp->nutrition);
  290:                         break;
  291:                 default:
  292:                         if (otmp->otyp >= CORPSE)
  293:                                 pline("That %s tasted terrible!", ftmp->oc_name);
  294:                         else
  295:                                 pline("That %s was delicious!", ftmp->oc_name);
  296:                         lesshungry(ftmp->nutrition);
  297:                         if (otmp->otyp == DEAD_LIZARD && (Confusion > 2))
  298:                                 Confusion = 2;
  299:                         else
  300: #ifdef QUEST
  301:                         if (otmp->otyp == CARROT && !Blind) {
  302:                                 u.uhorizon++;
  303:                                 setsee();
  304:                                 pline("Your vision improves.");
  305:                         } else
  306: #endif  /* QUEST */
  307:                         if (otmp->otyp == FORTUNE_COOKIE) {
  308:                                 if (Blind) {
  309:                                         pline("This cookie has a scrap of paper inside!");
  310:                                         pline("What a pity, that you cannot read it!");
  311:                                 } else
  312:                                         outrumor();
  313:                         } else if (otmp->otyp == LUMP_OF_ROYAL_JELLY) {
  314:                                 /* This stuff seems to be VERY healthy! */
  315:                                 if (u.ustrmax < 118)
  316:                                         u.ustrmax++;
  317:                                 if (u.ustr < u.ustrmax)
  318:                                         u.ustr++;
  319:                                 u.uhp += rnd(20);
  320:                                 if (u.uhp > u.uhpmax) {
  321:                                         if (!rn2(17))
  322:                                                 u.uhpmax++;
  323:                                         u.uhp = u.uhpmax;
  324:                                 }
  325:                                 heal_legs();
  326:                         }
  327:                         break;
  328:                 }
  329:         }
  330: eatx:
  331:         if (multi < 0 && !nomovemsg) {
  332:                 static char     msgbuf[BUFSZ];
  333:                 (void) sprintf(msgbuf, "You finished eating the %s.",
  334:                                ftmp->oc_name);
  335:                 nomovemsg = msgbuf;
  336:         }
  337:         useup(otmp);
  338:         return (1);
  339: }
  340: 
  341: /* called in hack.main.c */
  342: void
  343: gethungry()
  344: {
  345:         --u.uhunger;
  346:         if (moves % 2) {
  347:                 if (Regeneration)
  348:                         u.uhunger--;
  349:                 if (Hunger)
  350:                         u.uhunger--;
  351:                 /*
  352:                  * a3:  if(Hunger & LEFT_RING) u.uhunger--; if(Hunger &
  353:                  * RIGHT_RING) u.uhunger--; etc.
  354:                  */
  355:         }
  356:         if (moves % 20 == 0) { /* jimt@asgb */
  357:                 if (uleft)
  358:                         u.uhunger--;
  359:                 if (uright)
  360:                         u.uhunger--;
  361:         }
  362:         newuhs(TRUE);
  363: }
  364: 
  365: /* called after vomiting and after performing feats of magic */
  366: void
  367: morehungry(num)
  368:         int num;
  369: {
  370:         u.uhunger -= num;
  371:         newuhs(TRUE);
  372: }
  373: 
  374: /* called after eating something (and after drinking fruit juice) */
  375: void
  376: lesshungry(num)
  377:         int num;
  378: {
  379:         u.uhunger += num;
  380:         newuhs(FALSE);
  381: }
  382: 
  383: int
  384: unfaint()
  385: {
  386:         u.uhs = FAINTING;
  387:         flags.botl = 1;
  388:         return 0;
  389: }
  390: 
  391: void
  392: newuhs(incr)
  393:         boolean         incr;
  394: {
  395:         int             newhs, h = u.uhunger;
  396: 
  397:         newhs = (h > 1000) ? SATIATED :
  398:                 (h > 150) ? NOT_HUNGRY :
  399:                 (h > 50) ? HUNGRY :
  400:                 (h > 0) ? WEAK : FAINTING;
  401: 
  402:         if (newhs == FAINTING) {
  403:                 if (u.uhs == FAINTED)
  404:                         newhs = FAINTED;
  405:                 if (u.uhs <= WEAK || rn2(20 - u.uhunger / 10) >= 19) {
  406:                         if (u.uhs != FAINTED && multi >= 0 /* %% */ ) {
  407:                                 pline("You faint from lack of food.");
  408:                                 nomul(-10 + (u.uhunger / 10));
  409:                                 nomovemsg = "You regain consciousness.";
  410:                                 afternmv = unfaint;
  411:                                 newhs = FAINTED;
  412:                         }
  413:                 } else if (u.uhunger < -(int) (200 + 25 * u.ulevel)) {
  414:                         u.uhs = STARVED;
  415:                         flags.botl = 1;
  416:                         bot();
  417:                         pline("You die from starvation.");
  418:                         done("starved");
  419:                 }
  420:         }
  421:         if (newhs != u.uhs) {
  422:                 if (newhs >= WEAK && u.uhs < WEAK)
  423:                         losestr(1);  /* this may kill you -- see below */
  424:                 else if (newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax)
  425:                         losestr(-1);
  426:                 switch (newhs) {
  427:                 case HUNGRY:
  428:                         pline((!incr) ? "You only feel hungry now." :
  429:                               (u.uhunger < 145) ? "You feel hungry." :
  430:                               "You are beginning to feel hungry.");
  431:                         break;
  432:                 case WEAK:
  433:                         pline((!incr) ? "You feel weak now." :
  434:                               (u.uhunger < 45) ? "You feel weak." :
  435:                               "You are beginning to feel weak.");
  436:                         break;
  437:                 }
  438:                 u.uhs = newhs;
  439:                 flags.botl = 1;
  440:                 if (u.uhp < 1) {
  441:                         pline("You die from hunger and exhaustion.");
  442:                         killer = "exhaustion";
  443:                         done("starved");
  444:                 }
  445:         }
  446: }
  447: 
  448: #define CORPSE_I_TO_C(otyp)     (char) ((otyp >= DEAD_ACID_BLOB)\
  449:                      ?  'a' + (otyp - DEAD_ACID_BLOB)\
  450:                      :        '@' + (otyp - DEAD_HUMAN))
  451: int
  452: poisonous(otmp)
  453:         struct obj     *otmp;
  454: {
  455:         return (strchr(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0);
  456: }
  457: 
  458: /* returns 1 if some text was printed */
  459: int
  460: eatcorpse(otmp)
  461:         struct obj     *otmp;
  462: {
  463:         char            let = CORPSE_I_TO_C(otmp->otyp);
  464:         int             tp = 0;
  465:         if (let != 'a' && moves > otmp->age + 50 + rn2(100)) {
  466:                 tp++;
  467:                 pline("Ulch -- that meat was tainted!");
  468:                 pline("You get very sick.");
  469:                 Sick = 10 + rn2(10);
  470:                 u.usick_cause = objects[otmp->otyp].oc_name;
  471:         } else if (strchr(POISONOUS, let) && rn2(5)) {
  472:                 tp++;
  473:                 pline("Ecch -- that must have been poisonous!");
  474:                 if (!Poison_resistance) {
  475:                         losestr(rnd(4));
  476:                         losehp(rnd(15), "poisonous corpse");
  477:                 } else
  478:                         pline("You don't seem affected by the poison.");
  479:         } else if (strchr("ELNOPQRUuxz", let) && rn2(5)) {
  480:                 tp++;
  481:                 pline("You feel sick.");
  482:                 losehp(rnd(8), "cadaver");
  483:         }
  484:         switch (let) {
  485:         case 'L':
  486:         case 'N':
  487:         case 't':
  488:                 Teleportation |= INTRINSIC;
  489:                 break;
  490:         case 'W':
  491:                 pluslvl();
  492:                 break;
  493:         case 'n':
  494:                 u.uhp = u.uhpmax;
  495:                 flags.botl = 1;
  496:                 /* fall into next case */
  497:         case '@':
  498:                 pline("You cannibal! You will be sorry for this!");
  499:                 /* not tp++; */
  500:                 /* fall into next case */
  501:         case 'd':
  502:                 Aggravate_monster |= INTRINSIC;
  503:                 break;
  504:         case 'I':
  505:                 if (!Invis) {
  506:                         Invis = 50 + rn2(100);
  507:                         if (!See_invisible)
  508:                                 newsym(u.ux, u.uy);
  509:                 } else {
  510:                         Invis |= INTRINSIC;
  511:                         See_invisible |= INTRINSIC;
  512:                 }
  513:                 /* fall into next case */
  514:         case 'y':
  515: #ifdef QUEST
  516:                 u.uhorizon++;
  517: #endif  /* QUEST */
  518:                 /* fall into next case */
  519:         case 'B':
  520:                 Confusion = 50;
  521:                 break;
  522:         case 'D':
  523:                 Fire_resistance |= INTRINSIC;
  524:                 break;
  525:         case 'E':
  526:                 Telepat |= INTRINSIC;
  527:                 break;
  528:         case 'F':
  529:         case 'Y':
  530:                 Cold_resistance |= INTRINSIC;
  531:                 break;
  532:         case 'k':
  533:         case 's':
  534:                 Poison_resistance |= INTRINSIC;
  535:                 break;
  536:         case 'c':
  537:                 pline("You turn to stone.");
  538:                 killer = "dead cockatrice";
  539:                 done("died");
  540:                 /* NOTREACHED */
  541:         case 'a':
  542:                 if (Stoned) {
  543:                         pline("What a pity - you just destroyed a future piece of art!");
  544:                         tp++;
  545:                         Stoned = 0;
  546:                 }
  547:                 break;
  548:         case 'M':
  549:                 pline("You cannot resist the temptation to mimic a treasure chest.");
  550:                 tp++;
  551:                 nomul(-30);
  552:                 afternmv = Meatdone;
  553:                 nomovemsg = "You now again prefer mimicking a human.";
  554:                 u.usym = '$';
  555:                 prme();
  556:                 break;
  557:         }
  558:         return (tp);
  559: }
1