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
mon_in_room(mon,rmtyp)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
dosounds()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 *
growl_sound(mtmp)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
growl(mtmp)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
yelp(mtmp)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
whimper(mtmp)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
beg(mtmp)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
domonnoise(mtmp)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
dotalk()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
dochat()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
add_sound_mapping(mapping)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
play_sound_for_message(msg)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*/
1034