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