OSDN Git Service

no E-word
[nethackexpress/trunk.git] / src / sounds.c
1 /*      SCCS Id: @(#)sounds.c   3.4     2002/05/06      */
2 /*      Copyright (c) 1989 Janet Walz, Mike Threepoint */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6 #include "edog.h"
7 #ifdef USER_SOUNDS
8 # ifdef USER_SOUNDS_REGEX
9 #include <regex.h>
10 # endif
11 #endif
12
13 #ifdef OVLB
14
15 static int FDECL(domonnoise,(struct monst *));
16 static int NDECL(dochat);
17
18 #endif /* OVLB */
19
20 #ifdef OVL0
21
22 static int FDECL(mon_in_room, (struct monst *,int));
23
24 /* this easily could be a macro, but it might overtax dumb compilers */
25 static int
26 mon_in_room(mon, rmtyp)
27 struct monst *mon;
28 int rmtyp;
29 {
30     int rno = levl[mon->mx][mon->my].roomno;
31
32     return rooms[rno - ROOMOFFSET].rtype == rmtyp;
33 }
34
35 void
36 dosounds()
37 {
38     register struct mkroom *sroom;
39     register int hallu, vx, vy;
40 #if defined(AMIGA) && defined(AZTEC_C_WORKAROUND)
41     int xx;
42 #endif
43     struct monst *mtmp;
44
45     if (!flags.soundok || u.uswallow || Underwater) return;
46
47     hallu = Hallucination ? 1 : 0;
48
49     if (level.flags.nfountains && !rn2(400)) {
50         static const char * const fountain_msg[4] = {
51                 "bubbling water.",
52                 "water falling on coins.",
53                 "the splashing of a naiad.",
54                 "a soda fountain!",
55         };
56         You_hear(fountain_msg[rn2(3)+hallu]);
57     }
58 #ifdef SINK
59     if (level.flags.nsinks && !rn2(300)) {
60         static const char * const sink_msg[3] = {
61                 "a slow drip.",
62                 "a gurgling noise.",
63                 "dishes being washed!",
64         };
65         You_hear(sink_msg[rn2(2)+hallu]);
66     }
67 #endif
68     if (level.flags.has_court && !rn2(200)) {
69         static const char * const throne_msg[4] = {
70                 "the tones of courtly conversation.",
71                 "a sceptre pounded in judgment.",
72                 "Someone shouts \"Off with %s head!\"",
73                 "Queen Beruthiel's cats!",
74         };
75         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
76             if (DEADMONSTER(mtmp)) continue;
77             if ((mtmp->msleeping ||
78                         is_lord(mtmp->data) || is_prince(mtmp->data)) &&
79                 !is_animal(mtmp->data) &&
80                 mon_in_room(mtmp, COURT)) {
81                 /* finding one is enough, at least for now */
82                 int which = rn2(3)+hallu;
83
84                 if (which != 2) You_hear(throne_msg[which]);
85                 else            pline(throne_msg[2], uhis());
86                 return;
87             }
88         }
89     }
90     if (level.flags.has_swamp && !rn2(200)) {
91         static const char * const swamp_msg[3] = {
92                 "hear mosquitoes!",
93                 "smell marsh gas!",     /* so it's a smell...*/
94                 "hear Donald Duck!",
95         };
96         You(swamp_msg[rn2(2)+hallu]);
97         return;
98     }
99     if (level.flags.has_vault && !rn2(200)) {
100         if (!(sroom = search_special(VAULT))) {
101             /* strange ... */
102             level.flags.has_vault = 0;
103             return;
104         }
105         if(gd_sound())
106             switch (rn2(2)+hallu) {
107                 case 1: {
108                     boolean gold_in_vault = FALSE;
109
110                     for (vx = sroom->lx;vx <= sroom->hx; vx++)
111                         for (vy = sroom->ly; vy <= sroom->hy; vy++)
112                             if (g_at(vx, vy))
113                                 gold_in_vault = TRUE;
114 #if defined(AMIGA) && defined(AZTEC_C_WORKAROUND)
115                     /* Bug in aztec assembler here. Workaround below */
116                     xx = ROOM_INDEX(sroom) + ROOMOFFSET;
117                     xx = (xx != vault_occupied(u.urooms));
118                     if(xx)
119 #else
120                     if (vault_occupied(u.urooms) !=
121                          (ROOM_INDEX(sroom) + ROOMOFFSET))
122 #endif /* AZTEC_C_WORKAROUND */
123                     {
124                         if (gold_in_vault)
125                             You_hear(!hallu ? "someone counting money." :
126                                 "the quarterback calling the play.");
127                         else
128                             You_hear("someone searching.");
129                         break;
130                     }
131                     /* fall into... (yes, even for hallucination) */
132                 }
133                 case 0:
134                     You_hear("the footsteps of a guard on patrol.");
135                     break;
136                 case 2:
137                     You_hear("Ebenezer Scrooge!");
138                     break;
139             }
140         return;
141     }
142     if (level.flags.has_beehive && !rn2(200)) {
143         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
144             if (DEADMONSTER(mtmp)) continue;
145             if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data)) &&
146                 mon_in_room(mtmp, BEEHIVE)) {
147                 switch (rn2(2)+hallu) {
148                     case 0:
149                         You_hear("a low buzzing.");
150                         break;
151                     case 1:
152                         You_hear("an angry drone.");
153                         break;
154                     case 2:
155                         You_hear("bees in your %sbonnet!",
156                             uarmh ? "" : "(nonexistent) ");
157                         break;
158                 }
159                 return;
160             }
161         }
162     }
163     if (level.flags.has_morgue && !rn2(200)) {
164         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
165             if (DEADMONSTER(mtmp)) continue;
166             if (is_undead(mtmp->data) &&
167                 mon_in_room(mtmp, MORGUE)) {
168                 switch (rn2(2)+hallu) {
169                     case 0:
170                         You("suddenly realize it is unnaturally quiet.");
171                         break;
172                     case 1:
173                         pline_The("%s on the back of your %s stands up.",
174                                 body_part(HAIR), body_part(NECK));
175                         break;
176                     case 2:
177                         pline_The("%s on your %s seems to stand up.",
178                                 body_part(HAIR), body_part(HEAD));
179                         break;
180                 }
181                 return;
182             }
183         }
184     }
185     if (level.flags.has_barracks && !rn2(200)) {
186         static const char * const barracks_msg[4] = {
187                 "blades being honed.",
188                 "loud snoring.",
189                 "dice being thrown.",
190                 "General MacArthur!",
191         };
192         int count = 0;
193
194         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
195             if (DEADMONSTER(mtmp)) continue;
196             if (is_mercenary(mtmp->data) &&
197 #if 0           /* don't bother excluding these */
198                 !strstri(mtmp->data->mname, "watch") &&
199                 !strstri(mtmp->data->mname, "guard") &&
200 #endif
201                 mon_in_room(mtmp, BARRACKS) &&
202                 /* sleeping implies not-yet-disturbed (usually) */
203                 (mtmp->msleeping || ++count > 5)) {
204                 You_hear(barracks_msg[rn2(3)+hallu]);
205                 return;
206             }
207         }
208     }
209     if (level.flags.has_zoo && !rn2(200)) {
210         static const char * const zoo_msg[3] = {
211                 "a sound reminiscent of an elephant stepping on a peanut.",
212                 "a sound reminiscent of a seal barking.",
213                 "Doctor Doolittle!",
214         };
215         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
216             if (DEADMONSTER(mtmp)) continue;
217             if ((mtmp->msleeping || is_animal(mtmp->data)) &&
218                     mon_in_room(mtmp, ZOO)) {
219                 You_hear(zoo_msg[rn2(2)+hallu]);
220                 return;
221             }
222         }
223     }
224     if (level.flags.has_shop && !rn2(200)) {
225         if (!(sroom = search_special(ANY_SHOP))) {
226             /* strange... */
227             level.flags.has_shop = 0;
228             return;
229         }
230         if (tended_shop(sroom) &&
231                 !index(u.ushops, ROOM_INDEX(sroom) + ROOMOFFSET)) {
232             static const char * const shop_msg[3] = {
233                     "someone cursing shoplifters.",
234                     "the chime of a cash register.",
235                     "Neiman and Marcus arguing!",
236             };
237             You_hear(shop_msg[rn2(2)+hallu]);
238         }
239         return;
240     }
241     if (Is_oracle_level(&u.uz) && !rn2(400)) {
242         /* make sure the Oracle is still here */
243         for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
244             if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_ORACLE])
245                 break;
246         /* and don't produce silly effects when she's clearly visible */
247         if (mtmp && (hallu || !canseemon(mtmp))) {
248             static const char * const ora_msg[5] = {
249                     "a strange wind.",          /* Jupiter at Dodona */
250                     "convulsive ravings.",      /* Apollo at Delphi */
251                     "snoring snakes.",          /* AEsculapius at Epidaurus */
252                     "someone say \"No more woodchucks!\"",
253                     "a loud ZOT!"               /* both rec.humor.oracle */
254             };
255             You_hear(ora_msg[rn2(3)+hallu*2]);
256         }
257         return;
258     }
259 }
260
261 #endif /* OVL0 */
262 #ifdef OVLB
263
264 static const char * const h_sounds[] = {
265     "beep", "boing", "sing", "belche", "creak", "cough", "rattle",
266     "ululate", "pop", "jingle", "sniffle", "tinkle", "eep"
267 };
268
269 const char *
270 growl_sound(mtmp)
271 register struct monst *mtmp;
272 {
273         const char *ret;
274
275         switch (mtmp->data->msound) {
276         case MS_MEW:
277         case MS_HISS:
278             ret = "hiss";
279             break;
280         case MS_BARK:
281         case MS_GROWL:
282             ret = "growl";
283             break;
284         case MS_ROAR:
285             ret = "roar";
286             break;
287         case MS_BUZZ:
288             ret = "buzz";
289             break;
290         case MS_SQEEK:
291             ret = "squeal";
292             break;
293         case MS_SQAWK:
294             ret = "screech";
295             break;
296         case MS_NEIGH:
297             ret = "neigh";
298             break;
299         case MS_WAIL:
300             ret = "wail";
301             break;
302         case MS_SILENT:
303                 ret = "commotion";
304                 break;
305         default:
306                 ret = "scream";
307         }
308         return ret;
309 }
310
311 /* the sounds of a seriously abused pet, including player attacking it */
312 void
313 growl(mtmp)
314 register struct monst *mtmp;
315 {
316     register const char *growl_verb = 0;
317
318     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
319         return;
320
321     /* presumably nearness and soundok checks have already been made */
322     if (Hallucination)
323         growl_verb = h_sounds[rn2(SIZE(h_sounds))];
324     else
325         growl_verb = growl_sound(mtmp);
326     if (growl_verb) {
327         pline("%s %s!", Monnam(mtmp), vtense((char *)0, growl_verb));
328         if(flags.run) nomul(0);
329         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18);
330     }
331 }
332
333 /* the sounds of mistreated pets */
334 void
335 yelp(mtmp)
336 register struct monst *mtmp;
337 {
338     register const char *yelp_verb = 0;
339
340     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
341         return;
342
343     /* presumably nearness and soundok checks have already been made */
344     if (Hallucination)
345         yelp_verb = h_sounds[rn2(SIZE(h_sounds))];
346     else switch (mtmp->data->msound) {
347         case MS_MEW:
348             yelp_verb = "yowl";
349             break;
350         case MS_BARK:
351         case MS_GROWL:
352             yelp_verb = "yelp";
353             break;
354         case MS_ROAR:
355             yelp_verb = "snarl";
356             break;
357         case MS_SQEEK:
358             yelp_verb = "squeal";
359             break;
360         case MS_SQAWK:
361             yelp_verb = "screak";
362             break;
363         case MS_WAIL:
364             yelp_verb = "wail";
365             break;
366     }
367     if (yelp_verb) {
368         pline("%s %s!", Monnam(mtmp), vtense((char *)0, yelp_verb));
369         if(flags.run) nomul(0);
370         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
371     }
372 }
373
374 /* the sounds of distressed pets */
375 void
376 whimper(mtmp)
377 register struct monst *mtmp;
378 {
379     register const char *whimper_verb = 0;
380
381     if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
382         return;
383
384     /* presumably nearness and soundok checks have already been made */
385     if (Hallucination)
386         whimper_verb = h_sounds[rn2(SIZE(h_sounds))];
387     else switch (mtmp->data->msound) {
388         case MS_MEW:
389         case MS_GROWL:
390             whimper_verb = "whimper";
391             break;
392         case MS_BARK:
393             whimper_verb = "whine";
394             break;
395         case MS_SQEEK:
396             whimper_verb = "squeal";
397             break;
398     }
399     if (whimper_verb) {
400         pline("%s %s.", Monnam(mtmp), vtense((char *)0, whimper_verb));
401         if(flags.run) nomul(0);
402         wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6);
403     }
404 }
405
406 /* pet makes "I'm hungry" noises */
407 void
408 beg(mtmp)
409 register struct monst *mtmp;
410 {
411     if (mtmp->msleeping || !mtmp->mcanmove ||
412             !(carnivorous(mtmp->data) || herbivorous(mtmp->data)))
413         return;
414
415     /* presumably nearness and soundok checks have already been made */
416     if (!is_silent(mtmp->data) && mtmp->data->msound <= MS_ANIMAL)
417         (void) domonnoise(mtmp);
418     else if (mtmp->data->msound >= MS_HUMANOID) {
419         if (!canspotmon(mtmp))
420             map_invisible(mtmp->mx, mtmp->my);
421         verbalize("I'm hungry.");
422     }
423 }
424
425 static int
426 domonnoise(mtmp)
427 register struct monst *mtmp;
428 {
429     register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
430                         *verbl_msg = 0; /* verbalize() */
431     struct permonst *ptr = mtmp->data;
432     char verbuf[BUFSZ];
433
434     /* presumably nearness and sleep checks have already been made */
435     if (!flags.soundok) return(0);
436     if (is_silent(ptr)) return(0);
437
438     /* Make sure its your role's quest quardian; adjust if not */
439     if (ptr->msound == MS_GUARDIAN && ptr != &mons[urole.guardnum]) {
440         int mndx = monsndx(ptr);
441         ptr = &mons[genus(mndx,1)];
442     }
443
444     /* be sure to do this before talking; the monster might teleport away, in
445      * which case we want to check its pre-teleport position
446      */
447     if (!canspotmon(mtmp))
448         map_invisible(mtmp->mx, mtmp->my);
449
450     switch (ptr->msound) {
451         case MS_ORACLE:
452             return doconsult(mtmp);
453         case MS_PRIEST:
454             priest_talk(mtmp);
455             break;
456         case MS_LEADER:
457         case MS_NEMESIS:
458         case MS_GUARDIAN:
459             quest_chat(mtmp);
460             break;
461         case MS_SELL: /* pitch, pay, total */
462             shk_chat(mtmp);
463             break;
464         case MS_VAMPIRE:
465             {
466             /* vampire messages are varied by tameness, peacefulness, and time of night */
467                 boolean isnight = night();
468                 boolean kindred =    (Upolyd && (u.umonnum == PM_VAMPIRE ||
469                                        u.umonnum == PM_VAMPIRE_LORD));
470                 boolean nightchild = (Upolyd && (u.umonnum == PM_WOLF ||
471                                        u.umonnum == PM_WINTER_WOLF ||
472                                        u.umonnum == PM_WINTER_WOLF_CUB));
473                 const char *racenoun = (flags.female && urace.individual.f) ?
474                                         urace.individual.f : (urace.individual.m) ?
475                                         urace.individual.m : urace.noun;
476
477                 if (mtmp->mtame) {
478                         if (kindred) {
479                                 Sprintf(verbuf, "Good %s to you Master%s",
480                                         isnight ? "evening" : "day",
481                                         isnight ? "!" : ".  Why do we not rest?");
482                                 verbl_msg = verbuf;
483                         } else {
484                             Sprintf(verbuf,"%s%s",
485                                 nightchild ? "Child of the night, " : "",
486                                 midnight() ?
487                                         "I can stand this craving no longer!" :
488                                 isnight ?
489                                         "I beg you, help me satisfy this growing craving!" :
490                                         "I find myself growing a little weary.");
491                                 verbl_msg = verbuf;
492                         }
493                 } else if (mtmp->mpeaceful) {
494                         if (kindred && isnight) {
495                                 Sprintf(verbuf, "Good feeding %s!",
496                                         flags.female ? "sister" : "brother");
497                                 verbl_msg = verbuf;
498                         } else if (nightchild && isnight) {
499                                 Sprintf(verbuf,
500                                     "How nice to hear you, child of the night!");
501                                 verbl_msg = verbuf;
502                         } else
503                                 verbl_msg = "I only drink... potions.";
504                 } else {
505                         int vampindex;
506                         static const char * const vampmsg[] = {
507                                /* These first two (0 and 1) are specially handled below */
508                                 "I vant to suck your %s!",
509                                 "I vill come after %s without regret!",
510                                /* other famous vampire quotes can follow here if desired */
511                         };
512                         if (kindred)
513                             verbl_msg = "This is my hunting ground that you dare to prowl!";
514                         else if (youmonst.data == &mons[PM_SILVER_DRAGON] ||
515                                  youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
516                             /* Silver dragons are silver in color, not made of silver */
517                             Sprintf(verbuf, "%s! Your silver sheen does not frighten me!",
518                                         youmonst.data == &mons[PM_SILVER_DRAGON] ?
519                                         "Fool" : "Young Fool");
520                             verbl_msg = verbuf; 
521                         } else {
522                             vampindex = rn2(SIZE(vampmsg));
523                             if (vampindex == 0) {
524                                 Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
525                                 verbl_msg = verbuf;
526                             } else if (vampindex == 1) {
527                                 Sprintf(verbuf, vampmsg[vampindex],
528                                         Upolyd ? an(mons[u.umonnum].mname) : an(racenoun));
529                                 verbl_msg = verbuf;
530                             } else
531                                 verbl_msg = vampmsg[vampindex];
532                         }
533                 }
534             }
535             break;
536         case MS_WERE:
537             if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
538                 pline("%s throws back %s head and lets out a blood curdling %s!",
539                       Monnam(mtmp), mhis(mtmp),
540                       ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl");
541                 wake_nearto(mtmp->mx, mtmp->my, 11*11);
542             } else
543                 pline_msg =
544                      "whispers inaudibly.  All you can make out is \"moon\".";
545             break;
546         case MS_BARK:
547             if (flags.moonphase == FULL_MOON && night()) {
548                 pline_msg = "howls.";
549             } else if (mtmp->mpeaceful) {
550                 if (mtmp->mtame &&
551                         (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
552                          moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
553                     pline_msg = "whines.";
554                 else if (mtmp->mtame && EDOG(mtmp)->hungrytime > moves + 1000)
555                     pline_msg = "yips.";
556                 else {
557                     if (mtmp->data != &mons[PM_DINGO])  /* dingos do not actually bark */
558                             pline_msg = "barks.";
559                 }
560             } else {
561                 pline_msg = "growls.";
562             }
563             break;
564         case MS_MEW:
565             if (mtmp->mtame) {
566                 if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
567                         mtmp->mtame < 5)
568                     pline_msg = "yowls.";
569                 else if (moves > EDOG(mtmp)->hungrytime)
570                     pline_msg = "meows.";
571                 else if (EDOG(mtmp)->hungrytime > moves + 1000)
572                     pline_msg = "purrs.";
573                 else
574                     pline_msg = "mews.";
575                 break;
576             } /* else FALLTHRU */
577         case MS_GROWL:
578             pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
579             break;
580         case MS_ROAR:
581             pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
582             break;
583         case MS_SQEEK:
584             pline_msg = "squeaks.";
585             break;
586         case MS_SQAWK:
587             if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
588                 verbl_msg = "Nevermore!";
589             else
590                 pline_msg = "squawks.";
591             break;
592         case MS_HISS:
593             if (!mtmp->mpeaceful)
594                 pline_msg = "hisses!";
595             else return 0;      /* no sound */
596             break;
597         case MS_BUZZ:
598             pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
599             break;
600         case MS_GRUNT:
601             pline_msg = "grunts.";
602             break;
603         case MS_NEIGH:
604             if (mtmp->mtame < 5)
605                 pline_msg = "neighs.";
606             else if (moves > EDOG(mtmp)->hungrytime)
607                 pline_msg = "whinnies.";
608             else
609                 pline_msg = "whickers.";
610             break;
611         case MS_WAIL:
612             pline_msg = "wails mournfully.";
613             break;
614         case MS_GURGLE:
615             pline_msg = "gurgles.";
616             break;
617         case MS_BURBLE:
618             pline_msg = "burbles.";
619             break;
620         case MS_SHRIEK:
621             pline_msg = "shrieks.";
622             aggravate();
623             break;
624         case MS_IMITATE:
625             pline_msg = "imitates you.";
626             break;
627         case MS_BONES:
628             pline("%s rattles noisily.", Monnam(mtmp));
629             You("freeze for a moment.");
630             nomul(-2);
631             break;
632         case MS_LAUGH:
633             {
634                 static const char * const laugh_msg[4] = {
635                     "giggles.", "chuckles.", "snickers.", "laughs.",
636                 };
637                 pline_msg = laugh_msg[rn2(4)];
638             }
639             break;
640         case MS_MUMBLE:
641             pline_msg = "mumbles incomprehensibly.";
642             break;
643         case MS_DJINNI:
644             if (mtmp->mtame) {
645                 verbl_msg = "Sorry, I'm all out of wishes.";
646             } else if (mtmp->mpeaceful) {
647                 if (ptr == &mons[PM_WATER_DEMON])
648                     pline_msg = "gurgles.";
649                 else
650                     verbl_msg = "I'm free!";
651             } else verbl_msg = "This will teach you not to disturb me!";
652             break;
653         case MS_BOAST:  /* giants */
654             if (!mtmp->mpeaceful) {
655                 switch (rn2(4)) {
656                 case 0: pline("%s boasts about %s gem collection.",
657                               Monnam(mtmp), mhis(mtmp));
658                         break;
659                 case 1: pline_msg = "complains about a diet of mutton.";
660                         break;
661                default: pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
662                         wake_nearto(mtmp->mx, mtmp->my, 7*7);
663                         break;
664                 }
665                 break;
666             }
667             /* else FALLTHRU */
668         case MS_HUMANOID:
669             if (!mtmp->mpeaceful) {
670                 if (In_endgame(&u.uz) && is_mplayer(ptr)) {
671                     mplayer_talk(mtmp);
672                     break;
673                 } else return 0;        /* no sound */
674             }
675             /* Generic peaceful humanoid behaviour. */
676             if (mtmp->mflee)
677                 pline_msg = "wants nothing to do with you.";
678             else if (mtmp->mhp < mtmp->mhpmax/4)
679                 pline_msg = "moans.";
680             else if (mtmp->mconf || mtmp->mstun)
681                 verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
682             else if (!mtmp->mcansee)
683                 verbl_msg = "I can't see!";
684             else if (mtmp->mtrapped) {
685                 struct trap *t = t_at(mtmp->mx, mtmp->my);
686
687                 if (t) t->tseen = 1;
688                 verbl_msg = "I'm trapped!";
689             } else if (mtmp->mhp < mtmp->mhpmax/2)
690                 pline_msg = "asks for a potion of healing.";
691             else if (mtmp->mtame && !mtmp->isminion &&
692                                                 moves > EDOG(mtmp)->hungrytime)
693                 verbl_msg = "I'm hungry.";
694             /* Specific monsters' interests */
695             else if (is_elf(ptr))
696                 pline_msg = "curses orcs.";
697             else if (is_dwarf(ptr))
698                 pline_msg = "talks about mining.";
699             else if (likes_magic(ptr))
700                 pline_msg = "talks about spellcraft.";
701             else if (ptr->mlet == S_CENTAUR)
702                 pline_msg = "discusses hunting.";
703             else switch (monsndx(ptr)) {
704                 case PM_HOBBIT:
705                     pline_msg = (mtmp->mhpmax - mtmp->mhp >= 10) ?
706                                 "complains about unpleasant dungeon conditions."
707                                 : "asks you about the One Ring.";
708                     break;
709                 case PM_ARCHEOLOGIST:
710     pline_msg = "describes a recent article in \"Spelunker Today\" magazine.";
711                     break;
712 #ifdef TOURIST
713                 case PM_TOURIST:
714                     verbl_msg = "Aloha.";
715                     break;
716 #endif
717                 default:
718                     pline_msg = "discusses dungeon exploration.";
719                     break;
720             }
721             break;
722         case MS_SEDUCE:
723 #ifdef SEDUCE
724             if (ptr->mlet != S_NYMPH &&
725                 could_seduce(mtmp, &youmonst, (struct attack *)0) == 1) {
726                         (void) doseduce(mtmp);
727                         break;
728             }
729             switch ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0)
730 #else
731             switch ((poly_gender() == 0) ? rn2(3) : 0)
732 #endif
733             {
734                 case 2:
735                         verbl_msg = "Hello, sailor.";
736                         break;
737                 case 1:
738                         pline_msg = "comes on to you.";
739                         break;
740                 default:
741                         pline_msg = "cajoles you.";
742             }
743             break;
744 #ifdef KOPS
745         case MS_ARREST:
746             if (mtmp->mpeaceful)
747                 verbalize("Just the facts, %s.",
748                       flags.female ? "Ma'am" : "Sir");
749             else {
750                 static const char * const arrest_msg[3] = {
751                     "Anything you say can be used against you.",
752                     "You're under arrest!",
753                     "Stop in the name of the Law!",
754                 };
755                 verbl_msg = arrest_msg[rn2(3)];
756             }
757             break;
758 #endif
759         case MS_BRIBE:
760             if (mtmp->mpeaceful && !mtmp->mtame) {
761                 (void) demon_talk(mtmp);
762                 break;
763             }
764             /* fall through */
765         case MS_CUSS:
766             if (!mtmp->mpeaceful)
767                 cuss(mtmp);
768             break;
769         case MS_SPELL:
770             /* deliberately vague, since it's not actually casting any spell */
771             pline_msg = "seems to mutter a cantrip.";
772             break;
773         case MS_NURSE:
774             if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
775                 verbl_msg = "Put that weapon away before you hurt someone!";
776             else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
777                 verbl_msg = Role_if(PM_HEALER) ?
778                           "Doc, I can't help you unless you cooperate." :
779                           "Please undress so I can examine you.";
780 #ifdef TOURIST
781             else if (uarmu)
782                 verbl_msg = "Take off your shirt, please.";
783 #endif
784             else verbl_msg = "Relax, this won't hurt a bit.";
785             break;
786         case MS_GUARD:
787 #ifndef GOLDOBJ
788             if (u.ugold)
789 #else
790             if (money_cnt(invent))
791 #endif
792                 verbl_msg = "Please drop that gold and follow me.";
793             else
794                 verbl_msg = "Please follow me.";
795             break;
796         case MS_SOLDIER:
797             {
798                 static const char * const soldier_foe_msg[3] = {
799                     "Resistance is useless!",
800                     "You're dog meat!",
801                     "Surrender!",
802                 },                * const soldier_pax_msg[3] = {
803                     "What lousy pay we're getting here!",
804                     "The food's not fit for Orcs!",
805                     "My feet hurt, I've been on them all day!",
806                 };
807                 verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
808                                             : soldier_foe_msg[rn2(3)];
809             }
810             break;
811         case MS_RIDER:
812             if (ptr == &mons[PM_DEATH] && !rn2(10))
813                 pline_msg = "is busy reading a copy of Sandman #8.";
814             else verbl_msg = "Who do you think you are, War?";
815             break;
816     }
817
818     if (pline_msg) pline("%s %s", Monnam(mtmp), pline_msg);
819     else if (verbl_msg) verbalize(verbl_msg);
820     return(1);
821 }
822
823
824 int
825 dotalk()
826 {
827     int result;
828     boolean save_soundok = flags.soundok;
829     flags.soundok = 1;  /* always allow sounds while chatting */
830     result = dochat();
831     flags.soundok = save_soundok;
832     return result;
833 }
834
835 static int
836 dochat()
837 {
838     register struct monst *mtmp;
839     register int tx,ty;
840     struct obj *otmp;
841
842     if (is_silent(youmonst.data)) {
843         pline("As %s, you cannot speak.", an(youmonst.data->mname));
844         return(0);
845     }
846     if (Strangled) {
847         You_cant("speak.  You're choking!");
848         return(0);
849     }
850     if (u.uswallow) {
851         pline("They won't hear you out there.");
852         return(0);
853     }
854     if (Underwater) {
855         Your("speech is unintelligible underwater.");
856         return(0);
857     }
858
859     if (!Blind && (otmp = shop_object(u.ux, u.uy)) != (struct obj *)0) {
860         /* standing on something in a shop and chatting causes the shopkeeper
861            to describe the price(s).  This can inhibit other chatting inside
862            a shop, but that shouldn't matter much.  shop_object() returns an
863            object iff inside a shop and the shopkeeper is present and willing
864            (not angry) and able (not asleep) to speak and the position contains
865            any objects other than just gold.
866         */
867         price_quote(otmp);
868         return(1);
869     }
870
871     if (!getdir("Talk to whom? (in what direction)")) {
872         /* decided not to chat */
873         return(0);
874     }
875
876 #ifdef STEED
877     if (u.usteed && u.dz > 0)
878         return (domonnoise(u.usteed));
879 #endif
880     if (u.dz) {
881         pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
882         return(0);
883     }
884
885     if (u.dx == 0 && u.dy == 0) {
886 /*
887  * Let's not include this.  It raises all sorts of questions: can you wear
888  * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
889  * etc...  --KAA
890         if (u.umonnum == PM_ETTIN) {
891             You("discover that your other head makes boring conversation.");
892             return(1);
893         }
894 */
895         pline("Talking to yourself is a bad habit for a dungeoneer.");
896         return(0);
897     }
898
899     tx = u.ux+u.dx; ty = u.uy+u.dy;
900     mtmp = m_at(tx, ty);
901
902     if (!mtmp || mtmp->mundetected ||
903                 mtmp->m_ap_type == M_AP_FURNITURE ||
904                 mtmp->m_ap_type == M_AP_OBJECT)
905         return(0);
906
907     /* sleeping monsters won't talk, except priests (who wake up) */
908     if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
909         /* If it is unseen, the player can't tell the difference between
910            not noticing him and just not existing, so skip the message. */
911         if (canspotmon(mtmp))
912             pline("%s seems not to notice you.", Monnam(mtmp));
913         return(0);
914     }
915
916     /* if this monster is waiting for something, prod it into action */
917     mtmp->mstrategy &= ~STRAT_WAITMASK;
918
919     if (mtmp->mtame && mtmp->meating) {
920         if (!canspotmon(mtmp))
921             map_invisible(mtmp->mx, mtmp->my);
922         pline("%s is eating noisily.", Monnam(mtmp));
923         return (0);
924     }
925
926     return domonnoise(mtmp);
927 }
928
929 #ifdef USER_SOUNDS
930
931 extern void FDECL(play_usersound, (const char*, int));
932
933 typedef struct audio_mapping_rec {
934 #ifdef USER_SOUNDS_REGEX
935         struct re_pattern_buffer regex;
936 #else
937         char *pattern;
938 #endif
939         char *filename;
940         int volume;
941         struct audio_mapping_rec *next;
942 } audio_mapping;
943
944 static audio_mapping *soundmap = 0;
945
946 char* sounddir = ".";
947
948 /* adds a sound file mapping, returns 0 on failure, 1 on success */
949 int
950 add_sound_mapping(mapping)
951 const char *mapping;
952 {
953         char text[256];
954         char filename[256];
955         char filespec[256];
956         int volume;
957
958         if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d",
959                    text, filename, &volume) == 3) {
960             const char *err;
961             audio_mapping *new_map;
962
963             if (strlen(sounddir) + strlen(filename) > 254) {
964                 raw_print("sound file name too long");
965                 return 0;
966             }
967             Sprintf(filespec, "%s/%s", sounddir, filename);
968
969             if (can_read_file(filespec)) {
970                 new_map = (audio_mapping *)alloc(sizeof(audio_mapping));
971 #ifdef USER_SOUNDS_REGEX
972                 new_map->regex.translate = 0;
973                 new_map->regex.fastmap = 0;
974                 new_map->regex.buffer = 0;
975                 new_map->regex.allocated = 0;
976                 new_map->regex.regs_allocated = REGS_FIXED;
977 #else
978                 new_map->pattern = (char *)alloc(strlen(text) + 1);
979                 Strcpy(new_map->pattern, text);
980 #endif
981                 new_map->filename = strdup(filespec);
982                 new_map->volume = volume;
983                 new_map->next = soundmap;
984
985 #ifdef USER_SOUNDS_REGEX
986                 err = re_compile_pattern(text, strlen(text), &new_map->regex);
987 #else
988                 err = 0;
989 #endif
990                 if (err) {
991                     raw_print(err);
992                     free(new_map->filename);
993                     free(new_map);
994                     return 0;
995                 } else {
996                     soundmap = new_map;
997                 }
998             } else {
999                 Sprintf(text, "cannot read %.243s", filespec);
1000                 raw_print(text);
1001                 return 0;
1002             }
1003         } else {
1004             raw_print("syntax error in SOUND");
1005             return 0;
1006         }
1007
1008         return 1;
1009 }
1010
1011 void
1012 play_sound_for_message(msg)
1013 const char* msg;
1014 {
1015         audio_mapping* cursor = soundmap;
1016
1017         while (cursor) {
1018 #ifdef USER_SOUNDS_REGEX
1019             if (re_search(&cursor->regex, msg, strlen(msg), 0, 9999, 0) >= 0) {
1020 #else
1021             if (pmatch(cursor->pattern, msg)) {
1022 #endif
1023                 play_usersound(cursor->filename, cursor->volume);
1024             }
1025             cursor = cursor->next;
1026         }
1027 }
1028
1029 #endif /* USER_SOUNDS */
1030
1031 #endif /* OVLB */
1032
1033 /*sounds.c*/