From Wikihack
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.
[edit] Top of file
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.
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.
[edit] floating_above
15. void
16. floating_above(what)
17. const char *what;
18. {
19. You("are floating high above the %s.", what);
20. }
21.
[edit] dowatersnakes
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.
[edit] dowaterdemon
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.
[edit] dowaternymph
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.
[edit] dogushforth
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.
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.
[edit] dofindgem
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.
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.
[edit] drinkfountain
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.
[edit] dipfountain
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.
[edit] breaksink
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.
[edit] drinksink
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*/