Source:NetHack 3.4.0/fountain.c

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