Wikia

Wikihack

Source:Fountain.c

2,032pages on
this wiki
Talk0

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.

Top of file Edit

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

floating_above Edit

15.   void
16.   floating_above(what)
17.   const char *what;
18.   {
19.       You("are floating high above the %s.", what);
20.   }
21.   

dowatersnakes Edit

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.   

dowaterdemon Edit

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.   

dowaternymph Edit

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.   

dogushforth Edit

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.  

gush Edit

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.  

dofindgem Edit

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.  

dryup Edit

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.  

drinkfountain Edit

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.  

dipfountain Edit

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.  

breaksink Edit

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.  

drinksink Edit

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*/

Around Wikia's network

Random Wiki