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(put_monsters_to_sleep,(int));
32 STATIC_DCL void FDECL(charm_snakes,(int));
33 STATIC_DCL void FDECL(calm_nymphs,(int));
34 STATIC_DCL void FDECL(charm_monsters,(int));
35 STATIC_DCL int FDECL(do_improvisation,(struct obj *));
36
37 #ifdef UNIX386MUSIC
38 STATIC_DCL int NDECL(atconsole);
39 STATIC_DCL void FDECL(speaker,(struct obj *,char *));
40 #endif
41 #ifdef VPIX_MUSIC
42 extern int sco_flag_console; /* will need changing if not _M_UNIX */
43 STATIC_DCL void NDECL(playinit);
44 STATIC_DCL void FDECL(playstring, (char *,size_t));
45 STATIC_DCL void FDECL(speaker,(struct obj *,char *));
46 #endif
47 #ifdef PCMUSIC
48 void FDECL( pc_speaker, ( struct obj *, char * ) );
49 #endif
50 #ifdef AMIGA
51 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
52 #endif
53
54 /*
55 * Wake every monster in range...
56 */
57
58 void
awaken_monsters(distance)59 awaken_monsters(distance)
60 int distance;
61 {
62 register struct monst *mtmp = fmon;
63 register int distm;
64
65 while(mtmp) {
66 if (!DEADMONSTER(mtmp)) {
67 distm = distu(mtmp->mx, mtmp->my);
68 if (distm < distance) {
69 mtmp->msleeping = 0;
70 mtmp->mcanmove = 1;
71 mtmp->mfrozen = 0;
72 /* May scare some monsters */
73 if (distm < distance/3 &&
74 !resist(mtmp, TOOL_CLASS, 0, NOTELL))
75 monflee(mtmp, 0, FALSE, TRUE);
76 }
77 }
78 mtmp = mtmp->nmon;
79 }
80 }
81
82 /*
83 * Make monsters fall asleep. Note that they may resist the spell.
84 */
85
86 STATIC_OVL void
put_monsters_to_sleep(distance)87 put_monsters_to_sleep(distance)
88 int distance;
89 {
90 register struct monst *mtmp = fmon;
91
92 while(mtmp) {
93 if (!DEADMONSTER(mtmp) && distu(mtmp->mx, mtmp->my) < distance &&
94 sleep_monst(mtmp, d(10,10), TOOL_CLASS)) {
95 mtmp->msleeping = 1; /* 10d10 turns + wake_nearby to rouse */
96 slept_monst(mtmp);
97 }
98 mtmp = mtmp->nmon;
99 }
100 }
101
102 /*
103 * Charm snakes in range. Note that the snakes are NOT tamed.
104 */
105
106 STATIC_OVL void
charm_snakes(distance)107 charm_snakes(distance)
108 int distance;
109 {
110 register struct monst *mtmp = fmon;
111 int could_see_mon, was_peaceful;
112
113 while (mtmp) {
114 if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_SNAKE && mtmp->mcanmove &&
115 distu(mtmp->mx, mtmp->my) < distance) {
116 was_peaceful = mtmp->mpeaceful;
117 mtmp->mpeaceful = 1;
118 mtmp->mavenge = 0;
119 could_see_mon = canseemon(mtmp);
120 mtmp->mundetected = 0;
121 newsym(mtmp->mx, mtmp->my);
122 if (canseemon(mtmp)) {
123 if (!could_see_mon)
124 You("notice %s, swaying with the music.",
125 a_monnam(mtmp));
126 else
127 pline("%s freezes, then sways with the music%s.",
128 Monnam(mtmp),
129 was_peaceful ? "" : ", and now seems quieter");
130 }
131 }
132 mtmp = mtmp->nmon;
133 }
134 }
135
136 /*
137 * Calm nymphs in range.
138 */
139
140 STATIC_OVL void
calm_nymphs(distance)141 calm_nymphs(distance)
142 int distance;
143 {
144 register struct monst *mtmp = fmon;
145
146 while (mtmp) {
147 if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_NYMPH && mtmp->mcanmove &&
148 distu(mtmp->mx, mtmp->my) < distance) {
149 mtmp->msleeping = 0;
150 mtmp->mpeaceful = 1;
151 mtmp->mavenge = 0;
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 * If swallowed, range is reduced to 0.
184 */
185
186 STATIC_OVL void
charm_monsters(distance)187 charm_monsters(distance)
188 int distance;
189 {
190 struct monst *mtmp, *mtmp2;
191
192 if (u.uswallow) {
193 if (!resist(u.ustuck, TOOL_CLASS, 0, NOTELL))
194 (void) tamedog(u.ustuck, (struct obj *) 0);
195 } else {
196 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
197 mtmp2 = mtmp->nmon;
198 if (DEADMONSTER(mtmp)) continue;
199
200 if (distu(mtmp->mx, mtmp->my) <= distance) {
201 if (!resist(mtmp, TOOL_CLASS, 0, NOTELL))
202 (void) tamedog(mtmp, (struct obj *) 0);
203 }
204 }
205 }
206
207 }
208
209 /* Generate earthquake :-) of desired force.
210 * That is: create random chasms (pits).
211 */
212
213 void
do_earthquake(force)214 do_earthquake(force)
215 int force;
216 {
217 register int x,y;
218 struct monst *mtmp;
219 struct obj *otmp;
220 struct trap *chasm;
221 int start_x, start_y, end_x, end_y;
222
223 start_x = u.ux - (force * 2);
224 start_y = u.uy - (force * 2);
225 end_x = u.ux + (force * 2);
226 end_y = u.uy + (force * 2);
227 if (start_x < 1) start_x = 1;
228 if (start_y < 1) start_y = 1;
229 if (end_x >= COLNO) end_x = COLNO - 1;
230 if (end_y >= ROWNO) end_y = ROWNO - 1;
231 for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {
232 if ((mtmp = m_at(x,y)) != 0) {
233 wakeup(mtmp); /* peaceful monster will become hostile */
234 if (mtmp->mundetected && is_hider(mtmp->data)) {
235 mtmp->mundetected = 0;
236 if (cansee(x,y))
237 pline("%s is shaken loose from the ceiling!",
238 Amonnam(mtmp));
239 else
240 You_hear("a thumping sound.");
241 if (x==u.ux && y==u.uy)
242 You("easily dodge the falling %s.",
243 mon_nam(mtmp));
244 newsym(x,y);
245 }
246 }
247 if (!rn2(14 - force)) switch (levl[x][y].typ) {
248 case FOUNTAIN : /* Make the fountain disappear */
249 if (cansee(x,y))
250 pline_The("fountain falls into a chasm.");
251 goto do_pit;
252 #ifdef SINKS
253 case SINK :
254 if (cansee(x,y))
255 pline_The("kitchen sink falls into a chasm.");
256 goto do_pit;
257 #endif
258 case ALTAR :
259 if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) break;
260
261 if (cansee(x,y))
262 pline_The("altar falls into a chasm.");
263 goto do_pit;
264 case GRAVE :
265 if (cansee(x,y))
266 pline_The("headstone topples into a chasm.");
267 goto do_pit;
268 case THRONE :
269 if (cansee(x,y))
270 pline_The("throne falls into a chasm.");
271 /* Falls into next case */
272 case ROOM :
273 case CORR : /* Try to make a pit */
274 do_pit: chasm = maketrap(x,y,PIT);
275 if (!chasm) break; /* no pit if portal at that location */
276 chasm->tseen = 1;
277
278 levl[x][y].doormask = 0;
279
280 mtmp = m_at(x,y);
281
282 if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
283 if (cansee(x, y))
284 pline("KADOOM! The boulder falls into a chasm%s!",
285 ((x == u.ux) && (y == u.uy)) ? " below you" : "");
286 if (mtmp)
287 mtmp->mtrapped = 0;
288 obj_extract_self(otmp);
289 (void) flooreffects(otmp, x, y, "");
290 break;
291 }
292
293 /* We have to check whether monsters or player
294 falls in a chasm... */
295
296 if (mtmp) {
297 if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
298 mtmp->mtrapped = 1;
299 if(cansee(x,y))
300 pline("%s falls into a chasm!", Monnam(mtmp));
301 else if (flags.soundok && humanoid(mtmp->data))
302 You_hear("a scream!");
303 mselftouch(mtmp, "Falling, ", TRUE);
304 if (mtmp->mhp > 0)
305 if ((mtmp->mhp -= rnd(6)) <= 0) {
306 if(!cansee(x,y))
307 pline("It is destroyed!");
308 else {
309 You("destroy %s!", mtmp->mtame ?
310 x_monnam(mtmp, ARTICLE_THE, "poor",
311 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE):
312 mon_nam(mtmp));
313 }
314 xkilled(mtmp,0);
315 }
316 }
317 } else if (!u.utrap && x == u.ux && y == u.uy) {
318 if (Levitation || Flying ||
319 is_clinger(youmonst.data)) {
320 pline("A chasm opens up under you!");
321 You("don't fall in!");
322 } else {
323 You("fall into a chasm!");
324 u.utrap = rn1(6,2);
325 u.utraptype = TT_PIT;
326 losehp(rnd(6),"fell into a chasm",
327 NO_KILLER_PREFIX);
328 selftouch("Falling, you");
329 }
330 } else newsym(x,y);
331 break;
332 case DOOR : /* Make the door collapse */
333 /* ALI - artifact doors */
334 if (artifact_door(x, y)) break;
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 %s.", Hallucination ? "elevator music" : "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 %s is shaking around you!", get_generic_level_description(&u.uz));
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 warning("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 1;
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