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