Use define for iron ball weight increment
[aNetHack.git] / src / sounds.c
blobeaf36487d1bddb41afd207414ff33c2078457cdd
1 /* NetHack 3.6 sounds.c $NHDT-Date: 1450461632 2015/12/18 18:00:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.77 $ */
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;
827 if (SYSOPT_SEDUCE) {
828 if (ptr->mlet != S_NYMPH
829 && could_seduce(mtmp, &youmonst, (struct attack *) 0) == 1) {
830 (void) doseduce(mtmp);
831 break;
833 swval = ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0);
834 } else
835 swval = ((poly_gender() == 0) ? rn2(3) : 0);
836 switch (swval) {
837 case 2:
838 verbl_msg = "Hello, sailor.";
839 break;
840 case 1:
841 pline_msg = "comes on to you.";
842 break;
843 default:
844 pline_msg = "cajoles you.";
846 } break;
847 case MS_ARREST:
848 if (mtmp->mpeaceful)
849 verbalize("Just the facts, %s.", flags.female ? "Ma'am" : "Sir");
850 else {
851 static const char *const arrest_msg[3] = {
852 "Anything you say can be used against you.",
853 "You're under arrest!", "Stop in the name of the Law!",
855 verbl_msg = arrest_msg[rn2(3)];
857 break;
858 case MS_BRIBE:
859 if (mtmp->mpeaceful && !mtmp->mtame) {
860 (void) demon_talk(mtmp);
861 break;
863 /* fall through */
864 case MS_CUSS:
865 if (!mtmp->mpeaceful)
866 cuss(mtmp);
867 else if (is_lminion(mtmp))
868 verbl_msg = "It's not too late.";
869 else
870 verbl_msg = "We're all doomed.";
871 break;
872 case MS_SPELL:
873 /* deliberately vague, since it's not actually casting any spell */
874 pline_msg = "seems to mutter a cantrip.";
875 break;
876 case MS_NURSE:
877 verbl_msg_mcan = "I hate this job!";
878 if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
879 verbl_msg = "Put that weapon away before you hurt someone!";
880 else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
881 verbl_msg = Role_if(PM_HEALER)
882 ? "Doc, I can't help you unless you cooperate."
883 : "Please undress so I can examine you.";
884 else if (uarmu)
885 verbl_msg = "Take off your shirt, please.";
886 else
887 verbl_msg = "Relax, this won't hurt a bit.";
888 break;
889 case MS_GUARD:
890 if (money_cnt(invent))
891 verbl_msg = "Please drop that gold and follow me.";
892 else
893 verbl_msg = "Please follow me.";
894 break;
895 case MS_SOLDIER: {
896 static const char
897 *const soldier_foe_msg[3] =
899 "Resistance is useless!", "You're dog meat!", "Surrender!",
901 *const soldier_pax_msg[3] = {
902 "What lousy pay we're getting here!",
903 "The food's not fit for Orcs!",
904 "My feet hurt, I've been on them all day!",
906 verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
907 : soldier_foe_msg[rn2(3)];
908 break;
910 case MS_RIDER:
911 /* 3.6 tribute */
912 if (ptr == &mons[PM_DEATH]
913 && !context.tribute.Deathnotice && u_have_novel()) {
914 struct obj *book = u_have_novel();
915 const char *tribtitle = (char *)0;
917 if (book) {
918 int novelidx = book->novelidx;
920 tribtitle = noveltitle(&novelidx);
922 if (tribtitle) {
923 Sprintf(verbuf, "Ah, so you have a copy of /%s/.", tribtitle);
924 /* no Death featured in these two, so exclude them */
925 if (!(strcmpi(tribtitle, "Snuff") == 0
926 || strcmpi(tribtitle, "The Wee Free Men") == 0))
927 Strcat(verbuf, " I may have been misquoted there.");
928 verbl_msg = verbuf;
929 context.tribute.Deathnotice = 1;
931 } else if (ptr == &mons[PM_DEATH]
932 && !rn2(2) && Death_quote(verbuf, BUFSZ)) {
933 verbl_msg = verbuf;
935 /* end of tribute addition */
936 else if (ptr == &mons[PM_DEATH] && !rn2(10))
937 pline_msg = "is busy reading a copy of Sandman #8.";
938 else
939 verbl_msg = "Who do you think you are, War?";
940 break;
943 if (pline_msg)
944 pline("%s %s", Monnam(mtmp), pline_msg);
945 else if (mtmp->mcan && verbl_msg_mcan)
946 verbalize1(verbl_msg_mcan);
947 else if (verbl_msg) {
948 if (ptr == &mons[PM_DEATH]) {
949 /* Death talks in CAPITAL LETTERS
950 and without quotation marks */
951 char tmpbuf[BUFSZ];
952 Sprintf(tmpbuf, "%s", verbl_msg);
953 pline1(ucase(tmpbuf));
954 } else {
955 verbalize1(verbl_msg);
958 return 1;
961 /* #chat command */
963 dotalk()
965 int result;
967 result = dochat();
968 return result;
971 STATIC_OVL int
972 dochat()
974 struct monst *mtmp;
975 int tx, ty;
976 struct obj *otmp;
978 if (is_silent(youmonst.data)) {
979 pline("As %s, you cannot speak.", an(youmonst.data->mname));
980 return 0;
982 if (Strangled) {
983 You_cant("speak. You're choking!");
984 return 0;
986 if (u.uswallow) {
987 pline("They won't hear you out there.");
988 return 0;
990 if (Underwater) {
991 Your("speech is unintelligible underwater.");
992 return 0;
994 if (Deaf) {
995 pline("How can you hold a conversation when you cannot hear?");
996 return 0;
999 if (!Blind && (otmp = shop_object(u.ux, u.uy)) != (struct obj *) 0) {
1000 /* standing on something in a shop and chatting causes the shopkeeper
1001 to describe the price(s). This can inhibit other chatting inside
1002 a shop, but that shouldn't matter much. shop_object() returns an
1003 object iff inside a shop and the shopkeeper is present and willing
1004 (not angry) and able (not asleep) to speak and the position
1005 contains any objects other than just gold.
1007 price_quote(otmp);
1008 return 1;
1011 if (!getdir("Talk to whom? (in what direction)")) {
1012 /* decided not to chat */
1013 return 0;
1016 if (u.usteed && u.dz > 0) {
1017 if (!u.usteed->mcanmove || u.usteed->msleeping) {
1018 pline("%s seems not to notice you.", Monnam(u.usteed));
1019 return 1;
1020 } else
1021 return domonnoise(u.usteed);
1024 if (u.dz) {
1025 pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
1026 return 0;
1029 if (u.dx == 0 && u.dy == 0) {
1031 * Let's not include this.
1032 * It raises all sorts of questions: can you wear
1033 * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
1034 * etc... --KAA
1035 if (u.umonnum == PM_ETTIN) {
1036 You("discover that your other head makes boring conversation.");
1037 return 1;
1040 pline("Talking to yourself is a bad habit for a dungeoneer.");
1041 return 0;
1044 tx = u.ux + u.dx;
1045 ty = u.uy + u.dy;
1047 if (!isok(tx, ty))
1048 return 0;
1050 mtmp = m_at(tx, ty);
1052 if ((!mtmp || mtmp->mundetected)
1053 && (otmp = vobj_at(tx, ty)) != 0 && otmp->otyp == STATUE) {
1054 /* Talking to a statue */
1055 if (!Blind) {
1056 pline_The("%s seems not to notice you.",
1057 /* if hallucinating, you can't tell it's a statue */
1058 Hallucination ? rndmonnam((char *) 0) : "statue");
1060 return 0;
1063 if (!mtmp || mtmp->mundetected || mtmp->m_ap_type == M_AP_FURNITURE
1064 || mtmp->m_ap_type == M_AP_OBJECT)
1065 return 0;
1067 /* sleeping monsters won't talk, except priests (who wake up) */
1068 if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
1069 /* If it is unseen, the player can't tell the difference between
1070 not noticing him and just not existing, so skip the message. */
1071 if (canspotmon(mtmp))
1072 pline("%s seems not to notice you.", Monnam(mtmp));
1073 return 0;
1076 /* if this monster is waiting for something, prod it into action */
1077 mtmp->mstrategy &= ~STRAT_WAITMASK;
1079 if (mtmp->mtame && mtmp->meating) {
1080 if (!canspotmon(mtmp))
1081 map_invisible(mtmp->mx, mtmp->my);
1082 pline("%s is eating noisily.", Monnam(mtmp));
1083 return 0;
1086 return domonnoise(mtmp);
1089 #ifdef USER_SOUNDS
1091 extern void FDECL(play_usersound, (const char *, int));
1093 typedef struct audio_mapping_rec {
1094 struct nhregex *regex;
1095 char *filename;
1096 int volume;
1097 struct audio_mapping_rec *next;
1098 } audio_mapping;
1100 static audio_mapping *soundmap = 0;
1102 char *sounddir = ".";
1104 /* adds a sound file mapping, returns 0 on failure, 1 on success */
1106 add_sound_mapping(mapping)
1107 const char *mapping;
1109 char text[256];
1110 char filename[256];
1111 char filespec[256];
1112 int volume;
1114 if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
1115 filename, &volume) == 3) {
1116 audio_mapping *new_map;
1118 if (strlen(sounddir) + strlen(filename) > 254) {
1119 raw_print("sound file name too long");
1120 return 0;
1122 Sprintf(filespec, "%s/%s", sounddir, filename);
1124 if (can_read_file(filespec)) {
1125 new_map = (audio_mapping *) alloc(sizeof(audio_mapping));
1126 new_map->regex = regex_init();
1127 new_map->filename = dupstr(filespec);
1128 new_map->volume = volume;
1129 new_map->next = soundmap;
1131 if (!regex_compile(text, new_map->regex)) {
1132 raw_print(regex_error_desc(new_map->regex));
1133 regex_free(new_map->regex);
1134 free(new_map->filename);
1135 free(new_map);
1136 return 0;
1137 } else {
1138 soundmap = new_map;
1140 } else {
1141 Sprintf(text, "cannot read %.243s", filespec);
1142 raw_print(text);
1143 return 0;
1145 } else {
1146 raw_print("syntax error in SOUND");
1147 return 0;
1150 return 1;
1153 void
1154 play_sound_for_message(msg)
1155 const char *msg;
1157 audio_mapping *cursor = soundmap;
1159 while (cursor) {
1160 if (regex_match(msg, cursor->regex)) {
1161 play_usersound(cursor->filename, cursor->volume);
1163 cursor = cursor->next;
1167 #endif /* USER_SOUNDS */
1169 /*sounds.c*/