Iron bars, water and lava are not interesting for travel
[aNetHack.git] / src / sounds.c
blob5b6f085aaf2b2a62c1e2ed11f0d7804a9eaac772
1 /* NetHack 3.6 sounds.c $NHDT-Date: 1452992329 2016/01/17 00:58:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.78 $ */
2 /* Copyright (c) 1989 Janet Walz, Mike Threepoint */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_DCL boolean FDECL(mon_is_gecko, (struct monst *));
8 STATIC_DCL int FDECL(domonnoise, (struct monst *));
9 STATIC_DCL int NDECL(dochat);
10 STATIC_DCL int FDECL(mon_in_room, (struct monst *, int));
12 /* this easily could be a macro, but it might overtax dumb compilers */
13 STATIC_OVL int
14 mon_in_room(mon, rmtyp)
15 struct monst *mon;
16 int rmtyp;
18 int rno = levl[mon->mx][mon->my].roomno;
19 if (rno >= ROOMOFFSET)
20 return rooms[rno - ROOMOFFSET].rtype == rmtyp;
21 return FALSE;
24 void
25 dosounds()
27 register struct mkroom *sroom;
28 register int hallu, vx, vy;
29 #if defined(AMIGA) && defined(AZTEC_C_WORKAROUND)
30 int xx;
31 #endif
32 struct monst *mtmp;
34 if (Deaf || !flags.acoustics || u.uswallow || Underwater)
35 return;
37 hallu = Hallucination ? 1 : 0;
39 if (level.flags.nfountains && !rn2(400)) {
40 static const char *const fountain_msg[4] = {
41 "bubbling water.", "water falling on coins.",
42 "the splashing of a naiad.", "a soda fountain!",
44 You_hear1(fountain_msg[rn2(3) + hallu]);
46 if (level.flags.nsinks && !rn2(300)) {
47 static const char *const sink_msg[3] = {
48 "a slow drip.", "a gurgling noise.", "dishes being washed!",
50 You_hear1(sink_msg[rn2(2) + hallu]);
52 if (level.flags.has_court && !rn2(200)) {
53 static const char *const throne_msg[4] = {
54 "the tones of courtly conversation.",
55 "a sceptre pounded in judgment.",
56 "Someone shouts \"Off with %s head!\"", "Queen Beruthiel's cats!",
58 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
59 if (DEADMONSTER(mtmp))
60 continue;
61 if ((mtmp->msleeping || is_lord(mtmp->data)
62 || is_prince(mtmp->data)) && !is_animal(mtmp->data)
63 && mon_in_room(mtmp, COURT)) {
64 /* finding one is enough, at least for now */
65 int which = rn2(3) + hallu;
67 if (which != 2)
68 You_hear1(throne_msg[which]);
69 else
70 pline(throne_msg[2], uhis());
71 return;
75 if (level.flags.has_swamp && !rn2(200)) {
76 static const char *const swamp_msg[3] = {
77 "hear mosquitoes!", "smell marsh gas!", /* so it's a smell...*/
78 "hear Donald Duck!",
80 You1(swamp_msg[rn2(2) + hallu]);
81 return;
83 if (level.flags.has_vault && !rn2(200)) {
84 if (!(sroom = search_special(VAULT))) {
85 /* strange ... */
86 level.flags.has_vault = 0;
87 return;
89 if (gd_sound())
90 switch (rn2(2) + hallu) {
91 case 1: {
92 boolean gold_in_vault = FALSE;
94 for (vx = sroom->lx; vx <= sroom->hx; vx++)
95 for (vy = sroom->ly; vy <= sroom->hy; vy++)
96 if (g_at(vx, vy))
97 gold_in_vault = TRUE;
98 #if defined(AMIGA) && defined(AZTEC_C_WORKAROUND)
99 /* Bug in aztec assembler here. Workaround below */
100 xx = ROOM_INDEX(sroom) + ROOMOFFSET;
101 xx = (xx != vault_occupied(u.urooms));
102 if (xx)
103 #else
104 if (vault_occupied(u.urooms)
105 != (ROOM_INDEX(sroom) + ROOMOFFSET))
106 #endif /* AZTEC_C_WORKAROUND */
108 if (gold_in_vault)
109 You_hear(!hallu
110 ? "someone counting money."
111 : "the quarterback calling the play.");
112 else
113 You_hear("someone searching.");
114 break;
116 /* fall into... (yes, even for hallucination) */
118 case 0:
119 You_hear("the footsteps of a guard on patrol.");
120 break;
121 case 2:
122 You_hear("Ebenezer Scrooge!");
123 break;
125 return;
127 if (level.flags.has_beehive && !rn2(200)) {
128 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
129 if (DEADMONSTER(mtmp))
130 continue;
131 if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data))
132 && mon_in_room(mtmp, BEEHIVE)) {
133 switch (rn2(2) + hallu) {
134 case 0:
135 You_hear("a low buzzing.");
136 break;
137 case 1:
138 You_hear("an angry drone.");
139 break;
140 case 2:
141 You_hear("bees in your %sbonnet!",
142 uarmh ? "" : "(nonexistent) ");
143 break;
145 return;
149 if (level.flags.has_morgue && !rn2(200)) {
150 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
151 if (DEADMONSTER(mtmp))
152 continue;
153 if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
154 && mon_in_room(mtmp, MORGUE)) {
155 const char *hair = body_part(HAIR); /* hair/fur/scales */
157 switch (rn2(2) + hallu) {
158 case 0:
159 You("suddenly realize it is unnaturally quiet.");
160 break;
161 case 1:
162 pline_The("%s on the back of your %s %s up.", hair,
163 body_part(NECK), vtense(hair, "stand"));
164 break;
165 case 2:
166 pline_The("%s on your %s %s to stand up.", hair,
167 body_part(HEAD), vtense(hair, "seem"));
168 break;
170 return;
174 if (level.flags.has_barracks && !rn2(200)) {
175 static const char *const barracks_msg[4] = {
176 "blades being honed.", "loud snoring.", "dice being thrown.",
177 "General MacArthur!",
179 int count = 0;
181 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
182 if (DEADMONSTER(mtmp))
183 continue;
184 if (is_mercenary(mtmp->data)
185 #if 0 /* don't bother excluding these */
186 && !strstri(mtmp->data->mname, "watch")
187 && !strstri(mtmp->data->mname, "guard")
188 #endif
189 && mon_in_room(mtmp, BARRACKS)
190 /* sleeping implies not-yet-disturbed (usually) */
191 && (mtmp->msleeping || ++count > 5)) {
192 You_hear1(barracks_msg[rn2(3) + hallu]);
193 return;
197 if (level.flags.has_zoo && !rn2(200)) {
198 static const char *const zoo_msg[3] = {
199 "a sound reminiscent of an elephant stepping on a peanut.",
200 "a sound reminiscent of a seal barking.", "Doctor Dolittle!",
202 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
203 if (DEADMONSTER(mtmp))
204 continue;
205 if ((mtmp->msleeping || is_animal(mtmp->data))
206 && mon_in_room(mtmp, ZOO)) {
207 You_hear1(zoo_msg[rn2(2) + hallu]);
208 return;
212 if (level.flags.has_shop && !rn2(200)) {
213 if (!(sroom = search_special(ANY_SHOP))) {
214 /* strange... */
215 level.flags.has_shop = 0;
216 return;
218 if (tended_shop(sroom)
219 && !index(u.ushops, (int) (ROOM_INDEX(sroom) + ROOMOFFSET))) {
220 static const char *const shop_msg[3] = {
221 "someone cursing shoplifters.",
222 "the chime of a cash register.", "Neiman and Marcus arguing!",
224 You_hear1(shop_msg[rn2(2) + hallu]);
226 return;
228 if (level.flags.has_temple && !rn2(200)
229 && !(Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) {
230 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
231 if (DEADMONSTER(mtmp))
232 continue;
233 if (mtmp->ispriest && inhistemple(mtmp)
234 /* priest must be active */
235 && mtmp->mcanmove && !mtmp->msleeping
236 /* hero must be outside this temple */
237 && temple_occupied(u.urooms) != EPRI(mtmp)->shroom)
238 break;
240 if (mtmp) {
241 /* Generic temple messages; no attempt to match topic or tone
242 to the pantheon involved, let alone to the specific deity.
243 These are assumed to be coming from the attending priest;
244 asterisk means that the priest must be capable of speech;
245 pound sign (octathorpe,&c--don't go there) means that the
246 priest and the altar must not be directly visible (we don't
247 care if telepathy or extended detection reveals that the
248 priest is not currently standing on the altar; he's mobile). */
249 static const char *const temple_msg[] = {
250 "*someone praising %s.", "*someone beseeching %s.",
251 "#an animal carcass being offered in sacrifice.",
252 "*a strident plea for donations.",
254 const char *msg;
255 int trycount = 0, ax = EPRI(mtmp)->shrpos.x,
256 ay = EPRI(mtmp)->shrpos.y;
257 boolean speechless = (mtmp->data->msound <= MS_ANIMAL),
258 in_sight = canseemon(mtmp) || cansee(ax, ay);
260 do {
261 msg = temple_msg[rn2(SIZE(temple_msg) - 1 + hallu)];
262 if (index(msg, '*') && speechless)
263 continue;
264 if (index(msg, '#') && in_sight)
265 continue;
266 break; /* msg is acceptable */
267 } while (++trycount < 50);
268 while (!letter(*msg))
269 ++msg; /* skip control flags */
270 if (index(msg, '%'))
271 You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
272 else
273 You_hear1(msg);
274 return;
277 if (Is_oracle_level(&u.uz) && !rn2(400)) {
278 /* make sure the Oracle is still here */
279 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
280 if (DEADMONSTER(mtmp))
281 continue;
282 if (mtmp->data == &mons[PM_ORACLE])
283 break;
285 /* and don't produce silly effects when she's clearly visible */
286 if (mtmp && (hallu || !canseemon(mtmp))) {
287 static const char *const ora_msg[5] = {
288 "a strange wind.", /* Jupiter at Dodona */
289 "convulsive ravings.", /* Apollo at Delphi */
290 "snoring snakes.", /* AEsculapius at Epidaurus */
291 "someone say \"No more woodchucks!\"",
292 "a loud ZOT!" /* both rec.humor.oracle */
294 You_hear1(ora_msg[rn2(3) + hallu * 2]);
296 return;
300 static const char *const h_sounds[] = {
301 "beep", "boing", "sing", "belche", "creak", "cough",
302 "rattle", "ululate", "pop", "jingle", "sniffle", "tinkle",
303 "eep", "clatter", "hum", "sizzle", "twitter", "wheeze",
304 "rustle", "honk", "lisp", "yodel", "coo", "burp",
305 "moo", "boom", "murmur", "oink", "quack", "rumble",
306 "twang", "bellow", "toot", "gargle", "hoot", "warble"
309 const char *
310 growl_sound(mtmp)
311 register struct monst *mtmp;
313 const char *ret;
315 switch (mtmp->data->msound) {
316 case MS_MEW:
317 case MS_HISS:
318 ret = "hiss";
319 break;
320 case MS_BARK:
321 case MS_GROWL:
322 ret = "growl";
323 break;
324 case MS_ROAR:
325 ret = "roar";
326 break;
327 case MS_BUZZ:
328 ret = "buzz";
329 break;
330 case MS_SQEEK:
331 ret = "squeal";
332 break;
333 case MS_SQAWK:
334 ret = "screech";
335 break;
336 case MS_NEIGH:
337 ret = "neigh";
338 break;
339 case MS_WAIL:
340 ret = "wail";
341 break;
342 case MS_SILENT:
343 ret = "commotion";
344 break;
345 default:
346 ret = "scream";
348 return ret;
351 /* the sounds of a seriously abused pet, including player attacking it */
352 void
353 growl(mtmp)
354 register struct monst *mtmp;
356 register const char *growl_verb = 0;
358 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
359 return;
361 /* presumably nearness and soundok checks have already been made */
362 if (Hallucination)
363 growl_verb = h_sounds[rn2(SIZE(h_sounds))];
364 else
365 growl_verb = growl_sound(mtmp);
366 if (growl_verb) {
367 pline("%s %s!", Monnam(mtmp), vtense((char *) 0, growl_verb));
368 if (context.run)
369 nomul(0);
370 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18);
374 /* the sounds of mistreated pets */
375 void
376 yelp(mtmp)
377 register struct monst *mtmp;
379 register const char *yelp_verb = 0;
381 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
382 return;
384 /* presumably nearness and soundok checks have already been made */
385 if (Hallucination)
386 yelp_verb = h_sounds[rn2(SIZE(h_sounds))];
387 else
388 switch (mtmp->data->msound) {
389 case MS_MEW:
390 yelp_verb = (!Deaf) ? "yowl" : "arch";
391 break;
392 case MS_BARK:
393 case MS_GROWL:
394 yelp_verb = (!Deaf) ? "yelp" : "recoil";
395 break;
396 case MS_ROAR:
397 yelp_verb = (!Deaf) ? "snarl" : "bluff";
398 break;
399 case MS_SQEEK:
400 yelp_verb = (!Deaf) ? "squeal" : "quiver";
401 break;
402 case MS_SQAWK:
403 yelp_verb = (!Deaf) ? "screak" : "thrash";
404 break;
405 case MS_WAIL:
406 yelp_verb = (!Deaf) ? "wail" : "cringe";
407 break;
409 if (yelp_verb) {
410 pline("%s %s!", Monnam(mtmp), vtense((char *) 0, yelp_verb));
411 if (context.run)
412 nomul(0);
413 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
417 /* the sounds of distressed pets */
418 void
419 whimper(mtmp)
420 register struct monst *mtmp;
422 register const char *whimper_verb = 0;
424 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
425 return;
427 /* presumably nearness and soundok checks have already been made */
428 if (Hallucination)
429 whimper_verb = h_sounds[rn2(SIZE(h_sounds))];
430 else
431 switch (mtmp->data->msound) {
432 case MS_MEW:
433 case MS_GROWL:
434 whimper_verb = "whimper";
435 break;
436 case MS_BARK:
437 whimper_verb = "whine";
438 break;
439 case MS_SQEEK:
440 whimper_verb = "squeal";
441 break;
443 if (whimper_verb) {
444 pline("%s %s.", Monnam(mtmp), vtense((char *) 0, whimper_verb));
445 if (context.run)
446 nomul(0);
447 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6);
451 /* pet makes "I'm hungry" noises */
452 void
453 beg(mtmp)
454 register struct monst *mtmp;
456 if (mtmp->msleeping || !mtmp->mcanmove
457 || !(carnivorous(mtmp->data) || herbivorous(mtmp->data)))
458 return;
460 /* presumably nearness and soundok checks have already been made */
461 if (!is_silent(mtmp->data) && mtmp->data->msound <= MS_ANIMAL)
462 (void) domonnoise(mtmp);
463 else if (mtmp->data->msound >= MS_HUMANOID) {
464 if (!canspotmon(mtmp))
465 map_invisible(mtmp->mx, mtmp->my);
466 verbalize("I'm hungry.");
470 /* return True if mon is a gecko or seems to look like one (hallucination) */
471 STATIC_OVL boolean
472 mon_is_gecko(mon)
473 struct monst *mon;
475 int glyph;
477 /* return True if it is actually a gecko */
478 if (mon->data == &mons[PM_GECKO])
479 return TRUE;
480 /* return False if it is a long worm; we might be chatting to its tail
481 (not strictly needed; long worms are MS_SILENT so won't get here) */
482 if (mon->data == &mons[PM_LONG_WORM])
483 return FALSE;
484 /* result depends upon whether map spot shows a gecko, which will
485 be due to hallucination or to mimickery since mon isn't one */
486 glyph = glyph_at(mon->mx, mon->my);
487 return (boolean) (glyph_to_mon(glyph) == PM_GECKO);
490 STATIC_OVL int
491 domonnoise(mtmp)
492 register struct monst *mtmp;
494 char verbuf[BUFSZ];
495 register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
496 *verbl_msg = 0, /* verbalize() */
497 *verbl_msg_mcan = 0; /* verbalize() if cancelled */
498 struct permonst *ptr = mtmp->data;
499 int msound = ptr->msound;
501 /* presumably nearness and sleep checks have already been made */
502 if (Deaf)
503 return 0;
504 if (is_silent(ptr))
505 return 0;
507 /* leader might be poly'd; if he can still speak, give leader speech */
508 if (mtmp->m_id == quest_status.leader_m_id && msound > MS_ANIMAL)
509 msound = MS_LEADER;
510 /* make sure it's your role's quest guardian; adjust if not */
511 else if (msound == MS_GUARDIAN && ptr != &mons[urole.guardnum])
512 msound = mons[genus(monsndx(ptr), 1)].msound;
513 /* some normally non-speaking types can/will speak if hero is similar */
514 else if (msound == MS_ORC /* note: MS_ORC is same as MS_GRUNT */
515 && (same_race(ptr, youmonst.data) /* current form, */
516 || same_race(ptr, &mons[Race_switch]))) /* unpoly'd form */
517 msound = MS_HUMANOID;
518 /* silliness, with slight chance to interfere with shopping */
519 else if (Hallucination && mon_is_gecko(mtmp))
520 msound = MS_SELL;
522 /* be sure to do this before talking; the monster might teleport away, in
523 * which case we want to check its pre-teleport position
525 if (!canspotmon(mtmp))
526 map_invisible(mtmp->mx, mtmp->my);
528 switch (msound) {
529 case MS_ORACLE:
530 return doconsult(mtmp);
531 case MS_PRIEST:
532 priest_talk(mtmp);
533 break;
534 case MS_LEADER:
535 case MS_NEMESIS:
536 case MS_GUARDIAN:
537 quest_chat(mtmp);
538 break;
539 case MS_SELL: /* pitch, pay, total */
540 if (!Hallucination || (mtmp->isshk && !rn2(2))) {
541 shk_chat(mtmp);
542 } else {
543 /* approximation of GEICO's advertising slogan (it actually
544 concludes with "save you 15% or more on car insurance.") */
545 Sprintf(verbuf, "15 minutes could save you 15 %s.",
546 currency(15L)); /* "zorkmids" */
547 verbl_msg = verbuf;
549 break;
550 case MS_VAMPIRE: {
551 /* vampire messages are varied by tameness, peacefulness, and time of
552 * night */
553 boolean isnight = night();
554 boolean kindred = (Upolyd && (u.umonnum == PM_VAMPIRE
555 || u.umonnum == PM_VAMPIRE_LORD));
556 boolean nightchild =
557 (Upolyd && (u.umonnum == PM_WOLF || u.umonnum == PM_WINTER_WOLF
558 || u.umonnum == PM_WINTER_WOLF_CUB));
559 const char *racenoun =
560 (flags.female && urace.individual.f)
561 ? urace.individual.f
562 : (urace.individual.m) ? urace.individual.m : urace.noun;
564 if (mtmp->mtame) {
565 if (kindred) {
566 Sprintf(verbuf, "Good %s to you Master%s",
567 isnight ? "evening" : "day",
568 isnight ? "!" : ". Why do we not rest?");
569 verbl_msg = verbuf;
570 } else {
571 Sprintf(verbuf, "%s%s",
572 nightchild ? "Child of the night, " : "",
573 midnight()
574 ? "I can stand this craving no longer!"
575 : isnight
576 ? "I beg you, help me satisfy this growing craving!"
577 : "I find myself growing a little weary.");
578 verbl_msg = verbuf;
580 } else if (mtmp->mpeaceful) {
581 if (kindred && isnight) {
582 Sprintf(verbuf, "Good feeding %s!",
583 flags.female ? "sister" : "brother");
584 verbl_msg = verbuf;
585 } else if (nightchild && isnight) {
586 Sprintf(verbuf, "How nice to hear you, child of the night!");
587 verbl_msg = verbuf;
588 } else
589 verbl_msg = "I only drink... potions.";
590 } else {
591 int vampindex;
592 static const char *const vampmsg[] = {
593 /* These first two (0 and 1) are specially handled below */
594 "I vant to suck your %s!",
595 "I vill come after %s without regret!",
596 /* other famous vampire quotes can follow here if desired */
598 if (kindred)
599 verbl_msg =
600 "This is my hunting ground that you dare to prowl!";
601 else if (youmonst.data == &mons[PM_SILVER_DRAGON]
602 || youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
603 /* Silver dragons are silver in color, not made of silver */
604 Sprintf(verbuf, "%s! Your silver sheen does not frighten me!",
605 youmonst.data == &mons[PM_SILVER_DRAGON]
606 ? "Fool"
607 : "Young Fool");
608 verbl_msg = verbuf;
609 } else {
610 vampindex = rn2(SIZE(vampmsg));
611 if (vampindex == 0) {
612 Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
613 verbl_msg = verbuf;
614 } else if (vampindex == 1) {
615 Sprintf(verbuf, vampmsg[vampindex],
616 Upolyd ? an(mons[u.umonnum].mname)
617 : an(racenoun));
618 verbl_msg = verbuf;
619 } else
620 verbl_msg = vampmsg[vampindex];
623 } break;
624 case MS_WERE:
625 if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
626 pline("%s throws back %s head and lets out a blood curdling %s!",
627 Monnam(mtmp), mhis(mtmp),
628 ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl");
629 wake_nearto(mtmp->mx, mtmp->my, 11 * 11);
630 } else
631 pline_msg =
632 "whispers inaudibly. All you can make out is \"moon\".";
633 break;
634 case MS_BARK:
635 if (flags.moonphase == FULL_MOON && night()) {
636 pline_msg = "howls.";
637 } else if (mtmp->mpeaceful) {
638 if (mtmp->mtame
639 && (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
640 || moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
641 pline_msg = "whines.";
642 else if (mtmp->mtame && EDOG(mtmp)->hungrytime > moves + 1000)
643 pline_msg = "yips.";
644 else {
645 if (mtmp->data
646 != &mons[PM_DINGO]) /* dingos do not actually bark */
647 pline_msg = "barks.";
649 } else {
650 pline_msg = "growls.";
652 break;
653 case MS_MEW:
654 if (mtmp->mtame) {
655 if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
656 || mtmp->mtame < 5)
657 pline_msg = "yowls.";
658 else if (moves > EDOG(mtmp)->hungrytime)
659 pline_msg = "meows.";
660 else if (EDOG(mtmp)->hungrytime > moves + 1000)
661 pline_msg = "purrs.";
662 else
663 pline_msg = "mews.";
664 break;
665 } /* else FALLTHRU */
666 case MS_GROWL:
667 pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
668 break;
669 case MS_ROAR:
670 pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
671 break;
672 case MS_SQEEK:
673 pline_msg = "squeaks.";
674 break;
675 case MS_SQAWK:
676 if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
677 verbl_msg = "Nevermore!";
678 else
679 pline_msg = "squawks.";
680 break;
681 case MS_HISS:
682 if (!mtmp->mpeaceful)
683 pline_msg = "hisses!";
684 else
685 return 0; /* no sound */
686 break;
687 case MS_BUZZ:
688 pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
689 break;
690 case MS_GRUNT:
691 pline_msg = "grunts.";
692 break;
693 case MS_NEIGH:
694 if (mtmp->mtame < 5)
695 pline_msg = "neighs.";
696 else if (moves > EDOG(mtmp)->hungrytime)
697 pline_msg = "whinnies.";
698 else
699 pline_msg = "whickers.";
700 break;
701 case MS_WAIL:
702 pline_msg = "wails mournfully.";
703 break;
704 case MS_GURGLE:
705 pline_msg = "gurgles.";
706 break;
707 case MS_BURBLE:
708 pline_msg = "burbles.";
709 break;
710 case MS_SHRIEK:
711 pline_msg = "shrieks.";
712 aggravate();
713 break;
714 case MS_IMITATE:
715 pline_msg = "imitates you.";
716 break;
717 case MS_BONES:
718 pline("%s rattles noisily.", Monnam(mtmp));
719 You("freeze for a moment.");
720 nomul(-2);
721 multi_reason = "scared by rattling";
722 nomovemsg = 0;
723 break;
724 case MS_LAUGH: {
725 static const char *const laugh_msg[4] = {
726 "giggles.", "chuckles.", "snickers.", "laughs.",
728 pline_msg = laugh_msg[rn2(4)];
729 } break;
730 case MS_MUMBLE:
731 pline_msg = "mumbles incomprehensibly.";
732 break;
733 case MS_DJINNI:
734 if (mtmp->mtame) {
735 verbl_msg = "Sorry, I'm all out of wishes.";
736 } else if (mtmp->mpeaceful) {
737 if (ptr == &mons[PM_WATER_DEMON])
738 pline_msg = "gurgles.";
739 else
740 verbl_msg = "I'm free!";
741 } else {
742 if (ptr != &mons[PM_PRISONER])
743 verbl_msg = "This will teach you not to disturb me!";
744 #if 0
745 else
746 verbl_msg = "??????????";
747 #endif
749 break;
750 case MS_BOAST: /* giants */
751 if (!mtmp->mpeaceful) {
752 switch (rn2(4)) {
753 case 0:
754 pline("%s boasts about %s gem collection.", Monnam(mtmp),
755 mhis(mtmp));
756 break;
757 case 1:
758 pline_msg = "complains about a diet of mutton.";
759 break;
760 default:
761 pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
762 wake_nearto(mtmp->mx, mtmp->my, 7 * 7);
763 break;
765 break;
767 /* else FALLTHRU */
768 case MS_HUMANOID:
769 if (!mtmp->mpeaceful) {
770 if (In_endgame(&u.uz) && is_mplayer(ptr))
771 mplayer_talk(mtmp);
772 else
773 pline_msg = "threatens you.";
774 break;
776 /* Generic peaceful humanoid behaviour. */
777 if (mtmp->mflee)
778 pline_msg = "wants nothing to do with you.";
779 else if (mtmp->mhp < mtmp->mhpmax / 4)
780 pline_msg = "moans.";
781 else if (mtmp->mconf || mtmp->mstun)
782 verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
783 else if (!mtmp->mcansee)
784 verbl_msg = "I can't see!";
785 else if (mtmp->mtrapped) {
786 struct trap *t = t_at(mtmp->mx, mtmp->my);
788 if (t)
789 t->tseen = 1;
790 verbl_msg = "I'm trapped!";
791 } else if (mtmp->mhp < mtmp->mhpmax / 2)
792 pline_msg = "asks for a potion of healing.";
793 else if (mtmp->mtame && !mtmp->isminion
794 && moves > EDOG(mtmp)->hungrytime)
795 verbl_msg = "I'm hungry.";
796 /* Specific monsters' interests */
797 else if (is_elf(ptr))
798 pline_msg = "curses orcs.";
799 else if (is_dwarf(ptr))
800 pline_msg = "talks about mining.";
801 else if (likes_magic(ptr))
802 pline_msg = "talks about spellcraft.";
803 else if (ptr->mlet == S_CENTAUR)
804 pline_msg = "discusses hunting.";
805 else
806 switch (monsndx(ptr)) {
807 case PM_HOBBIT:
808 pline_msg =
809 (mtmp->mhpmax - mtmp->mhp >= 10)
810 ? "complains about unpleasant dungeon conditions."
811 : "asks you about the One Ring.";
812 break;
813 case PM_ARCHEOLOGIST:
814 pline_msg =
815 "describes a recent article in \"Spelunker Today\" magazine.";
816 break;
817 case PM_TOURIST:
818 verbl_msg = "Aloha.";
819 break;
820 default:
821 pline_msg = "discusses dungeon exploration.";
822 break;
824 break;
825 case MS_SEDUCE: {
826 int swval;
828 if (SYSOPT_SEDUCE) {
829 if (ptr->mlet != S_NYMPH
830 && could_seduce(mtmp, &youmonst, (struct attack *) 0) == 1) {
831 (void) doseduce(mtmp);
832 break;
834 swval = ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0);
835 } else
836 swval = ((poly_gender() == 0) ? rn2(3) : 0);
837 switch (swval) {
838 case 2:
839 verbl_msg = "Hello, sailor.";
840 break;
841 case 1:
842 pline_msg = "comes on to you.";
843 break;
844 default:
845 pline_msg = "cajoles you.";
847 } break;
848 case MS_ARREST:
849 if (mtmp->mpeaceful)
850 verbalize("Just the facts, %s.", flags.female ? "Ma'am" : "Sir");
851 else {
852 static const char *const arrest_msg[3] = {
853 "Anything you say can be used against you.",
854 "You're under arrest!", "Stop in the name of the Law!",
856 verbl_msg = arrest_msg[rn2(3)];
858 break;
859 case MS_BRIBE:
860 if (mtmp->mpeaceful && !mtmp->mtame) {
861 (void) demon_talk(mtmp);
862 break;
864 /* fall through */
865 case MS_CUSS:
866 if (!mtmp->mpeaceful)
867 cuss(mtmp);
868 else if (is_lminion(mtmp))
869 verbl_msg = "It's not too late.";
870 else
871 verbl_msg = "We're all doomed.";
872 break;
873 case MS_SPELL:
874 /* deliberately vague, since it's not actually casting any spell */
875 pline_msg = "seems to mutter a cantrip.";
876 break;
877 case MS_NURSE:
878 verbl_msg_mcan = "I hate this job!";
879 if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
880 verbl_msg = "Put that weapon away before you hurt someone!";
881 else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
882 verbl_msg = Role_if(PM_HEALER)
883 ? "Doc, I can't help you unless you cooperate."
884 : "Please undress so I can examine you.";
885 else if (uarmu)
886 verbl_msg = "Take off your shirt, please.";
887 else
888 verbl_msg = "Relax, this won't hurt a bit.";
889 break;
890 case MS_GUARD:
891 if (money_cnt(invent))
892 verbl_msg = "Please drop that gold and follow me.";
893 else
894 verbl_msg = "Please follow me.";
895 break;
896 case MS_SOLDIER: {
897 static const char
898 *const soldier_foe_msg[3] =
900 "Resistance is useless!", "You're dog meat!", "Surrender!",
902 *const soldier_pax_msg[3] = {
903 "What lousy pay we're getting here!",
904 "The food's not fit for Orcs!",
905 "My feet hurt, I've been on them all day!",
907 verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
908 : soldier_foe_msg[rn2(3)];
909 break;
911 case MS_RIDER: {
912 const char *tribtitle;
913 struct obj *book = 0;
914 boolean ms_Death = (ptr == &mons[PM_DEATH]);
916 /* 3.6 tribute */
917 if (ms_Death && !context.tribute.Deathnotice
918 && (book = u_have_novel()) != 0) {
919 if ((tribtitle = noveltitle(&book->novelidx)) != 0) {
920 Sprintf(verbuf, "Ah, so you have a copy of /%s/.", tribtitle);
921 /* no Death featured in these two, so exclude them */
922 if (strcmpi(tribtitle, "Snuff")
923 && strcmpi(tribtitle, "The Wee Free Men"))
924 Strcat(verbuf, " I may have been misquoted there.");
925 verbl_msg = verbuf;
927 context.tribute.Deathnotice = 1;
928 } else if (ms_Death && rn2(3) && Death_quote(verbuf, sizeof verbuf)) {
929 verbl_msg = verbuf;
930 /* end of tribute addition */
932 } else if (ms_Death && !rn2(10)) {
933 pline_msg = "is busy reading a copy of Sandman #8.";
934 } else
935 verbl_msg = "Who do you think you are, War?";
936 break;
937 } /* case MS_RIDER */
938 } /* switch */
940 if (pline_msg) {
941 pline("%s %s", Monnam(mtmp), pline_msg);
942 } else if (mtmp->mcan && verbl_msg_mcan) {
943 verbalize1(verbl_msg_mcan);
944 } else if (verbl_msg) {
945 /* more 3.6 tribute */
946 if (ptr == &mons[PM_DEATH]) {
947 /* Death talks in CAPITAL LETTERS
948 and without quotation marks */
949 char tmpbuf[BUFSZ];
951 pline1(ucase(strcpy(tmpbuf, verbl_msg)));
952 } else {
953 verbalize1(verbl_msg);
956 return 1;
959 /* #chat command */
961 dotalk()
963 int result;
965 result = dochat();
966 return result;
969 STATIC_OVL int
970 dochat()
972 struct monst *mtmp;
973 int tx, ty;
974 struct obj *otmp;
976 if (is_silent(youmonst.data)) {
977 pline("As %s, you cannot speak.", an(youmonst.data->mname));
978 return 0;
980 if (Strangled) {
981 You_cant("speak. You're choking!");
982 return 0;
984 if (u.uswallow) {
985 pline("They won't hear you out there.");
986 return 0;
988 if (Underwater) {
989 Your("speech is unintelligible underwater.");
990 return 0;
992 if (Deaf) {
993 pline("How can you hold a conversation when you cannot hear?");
994 return 0;
997 if (!Blind && (otmp = shop_object(u.ux, u.uy)) != (struct obj *) 0) {
998 /* standing on something in a shop and chatting causes the shopkeeper
999 to describe the price(s). This can inhibit other chatting inside
1000 a shop, but that shouldn't matter much. shop_object() returns an
1001 object iff inside a shop and the shopkeeper is present and willing
1002 (not angry) and able (not asleep) to speak and the position
1003 contains any objects other than just gold.
1005 price_quote(otmp);
1006 return 1;
1009 if (!getdir("Talk to whom? (in what direction)")) {
1010 /* decided not to chat */
1011 return 0;
1014 if (u.usteed && u.dz > 0) {
1015 if (!u.usteed->mcanmove || u.usteed->msleeping) {
1016 pline("%s seems not to notice you.", Monnam(u.usteed));
1017 return 1;
1018 } else
1019 return domonnoise(u.usteed);
1022 if (u.dz) {
1023 pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
1024 return 0;
1027 if (u.dx == 0 && u.dy == 0) {
1029 * Let's not include this.
1030 * It raises all sorts of questions: can you wear
1031 * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
1032 * etc... --KAA
1033 if (u.umonnum == PM_ETTIN) {
1034 You("discover that your other head makes boring conversation.");
1035 return 1;
1038 pline("Talking to yourself is a bad habit for a dungeoneer.");
1039 return 0;
1042 tx = u.ux + u.dx;
1043 ty = u.uy + u.dy;
1045 if (!isok(tx, ty))
1046 return 0;
1048 mtmp = m_at(tx, ty);
1050 if ((!mtmp || mtmp->mundetected)
1051 && (otmp = vobj_at(tx, ty)) != 0 && otmp->otyp == STATUE) {
1052 /* Talking to a statue */
1053 if (!Blind) {
1054 pline_The("%s seems not to notice you.",
1055 /* if hallucinating, you can't tell it's a statue */
1056 Hallucination ? rndmonnam((char *) 0) : "statue");
1058 return 0;
1061 if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE
1062 || mtmp->m_ap_type == M_AP_OBJECT)
1063 return 0;
1065 /* sleeping monsters won't talk, except priests (who wake up) */
1066 if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
1067 /* If it is unseen, the player can't tell the difference between
1068 not noticing him and just not existing, so skip the message. */
1069 if (canspotmon(mtmp))
1070 pline("%s seems not to notice you.", Monnam(mtmp));
1071 return 0;
1074 /* if this monster is waiting for something, prod it into action */
1075 mtmp->mstrategy &= ~STRAT_WAITMASK;
1077 if (mtmp->mtame && mtmp->meating) {
1078 if (!canspotmon(mtmp))
1079 map_invisible(mtmp->mx, mtmp->my);
1080 pline("%s is eating noisily.", Monnam(mtmp));
1081 return 0;
1084 return domonnoise(mtmp);
1087 #ifdef USER_SOUNDS
1089 extern void FDECL(play_usersound, (const char *, int));
1091 typedef struct audio_mapping_rec {
1092 struct nhregex *regex;
1093 char *filename;
1094 int volume;
1095 struct audio_mapping_rec *next;
1096 } audio_mapping;
1098 static audio_mapping *soundmap = 0;
1100 char *sounddir = ".";
1102 /* adds a sound file mapping, returns 0 on failure, 1 on success */
1104 add_sound_mapping(mapping)
1105 const char *mapping;
1107 char text[256];
1108 char filename[256];
1109 char filespec[256];
1110 int volume;
1112 if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
1113 filename, &volume) == 3) {
1114 audio_mapping *new_map;
1116 if (strlen(sounddir) + strlen(filename) > 254) {
1117 raw_print("sound file name too long");
1118 return 0;
1120 Sprintf(filespec, "%s/%s", sounddir, filename);
1122 if (can_read_file(filespec)) {
1123 new_map = (audio_mapping *) alloc(sizeof(audio_mapping));
1124 new_map->regex = regex_init();
1125 new_map->filename = dupstr(filespec);
1126 new_map->volume = volume;
1127 new_map->next = soundmap;
1129 if (!regex_compile(text, new_map->regex)) {
1130 raw_print(regex_error_desc(new_map->regex));
1131 regex_free(new_map->regex);
1132 free(new_map->filename);
1133 free(new_map);
1134 return 0;
1135 } else {
1136 soundmap = new_map;
1138 } else {
1139 Sprintf(text, "cannot read %.243s", filespec);
1140 raw_print(text);
1141 return 0;
1143 } else {
1144 raw_print("syntax error in SOUND");
1145 return 0;
1148 return 1;
1151 void
1152 play_sound_for_message(msg)
1153 const char *msg;
1155 audio_mapping *cursor = soundmap;
1157 while (cursor) {
1158 if (regex_match(msg, cursor->regex)) {
1159 play_usersound(cursor->filename, cursor->volume);
1161 cursor = cursor->next;
1165 #endif /* USER_SOUNDS */
1167 /*sounds.c*/