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*/