OSDN Git Service

add gitignore
[nethackexpress/trunk.git] / src / fountain.c
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
15 void
16 floating_above(what)
17 const char *what;
18 {
19     You("are floating high above the %s.", what);
20 }
21
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
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
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
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
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
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
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
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
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*/