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