Source:NetHack 3.3.0/potion.c

Below is the full text to potion.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/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	3.3	99/03/13	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   #ifdef OVLB 8.   boolean notonhead = FALSE; 9.    10.   static NEARDATA int nothing, unkn; 11.  static NEARDATA const char beverages[] = { POTION_CLASS, 0 }; 12.   13.   STATIC_DCL long FDECL(itimeout, (long)); 14.  STATIC_DCL long FDECL(itimeout_incr, (long,int)); 15.  STATIC_DCL void NDECL(ghost_from_bottle); 16.  STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *)); 17.   18.   /* force `val' to be within valid range for intrinsic timeout value */ 19.  STATIC_OVL long 20.  itimeout(val) 21.  long val; 22.  {  23.       if (val >= TIMEOUT) val = TIMEOUT; 24.      else if (val < 1) val = 0; 25.   26.       return val; 27.  }  28.    29.   /* increment `old' by `incr' and force result to be valid intrinsic timeout */ 30.  STATIC_OVL long 31.  itimeout_incr(old, incr) 32.  long old; 33.  int incr; 34.  {  35.       return itimeout((old & TIMEOUT) + (long)incr); 36.  }  37.    38.   /* set the timeout field of intrinsic `which' */ 39.  void 40.  set_itimeout(which, val) 41.  long *which, val; 42.  {  43.       *which &= ~TIMEOUT; 44.      *which |= itimeout(val); 45.  }  46.    47.   /* increment the timeout field of intrinsic `which' */ 48.  void 49.  incr_itimeout(which, incr) 50.  long *which; 51.  int incr; 52.  {  53.       set_itimeout(which, itimeout_incr(*which, incr)); 54.  }  55.    56.   void 57.  make_confused(xtime,talk) 58.  long xtime; 59.  boolean talk; 60.  {  61.   	long old = HConfusion; 62.   63.   	if (!xtime && old) { 64.  		if (talk) 65.  		    You_feel("less %s now.",  66.   			Hallucination ? "trippy" : "confused"); 67.  	}  68.   	if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE; 69.   70.   	set_itimeout(&HConfusion, xtime); 71.  }  72.    73.   void 74.  make_stunned(xtime,talk) 75.  long xtime; 76.  boolean talk; 77.  {  78.   	long old = HStun; 79.   80.   	if (!xtime && old) { 81.  		if (talk) 82.  		    You_feel("%s now.",  83.   			Hallucination ? "less wobbly" : "a bit steadier"); 84.  	}  85.   	if (xtime && !old) { 86.  		if (talk) You("stagger..."); 87.  	}  88.   	if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE; 89.   90.   	set_itimeout(&HStun, xtime); 91.  }  92.    93.   void 94.  make_sick(xtime, cause, talk, type) 95.  long xtime; 96.  const char *cause;	/* sickness cause */ 97.  boolean talk; 98.  int type; 99.  {  100.  	long old = Sick; 101.  102.  	if (xtime > 0L) { 103. 	    if (Sick_resistance) return; 104. 	    if (!old) { 105. 		/* newly sick */ 106. 		You_feel("deathly sick."); 107. 	    } else { 108. 		/* already sick */ 109. 		if (talk) You_feel("%s worse.",  110.  			      xtime <= Sick/2L ? "much" : "even"); 111. 	    }  112.  	    set_itimeout(&Sick, xtime); 113. 	    u.usick_type |= type; 114. 	    flags.botl = TRUE; 115. 	} else if (old && (type & u.usick_type)) { 116. 	    /* was sick, now not */ 117. 	    u.usick_type &= ~type; 118. 	    if (u.usick_type) { /* only partly cured */ 119. 		if (talk) You_feel("somewhat better."); 120. 		set_itimeout(&Sick, Sick * 2); /* approximation */ 121. 	    } else { 122. 		if (talk) pline("What a relief!"); 123. 		Sick = 0L;		/* set_itimeout(&Sick, 0L) */ 124. 	    }  125.  	    flags.botl = TRUE; 126. 	}  127.   128.  	if (Sick) { 129. 	    exercise(A_CON, FALSE); 130. 	    if (cause) { 131. 		(void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause)); 132. 		u.usick_cause[sizeof(u.usick_cause)-1] = 0; 133. 		}  134.  	    else 135. 		u.usick_cause[0] = 0; 136. 	} else 137. 	    u.usick_cause[0] = 0; 138. }  139.   140.  void 141. make_vomiting(xtime, talk) 142. long xtime; 143. boolean talk; 144. {  145.  	long old = Vomiting; 146.  147.  	if(!xtime && old) 148. 	    if(talk) You_feel("much less nauseous now."); 149.  150.  	set_itimeout(&Vomiting, xtime); 151. }  152.   153.   154.  void 155. make_blinded(xtime, talk) 156. long xtime; 157. boolean talk; 158. {  159.  	long old = Blinded; 160. 	boolean changed = FALSE; 161.  162.  	if (u.usleep) talk = FALSE; 163.  164.  	if (!xtime && old && !Blindfolded && haseyes(youmonst.data)) { 165. 	    if (talk) { 166. 		if (Hallucination) 167. 		    pline("Far out!  Everything is all cosmic again!"); 168. 		else		   You("can see again."); 169. 	    }  170.  	    changed = TRUE; 171. 	}  172.  	if (xtime && !old && !Blindfolded && haseyes(youmonst.data)) { 173. 	    if (talk) { 174. 		if (Hallucination) 175. 			pline("Oh, bummer!  Everything is dark!  Help!"); 176. 		else 177. 			pline("A cloud of darkness falls upon you."); 178. 	    }  179.  	    changed = TRUE; 180.  181.  	    /* Before the hero goes blind, set the ball&chain variables. */ 182.  	    if (Punished) set_bc(0); 183. 	}  184.  	set_itimeout(&Blinded, xtime); 185. 	if (changed) { 186. 	    flags.botl = 1; 187. 	    vision_full_recalc = 1; 188. 	    if (Blind_telepat || Infravision) see_monsters; 189. 	}  190.  }  191.   192.  void 193. make_hallucinated(xtime, talk, mask) 194. long xtime;	/* nonzero if this is an attempt to turn on hallucination */ 195. boolean talk; 196. long mask;	/* nonzero if resistance status should change by mask */ 197. {  198.  	boolean changed = 0; 199. #ifdef LINT 200. 	const char *message = 0; 201. #else 202. 	const char *message; 203. #endif 204.  205.  	if (!xtime) 206. 	    message = "Everything looks SO boring now."; 207. 	else 208. 	    message = "Oh wow!  Everything seems so cosmic!"; 209.  210.  	if (mask) { 211. 	    if (HHallucination) changed = TRUE; 212.  213.  	    if (!xtime) EHalluc_resistance |= mask; 214. 	    else EHalluc_resistance &= ~mask; 215. 	} else { 216. 	    if (!EHalluc_resistance && (!!HHallucination != !!xtime)) 217. 		changed = TRUE; 218. 	    set_itimeout(&HHallucination, xtime); 219. 	}  220.   221.  	if (changed) { 222. 	    if (u.uswallow) { 223. 		swallowed(0);	/* redraw swallow display */ 224. 	    } else { 225. 		/* The see_* routines should be called *before* the pline. */ 226.  		see_monsters; 227. 		see_objects; 228. 	    }  229.  	    flags.botl = 1; 230. 	    if (!Blind && talk) pline(message); 231. 	}  232.  }  233.   234.  STATIC_OVL void 235. ghost_from_bottle 236. {  237.  	struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS); 238.  239.  	if (!mtmp) { 240. 		pline("This bottle turns out to be empty."); 241. 		return; 242. 	}  243.  	if (Blind) { 244. 		pline("As you open the bottle, %s emerges.", something); 245. 		return; 246. 	}  247.  	pline("As you open the bottle, an enormous %s emerges!",  248.  		Hallucination ? rndmonnam : (const char *)"ghost"); 249. 	if(flags.verbose) 250. 	    You("are frightened to death, and unable to move."); 251. 	nomul(-3); 252. 	nomovemsg = "You regain your composure."; 253. }  254.   255.  int 256. dodrink { 257. 	register struct obj *otmp; 258. 	const char *potion_descr; 259.  260.  	if (Strangled) { 261. 		pline("If you can't breathe air, how can you drink liquid?"); 262. 		return 0; 263. 	}  264.  	/* Is there a fountain to drink from here? */ 265.  	if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) { 266. 		if(yn("Drink from the fountain?") == 'y') { 267. 			drinkfountain; 268. 			return 1; 269. 		}  270.  	}  271.  #ifdef SINKS 272. 	/* Or a kitchen sink? */ 273.  	if (IS_SINK(levl[u.ux][u.uy].typ)) { 274. 		if (yn("Drink from the sink?") == 'y') { 275. 			drinksink; 276. 			return 1; 277. 		}  278.  	}  279.  #endif 280.  281.  	/* Or are you surrounded by water? */ 282.  	if (Underwater) { 283. 		if (yn("Drink the water around you?") == 'y') { 284. 		    pline("Do you know what lives in this water!"); 285. 			return 1; 286. 		}  287.  	}  288.   289.  	otmp = getobj(beverages, "drink"); 290. 	if(!otmp) return(0); 291. 	otmp->in_use = TRUE;		/* you've opened the stopper */ 292.  293.  #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))	/* also in muse.c */ 294.  295.  	potion_descr = OBJ_DESCR(objects[otmp->otyp]); 296. 	if (potion_descr && !strcmp(potion_descr, "milky") &&  297.  		    flags.ghost_count < MAXMONNO &&  298.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) { 299. 		ghost_from_bottle; 300. 		useup(otmp); 301. 		return(1); 302. 	} else if (potion_descr && !strcmp(potion_descr, "smoky") &&  303.  		    flags.djinni_count < MAXMONNO &&  304.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) { 305. 		djinni_from_bottle(otmp); 306. 		useup(otmp); 307. 		return(1); 308. 	}  309.  	return dopotion(otmp); 310. }  311.   312.  int 313. dopotion(otmp) 314. register struct obj *otmp; 315. {  316.  	int retval; 317.  318.  	nothing = unkn = 0; 319. 	if((retval = peffects(otmp)) >= 0) return(retval); 320.  321.  	if(nothing) { 322. 	    unkn++; 323. 	    You("have a %s feeling for a moment, then it passes.",  324.  		  Hallucination ? "normal" : "peculiar"); 325. 	}  326.  	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { 327. 		if(!unkn) { 328. 			makeknown(otmp->otyp); 329. 			more_experienced(0,10); 330. 		} else if(!objects[otmp->otyp].oc_uname) 331. 			docall(otmp); 332. 	}  333.  	useup(otmp); 334. 	return(1); 335. }  336.   337.  int 338. peffects(otmp) 339. 	register struct obj	*otmp; 340. {  341.  	register int i, ii, lim; 342.  343.  	switch(otmp->otyp){ 344. 	case POT_RESTORE_ABILITY: 345. 	case SPE_RESTORE_ABILITY: 346. 		unkn++; 347. 		if(otmp->cursed) { 348. 		    pline("Ulch!  This makes you feel mediocre!"); 349. 		    break; 350. 		} else { 351. 		    pline("Wow!  This makes you feel %s!",  352.  			  (otmp->blessed) ? "great" : "good"); 353. 		    i = rn2(A_MAX);		/* start at a random point */ 354. 		    for (ii = 0; ii < A_MAX; ii++) { 355. 			lim = AMAX(i); 356. 			if (i == A_STR && u.uhs >= 3) --lim;	/* WEAK */ 357. 			if (ABASE(i) < lim) { 358. 			    ABASE(i) = lim; 359. 			    flags.botl = 1; 360. 			    /* only first found if not blessed */ 361. 			    if (!otmp->blessed) break; 362. 			}  363.  			if(++i >= A_MAX) i = 0; 364. 		    }  365.  		}  366.  		break; 367. 	case POT_HALLUCINATION: 368. 		if (Hallucination || Halluc_resistance) nothing++; 369. 		make_hallucinated(itimeout_incr(HHallucination, 370. 					   rn1(200, 600 - 300 * bcsign(otmp))),  371.  				  TRUE, 0L); 372. 		break; 373. 	case POT_WATER: 374. 		if(!otmp->blessed && !otmp->cursed) { 375. 			pline("This tastes like water."); 376. 			u.uhunger += rnd(10); 377. 			newuhs(FALSE); 378. 			break; 379. 		}  380.  		unkn++; 381. 		if(is_undead(youmonst.data) || is_demon(youmonst.data) ||  382.  				u.ualign.type == A_CHAOTIC) { 383. 		    if(otmp->blessed) { 384. 			pline("This burns like acid!"); 385. 			exercise(A_CON, FALSE); 386. 			if (u.ulycn >= LOW_PM) { 387. 			    Your("affinity to %s disappears!",  388.  				 makeplural(mons[u.ulycn].mname)); 389. 			    if (youmonst.data == &mons[u.ulycn]) 390. 				you_unwere(FALSE); 391. 			    u.ulycn = NON_PM;	/* cure lycanthropy */ 392. 			}  393.  			losehp(d(2,6), "potion of holy water", KILLED_BY_AN); 394. 		    } else if(otmp->cursed) { 395. 			You_feel("quite proud of yourself."); 396. 			healup(d(2,6),0,0,0); 397. 			if (u.ulycn >= LOW_PM && !Upolyd) you_were; 398. 			exercise(A_CON, TRUE); 399. 		    }  400.  		} else { 401. 		    if(otmp->blessed) { 402. 			You_feel("full of awe."); 403. 			make_sick(0L, (char *) 0, TRUE, SICK_ALL); 404. 			exercise(A_WIS, TRUE); 405. 			exercise(A_CON, TRUE); 406. 			if (u.ulycn >= LOW_PM) 407. 			    you_unwere(TRUE);	/* "Purified" */ 408. 			/* make_confused(0L,TRUE); */ 409. 		    } else { 410. 			if(u.ualign.type == A_LAWFUL) { 411. 			    pline("This burns like acid!"); 412. 			    losehp(d(2,6), "potion of unholy water",  413.  				KILLED_BY_AN); 414. 			} else 415. 			    You_feel("full of dread."); 416. 			if (u.ulycn >= LOW_PM && !Upolyd) you_were; 417. 			exercise(A_CON, FALSE); 418. 		    }  419.  		}  420.  		break; 421. 	case POT_BOOZE: 422. 		unkn++; 423. 		pline("Ooph!  This tastes like %s%s!",  424.  		      otmp->odiluted ? "watered down " : "",  425.  		      Hallucination ? "dandelion wine" : "liquid fire"); 426. 		if (!otmp->blessed) 427. 		    make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE); 428. 		/* the whiskey makes us feel better */ 429. 		if (!otmp->odiluted) healup(1, 0, FALSE, FALSE); 430. 		u.uhunger += 10 * (2 + bcsign(otmp)); 431. 		newuhs(FALSE); 432. 		exercise(A_WIS, FALSE); 433. 		if(otmp->cursed) { 434. 			You("pass out."); 435. 			multi = -rnd(15); 436. 			nomovemsg = "You awake with a headache."; 437. 		}  438.  		break; 439. 	case POT_ENLIGHTENMENT: 440. 		if(otmp->cursed) { 441. 			unkn++; 442. 			You("have an uneasy feeling..."); 443. 			exercise(A_WIS, FALSE); 444. 		} else { 445. 			if (otmp->blessed) { 446. 				(void) adjattrib(A_INT, 1, FALSE); 447. 				(void) adjattrib(A_WIS, 1, FALSE); 448. 			}  449.  			You_feel("self-knowledgeable..."); 450. 			display_nhwindow(WIN_MESSAGE, FALSE); 451. 			enlightenment(0); 452. 			pline_The("feeling subsides."); 453. 			exercise(A_WIS, TRUE); 454. 		}  455.  		break; 456. 	case SPE_INVISIBILITY: 457. 		/* spell cannot penetrate mummy wrapping */ 458. 		if (BInvis && uarmc->otyp == MUMMY_WRAPPING) { 459. 			You_feel("rather itchy under your %s.", xname(uarmc)); 460. 			break; 461. 		}  462.  		/* FALLTHRU */ 463. 	case POT_INVISIBILITY: 464. 		if (Invisible || Blind || BInvis) { 465. 		    nothing++; 466. 		} else { 467. 		    self_invis_message; 468. 		}  469.  		if (otmp->blessed) HInvis |= FROMOUTSIDE; 470. 		else incr_itimeout(&HInvis, rn1(15,31)); 471. 		newsym(u.ux,u.uy);	/* update position */ 472. 		if(otmp->cursed) { 473. 		    pline("For some reason, you feel your presence is known."); 474. 		    aggravate; 475. 		}  476.  		break; 477. 	case POT_SEE_INVISIBLE: 478. 		/* tastes like fruit juice in Rogue */ 479. 	case POT_FRUIT_JUICE: 480. 	    {  481.  		int msg = Invisible && !Blind; 482.  483.  		unkn++; 484. 		if (otmp->cursed) 485. 		    pline("Yecch!  This tastes %s.",  486.  			  Hallucination ? "overripe" : "rotten"); 487. 		else pline(Hallucination ?  488.  		"This tastes like 10%% real %s%s juice all-natural beverage." :  489.  				"This tastes like %s%s juice.",  490.  			  otmp->odiluted ? "reconstituted " : "", pl_fruit); 491. 		if (otmp->otyp == POT_FRUIT_JUICE) { 492. 		    u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp)); 493. 		    newuhs(FALSE); 494. 		    break; 495. 		}  496.  		if (!otmp->cursed) { 497. 			/* Tell them they can see again immediately, which 498. 			 * will help them identify the potion...  499. */ 500.  			make_blinded(0L,TRUE); 501. 		}  502.  		if (otmp->blessed) 503. 			HSee_invisible |= FROMOUTSIDE; 504. 		else 505. 			incr_itimeout(&HSee_invisible, rn1(100,750)); 506. 		set_mimic_blocking; /* do special mimic handling */ 507. 		see_monsters;	/* see invisible monsters */ 508. 		newsym(u.ux,u.uy); /* see yourself! */ 509.  		if (msg && !Blind) { /* Blind possible if polymorphed */ 510. 		    You("can see through yourself, but you are visible!"); 511. 		    unkn--; 512. 		}  513.  		break; 514. 	    }  515.  	case POT_PARALYSIS: 516. 		if (Free_action) 517. 		    You("stiffen momentarily."); 518. 		else { 519. 		    if (Levitation||Is_airlevel(&u.uz)||Is_waterlevel(&u.uz)) 520. 			You("are motionlessly suspended."); 521. 		    else 522. 			Your("%s are frozen to the %s!",  523.  			     makeplural(body_part(FOOT)), surface(u.ux, u.uy)); 524. 		    nomul(-(rn1(10, 25 - 12*bcsign(otmp)))); 525. 		    nomovemsg = You_can_move_again; 526. 		    exercise(A_DEX, FALSE); 527. 		}  528.  		break; 529. 	case POT_SLEEPING: 530. 		if(Sleep_resistance || Free_action) 531. 		    You("yawn."); 532. 		else { 533. 		    pline("You suddenly fall asleep!"); 534. 		    fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE); 535. 		}  536.  		break; 537. 	case POT_MONSTER_DETECTION: 538. 	case SPE_DETECT_MONSTERS: 539. 		if (otmp->blessed) { 540. 		    int x, y;  541. 542. 		    if (Detect_monsters) nothing++; 543. 		    unkn++; 544. 		    set_itimeout(&HDetect_monsters, 20L+rnd(40)); 545. 		    for (x = 1; x < COLNO; x++) { 546. 			for (y = 0; y < ROWNO; y++) { 547. 			    if (levl[x][y].glyph == GLYPH_INVISIBLE) { 548. 				unmap_object(x, y); 549. 				newsym(x,y); 550. 			    }  551.  			    if (MON_AT(x,y)) unkn = 0; 552. 			}  553.  		    }  554.  		    see_monsters; 555. 		    break; 556. 		}  557.  		if (monster_detect(otmp, 0)) 558. 			return(1);		/* nothing detected */ 559. 		exercise(A_WIS, TRUE); 560. 		break; 561. 	case POT_OBJECT_DETECTION: 562. 	case SPE_DETECT_TREASURE: 563. 		if (object_detect(otmp, 0)) 564. 			return(1);		/* nothing detected */ 565. 		exercise(A_WIS, TRUE); 566. 		break; 567. 	case POT_SICKNESS: 568. 		pline("Yecch!  This stuff tastes like poison."); 569. 		if (otmp->blessed) { 570. 		    pline("(But in fact it was mildly stale %s juice.)",  571.  			  pl_fruit); 572. 		    if (!Role_if(PM_HEALER)) 573. 			losehp(1, "mildly contaminated potion", KILLED_BY_AN); 574. 		} else { 575. 		    if(Poison_resistance) 576. 			pline(  577.  		    "(But in fact it was biologically contaminated %s juice.)",  578.  			      pl_fruit); 579. 		    if (Role_if(PM_HEALER)) 580. 			pline("Fortunately, you have been immunized."); 581. 		    else { 582. 			int typ = rn2(A_MAX); 583.  584.  			if (!Fixed_abil) { 585. 			    poisontell(typ); 586. 			    (void) adjattrib(typ,  587.  			    		Poison_resistance ? -1 : -rn1(4,3),  588.  			    		TRUE); 589. 			}  590.  			if(!Poison_resistance) 591. 				losehp(rnd(10)+5*!!(otmp->cursed),  592.  				       "contaminated potion", KILLED_BY_AN); 593. 			exercise(A_CON, FALSE); 594. 		    }  595.  		}  596.  		if(Hallucination) { 597. 			You("are shocked back to your senses!"); 598. 			make_hallucinated(0L,FALSE,0L); 599. 		}  600.  		break; 601. 	case POT_CONFUSION: 602. 		if(!Confusion) 603. 		    if (Hallucination) { 604. 			pline("What a trippy feeling!"); 605. 			unkn++; 606. 		    } else 607. 			pline("Huh, What?  Where am I?"); 608. 		else	nothing++; 609. 		make_confused(itimeout_incr(HConfusion, 610. 					    rn1(7, 16 - 8 * bcsign(otmp))),  611.  			      FALSE); 612. 		break; 613. 	case POT_GAIN_ABILITY: 614. 		if(otmp->cursed) { 615. 		    pline("Ulch!  That potion tasted foul!"); 616. 		    unkn++; 617. 		} else {      /* If blessed, increase all; if not, try up to */ 618. 		    int itmp; /* 6 times to find one which can be increased. */ 619.  		    i = -1;		/* increment to 0 */ 620. 		    for (ii = A_MAX; ii > 0; ii--) { 621. 			i = (otmp->blessed ? i + 1 : rn2(A_MAX)); 622. 			/* only give "your X is already as high as it can get" 623. 			   message on last attempt (except blessed potions) */ 624. 			itmp = (otmp->blessed || ii == 1) ? 0 : -1; 625.  			if (adjattrib(i, 1, itmp) && !otmp->blessed) 626. 			    break; 627. 		    }  628.  		}  629.  		break; 630. 	case POT_SPEED: 631. 		if(Wounded_legs && !otmp->cursed) { 632. 			heal_legs; 633. 			unkn++; 634. 			break; 635. 		}		/* and fall through */ 636. 	case SPE_HASTE_SELF: 637. 		if(!Very_fast) /* wwf@doe.carleton.ca */ 638. 			You("are suddenly moving %sfaster.",  639.  				Fast ? "" : "much "); 640. 		else { 641. 			Your("%s get new energy.",  642.  				makeplural(body_part(LEG))); 643. 			unkn++; 644. 		}  645.  		exercise(A_DEX, TRUE); 646. 		incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp))); 647. 		break; 648. 	case POT_BLINDNESS: 649. 		if(Blind) nothing++; 650. 		make_blinded(itimeout_incr(Blinded, 651. 					   rn1(200, 250 - 125 * bcsign(otmp))),  652.  			     TRUE); 653. 		break; 654. 	case POT_GAIN_LEVEL: 655. 		if (otmp->cursed) { 656. 			unkn++; 657. 			/* they went up a level */ 658. 			if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||  659.  				Can_rise_up(u.ux, u.uy, &u.uz)) { 660. 			    const char *riseup ="rise up, through the %s!"; 661. 			    if(ledger_no(&u.uz) == 1) { 662. 			        You(riseup, ceiling(u.ux,u.uy)); 663. 				goto_level(&earth_level, FALSE, FALSE, FALSE); 664. 			    } else { 665. 			        register int newlev = depth(&u.uz)-1; 666. 				d_level newlevel; 667.  668.  				get_level(&newlevel, newlev); 669. 				if(on_level(&newlevel, &u.uz)) { 670. 				    pline("It tasted bad."); 671. 				    break; 672. 				} else You(riseup, ceiling(u.ux,u.uy)); 673. 				goto_level(&newlevel, FALSE, FALSE, FALSE); 674. 			    }  675.  			}  676.  			else You("have an uneasy feeling."); 677. 			break; 678. 		}  679.  		pluslvl(FALSE); 680. 		if (otmp->blessed) 681. 			/* blessed potions place you at a random spot in the 682. 			 * middle of the new level instead of the low point 683. 			 */  684.  			u.uexp = rndexp; 685. 		break; 686. 	case POT_HEALING: 687. 		You_feel("better."); 688. 		healup(d(6 + 2 * bcsign(otmp), 4),  689.  		       !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed); 690. 		exercise(A_CON, TRUE); 691. 		break; 692. 	case POT_EXTRA_HEALING: 693. 		You_feel("much better."); 694. 		healup(d(6 + 2 * bcsign(otmp), 8),  695.  		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,  696.  		       !otmp->cursed, TRUE); 697. 		make_hallucinated(0L,TRUE,0L); 698. 		exercise(A_CON, TRUE); 699. 		exercise(A_STR, TRUE); 700. 		break; 701. 	case POT_FULL_HEALING: 702. 		You_feel("completely healed."); 703. 		healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE); 704. 		/* Restore one lost level if blessed */ 705. 		if (otmp->blessed && (u.ulevel < u.ulevelmax)) 706. 			pluslvl(FALSE); 707. 		make_hallucinated(0L,TRUE,0L); 708. 		exercise(A_STR, TRUE); 709. 		exercise(A_CON, TRUE); 710. 		break; 711. 	case POT_LEVITATION: 712. 	case SPE_LEVITATION: 713. 		if (otmp->cursed) HLevitation &= ~I_SPECIAL; 714. 		if(!Levitation) { 715. 			/* kludge to ensure proper operation of float_up */ 716. 			HLevitation = 1; 717. 			float_up; 718. 			/* reverse kludge */ 719. 			HLevitation = 0; 720. 			if (otmp->cursed && !Is_waterlevel(&u.uz)) { 721. 	if((u.ux != xupstair || u.uy != yupstair)  722.  	   && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)  723.  	   && (!xupladder || u.ux != xupladder || u.uy != yupladder)  724.  	) { 725. 					You("hit your %s on the %s.",  726.  						body_part(HEAD),  727.  						ceiling(u.ux,u.uy)); 728. 					losehp(uarmh ? 1 : rnd(10),  729.  						"colliding with the ceiling",  730.  						KILLED_BY); 731. 				} else (void) doup; 732. 			}  733.  		} else 734. 			nothing++; 735. 		if (otmp->blessed) { 736. 		    incr_itimeout(&HLevitation, rn1(50,250)); 737. 		    HLevitation |= I_SPECIAL; 738. 		} else incr_itimeout(&HLevitation, rn1(140,10)); 739. 		break; 740. 	case POT_GAIN_ENERGY:			/* M. Stephenson */ 741. 		{	register int num; 742. 			if(otmp->cursed) 743. 			    You_feel("lackluster."); 744. 			else 745. 			    pline("Magical energies course through your body."); 746. 			num = rnd(5) + 5 * otmp->blessed + 1; 747. 			u.uenmax += (otmp->cursed) ? -num : num; 748. 			u.uen += (otmp->cursed) ? -num : num; 749. 			if(u.uenmax <= 0) u.uenmax = 0; 750. 			if(u.uen <= 0) u.uen = 0; 751. 			flags.botl = 1; 752. 			exercise(A_WIS, TRUE); 753. 		}  754.  		break; 755. 	case POT_OIL:				/* P. Winner */ 756. 		{  757.  			boolean good_for_you = FALSE; 758.  759.  			if (otmp->lamplit) { 760. 			    if (likes_fire(youmonst.data)) { 761. 				pline("Ahh, a refreshing drink."); 762. 				good_for_you = TRUE; 763. 			    } else { 764. 				You("burn your %s.", body_part(FACE)); 765. 				losehp(d(Fire_resistance ? 1 : 3, 4), 766.  				       "burning potion of oil", KILLED_BY_AN); 767. 			    }  768.  			} else if(otmp->cursed) 769. 			    pline("This tastes like castor oil."); 770. 			else 771. 			    pline("That was smooth!"); 772. 			exercise(A_WIS, good_for_you); 773. 		}  774.  		break; 775. 	case POT_ACID: 776. 		if (Acid_resistance) 777. 			/* Not necessarily a creature who _likes_ acid */ 778. 			pline("This tastes %s.", Hallucination ? "tangy" : "sour"); 779. 		else { 780. 			pline("This burns%s!", otmp->blessed ? " a little" :  781.  					otmp->cursed ? " a lot" : ""); 782. 			losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8), 783.  					"potion of acid", KILLED_BY_AN); 784. 			exercise(A_CON, FALSE); 785. 		}  786.  		if (Stoned) fix_petrification; 787. 		break; 788. 	case POT_POLYMORPH: 789. 		You_feel("a little %s.", Hallucination ? "normal" : "strange"); 790. 		if (!Unchanging) polyself; 791. 		break; 792. 	default: 793. 		impossible("What a funny potion! (%u)", otmp->otyp); 794. 		return(0); 795. 	}  796.  	return(-1); 797. }  798.   799.  void 800. healup(nhp, nxtra, curesick, cureblind) 801. 	int nhp, nxtra; 802. 	register boolean curesick, cureblind; 803. {  804.  	if (nhp) { 805. 		if (Upolyd) { 806. 			u.mh += nhp; 807. 			if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra); 808. 		} else { 809. 			u.uhp += nhp; 810. 			if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra); 811. 		}  812.  	}  813.  	if(cureblind)	make_blinded(0L,TRUE); 814. 	if(curesick)	make_sick(0L, (char *) 0, TRUE, SICK_ALL); 815. 	flags.botl = 1; 816. 	return; 817. }  818.   819.  void 820. strange_feeling(obj,txt) 821. register struct obj *obj; 822. register const char *txt; 823. {  824.  	if(flags.beginner) 825. 		You("have a %s feeling for a moment, then it passes.",  826.  		Hallucination ? "normal" : "strange"); 827. 	else 828. 		pline(txt); 829.  830.  	if(!obj)	/* e.g., crystal ball finds no traps */ 831. 		return; 832.  833.  	if(obj->dknown && !objects[obj->otyp].oc_name_known &&  834.  						!objects[obj->otyp].oc_uname) 835. 		docall(obj); 836. 	useup(obj); 837. }  838.   839.  const char *bottlenames[] = { 840. 	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial" 841. };  842.   843.  void 844. potionhit(mon, obj, your_fault) 845. register struct monst *mon; 846. register struct obj *obj; 847. boolean your_fault; 848. {  849.  	register const char *botlnam = bottlenames[rn2(SIZE(bottlenames))]; 850. 	boolean isyou = (mon == &youmonst); 851. 	int distance; 852.  853.  	if(isyou) { 854. 		distance = 0; 855. 		pline_The("%s crashes on your %s and breaks into shards.",  856.  			botlnam, body_part(HEAD)); 857. 		losehp(rnd(2), "thrown potion", KILLED_BY_AN); 858. 	} else { 859. 		distance = distu(mon->mx,mon->my); 860. 		if (!cansee(mon->mx,mon->my)) pline("Crash!"); 861. 		else { 862. 		    char *mnam = mon_nam(mon); 863. 		    char buf[BUFSZ]; 864.  865.  		    if(has_head(mon->data)) { 866. 			Sprintf(buf, "%s %s",  867.  				s_suffix(mnam),  868.  				(notonhead ? "body" : "head")); 869. 		    } else { 870. 			Strcpy(buf, mnam); 871. 		    }  872.  		    pline_The("%s crashes on %s and breaks into shards.",  873.  			   botlnam, buf); 874. 		}  875.  		if(rn2(5) && mon->mhp > 1) 876. 			mon->mhp--; 877. 	}  878.   879.  	/* oil doesn't instantly evaporate */ 880. 	if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my)) 881. 		pline("%s evaporates.", The(xname(obj))); 882.  883.      if (isyou) { 884. 	switch (obj->otyp) { 885. 	case POT_OIL: 886. 		if (obj->lamplit) 887. 		    splatter_burning_oil(u.ux, u.uy); 888. 		break; 889. 	case POT_POLYMORPH: 890. 		You_feel("a little %s.", Hallucination ? "normal" : "strange"); 891. 		if (!Unchanging && !Antimagic) polyself; 892. 		break; 893. 	}  894.      } else { 895. 	boolean angermon = TRUE; 896.  897.  	if (!your_fault) angermon = FALSE; 898. 	switch (obj->otyp) { 899. 	case POT_RESTORE_ABILITY: 900. 	case POT_GAIN_ABILITY: 901. 	case POT_HEALING: 902. 	case POT_EXTRA_HEALING: 903. 	case POT_FULL_HEALING: 904. 		angermon = FALSE; 905. 		if(mon->mhp < mon->mhpmax) { 906. 		    mon->mhp = mon->mhpmax; 907. 		    if (canseemon(mon)) 908. 			pline("%s looks sound and hale again.", Monnam(mon)); 909. 		}  910.  		break; 911. 	case POT_SICKNESS: 912. 		if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL)) 913. 			mon->mhpmax /= 2; 914. 		if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL)) 915. 			mon->mhp /= 2; 916. 		if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax; 917. 		if (canseemon(mon)) 918. 		    pline("%s looks rather ill.", Monnam(mon)); 919. 		break; 920. 	case POT_CONFUSION: 921. 	case POT_BOOZE: 922. 		if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE; 923. 		break; 924. 	case POT_INVISIBILITY: 925. 		mon_set_minvis(mon); 926. 		break; 927. 	case POT_SLEEPING: 928. 		/* wakeup doesn't rouse victims of temporary sleep */ 929. 		if (sleep_monst(mon, rnd(12), POTION_CLASS)) { 930. 		    pline("%s falls asleep.", Monnam(mon)); 931. 		    slept_monst(mon); 932. 		}  933.  		break; 934. 	case POT_PARALYSIS: 935. 		if (mon->mcanmove) { 936. 			mon->mcanmove = 0; 937. 			/* really should be rnd(5) for consistency with players 938. 			 * breathing potions, but...  939. */ 940.  			mon->mfrozen = rnd(25); 941. 		}  942.  		break; 943. 	case POT_SPEED: 944. 		angermon = FALSE; 945. 		mon_adjust_speed(mon, 1); 946. 		break; 947. 	case POT_BLINDNESS: 948. 		if(haseyes(mon->data)) { 949. 		    register int btmp = 64 + rn2(32) + 950. 			rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL); 951. 		    btmp += mon->mblinded; 952. 		    mon->mblinded = min(btmp,127); 953. 		    mon->mcansee = 0; 954. 		}  955.  		break; 956. 	case POT_WATER: 957. 		if (is_undead(mon->data) || is_demon(mon->data) ||  958.  			is_were(mon->data)) { 959. 		    if (obj->blessed) { 960. 			pline("%s shrieks in pain!", Monnam(mon)); 961. 			mon->mhp -= d(2,6); 962. 			if (mon->mhp < 1) killed(mon); 963. 			else if (is_were(mon->data) && !is_human(mon->data)) 964. 			    new_were(mon);	/* revert to human */ 965. 		    } else if (obj->cursed) { 966. 			if (canseemon(mon)) 967. 			    pline("%s looks healthier.", Monnam(mon)); 968. 			mon->mhp += d(2,6); 969. 			if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax; 970. 			if (is_were(mon->data) && is_human(mon->data) &&  971.  				!Protection_from_shape_changers) 972. 			    new_were(mon);	/* transform into beast */ 973. 		    }  974.  		} else if(mon->data == &mons[PM_GREMLIN]) { 975. 		    (void)split_mon(mon, (struct monst *)0); 976. 		}  977.  		break; 978. 	case POT_OIL: 979. 		if (obj->lamplit) 980. 			splatter_burning_oil(mon->mx, mon->my); 981. 		break; 982. 	case POT_ACID: 983. 		if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) { 984. 		    pline("%s shrieks in pain!", Monnam(mon)); 985. 		    mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8); 986. 		    if (mon->mhp < 1) killed(mon); 987. 		}  988.  		break; 989. 	case POT_POLYMORPH: 990. 		(void) bhitm(mon, obj); 991. 		break; 992. /*  993.  	case POT_GAIN_LEVEL: 994. 	case POT_LEVITATION: 995. 	case POT_FRUIT_JUICE: 996. 	case POT_MONSTER_DETECTION: 997. 	case POT_OBJECT_DETECTION: 998. 		break; 999. */  1000. 	}  1001. 	if (angermon) 1002. 	   wakeup(mon); 1003. 	else 1004. 	   mon->msleeping = 0; 1005.    }  1006.  1007. 	/* Note: potionbreathe does its own docall */ 1008. 	if (distance==0 || ((distance < 3) && rn2(5))) 1009. 		potionbreathe(obj); 1010. 	else if (obj->dknown && !objects[obj->otyp].oc_name_known && 1011. 		   !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my)) 1012. 		docall(obj); 1013. 	if(*u.ushops && obj->unpaid) { 1014. 	       register struct monst *shkp = 1015. 			shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE)); 1016. 1017. 		if(!shkp) 1018. 		   obj->unpaid = 0; 1019. 		else { 1020. 		   (void)stolen_value(obj, u.ux, u.uy,  1021. 				 (boolean)shkp->mpeaceful, FALSE); 1022. 		   subfrombill(obj, shkp); 1023. 		} 1024. 	}  1025. 	obfree(obj, (struct obj *)0); 1026. } 1027.  1028. void 1029. potionbreathe(obj) 1030. register struct obj *obj; 1031. { 1032. 	register int i, ii, isdone, kn = 0; 1033. 1034. 	switch(obj->otyp) { 1035. 	case POT_RESTORE_ABILITY: 1036. 	case POT_GAIN_ABILITY: 1037. 		if(obj->cursed) { 1038. 		   pline("Ulch!  That potion smells terrible!"); 1039. 		   break; 1040. 		} else { 1041. 		   i = rn2(A_MAX);		/* start at a random point */ 1042. 		   for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) { 1043. 			if(ABASE(i) < AMAX(i)) { 1044. 			   ABASE(i)++; 1045. 			   /* only first found if not blessed */ 1046. 			   isdone = !(obj->blessed); 1047. 			   flags.botl = 1; 1048. 			} 1049. 			if(++i >= A_MAX) i = 0; 1050. 		   }  1051. 		}  1052. 		break; 1053. 	case POT_FULL_HEALING: 1054. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1055. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1056. 		/*FALL THROUGH*/ 1057. 	case POT_EXTRA_HEALING: 1058. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1059. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1060. 		/*FALL THROUGH*/ 1061. 	case POT_HEALING: 1062. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1; 1063. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1; 1064. 		exercise(A_CON, TRUE); 1065. 		break; 1066. 	case POT_SICKNESS: 1067. 		if (!Role_if(PM_HEALER)) { 1068. 			if (Upolyd) { 1069. 			   if (u.mh <= 5) u.mh = 1; else u.mh -= 5; 1070. 			} else { 1071. 			   if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5; 1072. 			} 1073. 			flags.botl = 1; 1074. 			exercise(A_CON, FALSE); 1075. 		} 1076. 		break; 1077. 	case POT_HALLUCINATION: 1078. 		You("have a momentary vision."); 1079. 		break; 1080. 	case POT_CONFUSION: 1081. 	case POT_BOOZE: 1082. 		if(!Confusion) 1083. 			You_feel("somewhat dizzy."); 1084. 		make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE); 1085. 		break; 1086. 	case POT_INVISIBILITY: 1087. 		if (!Blind && !Invis) { 1088. 		   kn++; 1089. 		   pline("For an instant you %s!",  1090. 			See_invisible ? "could see right through yourself"  1091. 			: "couldn't see yourself"); 1092. 		} 1093. 		break; 1094. 	case POT_PARALYSIS: 1095. 		kn++; 1096. 		if (!Free_action) { 1097. 		   pline("%s seems to be holding you.", Something); 1098. 		   nomul(-rnd(5)); 1099. 		   nomovemsg = You_can_move_again; 1100. 		   exercise(A_DEX, FALSE); 1101. 		} else You("stiffen momentarily."); 1102. 		break; 1103. 	case POT_SLEEPING: 1104. 		You("yawn."); 1105. 		break; 1106. 	case POT_SPEED: 1107. 		if (!Fast) Your("knees seem more flexible now."); 1108. 		incr_itimeout(&HFast, rnd(5)); 1109. 		exercise(A_DEX, TRUE); 1110. 		break; 1111. 	case POT_BLINDNESS: 1112. 		if (!Blind && !u.usleep) { 1113. 		   kn++; 1114. 		   pline("It suddenly gets dark."); 1115. 		} 1116. 		make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE); 1117. 		break; 1118. 	case POT_WATER: 1119. 		if(u.umonnum == PM_GREMLIN) { 1120. 		   (void)split_mon(&youmonst, (struct monst *)0); 1121. 		} else if (u.ulycn >= LOW_PM) { 1122. 		   /* vapor from [un]holy water will trigger 1123. 		      transformation but won't cure lycanthropy */ 1124. 		   if (obj->blessed && youmonst.data == &mons[u.ulycn]) 1125. 			you_unwere(FALSE); 1126. 		   else if (obj->cursed && !Upolyd) 1127. 			you_were; 1128. 		} 1129. 	case POT_ACID: 1130. 	case POT_POLYMORPH: 1131. 		exercise(A_CON, FALSE); 1132. 		break; 1133. /* 1134. 	case POT_GAIN_LEVEL: 1135. 	case POT_LEVITATION: 1136. 	case POT_FRUIT_JUICE: 1137. 	case POT_MONSTER_DETECTION: 1138. 	case POT_OBJECT_DETECTION: 1139. 	case POT_OIL: 1140. 		break; 1141. */ 1142. 	}  1143. 	/* note: no obfree */ 1144. 	if (obj->dknown) 1145. 	   if (kn) 1146. 		makeknown(obj->otyp); 1147. 	   else if (!objects[obj->otyp].oc_name_known &&  1148. 						!objects[obj->otyp].oc_uname) 1149. 		docall(obj); 1150. } 1151.  1152. STATIC_OVL short 1153. mixtype(o1, o2) 1154. register struct obj *o1, *o2; 1155. /* returns the potion type when o1 is dipped in o2 */ 1156. { 1157. 	/* cut down on the number of cases below */ 1158. 	if (o1->oclass == POTION_CLASS && 1159. 	    (o2->otyp == POT_GAIN_LEVEL || 1160. 	    o2->otyp == POT_GAIN_ENERGY || 1161. 	    o2->otyp == POT_HEALING || 1162. 	    o2->otyp == POT_EXTRA_HEALING || 1163. 	    o2->otyp == POT_FULL_HEALING || 1164. 	    o2->otyp == POT_ENLIGHTENMENT || 1165. 	    o2->otyp == POT_FRUIT_JUICE)) { 1166. 		struct obj *swp; 1167. 1168. 		swp = o1; o1 = o2; o2 = swp; 1169. 	} 1170.  1171. 	switch (o1->otyp) { 1172. 		case POT_HEALING: 1173. 			switch (o2->otyp) { 1174. 			   case POT_SPEED: 1175. 			   case POT_GAIN_LEVEL: 1176. 			   case POT_GAIN_ENERGY: 1177. 				return POT_EXTRA_HEALING; 1178. 			} 1179. 		case POT_EXTRA_HEALING: 1180. 			switch (o2->otyp) { 1181. 			   case POT_GAIN_LEVEL: 1182. 			   case POT_GAIN_ENERGY: 1183. 				return POT_FULL_HEALING; 1184. 			} 1185. 		case POT_FULL_HEALING: 1186. 			switch (o2->otyp) { 1187. 			   case POT_GAIN_LEVEL: 1188. 			   case POT_GAIN_ENERGY: 1189. 				return POT_GAIN_ABILITY; 1190. 			} 1191. 		case UNICORN_HORN: 1192. 			switch (o2->otyp) { 1193. 			   case POT_SICKNESS: 1194. 				return POT_FRUIT_JUICE; 1195. 			   case POT_HALLUCINATION: 1196. 			   case POT_BLINDNESS: 1197. 			   case POT_CONFUSION: 1198. 				return POT_WATER; 1199. 			} 1200. 			break; 1201. 		case AMETHYST:		/* "a-methyst" == "not intoxicated" */ 1202. 			if (o2->otyp == POT_BOOZE) 1203. 			   return POT_FRUIT_JUICE; 1204. 			break; 1205. 		case POT_GAIN_LEVEL: 1206. 		case POT_GAIN_ENERGY: 1207. 			switch (o2->otyp) { 1208. 			   case POT_CONFUSION: 1209. 				return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT); 1210. 			   case POT_HEALING: 1211. 				return POT_EXTRA_HEALING; 1212. 			   case POT_EXTRA_HEALING: 1213. 				return POT_FULL_HEALING; 1214. 			   case POT_FULL_HEALING: 1215. 				return POT_GAIN_ABILITY; 1216. 			   case POT_FRUIT_JUICE: 1217. 				return POT_SEE_INVISIBLE; 1218. 			   case POT_BOOZE: 1219. 				return POT_HALLUCINATION; 1220. 			} 1221. 			break; 1222. 		case POT_FRUIT_JUICE: 1223. 			switch (o2->otyp) { 1224. 			   case POT_SICKNESS: 1225. 				return POT_SICKNESS; 1226. 			   case POT_SPEED: 1227. 				return POT_BOOZE; 1228. 			   case POT_GAIN_LEVEL: 1229. 			   case POT_GAIN_ENERGY: 1230. 				return POT_SEE_INVISIBLE; 1231. 			} 1232. 			break; 1233. 		case POT_ENLIGHTENMENT: 1234. 			switch (o2->otyp) { 1235. 			   case POT_LEVITATION: 1236. 				if (rn2(3)) return POT_GAIN_LEVEL; 1237. 				break; 1238. 			   case POT_FRUIT_JUICE: 1239. 				return POT_BOOZE; 1240. 			   case POT_BOOZE: 1241. 				return POT_CONFUSION; 1242. 			} 1243. 			break; 1244. 	} 1245.  1246. 	return 0; 1247. } 1248.  1249.  1250. boolean 1251. get_wet(obj) 1252. register struct obj *obj; 1253. /* returns TRUE if something happened (potion should be used up) */ 1254. { 1255. 	char Your_buf[BUFSZ]; 1256. 1257. 	if (snuff_lit(obj)) return(TRUE); 1258. 1259. 	if (obj->greased) { 1260. 		grease_protect(obj,(char *)0,FALSE,&youmonst); 1261. 		return(FALSE); 1262. 	} 1263. 	(void) Shk_Your(Your_buf, obj); 1264. 	/* (Rusting and diluting unpaid shop goods ought to be charged for.) */ 1265. 	switch (obj->oclass) { 1266. 	   case WEAPON_CLASS: 1267. 		if (!obj->oerodeproof && is_rustprone(obj) && 1268. 		    (obj->oeroded < MAX_ERODE) && !rn2(10)) { 1269. 			pline("%s %s some%s.", 1270. 			      Your_buf, aobjnam(obj, "rust"),  1271. 			      obj->oeroded ? " more" : "what"); 1272. 			obj->oeroded++; 1273. 			return TRUE; 1274. 		} else break; 1275. 	   case POTION_CLASS: 1276. 		if (obj->otyp == POT_WATER) return FALSE; 1277. 		/* KMH -- Water into acid causes an explosion */ 1278. 		if (obj->otyp == POT_ACID) { 1279. 			pline("It boils vigorously!"); 1280. 			losehp(rnd(10), "elementary chemistry", KILLED_BY); 1281. 			makeknown(obj->otyp); 1282. 			return (TRUE); 1283. 		} 1284. 		pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"),  1285. 		      obj->odiluted ? " further" : ""); 1286. 		if (obj->odiluted) { 1287. 			obj->odiluted = 0; 1288. #ifdef UNIXPC 1289. 			obj->blessed = FALSE; 1290. 			obj->cursed = FALSE; 1291. #else 1292. 			obj->blessed = obj->cursed = FALSE; 1293. #endif 1294. 			obj->otyp = POT_WATER; 1295. 		} else obj->odiluted++; 1296. 		return TRUE; 1297. 	   case SCROLL_CLASS: 1298. 		if (obj->otyp != SCR_BLANK_PAPER 1299. #ifdef MAIL  1300. 		    && obj->otyp != SCR_MAIL  1301. #endif  1302. 		    ) { 1303. 			if (!Blind) { 1304. 				boolean oq1 = obj->quan == 1L; 1305. 				pline_The("scroll%s fade%s.", 1306. 					oq1 ? "" : "s",  1307. 					oq1 ? "s" : ""); 1308. 			} 1309. 			if(obj->unpaid) { 1310. 			   subfrombill(obj, shop_keeper(*u.ushops)); 1311. 			   You("erase it, you pay for it."); 1312. 			   bill_dummy_object(obj); 1313. 			} 1314. 			obj->otyp = SCR_BLANK_PAPER; 1315. 			obj->spe = 0; 1316. 			return TRUE; 1317. 		} else break; 1318. 	   case SPBOOK_CLASS: 1319. 		if (obj->otyp != SPE_BLANK_PAPER) { 1320. 1321. 			if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { 1322. 	pline("%s suddenly heats up; steam rises and it remains dry.", 1323. 				The(xname(obj))); 1324. 			} else { 1325. 			   if (!Blind) { 1326. 				   boolean oq1 = obj->quan == 1L; 1327. 				   pline_The("spellbook%s fade%s.",  1328. 					oq1 ? "" : "s", oq1 ? "s" : ""); 1329. 			   }  1330. 			    if(obj->unpaid) { 1331. 			       subfrombill(obj, shop_keeper(*u.ushops)); 1332. 			       You("erase it, you pay for it."); 1333. 			       bill_dummy_object(obj); 1334. 			   }  1335. 			    obj->otyp = SPE_BLANK_PAPER; 1336. 			} 1337. 			return TRUE; 1338. 		} 1339. 	}  1340. 	pline("%s %s wet.", Your_buf, aobjnam(obj,"get")); 1341. 	return FALSE; 1342. } 1343.  1344. int 1345. dodip 1346. { 1347. 	register struct obj *potion, *obj; 1348. 	const char *tmp; 1349. 	uchar here; 1350. 	char allowall[2]; 1351. 	short mixture; 1352. 	char qbuf[QBUFSZ], Your_buf[BUFSZ]; 1353. 1354. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0'; 1355. 	if(!(obj = getobj(allowall, "dip"))) 1356. 		return(0); 1357. 1358. 	here = levl[u.ux][u.uy].typ; 1359. 	/* Is there a fountain to dip into here? */ 1360. 	if (IS_FOUNTAIN(here)) { 1361. 		if(yn("Dip it into the fountain?") == 'y') { 1362. 			dipfountain(obj); 1363. 			return(1); 1364. 		} 1365. 	} else if (is_pool(u.ux,u.uy)) { 1366. 		tmp = (here == POOL) ? "pool" : "moat"; 1367. 		Sprintf(qbuf, "Dip it into the %s?", tmp); 1368. 		if (yn(qbuf) == 'y') { 1369. 		   if (Levitation) 1370. 			floating_above(tmp); 1371. 		   else { 1372. 			(void) get_wet(obj); 1373. 			if (obj->otyp == POT_ACID) useup(obj); 1374. 		   }  1375. 		    return 1; 1376. 		} 1377. 	}  1378.  1379. 	if(!(potion = getobj(beverages, "dip into"))) 1380. 		return(0); 1381. 	if (potion == obj && potion->quan == 1L) { 1382. 		pline("That is a potion bottle, not a Klein bottle!"); 1383. 		return 0; 1384. 	} 1385. 	if(potion->otyp == POT_WATER) { 1386. 		boolean useeit = !Blind; 1387. 		if (useeit) (void) Shk_Your(Your_buf, obj); 1388. 		if (potion->blessed) { 1389. 			if (obj->cursed) { 1390. 				if (useeit) 1391. 				   pline("%s %s %s.",  1392. 					  Your_buf,  1393. 					  aobjnam(obj, "softly glow"),  1394. 					  hcolor(amber)); 1395. 				uncurse(obj); 1396. 				obj->bknown=1; 1397. 	poof: 1398. 				if(!(objects[potion->otyp].oc_name_known) && 1399. 				   !(objects[potion->otyp].oc_uname)) 1400. 					docall(potion); 1401. 				useup(potion); 1402. 				return(1); 1403. 			} else if(!obj->blessed) { 1404. 				if (useeit) { 1405. 				   tmp = hcolor(light_blue); 1406. 				   pline("%s %s with a%s %s aura.",  1407. 					  Your_buf,  1408. 					  aobjnam(obj, "softly glow"),  1409. 					  index(vowels, *tmp) ? "n" : "", tmp); 1410. 				} 1411. 				bless(obj); 1412. 				obj->bknown=1; 1413. 				goto poof; 1414. 			} 1415. 		} else if (potion->cursed) { 1416. 			if (obj->blessed) { 1417. 				if (useeit) 1418. 				   pline("%s %s %s.",  1419. 					  Your_buf,  1420. 					  aobjnam(obj, "glow"),  1421. 					  hcolor((const char *)"brown")); 1422. 				unbless(obj); 1423. 				obj->bknown=1; 1424. 				goto poof; 1425. 			} else if(!obj->cursed) { 1426. 				if (useeit) { 1427. 				   tmp = hcolor(Black); 1428. 				   pline("%s %s with a%s %s aura.",  1429. 					  Your_buf,  1430. 					  aobjnam(obj, "glow"),  1431. 					  index(vowels, *tmp) ? "n" : "", tmp); 1432. 				} 1433. 				curse(obj); 1434. 				obj->bknown=1; 1435. 				goto poof; 1436. 			} 1437. 		} else 1438. 			if (get_wet(obj)) 1439. 			   goto poof; 1440. 	} else if ((obj->otyp == POT_POLYMORPH || potion->otyp == POT_POLYMORPH) 1441. 			&& obj->otyp != potion->otyp) { 1442. 	   if (obj->oclass != POTION_CLASS ||  1443. 	    	(obj->otyp == POT_POLYMORPH && 1444. 		 objects[potion->otyp].oc_name_known) || 1445. 	    	(potion->otyp == POT_POLYMORPH && 1446. 		 objects[obj->otyp].oc_name_known)) 1447. 	   	makeknown(POT_POLYMORPH); 1448.  1449. 	    /* KMH, conduct */ 1450. 	   u.uconduct.polypiles++; 1451.  1452. 	    poly_obj(obj, STRANGE_OBJECT); 1453. 	   useup(potion); 1454. 	   return(1); 1455. 	} else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) { 1456. 		/* Mixing potions is dangerous... */ 1457. 		pline_The("potions mix..."); 1458. 		/* KMH, balance patch -- acid is particularly unstable */ 1459. 		if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) { 1460. 			pline("BOOM! They explode!"); 1461. 			exercise(A_STR, FALSE); 1462. 			potionbreathe(obj); 1463. 			useup(obj); 1464. 			useup(potion); 1465. 			losehp(rnd(10), "alchemic blast", KILLED_BY_AN); 1466. 			return(1); 1467. 		} 1468.  1469. 		obj->blessed = obj->cursed = obj->bknown = 0; 1470. 		if (Blind || Hallucination) obj->dknown = 0; 1471. 1472. 		if ((mixture = mixtype(obj, potion)) != 0) { 1473. 			obj->otyp = mixture; 1474. 		} else { 1475. 		   switch (obj->odiluted ? 1 : rnd(8)) { 1476. 			case 1: 1477. 				obj->otyp = POT_WATER; 1478. 				break; 1479. 			case 2: 1480. 			case 3: 1481. 				obj->otyp = POT_SICKNESS; 1482. 				break; 1483. 			case 4: 1484. 				{ 1485. 				  struct obj *otmp; 1486. 				 otmp = mkobj(POTION_CLASS,FALSE); 1487. 				 obj->otyp = otmp->otyp; 1488. 				 obfree(otmp, (struct obj *)0); 1489. 				} 1490. 				break; 1491. 			default: 1492. 				if (!Blind) 1493. 			 pline_The("mixture glows brightly and evaporates."); 1494. 				useup(obj); 1495. 				useup(potion); 1496. 				return(1); 1497. 		   }  1498. 		}  1499.  1500.  1501. 		obj->odiluted = (obj->otyp != POT_WATER); 1502. 1503. 		if (obj->otyp == POT_WATER && !Hallucination) { 1504. 			pline_The("mixture bubbles%s.", 1505. 				Blind ? "" : ", then clears"); 1506. 		} else if (!Blind) { 1507. 			pline_The("mixture looks %s.", 1508. 				hcolor(OBJ_DESCR(objects[obj->otyp]))); 1509. 		} 1510.  1511. 		useup(potion); 1512. 		return(1); 1513. 	} 1514.  1515. #ifdef INVISIBLE_OBJECTS 1516. 	if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) { 1517. 		obj->oinvis = TRUE; 1518. 		if (!Blind) { 1519. 		   if (!See_invisible) pline("Where did %s go?",  1520. 		    		the(xname(obj))); 1521. 		   else pline("You notice a little haziness around %s.",  1522. 		    		the(xname(obj))); 1523. 		} 1524. 		goto poof; 1525. 	} else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) { 1526. 		obj->oinvis = FALSE; 1527. 		if (!Blind) { 1528. 		   if (!See_invisible) pline("So that's where %s went!",  1529. 		    		the(xname(obj))); 1530. 		   else pline("The haziness around %s disappears.",  1531. 		    		the(xname(obj))); 1532. 		} 1533. 		goto poof; 1534. 	} 1535. #endif 1536. 1537. 	if(is_poisonable(obj)) { 1538. 	   if(potion->otyp == POT_SICKNESS && !obj->opoisoned) { 1539. 		char buf[BUFSZ]; 1540. 		Strcpy(buf, The(xname(potion))); 1541. 		pline("%s form%s a coating on %s.", 1542. 			buf, potion->quan == 1L ? "s" : "", the(xname(obj))); 1543. 		obj->opoisoned = TRUE; 1544. 		goto poof; 1545. 	   } else if(obj->opoisoned &&  1546. 		      (potion->otyp == POT_HEALING || 1547. 		      potion->otyp == POT_EXTRA_HEALING || 1548. 		      potion->otyp == POT_FULL_HEALING)) { 1549. 		pline("A coating wears off %s.", the(xname(obj))); 1550. 		obj->opoisoned = 0; 1551. 		goto poof; 1552. 	   }  1553. 	}  1554.  1555. 	if (potion->otyp == POT_OIL &&  1556. 		(obj->oclass == WEAPON_CLASS || is_weptool(obj))) { 1557. 	   boolean wisx = FALSE; 1558. 	   if (potion->lamplit) {	/* burning */ 1559. 		int omat = objects[obj->otyp].oc_material; 1560. 		if (obj->oerodeproof || obj_resists(obj, 5, 95) || 1561. 			/* `METAL' should not be confused with is_metallic */  1562. 			omat == METAL || omat == MITHRIL || omat == BONE) { 1563. 		   pline("%s seem%s to burn for a moment.",  1564. 			  Yname2(obj),  1565. 			  (obj->quan > 1L) ? "" : "s"); 1566. 		} else { 1567. 		   if (omat == PLASTIC) obj->oeroded = MAX_ERODE; 1568. 		   pline_The("burning oil %s %s.",  1569. 			    obj->oeroded == MAX_ERODE ? "destroys" : "damages",  1570. 			    yname(obj)); 1571. 		   if (obj->oeroded == MAX_ERODE) { 1572. 			obj_extract_self(obj); 1573. 			obfree(obj, (struct obj *)0); 1574. 			obj = (struct obj *) 0; 1575. 		   } else { 1576. 			/* should check for and do something about 1577. 			  damaging unpaid shop goods here */ 1578. 			obj->oeroded++; 1579. 		   }  1580. 		}  1581. 	    } else if (potion->cursed || !is_metallic(obj) ||  1582. 		    /* arrows,&c are classed as metallic due to arrowhead  1583. 		       material, but dipping in oil shouldn't repair them */  1584. 		    is_ammo(obj)) { 1585. 		pline_The("potion spills and covers your %s with oil.", 1586. 			  makeplural(body_part(FINGER))); 1587. 		incr_itimeout(&Glib, d(2,10)); 1588. 	   /* oil removes rust and corrosion, but doesn't unburn */ 1589. 	   } else if (!is_flammable(obj) ||  1590. 					(!obj->oeroded && !obj->oeroded2)) { 1591. 		/* uses up potion, doesn't set obj->greased */ 1592. 		pline("%s gleam%s with an oily sheen.", 1593. 		      Yname2(obj),  1594. 		      (obj->quan > 1L) ? "" : "s"); 1595. 	   } else { 1596. 		pline("%s %s less %s.", 1597. 		      Yname2(obj),  1598. 		      (obj->quan > 1L) ? "are" : "is",  1599. 		      (obj->oeroded && obj->oeroded2) ? "corroded and rusty" :  1600. 			obj->oeroded ? "rusty" : "corroded"); 1601. 		if (obj->oeroded > 0) obj->oeroded--; 1602. 		if (obj->oeroded2 > 0) obj->oeroded2--; 1603. 		wisx = TRUE; 1604. 	   }  1605. 	    exercise(A_WIS, wisx); 1606. 	   makeknown(potion->otyp); 1607. 	   useup(potion); 1608. 	   return 1; 1609. 	} 1610.  1611. 	/* Allow filling of MAGIC_LAMPs to prevent identification by player */ 1612. 	if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) && 1613. 	   (potion->otyp == POT_OIL)) { 1614. 	   /* Turn off engine before fueling, turn off fuel too :-)  */  1615. 	    if (obj->lamplit || potion->lamplit) {  1616. 		useup(potion);  1617. 		explode(u.ux, u.uy, 11, d(6,6), 0);  1618. 		exercise(A_WIS, FALSE);  1619. 		return 1;  1620. 	    }  1621. 	    /* Adding oil to an empty magic lamp renders it into an oil lamp */  1622. 	    if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {  1623. 		obj->otyp = OIL_LAMP;  1624. 		obj->age = 0;  1625. 	    }  1626. 	    if (obj->age > 1000L) {  1627. 		pline("%s is full.", Yname2(obj));  1628. 	    } else {  1629. 		You("fill %s with oil.", yname(obj));  1630. 		check_unpaid(potion);	/* surcharge for using unpaid item */  1631. 		obj->age += 2*potion->age;	/* burns more efficiently */  1632. 		if (obj->age > 1500L) obj->age = 1500L;  1633. 		useup(potion);  1634. 		exercise(A_WIS, TRUE);  1635. 	    }  1636. 	    obj->spe = 1;  1637. update_inventory; 1638. 	   return 1; 1639. 	} 1640.  1641. 	if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) &&  1642. 	    (mixture = mixtype(obj, potion)) != 0) { 1643. 		/* with multiple merged potions, we should split off one and 1644. 		  just clear it, but clearing them all together is easier */ 1645. 		boolean more_than_one = potion->quan > 1L; 1646. 		potion->otyp = mixture; 1647. 		potion->blessed = 0; 1648. 		if (mixture == POT_WATER) 1649. 		   potion->cursed = potion->odiluted = 0; 1650. 		else 1651. 		   potion->cursed = obj->cursed;  /* odiluted left as-is */ 1652. 		if (Blind) 1653. 			potion->dknown = FALSE; 1654. 		else { 1655. 			if (mixture == POT_WATER && 1656. #ifdef DCC30_BUG  1657. 			    (potion->dknown = !Hallucination, 1658. 			    potion->dknown != 0)) 1659. #else 1660. 			   (potion->dknown = !Hallucination) != 0)  1661. #endif  1662. 				pline_The("potion%s clear%s.", 1663. 					more_than_one ? "s" : "", 1664. 					more_than_one ? "" : "s"); 1665. 			else  1666. 				pline_The("potion%s turn%s %s.", 1667. 					more_than_one ? "s" : "", 1668. 					more_than_one ? "" : "s", 1669. 					hcolor(OBJ_DESCR(objects[mixture]))); 1670. 		}  1671. 		return(1);  1672. 	}  1673.  1674. 	pline("Interesting...");  1675. 	return(1);  1676. }  1677.  1678.  1679. void  1680. djinni_from_bottle(obj)  1681. register struct obj *obj;  1682. {  1683. 	struct monst *mtmp;  1684. 	int chance;  1685.  1686. 	if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))){  1687. 		pline("It turns out to be empty.");  1688. 		return;  1689. 	}  1690.  1691. 	if (!Blind) {  1692. 		pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));  1693. 		pline("%s speaks.", Monnam(mtmp));  1694. 	} else {  1695. 		You("smell acrid fumes.");  1696. 		pline("%s speaks.", Something);  1697. 	}  1698.  1699. 	chance = rn2(5);  1700. 	if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;  1701. 	else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;  1702. 	/* 0,1,2,3,4:  b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */ 1703. 1704. 	switch (chance) { 1705. 	case 0 : verbalize("I am in your debt. I will grant one wish!"); 1706. 		makewish; 1707. 		mongone(mtmp); 1708. 		break; 1709. 	case 1 : verbalize("Thank you for freeing me!"); 1710. 		(void) tamedog(mtmp, (struct obj *)0); 1711. 		break; 1712. 	case 2 : verbalize("You freed me!"); 1713. 		mtmp->mpeaceful = TRUE; 1714. 		set_malign(mtmp); 1715. 		break; 1716. 	case 3 : verbalize("It is about time!"); 1717. 		pline("%s vanishes.", Monnam(mtmp)); 1718. 		mongone(mtmp); 1719. 		break; 1720. 	default: verbalize("You disturbed me, fool!"); 1721. 		break; 1722. 	} 1723. }  1724.  1725. /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger); 1726.   hit points are cut in half (odd HP stays with original) */ 1727. struct monst * 1728. split_mon(mon, mtmp) 1729. struct monst *mon,	/* monster being split */ 1730. 	    *mtmp;	/* optional attacker whose heat triggered it */ 1731. { 1732. 	struct monst *mtmp2; 1733. 	char reason[BUFSZ]; 1734. 1735. 	reason[0] = '\0'; 1736. 	if (mtmp) Sprintf(reason, " from %s heat", 1737. 			  (mtmp == &youmonst) ? (const char *)"your" :  1738. 			      (const char *)s_suffix(mon_nam(mtmp))); 1739. 1740. 	if (mon == &youmonst) { 1741. 	   mtmp2 = cloneu; 1742. 	   if (mtmp2) { 1743. 		mtmp2->mhpmax = u.mhmax / 2; 1744. 		u.mhmax -= mtmp2->mhpmax; 1745. 		flags.botl = 1; 1746. 		You("multiply%s!", reason); 1747. 	   }  1748. 	} else { 1749. 	   mtmp2 = clone_mon(mon); 1750. 	   if (mtmp2) { 1751. 		mtmp2->mhpmax = mon->mhpmax / 2; 1752. 		mon->mhpmax -= mtmp2->mhpmax; 1753. 		if (canspotmon(mon)) 1754. 		   pline("%s multiplies%s!", Monnam(mon), reason); 1755. 	   }  1756. 	}  1757. 	return mtmp2; 1758. } 1759.  1760. #endif /* OVLB */ 1761. 1762. /*potion.c*/