Source:NetHack 3.3.0/fountain.c

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

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

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