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