Fandom

Wikihack

Source:NetHack 3.1.0/fountain.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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*/

Also on Fandom

Random Wiki