1 /* SCCS Id: @(#)music.c 3.3 1999/08/19 */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /*
6 * This file contains the different functions designed to manipulate the
7 * musical instruments and their various effects.
8 *
9 * Actually the list of instruments / effects is :
10 *
11 * (wooden) flute may calm snakes if player has enough dexterity
12 * magic flute may put monsters to sleep: area of effect depends
13 * on player level.
14 * (tooled) horn Will awaken monsters: area of effect depends on player
15 * level. May also scare monsters.
16 * fire horn Acts like a wand of fire.
17 * frost horn Acts like a wand of cold.
18 * bugle Will awaken soldiers (if any): area of effect depends
19 * on player level.
20 * (wooden) harp May calm nymph if player has enough dexterity.
21 * magic harp Charm monsters: area of effect depends on player
22 * level.
23 * (leather) drum Will awaken monsters like the horn.
24 * drum of earthquake Will initiate an earthquake whose intensity depends
25 * on player level. That is, it creates random pits
26 * called here chasms.
27 */
28
29 #include "hack.h"
30
31 STATIC_DCL void FDECL(awaken_monsters,(int));
32 STATIC_DCL void FDECL(put_monsters_to_sleep,(int));
33 STATIC_DCL void FDECL(charm_snakes,(int));
34 STATIC_DCL void FDECL(calm_nymphs,(int));
35 STATIC_DCL void FDECL(charm_monsters,(int));
36 STATIC_DCL void FDECL(do_earthquake,(int));
37 STATIC_DCL int FDECL(do_improvisation,(struct obj *));
38
39 #ifdef UNIX386MUSIC
40 STATIC_DCL int NDECL(atconsole);
41 STATIC_DCL void FDECL(speaker,(struct obj *,char *));
42 #endif
43 #ifdef VPIX_MUSIC
44 extern int sco_flag_console; /* will need changing if not _M_UNIX */
45 STATIC_DCL void NDECL(playinit);
46 STATIC_DCL void FDECL(playstring, (char *,size_t));
47 STATIC_DCL void FDECL(speaker,(struct obj *,char *));
48 #endif
49 #ifdef PCMUSIC
50 void FDECL( pc_speaker, ( struct obj *, char * ) );
51 #endif
52 #ifdef AMIGA
53 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
54 #endif
55
56 /*
57 * Wake every monster in range...
58 */
59
60 STATIC_OVL void
awaken_monsters(distance)61 awaken_monsters(distance)
62 int distance;
63 {
64 register struct monst *mtmp = fmon;
65 register int distm;
66
67 while(mtmp) {
68 if (!DEADMONSTER(mtmp)) {
69 distm = distu(mtmp->mx, mtmp->my);
70 if (distm < distance) {
71 mtmp->msleeping = 0;
72 mtmp->mcanmove = 1;
73 mtmp->mfrozen = 0;
74 /* May scare some monsters */
75 if (distm < distance/3 &&
76 !resist(mtmp, SCROLL_CLASS, 0, NOTELL))
77 mtmp->mflee = 1;
78 }
79 }
80 mtmp = mtmp->nmon;
81 }
82 }
83
84 /*
85 * Make monsters fall asleep. Note that they may resist the spell.
86 */
87
88 STATIC_OVL void
put_monsters_to_sleep(distance)89 put_monsters_to_sleep(distance)
90 int distance;
91 {
92 register struct monst *mtmp = fmon;
93
94 while(mtmp) {
95 if (!DEADMONSTER(mtmp) && distu(mtmp->mx, mtmp->my) < distance &&
96 sleep_monst(mtmp, d(10,10), WAND_CLASS)) {
97 mtmp->msleeping = 1; /* 10d10 turns + wake_nearby to rouse */
98 slept_monst(mtmp);
99 }
100 mtmp = mtmp->nmon;
101 }
102 }
103
104 /*
105 * Charm snakes in range. Note that the snakes are NOT tamed.
106 */
107
108 STATIC_OVL void
charm_snakes(distance)109 charm_snakes(distance)
110 int distance;
111 {
112 register struct monst *mtmp = fmon;
113 int could_see_mon, was_peaceful;
114
115 while (mtmp) {
116 if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_SNAKE && mtmp->mcanmove &&
117 distu(mtmp->mx, mtmp->my) < distance) {
118 was_peaceful = mtmp->mpeaceful;
119 mtmp->mpeaceful = 1;
120 could_see_mon = canseemon(mtmp);
121 mtmp->mundetected = 0;
122 newsym(mtmp->mx, mtmp->my);
123 if (canseemon(mtmp)) {
124 if (!could_see_mon)
125 You("notice %s, swaying with the music.",
126 a_monnam(mtmp));
127 else
128 pline("%s freezes, then sways with the music%s.",
129 Monnam(mtmp),
130 was_peaceful ? "" : ", and now seems quieter");
131 }
132 }
133 mtmp = mtmp->nmon;
134 }
135 }
136
137 /*
138 * Calm nymphs in range.
139 */
140
141 STATIC_OVL void
calm_nymphs(distance)142 calm_nymphs(distance)
143 int distance;
144 {
145 register struct monst *mtmp = fmon;
146
147 while (mtmp) {
148 if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_NYMPH && mtmp->mcanmove &&
149 distu(mtmp->mx, mtmp->my) < distance) {
150 mtmp->msleeping = 0;
151 mtmp->mpeaceful = 1;
152 if (canseemon(mtmp))
153 pline(
154 "%s listens cheerfully to the music, then seems quieter.",
155 Monnam(mtmp));
156 }
157 mtmp = mtmp->nmon;
158 }
159 }
160
161 /* Awake only soldiers of the level. */
162
163 void
awaken_soldiers()164 awaken_soldiers()
165 {
166 register struct monst *mtmp = fmon;
167
168 while(mtmp) {
169 if (!DEADMONSTER(mtmp) &&
170 is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) {
171 mtmp->mpeaceful = mtmp->msleeping = mtmp->mfrozen = 0;
172 mtmp->mcanmove = 1;
173 if (canseemon(mtmp))
174 pline("%s is now ready for battle!", Monnam(mtmp));
175 else
176 Norep("You hear the rattle of battle gear being readied.");
177 }
178 mtmp = mtmp->nmon;
179 }
180 }
181
182 /* Charm monsters in range. Note that they may resist the spell. */
183
184 STATIC_OVL void
charm_monsters(distance)185 charm_monsters(distance)
186 int distance;
187 {
188 register struct monst *mtmp = fmon, *mtmp2;
189
190 while(mtmp) {
191 mtmp2 = mtmp->nmon;
192 if (!DEADMONSTER(mtmp)) {
193 if (distu(mtmp->mx, mtmp->my) <= distance)
194 if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL))
195 (void) tamedog(mtmp, (struct obj *) 0);
196 }
197 mtmp = mtmp2;
198 }
199
200 }
201
202 /* Generate earthquake :-) of desired force.
203 * That is: create random chasms (pits).
204 */
205
206 STATIC_OVL void
do_earthquake(force)207 do_earthquake(force)
208 int force;
209 {
210 register int x,y;
211 struct monst *mtmp;
212 struct obj *otmp;
213 struct trap *chasm;
214 int start_x, start_y, end_x, end_y;
215
216 start_x = u.ux - (force * 2);
217 start_y = u.uy - (force * 2);
218 end_x = u.ux + (force * 2);
219 end_y = u.uy + (force * 2);
220 if (start_x < 1) start_x = 1;
221 if (start_y < 1) start_y = 1;
222 if (end_x >= COLNO) end_x = COLNO - 1;
223 if (end_y >= ROWNO) end_y = ROWNO - 1;
224 for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {
225 if ((mtmp = m_at(x,y)) != 0) {
226 wakeup(mtmp); /* peaceful monster will become hostile */
227 if (mtmp->mundetected && is_hider(mtmp->data)) {
228 mtmp->mundetected = 0;
229 if (cansee(x,y))
230 pline("%s is shaken loose from the ceiling!",
231 Amonnam(mtmp));
232 else
233 You_hear("a thumping sound.");
234 if (x==u.ux && y==u.uy)
235 You("easily dodge the falling %s.",
236 mon_nam(mtmp));
237 newsym(x,y);
238 }
239 }
240 if (!rn2(14 - force)) switch (levl[x][y].typ) {
241 case FOUNTAIN : /* Make the fountain disappear */
242 if (cansee(x,y))
243 pline_The("fountain falls into a chasm.");
244 goto do_pit;
245 #ifdef SINKS
246 case SINK :
247 if (cansee(x,y))
248 pline_The("kitchen sink falls into a chasm.");
249 goto do_pit;
250 #endif
251 case ALTAR :
252 if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) break;
253
254 if (cansee(x,y))
255 pline_The("altar falls into a chasm.");
256 goto do_pit;
257 case GRAVE :
258 if (cansee(x,y))
259 pline_The("headstone topples into a chasm.");
260 goto do_pit;
261 case THRONE :
262 if (cansee(x,y))
263 pline_The("throne falls into a chasm.");
264 /* Falls into next case */
265 case ROOM :
266 case CORR : /* Try to make a pit */
267 do_pit: chasm = maketrap(x,y,PIT);
268 if (!chasm) break; /* no pit if portal at that location */
269 chasm->tseen = 1;
270
271 levl[x][y].doormask = 0;
272
273 mtmp = m_at(x,y);
274
275 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
276 if (cansee(x, y))
277 pline("KADOOM! The boulder falls into a chasm%s!",
278 ((x == u.ux) && (y == u.uy)) ? " below you" : "");
279 if (mtmp)
280 mtmp->mtrapped = 0;
281 obj_extract_self(otmp);
282 (void) flooreffects(otmp, x, y, "");
283 break;
284 }
285
286 /* We have to check whether monsters or player
287 falls in a chasm... */
288
289 if (mtmp) {
290 if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
291 mtmp->mtrapped = 1;
292 if(cansee(x,y))
293 pline("%s falls into a chasm!", Monnam(mtmp));
294 else if (flags.soundok && humanoid(mtmp->data))
295 You_hear("a scream!");
296 mselftouch(mtmp, "Falling, ", TRUE);
297 if (mtmp->mhp > 0)
298 if ((mtmp->mhp -= rnd(6)) <= 0) {
299 if(!cansee(x,y))
300 pline("It is destroyed!");
301 else {
302 You("destroy %s!", mtmp->mtame ?
303 x_monnam(mtmp, ARTICLE_THE, "poor",
304 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE):
305 mon_nam(mtmp));
306 }
307 xkilled(mtmp,0);
308 }
309 }
310 } else if (x == u.ux && y == u.uy) {
311 if (Levitation || Flying ||
312 is_clinger(youmonst.data)) {
313 pline("A chasm opens up under you!");
314 You("don't fall in!");
315 } else {
316 You("fall into a chasm!");
317 u.utrap = rn1(6,2);
318 u.utraptype = TT_PIT;
319 losehp(rnd(6),"fell into a chasm",
320 NO_KILLER_PREFIX);
321 selftouch("Falling, you");
322 }
323 } else newsym(x,y);
324 break;
325 case DOOR : /* Make the door collapse */
326 if (levl[x][y].doormask == D_NODOOR) goto do_pit;
327 if (cansee(x,y))
328 pline_The("door collapses.");
329 if (*in_rooms(x, y, SHOPBASE))
330 add_damage(x, y, 0L);
331 levl[x][y].doormask = D_NODOOR;
332 newsym(x,y);
333 break;
334 }
335 }
336 }
337
338 /*
339 * The player is trying to extract something from his/her instrument.
340 */
341
342 STATIC_OVL int
do_improvisation(instr)343 do_improvisation(instr)
344 struct obj *instr;
345 {
346 int damage, do_spec = !Confusion;
347 #if defined(MAC) || defined(AMIGA) || defined(VPIX_MUSIC) || defined (PCMUSIC)
348 struct obj itmp;
349
350 itmp = *instr;
351 /* if won't yield special effect, make sound of mundane counterpart */
352 if (!do_spec || instr->spe <= 0)
353 while (objects[itmp.otyp].oc_magic) itmp.otyp -= 1;
354 # ifdef MAC
355 mac_speaker(&itmp, "C");
356 # endif
357 # ifdef AMIGA
358 amii_speaker(&itmp, "Cw", AMII_OKAY_VOLUME);
359 # endif
360 # ifdef VPIX_MUSIC
361 if (sco_flag_console)
362 speaker(&itmp, "C");
363 # endif
364 #ifdef PCMUSIC
365 pc_speaker ( &itmp, "C");
366 #endif
367 #endif /* MAC || AMIGA || VPIX_MUSIC || PCMUSIC */
368
369 if (!do_spec)
370 pline("What you produce is quite far from music...");
371 else
372 You("start playing %s.", the(xname(instr)));
373
374 switch (instr->otyp) {
375 case MAGIC_FLUTE: /* Make monster fall asleep */
376 if (do_spec && instr->spe > 0) {
377 check_unpaid(instr);
378 instr->spe--;
379 You("produce soft music.");
380 put_monsters_to_sleep(u.ulevel * 5);
381 exercise(A_DEX, TRUE);
382 break;
383 } /* else FALLTHRU */
384 case WOODEN_FLUTE: /* May charm snakes */
385 do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
386 pline("%s %s.", The(xname(instr)),
387 do_spec ? "trills" : "toots");
388 if (do_spec) charm_snakes(u.ulevel * 3);
389 exercise(A_DEX, TRUE);
390 break;
391 case FROST_HORN: /* Idem wand of cold */
392 case FIRE_HORN: /* Idem wand of fire */
393 if (do_spec && instr->spe > 0) {
394 check_unpaid(instr);
395 instr->spe--;
396 if (!getdir((char *)0)) {
397 pline("%s vibrates.", The(xname(instr)));
398 break;
399 } else if (!u.dx && !u.dy && !u.dz) {
400 if ((damage = zapyourself(instr, TRUE)) != 0)
401 losehp(damage,
402 self_pronoun("using a magical horn on %sself",
403 "him"),
404 NO_KILLER_PREFIX);
405 } else {
406 buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1,
407 rn1(6,6), u.ux, u.uy, u.dx, u.dy);
408 }
409 makeknown(instr->otyp);
410 break;
411 } /* else FALLTHRU */
412 case TOOLED_HORN: /* Awaken or scare monsters */
413 You("produce a frightful, grave sound.");
414 awaken_monsters(u.ulevel * 30);
415 exercise(A_WIS, FALSE);
416 break;
417 case BUGLE: /* Awaken & attract soldiers */
418 You("extract a loud noise from %s.", the(xname(instr)));
419 awaken_soldiers();
420 exercise(A_WIS, FALSE);
421 break;
422 case MAGIC_HARP: /* Charm monsters */
423 if (do_spec && instr->spe > 0) {
424 check_unpaid(instr);
425 instr->spe--;
426 pline("%s produces very attractive music.",
427 The(xname(instr)));
428 charm_monsters((u.ulevel - 1) / 3 + 1);
429 exercise(A_DEX, TRUE);
430 break;
431 } /* else FALLTHRU */
432 case WOODEN_HARP: /* May calm Nymph */
433 do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25);
434 pline("%s %s.", The(xname(instr)),
435 do_spec ? "produces a lilting melody" : "twangs");
436 if (do_spec) calm_nymphs(u.ulevel * 3);
437 exercise(A_DEX, TRUE);
438 break;
439 case DRUM_OF_EARTHQUAKE: /* create several pits */
440 if (do_spec && instr->spe > 0) {
441 check_unpaid(instr);
442 instr->spe--;
443 You("produce a heavy, thunderous rolling!");
444 pline_The("entire dungeon is shaking around you!");
445 do_earthquake((u.ulevel - 1) / 3 + 1);
446 /* shake up monsters in a much larger radius... */
447 awaken_monsters(ROWNO * COLNO);
448 makeknown(DRUM_OF_EARTHQUAKE);
449 break;
450 } /* else FALLTHRU */
451 case LEATHER_DRUM: /* Awaken monsters */
452 You("beat a deafening row!");
453 awaken_monsters(u.ulevel * 40);
454 exercise(A_WIS, FALSE);
455 break;
456 default:
457 impossible("What a weird instrument (%d)!", instr->otyp);
458 break;
459 }
460 return 2; /* That takes time */
461 }
462
463 /*
464 * So you want music...
465 */
466
467 int
do_play_instrument(instr)468 do_play_instrument(instr)
469 struct obj *instr;
470 {
471 char buf[BUFSZ], c = 'y';
472 #ifndef AMIGA
473 char *s;
474 #endif
475 int x,y;
476 boolean ok;
477
478 if (Underwater) {
479 You_cant("play music underwater!");
480 return(0);
481 }
482 if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) {
483 c = yn("Improvise?");
484 }
485 if (c == 'n') {
486 if (u.uevent.uheard_tune == 2 && yn("Play the passtune?") == 'y')
487 Strcpy(buf, tune);
488 else
489 getlin("What tune are you playing? [what 5 notes]", buf);
490 #ifndef AMIGA
491 /* The AMIGA supports two octaves of notes */
492 for (s=buf; *s; s++) *s = highc(*s);
493 #endif
494 You("extract a strange sound from %s!", the(xname(instr)));
495 #ifdef UNIX386MUSIC
496 /* if user is at the console, play through the console speaker */
497 if (atconsole())
498 speaker(instr, buf);
499 #endif
500 #ifdef VPIX_MUSIC
501 if (sco_flag_console)
502 speaker(instr, buf);
503 #endif
504 #ifdef MAC
505 mac_speaker ( instr , buf ) ;
506 #endif
507 #ifdef PCMUSIC
508 pc_speaker ( instr, buf );
509 #endif
510 #ifdef AMIGA
511 {
512 char nbuf[ 20 ];
513 int i;
514 for( i = 0; buf[i] && i < 5; ++i )
515 {
516 nbuf[ i*2 ] = buf[ i ];
517 nbuf[ (i*2)+1 ] = 'h';
518 }
519 nbuf[ i*2 ] = 0;
520 amii_speaker ( instr , nbuf, AMII_OKAY_VOLUME ) ;
521 }
522 #endif
523 /* Check if there was the Stronghold drawbridge near
524 * and if the tune conforms to what we're waiting for.
525 */
526 if(Is_stronghold(&u.uz)) {
527 exercise(A_WIS, TRUE); /* just for trying */
528 if(!strcmp(buf,tune)) {
529 /* Search for the drawbridge */
530 for(y=u.uy-1; y<=u.uy+1; y++)
531 for(x=u.ux-1;x<=u.ux+1;x++)
532 if(isok(x,y))
533 if(find_drawbridge(&x,&y)) {
534 u.uevent.uheard_tune = 2; /* tune now fully known */
535 if(levl[x][y].typ == DRAWBRIDGE_DOWN)
536 close_drawbridge(x,y);
537 else
538 open_drawbridge(x,y);
539 return 0;
540 }
541 } else if(flags.soundok) {
542 if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1;
543 /* Okay, it wasn't the right tune, but perhaps
544 * we can give the player some hints like in the
545 * Mastermind game */
546 ok = FALSE;
547 for(y = u.uy-1; y <= u.uy+1 && !ok; y++)
548 for(x = u.ux-1; x <= u.ux+1 && !ok; x++)
549 if(isok(x,y))
550 if(IS_DRAWBRIDGE(levl[x][y].typ) ||
551 is_drawbridge_wall(x,y) >= 0)
552 ok = TRUE;
553 if(ok) { /* There is a drawbridge near */
554 int tumblers, gears;
555 boolean matched[5];
556
557 tumblers = gears = 0;
558 for(x=0; x < 5; x++)
559 matched[x] = FALSE;
560
561 for(x=0; x < (int)strlen(buf); x++)
562 if(x < 5) {
563 if(buf[x] == tune[x]) {
564 gears++;
565 matched[x] = TRUE;
566 } else
567 for(y=0; y < 5; y++)
568 if(!matched[y] &&
569 buf[x] == tune[y] &&
570 buf[y] != tune[y]) {
571 tumblers++;
572 matched[y] = TRUE;
573 break;
574 }
575 }
576 if(tumblers)
577 if(gears)
578 You_hear("%d tumbler%s click and %d gear%s turn.",
579 tumblers, plur(tumblers), gears, plur(gears));
580 else
581 You_hear("%d tumbler%s click.",
582 tumblers, plur(tumblers));
583 else if(gears) {
584 You_hear("%d gear%s turn.", gears, plur(gears));
585 /* could only get `gears == 5' by playing five
586 correct notes followed by excess; otherwise,
587 tune would have matched above */
588 if (gears == 5) u.uevent.uheard_tune = 2;
589 }
590 }
591 }
592 }
593 return 1;
594 } else
595 return do_improvisation(instr);
596 }
597
598 #ifdef UNIX386MUSIC
599 /*
600 * Play audible music on the machine's speaker if appropriate.
601 */
602
603 STATIC_OVL int
atconsole()604 atconsole()
605 {
606 /*
607 * Kluge alert: This code assumes that your [34]86 has no X terminals
608 * attached and that the console tty type is AT386 (this is always true
609 * under AT&T UNIX for these boxen). The theory here is that your remote
610 * ttys will have terminal type `ansi' or something else other than
611 * `AT386' or `xterm'. We'd like to do better than this, but testing
612 * to see if we're running on the console physical terminal is quite
613 * difficult given the presence of virtual consoles and other modern
614 * UNIX impedimenta...
615 */
616 char *termtype = nh_getenv("TERM");
617
618 return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm"));
619 }
620
621 STATIC_OVL void
speaker(instr,buf)622 speaker(instr, buf)
623 struct obj *instr;
624 char *buf;
625 {
626 /*
627 * For this to work, you need to have installed the PD speaker-control
628 * driver for PC-compatible UNIX boxes that I (esr@snark.thyrsus.com)
629 * posted to comp.sources.unix in Feb 1990. A copy should be included
630 * with your nethack distribution.
631 */
632 int fd;
633
634 if ((fd = open("/dev/speaker", 1)) != -1)
635 {
636 /* send a prefix to modify instrumental `timbre' */
637 switch (instr->otyp)
638 {
639 case WOODEN_FLUTE:
640 case MAGIC_FLUTE:
641 (void) write(fd, ">ol", 1); /* up one octave & lock */
642 break;
643 case TOOLED_HORN:
644 case FROST_HORN:
645 case FIRE_HORN:
646 (void) write(fd, "<<ol", 2); /* drop two octaves & lock */
647 break;
648 case BUGLE:
649 (void) write(fd, "ol", 2); /* octave lock */
650 break;
651 case WOODEN_HARP:
652 case MAGIC_HARP:
653 (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */
654 break;
655 }
656 (void) write(fd, buf, strlen(buf));
657 (void) close(fd);
658 }
659 }
660 #endif /* UNIX386MUSIC */
661
662 #ifdef VPIX_MUSIC
663
664 # if 0
665 #include <sys/types.h>
666 #include <sys/console.h>
667 #include <sys/vtkd.h>
668 # else
669 #define KIOC ('K' << 8)
670 #define KDMKTONE (KIOC | 8)
671 # endif
672
673 #define noDEBUG
674
tone(hz,ticks)675 STATIC_OVL void tone(hz, ticks)
676 /* emit tone of frequency hz for given number of ticks */
677 unsigned int hz, ticks;
678 {
679 ioctl(0,KDMKTONE,hz|((ticks*10)<<16));
680 # ifdef DEBUG
681 printf("TONE: %6d %6d\n",hz,ticks * 10);
682 # endif
683 nap(ticks * 10);
684 }
685
rest(ticks)686 STATIC_OVL void rest(ticks)
687 /* rest for given number of ticks */
688 int ticks;
689 {
690 nap(ticks * 10);
691 # ifdef DEBUG
692 printf("REST: %6d\n",ticks * 10);
693 # endif
694 }
695
696
697 #include "interp.c" /* from snd86unx.shr */
698
699
700 STATIC_OVL void
speaker(instr,buf)701 speaker(instr, buf)
702 struct obj *instr;
703 char *buf;
704 {
705 /* emit a prefix to modify instrumental `timbre' */
706 playinit();
707 switch (instr->otyp)
708 {
709 case WOODEN_FLUTE:
710 case MAGIC_FLUTE:
711 playstring(">ol", 1); /* up one octave & lock */
712 break;
713 case TOOLED_HORN:
714 case FROST_HORN:
715 case FIRE_HORN:
716 playstring("<<ol", 2); /* drop two octaves & lock */
717 break;
718 case BUGLE:
719 playstring("ol", 2); /* octave lock */
720 break;
721 case WOODEN_HARP:
722 case MAGIC_HARP:
723 playstring("l8mlol", 4); /* fast, legato, octave lock */
724 break;
725 }
726 playstring( buf, strlen(buf));
727 }
728
729 # ifdef DEBUG
main(argc,argv)730 main(argc,argv)
731 char *argv[];
732 {
733 if (argc == 2) {
734 playinit();
735 playstring(argv[1], strlen(argv[1]));
736 }
737 }
738 # endif
739 #endif /* VPIX_MUSIC */
740
741 /*music.c*/
742