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