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