1 /* NetHack 3.7 sounds.c $NHDT-Date: 1600933442 2020/09/24 07:44:02 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.103 $ */
2 /* Copyright (c) 1989 Janet Walz, Mike Threepoint */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "hack.h"
6
7 static boolean mon_is_gecko(struct monst *);
8 static int domonnoise(struct monst *);
9 static int dochat(void);
10 static struct monst *responsive_mon_at(int, int);
11 static int mon_in_room(struct monst *, int);
12
13 /* this easily could be a macro, but it might overtax dumb compilers */
14 static int
mon_in_room(struct monst * mon,int rmtyp)15 mon_in_room(struct monst* mon, int rmtyp)
16 {
17 int rno = levl[mon->mx][mon->my].roomno;
18 if (rno >= ROOMOFFSET)
19 return g.rooms[rno - ROOMOFFSET].rtype == rmtyp;
20 return FALSE;
21 }
22
23 /* Given an x and y space, return the type of the room there. */
24 int
getroomtype(xchar x,xchar y)25 getroomtype(xchar x, xchar y)
26 {
27 int rno = levl[x][y].roomno;
28 if (rno >= ROOMOFFSET) {
29 /* rtype is valid while the level is still being created and up until
30 * the player first enters the room. orig_rtype is only initialized late
31 * in level creation and is effectively valid only after the level is
32 * created. */
33 return g.in_mklev ? g.rooms[rno - ROOMOFFSET].rtype
34 : g.rooms[rno - ROOMOFFSET].orig_rtype;
35 }
36 /* not a room */
37 return OROOM;
38 }
39
40
41 void
dosounds(void)42 dosounds(void)
43 {
44 register struct mkroom *sroom;
45 register int hallu, vx, vy;
46 struct monst *mtmp;
47
48 if (Deaf || !flags.acoustics || u.uswallow || Underwater)
49 return;
50
51 hallu = Hallucination ? 1 : 0;
52
53 if (g.level.flags.nfountains && !rn2(400)) {
54 static const char *const fountain_msg[4] = {
55 "bubbling water.", "water falling on coins.",
56 "the splashing of a naiad.", "a soda fountain!",
57 };
58 You_hear1(fountain_msg[rn2(3) + hallu]);
59 }
60 if (g.level.flags.nsinks && !rn2(300)) {
61 static const char *const sink_msg[3] = {
62 "a slow drip.", "a gurgling noise.", "dishes being washed!",
63 };
64 You_hear1(sink_msg[rn2(2) + hallu]);
65 }
66 if (g.level.flags.has_court && !rn2(200)) {
67 static const char *const throne_msg[4] = {
68 "the tones of courtly conversation.",
69 "a sceptre pounded in judgment.",
70 "Someone shouts \"Off with %s head!\"", "Queen Beruthiel's cats!",
71 };
72 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
73 if (DEADMONSTER(mtmp))
74 continue;
75 if ((mtmp->msleeping || is_lord(mtmp->data)
76 || is_prince(mtmp->data)) && !is_animal(mtmp->data)
77 && mon_in_room(mtmp, COURT)) {
78 /* finding one is enough, at least for now */
79 int which = rn2(3) + hallu;
80
81 if (which != 2)
82 You_hear1(throne_msg[which]);
83 else
84 pline(throne_msg[2], uhis());
85 return;
86 }
87 }
88 }
89 if (g.level.flags.has_swamp && !rn2(200)) {
90 static const char *const swamp_msg[3] = {
91 "hear mosquitoes!", "smell marsh gas!", /* so it's a smell...*/
92 "hear Donald Duck!",
93 };
94 You1(swamp_msg[rn2(2) + hallu]);
95 return;
96 }
97 if (g.level.flags.has_vault && !rn2(200)) {
98 if (!(sroom = search_special(VAULT))) {
99 /* strange ... */
100 g.level.flags.has_vault = 0;
101 return;
102 }
103 if (gd_sound())
104 switch (rn2(2) + hallu) {
105 case 1: {
106 boolean gold_in_vault = FALSE;
107
108 for (vx = sroom->lx; vx <= sroom->hx; vx++)
109 for (vy = sroom->ly; vy <= sroom->hy; vy++)
110 if (g_at(vx, vy))
111 gold_in_vault = TRUE;
112 if (vault_occupied(u.urooms)
113 != (ROOM_INDEX(sroom) + ROOMOFFSET)) {
114 if (gold_in_vault)
115 You_hear(!hallu
116 ? "someone counting gold coins."
117 : "the quarterback calling the play.");
118 else
119 You_hear("someone searching.");
120 break;
121 }
122 }
123 /*FALLTHRU*/
124 case 0:
125 You_hear("the footsteps of a guard on patrol.");
126 break;
127 case 2:
128 You_hear("Ebenezer Scrooge!");
129 break;
130 }
131 return;
132 }
133 if (g.level.flags.has_beehive && !rn2(200)) {
134 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
135 if (DEADMONSTER(mtmp))
136 continue;
137 if (is_bee(mtmp->data)
138 && mon_in_room(mtmp, BEEHIVE)) {
139 switch (rn2(2) + hallu) {
140 case 0:
141 You_hear("a low buzzing.");
142 break;
143 case 1:
144 You_hear("an angry drone.");
145 break;
146 case 2:
147 You_hear("bees in your %sbonnet!",
148 uarmh ? "" : "(nonexistent) ");
149 break;
150 }
151 return;
152 }
153 }
154 }
155 if (g.level.flags.has_morgue && !rn2(200)) {
156 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
157 if (DEADMONSTER(mtmp))
158 continue;
159 if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
160 && mon_in_room(mtmp, MORGUE)) {
161 const char *hair = body_part(HAIR); /* hair/fur/scales */
162
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 %s up.", hair,
169 body_part(NECK), vtense(hair, "stand"));
170 break;
171 case 2:
172 pline_The("%s on your %s %s to stand up.", hair,
173 body_part(HEAD), vtense(hair, "seem"));
174 break;
175 }
176 return;
177 }
178 }
179 }
180 if (g.level.flags.has_barracks && !rn2(200)) {
181 static const char *const barracks_msg[4] = {
182 "blades being honed.", "loud snoring.", "dice being thrown.",
183 "General MacArthur!",
184 };
185 int count = 0;
186
187 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
188 if (DEADMONSTER(mtmp))
189 continue;
190 if (is_mercenary(mtmp->data)
191 #if 0 /* don't bother excluding these */
192 && !strstri(mtmp->data->pmnames[NEUTRAL], "watch")
193 && !strstri(mtmp->data->pmnames[NEUTRAL], "guard")
194 #endif
195 && mon_in_room(mtmp, BARRACKS)
196 /* sleeping implies not-yet-disturbed (usually) */
197 && (mtmp->msleeping || ++count > 5)) {
198 You_hear1(barracks_msg[rn2(3) + hallu]);
199 return;
200 }
201 }
202 }
203 if (g.level.flags.has_zoo && !rn2(200)) {
204 static const char *const zoo_msg[3] = {
205 "a sound reminiscent of an elephant stepping on a peanut.",
206 "a sound reminiscent of a seal barking.", "Doctor Dolittle!",
207 };
208 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
209 if (DEADMONSTER(mtmp))
210 continue;
211 if ((mtmp->msleeping || is_animal(mtmp->data))
212 && mon_in_room(mtmp, ZOO)) {
213 You_hear1(zoo_msg[rn2(2) + hallu]);
214 return;
215 }
216 }
217 }
218 if (g.level.flags.has_shop && !rn2(200)) {
219 if (!(sroom = search_special(ANY_SHOP))) {
220 /* strange... */
221 g.level.flags.has_shop = 0;
222 return;
223 }
224 if (tended_shop(sroom)
225 && !index(u.ushops, (int) (ROOM_INDEX(sroom) + ROOMOFFSET))) {
226 const char *name = shkname(sroom->resident);
227 struct eshk *eshkp = ESHK(sroom->resident);
228 if (!eshkp->visitct) {
229 name = "someone";
230 }
231 static const char *const shop_msg[3] = {
232 "%s cursing shoplifters.",
233 "the chime of a cash register.", "Neiman and Marcus arguing!",
234 };
235 You_hear(shop_msg[rn2(2) + hallu], name);
236 }
237 return;
238 }
239 if (g.level.flags.has_temple && !rn2(200)
240 && !(Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) {
241 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
242 if (DEADMONSTER(mtmp))
243 continue;
244 if (mtmp->ispriest && inhistemple(mtmp)
245 /* priest must be active */
246 && mtmp->mcanmove && !mtmp->msleeping
247 /* hero must be outside this temple */
248 && temple_occupied(u.urooms) != EPRI(mtmp)->shroom)
249 break;
250 }
251 if (mtmp) {
252 /* Generic temple messages; no attempt to match topic or tone
253 to the pantheon involved, let alone to the specific deity.
254 These are assumed to be coming from the attending priest;
255 asterisk means that the priest must be capable of speech;
256 pound sign (octathorpe,&c--don't go there) means that the
257 priest and the altar must not be directly visible (we don't
258 care if telepathy or extended detection reveals that the
259 priest is not currently standing on the altar; he's mobile). */
260 static const char *const temple_msg[] = {
261 "*someone praising %s.", "*someone beseeching %s.",
262 "#an animal carcass being offered in sacrifice.",
263 "*a strident plea for donations.",
264 };
265 const char *msg;
266 int trycount = 0, ax = EPRI(mtmp)->shrpos.x,
267 ay = EPRI(mtmp)->shrpos.y;
268 boolean speechless = (mtmp->data->msound <= MS_ANIMAL),
269 in_sight = canseemon(mtmp) || cansee(ax, ay);
270
271 do {
272 msg = temple_msg[rn2(SIZE(temple_msg) - 1 + hallu)];
273 if (index(msg, '*') && speechless)
274 continue;
275 if (index(msg, '#') && in_sight)
276 continue;
277 break; /* msg is acceptable */
278 } while (++trycount < 50);
279 while (!letter(*msg))
280 ++msg; /* skip control flags */
281 if (index(msg, '%'))
282 You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
283 else
284 You_hear1(msg);
285 return;
286 }
287 }
288 if (Is_oracle_level(&u.uz) && !rn2(400)) {
289 /* make sure the Oracle is still here */
290 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
291 if (DEADMONSTER(mtmp))
292 continue;
293 if (mtmp->data == &mons[PM_ORACLE])
294 break;
295 }
296 /* and don't produce silly effects when she's clearly visible */
297 if (mtmp && (hallu || !canseemon(mtmp))) {
298 static const char *const ora_msg[5] = {
299 "a strange wind.", /* Jupiter at Dodona */
300 "convulsive ravings.", /* Apollo at Delphi */
301 "snoring snakes.", /* AEsculapius at Epidaurus */
302 "someone say \"No more woodchucks!\"",
303 "a loud ZOT!" /* both rec.humor.oracle */
304 };
305 You_hear1(ora_msg[rn2(3) + hallu * 2]);
306 }
307 return;
308 }
309 if (g.level.bonesinfo && !rn2(300)) {
310 struct cemetery *bp;
311 for (bp = g.level.bonesinfo; bp; bp = bp->next) {
312 if (!bp->bonesknown) {
313 /* only give bones noises if there are still undiscovered bones
314 * locations on the level */
315 if (hallu) {
316 You("have a cheery feeling.");
317 }
318 else {
319 You("have an eerie feeling...");
320 }
321 break;
322 }
323 }
324 return;
325 }
326 if (!rn2(300)) {
327 branch *br = Is_branchlev(&u.uz);
328 if (br && In_mines(&br->end2) && !In_mines(&u.uz)) {
329 static const char *const mines_msgs[2] = {
330 "a pick striking rock.", "someone singing 'Gold, gold, gold.'"
331 };
332 You_hear1(mines_msgs[0 + hallu]);
333 return;
334 }
335 else if (br && In_sokoban(&br->end2) && !In_sokoban(&u.uz)
336 && !sokoban_solved(&br->end2)) {
337 static const char *const soko_msgs[2] = {
338 "a deep rolling sound.", "a golfing giant."
339 };
340 You_hear1(soko_msgs[0 + hallu]);
341 return;
342 }
343 else if (br && In_V_tower(&br->end2) && !In_V_tower(&u.uz)
344 && g.mvitals[PM_VLAD_THE_IMPALER].died == 0) {
345 static const char *const vlad_msgs[3] = {
346 "the whispering of leathery wings.",
347 "a horrible choking scream.",
348 "a voice say \"I never drink... wine.\""
349 };
350 You_hear1(vlad_msgs[rn2(2) + hallu]);
351 return;
352 }
353 }
354 if (In_quest(&u.uz) && u.uz.dlevel >= qlocate_level.dlevel
355 && Role_if(PM_ARCHEOLOGIST) && !g.quest_status.touched_artifact
356 && !g.quest_status.met_nemesis && !rn2(300)) {
357 /* special sounds for Arc quest */
358 if (!Deaf) {
359 You_hear("another explosion.");
360 }
361 else {
362 pline("You feel the tremor from another explosion.");
363 }
364 }
365 }
366
367 static const char *const h_sounds[] = {
368 "beep", "boing", "sing", "belche", "creak", "cough",
369 "rattle", "ululate", "pop", "jingle", "sniffle", "tinkle",
370 "eep", "clatter", "hum", "sizzle", "twitter", "wheeze",
371 "rustle", "honk", "lisp", "yodel", "coo", "burp",
372 "moo", "boom", "murmur", "oink", "quack", "rumble",
373 "twang", "bellow", "toot", "gargle", "hoot", "warble"
374 };
375
376 const char *
growl_sound(register struct monst * mtmp)377 growl_sound(register struct monst* mtmp)
378 {
379 const char *ret;
380
381 switch (mtmp->data->msound) {
382 case MS_MEW:
383 case MS_HISS:
384 ret = "hiss";
385 break;
386 case MS_BARK:
387 case MS_GROWL:
388 ret = "growl";
389 break;
390 case MS_ROAR:
391 ret = "roar";
392 break;
393 case MS_BUZZ:
394 ret = "buzz";
395 break;
396 case MS_SQEEK:
397 ret = "squeal";
398 break;
399 case MS_SQAWK:
400 ret = "screech";
401 break;
402 case MS_NEIGH:
403 ret = "neigh";
404 break;
405 case MS_WAIL:
406 ret = "wail";
407 break;
408 case MS_GROAN:
409 ret = "groan";
410 break;
411 case MS_MOO:
412 ret = "low";
413 break;
414 case MS_SILENT:
415 ret = "commotion";
416 break;
417 default:
418 ret = "scream";
419 }
420 return ret;
421 }
422
423 /* the sounds of a seriously abused pet, including player attacking it */
424 void
growl(register struct monst * mtmp)425 growl(register struct monst* mtmp)
426 {
427 register const char *growl_verb = 0;
428
429 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
430 return;
431
432 /* presumably nearness and soundok checks have already been made */
433 if (Hallucination)
434 growl_verb = h_sounds[rn2(SIZE(h_sounds))];
435 else
436 growl_verb = growl_sound(mtmp);
437 if (growl_verb) {
438 pline("%s %s!", Monnam(mtmp), vtense((char *) 0, growl_verb));
439 iflags.last_msg = PLNMSG_GROWL;
440 if (g.context.run)
441 nomul(0);
442 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18);
443 }
444 }
445
446 /* the sounds of mistreated pets */
447 void
yelp(register struct monst * mtmp)448 yelp(register struct monst* mtmp)
449 {
450 register const char *yelp_verb = 0;
451
452 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
453 return;
454
455 /* presumably nearness and soundok checks have already been made */
456 if (Hallucination)
457 yelp_verb = h_sounds[rn2(SIZE(h_sounds))];
458 else
459 switch (mtmp->data->msound) {
460 case MS_MEW:
461 yelp_verb = (!Deaf) ? "yowl" : "arch";
462 break;
463 case MS_BARK:
464 case MS_GROWL:
465 yelp_verb = (!Deaf) ? "yelp" : "recoil";
466 break;
467 case MS_ROAR:
468 yelp_verb = (!Deaf) ? "roar" : "bluff";
469 break;
470 case MS_SQEEK:
471 yelp_verb = (!Deaf) ? "squeal" : "quiver";
472 break;
473 case MS_SQAWK:
474 yelp_verb = (!Deaf) ? "screak" : "thrash";
475 break;
476 case MS_WAIL:
477 yelp_verb = (!Deaf) ? "wail" : "cringe";
478 break;
479 }
480 if (yelp_verb) {
481 pline("%s %s!", Monnam(mtmp), vtense((char *) 0, yelp_verb));
482 if (g.context.run)
483 nomul(0);
484 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
485 }
486 }
487
488 /* the sounds of distressed pets */
489 void
whimper(register struct monst * mtmp)490 whimper(register struct monst* mtmp)
491 {
492 register const char *whimper_verb = 0;
493
494 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
495 return;
496
497 /* presumably nearness and soundok checks have already been made */
498 if (Hallucination)
499 whimper_verb = h_sounds[rn2(SIZE(h_sounds))];
500 else
501 switch (mtmp->data->msound) {
502 case MS_MEW:
503 case MS_GROWL:
504 whimper_verb = "whimper";
505 break;
506 case MS_BARK:
507 whimper_verb = "whine";
508 break;
509 case MS_SQEEK:
510 whimper_verb = "squeal";
511 break;
512 }
513 if (whimper_verb) {
514 pline("%s %s.", Monnam(mtmp), vtense((char *) 0, whimper_verb));
515 if (g.context.run)
516 nomul(0);
517 wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6);
518 }
519 }
520
521 /* pet makes "I'm hungry" noises */
522 void
beg(register struct monst * mtmp)523 beg(register struct monst* mtmp)
524 {
525 if (mtmp->msleeping || !mtmp->mcanmove
526 || !(carnivorous(mtmp->data) || herbivorous(mtmp->data)))
527 return;
528
529 /* presumably nearness and soundok checks have already been made */
530 if (!is_silent(mtmp->data) && mtmp->data->msound <= MS_ANIMAL) {
531 (void) domonnoise(mtmp);
532 } else if (mtmp->data->msound >= MS_HUMANOID) {
533 if (!canspotmon(mtmp))
534 map_invisible(mtmp->mx, mtmp->my);
535 verbalize("I'm hungry.");
536 } else {
537 /* this is pretty lame but is better than leaving out the block
538 of speech types between animal and humanoid; this covers
539 MS_SILENT too (if caller lets that get this far) since it's
540 excluded by the first two cases */
541 if (canspotmon(mtmp))
542 pline("%s seems famished.", Monnam(mtmp));
543 /* looking famished will be a good trick for a tame skeleton... */
544 }
545 }
546
547 /* hero has attacked a peaceful monster within 'mon's view */
548 const char *
maybe_gasp(struct monst * mon)549 maybe_gasp(struct monst* mon)
550 {
551 static const char *const Exclam[] = {
552 "Gasp!", "Uh-oh.", "Oh my!", "What?", "Why?",
553 };
554 struct permonst *mptr = mon->data;
555 int msound = mptr->msound;
556 boolean dogasp = FALSE;
557
558 /* other roles' guardians and cross-aligned priests don't gasp */
559 if ((msound == MS_GUARDIAN && mptr != &mons[g.urole.guardnum])
560 || (msound == MS_PRIEST && !p_coaligned(mon)))
561 msound = MS_SILENT;
562 /* co-aligned angels do gasp */
563 else if (msound == MS_CUSS && has_emin(mon)
564 && (p_coaligned(mon) ? !EMIN(mon)->renegade : EMIN(mon)->renegade))
565 msound = MS_HUMANOID;
566
567 /*
568 * Only called for humanoids so animal noise handling is ignored.
569 */
570 switch (msound) {
571 case MS_HUMANOID:
572 case MS_ARREST: /* Kops */
573 case MS_SOLDIER: /* solider, watchman */
574 case MS_GUARD: /* vault guard */
575 case MS_NURSE:
576 case MS_SEDUCE: /* nymph, succubus/incubus */
577 case MS_LEADER: /* quest leader */
578 case MS_GUARDIAN: /* leader's guards */
579 case MS_SELL: /* shopkeeper */
580 case MS_ORACLE:
581 case MS_PRIEST: /* temple priest, roaming aligned priest (not mplayer) */
582 case MS_BOAST: /* giants */
583 case MS_IMITATE: /* doppelganger, leocrotta, Aleax */
584 dogasp = TRUE;
585 break;
586 /* issue comprehensible word(s) if hero is similar type of creature */
587 case MS_ORC: /* used to be synonym for MS_GRUNT */
588 case MS_GRUNT: /* ogres, trolls, gargoyles, one or two others */
589 case MS_LAUGH: /* leprechaun, gremlin */
590 case MS_ROAR: /* dragon, xorn, owlbear */
591 /* capable of speech but only do so if hero is similar type */
592 case MS_DJINNI:
593 case MS_VAMPIRE: /* vampire in its own form */
594 case MS_WERE: /* lycanthrope in human form */
595 case MS_SPELL: /* titan, barrow wight, Nazgul, nalfeshnee */
596 dogasp = (mptr->mlet == g.youmonst.data->mlet);
597 break;
598 /* capable of speech but don't care if you attack peacefuls */
599 case MS_BRIBE:
600 case MS_CUSS:
601 case MS_RIDER:
602 case MS_NEMESIS:
603 /* can't speak */
604 case MS_SILENT:
605 default:
606 break;
607 }
608 if (dogasp) {
609 return Exclam[rn2(SIZE(Exclam))]; /* [mon->m_id % SIZE(Exclam)]; */
610 }
611 return (const char *) 0;
612 }
613
614 /* return True if mon is a gecko or seems to look like one (hallucination) */
615 static boolean
mon_is_gecko(struct monst * mon)616 mon_is_gecko(struct monst* mon)
617 {
618 int glyph;
619
620 /* return True if it is actually a gecko */
621 if (mon->data == &mons[PM_GECKO])
622 return TRUE;
623 /* return False if it is a long worm; we might be chatting to its tail
624 (not strictly needed; long worms are MS_SILENT so won't get here) */
625 if (mon->data == &mons[PM_LONG_WORM])
626 return FALSE;
627 /* result depends upon whether map spot shows a gecko, which will
628 be due to hallucination or to mimickery since mon isn't one */
629 glyph = glyph_at(mon->mx, mon->my);
630 return (boolean) (glyph_to_mon(glyph) == PM_GECKO);
631 }
632
633 DISABLE_WARNING_FORMAT_NONLITERAL
634
635 static int
domonnoise(register struct monst * mtmp)636 domonnoise(register struct monst* mtmp)
637 {
638 char verbuf[BUFSZ];
639 register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
640 *verbl_msg = 0, /* verbalize() */
641 *verbl_msg_mcan = 0; /* verbalize() if cancelled */
642 struct permonst *ptr = mtmp->data;
643 int msound = ptr->msound, gnomeplan = 0;
644
645 /* presumably nearness and sleep checks have already been made */
646 if (Deaf)
647 return 0;
648 if (is_silent(ptr))
649 return 0;
650
651 /* leader might be poly'd; if he can still speak, give leader speech */
652 if (mtmp->m_id == g.quest_status.leader_m_id && msound > MS_ANIMAL)
653 msound = MS_LEADER;
654 /* make sure it's your role's quest guardian; adjust if not */
655 else if (msound == MS_GUARDIAN && ptr != &mons[g.urole.guardnum])
656 msound = mons[genus(monsndx(ptr), 1)].msound;
657 /* some normally non-speaking types can/will speak if hero is similar */
658 else if (msound == MS_ORC
659 && ((same_race(ptr, g.youmonst.data) /* current form, */
660 || same_race(ptr, &mons[Race_switch])) /* unpoly'd form */
661 || Hallucination))
662 msound = MS_HUMANOID;
663 /* silliness, with slight chance to interfere with shopping */
664 else if (Hallucination && mon_is_gecko(mtmp))
665 msound = MS_SELL;
666
667 /* be sure to do this before talking; the monster might teleport away, in
668 * which case we want to check its pre-teleport position
669 */
670 if (!canspotmon(mtmp))
671 map_invisible(mtmp->mx, mtmp->my);
672
673 switch (msound) {
674 case MS_ORACLE:
675 return doconsult(mtmp);
676 case MS_PRIEST:
677 priest_talk(mtmp);
678 break;
679 case MS_LEADER:
680 case MS_NEMESIS:
681 case MS_GUARDIAN:
682 quest_chat(mtmp);
683 break;
684 case MS_SELL: /* pitch, pay, total */
685 if (!Hallucination || (mtmp->isshk && !rn2(2))) {
686 shk_chat(mtmp);
687 } else {
688 /* approximation of GEICO's advertising slogan (it actually
689 concludes with "save you 15% or more on car insurance.") */
690 Strcat(verbuf, "15 minutes could save you 15 zorkmids.");
691 }
692 break;
693 case MS_VAMPIRE: {
694 /* vampire messages are varied by tameness, peacefulness, and time of
695 * night */
696 boolean isnight = night();
697 boolean kindred = (Upolyd && (u.umonnum == PM_VAMPIRE
698 || u.umonnum == PM_VAMPIRE_LEADER));
699 boolean nightchild =
700 (Upolyd && (u.umonnum == PM_WOLF || u.umonnum == PM_WINTER_WOLF
701 || u.umonnum == PM_WINTER_WOLF_CUB));
702 const char *racenoun =
703 (flags.female && g.urace.individual.f)
704 ? g.urace.individual.f
705 : (g.urace.individual.m) ? g.urace.individual.m : g.urace.noun;
706
707 if (mtmp->mtame) {
708 if (kindred) {
709 Sprintf(verbuf, "Good %s to you Master%s",
710 isnight ? "evening" : "day",
711 isnight ? "!" : ". Why do we not rest?");
712 verbl_msg = verbuf;
713 } else {
714 Sprintf(verbuf, "%s%s",
715 nightchild ? "Child of the night, " : "",
716 midnight()
717 ? "I can stand this craving no longer!"
718 : isnight
719 ? "I beg you, help me satisfy this growing craving!"
720 : "I find myself growing a little weary.");
721 verbl_msg = verbuf;
722 }
723 } else if (mtmp->mpeaceful) {
724 if (kindred && isnight) {
725 Sprintf(verbuf, "Good feeding %s!",
726 flags.female ? "sister" : "brother");
727 verbl_msg = verbuf;
728 } else if (nightchild && isnight) {
729 Sprintf(verbuf, "How nice to hear you, child of the night!");
730 verbl_msg = verbuf;
731 } else
732 verbl_msg = "I only drink... potions.";
733 } else {
734 static const char *const vampmsg[] = {
735 /* These first two (0 and 1) are specially handled below */
736 "I vant to suck your %s!",
737 "I vill come after %s without regret!",
738 /* other famous vampire quotes can follow here if desired */
739 };
740 int vampindex;
741
742 if (kindred)
743 verbl_msg =
744 "This is my hunting ground that you dare to prowl!";
745 else if (g.youmonst.data == &mons[PM_SILVER_DRAGON]
746 || g.youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
747 /* Silver dragons are silver in color, not made of silver */
748 Sprintf(verbuf, "%s! Your silver sheen does not frighten me!",
749 g.youmonst.data == &mons[PM_SILVER_DRAGON]
750 ? "Fool"
751 : "Young Fool");
752 verbl_msg = verbuf;
753 } else {
754 vampindex = rn2(SIZE(vampmsg));
755 if (vampindex == 0) {
756 Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
757 verbl_msg = verbuf;
758 } else if (vampindex == 1) {
759 Sprintf(verbuf, vampmsg[vampindex],
760 Upolyd ? an(pmname(&mons[u.umonnum],
761 flags.female ? FEMALE : MALE))
762 : an(racenoun));
763 verbl_msg = verbuf;
764 } else
765 verbl_msg = vampmsg[vampindex];
766 }
767 }
768 break;
769 }
770 case MS_WERE:
771 if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
772 pline("%s throws back %s head and lets out a blood curdling %s!",
773 Monnam(mtmp), mhis(mtmp),
774 (ptr == &mons[PM_HUMAN_WERERAT]) ? "shriek" : "howl");
775 wake_nearto(mtmp->mx, mtmp->my, 11 * 11);
776 } else
777 pline_msg =
778 "whispers inaudibly. All you can make out is \"moon\".";
779 break;
780 case MS_BARK:
781 if (flags.moonphase == FULL_MOON && night()) {
782 pline_msg = "howls.";
783 } else if (mtmp->mpeaceful) {
784 if (mtmp->mtame
785 && (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
786 || g.moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
787 pline_msg = "whines.";
788 else if (mtmp->mtame && EDOG(mtmp)->hungrytime > g.moves + 1000)
789 pline_msg = "yips.";
790 else {
791 if (mtmp->data
792 != &mons[PM_DINGO]) /* dingos do not actually bark */
793 pline_msg = "barks.";
794 }
795 } else {
796 pline_msg = "growls.";
797 }
798 break;
799 case MS_MEW:
800 if (mtmp->mtame) {
801 if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped
802 || mtmp->mtame < 5)
803 pline_msg = "yowls.";
804 else if (g.moves > EDOG(mtmp)->hungrytime)
805 pline_msg = "meows.";
806 else if (EDOG(mtmp)->hungrytime > g.moves + 1000)
807 pline_msg = "purrs.";
808 else
809 pline_msg = "mews.";
810 break;
811 }
812 /*FALLTHRU*/
813 case MS_GROWL:
814 pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
815 break;
816 case MS_ROAR:
817 pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
818 break;
819 case MS_SQEEK:
820 pline_msg = "squeaks.";
821 break;
822 case MS_SQAWK:
823 if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
824 verbl_msg = "Nevermore!";
825 else
826 pline_msg = "squawks.";
827 break;
828 case MS_HISS:
829 if (!mtmp->mpeaceful)
830 pline_msg = "hisses!";
831 else
832 return 0; /* no sound */
833 break;
834 case MS_BUZZ:
835 pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
836 break;
837 case MS_GRUNT:
838 pline_msg = "grunts.";
839 break;
840 case MS_NEIGH:
841 if (mtmp->mtame < 5)
842 pline_msg = "neighs.";
843 else if (g.moves > EDOG(mtmp)->hungrytime)
844 pline_msg = "whinnies.";
845 else
846 pline_msg = "whickers.";
847 break;
848 case MS_MOO:
849 pline_msg = mtmp->mpeaceful ? "moos." : "bellows!";
850 break;
851 case MS_WAIL:
852 pline_msg = "wails mournfully.";
853 break;
854 case MS_GROAN:
855 if (rn2(10) || !(ptr->mlet == S_ZOMBIE))
856 pline_msg = "groans.";
857 else
858 verbl_msg = "Braaaaaains...";
859 break;
860 case MS_GURGLE:
861 pline_msg = "gurgles.";
862 break;
863 case MS_BURBLE:
864 pline_msg = "burbles.";
865 break;
866 case MS_TRUMPET:
867 pline_msg = "trumpets!";
868 wake_nearto(mtmp->mx, mtmp->my, 11 * 11);
869 break;
870 case MS_SHRIEK:
871 pline_msg = "shrieks.";
872 aggravate();
873 break;
874 case MS_IMITATE:
875 pline_msg = "imitates you.";
876 break;
877 case MS_BONES:
878 pline("%s rattles noisily.", Monnam(mtmp));
879 You("freeze for a moment.");
880 nomul(-2);
881 g.multi_reason = "scared by rattling";
882 g.nomovemsg = 0;
883 break;
884 case MS_LAUGH: {
885 static const char *const laugh_msg[4] = {
886 "giggles.", "chuckles.", "snickers.", "laughs.",
887 };
888 pline_msg = laugh_msg[rn2(4)];
889 break;
890 }
891 case MS_MUMBLE:
892 pline_msg = "mumbles incomprehensibly.";
893 break;
894 case MS_ORC: /* this used to be an alias for grunt, now it is distinct */
895 pline_msg = "grunts.";
896 break;
897 case MS_DJINNI:
898 if (mtmp->mtame) {
899 verbl_msg = "Sorry, I'm all out of wishes.";
900 } else if (mtmp->mpeaceful) {
901 if (ptr == &mons[PM_WATER_DEMON])
902 pline_msg = "gurgles.";
903 else
904 verbl_msg = "I'm free!";
905 } else {
906 if (ptr != &mons[PM_PRISONER])
907 verbl_msg = "This will teach you not to disturb me!";
908 else /* vague because prisoner might already be out of cell */
909 verbl_msg = "Get me out of here.";
910 }
911 break;
912 case MS_BOAST: /* giants */
913 if (!mtmp->mpeaceful) {
914 switch (rn2(4)) {
915 case 0:
916 pline("%s boasts about %s gem collection.", Monnam(mtmp),
917 mhis(mtmp));
918 break;
919 case 1:
920 pline_msg = "complains about a diet of mutton.";
921 break;
922 default:
923 pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
924 wake_nearto(mtmp->mx, mtmp->my, 7 * 7);
925 break;
926 }
927 break;
928 }
929 /*FALLTHRU*/
930 case MS_HUMANOID:
931 if (!mtmp->mpeaceful) {
932 if (In_endgame(&u.uz) && is_mplayer(ptr))
933 mplayer_talk(mtmp);
934 else
935 pline_msg = "threatens you.";
936 break;
937 }
938 /* Generic peaceful humanoid behaviour. */
939 if (mtmp->mflee)
940 pline_msg = "wants nothing to do with you.";
941 else if (mtmp->mhp < mtmp->mhpmax / 4)
942 pline_msg = "moans.";
943 else if (mtmp->mconf || mtmp->mstun)
944 verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
945 else if (!mtmp->mcansee)
946 verbl_msg = "I can't see!";
947 else if (mtmp->mtrapped) {
948 struct trap *t = t_at(mtmp->mx, mtmp->my);
949
950 if (t)
951 t->tseen = 1;
952 verbl_msg = "I'm trapped!";
953 } else if (mtmp->mhp < mtmp->mhpmax / 2)
954 pline_msg = "asks for a potion of healing.";
955 else if (mtmp->mtame && !mtmp->isminion
956 && g.moves > EDOG(mtmp)->hungrytime)
957 verbl_msg = "I'm hungry.";
958 /* Specific monsters' interests */
959 else if (is_elf(ptr))
960 pline_msg = "curses orcs.";
961 else if (is_dwarf(ptr))
962 pline_msg = "talks about mining.";
963 else if (is_gnome(ptr))
964 verbl_msg =
965 "Many enter the dungeon, and few return to the sunlit lands.";
966 else if (likes_magic(ptr))
967 pline_msg = "talks about spellcraft.";
968 else if (ptr->mlet == S_CENTAUR)
969 pline_msg = "discusses hunting.";
970 else if (is_gnome(ptr)) {
971 if (Hallucination && (gnomeplan = rn2(4)) % 2) {
972 /* skipped for rn2(4) result of 0 or 2;
973 gag from an early episode of South Park called "Gnomes";
974 initially, Tweek (introduced in that episode) is the only
975 one aware of the tiny gnomes after spotting them sneaking
976 about; they are embarked upon a three-step business plan;
977 a diagram of the plan shows:
978 Phase 1 Phase 2 Phase 3
979 Collect underpants ? Profit
980 and they never verbalize step 2 so we don't either */
981 verbl_msg = (gnomeplan == 1) ? "Phase one, collect underpants."
982 : "Phase three, profit!";
983 }
984 else {
985 verbl_msg =
986 "Many enter the dungeon, and few return to the sunlit lands.";
987 }
988 }
989 else
990 switch (monsndx(ptr)) {
991 case PM_HOBBIT:
992 pline_msg =
993 (mtmp->mhpmax - mtmp->mhp >= 10)
994 ? "complains about unpleasant dungeon conditions."
995 : "asks you about the One Ring.";
996 break;
997 case PM_ARCHEOLOGIST:
998 pline_msg =
999 "describes a recent article in \"Spelunker Today\" magazine.";
1000 break;
1001 case PM_TOURIST:
1002 verbl_msg = "Aloha.";
1003 break;
1004 default:
1005 pline_msg = "discusses dungeon exploration.";
1006 break;
1007 }
1008 break;
1009 case MS_SEDUCE: {
1010 int swval;
1011
1012 if (SYSOPT_SEDUCE) {
1013 if (ptr->mlet != S_NYMPH
1014 && could_seduce(mtmp, &g.youmonst, (struct attack *) 0) == 1) {
1015 (void) doseduce(mtmp);
1016 break;
1017 }
1018 swval = ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0);
1019 } else
1020 swval = ((poly_gender() == 0) ? rn2(3) : 0);
1021 switch (swval) {
1022 case 2:
1023 verbl_msg = "Hello, sailor.";
1024 break;
1025 case 1:
1026 pline_msg = "comes on to you.";
1027 break;
1028 default:
1029 pline_msg = "cajoles you.";
1030 }
1031 } break;
1032 case MS_ARREST:
1033 if (mtmp->mpeaceful)
1034 verbalize("Just the facts, %s.", flags.female ? "Ma'am" : "Sir");
1035 else {
1036 static const char *const arrest_msg[3] = {
1037 "Anything you say can be used against you.",
1038 "You're under arrest!", "Stop in the name of the Law!",
1039 };
1040 verbl_msg = arrest_msg[rn2(3)];
1041 }
1042 break;
1043 case MS_BRIBE:
1044 if (mtmp->mpeaceful && !mtmp->mtame) {
1045 (void) demon_talk(mtmp);
1046 break;
1047 }
1048 /* fall through */
1049 case MS_CUSS:
1050 if (!mtmp->mpeaceful)
1051 cuss(mtmp);
1052 else if (is_lminion(mtmp))
1053 verbl_msg = "It's not too late.";
1054 else
1055 verbl_msg = "We're all doomed.";
1056 break;
1057 case MS_SPELL:
1058 /* deliberately vague, since it's not actually casting any spell */
1059 pline_msg = "seems to mutter a cantrip.";
1060 break;
1061 case MS_NURSE:
1062 verbl_msg_mcan = "I hate this job!";
1063 if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
1064 verbl_msg = "Put that weapon away before you hurt someone!";
1065 else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
1066 verbl_msg = Role_if(PM_HEALER)
1067 ? "Doc, I can't help you unless you cooperate."
1068 : "Please undress so I can examine you.";
1069 else if (uarmu)
1070 verbl_msg = "Take off your shirt, please.";
1071 else
1072 verbl_msg = "Relax, this won't hurt a bit.";
1073 break;
1074 case MS_GUARD:
1075 if (money_cnt(g.invent))
1076 verbl_msg = "Please drop that gold and follow me.";
1077 else
1078 verbl_msg = "Please follow me.";
1079 break;
1080 case MS_SOLDIER: {
1081 static const char
1082 *const soldier_foe_msg[3] = {
1083 "Resistance is useless!", "You're dog meat!", "Surrender!",
1084 },
1085 *const soldier_pax_msg[3] = {
1086 "What lousy pay we're getting here!",
1087 "The food's not fit for Orcs!",
1088 "My feet hurt, I've been on them all day!",
1089 };
1090 verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
1091 : soldier_foe_msg[rn2(3)];
1092 break;
1093 }
1094 case MS_RIDER: {
1095 const char *tribtitle;
1096 struct obj *book = 0;
1097 boolean ms_Death = (ptr == &mons[PM_DEATH]);
1098
1099 /* 3.6 tribute */
1100 if (ms_Death && !g.context.tribute.Deathnotice
1101 && (book = u_have_novel()) != 0) {
1102 if ((tribtitle = noveltitle(&book->novelidx)) != 0) {
1103 Sprintf(verbuf, "Ah, so you have a copy of /%s/.", tribtitle);
1104 /* no Death featured in these two, so exclude them */
1105 if (strcmpi(tribtitle, "Snuff")
1106 && strcmpi(tribtitle, "The Wee Free Men"))
1107 Strcat(verbuf, " I may have been misquoted there.");
1108 verbl_msg = verbuf;
1109 }
1110 g.context.tribute.Deathnotice = 1;
1111 } else if (ms_Death && rn2(3) && Death_quote(verbuf, sizeof verbuf)) {
1112 verbl_msg = verbuf;
1113 /* end of tribute addition */
1114
1115 } else if (ms_Death && !rn2(10)) {
1116 pline_msg = "is busy reading a copy of Sandman #8.";
1117 } else
1118 verbl_msg = "Who do you think you are, War?";
1119 break;
1120 } /* case MS_RIDER */
1121 } /* switch */
1122
1123 if (pline_msg) {
1124 pline("%s %s", Monnam(mtmp), pline_msg);
1125 } else if (mtmp->mcan && verbl_msg_mcan) {
1126 verbalize1(verbl_msg_mcan);
1127 } else if (verbl_msg) {
1128 /* more 3.6 tribute */
1129 if (ptr == &mons[PM_DEATH]) {
1130 /* Death talks in CAPITAL LETTERS
1131 and without quotation marks */
1132 char tmpbuf[BUFSZ];
1133
1134 pline1(ucase(strcpy(tmpbuf, verbl_msg)));
1135 } else {
1136 verbalize1(verbl_msg);
1137 }
1138 }
1139 return 1;
1140 }
1141
1142 RESTORE_WARNING_FORMAT_NONLITERAL
1143
1144 /* #chat command */
1145 int
dotalk(void)1146 dotalk(void)
1147 {
1148 int result;
1149
1150 result = dochat();
1151 return result;
1152 }
1153
1154 static int
dochat(void)1155 dochat(void)
1156 {
1157 struct monst *mtmp;
1158 int tx, ty;
1159 struct obj *otmp;
1160
1161 if (is_silent(g.youmonst.data)) {
1162 pline("As %s, you cannot speak.",
1163 an(pmname(g.youmonst.data, flags.female ? FEMALE : MALE)));
1164 return 0;
1165 }
1166 if (Strangled) {
1167 You_cant("speak. You're choking!");
1168 return 0;
1169 }
1170 if (u.uswallow) {
1171 pline("They won't hear you out there.");
1172 return 0;
1173 }
1174 if (Underwater) {
1175 Your("speech is unintelligible underwater.");
1176 return 0;
1177 }
1178 if (Deaf) {
1179 pline("How can you hold a conversation when you cannot hear?");
1180 return 0;
1181 }
1182
1183 if (!Blind && (otmp = shop_object(u.ux, u.uy)) != (struct obj *) 0) {
1184 /* standing on something in a shop and chatting causes the shopkeeper
1185 to describe the price(s). This can inhibit other chatting inside
1186 a shop, but that shouldn't matter much. shop_object() returns an
1187 object iff inside a shop and the shopkeeper is present and willing
1188 (not angry) and able (not asleep) to speak and the position
1189 contains any objects other than just gold.
1190 */
1191 price_quote(otmp);
1192 return 1;
1193 }
1194
1195 if (!getdir("Talk to whom? (in what direction)")) {
1196 /* decided not to chat */
1197 return 0;
1198 }
1199
1200 if (u.usteed && u.dz > 0) {
1201 if (!u.usteed->mcanmove || u.usteed->msleeping) {
1202 pline("%s seems not to notice you.", Monnam(u.usteed));
1203 return 1;
1204 } else
1205 return domonnoise(u.usteed);
1206 }
1207
1208 if (u.dz) {
1209 pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
1210 return 0;
1211 }
1212
1213 if (u.dx == 0 && u.dy == 0) {
1214 /*
1215 * Let's not include this.
1216 * It raises all sorts of questions: can you wear
1217 * 2 helmets, 2 amulets, 3 pairs of gloves or 6 rings as a marilith,
1218 * etc... --KAA
1219 if (u.umonnum == PM_ETTIN) {
1220 You("discover that your other head makes boring conversation.");
1221 return 1;
1222 }
1223 */
1224 pline("Talking to yourself is a bad habit for a dungeoneer.");
1225 return 0;
1226 }
1227
1228 tx = u.ux + u.dx;
1229 ty = u.uy + u.dy;
1230
1231 if (!isok(tx, ty))
1232 return 0;
1233
1234 mtmp = m_at(tx, ty);
1235
1236 if (!mtmp || mtmp->mundetected) {
1237 if ((otmp = vobj_at(tx, ty)) != 0 && otmp->otyp == STATUE) {
1238 /* Talking to a statue */
1239 if (!Blind)
1240 pline_The("%s seems not to notice you.",
1241 /* if hallucinating, you can't tell it's a statue */
1242 Hallucination ? rndmonnam((char *) 0) : "statue");
1243 return 0;
1244 }
1245 if (IS_WALL(levl[tx][ty].typ) || levl[tx][ty].typ == SDOOR) {
1246 /* Talking to a wall; secret door remains hidden by behaving
1247 like a wall; IS_WALL() test excludes solid rock even when
1248 that serves as a wall bordering a corridor */
1249 if (Blind && !IS_WALL(g.lastseentyp[tx][ty])) {
1250 /* when blind, you can only talk to a wall if it has
1251 already been mapped as a wall */
1252 ;
1253 } else if (!Hallucination) {
1254 /* Walls have ears, not mouths. */
1255 pline(rn2(2) ? "The wall listens intently, but doesn't reply."
1256 : "It's like talking to a wall.");
1257 } else {
1258 static const char *const walltalk[] = {
1259 "gripes about its job.",
1260 "tells you a funny joke!",
1261 "insults your heritage!",
1262 "chuckles.",
1263 "guffaws merrily!",
1264 "deprecates your exploration efforts.",
1265 "suggests a stint of rehab...",
1266 "doesn't seem to be interested.",
1267 };
1268 int idx = rn2(10);
1269
1270 if (idx >= SIZE(walltalk))
1271 idx = SIZE(walltalk) - 1;
1272 pline_The("wall %s", walltalk[idx]);
1273 }
1274 return 0;
1275 }
1276 }
1277
1278 if (!mtmp || mtmp->mundetected
1279 || M_AP_TYPE(mtmp) == M_AP_FURNITURE
1280 || M_AP_TYPE(mtmp) == M_AP_OBJECT)
1281 return 0;
1282
1283 /* sleeping monsters won't talk, except priests (who wake up) */
1284 if ((!mtmp->mcanmove || mtmp->msleeping) && !mtmp->ispriest) {
1285 /* If it is unseen, the player can't tell the difference between
1286 not noticing him and just not existing, so skip the message. */
1287 if (canspotmon(mtmp))
1288 pline("%s seems not to notice you.", Monnam(mtmp));
1289 return 0;
1290 }
1291
1292 /* if this monster is waiting for something, prod it into action */
1293 mtmp->mstrategy &= ~STRAT_WAITMASK;
1294
1295 if (mtmp->mtame && mtmp->meating) {
1296 if (!canspotmon(mtmp))
1297 map_invisible(mtmp->mx, mtmp->my);
1298 pline("%s is eating noisily.", Monnam(mtmp));
1299 return 0;
1300 }
1301
1302 return domonnoise(mtmp);
1303 }
1304
1305 /* is there a monster at <x,y> that can see the hero and react? */
1306 static struct monst *
responsive_mon_at(int x,int y)1307 responsive_mon_at(int x, int y)
1308 {
1309 struct monst *mtmp = isok(x, y) ? m_at(x, y) : 0;
1310
1311 if (mtmp && (!mtmp->mcanmove || mtmp->msleeping /* immobilized monst */
1312 || !mtmp->mcansee || !haseyes(mtmp->data) /* blind monst */
1313 || (Invis && !perceives(mtmp->data)) /* unseen hero */
1314 || (x != mtmp->mx || y != mtmp->my))) /* worm tail */
1315 mtmp = (struct monst *) 0;
1316 return mtmp;
1317 }
1318
1319 /* player chose 'uarmh' for #tip (pickup.c); visual #chat, sort of... */
1320 int
tiphat(void)1321 tiphat(void)
1322 {
1323 struct monst *mtmp;
1324 struct obj *otmp;
1325 int x, y, range, glyph, vismon, unseen, statue, res;
1326
1327 if (!uarmh) /* can't get here from there */
1328 return 0;
1329
1330 res = uarmh->bknown ? 0 : 1;
1331 if (cursed(uarmh)) /* "You can't. It is cursed." */
1332 return res; /* if learned of curse, use a move */
1333
1334 /* might choose a position, but dealing with direct lines is simpler */
1335 if (!getdir("At whom? (in what direction)")) /* bail on ESC */
1336 return res; /* iffy; now know it's not cursed for sure (since we got
1337 * past prior test) but might have already known that */
1338 res = 1; /* physical action is going to take place */
1339
1340 /* most helmets have a short wear/take-off delay and we could set
1341 'multi' to account for that, but we'll pretend that no extra time
1342 beyond the current move is necessary */
1343 You("briefly doff your %s.", helm_simple_name(uarmh));
1344
1345 if (!u.dx && !u.dy) {
1346 if (u.usteed && u.dz > 0) {
1347 if (!u.usteed->mcanmove || u.usteed->msleeping)
1348 pline("%s doesn't notice.", Monnam(u.usteed));
1349 else
1350 (void) domonnoise(u.usteed);
1351 } else if (u.dz) {
1352 pline("There's no one %s there.", (u.dz < 0) ? "up" : "down");
1353 } else {
1354 pline_The("lout here doesn't acknowledge you...");
1355 }
1356 return res;
1357 }
1358
1359 mtmp = (struct monst *) 0;
1360 vismon = unseen = statue = 0, glyph = GLYPH_MON_OFF;
1361 x = u.ux, y = u.uy;
1362 for (range = 1; range <= BOLT_LIM + 1; ++range) {
1363 x += u.dx, y += u.dy;
1364 if (!isok(x, y) || (range > 1 && !couldsee(x, y))) {
1365 /* switch back to coordinates for previous interation's 'mtmp' */
1366 x -= u.dx, y -= u.dy;
1367 break;
1368 }
1369 mtmp = m_at(x, y);
1370 vismon = (mtmp && canseemon(mtmp));
1371 glyph = glyph_at(x, y);
1372 unseen = glyph_is_invisible(glyph);
1373 statue = (glyph_is_statue(glyph) /* mimic or hallucinatory statue */
1374 || (!vismon && !unseen && (otmp = vobj_at(x, y)) != 0
1375 && otmp->otyp == STATUE)); /* or actual statue */
1376 if (vismon && (M_AP_TYPE(mtmp) == M_AP_FURNITURE
1377 || M_AP_TYPE(mtmp) == M_AP_OBJECT))
1378 vismon = 0, mtmp = (struct monst *) 0;
1379 if (vismon || unseen || (statue && Hallucination)
1380 /* unseen adjacent monster will respond if able */
1381 || (range == 1 && mtmp && responsive_mon_at(x, y)
1382 && !is_silent(mtmp->data))
1383 /* we check accessible() after m_at() in case there's a
1384 visible monster phazing through a wall here */
1385 || !(accessible(x, y) || levl[x][y].typ == IRONBARS))
1386 break;
1387 }
1388
1389 if (unseen || (statue && Hallucination)) {
1390 pline("That %screature is ignoring you!", unseen ? "unseen " : "");
1391 } else if (!mtmp || !responsive_mon_at(x, y)) {
1392 if (vismon) /* 'vismon' is only True when 'mtmp' is non-Null */
1393 pline("%s seems not to notice you.", Monnam(mtmp));
1394 else
1395 goto nada;
1396 } else { /* 'mtmp' is guaranteed to be non-Null if we get here */
1397 /* if this monster is waiting for something, prod it into action */
1398 mtmp->mstrategy &= ~STRAT_WAITMASK;
1399
1400 if (vismon && humanoid(mtmp->data) && mtmp->mpeaceful && !Conflict) {
1401 if ((otmp = which_armor(mtmp, W_ARMH)) == 0) {
1402 pline("%s waves.", Monnam(mtmp));
1403 } else if (otmp->cursed) {
1404 pline("%s grasps %s %s but can't remove it.", Monnam(mtmp),
1405 mhis(mtmp), helm_simple_name(otmp));
1406 otmp->bknown = 1;
1407 } else {
1408 pline("%s tips %s %s in response.", Monnam(mtmp),
1409 mhis(mtmp), helm_simple_name(otmp));
1410 }
1411 } else if (vismon && humanoid(mtmp->data)) {
1412 static const char *const reaction[3] = {
1413 "curses", "gestures rudely", "gestures offensively",
1414 };
1415 int which = !Deaf ? rn2(3) : rn1(2, 1),
1416 twice = (Deaf || which > 0 || rn2(3)) ? 0 : rn1(2, 1);
1417
1418 pline("%s %s%s%s at you...", Monnam(mtmp), reaction[which],
1419 twice ? " and " : "", twice ? reaction[twice] : "");
1420 } else if (distu(x, y) <= 2 && !Deaf && domonnoise(mtmp)) {
1421 if (!vismon)
1422 map_invisible(x, y);
1423 } else if (vismon) {
1424 pline("%s doesn't respond.", Monnam(mtmp));
1425 } else {
1426 nada:
1427 pline("%s", nothing_happens);
1428 }
1429 }
1430 return res;
1431 }
1432
1433 #ifdef USER_SOUNDS
1434
1435 #if defined(WIN32) || defined(QT_GRAPHICS)
1436 extern void play_usersound(const char *, int);
1437 #endif
1438 #if defined(TTY_SOUND_ESCCODES)
1439 extern void play_usersound_via_idx(int, int);
1440 #endif
1441
1442 typedef struct audio_mapping_rec {
1443 struct nhregex *regex;
1444 char *filename;
1445 int volume;
1446 int idx;
1447 struct audio_mapping_rec *next;
1448 } audio_mapping;
1449
1450 static audio_mapping *soundmap = 0;
1451 static audio_mapping *sound_matches_message(const char *);
1452
1453 char *sounddir = 0; /* set in files.c */
1454
1455 /* adds a sound file mapping, returns 0 on failure, 1 on success */
1456 int
add_sound_mapping(const char * mapping)1457 add_sound_mapping(const char* mapping)
1458 {
1459 char text[256];
1460 char filename[256];
1461 char filespec[256];
1462 int volume, idx = -1;
1463
1464 if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d %d", text,
1465 filename, &volume, &idx) == 4
1466 || sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", text,
1467 filename, &volume) == 3) {
1468 audio_mapping *new_map;
1469
1470 if (!sounddir)
1471 sounddir = dupstr(".");
1472 if (strlen(sounddir) + 1 + strlen(filename) >= sizeof filespec) {
1473 raw_print("sound file name too long");
1474 return 0;
1475 }
1476 Snprintf(filespec, sizeof filespec, "%s/%s", sounddir, filename);
1477
1478 if (idx >= 0 || can_read_file(filespec)) {
1479 new_map = (audio_mapping *) alloc(sizeof *new_map);
1480 new_map->regex = regex_init();
1481 new_map->filename = dupstr(filespec);
1482 new_map->volume = volume;
1483 new_map->idx = idx;
1484 new_map->next = soundmap;
1485
1486 if (!regex_compile(text, new_map->regex)) {
1487 const char *re_error_desc = regex_error_desc(new_map->regex);
1488
1489 regex_free(new_map->regex);
1490 free((genericptr_t) new_map->filename);
1491 free((genericptr_t) new_map);
1492 raw_print(re_error_desc);
1493 return 0;
1494 } else {
1495 soundmap = new_map;
1496 }
1497 } else {
1498 Sprintf(text, "cannot read %.243s", filespec);
1499 raw_print(text);
1500 return 0;
1501 }
1502 } else {
1503 raw_print("syntax error in SOUND");
1504 return 0;
1505 }
1506
1507 return 1;
1508 }
1509
1510 static audio_mapping *
sound_matches_message(const char * msg)1511 sound_matches_message(const char* msg)
1512 {
1513 audio_mapping *snd = soundmap;
1514
1515 while (snd) {
1516 if (regex_match(msg, snd->regex))
1517 return snd;
1518 snd = snd->next;
1519 }
1520 return (audio_mapping *) 0;
1521 }
1522
1523 void
play_sound_for_message(const char * msg)1524 play_sound_for_message(const char* msg)
1525 {
1526 audio_mapping *snd = sound_matches_message(msg);
1527
1528 if (snd)
1529 play_usersound(snd->filename, snd->volume);
1530 }
1531
1532 void
maybe_play_sound(const char * msg)1533 maybe_play_sound(const char* msg)
1534 {
1535 #if defined(WIN32) || defined(QT_GRAPHICS) || defined(TTY_SOUND_ESCCODES)
1536 audio_mapping *snd = sound_matches_message(msg);
1537
1538 if (snd
1539 #if defined(WIN32) || defined(QT_GRAPHICS)
1540 #ifdef TTY_SOUND_ESCCODES
1541 && !iflags.vt_sounddata
1542 #endif
1543 #if defined(QT_GRAPHICS)
1544 && WINDOWPORT("Qt")
1545 #endif
1546 #if defined(WIN32)
1547 && (WINDOWPORT("tty") || WINDOWPORT("mswin") || WINDOWPORT("curses"))
1548 #endif
1549 #endif /* WIN32 || QT_GRAPHICS */
1550 )
1551 play_usersound(snd->filename, snd->volume);
1552 #if defined(TTY_GRAPHICS) && defined(TTY_SOUND_ESCCODES)
1553 else if (snd && iflags.vt_sounddata && snd->idx >= 0 && WINDOWPORT("tty"))
1554 play_usersound_via_idx(snd->idx, snd->volume);
1555 #endif /* TTY_GRAPHICS && TTY_SOUND_ESCCODES */
1556 #endif /* WIN32 || QT_GRAPHICS || TTY_SOUND_ESCCODES */
1557 }
1558
1559 void
release_sound_mappings(void)1560 release_sound_mappings(void)
1561 {
1562 audio_mapping *nextsound = 0;
1563
1564 while (soundmap) {
1565 nextsound = soundmap->next;
1566 regex_free(soundmap->regex);
1567 free((genericptr_t) soundmap->filename);
1568 free((genericptr_t) soundmap);
1569 soundmap = nextsound;
1570 }
1571
1572 if (sounddir)
1573 free((genericptr_t) sounddir), sounddir = 0;
1574 }
1575
1576 #endif /* USER_SOUNDS */
1577
1578 /*sounds.c*/
1579