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