Source:NetHack 3.1.0/fountain.c

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