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