Source:Music.c

Below is the full text to src/music.c from NetHack 3.4.3. To link to a particular line, write [[music.c#line123 ]], for example. 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 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 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 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 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 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 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  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 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 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 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 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, "<  680. #include  681. #include  682. # else 683. #define KIOC ('K' << 8) 684. #define KDMKTONE (KIOC | 8) 685. # endif 686.  687.  #define noDEBUG 688.  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.   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 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 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*/