1 /* NetHack 3.7	sounds.c	$NHDT-Date: 1600933442 2020/09/24 07:44:02 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.103 $ */
2 /*      Copyright (c) 1989 Janet Walz, Mike Threepoint */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 
7 static boolean mon_is_gecko(struct monst *);
8 static int domonnoise(struct monst *);
9 static int dochat(void);
10 static struct monst *responsive_mon_at(int, int);
11 static int mon_in_room(struct monst *, int);
12 
13 /* this easily could be a macro, but it might overtax dumb compilers */
14 static int
mon_in_room(struct monst * mon,int rmtyp)15 mon_in_room(struct monst* mon, int rmtyp)
16 {
17     int rno = levl[mon->mx][mon->my].roomno;
18     if (rno >= ROOMOFFSET)
19         return g.rooms[rno - ROOMOFFSET].rtype == rmtyp;
20     return FALSE;
21 }
22 
23 /* Given an x and y space, return the type of the room there. */
24 int
getroomtype(xchar x,xchar y)25 getroomtype(xchar x, xchar y)
26 {
27     int rno = levl[x][y].roomno;
28     if (rno >= ROOMOFFSET) {
29         /* rtype is valid while the level is still being created and up until
30          * the player first enters the room. orig_rtype is only initialized late
31          * in level creation and is effectively valid only after the level is
32          * created. */
33         return g.in_mklev ? g.rooms[rno - ROOMOFFSET].rtype
34                           : g.rooms[rno - ROOMOFFSET].orig_rtype;
35     }
36     /* not a room */
37     return OROOM;
38 }
39 
40 
41 void
dosounds(void)42 dosounds(void)
43 {
44     register struct mkroom *sroom;
45     register int hallu, vx, vy;
46     struct monst *mtmp;
47 
48     if (Deaf || !flags.acoustics || u.uswallow || Underwater)
49         return;
50 
51     hallu = Hallucination ? 1 : 0;
52 
53     if (g.level.flags.nfountains && !rn2(400)) {
54         static const char *const fountain_msg[4] = {
55             "bubbling water.", "water falling on coins.",
56             "the splashing of a naiad.", "a soda fountain!",
57         };
58         You_hear1(fountain_msg[rn2(3) + hallu]);
59     }
60     if (g.level.flags.nsinks && !rn2(300)) {
61         static const char *const sink_msg[3] = {
62             "a slow drip.", "a gurgling noise.", "dishes being washed!",
63         };
64         You_hear1(sink_msg[rn2(2) + hallu]);
65     }
66     if (g.level.flags.has_court && !rn2(200)) {
67         static const char *const throne_msg[4] = {
68             "the tones of courtly conversation.",
69             "a sceptre pounded in judgment.",
70             "Someone shouts \"Off with %s head!\"", "Queen Beruthiel's cats!",
71         };
72         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
73             if (DEADMONSTER(mtmp))
74                 continue;
75             if ((mtmp->msleeping || is_lord(mtmp->data)
76                  || is_prince(mtmp->data)) && !is_animal(mtmp->data)
77                 && mon_in_room(mtmp, COURT)) {
78                 /* finding one is enough, at least for now */
79                 int which = rn2(3) + hallu;
80 
81                 if (which != 2)
82                     You_hear1(throne_msg[which]);
83                 else
84                     pline(throne_msg[2], uhis());
85                 return;
86             }
87         }
88     }
89     if (g.level.flags.has_swamp && !rn2(200)) {
90         static const char *const swamp_msg[3] = {
91             "hear mosquitoes!", "smell marsh gas!", /* so it's a smell...*/
92             "hear Donald Duck!",
93         };
94         You1(swamp_msg[rn2(2) + hallu]);
95         return;
96     }
97     if (g.level.flags.has_vault && !rn2(200)) {
98         if (!(sroom = search_special(VAULT))) {
99             /* strange ... */
100             g.level.flags.has_vault = 0;
101             return;
102         }
103         if (gd_sound())
104             switch (rn2(2) + hallu) {
105             case 1: {
106                 boolean gold_in_vault = FALSE;
107 
108                 for (vx = sroom->lx; vx <= sroom->hx; vx++)
109                     for (vy = sroom->ly; vy <= sroom->hy; vy++)
110                         if (g_at(vx, vy))
111                             gold_in_vault = TRUE;
112                 if (vault_occupied(u.urooms)
113                     != (ROOM_INDEX(sroom) + ROOMOFFSET)) {
114                     if (gold_in_vault)
115                         You_hear(!hallu
116                                      ? "someone counting gold coins."
117                                      : "the quarterback calling the play.");
118                     else
119                         You_hear("someone searching.");
120                     break;
121                 }
122             }
123                 /*FALLTHRU*/
124             case 0:
125                 You_hear("the footsteps of a guard on patrol.");
126                 break;
127             case 2:
128                 You_hear("Ebenezer Scrooge!");
129                 break;
130             }
131         return;
132     }
133     if (g.level.flags.has_beehive && !rn2(200)) {
134         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
135             if (DEADMONSTER(mtmp))
136                 continue;
137             if (is_bee(mtmp->data)
138                 && mon_in_room(mtmp, BEEHIVE)) {
139                 switch (rn2(2) + hallu) {
140                 case 0:
141                     You_hear("a low buzzing.");
142                     break;
143                 case 1:
144                     You_hear("an angry drone.");
145                     break;
146                 case 2:
147                     You_hear("bees in your %sbonnet!",
148                              uarmh ? "" : "(nonexistent) ");
149                     break;
150                 }
151                 return;
152             }
153         }
154     }
155     if (g.level.flags.has_morgue && !rn2(200)) {
156         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
157             if (DEADMONSTER(mtmp))
158                 continue;
159             if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
160                 && mon_in_room(mtmp, MORGUE)) {
161                 const char *hair = body_part(HAIR); /* hair/fur/scales */
162 
163                 switch (rn2(2) + hallu) {
164                 case 0:
165                     You("suddenly realize it is unnaturally quiet.");
166                     break;
167                 case 1:
168                     pline_The("%s on the back of your %s %s up.", hair,
169                               body_part(NECK), vtense(hair, "stand"));
170                     break;
171                 case 2:
172                     pline_The("%s on your %s %s to stand up.", hair,
173                               body_part(HEAD), vtense(hair, "seem"));
174                     break;
175                 }
176                 return;
177             }
178         }
179     }
180     if (g.level.flags.has_barracks && !rn2(200)) {
181         static const char *const barracks_msg[4] = {
182             "blades being honed.", "loud snoring.", "dice being thrown.",
183             "General MacArthur!",
184         };
185         int count = 0;
186 
187         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
188             if (DEADMONSTER(mtmp))
189                 continue;
190             if (is_mercenary(mtmp->data)
191 #if 0 /* don't bother excluding these */
192                 && !strstri(mtmp->data->pmnames[NEUTRAL], "watch")
193                 && !strstri(mtmp->data->pmnames[NEUTRAL], "guard")
194 #endif
195                 && mon_in_room(mtmp, BARRACKS)
196                 /* sleeping implies not-yet-disturbed (usually) */
197                 && (mtmp->msleeping || ++count > 5)) {
198                 You_hear1(barracks_msg[rn2(3) + hallu]);
199                 return;
200             }
201         }
202     }
203     if (g.level.flags.has_zoo && !rn2(200)) {
204         static const char *const zoo_msg[3] = {
205             "a sound reminiscent of an elephant stepping on a peanut.",
206             "a sound reminiscent of a seal barking.", "Doctor Dolittle!",
207         };
208         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
209             if (DEADMONSTER(mtmp))
210                 continue;
211             if ((mtmp->msleeping || is_animal(mtmp->data))
212                 && mon_in_room(mtmp, ZOO)) {
213                 You_hear1(zoo_msg[rn2(2) + hallu]);
214                 return;
215             }
216         }
217     }
218     if (g.level.flags.has_shop && !rn2(200)) {
219         if (!(sroom = search_special(ANY_SHOP))) {
220             /* strange... */
221             g.level.flags.has_shop = 0;
222             return;
223         }
224         if (tended_shop(sroom)
225             && !index(u.ushops, (int) (ROOM_INDEX(sroom) + ROOMOFFSET))) {
226             const char *name = shkname(sroom->resident);
227             struct eshk *eshkp = ESHK(sroom->resident);
228             if (!eshkp->visitct) {
229                 name = "someone";
230             }
231             static const char *const shop_msg[3] = {
232                 "%s cursing shoplifters.",
233                 "the chime of a cash register.", "Neiman and Marcus arguing!",
234             };
235             You_hear(shop_msg[rn2(2) + hallu], name);
236         }
237         return;
238     }
239     if (g.level.flags.has_temple && !rn2(200)
240         && !(Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) {
241         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
242             if (DEADMONSTER(mtmp))
243                 continue;
244             if (mtmp->ispriest && inhistemple(mtmp)
245                 /* priest must be active */
246                 && mtmp->mcanmove && !mtmp->msleeping
247                 /* hero must be outside this temple */
248                 && temple_occupied(u.urooms) != EPRI(mtmp)->shroom)
249                 break;
250         }
251         if (mtmp) {
252             /* Generic temple messages; no attempt to match topic or tone
253                to the pantheon involved, let alone to the specific deity.
254                These are assumed to be coming from the attending priest;
255                asterisk means that the priest must be capable of speech;
256                pound sign (octathorpe,&c--don't go there) means that the
257                priest and the altar must not be directly visible (we don't
258                care if telepathy or extended detection reveals that the
259                priest is not currently standing on the altar; he's mobile). */
260             static const char *const temple_msg[] = {
261                 "*someone praising %s.", "*someone beseeching %s.",
262                 "#an animal carcass being offered in sacrifice.",
263                 "*a strident plea for donations.",
264             };
265             const char *msg;
266             int trycount = 0, ax = EPRI(mtmp)->shrpos.x,
267                 ay = EPRI(mtmp)->shrpos.y;
268             boolean speechless = (mtmp->data->msound <= MS_ANIMAL),
269                     in_sight = canseemon(mtmp) || cansee(ax, ay);
270 
271             do {
272                 msg = temple_msg[rn2(SIZE(temple_msg) - 1 + hallu)];
273                 if (index(msg, '*') && speechless)
274                     continue;
275                 if (index(msg, '#') && in_sight)
276                     continue;
277                 break; /* msg is acceptable */
278             } while (++trycount < 50);
279             while (!letter(*msg))
280                 ++msg; /* skip control flags */
281             if (index(msg, '%'))
282                 You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
283             else
284                 You_hear1(msg);
285             return;
286         }
287     }
288     if (Is_oracle_level(&u.uz) && !rn2(400)) {
289         /* make sure the Oracle is still here */
290         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
291             if (DEADMONSTER(mtmp))
292                 continue;
293             if (mtmp->data == &mons[PM_ORACLE])
294                 break;
295         }
296         /* and don't produce silly effects when she's clearly visible */
297         if (mtmp && (hallu || !canseemon(mtmp))) {
298             static const char *const ora_msg[5] = {
299                 "a strange wind.",     /* Jupiter at Dodona */
300                 "convulsive ravings.", /* Apollo at Delphi */
301                 "snoring snakes.",     /* AEsculapius at Epidaurus */
302                 "someone say \"No more woodchucks!\"",
303                 "a loud ZOT!" /* both rec.humor.oracle */
304             };
305             You_hear1(ora_msg[rn2(3) + hallu * 2]);
306         }
307         return;
308     }
309     if (g.level.bonesinfo && !rn2(300)) {
310         struct cemetery *bp;
311         for (bp = g.level.bonesinfo; bp; bp = bp->next) {
312             if (!bp->bonesknown) {
313                 /* only give bones noises if there are still undiscovered bones
314                  * locations on the level */
315                 if (hallu) {
316                     You("have a cheery feeling.");
317                 }
318                 else {
319                     You("have an eerie feeling...");
320                 }
321                 break;
322             }
323         }
324         return;
325     }
326     if (!rn2(300)) {
327         branch *br = Is_branchlev(&u.uz);
328         if (br && In_mines(&br->end2) && !In_mines(&u.uz)) {
329             static const char *const mines_msgs[2] = {
330                 "a pick striking rock.", "someone singing 'Gold, gold, gold.'"
331             };
332             You_hear1(mines_msgs[0 + hallu]);
333             return;
334         }
335         else if (br && In_sokoban(&br->end2) && !In_sokoban(&u.uz)
336                  && !sokoban_solved(&br->end2)) {
337             static const char *const soko_msgs[2] = {
338                 "a deep rolling sound.", "a golfing giant."
339             };
340             You_hear1(soko_msgs[0 + hallu]);
341             return;
342         }
343         else if (br && In_V_tower(&br->end2) && !In_V_tower(&u.uz)
344                  && g.mvitals[PM_VLAD_THE_IMPALER].died == 0) {
345             static const char *const vlad_msgs[3] = {
346                 "the whispering of leathery wings.",
347                 "a horrible choking scream.",
348                 "a voice say \"I never drink... wine.\""
349             };
350             You_hear1(vlad_msgs[rn2(2) + hallu]);
351             return;
352         }
353     }
354     if (In_quest(&u.uz) && u.uz.dlevel >= qlocate_level.dlevel
355         && Role_if(PM_ARCHEOLOGIST) && !g.quest_status.touched_artifact
356         && !g.quest_status.met_nemesis && !rn2(300)) {
357         /* special sounds for Arc quest */
358         if (!Deaf) {
359             You_hear("another explosion.");
360         }
361         else {
362             pline("You feel the tremor from another explosion.");
363         }
364     }
365 }
366 
367 static const char *const h_sounds[] = {
368     "beep",   "boing",   "sing",   "belche", "creak",   "cough",
369     "rattle", "ululate", "pop",    "jingle", "sniffle", "tinkle",
370     "eep",    "clatter", "hum",    "sizzle", "twitter", "wheeze",
371     "rustle", "honk",    "lisp",   "yodel",  "coo",     "burp",
372     "moo",    "boom",    "murmur", "oink",   "quack",   "rumble",
373     "twang",  "bellow",  "toot",   "gargle", "hoot",    "warble"
374 };
375 
376 const char *
growl_sound(register struct monst * mtmp)377 growl_sound(register struct monst* mtmp)
378 {
379     const char *ret;
380 
381     switch (mtmp->data->msound) {
382     case MS_MEW:
383     case MS_HISS:
384         ret = "hiss";
385         break;
386     case MS_BARK:
387     case MS_GROWL:
388         ret = "growl";
389         break;
390     case MS_ROAR:
391         ret = "roar";
392         break;
393     case MS_BUZZ:
394         ret = "buzz";
395         break;
396     case MS_SQEEK:
397         ret = "squeal";
398         break;
399     case MS_SQAWK:
400         ret = "screech";
401         break;
402     case MS_NEIGH:
403         ret = "neigh";
404         break;
405     case MS_WAIL:
406         ret = "wail";
407         break;
408     case MS_GROAN:
409         ret = "groan";
410         break;
411     case MS_MOO:
412         ret = "low";
413         break;
414     case MS_SILENT:
415         ret = "commotion";
416         break;
417     default:
418         ret = "scream";
419     }
420     return ret;
421 }
422 
423 /* the sounds of a seriously abused pet, including player attacking it */
424 void
growl(register struct monst * mtmp)425 growl(register struct monst* mtmp)
426 {
427     register const char *growl_verb = 0;
428 
429     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
430         return;
431 
432     /* presumably nearness and soundok checks have already been made */
433     if (Hallucination)
434         growl_verb = h_sounds[rn2(SIZE(h_sounds))];
435     else
436         growl_verb = growl_sound(mtmp);
437     if (growl_verb) {
438         pline("%s %s!", Monnam(mtmp), vtense((char *) 0, growl_verb));
439         iflags.last_msg = PLNMSG_GROWL;
440         if (g.context.run)
441             nomul(0);
442         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18);
443     }
444 }
445 
446 /* the sounds of mistreated pets */
447 void
yelp(register struct monst * mtmp)448 yelp(register struct monst* mtmp)
449 {
450     register const char *yelp_verb = 0;
451 
452     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
453         return;
454 
455     /* presumably nearness and soundok checks have already been made */
456     if (Hallucination)
457         yelp_verb = h_sounds[rn2(SIZE(h_sounds))];
458     else
459         switch (mtmp->data->msound) {
460         case MS_MEW:
461             yelp_verb = (!Deaf) ? "yowl" : "arch";
462             break;
463         case MS_BARK:
464         case MS_GROWL:
465             yelp_verb = (!Deaf) ? "yelp" : "recoil";
466             break;
467         case MS_ROAR:
468             yelp_verb = (!Deaf) ? "roar" : "bluff";
469             break;
470         case MS_SQEEK:
471             yelp_verb = (!Deaf) ? "squeal" : "quiver";
472             break;
473         case MS_SQAWK:
474             yelp_verb = (!Deaf) ? "screak" : "thrash";
475             break;
476         case MS_WAIL:
477             yelp_verb = (!Deaf) ? "wail" : "cringe";
478             break;
479         }
480     if (yelp_verb) {
481         pline("%s %s!", Monnam(mtmp), vtense((char *) 0, yelp_verb));
482         if (g.context.run)
483             nomul(0);
484         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
485     }
486 }
487 
488 /* the sounds of distressed pets */
489 void
whimper(register struct monst * mtmp)490 whimper(register struct monst* mtmp)
491 {
492     register const char *whimper_verb = 0;
493 
494     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
495         return;
496 
497     /* presumably nearness and soundok checks have already been made */
498     if (Hallucination)
499         whimper_verb = h_sounds[rn2(SIZE(h_sounds))];
500     else
501         switch (mtmp->data->msound) {
502         case MS_MEW:
503         case MS_GROWL:
504             whimper_verb = "whimper";
505             break;
506         case MS_BARK:
507             whimper_verb = "whine";
508             break;
509         case MS_SQEEK:
510             whimper_verb = "squeal";
511             break;
512         }
513     if (whimper_verb) {
514         pline("%s %s.", Monnam(mtmp), vtense((char *) 0, whimper_verb));
515         if (g.context.run)
516             nomul(0);
517         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6);
518     }
519 }
520 
521 /* pet makes "I'm hungry" noises */
522 void
beg(register struct monst * mtmp)523 beg(register struct monst* mtmp)
524 {
525     if (mtmp->msleeping || !mtmp->mcanmove
526         || !(carnivorous(mtmp->data) || herbivorous(mtmp->data)))
527         return;
528 
529     /* presumably nearness and soundok checks have already been made */
530     if (!is_silent(mtmp->data) && mtmp->data->msound <= MS_ANIMAL) {
531         (void) domonnoise(mtmp);
532     } else if (mtmp->data->msound >= MS_HUMANOID) {
533         if (!canspotmon(mtmp))
534             map_invisible(mtmp->mx, mtmp->my);
535         verbalize("I'm hungry.");
536     } else {
537         /* this is pretty lame but is better than leaving out the block
538            of speech types between animal and humanoid; this covers
539            MS_SILENT too (if caller lets that get this far) since it's
540            excluded by the first two cases */
541         if (canspotmon(mtmp))
542             pline("%s seems famished.", Monnam(mtmp));
543         /* looking famished will be a good trick for a tame skeleton... */
544     }
545 }
546 
547 /* hero has attacked a peaceful monster within 'mon's view */
548 const char *
maybe_gasp(struct monst * mon)549 maybe_gasp(struct monst* mon)
550 {
551     static const char *const Exclam[] = {
552         "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
553     };
554     struct permonst *mptr = mon->data;
555     int msound = mptr->msound;
556     boolean dogasp = FALSE;
557 
558     /* other roles' guardians and cross-aligned priests don't gasp */
559     if ((msound == MS_GUARDIAN && mptr != &mons[g.urole.guardnum])
560         || (msound == MS_PRIEST && !p_coaligned(mon)))
561         msound = MS_SILENT;
562     /* co-aligned angels do gasp */
563     else if (msound == MS_CUSS && has_emin(mon)
564            && (p_coaligned(mon) ? !EMIN(mon)->renegade : EMIN(mon)->renegade))
565         msound = MS_HUMANOID;
566 
567     /*
568      * Only called for humanoids so animal noise handling is ignored.
569      */
570     switch (msound) {
571     case MS_HUMANOID:
572     case MS_ARREST: /* Kops */
573     case MS_SOLDIER: /* solider, watchman */
574     case MS_GUARD: /* vault guard */
575     case MS_NURSE:
576     case MS_SEDUCE: /* nymph, succubus/incubus */
577     case MS_LEADER: /* quest leader */
578     case MS_GUARDIAN: /* leader's guards */
579     case MS_SELL: /* shopkeeper */
580     case MS_ORACLE:
581     case MS_PRIEST: /* temple priest, roaming aligned priest (not mplayer) */
582     case MS_BOAST: /* giants */
583     case MS_IMITATE: /* doppelganger, leocrotta, Aleax */
584         dogasp = TRUE;
585         break;
586     /* issue comprehensible word(s) if hero is similar type of creature */
587     case MS_ORC: /* used to be synonym for MS_GRUNT */
588     case MS_GRUNT: /* ogres, trolls, gargoyles, one or two others */
589     case MS_LAUGH: /* leprechaun, gremlin */
590     case MS_ROAR: /* dragon, xorn, owlbear */
591     /* capable of speech but only do so if hero is similar type */
592     case MS_DJINNI:
593     case MS_VAMPIRE: /* vampire in its own form */
594     case MS_WERE: /* lycanthrope in human form */
595     case MS_SPELL: /* titan, barrow wight, Nazgul, nalfeshnee */
596         dogasp = (mptr->mlet == g.youmonst.data->mlet);
597         break;
598     /* capable of speech but don't care if you attack peacefuls */
599     case MS_BRIBE:
600     case MS_CUSS:
601     case MS_RIDER:
602     case MS_NEMESIS:
603     /* can't speak */
604     case MS_SILENT:
605     default:
606         break;
607     }
608     if (dogasp) {
609         return Exclam[rn2(SIZE(Exclam))]; /* [mon->m_id % SIZE(Exclam)]; */
610     }
611     return (const char *) 0;
612 }
613 
614 /* return True if mon is a gecko or seems to look like one (hallucination) */
615 static boolean
mon_is_gecko(struct monst * mon)616 mon_is_gecko(struct monst* mon)
617 {
618     int glyph;
619 
620     /* return True if it is actually a gecko */
621     if (mon->data == &mons[PM_GECKO])
622         return TRUE;
623     /* return False if it is a long worm; we might be chatting to its tail
624        (not strictly needed; long worms are MS_SILENT so won't get here) */
625     if (mon->data == &mons[PM_LONG_WORM])
626         return FALSE;
627     /* result depends upon whether map spot shows a gecko, which will
628        be due to hallucination or to mimickery since mon isn't one */
629     glyph = glyph_at(mon->mx, mon->my);
630     return (boolean) (glyph_to_mon(glyph) == PM_GECKO);
631 }
632 
633 DISABLE_WARNING_FORMAT_NONLITERAL
634 
635 static int
domonnoise(register struct monst * mtmp)636 domonnoise(register struct monst* mtmp)
637 {
638     char verbuf[BUFSZ];
639     register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
640         *verbl_msg = 0,                 /* verbalize() */
641         *verbl_msg_mcan = 0;            /* verbalize() if cancelled */
642     struct permonst *ptr = mtmp->data;
643     int msound = ptr->msound, gnomeplan = 0;
644 
645     /* presumably nearness and sleep checks have already been made */
646     if (Deaf)
647         return 0;
648     if (is_silent(ptr))
649         return 0;
650 
651     /* leader might be poly'd; if he can still speak, give leader speech */
652     if (mtmp->m_id == g.quest_status.leader_m_id && msound > MS_ANIMAL)
653         msound = MS_LEADER;
654     /* make sure it's your role's quest guardian; adjust if not */
655     else if (msound == MS_GUARDIAN && ptr != &mons[g.urole.guardnum])
656         msound = mons[genus(monsndx(ptr), 1)].msound;
657     /* some normally non-speaking types can/will speak if hero is similar */
658     else if (msound == MS_ORC
659              && ((same_race(ptr, g.youmonst.data)        /* current form, */
660                   || same_race(ptr, &mons[Race_switch])) /* unpoly'd form */
661                  || Hallucination))
662         msound = MS_HUMANOID;
663     /* silliness, with slight chance to interfere with shopping */
664     else if (Hallucination && mon_is_gecko(mtmp))
665         msound = MS_SELL;
666 
667     /* be sure to do this before talking; the monster might teleport away, in
668      * which case we want to check its pre-teleport position
669      */
670     if (!canspotmon(mtmp))
671         map_invisible(mtmp->mx, mtmp->my);
672 
673     switch (msound) {
674     case MS_ORACLE:
675         return doconsult(mtmp);
676     case MS_PRIEST:
677         priest_talk(mtmp);
678         break;
679     case MS_LEADER:
680     case MS_NEMESIS:
681     case MS_GUARDIAN:
682         quest_chat(mtmp);
683         break;
684     case MS_SELL: /* pitch, pay, total */
685         if (!Hallucination || (mtmp->isshk && !rn2(2))) {
686             shk_chat(mtmp);
687         } else {
688             /* approximation of GEICO's advertising slogan (it actually
689                concludes with "save you 15% or more on car insurance.") */
690             Strcat(verbuf, "15 minutes could save you 15 zorkmids.");
691         }
692         break;
693     case MS_VAMPIRE: {
694         /* vampire messages are varied by tameness, peacefulness, and time of
695          * night */
696         boolean isnight = night();
697         boolean kindred = (Upolyd && (u.umonnum == PM_VAMPIRE
698                                       || u.umonnum == PM_VAMPIRE_LEADER));
699         boolean nightchild =
700             (Upolyd && (u.umonnum == PM_WOLF || u.umonnum == PM_WINTER_WOLF
701                         || u.umonnum == PM_WINTER_WOLF_CUB));
702         const char *racenoun =
703             (flags.female && g.urace.individual.f)
704                 ? g.urace.individual.f
705                 : (g.urace.individual.m) ? g.urace.individual.m : g.urace.noun;
706 
707         if (mtmp->mtame) {
708             if (kindred) {
709                 Sprintf(verbuf, "Good %s to you Master%s",
710                         isnight ? "evening" : "day",
711                         isnight ? "!" : ".  Why do we not rest?");
712                 verbl_msg = verbuf;
713             } else {
714                 Sprintf(verbuf, "%s%s",
715                         nightchild ? "Child of the night, " : "",
716                         midnight()
717                          ? "I can stand this craving no longer!"
718                          : isnight
719                           ? "I beg you, help me satisfy this growing craving!"
720                           : "I find myself growing a little weary.");
721                 verbl_msg = verbuf;
722             }
723         } else if (mtmp->mpeaceful) {
724             if (kindred && isnight) {
725                 Sprintf(verbuf, "Good feeding %s!",
726                         flags.female ? "sister" : "brother");
727                 verbl_msg = verbuf;
728             } else if (nightchild && isnight) {
729                 Sprintf(verbuf, "How nice to hear you, child of the night!");
730                 verbl_msg = verbuf;
731             } else
732                 verbl_msg = "I only drink... potions.";
733         } else {
734             static const char *const vampmsg[] = {
735                 /* These first two (0 and 1) are specially handled below */
736                 "I vant to suck your %s!",
737                 "I vill come after %s without regret!",
738                 /* other famous vampire quotes can follow here if desired */
739             };
740             int vampindex;
741 
742             if (kindred)
743                 verbl_msg =
744                     "This is my hunting ground that you dare to prowl!";
745             else if (g.youmonst.data == &mons[PM_SILVER_DRAGON]
746                      || g.youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
747                 /* Silver dragons are silver in color, not made of silver */
748                 Sprintf(verbuf, "%s!  Your silver sheen does not frighten me!",
749                         g.youmonst.data == &mons[PM_SILVER_DRAGON]
750                             ? "Fool"
751                             : "Young Fool");
752                 verbl_msg = verbuf;
753             } else {
754                 vampindex = rn2(SIZE(vampmsg));
755                 if (vampindex == 0) {
756                     Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
757                     verbl_msg = verbuf;
758                 } else if (vampindex == 1) {
759                     Sprintf(verbuf, vampmsg[vampindex],
760                             Upolyd ? an(pmname(&mons[u.umonnum],
761                                                flags.female ? FEMALE : MALE))
762                                    : an(racenoun));
763                     verbl_msg = verbuf;
764                 } else
765                     verbl_msg = vampmsg[vampindex];
766             }
767         }
768         break;
769     }
770     case MS_WERE:
771         if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
772             pline("%s throws back %s head and lets out a blood curdling %s!",
773                   Monnam(mtmp), mhis(mtmp),
774                   (ptr == &mons[PM_HUMAN_WERERAT]) ? "shriek" : "howl");
775             wake_nearto(mtmp->mx, mtmp->my, 11 * 11);
776         } else
777             pline_msg =
778                 "whispers inaudibly.  All you can make out is \"moon\".";
779         break;
780     case MS_BARK:
781         if (flags.moonphase == FULL_MOON && night()) {
782             pline_msg = "howls.";
783         } else if (mtmp->mpeaceful) {
784             if (mtmp->mtame
785                 && (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
786                     || g.moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
787                 pline_msg = "whines.";
788             else if (mtmp->mtame && EDOG(mtmp)->hungrytime > g.moves + 1000)
789                 pline_msg = "yips.";
790             else {
791                 if (mtmp->data
792                     != &mons[PM_DINGO]) /* dingos do not actually bark */
793                     pline_msg = "barks.";
794             }
795         } else {
796             pline_msg = "growls.";
797         }
798         break;
799     case MS_MEW:
800         if (mtmp->mtame) {
801             if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
802                 || mtmp->mtame < 5)
803                 pline_msg = "yowls.";
804             else if (g.moves > EDOG(mtmp)->hungrytime)
805                 pline_msg = "meows.";
806             else if (EDOG(mtmp)->hungrytime > g.moves + 1000)
807                 pline_msg = "purrs.";
808             else
809                 pline_msg = "mews.";
810             break;
811         }
812         /*FALLTHRU*/
813     case MS_GROWL:
814         pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
815         break;
816     case MS_ROAR:
817         pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
818         break;
819     case MS_SQEEK:
820         pline_msg = "squeaks.";
821         break;
822     case MS_SQAWK:
823         if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
824             verbl_msg = "Nevermore!";
825         else
826             pline_msg = "squawks.";
827         break;
828     case MS_HISS:
829         if (!mtmp->mpeaceful)
830             pline_msg = "hisses!";
831         else
832             return 0; /* no sound */
833         break;
834     case MS_BUZZ:
835         pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
836         break;
837     case MS_GRUNT:
838         pline_msg = "grunts.";
839         break;
840     case MS_NEIGH:
841         if (mtmp->mtame < 5)
842             pline_msg = "neighs.";
843         else if (g.moves > EDOG(mtmp)->hungrytime)
844             pline_msg = "whinnies.";
845         else
846             pline_msg = "whickers.";
847         break;
848     case MS_MOO:
849         pline_msg = mtmp->mpeaceful ? "moos." : "bellows!";
850         break;
851     case MS_WAIL:
852         pline_msg = "wails mournfully.";
853         break;
854     case MS_GROAN:
855         if (rn2(10) || !(ptr->mlet == S_ZOMBIE))
856             pline_msg = "groans.";
857         else
858             verbl_msg = "Braaaaaains...";
859 	break;
860     case MS_GURGLE:
861         pline_msg = "gurgles.";
862         break;
863     case MS_BURBLE:
864         pline_msg = "burbles.";
865         break;
866     case MS_TRUMPET:
867         pline_msg = "trumpets!";
868         wake_nearto(mtmp->mx, mtmp->my, 11 * 11);
869         break;
870     case MS_SHRIEK:
871         pline_msg = "shrieks.";
872         aggravate();
873         break;
874     case MS_IMITATE:
875         pline_msg = "imitates you.";
876         break;
877     case MS_BONES:
878         pline("%s rattles noisily.", Monnam(mtmp));
879         You("freeze for a moment.");
880         nomul(-2);
881         g.multi_reason = "scared by rattling";
882         g.nomovemsg = 0;
883         break;
884     case MS_LAUGH: {
885         static const char *const laugh_msg[4] = {
886             "giggles.", "chuckles.", "snickers.", "laughs.",
887         };
888         pline_msg = laugh_msg[rn2(4)];
889         break;
890     }
891     case MS_MUMBLE:
892         pline_msg = "mumbles incomprehensibly.";
893         break;
894     case MS_ORC: /* this used to be an alias for grunt, now it is distinct */
895         pline_msg = "grunts.";
896         break;
897     case MS_DJINNI:
898         if (mtmp->mtame) {
899             verbl_msg = "Sorry, I'm all out of wishes.";
900         } else if (mtmp->mpeaceful) {
901             if (ptr == &mons[PM_WATER_DEMON])
902                 pline_msg = "gurgles.";
903             else
904                 verbl_msg = "I'm free!";
905         } else {
906             if (ptr != &mons[PM_PRISONER])
907                 verbl_msg = "This will teach you not to disturb me!";
908             else /* vague because prisoner might already be out of cell */
909                 verbl_msg = "Get me out of here.";
910         }
911         break;
912     case MS_BOAST: /* giants */
913         if (!mtmp->mpeaceful) {
914             switch (rn2(4)) {
915             case 0:
916                 pline("%s boasts about %s gem collection.", Monnam(mtmp),
917                       mhis(mtmp));
918                 break;
919             case 1:
920                 pline_msg = "complains about a diet of mutton.";
921                 break;
922             default:
923                 pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
924                 wake_nearto(mtmp->mx, mtmp->my, 7 * 7);
925                 break;
926             }
927             break;
928         }
929         /*FALLTHRU*/
930     case MS_HUMANOID:
931         if (!mtmp->mpeaceful) {
932             if (In_endgame(&u.uz) && is_mplayer(ptr))
933                 mplayer_talk(mtmp);
934             else
935                 pline_msg = "threatens you.";
936             break;
937         }
938         /* Generic peaceful humanoid behaviour. */
939         if (mtmp->mflee)
940             pline_msg = "wants nothing to do with you.";
941         else if (mtmp->mhp < mtmp->mhpmax / 4)
942             pline_msg = "moans.";
943         else if (mtmp->mconf || mtmp->mstun)
944             verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
945         else if (!mtmp->mcansee)
946             verbl_msg = "I can't see!";
947         else if (mtmp->mtrapped) {
948             struct trap *t = t_at(mtmp->mx, mtmp->my);
949 
950             if (t)
951                 t->tseen = 1;
952             verbl_msg = "I'm trapped!";
953         } else if (mtmp->mhp < mtmp->mhpmax / 2)
954             pline_msg = "asks for a potion of healing.";
955         else if (mtmp->mtame && !mtmp->isminion
956                  && g.moves > EDOG(mtmp)->hungrytime)
957             verbl_msg = "I'm hungry.";
958         /* Specific monsters' interests */
959         else if (is_elf(ptr))
960             pline_msg = "curses orcs.";
961         else if (is_dwarf(ptr))
962             pline_msg = "talks about mining.";
963         else if (is_gnome(ptr))
964             verbl_msg =
965                 "Many enter the dungeon, and few return to the sunlit lands.";
966         else if (likes_magic(ptr))
967             pline_msg = "talks about spellcraft.";
968         else if (ptr->mlet == S_CENTAUR)
969             pline_msg = "discusses hunting.";
970         else if (is_gnome(ptr)) {
971             if (Hallucination && (gnomeplan = rn2(4)) % 2) {
972                 /* skipped for rn2(4) result of 0 or 2;
973                    gag from an early episode of South Park called "Gnomes";
974                    initially, Tweek (introduced in that episode) is the only
975                    one aware of the tiny gnomes after spotting them sneaking
976                    about; they are embarked upon a three-step business plan;
977                    a diagram of the plan shows:
978                                Phase 1         Phase 2      Phase 3
979                          Collect underpants       ?          Profit
980                    and they never verbalize step 2 so we don't either */
981                 verbl_msg = (gnomeplan == 1) ? "Phase one, collect underpants."
982                                              : "Phase three, profit!";
983             }
984             else {
985                 verbl_msg =
986                 "Many enter the dungeon, and few return to the sunlit lands.";
987             }
988         }
989         else
990             switch (monsndx(ptr)) {
991             case PM_HOBBIT:
992                 pline_msg =
993                     (mtmp->mhpmax - mtmp->mhp >= 10)
994                         ? "complains about unpleasant dungeon conditions."
995                         : "asks you about the One Ring.";
996                 break;
997             case PM_ARCHEOLOGIST:
998                 pline_msg =
999                 "describes a recent article in \"Spelunker Today\" magazine.";
1000                 break;
1001             case PM_TOURIST:
1002                 verbl_msg = "Aloha.";
1003                 break;
1004             default:
1005                 pline_msg = "discusses dungeon exploration.";
1006                 break;
1007             }
1008         break;
1009     case MS_SEDUCE: {
1010         int swval;
1011 
1012         if (SYSOPT_SEDUCE) {
1013             if (ptr->mlet != S_NYMPH
1014                 && could_seduce(mtmp, &g.youmonst, (struct attack *) 0) == 1) {
1015                 (void) doseduce(mtmp);
1016                 break;
1017             }
1018             swval = ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0);
1019         } else
1020             swval = ((poly_gender() == 0) ? rn2(3) : 0);
1021         switch (swval) {
1022         case 2:
1023             verbl_msg = "Hello, sailor.";
1024             break;
1025         case 1:
1026             pline_msg = "comes on to you.";
1027             break;
1028         default:
1029             pline_msg = "cajoles you.";
1030         }
1031     } break;
1032     case MS_ARREST:
1033         if (mtmp->mpeaceful)
1034             verbalize("Just the facts, %s.", flags.female ? "Ma'am" : "Sir");
1035         else {
1036             static const char *const arrest_msg[3] = {
1037                 "Anything you say can be used against you.",
1038                 "You're under arrest!", "Stop in the name of the Law!",
1039             };
1040             verbl_msg = arrest_msg[rn2(3)];
1041         }
1042         break;
1043     case MS_BRIBE:
1044         if (mtmp->mpeaceful && !mtmp->mtame) {
1045             (void) demon_talk(mtmp);
1046             break;
1047         }
1048     /* fall through */
1049     case MS_CUSS:
1050         if (!mtmp->mpeaceful)
1051             cuss(mtmp);
1052         else if (is_lminion(mtmp))
1053             verbl_msg = "It's not too late.";
1054         else
1055             verbl_msg = "We're all doomed.";
1056         break;
1057     case MS_SPELL:
1058         /* deliberately vague, since it's not actually casting any spell */
1059         pline_msg = "seems to mutter a cantrip.";
1060         break;
1061     case MS_NURSE:
1062         verbl_msg_mcan = "I hate this job!";
1063         if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
1064             verbl_msg = "Put that weapon away before you hurt someone!";
1065         else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
1066             verbl_msg = Role_if(PM_HEALER)
1067                             ? "Doc, I can't help you unless you cooperate."
1068                             : "Please undress so I can examine you.";
1069         else if (uarmu)
1070             verbl_msg = "Take off your shirt, please.";
1071         else
1072             verbl_msg = "Relax, this won't hurt a bit.";
1073         break;
1074     case MS_GUARD:
1075         if (money_cnt(g.invent))
1076             verbl_msg = "Please drop that gold and follow me.";
1077         else
1078             verbl_msg = "Please follow me.";
1079         break;
1080     case MS_SOLDIER: {
1081         static const char
1082             *const soldier_foe_msg[3] = {
1083                 "Resistance is useless!", "You're dog meat!", "Surrender!",
1084             },
1085             *const soldier_pax_msg[3] = {
1086                 "What lousy pay we're getting here!",
1087                 "The food's not fit for Orcs!",
1088                 "My feet hurt, I've been on them all day!",
1089             };
1090         verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
1091                                     : soldier_foe_msg[rn2(3)];
1092         break;
1093     }
1094     case MS_RIDER: {
1095         const char *tribtitle;
1096         struct obj *book = 0;
1097         boolean ms_Death = (ptr == &mons[PM_DEATH]);
1098 
1099         /* 3.6 tribute */
1100         if (ms_Death && !g.context.tribute.Deathnotice
1101             && (book = u_have_novel()) != 0) {
1102             if ((tribtitle = noveltitle(&book->novelidx)) != 0) {
1103                 Sprintf(verbuf, "Ah, so you have a copy of /%s/.", tribtitle);
1104                 /* no Death featured in these two, so exclude them */
1105                 if (strcmpi(tribtitle, "Snuff")
1106                     && strcmpi(tribtitle, "The Wee Free Men"))
1107                     Strcat(verbuf, "  I may have been misquoted there.");
1108                 verbl_msg = verbuf;
1109             }
1110             g.context.tribute.Deathnotice = 1;
1111         } else if (ms_Death && rn2(3) && Death_quote(verbuf, sizeof verbuf)) {
1112             verbl_msg = verbuf;
1113         /* end of tribute addition */
1114 
1115         } else if (ms_Death && !rn2(10)) {
1116             pline_msg = "is busy reading a copy of Sandman #8.";
1117         } else
1118             verbl_msg = "Who do you think you are, War?";
1119         break;
1120     } /* case MS_RIDER */
1121     } /* switch */
1122 
1123     if (pline_msg) {
1124         pline("%s %s", Monnam(mtmp), pline_msg);
1125     } else if (mtmp->mcan && verbl_msg_mcan) {
1126         verbalize1(verbl_msg_mcan);
1127     } else if (verbl_msg) {
1128         /* more 3.6 tribute */
1129         if (ptr == &mons[PM_DEATH]) {
1130             /* Death talks in CAPITAL LETTERS
1131                and without quotation marks */
1132             char tmpbuf[BUFSZ];
1133 
1134             pline1(ucase(strcpy(tmpbuf, verbl_msg)));
1135         } else {
1136             verbalize1(verbl_msg);
1137         }
1138     }
1139     return 1;
1140 }
1141 
1142 RESTORE_WARNING_FORMAT_NONLITERAL
1143 
1144 /* #chat command */
1145 int
dotalk(void)1146 dotalk(void)
1147 {
1148     int result;
1149 
1150     result = dochat();
1151     return result;
1152 }
1153 
1154 static int
dochat(void)1155 dochat(void)
1156 {
1157     struct monst *mtmp;
1158     int tx, ty;
1159     struct obj *otmp;
1160 
1161     if (is_silent(g.youmonst.data)) {
1162         pline("As %s, you cannot speak.",
1163               an(pmname(g.youmonst.data, flags.female ? FEMALE : MALE)));
1164         return 0;
1165     }
1166     if (Strangled) {
1167         You_cant("speak.  You're choking!");
1168         return 0;
1169     }
1170     if (u.uswallow) {
1171         pline("They won't hear you out there.");
1172         return 0;
1173     }
1174     if (Underwater) {
1175         Your("speech is unintelligible underwater.");
1176         return 0;
1177     }
1178     if (Deaf) {
1179         pline("How can you hold a conversation when you cannot hear?");
1180         return 0;
1181     }
1182 
1183     if (!Blind && (otmp = shop_object(u.ux, u.uy)) != (struct obj *) 0) {
1184         /* standing on something in a shop and chatting causes the shopkeeper
1185            to describe the price(s).  This can inhibit other chatting inside
1186            a shop, but that shouldn't matter much.  shop_object() returns an
1187            object iff inside a shop and the shopkeeper is present and willing
1188            (not angry) and able (not asleep) to speak and the position
1189            contains any objects other than just gold.
1190         */
1191         price_quote(otmp);
1192         return 1;
1193     }
1194 
1195     if (!getdir("Talk to whom? (in what direction)")) {
1196         /* decided not to chat */
1197         return 0;
1198     }
1199 
1200     if (u.usteed && u.dz > 0) {
1201         if (!u.usteed->mcanmove || u.usteed->msleeping) {
1202             pline("%s seems not to notice you.", Monnam(u.usteed));
1203             return 1;
1204         } else
1205             return domonnoise(u.usteed);
1206     }
1207 
1208     if (u.dz) {
1209         pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
1210         return 0;
1211     }
1212 
1213     if (u.dx == 0 && u.dy == 0) {
1214         /*
1215          * Let's not include this.
1216          * It raises all sorts of questions: can you wear
1217          * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
1218          * etc...  --KAA
1219         if (u.umonnum == PM_ETTIN) {
1220             You("discover that your other head makes boring conversation.");
1221             return 1;
1222         }
1223          */
1224         pline("Talking to yourself is a bad habit for a dungeoneer.");
1225         return 0;
1226     }
1227 
1228     tx = u.ux + u.dx;
1229     ty = u.uy + u.dy;
1230 
1231     if (!isok(tx, ty))
1232         return 0;
1233 
1234     mtmp = m_at(tx, ty);
1235 
1236     if (!mtmp || mtmp->mundetected) {
1237         if ((otmp = vobj_at(tx, ty)) != 0 && otmp->otyp == STATUE) {
1238             /* Talking to a statue */
1239             if (!Blind)
1240                 pline_The("%s seems not to notice you.",
1241                           /* if hallucinating, you can't tell it's a statue */
1242                           Hallucination ? rndmonnam((char *) 0) : "statue");
1243             return 0;
1244         }
1245         if (IS_WALL(levl[tx][ty].typ) || levl[tx][ty].typ == SDOOR) {
1246             /* Talking to a wall; secret door remains hidden by behaving
1247                like a wall; IS_WALL() test excludes solid rock even when
1248                that serves as a wall bordering a corridor */
1249             if (Blind && !IS_WALL(g.lastseentyp[tx][ty])) {
1250                 /* when blind, you can only talk to a wall if it has
1251                    already been mapped as a wall */
1252                 ;
1253             } else if (!Hallucination) {
1254                 /* Walls have ears, not mouths. */
1255                 pline(rn2(2) ? "The wall listens intently, but doesn't reply."
1256                              : "It's like talking to a wall.");
1257             } else {
1258                 static const char *const walltalk[] = {
1259                     "gripes about its job.",
1260                     "tells you a funny joke!",
1261                     "insults your heritage!",
1262                     "chuckles.",
1263                     "guffaws merrily!",
1264                     "deprecates your exploration efforts.",
1265                     "suggests a stint of rehab...",
1266                     "doesn't seem to be interested.",
1267                 };
1268                 int idx = rn2(10);
1269 
1270                 if (idx >= SIZE(walltalk))
1271                     idx = SIZE(walltalk) - 1;
1272                 pline_The("wall %s", walltalk[idx]);
1273             }
1274             return 0;
1275         }
1276     }
1277 
1278     if (!mtmp || mtmp->mundetected
1279         || M_AP_TYPE(mtmp) == M_AP_FURNITURE
1280         || M_AP_TYPE(mtmp) == M_AP_OBJECT)
1281         return 0;
1282 
1283     /* sleeping monsters won't talk, except priests (who wake up) */
1284     if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
1285         /* If it is unseen, the player can't tell the difference between
1286            not noticing him and just not existing, so skip the message. */
1287         if (canspotmon(mtmp))
1288             pline("%s seems not to notice you.", Monnam(mtmp));
1289         return 0;
1290     }
1291 
1292     /* if this monster is waiting for something, prod it into action */
1293     mtmp->mstrategy &= ~STRAT_WAITMASK;
1294 
1295     if (mtmp->mtame && mtmp->meating) {
1296         if (!canspotmon(mtmp))
1297             map_invisible(mtmp->mx, mtmp->my);
1298         pline("%s is eating noisily.", Monnam(mtmp));
1299         return 0;
1300     }
1301 
1302     return domonnoise(mtmp);
1303 }
1304 
1305 /* is there a monster at <x,y> that can see the hero and react? */
1306 static struct monst *
responsive_mon_at(int x,int y)1307 responsive_mon_at(int x, int y)
1308 {
1309     struct monst *mtmp = isok(x, y) ? m_at(x, y) : 0;
1310 
1311     if (mtmp && (!mtmp->mcanmove || mtmp->msleeping /* immobilized monst */
1312                  || !mtmp->mcansee || !haseyes(mtmp->data) /* blind monst */
1313                  || (Invis && !perceives(mtmp->data)) /* unseen hero */
1314                  || (x != mtmp->mx || y != mtmp->my))) /* worm tail */
1315         mtmp = (struct monst *) 0;
1316     return mtmp;
1317 }
1318 
1319 /* player chose 'uarmh' for #tip (pickup.c); visual #chat, sort of... */
1320 int
tiphat(void)1321 tiphat(void)
1322 {
1323     struct monst *mtmp;
1324     struct obj *otmp;
1325     int x, y, range, glyph, vismon, unseen, statue, res;
1326 
1327     if (!uarmh) /* can't get here from there */
1328         return 0;
1329 
1330     res = uarmh->bknown ? 0 : 1;
1331     if (cursed(uarmh)) /* "You can't.  It is cursed." */
1332         return res; /* if learned of curse, use a move */
1333 
1334     /* might choose a position, but dealing with direct lines is simpler */
1335     if (!getdir("At whom? (in what direction)")) /* bail on ESC */
1336         return res; /* iffy; now know it's not cursed for sure (since we got
1337                      * past prior test) but might have already known that */
1338     res = 1; /* physical action is going to take place */
1339 
1340     /* most helmets have a short wear/take-off delay and we could set
1341        'multi' to account for that, but we'll pretend that no extra time
1342        beyond the current move is necessary */
1343     You("briefly doff your %s.", helm_simple_name(uarmh));
1344 
1345     if (!u.dx && !u.dy) {
1346         if (u.usteed && u.dz > 0) {
1347             if (!u.usteed->mcanmove || u.usteed->msleeping)
1348                 pline("%s doesn't notice.", Monnam(u.usteed));
1349             else
1350                 (void) domonnoise(u.usteed);
1351         } else if (u.dz) {
1352             pline("There's no one %s there.", (u.dz < 0) ? "up" : "down");
1353         } else {
1354             pline_The("lout here doesn't acknowledge you...");
1355         }
1356         return res;
1357     }
1358 
1359     mtmp = (struct monst *) 0;
1360     vismon = unseen = statue = 0, glyph = GLYPH_MON_OFF;
1361     x = u.ux, y = u.uy;
1362     for (range = 1; range <= BOLT_LIM + 1; ++range) {
1363         x += u.dx, y += u.dy;
1364         if (!isok(x, y) || (range > 1 && !couldsee(x, y))) {
1365             /* switch back to coordinates for previous interation's 'mtmp' */
1366             x -= u.dx, y -= u.dy;
1367             break;
1368         }
1369         mtmp = m_at(x, y);
1370         vismon = (mtmp && canseemon(mtmp));
1371         glyph = glyph_at(x, y);
1372         unseen = glyph_is_invisible(glyph);
1373         statue = (glyph_is_statue(glyph) /* mimic or hallucinatory statue */
1374                   || (!vismon && !unseen && (otmp = vobj_at(x, y)) != 0
1375                       && otmp->otyp == STATUE)); /* or actual statue */
1376         if (vismon && (M_AP_TYPE(mtmp) == M_AP_FURNITURE
1377                        || M_AP_TYPE(mtmp) == M_AP_OBJECT))
1378             vismon = 0, mtmp = (struct monst *) 0;
1379         if (vismon || unseen || (statue && Hallucination)
1380             /* unseen adjacent monster will respond if able */
1381             || (range == 1 && mtmp && responsive_mon_at(x, y)
1382                 && !is_silent(mtmp->data))
1383             /* we check accessible() after m_at() in case there's a
1384                visible monster phazing through a wall here */
1385             || !(accessible(x, y) || levl[x][y].typ == IRONBARS))
1386             break;
1387     }
1388 
1389     if (unseen || (statue && Hallucination)) {
1390         pline("That %screature is ignoring you!", unseen ? "unseen " : "");
1391     } else if (!mtmp || !responsive_mon_at(x, y)) {
1392         if (vismon) /* 'vismon' is only True when 'mtmp' is non-Null */
1393             pline("%s seems not to notice you.", Monnam(mtmp));
1394         else
1395             goto nada;
1396     } else { /* 'mtmp' is guaranteed to be non-Null if we get here */
1397         /* if this monster is waiting for something, prod it into action */
1398         mtmp->mstrategy &= ~STRAT_WAITMASK;
1399 
1400         if (vismon && humanoid(mtmp->data) && mtmp->mpeaceful && !Conflict) {
1401             if ((otmp = which_armor(mtmp, W_ARMH)) == 0) {
1402                 pline("%s waves.", Monnam(mtmp));
1403             } else if (otmp->cursed) {
1404                 pline("%s grasps %s %s but can't remove it.", Monnam(mtmp),
1405                       mhis(mtmp), helm_simple_name(otmp));
1406                 otmp->bknown = 1;
1407             } else {
1408                 pline("%s tips %s %s in response.", Monnam(mtmp),
1409                       mhis(mtmp), helm_simple_name(otmp));
1410             }
1411         } else if (vismon && humanoid(mtmp->data)) {
1412             static const char *const reaction[3] = {
1413                 "curses", "gestures rudely", "gestures offensively",
1414             };
1415             int which = !Deaf ? rn2(3) : rn1(2, 1),
1416                 twice = (Deaf || which > 0 || rn2(3)) ? 0 : rn1(2, 1);
1417 
1418             pline("%s %s%s%s at you...", Monnam(mtmp), reaction[which],
1419                   twice ? " and " : "", twice ? reaction[twice] : "");
1420         } else if (distu(x, y) <= 2 && !Deaf && domonnoise(mtmp)) {
1421             if (!vismon)
1422                 map_invisible(x, y);
1423         } else if (vismon) {
1424             pline("%s doesn't respond.", Monnam(mtmp));
1425         } else {
1426  nada:
1427             pline("%s", nothing_happens);
1428         }
1429     }
1430     return res;
1431 }
1432 
1433 #ifdef USER_SOUNDS
1434 
1435 #if defined(WIN32) || defined(QT_GRAPHICS)
1436 extern void play_usersound(const char *, int);
1437 #endif
1438 #if defined(TTY_SOUND_ESCCODES)
1439 extern void play_usersound_via_idx(int, int);
1440 #endif
1441 
1442 typedef struct audio_mapping_rec {
1443     struct nhregex *regex;
1444     char *filename;
1445     int volume;
1446     int idx;
1447     struct audio_mapping_rec *next;
1448 } audio_mapping;
1449 
1450 static audio_mapping *soundmap = 0;
1451 static audio_mapping *sound_matches_message(const char *);
1452 
1453 char *sounddir = 0; /* set in files.c */
1454 
1455 /* adds a sound file mapping, returns 0 on failure, 1 on success */
1456 int
add_sound_mapping(const char * mapping)1457 add_sound_mapping(const char* mapping)
1458 {
1459     char text[256];
1460     char filename[256];
1461     char filespec[256];
1462     int volume, idx = -1;
1463 
1464     if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d %d", text,
1465                filename, &volume, &idx) == 4
1466         || sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
1467                filename, &volume) == 3) {
1468         audio_mapping *new_map;
1469 
1470         if (!sounddir)
1471             sounddir = dupstr(".");
1472         if (strlen(sounddir) + 1 + strlen(filename) >= sizeof filespec) {
1473             raw_print("sound file name too long");
1474             return 0;
1475 	}
1476         Snprintf(filespec, sizeof filespec, "%s/%s", sounddir, filename);
1477 
1478         if (idx >= 0 || can_read_file(filespec)) {
1479             new_map = (audio_mapping *) alloc(sizeof *new_map);
1480             new_map->regex = regex_init();
1481             new_map->filename = dupstr(filespec);
1482             new_map->volume = volume;
1483             new_map->idx = idx;
1484             new_map->next = soundmap;
1485 
1486             if (!regex_compile(text, new_map->regex)) {
1487                 const char *re_error_desc = regex_error_desc(new_map->regex);
1488 
1489                 regex_free(new_map->regex);
1490                 free((genericptr_t) new_map->filename);
1491                 free((genericptr_t) new_map);
1492                 raw_print(re_error_desc);
1493                 return 0;
1494             } else {
1495                 soundmap = new_map;
1496             }
1497         } else {
1498             Sprintf(text, "cannot read %.243s", filespec);
1499             raw_print(text);
1500             return 0;
1501         }
1502     } else {
1503         raw_print("syntax error in SOUND");
1504         return 0;
1505     }
1506 
1507     return 1;
1508 }
1509 
1510 static audio_mapping *
sound_matches_message(const char * msg)1511 sound_matches_message(const char* msg)
1512 {
1513     audio_mapping *snd = soundmap;
1514 
1515     while (snd) {
1516         if (regex_match(msg, snd->regex))
1517             return snd;
1518         snd = snd->next;
1519     }
1520     return (audio_mapping *) 0;
1521 }
1522 
1523 void
play_sound_for_message(const char * msg)1524 play_sound_for_message(const char* msg)
1525 {
1526     audio_mapping *snd = sound_matches_message(msg);
1527 
1528     if (snd)
1529         play_usersound(snd->filename, snd->volume);
1530 }
1531 
1532 void
maybe_play_sound(const char * msg)1533 maybe_play_sound(const char* msg)
1534 {
1535 #if defined(WIN32) || defined(QT_GRAPHICS) || defined(TTY_SOUND_ESCCODES)
1536     audio_mapping *snd = sound_matches_message(msg);
1537 
1538     if (snd
1539 #if defined(WIN32) || defined(QT_GRAPHICS)
1540 #ifdef TTY_SOUND_ESCCODES
1541         && !iflags.vt_sounddata
1542 #endif
1543 #if defined(QT_GRAPHICS)
1544         && WINDOWPORT("Qt")
1545 #endif
1546 #if defined(WIN32)
1547         && (WINDOWPORT("tty") || WINDOWPORT("mswin") || WINDOWPORT("curses"))
1548 #endif
1549 #endif /* WIN32 || QT_GRAPHICS */
1550         )
1551         play_usersound(snd->filename, snd->volume);
1552 #if defined(TTY_GRAPHICS) && defined(TTY_SOUND_ESCCODES)
1553     else if (snd && iflags.vt_sounddata && snd->idx >= 0 && WINDOWPORT("tty"))
1554         play_usersound_via_idx(snd->idx, snd->volume);
1555 #endif  /* TTY_GRAPHICS && TTY_SOUND_ESCCODES */
1556 #endif  /* WIN32 || QT_GRAPHICS || TTY_SOUND_ESCCODES */
1557 }
1558 
1559 void
release_sound_mappings(void)1560 release_sound_mappings(void)
1561 {
1562     audio_mapping *nextsound = 0;
1563 
1564     while (soundmap) {
1565         nextsound = soundmap->next;
1566         regex_free(soundmap->regex);
1567         free((genericptr_t) soundmap->filename);
1568         free((genericptr_t) soundmap);
1569         soundmap = nextsound;
1570     }
1571 
1572     if (sounddir)
1573         free((genericptr_t) sounddir), sounddir = 0;
1574 }
1575 
1576 #endif /* USER_SOUNDS */
1577 
1578 /*sounds.c*/
1579