Source:SLASH'EM 0.0.7E7F2/music.c

Below is the full text to music.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/music.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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. 		  case TOILET : 260. 			if (cansee(x,y)) 261. 				pline("The toilet falls into a chasm."); 262. 			goto do_pit; 263. #endif 264. 		  case ALTAR : 265. 			if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) break; 266.  267.  			if (cansee(x,y)) 268. 				pline_The("altar falls into a chasm."); 269. 			goto do_pit; 270. 		  case GRAVE : 271. 			if (cansee(x,y)) 272. 				pline_The("headstone topples into a chasm."); 273. 			goto do_pit; 274. 		  case THRONE : 275. 			if (cansee(x,y)) 276. 				pline_The("throne falls into a chasm."); 277. 			/* Falls into next case */ 278. 		  case ROOM : 279. 		  case CORR : /* Try to make a pit */ 280. do_pit:		    chasm = maketrap(x,y,PIT); 281. 		    if (!chasm) break;	/* no pit if portal at that location */ 282. 		    chasm->tseen = 1; 283.  284.  		    levl[x][y].doormask = 0; 285.  286.  		    mtmp = m_at(x,y); 287.  288.  		    if ((otmp = sobj_at(BOULDER, x, y)) != 0) { 289. 			if (cansee(x, y)) 290. 			   pline("KADOOM! The boulder falls into a chasm%s!",  291.  			      ((x == u.ux) && (y == u.uy)) ? " below you" : ""); 292. 			if (mtmp) 293. 				mtmp->mtrapped = 0; 294. 			obj_extract_self(otmp); 295. 			(void) flooreffects(otmp, x, y, ""); 296. 			break; 297. 		    }  298.   299.  		    /* We have to check whether monsters or player 300. 		       falls in a chasm... */ 301.   302.  		    if (mtmp) { 303. 			if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) { 304. 			    mtmp->mtrapped = 1; 305. 			    if(cansee(x,y)) 306. 				pline("%s falls into a chasm!", Monnam(mtmp)); 307. 			    else if (flags.soundok && humanoid(mtmp->data)) 308. 				You_hear("a scream!"); 309. 			    mselftouch(mtmp, "Falling, ", TRUE); 310. 			    if (mtmp->mhp > 0) 311. 				if ((mtmp->mhp -= rnd(6)) <= 0) { 312. 				    if(!cansee(x,y)) 313. 					pline("It is destroyed!"); 314. 				    else { 315. 					You("destroy %s!", mtmp->mtame ?  316.  					    x_monnam(mtmp, ARTICLE_THE, "poor", 317. 				mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE): 318.  					    mon_nam(mtmp)); 319. 				    }  320.  				    xkilled(mtmp,0); 321. 				}  322.  			}  323.  		    } else if (x == u.ux && y == u.uy) { 324. 				/* KMH, balance patch -- new intrinsic */ 325. 			    if (Levitation || Flying ||  326.  						is_clinger(youmonst.data)) { 327. 				    pline("A chasm opens up under you!"); 328. 				    You("don't fall in!"); 329. 			    } else { 330. 				    You("fall into a chasm!"); 331. 				    u.utrap = rn1(6,2); 332. 				    u.utraptype = TT_PIT; 333. 				    losehp(rnd(6),"fell into a chasm",  334.  					NO_KILLER_PREFIX); 335. 				    selftouch("Falling, you"); 336. 			    }  337.  		    } else newsym(x,y); 338. 		    break; 339. 		  case DOOR : /* Make the door collapse */ 340. 		    /* ALI - artifact doors */ 341. 		    if (artifact_door(x, y))  break; 342. 		    if (levl[x][y].doormask == D_NODOOR) goto do_pit; 343. 		    if (cansee(x,y)) 344. 			pline_The("door collapses."); 345. 		    if (*in_rooms(x, y, SHOPBASE)) 346. 			add_damage(x, y, 0L); 347. 		    levl[x][y].doormask = D_NODOOR; 348. 		    unblock_point(x,y); 349. 		    newsym(x,y); 350. 		    break; 351. 	    }  352.  	}  353.  }  354.   355.  /*  356.   * The player is trying to extract something from his/her instrument. 357.  */  358.   359.  STATIC_OVL int 360. do_improvisation(instr) 361. struct obj *instr; 362. {  363.  	int damage, do_spec = !Confusion; 364. #if defined(MAC) || defined(AMIGA) || defined(VPIX_MUSIC) || defined (PCMUSIC) 365. 	struct obj itmp; 366.  367.  	itmp = *instr; 368. 	/* if won't yield special effect, make sound of mundane counterpart */ 369. 	if (!do_spec || instr->spe <= 0) 370. 	    while (objects[itmp.otyp].oc_magic) itmp.otyp -= 1; 371. # ifdef MAC 372. 	mac_speaker(&itmp, "C"); 373. # endif 374. # ifdef AMIGA 375. 	amii_speaker(&itmp, "Cw", AMII_OKAY_VOLUME); 376. # endif 377. # ifdef VPIX_MUSIC 378. 	if (sco_flag_console) 379. 	    speaker(&itmp, "C"); 380. # endif 381. #ifdef PCMUSIC 382. 	  pc_speaker ( &itmp, "C"); 383. #endif 384. #endif /* MAC || AMIGA || VPIX_MUSIC || PCMUSIC */ 385.  386.  	if (!do_spec) 387. 	    pline("What you produce is quite far from music..."); 388. 	else 389. 	    You("start playing %s.", the(xname(instr))); 390.  391.  	switch (instr->otyp) { 392. 	case MAGIC_FLUTE:		/* Make monster fall asleep */ 393. 	    if (do_spec && instr->spe > 0) { 394. 		consume_obj_charge(instr, TRUE); 395.  396.  		You("produce soft music."); 397. 		put_monsters_to_sleep(u.ulevel * 5); 398. 		exercise(A_DEX, TRUE); 399. 		break; 400. 	    } /* else FALLTHRU */ 401. 	case WOODEN_FLUTE:		/* May charm snakes */ 402. 	/* KMH, balance patch -- removed 403. 	case PAN_PIPE: */ 404. 	    do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25); 405. 	    pline("%s.", Tobjnam(instr, do_spec ? "trill" : "toot")); 406. 	    if (do_spec) charm_snakes(u.ulevel * 3); 407. 	    exercise(A_DEX, TRUE); 408. 	    break; 409. 	case FROST_HORN:		/* Idem wand of cold */ 410. 	case FIRE_HORN:			/* Idem wand of fire */ 411. 	    if (do_spec && instr->spe > 0) { 412. 		consume_obj_charge(instr, TRUE); 413.  414.  		if (!getdir((char *)0)) { 415. 		    pline("%s.", Tobjnam(instr, "vibrate")); 416. 		    break; 417. 		} else if (!u.dx && !u.dy && !u.dz) { 418. 		    if ((damage = zapyourself(instr, TRUE)) != 0) { 419. 			char buf[BUFSZ]; 420. 			Sprintf(buf, "using a magical horn on %sself", uhim); 421. 			losehp(damage, buf, KILLED_BY); 422. 		    }  423.  		} else { 424. 		    buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1,  425.  			 rn1(6,6), u.ux, u.uy, u.dx, u.dy); 426. 		}  427.  		makeknown(instr->otyp); 428. 		break; 429. 	    } /* else FALLTHRU */ 430. 	case TOOLED_HORN:		/* Awaken or scare monsters */ 431. 	    You("produce a frightful, grave sound."); 432. 	    awaken_monsters(u.ulevel * 30); 433. 	    exercise(A_WIS, FALSE); 434. 	    break; 435. 	case BUGLE:			/* Awaken & attract soldiers */ 436. 	    You("extract a loud noise from %s.", the(xname(instr))); 437. 	    awaken_soldiers; 438. 	    exercise(A_WIS, FALSE); 439. 	    break; 440. 	case MAGIC_HARP:		/* Charm monsters */ 441. 	    if (do_spec && instr->spe > 0) { 442. 		consume_obj_charge(instr, TRUE); 443.  444.  		pline("%s very attractive music.", Tobjnam(instr, "produce")); 445. 		charm_monsters((u.ulevel - 1) / 3 + 1); 446. 		exercise(A_DEX, TRUE); 447. 		break; 448. 	    } /* else FALLTHRU */ 449. 	case WOODEN_HARP:		/* May calm Nymph */ 450. 	    do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25); 451. 	    pline("%s %s.", The(xname(instr)),  452.  		  do_spec ? "produces a lilting melody" : "twangs"); 453. 	    if (do_spec) calm_nymphs(u.ulevel * 3); 454. 	    exercise(A_DEX, TRUE); 455. 	    break; 456. 	case DRUM_OF_EARTHQUAKE:	/* create several pits */ 457. 	    if (do_spec && instr->spe > 0) { 458. 		consume_obj_charge(instr, TRUE); 459.  460.  		You("produce a heavy, thunderous rolling!"); 461. 		pline_The("entire dungeon is shaking around you!"); 462. 		do_earthquake((u.ulevel - 1) / 3 + 1); 463. 		/* shake up monsters in a much larger radius... */ 464.  		awaken_monsters(ROWNO * COLNO); 465. 		makeknown(DRUM_OF_EARTHQUAKE); 466. 		break; 467. 	    } /* else FALLTHRU */ 468. 	/* KMH, balance patch -- removed (in the wrong place anyways) */ 469. #if 0 470. 	case PAN_PIPE_OF_SUMMONING: /* yikes! */ 471.  	    if (instr->spe > 0) { 472. 		register int cnt = 1; 473. 		instr->spe--; 474. 		cnt += rn2(4) + 3; 475. 		while(cnt--) 476. 		(void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS); 477. 	    }  478.  		break; 479. 	case PAN_PIPE_OF_THE_SEWERS: 480. 	    You("call out the rats!"); 481. 	    if (instr->spe > 0) { 482. 		register int cnt = 1; 483. 		register struct monst *mtmp; 484. 		instr->spe--; 485. 		cnt += rn2(4) + 3; 486. 		while(cnt--) { 487. 		mtmp = makemon(&mons[PM_SEWER_RAT], u.ux, u.uy, NO_MM_FLAGS); 488. 		(void) tamedog(mtmp, (struct obj *) 0); 489. 		}  490.  	     }  491.  		break; 492. #endif 493. 	case LEATHER_DRUM:		/* Awaken monsters */ 494. 	    You("beat a deafening row!"); 495. 	    awaken_monsters(u.ulevel * 40); 496. 	    exercise(A_WIS, FALSE); 497. 	    break; 498. 	default: 499. 	    impossible("What a weird instrument (%d)!", instr->otyp); 500. 	    break; 501. 	}  502.  	return 2;		/* That takes time */ 503. }  504.   505.  /*  506.   * So you want music...  507. */ 508.   509.  int 510. do_play_instrument(instr) 511. struct obj *instr; 512. {  513.      char buf[BUFSZ], c = 'y'; 514.     char *s; 515.     int x,y; 516.     boolean ok; 517.  518.      if (Underwater) { 519. 	You_cant("play music underwater!"); 520. 	return(0); 521.     }  522.      if (instr->otyp != LEATHER_DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) { 523. 	c = yn("Improvise?"); 524.     }  525.      if (c == 'n') { 526. 	if (u.uevent.uheard_tune == 2 && yn("Play the passtune?") == 'y') { 527. 	    Strcpy(buf, tune); 528. 	} else { 529. 	    getlin("What tune are you playing? [5 notes, A-G]", buf); 530. 	    (void)mungspaces(buf); 531. 	    /* convert to uppercase and change any "H" to the expected "B" */ 532. 	    for (s = buf; *s; s++) { 533. #ifndef AMIGA 534. 		*s = highc(*s); 535. #else 536. 		/* The AMIGA supports two octaves of notes */ 537. 		if (*s == 'h') *s = 'b'; 538. #endif 539. 		if (*s == 'H') *s = 'B'; 540. 	    }  541.  	}  542.  	You("extract a strange sound from %s!", the(xname(instr))); 543. #ifdef UNIX386MUSIC 544. 	/* if user is at the console, play through the console speaker */ 545. 	if (atconsole) 546. 	    speaker(instr, buf); 547. #endif 548. #ifdef VPIX_MUSIC 549. 	if (sco_flag_console) 550. 	    speaker(instr, buf); 551. #endif 552. #ifdef MAC 553. 	mac_speaker ( instr, buf ) ; 554. #endif 555. #ifdef PCMUSIC 556. 	pc_speaker ( instr, buf ); 557. #endif 558. #ifdef AMIGA 559. 	{  560.  		char nbuf[ 20 ]; 561. 		int i;  562. for( i = 0; buf[i] && i < 5; ++i ) 563. 		{  564.  			nbuf[ i*2 ] = buf[ i ]; 565. 			nbuf[ (i*2)+1 ] = 'h'; 566. 		}  567.  		nbuf[ i*2 ] = 0; 568. 		amii_speaker ( instr, nbuf, AMII_OKAY_VOLUME ) ; 569. 	}  570.  #endif 571. 	/* Check if there was the Stronghold drawbridge near 572. 	 * and if the tune conforms to what we're waiting for. 573. 	 */  574.  	if(Is_stronghold(&u.uz)) { 575. 	    exercise(A_WIS, TRUE);		/* just for trying */ 576. 	    if(!strcmp(buf,tune)) { 577. 		/* Search for the drawbridge */ 578. 		for(y=u.uy-1; y<=u.uy+1; y++) 579. 		    for(x=u.ux-1;x<=u.ux+1;x++) 580. 			if(isok(x,y)) 581. 			if(find_drawbridge(&x,&y)) { 582. 			    u.uevent.uheard_tune = 2; /* tune now fully known */ 583. 			    if(levl[x][y].typ == DRAWBRIDGE_DOWN) 584. 				close_drawbridge(x,y); 585. 			    else 586. 				open_drawbridge(x,y); 587. 			    return 0; 588. 			}  589.  	    } else if(flags.soundok) { 590. 		if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1; 591. 		/* Okay, it wasn't the right tune, but perhaps 592. 		 * we can give the player some hints like in the 593. 		 * Mastermind game */ 594. 		ok = FALSE; 595. 		for(y = u.uy-1; y <= u.uy+1 && !ok; y++) 596. 		    for(x = u.ux-1; x <= u.ux+1 && !ok; x++) 597. 			if(isok(x,y)) 598. 			if(IS_DRAWBRIDGE(levl[x][y].typ) ||  599.  			   is_drawbridge_wall(x,y) >= 0) 600. 				ok = TRUE; 601. 		if(ok) { /* There is a drawbridge near */ 602. 		    int tumblers, gears; 603. 		    boolean matched[5]; 604.  605.  		    tumblers = gears = 0; 606. 		    for(x=0; x < 5; x++) 607. 			matched[x] = FALSE; 608.  609.  		    for(x=0; x < (int)strlen(buf); x++) 610. 			if(x < 5) { 611. 			    if(buf[x] == tune[x]) { 612. 				gears++; 613. 				matched[x] = TRUE; 614. 			    } else 615. 				for(y=0; y < 5; y++) 616. 				    if(!matched[y] &&  617.  				       buf[x] == tune[y] &&  618.  				       buf[y] != tune[y]) { 619. 					tumblers++; 620. 					matched[y] = TRUE; 621. 					break; 622. 				    }  623.  			}  624.  			 if(tumblers) { 625. 			if(gears) 626. 			    You_hear("%d tumbler%s click and %d gear%s turn.",  627.  				tumblers, plur(tumblers), gears, plur(gears)); 628. 			else 629. 			    You_hear("%d tumbler%s click.",  630.  				tumblers, plur(tumblers)); 631. 			 } else if(gears) { 632. 			You_hear("%d gear%s turn.", gears, plur(gears)); 633. 			/* could only get `gears == 5' by playing five 634. 			   correct notes followed by excess; otherwise, 635. 			   tune would have matched above */ 636. 			if (gears == 5) u.uevent.uheard_tune = 2; 637. 		    }  638.  		}  639.  	    }  640.  	  }  641.  	return 1; 642.     } else 643. 	    return do_improvisation(instr); 644. }  645.   646.  #ifdef UNIX386MUSIC 647. /*  648.   * Play audible music on the machine's speaker if appropriate. 649.  */  650.   651.  STATIC_OVL int 652. atconsole 653. {  654.      /*  655.       * Kluge alert: This code assumes that your [34]86 has no X terminals 656.      * attached and that the console tty type is AT386 (this is always true  657.       * under AT&T UNIX for these boxen). The theory here is that your remote 658.      * ttys will have terminal type `ansi' or something else other than 659.      * `AT386' or `xterm'. We'd like to do better than this, but testing 660.      * to see if we're running on the console physical terminal is quite 661.      * difficult given the presence of virtual consoles and other modern 662.      * UNIX impedimenta...  663. */ 664.      char	*termtype = nh_getenv("TERM"); 665.  666.       return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm")); 667. }  668.   669.  STATIC_OVL void 670. speaker(instr, buf) 671. struct obj *instr; 672. char	*buf; 673. {  674.      /*  675.       * For this to work, you need to have installed the PD speaker-control 676.      * driver for PC-compatible UNIX boxes that I (esr@snark.thyrsus.com) 677.      * posted to comp.sources.unix in Feb 1990. A copy should be included 678.      * with your nethack distribution. 679.      */  680.      int	fd; 681.  682.      if ((fd = open("/dev/speaker", 1)) != -1) 683.     {  684.  	/* send a prefix to modify instrumental `timbre' */ 685. 	switch (instr->otyp) 686. 	{  687.  	case WOODEN_FLUTE: 688. 	case MAGIC_FLUTE: 689. 	    (void) write(fd, ">ol", 1); /* up one octave & lock */ 690. 	    break; 691. 	case TOOLED_HORN: 692. 	case FROST_HORN: 693. 	case FIRE_HORN: 694. 	    (void) write(fd, "<  714. #include  715. #include  716. # else 717. #define KIOC ('K' << 8) 718. #define KDMKTONE (KIOC | 8) 719. # endif 720.  721.  #define noDEBUG 722.  723.  STATIC_OVL void tone(hz, ticks) 724. /* emit tone of frequency hz for given number of ticks */ 725. unsigned int hz, ticks; 726. {  727.      ioctl(0,KDMKTONE,hz|((ticks*10)<<16)); 728. # ifdef DEBUG 729.     printf("TONE: %6d %6d\n",hz,ticks * 10); 730. # endif 731.     nap(ticks * 10); 732. }  733.   734.  STATIC_OVL void rest(ticks) 735. /* rest for given number of ticks */ 736. int	ticks; 737. {  738.      nap(ticks * 10); 739. # ifdef DEBUG 740.     printf("REST:        %6d\n",ticks * 10); 741. # endif 742. }  743.   744.   745.  #include "interp.c"	/* from snd86unx.shr */ 746.  747.   748.  STATIC_OVL void 749. speaker(instr, buf) 750. struct obj *instr; 751. char	*buf; 752. {  753.      /* emit a prefix to modify instrumental `timbre' */ 754.     playinit; 755.     switch (instr->otyp) 756.     {  757.  	case WOODEN_FLUTE: 758. 	case MAGIC_FLUTE: 759. 	    playstring(">ol", 1); /* up one octave & lock */ 760. 	    break; 761. 	case TOOLED_HORN: 762. 	case FROST_HORN: 763. 	case FIRE_HORN: 764. 	    playstring("<<ol", 2); /* drop two octaves & lock */ 765. 	    break; 766. 	case BUGLE: 767. 	    playstring("ol", 2); /* octave lock */ 768. 	    break; 769. 	case WOODEN_HARP: 770. 	case MAGIC_HARP: 771. 	    playstring("l8mlol", 4); /* fast, legato, octave lock */ 772. 	    break; 773.     }  774.      playstring( buf, strlen(buf)); 775. }  776.   777.  # ifdef DEBUG 778. main(argc,argv) 779. char *argv[]; 780. {  781.      if (argc == 2) { 782. 	playinit; 783. 	playstring(argv[1], strlen(argv[1])); 784.     }  785.  }  786.  # endif 787. #endif	/* VPIX_MUSIC */ 788.  789.  /*music.c*/