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 31STATIC_DCL void FDECL(awaken_monsters,(int)); 32STATIC_DCL void FDECL(put_monsters_to_sleep,(int)); 33STATIC_DCL void FDECL(charm_snakes,(int)); 34STATIC_DCL void FDECL(calm_nymphs,(int)); 35STATIC_DCL void FDECL(charm_monsters,(int)); 36STATIC_DCL void FDECL(do_earthquake,(int)); 37STATIC_DCL int FDECL(do_improvisation,(struct obj *)); 38 39#ifdef UNIX386MUSIC 40STATIC_DCL int NDECL(atconsole); 41STATIC_DCL void FDECL(speaker,(struct obj *,char *)); 42#endif 43#ifdef VPIX_MUSIC 44extern int sco_flag_console; /* will need changing if not _M_UNIX */ 45STATIC_DCL void NDECL(playinit); 46STATIC_DCL void FDECL(playstring, (char *,size_t)); 47STATIC_DCL void FDECL(speaker,(struct obj *,char *)); 48#endif 49#ifdef PCMUSIC 50void FDECL( pc_speaker, ( struct obj *, char * ) ); 51#endif 52#ifdef AMIGA 53void FDECL( amii_speaker, ( struct obj *, char *, int ) ); 54#endif 55 56/* 57 * Wake every monster in range... 58 */ 59 60STATIC_OVL void 61awaken_monsters(distance) 62int 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 88STATIC_OVL void 89put_monsters_to_sleep(distance) 90int 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 108STATIC_OVL void 109charm_snakes(distance) 110int 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 142STATIC_OVL void 143calm_nymphs(distance) 144int 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 165void 166awaken_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 188STATIC_OVL void 189charm_monsters(distance) 190int 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 215STATIC_OVL void 216do_earthquake(force) 217int 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 */ 276do_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 352STATIC_OVL int 353do_improvisation(instr) 354struct 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 475int 476do_play_instrument(instr) 477struct 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 617STATIC_OVL int 618atconsole() 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 635STATIC_OVL void 636speaker(instr, buf) 637struct obj *instr; 638char *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 689STATIC_OVL void tone(hz, ticks) 690/* emit tone of frequency hz for given number of ticks */ 691unsigned 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 700STATIC_OVL void rest(ticks) 701/* rest for given number of ticks */ 702int 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 714STATIC_OVL void 715speaker(instr, buf) 716struct obj *instr; 717char *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 744main(argc,argv) 745char *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