Source:Fountain.c

Below is the full text to src/fountain.c from NetHack 3.4.3. To link to a particular line, write [[fountain.c#line123 ]], for example. 1.   /*	SCCS Id: @(#)fountain.c	3.4	2003/03/23	*/ 2.   /*	Copyright Scott R. Turner, srt@ucla, 10/27/86 */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.

5.   /* Code for drinking from fountains. */ 6.     7.    #include "hack.h"  8. 9.   STATIC_DCL void NDECL(dowatersnakes); 10.  STATIC_DCL void NDECL(dowaterdemon); 11.  STATIC_DCL void NDECL(dowaternymph); 12.  STATIC_PTR void FDECL(gush, (int,int,genericptr_t)); 13.  STATIC_DCL void NDECL(dofindgem); 14.   15.   void 16.  floating_above(what) 17.  const char *what; 18.  {  19.       You("are floating high above the %s.", what); 20.  }  21.    22.   STATIC_OVL void 23.  dowatersnakes /* Fountain of snakes! */ 24.   {  25.       register int num = rn1(5,2); 26.      struct monst *mtmp; 27.   28.       if (!(mvitals[PM_WATER_MOCCASIN].mvflags & G_GONE)) { 29.  	if (!Blind) 30.  	    pline("An endless stream of %s pours forth!",  31.   		  Hallucination ? makeplural(rndmonnam) : "snakes"); 32.  	else 33.  	    You_hear("%s hissing!", something); 34.  	while(num-- > 0) 35.  	    if((mtmp = makemon(&mons[PM_WATER_MOCCASIN],  36.   			u.ux, u.uy, NO_MM_FLAGS)) && t_at(mtmp->mx, mtmp->my)) 37.  		(void) mintrap(mtmp); 38.      } else 39.  	pline_The("fountain bubbles furiously for a moment, then calms."); 40.  }  41.    42.   STATIC_OVL 43.  void 44.  dowaterdemon /* Water demon */ 45.  {  46.       register struct monst *mtmp; 47.   48.       if(!(mvitals[PM_WATER_DEMON].mvflags & G_GONE)) { 49.  	if((mtmp = makemon(&mons[PM_WATER_DEMON],u.ux,u.uy, NO_MM_FLAGS))) { 50.  	    if (!Blind) 51.  		You("unleash %s!", a_monnam(mtmp)); 52.  	    else 53.  		You_feel("the presence of evil."); 54.   55.   	/* Give those on low levels a (slightly) better chance of survival */ 56.  	    if (rnd(100) > (80 + level_difficulty)) { 57.  		pline("Grateful for %s release, %s grants you a wish!",  58.   		      mhis(mtmp), mhe(mtmp)); 59.  		makewish; 60.  		mongone(mtmp); 61.  	    } else if (t_at(mtmp->mx, mtmp->my)) 62.  		(void) mintrap(mtmp); 63.  	}  64.       } else 65.  	pline_The("fountain bubbles furiously for a moment, then calms."); 66.  }  67.    68.   STATIC_OVL void 69.  dowaternymph /* Water Nymph */ 70.  {  71.   	register struct monst *mtmp; 72.   73.   	if(!(mvitals[PM_WATER_NYMPH].mvflags & G_GONE) &&  74.   	   (mtmp = makemon(&mons[PM_WATER_NYMPH],u.ux,u.uy, NO_MM_FLAGS))) { 75.  		if (!Blind) 76.  		   You("attract %s!", a_monnam(mtmp)); 77.  		else 78.  		   You_hear("a seductive voice."); 79.  		mtmp->msleeping = 0; 80.  		if (t_at(mtmp->mx, mtmp->my)) 81.  		    (void) mintrap(mtmp); 82.  	} else 83.  		if (!Blind) 84.  		   pline("A large bubble rises to the surface and pops."); 85.  		else 86.  		   You_hear("a loud pop."); 87.  }  88.    89.   void 90.  dogushforth(drinking) /* Gushing forth along LOS from (u.ux, u.uy) */ 91.  int drinking; 92.  {  93.   	int madepool = 0; 94.   95.   	do_clear_area(u.ux, u.uy, 7, gush, (genericptr_t)&madepool); 96.  	if (!madepool) { 97.  	    if (drinking) 98.  		Your("thirst is quenched."); 99.  	    else 100. 		pline("Water sprays all over you."); 101. 	}  102.  }  103.   104.  STATIC_PTR void 105. gush(x, y, poolcnt) 106. int x, y;  107. genericptr_t poolcnt; 108. {  109.  	register struct monst *mtmp; 110. 	register struct trap *ttmp; 111.  112.  	if (((x+y)%2) || (x == u.ux && y == u.uy) ||  113.  	    (rn2(1 + distmin(u.ux, u.uy, x, y)))  ||  114.  	    (levl[x][y].typ != ROOM) ||  115.  	    (sobj_at(BOULDER, x, y)) || nexttodoor(x, y)) 116. 		return; 117.  118.  	if ((ttmp = t_at(x, y)) != 0 && !delfloortrap(ttmp)) 119. 		return; 120.  121.  	if (!((*(int *)poolcnt)++)) 122. 	    pline("Water gushes forth from the overflowing fountain!"); 123.  124.  	/* Put a pool at x, y */ 125. 	levl[x][y].typ = POOL; 126. 	/* No kelp! */ 127.  	del_engr_at(x, y); 128. 	water_damage(level.objects[x][y], FALSE, TRUE); 129.  130.  	if ((mtmp = m_at(x, y)) != 0) 131. 		(void) minliquid(mtmp); 132. 	else 133. 		newsym(x,y); 134. }  135.   136.  STATIC_OVL void 137. dofindgem /* Find a gem in the sparkling waters. */ 138.  {  139.  	if (!Blind) You("spot a gem in the sparkling waters!"); 140. 	else You_feel("a gem here!"); 141. 	(void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE-1),  142.  			 u.ux, u.uy, FALSE, FALSE); 143. 	SET_FOUNTAIN_LOOTED(u.ux,u.uy); 144. 	newsym(u.ux, u.uy); 145. 	exercise(A_WIS, TRUE);			/* a discovery! */ 146.  }  147.   148.  void 149. dryup(x, y, isyou) 150. xchar x, y;  151. boolean isyou; 152. {  153.  	if (IS_FOUNTAIN(levl[x][y].typ) &&  154.  	    (!rn2(3) || FOUNTAIN_IS_WARNED(x,y))) { 155. 		if(isyou && in_town(x, y) && !FOUNTAIN_IS_WARNED(x,y)) { 156. 			struct monst *mtmp; 157. 			SET_FOUNTAIN_WARNED(x,y); 158. 			/* Warn about future fountain use. */ 159.  			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 160. 			    if (DEADMONSTER(mtmp)) continue; 161. 			    if ((mtmp->data == &mons[PM_WATCHMAN] || 162. 				mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&  163.  			       couldsee(mtmp->mx, mtmp->my) &&  164.  			       mtmp->mpeaceful) { 165. 				pline("%s yells:", Amonnam(mtmp)); 166. 				verbalize("Hey, stop using that fountain!"); 167. 				break; 168. 			    }  169.  			}  170.  			/* You can see or hear this effect */ 171. 			if(!mtmp) pline_The("flow reduces to a trickle."); 172. 			return; 173. 		}  174.  #ifdef WIZARD 175. 		if (isyou && wizard) { 176. 			if (yn("Dry up fountain?") == 'n') 177. 				return; 178. 		}  179.  #endif 180. 		/* replace the fountain with ordinary floor */ 181. 		levl[x][y].typ = ROOM; 182. 		levl[x][y].looted = 0; 183. 		levl[x][y].blessedftn = 0; 184. 		if (cansee(x,y)) pline_The("fountain dries up!"); 185. 		/* The location is seen if the hero/monster is invisible */ 186. 		/* or felt if the hero is blind. */ 187.  		newsym(x, y); 188. 		level.flags.nfountains--; 189. 		if(isyou && in_town(x, y)) 190. 		    (void) angry_guards(FALSE); 191. 	}  192.  }  193.   194.  void 195. drinkfountain 196. {  197.  	/* What happens when you drink from a fountain? */ 198.  	register boolean mgkftn = (levl[u.ux][u.uy].blessedftn == 1); 199. 	register int fate = rnd(30); 200.  201.  	if (Levitation) { 202. 		floating_above("fountain"); 203. 		return; 204. 	}  205.   206.  	if (mgkftn && u.uluck >= 0 && fate >= 10) { 207. 		int i, ii, littleluck = (u.uluck < 4); 208.  209.  		pline("Wow!  This makes you feel great!"); 210. 		/* blessed restore ability */ 211. 		for (ii = 0; ii < A_MAX; ii++) 212. 		    if (ABASE(ii) < AMAX(ii)) { 213. 			ABASE(ii) = AMAX(ii); 214. 			flags.botl = 1; 215. 		    }  216.  		/* gain ability, blessed if "natural" luck is high */ 217. 		i = rn2(A_MAX);		/* start at a random attribute */ 218. 		for (ii = 0; ii < A_MAX; ii++) { 219. 		    if (adjattrib(i, 1, littleluck ? -1 : 0) && littleluck) 220. 			break; 221. 		    if (++i >= A_MAX) i = 0; 222. 		}  223.  		display_nhwindow(WIN_MESSAGE, FALSE); 224. 		pline("A wisp of vapor escapes the fountain..."); 225. 		exercise(A_WIS, TRUE); 226. 		levl[u.ux][u.uy].blessedftn = 0; 227. 		return; 228. 	}  229.   230.  	if (fate < 10) { 231. 		pline_The("cool draught refreshes you."); 232. 		u.uhunger += rnd(10); /* don't choke on water */ 233. 		newuhs(FALSE); 234. 		if(mgkftn) return; 235. 	} else { 236. 	    switch (fate) { 237.  238.  		case 19: /* Self-knowledge */ 239.  240.  			You_feel("self-knowledgeable..."); 241. 			display_nhwindow(WIN_MESSAGE, FALSE); 242. 			enlightenment(0); 243. 			exercise(A_WIS, TRUE); 244. 			pline_The("feeling subsides."); 245. 			break; 246.  247.  		case 20: /* Foul water */ 248.  249.  			pline_The("water is foul!  You gag and vomit."); 250. 			morehungry(rn1(20, 11)); 251. 			vomit; 252. 			break; 253.  254.  		case 21: /* Poisonous */ 255.  256.  			pline_The("water is contaminated!"); 257. 			if (Poison_resistance) { 258. 			   pline(  259.  			      "Perhaps it is runoff from the nearby %s farm.",  260.  				 fruitname(FALSE)); 261. 			   losehp(rnd(4),"unrefrigerated sip of juice",  262.  				KILLED_BY_AN); 263. 			   break; 264. 			}  265.  			losestr(rn1(4,3)); 266. 			losehp(rnd(10),"contaminated water", KILLED_BY); 267. 			exercise(A_CON, FALSE); 268. 			break; 269.  270.  		case 22: /* Fountain of snakes! */ 271.   272.  			dowatersnakes; 273. 			break; 274.  275.  		case 23: /* Water demon */ 276. 			dowaterdemon; 277. 			break; 278.  279.  		case 24: /* Curse an item */ { 280. 			register struct obj *obj; 281.  282.  			pline("This water's no good!"); 283. 			morehungry(rn1(20, 11)); 284. 			exercise(A_CON, FALSE); 285. 			for(obj = invent; obj ; obj = obj->nobj) 286. 				if (!rn2(5))	curse(obj); 287. 			break; 288. 			}  289.   290.  		case 25: /* See invisible */ 291.  292.  			if (Blind) { 293. 			    if (Invisible) { 294. 				You("feel transparent."); 295. 			    } else { 296. 			    	You("feel very self-conscious."); 297. 			    	pline("Then it passes."); 298. 			    }  299.  			} else { 300. 			   You("see an image of someone stalking you."); 301. 			   pline("But it disappears."); 302. 			}  303.  			HSee_invisible |= FROMOUTSIDE; 304. 			newsym(u.ux,u.uy); 305. 			exercise(A_WIS, TRUE); 306. 			break; 307.  308.  		case 26: /* See Monsters */ 309.  310.  			(void) monster_detect((struct obj *)0, 0); 311. 			exercise(A_WIS, TRUE); 312. 			break; 313.  314.  		case 27: /* Find a gem in the sparkling waters. */ 315.   316.  			if (!FOUNTAIN_IS_LOOTED(u.ux,u.uy)) { 317. 				dofindgem; 318. 				break; 319. 			}  320.   321.  		case 28: /* Water Nymph */ 322.  323.  			dowaternymph; 324. 			break; 325.  326.  		case 29: /* Scare */ { 327. 			register struct monst *mtmp; 328.  329.  			pline("This water gives you bad breath!"); 330. 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 331. 			    if(!DEADMONSTER(mtmp)) 332. 				monflee(mtmp, 0, FALSE, FALSE); 333. 			}  334.  			break; 335.  336.  		case 30: /* Gushing forth in this room */ 337.  338.  			dogushforth(TRUE); 339. 			break; 340.  341.  		default: 342.  343.  			pline("This tepid water is tasteless."); 344. 			break; 345. 	    }  346.  	}  347.  	dryup(u.ux, u.uy, TRUE); 348. }  349.   350.  void 351. dipfountain(obj) 352. register struct obj *obj; 353. {  354.  	if (Levitation) { 355. 		floating_above("fountain"); 356. 		return; 357. 	}  358.   359.  	/* Don't grant Excalibur when there's more than one object. */ 360.  	/* (quantity could be > 1 if merged daggers got polymorphed) */ 361. 	if (obj->otyp == LONG_SWORD && obj->quan == 1L  362.  	    && u.ulevel >= 5 && !rn2(6)  363.  	    && !obj->oartifact  364.  	    && !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) { 365.  366.  		if (u.ualign.type != A_LAWFUL) { 367. 			/* Ha! Trying to cheat her. */ 368.  			pline("A freezing mist rises from the water and envelopes the sword."); 369. 			pline_The("fountain disappears!"); 370. 			curse(obj); 371. 			if (obj->spe > -6 && !rn2(3)) obj->spe--; 372. 			obj->oerodeproof = FALSE; 373. 			exercise(A_WIS, FALSE); 374. 		} else { 375. 			/* The lady of the lake acts! - Eric Backus */ 376. 			/* Be *REAL* nice */ 377. 	  pline("From the murky depths, a hand reaches up to bless the sword."); 378. 			pline("As the hand retreats, the fountain disappears!"); 379. 			obj = oname(obj, artiname(ART_EXCALIBUR)); 380. 			discover_artifact(ART_EXCALIBUR); 381. 			bless(obj); 382. 			obj->oeroded = obj->oeroded2 = 0; 383. 			obj->oerodeproof = TRUE; 384. 			exercise(A_WIS, TRUE); 385. 		}  386.  		update_inventory; 387. 		levl[u.ux][u.uy].typ = ROOM; 388. 		levl[u.ux][u.uy].looted = 0; 389. 		newsym(u.ux, u.uy); 390. 		level.flags.nfountains--; 391. 		if(in_town(u.ux, u.uy)) 392. 		    (void) angry_guards(FALSE); 393. 		return; 394. 	} else if (get_wet(obj) && !rn2(2)) 395. 		return; 396.  397.  	/* Acid and water don't mix */ 398. 	if (obj->otyp == POT_ACID) { 399. 	    useup(obj); 400. 	    return; 401. 	}  402.   403.  	switch (rnd(30)) { 404. 		case 16: /* Curse the item */ 405. 			curse(obj); 406. 			break; 407. 		case 17: 408. 		case 18: 409. 		case 19: 410. 		case 20: /* Uncurse the item */ 411. 			if(obj->cursed) { 412. 			    if (!Blind) 413. 				pline_The("water glows for a moment."); 414. 			    uncurse(obj); 415. 			} else { 416. 			    pline("A feeling of loss comes over you."); 417. 			}  418.  			break; 419. 		case 21: /* Water Demon */ 420. 			dowaterdemon; 421. 			break; 422. 		case 22: /* Water Nymph */ 423. 			dowaternymph; 424. 			break; 425. 		case 23: /* an Endless Stream of Snakes */ 426. 			dowatersnakes; 427. 			break; 428. 		case 24: /* Find a gem */ 429. 			if (!FOUNTAIN_IS_LOOTED(u.ux,u.uy)) { 430. 				dofindgem; 431. 				break; 432. 			}  433.  		case 25: /* Water gushes forth */ 434. 			dogushforth(FALSE); 435. 			break; 436. 		case 26: /* Strange feeling */ 437. 			pline("A strange tingling runs up your %s.",  438.  							body_part(ARM)); 439. 			break; 440. 		case 27: /* Strange feeling */ 441. 			You_feel("a sudden chill."); 442. 			break; 443. 		case 28: /* Strange feeling */ 444. 			pline("An urge to take a bath overwhelms you."); 445. #ifndef GOLDOBJ 446. 			if (u.ugold > 10) { 447. 			    u.ugold -= somegold / 10; 448. 			    You("lost some of your gold in the fountain!"); 449. 			    CLEAR_FOUNTAIN_LOOTED(u.ux,u.uy); 450. 			    exercise(A_WIS, FALSE); 451. 			}  452.  #else 453. 			{  454.  			    long money = money_cnt(invent); 455. 			    struct obj *otmp; 456.                             if (money > 10) { 457. 				/* Amount to loose. Might get rounded up as fountains don't pay change... */ 458.  			        money = somegold(money) / 10; 459. 			        for (otmp = invent; otmp && money > 0; otmp = otmp->nobj) if (otmp->oclass == COIN_CLASS) { 460. 				    int denomination = objects[otmp->otyp].oc_cost; 461. 				    long coin_loss = (money + denomination - 1) / denomination; 462.                                     coin_loss = min(coin_loss, otmp->quan); 463. 				    otmp->quan -= coin_loss; 464. 				    money -= coin_loss * denomination; 465. 				    if (!otmp->quan) delobj(otmp); 466. 				}  467.  			        You("lost some of your money in the fountain!"); 468. 				CLEAR_FOUNTAIN_LOOTED(u.ux,u.uy); 469. 			        exercise(A_WIS, FALSE); 470.                             }  471.  			}  472.  #endif 473. 			break; 474. 		case 29: /* You see coins */ 475.  476.  		/* We make fountains have more coins the closer you are to the 477. 		 * surface. After all, there will have been more people going 478. 		 * by. Just like a shopping mall! Chris Woodbury */ 479.  480.  		    if (FOUNTAIN_IS_LOOTED(u.ux,u.uy)) break; 481. 		    SET_FOUNTAIN_LOOTED(u.ux,u.uy); 482. 		    (void) mkgold((long)  483.  			(rnd((dunlevs_in_dungeon(&u.uz)-dunlev(&u.uz)+1)*2)+5),  484.  			u.ux, u.uy); 485. 		    if (!Blind) 486. 		pline("Far below you, you see coins glistening in the water."); 487. 		    exercise(A_WIS, TRUE); 488. 		    newsym(u.ux,u.uy); 489. 		    break; 490. 	}  491.  	update_inventory; 492. 	dryup(u.ux, u.uy, TRUE); 493. }  494.   495.  #ifdef SINKS 496. void 497. breaksink(x,y) 498. int x, y;  499. { 500.      if(cansee(x,y) || (x == u.ux && y == u.uy)) 501. 	pline_The("pipes break!  Water spurts out!"); 502.     level.flags.nsinks--; 503.     levl[x][y].doormask = 0; 504.     levl[x][y].typ = FOUNTAIN; 505.     level.flags.nfountains++; 506.     newsym(x,y); 507. }  508.   509.  void 510. drinksink 511. {  512.  	struct obj *otmp; 513. 	struct monst *mtmp; 514.  515.  	if (Levitation) { 516. 		floating_above("sink"); 517. 		return; 518. 	}  519.  	switch(rn2(20)) { 520. 		case 0: You("take a sip of very cold water."); 521. 			break; 522. 		case 1: You("take a sip of very warm water."); 523. 			break; 524. 		case 2: You("take a sip of scalding hot water."); 525. 			if (Fire_resistance) 526. 				pline("It seems quite tasty."); 527. 			else losehp(rnd(6), "sipping boiling water", KILLED_BY); 528. 			break; 529. 		case 3: if (mvitals[PM_SEWER_RAT].mvflags & G_GONE) 530. 				pline_The("sink seems quite dirty."); 531. 			else { 532. 				mtmp = makemon(&mons[PM_SEWER_RAT],  533.  						u.ux, u.uy, NO_MM_FLAGS); 534. 				if (mtmp) pline("Eek!  There's %s in the sink!",  535.  					(Blind || !canspotmon(mtmp)) ?  536.  					"something squirmy" :  537.  					a_monnam(mtmp)); 538. 			}  539.  			break; 540. 		case 4: do { 541. 				otmp = mkobj(POTION_CLASS,FALSE); 542. 				if (otmp->otyp == POT_WATER) { 543. 					obfree(otmp, (struct obj *)0); 544. 					otmp = (struct obj *) 0; 545. 				}  546.  			} while(!otmp); 547. 			otmp->cursed = otmp->blessed = 0; 548. 			pline("Some %s liquid flows from the faucet.",  549.  			      Blind ? "odd" :  550.  			      hcolor(OBJ_DESCR(objects[otmp->otyp]))); 551. 			otmp->dknown = !(Blind || Hallucination); 552. 			otmp->quan++; /* Avoid panic upon useup */ 553. 			otmp->fromsink = 1; /* kludge for docall */ 554. 			(void) dopotion(otmp); 555. 			obfree(otmp, (struct obj *)0); 556. 			break; 557. 		case 5: if (!(levl[u.ux][u.uy].looted & S_LRING)) { 558. 			    You("find a ring in the sink!"); 559. 			    (void) mkobj_at(RING_CLASS, u.ux, u.uy, TRUE); 560. 			    levl[u.ux][u.uy].looted |= S_LRING; 561. 			    exercise(A_WIS, TRUE); 562. 			    newsym(u.ux,u.uy); 563. 			} else pline("Some dirty water backs up in the drain."); 564. 			break; 565. 		case 6: breaksink(u.ux,u.uy); 566. 			break; 567. 		case 7: pline_The("water moves as though of its own will!"); 568. 			if ((mvitals[PM_WATER_ELEMENTAL].mvflags & G_GONE)  569.  			    || !makemon(&mons[PM_WATER_ELEMENTAL], 570. 					u.ux, u.uy, NO_MM_FLAGS)) 571. 				pline("But it quiets down."); 572. 			break; 573. 		case 8: pline("Yuk, this water tastes awful."); 574. 			more_experienced(1,0); 575. 			newexplevel; 576. 			break; 577. 		case 9: pline("Gaggg... this tastes like sewage!  You vomit."); 578. 			morehungry(rn1(30-ACURR(A_CON), 11)); 579. 			vomit; 580. 			break; 581. 		case 10: pline("This water contains toxic wastes!"); 582. 			if (!Unchanging) { 583. 				You("undergo a freakish metamorphosis!"); 584. 				polyself(FALSE); 585. 			}  586.  			break; 587. 		/* more odd messages --JJB */ 588. 		case 11: You_hear("clanking from the pipes..."); 589. 			break; 590. 		case 12: You_hear("snatches of song from among the sewers..."); 591. 			break; 592. 		case 19: if (Hallucination) { 593. 		   pline("From the murky drain, a hand reaches up... --oops--"); 594. 				break; 595. 			}  596.  		default: You("take a sip of %s water.",  597.  			rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot"); 598. 	}  599.  }  600.  #endif /* SINKS */ 601.  602.  /*fountain.c*/