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. */
8 # ifdef USER_SOUNDS_REGEX
15 static int FDECL(domonnoise,(struct monst *));
16 static int NDECL(dochat);
22 static int FDECL(mon_in_room, (struct monst *,int));
24 /* this easily could be a macro, but it might overtax dumb compilers */
26 mon_in_room(mon, rmtyp)
30 int rno = levl[mon->mx][mon->my].roomno;
32 return rooms[rno - ROOMOFFSET].rtype == rmtyp;
38 register struct mkroom *sroom;
39 register int hallu, vx, vy;
40 #if defined(AMIGA) && defined(AZTEC_C_WORKAROUND)
45 if (!flags.soundok || u.uswallow || Underwater) return;
47 hallu = Hallucination ? 1 : 0;
49 if (level.flags.nfountains && !rn2(400)) {
50 static const char * const fountain_msg[4] = {
52 "water falling on coins.",
53 "the splashing of a naiad.",
56 You_hear(fountain_msg[rn2(3)+hallu]);
59 if (level.flags.nsinks && !rn2(300)) {
60 static const char * const sink_msg[3] = {
63 "dishes being washed!",
65 You_hear(sink_msg[rn2(2)+hallu]);
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!",
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;
84 if (which != 2) You_hear(throne_msg[which]);
85 else pline(throne_msg[2], uhis());
90 if (level.flags.has_swamp && !rn2(200)) {
91 static const char * const swamp_msg[3] = {
93 "smell marsh gas!", /* so it's a smell...*/
96 You(swamp_msg[rn2(2)+hallu]);
99 if (level.flags.has_vault && !rn2(200)) {
100 if (!(sroom = search_special(VAULT))) {
102 level.flags.has_vault = 0;
106 switch (rn2(2)+hallu) {
108 boolean gold_in_vault = FALSE;
110 for (vx = sroom->lx;vx <= sroom->hx; vx++)
111 for (vy = sroom->ly; vy <= sroom->hy; 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));
120 if (vault_occupied(u.urooms) !=
121 (ROOM_INDEX(sroom) + ROOMOFFSET))
122 #endif /* AZTEC_C_WORKAROUND */
125 You_hear(!hallu ? "someone counting money." :
126 "the quarterback calling the play.");
128 You_hear("someone searching.");
131 /* fall into... (yes, even for hallucination) */
134 You_hear("the footsteps of a guard on patrol.");
137 You_hear("Ebenezer Scrooge!");
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) {
149 You_hear("a low buzzing.");
152 You_hear("an angry drone.");
155 You_hear("bees in your %sbonnet!",
156 uarmh ? "" : "(nonexistent) ");
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) {
170 You("suddenly realize it is unnaturally quiet.");
173 pline_The("%s on the back of your %s stands up.",
174 body_part(HAIR), body_part(NECK));
177 pline_The("%s on your %s seems to stand up.",
178 body_part(HAIR), body_part(HEAD));
185 if (level.flags.has_barracks && !rn2(200)) {
186 static const char * const barracks_msg[4] = {
187 "blades being honed.",
189 "dice being thrown.",
190 "General MacArthur!",
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") &&
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]);
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.",
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]);
224 if (level.flags.has_shop && !rn2(200)) {
225 if (!(sroom = search_special(ANY_SHOP))) {
227 level.flags.has_shop = 0;
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!",
237 You_hear(shop_msg[rn2(2)+hallu]);
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])
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 */
255 You_hear(ora_msg[rn2(3)+hallu*2]);
264 static const char * const h_sounds[] = {
265 "beep", "boing", "sing", "belche", "creak", "cough", "rattle",
266 "ululate", "pop", "jingle", "sniffle", "tinkle", "eep"
271 register struct monst *mtmp;
275 switch (mtmp->data->msound) {
311 /* the sounds of a seriously abused pet, including player attacking it */
314 register struct monst *mtmp;
316 register const char *growl_verb = 0;
318 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
321 /* presumably nearness and soundok checks have already been made */
323 growl_verb = h_sounds[rn2(SIZE(h_sounds))];
325 growl_verb = growl_sound(mtmp);
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);
333 /* the sounds of mistreated pets */
336 register struct monst *mtmp;
338 register const char *yelp_verb = 0;
340 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
343 /* presumably nearness and soundok checks have already been made */
345 yelp_verb = h_sounds[rn2(SIZE(h_sounds))];
346 else switch (mtmp->data->msound) {
358 yelp_verb = "squeal";
361 yelp_verb = "screak";
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);
374 /* the sounds of distressed pets */
377 register struct monst *mtmp;
379 register const char *whimper_verb = 0;
381 if (mtmp->msleeping || !mtmp->mcanmove || !mtmp->data->msound)
384 /* presumably nearness and soundok checks have already been made */
386 whimper_verb = h_sounds[rn2(SIZE(h_sounds))];
387 else switch (mtmp->data->msound) {
390 whimper_verb = "whimper";
393 whimper_verb = "whine";
396 whimper_verb = "squeal";
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);
406 /* pet makes "I'm hungry" noises */
409 register struct monst *mtmp;
411 if (mtmp->msleeping || !mtmp->mcanmove ||
412 !(carnivorous(mtmp->data) || herbivorous(mtmp->data)))
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.");
427 register struct monst *mtmp;
429 register const char *pline_msg = 0, /* Monnam(mtmp) will be prepended */
430 *verbl_msg = 0; /* verbalize() */
431 struct permonst *ptr = mtmp->data;
434 /* presumably nearness and sleep checks have already been made */
435 if (!flags.soundok) return(0);
436 if (is_silent(ptr)) return(0);
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)];
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
447 if (!canspotmon(mtmp))
448 map_invisible(mtmp->mx, mtmp->my);
450 switch (ptr->msound) {
452 return doconsult(mtmp);
461 case MS_SELL: /* pitch, pay, total */
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;
479 Sprintf(verbuf, "Good %s to you Master%s",
480 isnight ? "evening" : "day",
481 isnight ? "!" : ". Why do we not rest?");
484 Sprintf(verbuf,"%s%s",
485 nightchild ? "Child of the night, " : "",
487 "I can stand this craving no longer!" :
489 "I beg you, help me satisfy this growing craving!" :
490 "I find myself growing a little weary.");
493 } else if (mtmp->mpeaceful) {
494 if (kindred && isnight) {
495 Sprintf(verbuf, "Good feeding %s!",
496 flags.female ? "sister" : "brother");
498 } else if (nightchild && isnight) {
500 "How nice to hear you, child of the night!");
503 verbl_msg = "I only drink... potions.";
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 */
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");
522 vampindex = rn2(SIZE(vampmsg));
523 if (vampindex == 0) {
524 Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
526 } else if (vampindex == 1) {
527 Sprintf(verbuf, vampmsg[vampindex],
528 Upolyd ? an(mons[u.umonnum].mname) : an(racenoun));
531 verbl_msg = vampmsg[vampindex];
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);
544 "whispers inaudibly. All you can make out is \"moon\".";
547 if (flags.moonphase == FULL_MOON && night()) {
548 pline_msg = "howls.";
549 } else if (mtmp->mpeaceful) {
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)
557 if (mtmp->data != &mons[PM_DINGO]) /* dingos do not actually bark */
558 pline_msg = "barks.";
561 pline_msg = "growls.";
566 if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
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.";
576 } /* else FALLTHRU */
578 pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
581 pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
584 pline_msg = "squeaks.";
587 if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
588 verbl_msg = "Nevermore!";
590 pline_msg = "squawks.";
593 if (!mtmp->mpeaceful)
594 pline_msg = "hisses!";
595 else return 0; /* no sound */
598 pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
601 pline_msg = "grunts.";
605 pline_msg = "neighs.";
606 else if (moves > EDOG(mtmp)->hungrytime)
607 pline_msg = "whinnies.";
609 pline_msg = "whickers.";
612 pline_msg = "wails mournfully.";
615 pline_msg = "gurgles.";
618 pline_msg = "burbles.";
621 pline_msg = "shrieks.";
625 pline_msg = "imitates you.";
628 pline("%s rattles noisily.", Monnam(mtmp));
629 You("freeze for a moment.");
634 static const char * const laugh_msg[4] = {
635 "giggles.", "chuckles.", "snickers.", "laughs.",
637 pline_msg = laugh_msg[rn2(4)];
641 pline_msg = "mumbles incomprehensibly.";
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.";
650 verbl_msg = "I'm free!";
651 } else verbl_msg = "This will teach you not to disturb me!";
653 case MS_BOAST: /* giants */
654 if (!mtmp->mpeaceful) {
656 case 0: pline("%s boasts about %s gem collection.",
657 Monnam(mtmp), mhis(mtmp));
659 case 1: pline_msg = "complains about a diet of mutton.";
661 default: pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
662 wake_nearto(mtmp->mx, mtmp->my, 7*7);
669 if (!mtmp->mpeaceful) {
670 if (In_endgame(&u.uz) && is_mplayer(ptr)) {
673 } else return 0; /* no sound */
675 /* Generic peaceful humanoid behaviour. */
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);
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)) {
705 pline_msg = (mtmp->mhpmax - mtmp->mhp >= 10) ?
706 "complains about unpleasant dungeon conditions."
707 : "asks you about the One Ring.";
709 case PM_ARCHEOLOGIST:
710 pline_msg = "describes a recent article in \"Spelunker Today\" magazine.";
714 verbl_msg = "Aloha.";
718 pline_msg = "discusses dungeon exploration.";
724 if (ptr->mlet != S_NYMPH &&
725 could_seduce(mtmp, &youmonst, (struct attack *)0) == 1) {
726 (void) doseduce(mtmp);
729 switch ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0)
731 switch ((poly_gender() == 0) ? rn2(3) : 0)
735 verbl_msg = "Hello, sailor.";
738 pline_msg = "comes on to you.";
741 pline_msg = "cajoles you.";
747 verbalize("Just the facts, %s.",
748 flags.female ? "Ma'am" : "Sir");
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!",
755 verbl_msg = arrest_msg[rn2(3)];
760 if (mtmp->mpeaceful && !mtmp->mtame) {
761 (void) demon_talk(mtmp);
766 if (!mtmp->mpeaceful)
770 /* deliberately vague, since it's not actually casting any spell */
771 pline_msg = "seems to mutter a cantrip.";
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.";
782 verbl_msg = "Take off your shirt, please.";
784 else verbl_msg = "Relax, this won't hurt a bit.";
790 if (money_cnt(invent))
792 verbl_msg = "Please drop that gold and follow me.";
794 verbl_msg = "Please follow me.";
798 static const char * const soldier_foe_msg[3] = {
799 "Resistance is useless!",
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!",
807 verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
808 : soldier_foe_msg[rn2(3)];
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?";
818 if (pline_msg) pline("%s %s", Monnam(mtmp), pline_msg);
819 else if (verbl_msg) verbalize(verbl_msg);
828 boolean save_soundok = flags.soundok;
829 flags.soundok = 1; /* always allow sounds while chatting */
831 flags.soundok = save_soundok;
838 register struct monst *mtmp;
842 if (is_silent(youmonst.data)) {
843 pline("As %s, you cannot speak.", an(youmonst.data->mname));
847 You_cant("speak. You're choking!");
851 pline("They won't hear you out there.");
855 Your("speech is unintelligible underwater.");
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.
871 if (!getdir("Talk to whom? (in what direction)")) {
872 /* decided not to chat */
877 if (u.usteed && u.dz > 0)
878 return (domonnoise(u.usteed));
881 pline("They won't hear you %s there.", u.dz < 0 ? "up" : "down");
885 if (u.dx == 0 && u.dy == 0) {
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,
890 if (u.umonnum == PM_ETTIN) {
891 You("discover that your other head makes boring conversation.");
895 pline("Talking to yourself is a bad habit for a dungeoneer.");
899 tx = u.ux+u.dx; ty = u.uy+u.dy;
902 if (!mtmp || mtmp->mundetected ||
903 mtmp->m_ap_type == M_AP_FURNITURE ||
904 mtmp->m_ap_type == M_AP_OBJECT)
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));
916 /* if this monster is waiting for something, prod it into action */
917 mtmp->mstrategy &= ~STRAT_WAITMASK;
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));
926 return domonnoise(mtmp);
931 extern void FDECL(play_usersound, (const char*, int));
933 typedef struct audio_mapping_rec {
934 #ifdef USER_SOUNDS_REGEX
935 struct re_pattern_buffer regex;
941 struct audio_mapping_rec *next;
944 static audio_mapping *soundmap = 0;
946 char* sounddir = ".";
948 /* adds a sound file mapping, returns 0 on failure, 1 on success */
950 add_sound_mapping(mapping)
958 if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d",
959 text, filename, &volume) == 3) {
961 audio_mapping *new_map;
963 if (strlen(sounddir) + strlen(filename) > 254) {
964 raw_print("sound file name too long");
967 Sprintf(filespec, "%s/%s", sounddir, filename);
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;
978 new_map->pattern = (char *)alloc(strlen(text) + 1);
979 Strcpy(new_map->pattern, text);
981 new_map->filename = strdup(filespec);
982 new_map->volume = volume;
983 new_map->next = soundmap;
985 #ifdef USER_SOUNDS_REGEX
986 err = re_compile_pattern(text, strlen(text), &new_map->regex);
992 free(new_map->filename);
999 Sprintf(text, "cannot read %.243s", filespec);
1004 raw_print("syntax error in SOUND");
1012 play_sound_for_message(msg)
1015 audio_mapping* cursor = soundmap;
1018 #ifdef USER_SOUNDS_REGEX
1019 if (re_search(&cursor->regex, msg, strlen(msg), 0, 9999, 0) >= 0) {
1021 if (pmatch(cursor->pattern, msg)) {
1023 play_usersound(cursor->filename, cursor->volume);
1025 cursor = cursor->next;
1029 #endif /* USER_SOUNDS */