Source:NetHack 3.2.0/music.c

Below is the full text to music.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/music.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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