Files
nethack/src/fountain.c
nhmall e4e65c4b8b whitelist several non-literal format strings
djgpp cross-compiler was griping about several.

This also removes these lines from sys/unix/hints/include/compiler.370.
    CFLAGS+=-Wno-format-nonliteral
    CCXXFLAGS+=-Wno-format-nonliteral

-Wformat-nonliteral should not be incompatible with the printf
argument-checking capabilities on literal format strings and there
shouldn't be any new warnings created.

-- &< --

artifact.c: In function 'artifact_hit':
artifact.c:1309:23: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1309 |                       mon_nam(mdef));
      |                       ^~~~~~~
artifact.c:1328:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1328 |                 pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
      |                 ^~~~~

ball.c: In function 'drop_ball':
ball.c:896:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  896 |                 pline(pullmsg, "pit");
      |                 ^~~~~
ball.c:899:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  899 |                 pline(pullmsg, "web");
      |                 ^~~~~
ball.c:904:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  904 |                 pline(pullmsg, hliquid("lava"));
      |                 ^~~~~
ball.c:908:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  908 |                 pline(pullmsg, "bear trap");
      |                 ^~~~~

dig.c: In function 'liquid_flow':
dig.c:747:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  747 |         pline(fillmsg, hliquid(typ == LAVAPOOL ? "lava" : "water"));
      |         ^~~~~

fountain.c: In function 'floating_above':
fountain.c:28:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
   28 |     You(umsg, what);
      |     ^~~

invent.c: In function 'hold_another_object':
invent.c:1018:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1018 |                 pline(drop_fmt, drop_arg);
      |                 ^~~~~
invent.c:1073:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1073 |         pline(drop_fmt, drop_arg);
      |         ^~~~~
invent.c: In function 'silly_thing':
invent.c:1811:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1811 |         pline(silly_thing_to, word);
      |         ^~~~~

lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  375 |             pline(no_longer, "hold the", what);
      |                   ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  379 |             pline(no_longer, "reach the", "lock");
      |                   ^~~~~~~~~
lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  375 |             pline(no_longer, "hold the", what);
      |                   ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  379 |             pline(no_longer, "reach the", "lock");
      |                   ^~~~~~~~~
mcastu.c: In function 'cast_cleric_spell':
mcastu.c:670:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  670 |             pline(fmt, Monnam(mtmp), what);
      |             ^~~~~

mhitu.c: In function 'hitmsg':
mhitu.c:68:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
   68 |             pline(pfmt, Monst_name);
      |             ^~~~~

mkobj.c: In function 'insane_object':
mkobj.c:2848:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2848 |         impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
      |                    ^~~~~~
mkobj.c:2852:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2852 |                    objnm);
      |                    ^~~~~

mon.c: In function 'mon_givit':
mon.c:1469:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1469 |         pline(msg, Monnam(mtmp));
      |         ^~~~~
mon.c: In function 'mondead':
mon.c:2485:33: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2485 |                                 | SUPPRESS_INVISIBLE), FALSE));
      |                                 ^

muse.c: In function 'mon_reflects':
muse.c:2438:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2438 |             pline(str, s_suffix(mon_nam(mon)), "shield");
      |             ^~~~~
muse.c:2445:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2445 |             pline(str, s_suffix(mon_nam(mon)), "weapon");
      |             ^~~~~
muse.c:2450:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2450 |             pline(str, s_suffix(mon_nam(mon)), "amulet");
      |             ^~~~~
muse.c:2458:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2458 |             pline(str, s_suffix(mon_nam(mon)), "armor");
      |             ^~~~~
muse.c:2464:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2464 |             pline(str, s_suffix(mon_nam(mon)), "scales");
      |             ^~~~~
muse.c: In function 'ureflects':
muse.c:2476:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2476 |             pline(fmt, str, "shield");
      |             ^~~~~
muse.c:2483:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2483 |             pline(fmt, str, "weapon");
      |             ^~~~~
muse.c:2487:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2487 |             pline(fmt, str, "medallion");
      |             ^~~~~
muse.c:2493:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2493 |             pline(fmt, str, uskin ? "luster" : "armor");
      |             ^~~~~
muse.c:2497:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2497 |             pline(fmt, str, "scales");
      |             ^~~~~

polyself.c: In function 'polyman':
polyself.c:201:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  201 |     urgent_pline(fmt, arg);
      |     ^~~~~~~~~~~~

potion.c: In function 'make_hallucinated':
potion.c:423:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  423 |             pline(message, verb);
      |             ^~~~~
potion.c: In function 'peffect_gain_level':
potion.c:1033:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1033 |                 You(riseup, ceiling(u.ux, u.uy));
      |                 ^~~
potion.c:1044:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1044 |                     You(riseup, ceiling(u.ux, u.uy));
      |                     ^~~

priest.c: In function 'intemple':
priest.c:487:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  487 |                 You(msg1, msg2);
      |                 ^~~

read.c: In function 'doread':
read.c:522:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  522 |         pline(silly_thing_to, "read");
      |         ^~~~~

shk.c: In function 'shk_names_obj':
shk.c:2576:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2576 |         pline(fmtbuf, obj_name, (obj->quan > 1L) ? "them" : "it", amt,
      |               ^~~~~~
shk.c:2579:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2579 |         You(fmt, obj_name, amt, plur(amt), arg);
      |         ^~~
shk.c: In function 'shk_chat':
shk.c:4506:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 4506 |             pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
      |             ^~~~~
shk.c: In function 'check_unpaid_usage':
shk.c:4633:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 4633 |         verbalize(fmt, arg1, arg2, tmp, currency(tmp));
      |         ^~~~~~~~~

sounds.c: In function 'dosounds':
sounds.c:66:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
   66 |                     pline(throne_msg[2], uhis());
      |                     ^~~~~
sounds.c:259:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  259 |                 You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
      |                 ^~~~~~~~

timeout.c: In function 'choke_dialogue':
timeout.c:269:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  269 |                          body_part(NECK));
      |                          ^~~~~~~~~
timeout.c:274:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  274 |                 urgent_pline(str, hcolor(NH_BLUE));
      |                 ^~~~~~~~~~~~
timeout.c: In function 'levitation_dialogue':
timeout.c:339:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  339 |                          danger ? surface(u.ux, u.uy) : "air");
      |                          ^~~~~~
timeout.c: In function 'slime_dialogue':
timeout.c:379:34: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  379 |                     urgent_pline(buf, hcolor(NH_GREEN));
      |                                  ^~~
timeout.c:381:30: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
  381 |                 urgent_pline(buf, an(Hallucination ? rndmonnam(NULL)
      |                              ^~~

uhitm.c: In function 'hmon_hitmon':
uhitm.c:1398:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1398 |         pline(fmt, whom);
      |         ^~~~~
uhitm.c:1421:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1421 |         pline(fmt, whom);
      |         ^~~~~
uhitm.c: In function 'stumble_onto_mimic':
uhitm.c:5301:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 5301 |         pline(fmt, what);
      |         ^~~~~

../win/tty/wintty.c: In function 'tty_clear_nhwindow':
../win/tty/wintty.c:1649:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 1649 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_display_nhwindow':
../win/tty/wintty.c:2339:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2339 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_dismiss_nhwindow':
../win/tty/wintty.c:2432:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2432 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_destroy_nhwindow':
../win/tty/wintty.c:2477:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2477 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_curs':
../win/tty/wintty.c:2503:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2503 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_putsym':
../win/tty/wintty.c:2599:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2599 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_add_menu':
../win/tty/wintty.c:2967:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 2967 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_end_menu':
../win/tty/wintty.c:3032:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 3032 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_select_menu':
../win/tty/wintty.c:3140:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
 3140 |         panic(winpanicstr, window);
      |               ^~~~~~~~~~~
2022-01-09 14:18:10 -05:00

641 lines
20 KiB
C

/* NetHack 3.7 fountain.c $NHDT-Date: 1596498170 2020/08/03 23:42:50 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.69 $ */
/* Copyright Scott R. Turner, srt@ucla, 10/27/86 */
/* NetHack may be freely redistributed. See license for details. */
/* Code for drinking from fountains. */
#include "hack.h"
static void dowatersnakes(void);
static void dowaterdemon(void);
static void dowaternymph(void);
static void gush(int, int, genericptr_t);
static void dofindgem(void);
DISABLE_WARNING_FORMAT_NONLITERAL
/* used when trying to dip in or drink from fountain or sink or pool while
levitating above it, or when trying to move downwards in that state */
void
floating_above(const char *what)
{
const char *umsg = "are floating high above the %s.";
if (u.utrap && (u.utraptype == TT_INFLOOR || u.utraptype == TT_LAVA)) {
/* when stuck in floor (not possible at fountain or sink location,
so must be attempting to move down), override the usual message */
umsg = "are trapped in the %s.";
what = surface(u.ux, u.uy); /* probably redundant */
}
You(umsg, what);
}
RESTORE_WARNING_FORMAT_NONLITERAL
/* Fountain of snakes! */
static void
dowatersnakes(void)
{
register int num = rn1(5, 2);
struct monst *mtmp;
if (!(g.mvitals[PM_WATER_MOCCASIN].mvflags & G_GONE)) {
if (!Blind)
pline("An endless stream of %s pours forth!",
Hallucination ? makeplural(rndmonnam(NULL)) : "snakes");
else
You_hear("%s hissing!", something);
while (num-- > 0)
if ((mtmp = makemon(&mons[PM_WATER_MOCCASIN], u.ux, u.uy,
MM_NOMSG)) != 0
&& t_at(mtmp->mx, mtmp->my))
(void) mintrap(mtmp);
} else
pline_The("fountain bubbles furiously for a moment, then calms.");
}
/* Water demon */
static void
dowaterdemon(void)
{
struct monst *mtmp;
if (!(g.mvitals[PM_WATER_DEMON].mvflags & G_GONE)) {
if ((mtmp = makemon(&mons[PM_WATER_DEMON], u.ux, u.uy,
MM_NOMSG)) != 0) {
if (!Blind)
You("unleash %s!", a_monnam(mtmp));
else
You_feel("the presence of evil.");
/* Give those on low levels a (slightly) better chance of survival
*/
if (rnd(100) > (80 + level_difficulty())) {
pline("Grateful for %s release, %s grants you a wish!",
mhis(mtmp), mhe(mtmp));
/* give a wish and discard the monster (mtmp set to null) */
mongrantswish(&mtmp);
} else if (t_at(mtmp->mx, mtmp->my))
(void) mintrap(mtmp);
}
} else
pline_The("fountain bubbles furiously for a moment, then calms.");
}
/* Water Nymph */
static void
dowaternymph(void)
{
register struct monst *mtmp;
if (!(g.mvitals[PM_WATER_NYMPH].mvflags & G_GONE)
&& (mtmp = makemon(&mons[PM_WATER_NYMPH], u.ux, u.uy,
MM_NOMSG)) != 0) {
if (!Blind)
You("attract %s!", a_monnam(mtmp));
else
You_hear("a seductive voice.");
mtmp->msleeping = 0;
if (t_at(mtmp->mx, mtmp->my))
(void) mintrap(mtmp);
} else if (!Blind)
pline("A large bubble rises to the surface and pops.");
else
You_hear("a loud pop.");
}
/* Gushing forth along LOS from (u.ux, u.uy) */
void
dogushforth(int drinking)
{
int madepool = 0;
do_clear_area(u.ux, u.uy, 7, gush, (genericptr_t) &madepool);
if (!madepool) {
if (drinking)
Your("thirst is quenched.");
else
pline("Water sprays all over you.");
}
}
static void
gush(int x, int y, genericptr_t poolcnt)
{
register struct monst *mtmp;
register struct trap *ttmp;
if (((x + y) % 2) || (x == u.ux && y == u.uy)
|| (rn2(1 + distmin(u.ux, u.uy, x, y))) || (levl[x][y].typ != ROOM)
|| (sobj_at(BOULDER, x, y)) || nexttodoor(x, y))
return;
if ((ttmp = t_at(x, y)) != 0 && !delfloortrap(ttmp))
return;
if (!((*(int *) poolcnt)++))
pline("Water gushes forth from the overflowing fountain!");
/* Put a pool at x, y */
levl[x][y].typ = POOL, levl[x][y].flags = 0;
/* No kelp! */
del_engr_at(x, y);
water_damage_chain(g.level.objects[x][y], TRUE);
if ((mtmp = m_at(x, y)) != 0)
(void) minliquid(mtmp);
else
newsym(x, y);
}
/* Find a gem in the sparkling waters. */
static void
dofindgem(void)
{
if (!Blind)
You("spot a gem in the sparkling waters!");
else
You_feel("a gem here!");
(void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE - 1), u.ux, u.uy,
FALSE, FALSE);
SET_FOUNTAIN_LOOTED(u.ux, u.uy);
newsym(u.ux, u.uy);
exercise(A_WIS, TRUE); /* a discovery! */
}
void
dryup(xchar x, xchar y, boolean isyou)
{
if (IS_FOUNTAIN(levl[x][y].typ)
&& (!rn2(3) || FOUNTAIN_IS_WARNED(x, y))) {
if (isyou && in_town(x, y) && !FOUNTAIN_IS_WARNED(x, y)) {
struct monst *mtmp;
SET_FOUNTAIN_WARNED(x, y);
/* Warn about future fountain use. */
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
&& mtmp->mpeaceful) {
if (!Deaf) {
pline("%s yells:", Amonnam(mtmp));
verbalize("Hey, stop using that fountain!");
} else {
pline("%s earnestly %s %s %s!",
Amonnam(mtmp),
nolimbs(mtmp->data) ? "shakes" : "waves",
mhis(mtmp),
nolimbs(mtmp->data)
? mbodypart(mtmp, HEAD)
: makeplural(mbodypart(mtmp, ARM)));
}
break;
}
}
/* You can see or hear this effect */
if (!mtmp)
pline_The("flow reduces to a trickle.");
return;
}
if (isyou && wizard) {
if (yn("Dry up fountain?") == 'n')
return;
}
/* FIXME: sight-blocking clouds should use block_point() when
being created and unblock_point() when going away, then this
glyph hackery wouldn't be necessary */
if (cansee(x, y)) {
int glyph = glyph_at(x, y);
if (!glyph_is_cmap(glyph) || glyph_to_cmap(glyph) != S_cloud)
pline_The("fountain dries up!");
}
/* replace the fountain with ordinary floor */
levl[x][y].typ = ROOM, levl[x][y].flags = 0;
levl[x][y].blessedftn = 0;
g.level.flags.nfountains--;
/* The location is seen if the hero/monster is invisible
or felt if the hero is blind. */
newsym(x, y);
if (isyou && in_town(x, y))
(void) angry_guards(FALSE);
}
}
void
drinkfountain(void)
{
/* What happens when you drink from a fountain? */
register boolean mgkftn = (levl[u.ux][u.uy].blessedftn == 1);
register int fate = rnd(30);
if (Levitation) {
floating_above("fountain");
return;
}
if (mgkftn && u.uluck >= 0 && fate >= 10) {
int i, ii, littleluck = (u.uluck < 4);
pline("Wow! This makes you feel great!");
/* blessed restore ability */
for (ii = 0; ii < A_MAX; ii++)
if (ABASE(ii) < AMAX(ii)) {
ABASE(ii) = AMAX(ii);
g.context.botl = 1;
}
/* gain ability, blessed if "natural" luck is high */
i = rn2(A_MAX); /* start at a random attribute */
for (ii = 0; ii < A_MAX; ii++) {
if (adjattrib(i, 1, littleluck ? -1 : 0) && littleluck)
break;
if (++i >= A_MAX)
i = 0;
}
display_nhwindow(WIN_MESSAGE, FALSE);
pline("A wisp of vapor escapes the fountain...");
exercise(A_WIS, TRUE);
levl[u.ux][u.uy].blessedftn = 0;
return;
}
if (fate < 10) {
pline_The("cool draught refreshes you.");
u.uhunger += rnd(10); /* don't choke on water */
newuhs(FALSE);
if (mgkftn)
return;
} else {
switch (fate) {
case 19: /* Self-knowledge */
You_feel("self-knowledgeable...");
display_nhwindow(WIN_MESSAGE, FALSE);
enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
exercise(A_WIS, TRUE);
pline_The("feeling subsides.");
break;
case 20: /* Foul water */
pline_The("water is foul! You gag and vomit.");
morehungry(rn1(20, 11));
vomit();
break;
case 21: /* Poisonous */
pline_The("water is contaminated!");
if (Poison_resistance) {
pline("Perhaps it is runoff from the nearby %s farm.",
fruitname(FALSE));
losehp(rnd(4), "unrefrigerated sip of juice", KILLED_BY_AN);
break;
}
losestr(rn1(4, 3));
losehp(rnd(10), "contaminated water", KILLED_BY);
exercise(A_CON, FALSE);
break;
case 22: /* Fountain of snakes! */
dowatersnakes();
break;
case 23: /* Water demon */
dowaterdemon();
break;
case 24: { /* Maybe curse some items */
register struct obj *obj;
int buc_changed = 0;
pline("This water's no good!");
morehungry(rn1(20, 11));
exercise(A_CON, FALSE);
/* this is more severe than rndcurse() */
for (obj = g.invent; obj; obj = obj->nobj)
if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) {
curse(obj);
++buc_changed;
}
if (buc_changed)
update_inventory();
break;
}
case 25: /* See invisible */
if (Blind) {
if (Invisible) {
You("feel transparent.");
} else {
You("feel very self-conscious.");
pline("Then it passes.");
}
} else {
You_see("an image of someone stalking you.");
pline("But it disappears.");
}
HSee_invisible |= FROMOUTSIDE;
newsym(u.ux, u.uy);
exercise(A_WIS, TRUE);
break;
case 26: /* See Monsters */
(void) monster_detect((struct obj *) 0, 0);
exercise(A_WIS, TRUE);
break;
case 27: /* Find a gem in the sparkling waters. */
if (!FOUNTAIN_IS_LOOTED(u.ux, u.uy)) {
dofindgem();
break;
}
/*FALLTHRU*/
case 28: /* Water Nymph */
dowaternymph();
break;
case 29: /* Scare */
{
register struct monst *mtmp;
pline("This %s gives you bad breath!",
hliquid("water"));
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
monflee(mtmp, 0, FALSE, FALSE);
}
break;
}
case 30: /* Gushing forth in this room */
dogushforth(TRUE);
break;
default:
pline("This tepid %s is tasteless.",
hliquid("water"));
break;
}
}
dryup(u.ux, u.uy, TRUE);
}
void
dipfountain(register struct obj *obj)
{
if (Levitation) {
floating_above("fountain");
return;
}
/* Don't grant Excalibur when there's more than one object. */
/* (quantity could be > 1 if merged daggers got polymorphed) */
if (obj->otyp == LONG_SWORD && obj->quan == 1L && u.ulevel >= 5 && !rn2(6)
&& !obj->oartifact
&& !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) {
if (u.ualign.type != A_LAWFUL) {
/* Ha! Trying to cheat her. */
pline("A freezing mist rises from the %s and envelopes the sword.",
hliquid("water"));
pline_The("fountain disappears!");
curse(obj);
if (obj->spe > -6 && !rn2(3))
obj->spe--;
obj->oerodeproof = FALSE;
exercise(A_WIS, FALSE);
} else {
/* The lady of the lake acts! - Eric Backus */
/* Be *REAL* nice */
pline(
"From the murky depths, a hand reaches up to bless the sword.");
pline("As the hand retreats, the fountain disappears!");
obj = oname(obj, artiname(ART_EXCALIBUR));
discover_artifact(ART_EXCALIBUR);
bless(obj);
obj->oeroded = obj->oeroded2 = 0;
obj->oerodeproof = TRUE;
exercise(A_WIS, TRUE);
}
update_inventory();
levl[u.ux][u.uy].typ = ROOM, levl[u.ux][u.uy].flags = 0;
newsym(u.ux, u.uy);
g.level.flags.nfountains--;
if (in_town(u.ux, u.uy))
(void) angry_guards(FALSE);
return;
} else {
int er = water_damage(obj, NULL, TRUE);
if (obj->otyp == POT_ACID
&& er != ER_DESTROYED) { /* Acid and water don't mix */
useup(obj);
return;
} else if (er != ER_NOTHING && !rn2(2)) { /* no further effect */
return;
}
}
switch (rnd(30)) {
case 16: /* Curse the item */
if (obj->oclass != COIN_CLASS && !obj->cursed) {
curse(obj);
}
break;
case 17:
case 18:
case 19:
case 20: /* Uncurse the item */
if (obj->cursed) {
if (!Blind)
pline_The("%s glows for a moment.", hliquid("water"));
uncurse(obj);
} else {
pline("A feeling of loss comes over you.");
}
break;
case 21: /* Water Demon */
dowaterdemon();
break;
case 22: /* Water Nymph */
dowaternymph();
break;
case 23: /* an Endless Stream of Snakes */
dowatersnakes();
break;
case 24: /* Find a gem */
if (!FOUNTAIN_IS_LOOTED(u.ux, u.uy)) {
dofindgem();
break;
}
/*FALLTHRU*/
case 25: /* Water gushes forth */
dogushforth(FALSE);
break;
case 26: /* Strange feeling */
pline("A strange tingling runs up your %s.", body_part(ARM));
break;
case 27: /* Strange feeling */
You_feel("a sudden chill.");
break;
case 28: /* Strange feeling */
pline("An urge to take a bath overwhelms you.");
{
long money = money_cnt(g.invent);
struct obj *otmp;
if (money > 10) {
/* Amount to lose. Might get rounded up as fountains don't
* pay change... */
money = somegold(money) / 10;
for (otmp = g.invent; otmp && money > 0; otmp = otmp->nobj)
if (otmp->oclass == COIN_CLASS) {
int denomination = objects[otmp->otyp].oc_cost;
long coin_loss =
(money + denomination - 1) / denomination;
coin_loss = min(coin_loss, otmp->quan);
otmp->quan -= coin_loss;
money -= coin_loss * denomination;
if (!otmp->quan)
delobj(otmp);
}
You("lost some of your gold in the fountain!");
CLEAR_FOUNTAIN_LOOTED(u.ux, u.uy);
exercise(A_WIS, FALSE);
}
}
break;
case 29: /* You see coins */
/* We make fountains have more coins the closer you are to the
* surface. After all, there will have been more people going
* by. Just like a shopping mall! Chris Woodbury */
if (FOUNTAIN_IS_LOOTED(u.ux, u.uy))
break;
SET_FOUNTAIN_LOOTED(u.ux, u.uy);
(void) mkgold((long) (rnd((dunlevs_in_dungeon(&u.uz) - dunlev(&u.uz)
+ 1) * 2) + 5),
u.ux, u.uy);
if (!Blind)
pline("Far below you, you see coins glistening in the %s.",
hliquid("water"));
exercise(A_WIS, TRUE);
newsym(u.ux, u.uy);
break;
}
update_inventory();
dryup(u.ux, u.uy, TRUE);
}
void
breaksink(int x, int y)
{
if (cansee(x, y) || (x == u.ux && y == u.uy))
pline_The("pipes break! Water spurts out!");
g.level.flags.nsinks--;
levl[x][y].typ = FOUNTAIN, levl[x][y].looted = 0;
levl[x][y].blessedftn = 0;
SET_FOUNTAIN_LOOTED(x, y);
g.level.flags.nfountains++;
newsym(x, y);
}
void
drinksink(void)
{
struct obj *otmp;
struct monst *mtmp;
if (Levitation) {
floating_above("sink");
return;
}
switch (rn2(20)) {
case 0:
You("take a sip of very cold %s.", hliquid("water"));
break;
case 1:
You("take a sip of very warm %s.", hliquid("water"));
break;
case 2:
You("take a sip of scalding hot %s.", hliquid("water"));
if (Fire_resistance) {
pline("It seems quite tasty.");
monstseesu(M_SEEN_FIRE);
} else
losehp(rnd(6), "sipping boiling water", KILLED_BY);
/* boiling water burns considered fire damage */
break;
case 3:
if (g.mvitals[PM_SEWER_RAT].mvflags & G_GONE)
pline_The("sink seems quite dirty.");
else {
mtmp = makemon(&mons[PM_SEWER_RAT], u.ux, u.uy, MM_NOMSG);
if (mtmp)
pline("Eek! There's %s in the sink!",
(Blind || !canspotmon(mtmp)) ? "something squirmy"
: a_monnam(mtmp));
}
break;
case 4:
do {
otmp = mkobj(POTION_CLASS, FALSE);
if (otmp->otyp == POT_WATER) {
obfree(otmp, (struct obj *) 0);
otmp = (struct obj *) 0;
}
} while (!otmp);
otmp->cursed = otmp->blessed = 0;
pline("Some %s liquid flows from the faucet.",
Blind ? "odd" : hcolor(OBJ_DESCR(objects[otmp->otyp])));
otmp->dknown = !(Blind || Hallucination);
otmp->quan++; /* Avoid panic upon useup() */
otmp->fromsink = 1; /* kludge for docall() */
(void) dopotion(otmp);
obfree(otmp, (struct obj *) 0);
break;
case 5:
if (!(levl[u.ux][u.uy].looted & S_LRING)) {
You("find a ring in the sink!");
(void) mkobj_at(RING_CLASS, u.ux, u.uy, TRUE);
levl[u.ux][u.uy].looted |= S_LRING;
exercise(A_WIS, TRUE);
newsym(u.ux, u.uy);
} else
pline("Some dirty %s backs up in the drain.", hliquid("water"));
break;
case 6:
breaksink(u.ux, u.uy);
break;
case 7:
pline_The("%s moves as though of its own will!", hliquid("water"));
if ((g.mvitals[PM_WATER_ELEMENTAL].mvflags & G_GONE)
|| !makemon(&mons[PM_WATER_ELEMENTAL], u.ux, u.uy, MM_NOMSG))
pline("But it quiets down.");
break;
case 8:
pline("Yuk, this %s tastes awful.", hliquid("water"));
more_experienced(1, 0);
newexplevel();
break;
case 9:
pline("Gaggg... this tastes like sewage! You vomit.");
morehungry(rn1(30 - ACURR(A_CON), 11));
vomit();
break;
case 10:
pline("This %s contains toxic wastes!", hliquid("water"));
if (!Unchanging) {
You("undergo a freakish metamorphosis!");
polyself(0);
}
break;
/* more odd messages --JJB */
case 11:
You_hear("clanking from the pipes...");
break;
case 12:
You_hear("snatches of song from among the sewers...");
break;
case 19:
if (Hallucination) {
pline("From the murky drain, a hand reaches up... --oops--");
break;
}
/*FALLTHRU*/
default:
You("take a sip of %s %s.",
rn2(3) ? (rn2(2) ? "cold" : "warm") : "hot",
hliquid("water"));
}
}
/*fountain.c*/