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