Source:NetHack 2.3e/potion.c

Below is the full text to potion.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/potion.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)potion.c	2.3	88/02/11 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include "hack.h"  5.    extern int float_down; 6.   extern char *nomovemsg; 7.   extern struct monst youmonst; 8.   extern struct monst *makemon; 9.   char *hcolor; 10.  #ifdef KAA 11.  char *xname; 12.  extern char pl_character[]; 13.  #endif 14.  #ifdef FOUNTAINS 15.  extern int drinkfountain; 16.  extern int dipfountain; 17.  #endif 18.   19.   int	nothing, unkn; 20.   21.   dodrink { 22.  	register struct obj *otmp; 23.  	register int	retval; 24.   25.   #ifdef FOUNTAINS 26.   27.         /* Is there something to drink here, i.e., a fountain? */ 28.          if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 29.  	  pline("Drink from the fountain? [ny] "); 30.  	  if(readchar == 'y') { 31.  	    (void) drinkfountain; 32.  	    return(0); 33.  	  }  34.          }    35.    36.   #endif /* FOUNTAINS /**/ 37.   38.   	nothing = unkn = 0; 39.  	otmp = getobj("!", "drink"); 40.  	if(!otmp) return(0); 41.  	if(!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) { 42.  		ghost_from_bottle; 43.  		goto use_it; 44.  	}  45.   	if(!strcmp(objects[otmp->otyp].oc_descr, "glowing") && !rn2(13)) { 46.  		djinni_from_bottle; 47.  		goto use_it; 48.  	}  49.   	if((retval = peffects(otmp)) >= 0) return(retval); 50.   51.   	if(nothing) { 52.  	    unkn++; 53.  	    pline("You have a %s feeling for a moment, then it passes.",  54.   		  Hallucination ? "normal" : "peculiar"); 55.  	}  56.   	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { 57.  		if(!unkn) { 58.  			objects[otmp->otyp].oc_name_known = 1; 59.  			more_experienced(0,10); 60.  		} else if(!objects[otmp->otyp].oc_uname) 61.  			docall(otmp); 62.  	}  63.   use_it: 64.  	useup(otmp); 65.  	return(1); 66.  }  67.    68.   peffects(otmp) 69.  	register struct obj	*otmp; 70.  {  71.   	register struct obj	*objs; 72.  	register struct monst	*mtmp; 73.   74.   	switch(otmp->otyp){ 75.  	case POT_RESTORE_STRENGTH: 76.  #ifdef SPELLS 77.  	case SPE_RESTORE_STRENGTH: 78.  #endif 79.  		unkn++; 80.  		pline("Wow!  This makes you feel great!"); 81.  		if(u.ustr < u.ustrmax) { 82.  			u.ustr = u.ustrmax; 83.  			flags.botl = 1; 84.  		}  85.   		break; 86.  #ifdef KAA 87.  	case POT_HALLUCINATION: 88.  		if (Hallucination) nothing++; 89.  		else pline("Oh wow!  Everything looks so cosmic!"); 90.  		Hallucination += rn1(100,750); 91.  		setsee; 92.  		break; 93.  	case POT_HOLY_WATER: 94.  		unkn++; 95.  		if(index("VWZ&",u.usym)) { 96.  			pline("This burns like acid!"); 97.  			/* should never kill you, but... */ 98.   			losehp(d(2,6), "potion of holy water"); 99.  		} else { 100. 			pline("You feel full of awe."); 101. 			if (Sick) Sick=0; 102. 			if (HConfusion) HConfusion=0; 103. 		}  104.  #else 105. 	case POT_HOLY_WATER: 106. 	case POT_HALLUCINATION: 107. #endif 108. 		break; 109. 	case POT_BOOZE: 110. 		unkn++; 111. 		pline("Ooph!  This tastes like liquid fire!"); 112. 		HConfusion += d(3,8); 113. 		/* the whiskey makes us feel better */ 114. 		if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey"); 115. 		if(!rn2(4)) { 116. 			pline("You pass out."); 117. 			multi = -rnd(15); 118. 			nomovemsg = "You awake with a headache."; 119. 		}  120.  		break; 121. 	case POT_INVISIBILITY: 122. #ifdef SPELLS 123. 	case SPE_INVISIBILITY: 124. #endif 125. 		if(Invis || See_invisible) 126. 		  nothing++; 127. 		else { 128. 		  if(!Blind) 129. 		    pline("Gee!  All of a sudden, you can't see yourself."); 130. 		  else 131. 		    pline("You feel rather airy."), unkn++; 132. 		  newsym(u.ux,u.uy); 133. 		}  134.  		HInvis += rn1(15,31); 135. 		break; 136. 	case POT_FRUIT_JUICE: 137. 		pline("This tastes like fruit juice."); 138. 		lesshungry(20); 139. 		break; 140. 	case POT_HEALING: 141. 		pline("You begin to feel better."); 142. 		healup(rnd(10), 1, 1, 1); 143. 		break; 144. 	case POT_PARALYSIS: 145. 		if(Levitation) 146. 			pline("You are motionlessly suspended."); 147. 		else 148. 			pline("Your feet are frozen to the floor!"); 149. 		nomul(-(rn1(10,25))); 150. 		break; 151. 	case POT_MONSTER_DETECTION: 152. #ifdef SPELLS 153. 	case SPE_DETECT_MONSTERS: 154. #endif 155. 		if(!fmon) { 156. 			strange_feeling(otmp, "You feel threatened."); 157. 			return(1); 158. 		} else { 159. 			cls; 160. 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 161. 				if(mtmp->mx > 0) 162. 				at(mtmp->mx,mtmp->my,Hallucination ? rndmonsym :  163.  				mtmp->data->mlet); 164. 			prme; 165. 			pline("You sense the presence of monsters."); 166. 			more; 167. 			docrt; 168. 		}  169.  		break; 170. 	case POT_OBJECT_DETECTION: 171. #ifdef SPELLS 172. 	case SPE_DETECT_TREASURE: 173. #endif 174. 		if(!fobj) { 175. 			strange_feeling(otmp, "You feel a pull downward."); 176. 			return(1); 177. 		} else { 178. 		    for(objs = fobj; objs; objs = objs->nobj) 179. 			if(objs->ox != u.ux || objs->oy != u.uy) 180. 				goto outobjmap; 181. 		    pline("You sense the presence of objects close nearby."); 182. 		    break; 183. 		outobjmap: 184. 			cls; 185. 			for(objs = fobj; objs; objs = objs->nobj) 186. 				at(objs->ox,objs->oy,Hallucination ? rndobjsym  187.  				 : objs->olet); 188.  189.  			/* monster possessions added by GAN 12/16/86 */ 190. 			for(mtmp = fmon ; mtmp ; mtmp = mtmp->nmon) 191. 				if(mtmp->minvent) 192. 					for(objs = mtmp->minvent; objs ;  193.  					    objs = objs->nobj) 194. 						at(mtmp->mx,mtmp->my,objs->olet); 195. 			prme; 196. 			pline("You sense the presence of objects."); 197. 			more; 198. 			docrt; 199. 		}  200.  		break; 201. 	case POT_SICKNESS: 202. 		pline("Yech! This stuff tastes like poison."); 203. 		if(Poison_resistance) 204.     pline("(But in fact it was biologically contaminated orange juice.)"); 205. #ifdef KAA 206. 		if (pl_character[0] == 'H') 207. 			pline("Fortunately you have been immunized!"); 208. 		else { 209. #endif 210. 			losestr((Poison_resistance) ? 1 : rn1(4,3)); 211. 			if(!Poison_resistance) 212. 				losehp(rnd(10), "contaminated potion"); 213. #ifdef KAA 214. 		}  215.  #endif 216. 		if(Hallucination) { 217. 			pline("You are shocked back to your senses!"); 218. 			Hallucination=1; 219. 		}  220.  		break; 221. 	case POT_CONFUSION: 222. 		if(!Confusion) 223. 		    if (Hallucination) { 224. 			pline("What a trippy feeling!"); 225. 			unkn++; 226. 		    } else 227. 			pline("Huh, What?  Where am I?"); 228. 		else	nothing++; 229. 		HConfusion += rn1(7,16); 230. 		break; 231. 	case POT_GAIN_STRENGTH: 232. 		pline("Wow do you feel strong!"); 233. 		gainstr(0); 234. 		break; 235. 	case POT_SPEED: 236. 		if(Wounded_legs) { 237. 			heal_legs; 238. 			unkn++; 239. 			break; 240. 		}		/* and fall through */ 241. #ifdef SPELLS 242. 	case SPE_HASTE_SELF: 243. #endif 244. 		if(!(Fast & ~INTRINSIC)) 245. 			pline("You are suddenly moving much faster."); 246. 		else 247. 			pline("Your legs get new energy."), unkn++; 248. 		Fast += rn1(10,100); 249. 		break; 250. 	case POT_BLINDNESS: 251. 		if(!Blind) 252. 			if (Hallucination) 253. 				pline("Bummer!  Everything is dark!  Help!"); 254. 			else 255. 				pline("A cloud of darkness falls upon you."); 256. 		else	nothing++; 257. 		Blinded += rn1(100,250); 258. 		seeoff(0); 259. 		break; 260. 	case POT_GAIN_LEVEL: 261. 		pluslvl; 262. 		break; 263. 	case POT_EXTRA_HEALING: 264. 		pline("You feel much better."); 265. 		healup(d(2,20)+1, 2, 1, 1); 266. 		if(Hallucination) Hallucination = 1; 267. 		break; 268. 	case POT_LEVITATION: 269. #ifdef SPELLS 270. 	case SPE_LEVITATION: 271. #endif 272. 		if(!Levitation) 273. 			float_up; 274. 		else 275. 			nothing++; 276. 		Levitation += rnd(100); 277. 		u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down; 278. 		break; 279. 	case POT_GAIN_ENERGY:			/* M. Stephenson */ 280. #ifdef SPELLS 281. 		{	register int	 num; 282. 			if(Confusion) { 283. 			    pline("You feel feverish."); 284. 			    unkn++; 285. 			} else 286. 			    pline("Magical energies course through your body."); 287. 			num = rnd(5) + 1; 288. 			u.uenmax += num; 289. 			u.uen += num; 290. 			flags.botl = 1; 291. 			break; 292. 		}  293.  #else 294. 		pline("This potion tastes weird!"); 295. 		break; 296. #endif 297. 	default: 298. 		impossible("What a funny potion! (%u)", otmp->otyp); 299. 		return(0); 300. 	}  301.  	return(-1); 302. }  303.   304.  healup(nhp, nxtra, curesick, cureblind) 305. 	int	nhp, nxtra; 306. 	register boolean curesick, cureblind; 307. {  308.  #ifdef KAA 309. 	if (u.mtimedone & nhp) { 310. 		u.mh += rnd(nhp); 311. 		if (u.mh > u.mhmax) u.mh = (u.mhmax + nxtra); 312. 	}  313.  #endif 314. 	if(nhp)	{ 315. 		u.uhp += nhp; 316. 		if(u.uhp > u.uhpmax)	u.uhp = (u.uhpmax += nxtra); 317. 	}  318.  	if(Blind && cureblind)	Blinded = 1;	/* see on next move */ 319. 	if(Sick && curesick)	Sick = 0; 320. 	flags.botl = 1; 321. 	return; 322. }  323.   324.  pluslvl 325. {  326.  	register num; 327.  328.  	pline("You feel more experienced."); 329. 	num = rnd(10); 330. 	u.uhpmax += num; 331. 	u.uhp += num; 332. #ifdef SPELLS 333. 	num = rnd(u.ulevel/2+1) + 1;		/* M. Stephenson */ 334. 	u.uenmax += num; 335. 	u.uen += num; 336. #endif 337. 	if(u.ulevel < 14) { 338. 		extern long newuexp; 339.  340.  		u.uexp = newuexp+1; 341. 		pline("Welcome to experience level %u.", ++u.ulevel); 342. 	}  343.  	flags.botl = 1; 344. }  345.   346.  strange_feeling(obj,txt) 347. register struct obj *obj; 348. register char *txt; 349. {  350.  	if(flags.beginner) 351. 		pline("You have a %s feeling for a moment, then it passes.",  352.  		Hallucination ? "normal" : "strange"); 353. 	else 354. 		pline(txt); 355. 	if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname) 356. 		docall(obj); 357. 	useup(obj); 358. }  359.   360.  char *bottlenames[] = { 361. 	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial" 362. };  363.   364.  potionhit(mon, obj) 365. register struct monst *mon; 366. register struct obj *obj; 367. {  368.  	extern char *xname; 369. 	register char *botlnam = bottlenames[rn2(SIZE(bottlenames))]; 370. 	boolean uclose, isyou = (mon == &youmonst); 371.  372.  	if(isyou) { 373. 		uclose = TRUE; 374. 		pline("The %s crashes on your head and breaks into shivers.",  375.  			botlnam); 376. 		losehp(rnd(2), "thrown potion"); 377. 	} else { 378. 		uclose = (dist(mon->mx,mon->my) < 3); 379. 		/* perhaps 'E' and 'a' have no head? */ 380.  		pline("The %s crashes on %s's head and breaks into shivers.",  381.  			botlnam, monnam(mon)); 382. 		if(rn2(5) && mon->mhp > 1) 383. 			mon->mhp--; 384. 	}  385.  	pline("The %s evaporates.", xname(obj)); 386.  387.  #ifdef KAA 388. 	if(!isyou) switch (obj->otyp) { 389. #else 390. 	if(!isyou && !rn2(3)) switch(obj->otyp) { 391. #endif 392.  393.  	case POT_RESTORE_STRENGTH: 394. 	case POT_GAIN_STRENGTH: 395. 	case POT_HEALING: 396. 	case POT_EXTRA_HEALING: 397. 		if(mon->mhp < mon->mhpmax) { 398. 			mon->mhp = mon->mhpmax; 399. 			pline("%s looks sound and hale again!", Monnam(mon)); 400. 		}  401.  		break; 402. 	case POT_SICKNESS: 403. 		if((mon->mhpmax > 3) && !resist(mon, '!', 0, NOTELL)) 404. 			mon->mhpmax /= 2; 405. 		if((mon->mhp > 2) && !resist(mon, '!', 0, NOTELL)) 406. 			mon->mhp /= 2; 407. #ifdef KAA 408. 		pline("%s looks rather ill.", Monnam(mon)); 409. #endif 410. 		break; 411. 	case POT_CONFUSION: 412. 	case POT_BOOZE: 413. 		if(!resist(mon, '!', 0, NOTELL))  mon->mconf = 1; 414. 		break; 415. 	case POT_INVISIBILITY: 416. 		unpmon(mon); 417. 		mon->minvis = 1; 418. 		pmon(mon); 419. 		break; 420. 	case POT_PARALYSIS: 421. 		mon->mfroz = 1; 422. 		break; 423. 	case POT_SPEED: 424. 		mon->mspeed = MFAST; 425. 		break; 426. 	case POT_BLINDNESS: 427. 		mon->mblinded |= 64 + rn2(32) + 428. 				      rn2(32) * !resist(mon, '!', 0, NOTELL); 429. 		break; 430. #ifdef KAA 431. 	case POT_HOLY_WATER: 432. 		if (index("ZVW &", mon->data->mlet)) { 433. 			pline("%s shrieks in pain!", Monnam(mon)); 434. 			mon->mhp -= d(2,6); 435. 			if (mon->mhp <1) killed(mon); 436. 		}  437.  		break; 438. #endif 439. /*	  440.  	case POT_GAIN_LEVEL: 441. 	case POT_LEVITATION: 442. 	case POT_FRUIT_JUICE: 443. 	case POT_MONSTER_DETECTION: 444. 	case POT_OBJECT_DETECTION: 445. 		break; 446. */  447.  	}  448.  	if(uclose && rn2(5)) 449. 		potionbreathe(obj); 450. 	obfree(obj, Null(obj)); 451. }  452.   453.  potionbreathe(obj) 454. register struct obj *obj; 455. {  456.  	switch(obj->otyp) { 457. 	case POT_RESTORE_STRENGTH: 458. 	case POT_GAIN_STRENGTH: 459. 		if(u.ustr < u.ustrmax) u.ustr++, flags.botl = 1; 460. 		break; 461. 	case POT_HEALING: 462. 	case POT_EXTRA_HEALING: 463. 		if(u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 464. 		break; 465. 	case POT_SICKNESS: 466. 		if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5; 467. 		flags.botl = 1; 468. 		break; 469. 	case POT_HALLUCINATION: 470. #ifdef KAA 471. 		pline("You have a vision for a moment."); 472. 		break; 473. #endif 474. 	case POT_CONFUSION: 475. 	case POT_BOOZE: 476. 		if(!Confusion) 477. 			pline("You feel somewhat dizzy."); 478. 		HConfusion += rnd(5); 479. 		break; 480. 	case POT_INVISIBILITY: 481. 		pline("For an instant you could see through yourself!"); 482. 		break; 483. 	case POT_PARALYSIS: 484. 		pline("Something seems to be holding you."); 485. 		nomul(-rnd(5)); 486. 		break; 487. 	case POT_SPEED: 488. 		Fast += rnd(5); 489. 		pline("Your knees seem more flexible now."); 490. 		break; 491. 	case POT_BLINDNESS: 492. 		if(!Blind) pline("It suddenly gets dark."); 493. 		Blinded += rnd(5); 494. 		seeoff(0); 495. 		break; 496. /*	  497.  	case POT_GAIN_LEVEL: 498. 	case POT_LEVITATION: 499. 	case POT_FRUIT_JUICE: 500. 	case POT_MONSTER_DETECTION: 501. 	case POT_OBJECT_DETECTION: 502. 		break; 503. */  504.  	}  505.  	/* note: no obfree */ 506. }  507.   508.  /*  509.   * -- rudimentary -- to do this correctly requires much more work 510.  * -- all sharp weapons get one or more qualities derived from the potions 511.  * -- texts on scrolls may be (partially) wiped out; do they become blank? 512.  * --   or does their effect change, like under Confusion? 513.  * -- all objects may be made invisible by POT_INVISIBILITY 514.  * -- If the flask is small, can one dip a large object? Does it magically 515.  * --   become a jug? Etc. 516.  */  517.  dodip{ 518. 	register struct obj *potion, *obj; 519. #ifdef KAA 520. 	char *tmp; 521. #endif 522.  523.  	if(!(obj = getobj("#", "dip"))) 524. 		return(0); 525. #ifdef FOUNTAINS 526. 	/* Is there something to dip into here, i.e., a fountain? */ 527.  	if (levl[u.ux][u.uy].typ == FOUNTAIN) { 528. 		pline("Dip it in the fountain? [ny] "); 529. 		if(readchar == 'y') { 530. 			dipfountain(obj); 531. 			return(1); 532. 		}  533.  	}  534.  #endif 535. 	if(!(potion = getobj("!", "dip into"))) 536. 		return(0); 537. #ifndef KAA 538. 	pline("Interesting..."); 539. #else 540. 	if(potion->otyp == POT_HOLY_WATER) { 541. 		if (obj->cursed) { 542. 			obj->cursed=0; 543. 			pline("Your %s %s.", aobjnam(obj,"softly glow"),  544.  			Hallucination ? hcolor : "amber"); 545. 	poof:	useup(potion); 546. 			return(1); 547. 		} else if(obj->otyp >= ARROW && obj->otyp <= SPEAR) { 548. 			obj->dknown=1; 549. 			tmp = Hallucination ? hcolor : "light blue"; 550. 	/* dknown for weapons is meaningless, so it's free to be reused. */ 551.  			pline("Your %s with a%s %s aura.", aobjnam(obj,"softly glow"),  552.  			index("aeiou",*tmp) ? "n" : "", tmp); 553. 			goto poof; 554. 		}  555.  	}  556.  #endif 557. 	if(obj->otyp == ARROW || obj->otyp == DART ||  558.  	   obj->otyp == CROSSBOW_BOLT || obj->otyp == SHURIKEN) { 559. 		if(potion->otyp == POT_SICKNESS) { 560. 			char buf[BUFSZ]; 561. 			useup(potion); 562. 			if(obj->spe < 7) obj->spe++;	/* %% */ 563. 			sprintf(buf, xname(potion)); 564. 			pline("The %s forms a coating on the %s.",  565.  				buf, xname(obj)); 566. 		}  567.  	}  568.  #ifdef HARD 569. 	else	if (!rn2(4)) useup(potion); 570. #endif 571. #ifdef KAA 572. 	pline("Interesting..."); 573. #endif 574. 	return(1); 575. }  576.   577.  ghost_from_bottle{ 578. 	extern struct permonst pm_ghost; 579. 	register struct monst *mtmp; 580.  581.  	if(!(mtmp = makemon(PM_GHOST,u.ux,u.uy))){ 582. 		pline("This bottle turns out to be empty."); 583. 		return; 584. 	}  585.  	mnexto(mtmp); 586. 	pline("As you open the bottle, an enormous ghost emerges!"); 587. 	pline("You are frightened to death, and unable to move."); 588. 	nomul(-3); 589. }  590.   591.  djinni_from_bottle{ 592. 	extern struct permonst pm_djinni; 593. 	register struct monst *mtmp; 594.  595.  	if(!(mtmp = makemon(PM_DJINNI,u.ux,u.uy))){ 596. 		pline("It turns out to be empty."); 597. 		return; 598. 	}  599.   600.  	mtmp->isdjinni = 1; 601. 	mnexto(mtmp); 602. 	if (!Blind) { 603. 		pline("In a cloud of smoke, a djinni emerges!"); 604. 		pline("%s speaks.", Monnam(mtmp)); 605. 	} else { 606. 		pline("You smell fumes!"); 607. 		pline("Something speaks."); 608. 	}  609.   610.  	switch (rn2(5)) { 611. 	case 0 : pline("'I am in your debt. I will grant one wish!'"); 612. 		makewish; 613. 		mondied(mtmp); 614. 		break; 615. 	case 1 : pline("'Thank you for freeing me!'"); 616. 		tamedog(mtmp, (struct obj *) 0); 617. 		break; 618. 	case 2 : pline("'You freed me!'"); 619. 		mtmp->mpeaceful = 1; 620. 		break; 621. 	case 3 : pline("'It is about time!'"); 622. 		pline("The djinni vanishes!"); 623. 		mondied(mtmp); 624. 		break; 625. 	default: pline("You disturbed me fool!"); 626. 		break; 627. 	}  628.  }  629.   630.  gainstr(inc) 631. register int	inc; 632. {  633.  	if (inc) u.ustr++; 634. 	else { 635. 	         if (u.ustr < 18) u.ustr += (rn2(4) ? 1 : rnd(6) ); 636. 		 else if (u.ustr < 103) u.ustr += rnd(10); 637. 		 else u.ustr++; 638. 	       }  639.   640.  	if(u.ustr > 118)	u.ustr = 118; 641. 	if(u.ustr > u.ustrmax)	u.ustrmax = u.ustr; 642. 	flags.botl = 1; 643. }