1 /* NetHack 3.6 fountain.c $NHDT-Date: 1455402364 2016/02/13 22:26:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.56 $ */
2 /* Copyright Scott R. Turner, srt@ucla, 10/27/86 */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* Code for drinking from fountains. */
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
);
15 /* used when trying to dip in or drink from fountain or sink or pool while
16 levitating above it, or when trying to move downwards in that state */
21 const char *umsg
= "are floating high above the %s.";
23 if (u
.utrap
&& (u
.utraptype
== TT_INFLOOR
|| u
.utraptype
== TT_LAVA
)) {
24 /* when stuck in floor (not possible at fountain or sink location,
25 so must be attempting to move down), override the usual message */
26 umsg
= "are trapped in the %s.";
27 what
= surface(u
.ux
, u
.uy
); /* probably redundant */
32 /* Fountain of snakes! */
36 register int num
= rn1(5, 2);
39 if (!(mvitals
[PM_WATER_MOCCASIN
].mvflags
& G_GONE
)) {
41 pline("An endless stream of %s pours forth!",
42 Hallucination
? makeplural(rndmonnam(NULL
)) : "snakes");
44 You_hear("%s hissing!", something
);
46 if ((mtmp
= makemon(&mons
[PM_WATER_MOCCASIN
], u
.ux
, u
.uy
,
48 && t_at(mtmp
->mx
, mtmp
->my
))
51 pline_The("fountain bubbles furiously for a moment, then calms.");
60 if (!(mvitals
[PM_WATER_DEMON
].mvflags
& G_GONE
)) {
61 if ((mtmp
= makemon(&mons
[PM_WATER_DEMON
], u
.ux
, u
.uy
,
64 You("unleash %s!", a_monnam(mtmp
));
66 You_feel("the presence of evil.");
68 /* Give those on low levels a (slightly) better chance of survival
70 if (rnd(100) > (80 + level_difficulty())) {
71 pline("Grateful for %s release, %s grants you a wish!",
72 mhis(mtmp
), mhe(mtmp
));
73 /* give a wish and discard the monster (mtmp set to null) */
75 } else if (t_at(mtmp
->mx
, mtmp
->my
))
79 pline_The("fountain bubbles furiously for a moment, then calms.");
86 register struct monst
*mtmp
;
88 if (!(mvitals
[PM_WATER_NYMPH
].mvflags
& G_GONE
)
89 && (mtmp
= makemon(&mons
[PM_WATER_NYMPH
], u
.ux
, u
.uy
,
92 You("attract %s!", a_monnam(mtmp
));
94 You_hear("a seductive voice.");
96 if (t_at(mtmp
->mx
, mtmp
->my
))
99 pline("A large bubble rises to the surface and pops.");
101 You_hear("a loud pop.");
104 /* Gushing forth along LOS from (u.ux, u.uy) */
106 dogushforth(drinking
)
111 do_clear_area(u
.ux
, u
.uy
, 7, gush
, (genericptr_t
) &madepool
);
114 Your("thirst is quenched.");
116 pline("Water sprays all over you.");
123 genericptr_t poolcnt
;
125 register struct monst
*mtmp
;
126 register struct trap
*ttmp
;
128 if (((x
+ y
) % 2) || (x
== u
.ux
&& y
== u
.uy
)
129 || (rn2(1 + distmin(u
.ux
, u
.uy
, x
, y
))) || (levl
[x
][y
].typ
!= ROOM
)
130 || (sobj_at(BOULDER
, x
, y
)) || nexttodoor(x
, y
))
133 if ((ttmp
= t_at(x
, y
)) != 0 && !delfloortrap(ttmp
))
136 if (!((*(int *) poolcnt
)++))
137 pline("Water gushes forth from the overflowing fountain!");
139 /* Put a pool at x, y */
140 levl
[x
][y
].typ
= POOL
;
143 water_damage_chain(level
.objects
[x
][y
], TRUE
);
145 if ((mtmp
= m_at(x
, y
)) != 0)
146 (void) minliquid(mtmp
);
151 /* Find a gem in the sparkling waters. */
156 You("spot a gem in the sparkling waters!");
158 You_feel("a gem here!");
159 (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL
, LUCKSTONE
- 1), u
.ux
, u
.uy
,
161 SET_FOUNTAIN_LOOTED(u
.ux
, u
.uy
);
163 exercise(A_WIS
, TRUE
); /* a discovery! */
171 if (IS_FOUNTAIN(levl
[x
][y
].typ
)
172 && (!rn2(3) || FOUNTAIN_IS_WARNED(x
, y
))) {
173 if (isyou
&& in_town(x
, y
) && !FOUNTAIN_IS_WARNED(x
, y
)) {
176 SET_FOUNTAIN_WARNED(x
, y
);
177 /* Warn about future fountain use. */
178 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
179 if (DEADMONSTER(mtmp
))
181 if (is_watch(mtmp
->data
) && couldsee(mtmp
->mx
, mtmp
->my
)
182 && mtmp
->mpeaceful
) {
184 pline("%s yells:", Amonnam(mtmp
));
185 verbalize("Hey, stop using that fountain!");
187 pline("%s earnestly %s %s %s!",
189 nolimbs(mtmp
->data
) ? "shakes" : "waves",
192 ? mbodypart(mtmp
, HEAD
)
193 : makeplural(mbodypart(mtmp
, ARM
)));
198 /* You can see or hear this effect */
200 pline_The("flow reduces to a trickle.");
203 if (isyou
&& wizard
) {
204 if (yn("Dry up fountain?") == 'n')
207 /* replace the fountain with ordinary floor */
208 levl
[x
][y
].typ
= ROOM
;
209 levl
[x
][y
].looted
= 0;
210 levl
[x
][y
].blessedftn
= 0;
212 pline_The("fountain dries up!");
213 /* The location is seen if the hero/monster is invisible
214 or felt if the hero is blind. */
216 level
.flags
.nfountains
--;
217 if (isyou
&& in_town(x
, y
))
218 (void) angry_guards(FALSE
);
225 /* What happens when you drink from a fountain? */
226 register boolean mgkftn
= (levl
[u
.ux
][u
.uy
].blessedftn
== 1);
227 register int fate
= rnd(30);
230 floating_above("fountain");
234 if (mgkftn
&& u
.uluck
>= 0 && fate
>= 10) {
235 int i
, ii
, littleluck
= (u
.uluck
< 4);
237 pline("Wow! This makes you feel great!");
238 /* blessed restore ability */
239 for (ii
= 0; ii
< A_MAX
; ii
++)
240 if (ABASE(ii
) < AMAX(ii
)) {
241 ABASE(ii
) = AMAX(ii
);
244 /* gain ability, blessed if "natural" luck is high */
245 i
= rn2(A_MAX
); /* start at a random attribute */
246 for (ii
= 0; ii
< A_MAX
; ii
++) {
247 if (adjattrib(i
, 1, littleluck
? -1 : 0) && littleluck
)
252 display_nhwindow(WIN_MESSAGE
, FALSE
);
253 pline("A wisp of vapor escapes the fountain...");
254 exercise(A_WIS
, TRUE
);
255 levl
[u
.ux
][u
.uy
].blessedftn
= 0;
260 pline_The("cool draught refreshes you.");
261 u
.uhunger
+= rnd(10); /* don't choke on water */
267 case 19: /* Self-knowledge */
268 You_feel("self-knowledgeable...");
269 display_nhwindow(WIN_MESSAGE
, FALSE
);
270 enlightenment(MAGICENLIGHTENMENT
, ENL_GAMEINPROGRESS
);
271 exercise(A_WIS
, TRUE
);
272 pline_The("feeling subsides.");
274 case 20: /* Foul water */
275 pline_The("water is foul! You gag and vomit.");
276 morehungry(rn1(20, 11));
279 case 21: /* Poisonous */
280 pline_The("water is contaminated!");
281 if (Poison_resistance
) {
282 pline("Perhaps it is runoff from the nearby %s farm.",
284 losehp(rnd(4), "unrefrigerated sip of juice", KILLED_BY_AN
);
288 losehp(rnd(10), "contaminated water", KILLED_BY
);
289 exercise(A_CON
, FALSE
);
291 case 22: /* Fountain of snakes! */
294 case 23: /* Water demon */
297 case 24: /* Curse an item */ {
298 register struct obj
*obj
;
300 pline("This water's no good!");
301 morehungry(rn1(20, 11));
302 exercise(A_CON
, FALSE
);
303 for (obj
= invent
; obj
; obj
= obj
->nobj
)
308 case 25: /* See invisible */
311 You("feel transparent.");
313 You("feel very self-conscious.");
314 pline("Then it passes.");
317 You_see("an image of someone stalking you.");
318 pline("But it disappears.");
320 HSee_invisible
|= FROMOUTSIDE
;
322 exercise(A_WIS
, TRUE
);
324 case 26: /* See Monsters */
325 (void) monster_detect((struct obj
*) 0, 0);
326 exercise(A_WIS
, TRUE
);
328 case 27: /* Find a gem in the sparkling waters. */
329 if (!FOUNTAIN_IS_LOOTED(u
.ux
, u
.uy
)) {
333 case 28: /* Water Nymph */
338 register struct monst
*mtmp
;
340 pline("This %s gives you bad breath!",
342 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
) {
343 if (DEADMONSTER(mtmp
))
345 monflee(mtmp
, 0, FALSE
, FALSE
);
349 case 30: /* Gushing forth in this room */
353 pline("This tepid %s is tasteless.",
358 dryup(u
.ux
, u
.uy
, TRUE
);
363 register struct obj
*obj
;
366 floating_above("fountain");
370 /* Don't grant Excalibur when there's more than one object. */
371 /* (quantity could be > 1 if merged daggers got polymorphed) */
372 if (obj
->otyp
== LONG_SWORD
&& obj
->quan
== 1L && u
.ulevel
>= 5 && !rn2(6)
374 && !exist_artifact(LONG_SWORD
, artiname(ART_EXCALIBUR
))) {
375 if (u
.ualign
.type
!= A_LAWFUL
) {
376 /* Ha! Trying to cheat her. */
377 pline("A freezing mist rises from the %s and envelopes the sword.",
379 pline_The("fountain disappears!");
381 if (obj
->spe
> -6 && !rn2(3))
383 obj
->oerodeproof
= FALSE
;
384 exercise(A_WIS
, FALSE
);
386 /* The lady of the lake acts! - Eric Backus */
389 "From the murky depths, a hand reaches up to bless the sword.");
390 pline("As the hand retreats, the fountain disappears!");
391 obj
= oname(obj
, artiname(ART_EXCALIBUR
));
392 discover_artifact(ART_EXCALIBUR
);
394 obj
->oeroded
= obj
->oeroded2
= 0;
395 obj
->oerodeproof
= TRUE
;
396 exercise(A_WIS
, TRUE
);
399 levl
[u
.ux
][u
.uy
].typ
= ROOM
;
400 levl
[u
.ux
][u
.uy
].looted
= 0;
402 level
.flags
.nfountains
--;
403 if (in_town(u
.ux
, u
.uy
))
404 (void) angry_guards(FALSE
);
407 int er
= water_damage(obj
, NULL
, TRUE
);
409 if (obj
->otyp
== POT_ACID
410 && er
!= ER_DESTROYED
) { /* Acid and water don't mix */
413 } else if (er
!= ER_NOTHING
&& !rn2(2)) { /* no further effect */
419 case 16: /* Curse the item */
425 case 20: /* Uncurse the item */
428 pline_The("%s glows for a moment.", hliquid("water"));
431 pline("A feeling of loss comes over you.");
434 case 21: /* Water Demon */
437 case 22: /* Water Nymph */
440 case 23: /* an Endless Stream of Snakes */
443 case 24: /* Find a gem */
444 if (!FOUNTAIN_IS_LOOTED(u
.ux
, u
.uy
)) {
448 case 25: /* Water gushes forth */
451 case 26: /* Strange feeling */
452 pline("A strange tingling runs up your %s.", body_part(ARM
));
454 case 27: /* Strange feeling */
455 You_feel("a sudden chill.");
457 case 28: /* Strange feeling */
458 pline("An urge to take a bath overwhelms you.");
460 long money
= money_cnt(invent
);
463 /* Amount to lose. Might get rounded up as fountains don't
465 money
= somegold(money
) / 10;
466 for (otmp
= invent
; otmp
&& money
> 0; otmp
= otmp
->nobj
)
467 if (otmp
->oclass
== COIN_CLASS
) {
468 int denomination
= objects
[otmp
->otyp
].oc_cost
;
470 (money
+ denomination
- 1) / denomination
;
471 coin_loss
= min(coin_loss
, otmp
->quan
);
472 otmp
->quan
-= coin_loss
;
473 money
-= coin_loss
* denomination
;
477 You("lost some of your money in the fountain!");
478 CLEAR_FOUNTAIN_LOOTED(u
.ux
, u
.uy
);
479 exercise(A_WIS
, FALSE
);
483 case 29: /* You see coins */
484 /* We make fountains have more coins the closer you are to the
485 * surface. After all, there will have been more people going
486 * by. Just like a shopping mall! Chris Woodbury */
488 if (FOUNTAIN_IS_LOOTED(u
.ux
, u
.uy
))
490 SET_FOUNTAIN_LOOTED(u
.ux
, u
.uy
);
491 (void) mkgold((long) (rnd((dunlevs_in_dungeon(&u
.uz
) - dunlev(&u
.uz
)
495 pline("Far below you, you see coins glistening in the %s.",
497 exercise(A_WIS
, TRUE
);
502 dryup(u
.ux
, u
.uy
, TRUE
);
509 if (cansee(x
, y
) || (x
== u
.ux
&& y
== u
.uy
))
510 pline_The("pipes break! Water spurts out!");
511 level
.flags
.nsinks
--;
512 levl
[x
][y
].doormask
= 0;
513 levl
[x
][y
].typ
= FOUNTAIN
;
514 level
.flags
.nfountains
++;
525 floating_above("sink");
530 You("take a sip of very cold %s.", hliquid("water"));
533 You("take a sip of very warm %s.", hliquid("water"));
536 You("take a sip of scalding hot %s.", hliquid("water"));
538 pline("It seems quite tasty.");
540 losehp(rnd(6), "sipping boiling water", KILLED_BY
);
541 /* boiling water burns considered fire damage */
544 if (mvitals
[PM_SEWER_RAT
].mvflags
& G_GONE
)
545 pline_The("sink seems quite dirty.");
547 mtmp
= makemon(&mons
[PM_SEWER_RAT
], u
.ux
, u
.uy
, NO_MM_FLAGS
);
549 pline("Eek! There's %s in the sink!",
550 (Blind
|| !canspotmon(mtmp
)) ? "something squirmy"
556 otmp
= mkobj(POTION_CLASS
, FALSE
);
557 if (otmp
->otyp
== POT_WATER
) {
558 obfree(otmp
, (struct obj
*) 0);
559 otmp
= (struct obj
*) 0;
562 otmp
->cursed
= otmp
->blessed
= 0;
563 pline("Some %s liquid flows from the faucet.",
564 Blind
? "odd" : hcolor(OBJ_DESCR(objects
[otmp
->otyp
])));
565 otmp
->dknown
= !(Blind
|| Hallucination
);
566 otmp
->quan
++; /* Avoid panic upon useup() */
567 otmp
->fromsink
= 1; /* kludge for docall() */
568 (void) dopotion(otmp
);
569 obfree(otmp
, (struct obj
*) 0);
572 if (!(levl
[u
.ux
][u
.uy
].looted
& S_LRING
)) {
573 You("find a ring in the sink!");
574 (void) mkobj_at(RING_CLASS
, u
.ux
, u
.uy
, TRUE
);
575 levl
[u
.ux
][u
.uy
].looted
|= S_LRING
;
576 exercise(A_WIS
, TRUE
);
579 pline("Some dirty %s backs up in the drain.", hliquid("water"));
582 breaksink(u
.ux
, u
.uy
);
585 pline_The("%s moves as though of its own will!", hliquid("water"));
586 if ((mvitals
[PM_WATER_ELEMENTAL
].mvflags
& G_GONE
)
587 || !makemon(&mons
[PM_WATER_ELEMENTAL
], u
.ux
, u
.uy
, NO_MM_FLAGS
))
588 pline("But it quiets down.");
591 pline("Yuk, this %s tastes awful.", hliquid("water"));
592 more_experienced(1, 0);
596 pline("Gaggg... this tastes like sewage! You vomit.");
597 morehungry(rn1(30 - ACURR(A_CON
), 11));
601 pline("This %s contains toxic wastes!", hliquid("water"));
603 You("undergo a freakish metamorphosis!");
607 /* more odd messages --JJB */
609 You_hear("clanking from the pipes...");
612 You_hear("snatches of song from among the sewers...");
616 pline("From the murky drain, a hand reaches up... --oops--");
620 You("take a sip of %s %s.",
621 rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot",