Source:NetHack 3.1.0/music.c

Below is the full text to music.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	92/11/26	*/ 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 ramdom 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.   /*  40.    * Wake every monster in range...  41. */ 42.    43.   static void 44.  awaken_monsters(distance) 45.  int distance; 46.  {  47.   	register struct monst *mtmp = fmon; 48.   49.   	while(mtmp) { 50.  		if (distu(mtmp->mx, mtmp->my) < distance/3) { 51.  			/* May scare some monsters */ 52.  			if (!resist(mtmp, SCROLL_CLASS, 0, NOTELL)) 53.  			  mtmp->mflee = 1; 54.  		} else if (distu(mtmp->mx, mtmp->my) < distance) { 55.  			mtmp->msleep = 0; 56.  			mtmp->mcanmove = 1; 57.  			mtmp->mfrozen = 0; 58.  		}  59.   		mtmp = mtmp->nmon; 60.  	}  61.   }  62.    63.   /*  64.    * Make monsters fall asleep. Note that they may resist the spell. 65.   */  66.    67.   static void 68.  put_monsters_to_sleep(distance) 69.  int distance; 70.  {  71.   	register struct monst *mtmp = fmon; 72.   73.   	while(mtmp) { 74.  		  if (distu(mtmp->mx, mtmp->my) < distance) 75.  		    if(mtmp->mcanmove && !resist(mtmp, WAND_CLASS, 0, NOTELL)) 76.  		      mtmp->mcanmove = mtmp->mfrozen = 0; 77.  		mtmp = mtmp->nmon; 78.  	}  79.   }  80.    81.   /*  82.    * Charm snakes in range. Note that the snakes are NOT tamed. 83.   */  84.    85.   static void 86.  charm_snakes(distance) 87.  int distance; 88.  {  89.   	register struct monst *mtmp = fmon; 90.   91.   	while (mtmp) { 92.  		if (mtmp->data->mlet == S_SNAKE &&  93.   		    distu(mtmp->mx, mtmp->my) < distance) { 94.  			mtmp->mpeaceful = 1; 95.  			if (cansee(mtmp->mx, mtmp->my)) 96.  				pline(  97.    "%s freezes and sways with the music, then seems quieter.", Monnam(mtmp)); 98.  		}  99.   		mtmp = mtmp->nmon; 100. 	}  101.  }  102.   103.  /*  104.   * Calm nymphs in range. 105.  */  106.   107.  static void 108. calm_nymphs(distance) 109. int distance; 110. {  111.  	register struct monst *mtmp = fmon; 112.  113.  	while (mtmp) { 114. 		if (mtmp->data->mlet == S_NYMPH &&  115.  		    distu(mtmp->mx, mtmp->my) < distance) { 116. 			mtmp->mpeaceful = 1; 117. 			if (cansee(mtmp->mx, mtmp->my)) 118. 				pline(  119.   "%s listens cheerfully to the music, then seems quieter.", Monnam(mtmp)); 120. 		}  121.  		mtmp = mtmp->nmon; 122. 	}  123.  }  124.   125.  /* Awake only soldiers of the level. */ 126.   127.  void 128. awaken_soldiers { 129. #ifdef ARMY 130. 	register struct monst *mtmp = fmon; 131.  132.  	while(mtmp) { 133. 	    if (is_mercenary(mtmp->data) && mtmp->data != &mons[PM_GUARD]) { 134. 		mtmp->mpeaceful = mtmp->msleep = 0; 135. 		mtmp->mcanmove = 1; 136. 		if (canseemon(mtmp)) 137. 		    pline("%s is now ready for battle!", Monnam(mtmp)); 138. 		else 139. 		    Norep("You hear the sound of battle gear being readied."); 140. 	    }  141.  	    mtmp = mtmp->nmon; 142. 	}  143.  #endif /* ARMY */ 144. }  145.   146.  /* Charm monsters in range. Note that they may resist the spell. */ 147.   148.  static void 149. charm_monsters(distance) 150. int distance; 151. {  152.  	register struct monst *mtmp = fmon, *mtmp2; 153.  154.  	while(mtmp) { 155. 		mtmp2 = mtmp->nmon; 156. 		if (distu(mtmp->mx, mtmp->my) <= distance) 157. 		    if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL)) 158. 			(void) tamedog(mtmp, (struct obj *) 0); 159. 		mtmp = mtmp2; 160. 	}  161.   162.  }  163.   164.  /* Generate earthquake :-) of desired force.  165.   * That is:  create random chasms (pits).  166.   */  167.   168.  static void  169.  do_earthquake(force)  170.  int force;  171.  {  172.  	register int x,y;  173.  	struct monst *mtmp;  174.  	struct obj *otmp;  175.  	struct trap *chasm;  176.  	int start_x, start_y, end_x, end_y;  177.   178.  	start_x = u.ux - (force * 2);  179.  	start_y = u.uy - (force * 2);  180.  	end_x = u.ux + (force * 2);  181.  	end_y = u.uy + (force * 2);  182.  	if (start_x < 1) start_x = 1;  183.  	if (start_y < 1) start_y = 1;  184.  	if (end_x >= COLNO) end_x = COLNO - 1;  185.  	if (end_y >= ROWNO) end_y = ROWNO - 1;  186.  	for (x=start_x; x<=end_x; x++) for (y=start_y; y<=end_y; y++) {  187.  	    if (mtmp = m_at(x,y)) {  188.  		if (mtmp->mundetected && is_hider(mtmp->data)) {  189.  		    mtmp->mundetected = 0; 190. 		    if (cansee(x,y)) 191. 			pline("%s is shaken loose from the ceiling!",  192.  							    Amonnam(mtmp)); 193. 		    else 194. 			You("hear a thumping sound."); 195. 		    if (x==u.ux && y==u.uy) 196. 			You("easily dodge the falling %s.",  197.  							    mon_nam(mtmp)); 198. 		    newsym(x,y); 199. 		}  200.  	    }  201.  	    if (!rn2(14 - force)) switch (levl[x][y].typ) { 202. 		  case FOUNTAIN : /* Make the fountain disappear */ 203. 			if (cansee(x,y)) 204. 				pline("The fountain falls into a chasm."); 205. 			goto do_pit; 206. #ifdef SINKS 207. 		  case SINK : 208. 			if (cansee(x,y)) 209. 				pline("The kitchen sink falls into a chasm."); 210. 			goto do_pit; 211. #endif 212. 		  case ALTAR : 213. 			if (cansee(x,y)) 214. 				pline("The altar falls into a chasm."); 215. 			goto do_pit; 216. 		  case THRONE : 217. 			if (cansee(x,y)) 218. 				pline("The throne falls into a chasm."); 219. 			/* Falls into next case */ 220. 		  case ROOM : 221. 		  case CORR : /* Try to make a pit */ 222. do_pit:		    chasm = maketrap(x,y,PIT); 223. 		    chasm->tseen = 1; 224.  225.  		    levl[x][y].doormask = 0; 226.  227.  		    mtmp = m_at(x,y); 228.  229.  		    if (otmp = sobj_at(BOULDER, x, y)) { 230. 			if (cansee(x, y)) 231. 			   pline("KADOOM! The boulder falls into a chasm%s!",  232.  			      ((x == u.ux) && (y == u.uy)) ? " below you" : ""); 233. 			if (mtmp) 234. 				mtmp->mtrapped = 0; 235. 			freeobj(otmp); 236. 			(void) flooreffects(otmp, x, y, ""); 237. 			break; 238. 		    }	  239.   240.  		    /* We have to check whether monsters or player 241. 		       falls in a chasm... */ 242.   243.  		    if (mtmp) { 244. 			if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) { 245. 			    mtmp->mtrapped = 1; 246. 			    if(cansee(x,y)) 247. 				pline("%s falls into a chasm!", Monnam(mtmp)); 248. 			    else if (flags.soundok && humanoid(mtmp->data)) 249. 				You("hear a scream!"); 250. 			    if ((mtmp->mhp -= rnd(6)) <= 0) { 251. 				if(!cansee(x,y)) 252. 				    pline("It is destroyed!"); 253. 				else { 254. 				    You("destroy %s!", mtmp->mtame ?  255.  					x_monnam(mtmp, 0, "poor", 0) :  256.  					mon_nam(mtmp)); 257. 				}  258.  				xkilled(mtmp,0); 259. 			    }  260.  			}  261.  		    } else if (x == u.ux && y == u.uy) { 262. 			    if (Levitation  263.  #ifdef POLYSELF  264.  				|| is_flyer(uasmon) || is_clinger(uasmon)  265.  #endif  266.  				) { 267. 				    pline("A chasm opens up under you!"); 268. 				    You("don't fall in!"); 269. 			    } else { 270. 				    You("fall into a chasm!"); 271. 				    u.utrap = rn1(6,2); 272. 				    u.utraptype = TT_PIT; 273. 				    losehp(rnd(6),"fell into a chasm",  274.  					NO_KILLER_PREFIX); 275. 				    selftouch("Falling, you"); 276. 			    }  277.  		    } else newsym(x,y); 278. 		    break; 279. 		  case DOOR : /* Make the door collapse */ 280. 		    if (levl[x][y].doormask == D_NODOOR) break; 281. 		    if (cansee(x,y)) 282. 			pline("The door collapses."); 283. 		    levl[x][y].doormask = D_NODOOR; 284. 		    newsym(x,y); 285. 		    break; 286. 	    }  287.  	}  288.  }  289.   290.  /*  291.   * The player is trying to extract something from his/her instrument. 292.  */  293.   294.  static int 295. do_improvisation(instr) 296. struct obj *instr; 297. {  298.  	int damage; 299.  300.  #ifdef MAC 301. 	mac_speaker ( instr, "C" ) ; 302. #endif 303.  304.  	if (Confusion) 305. 	  pline("What you produce is quite far from music..."); 306. 	else 307. 	  You("start playing %s.", the(xname(instr))); 308. 	switch (instr->otyp) { 309. 	      case WOODEN_FLUTE:	/* May charm snakes */ 310. 		if (rn2(ACURR(A_DEX)) + u.ulevel > 25) 311. 		  charm_snakes((int)u.ulevel*3); 312. 		exercise(A_DEX, TRUE); 313. 		break; 314. 	      case MAGIC_FLUTE: /* Make monster fall asleep */ 315. 		if (instr->spe > 0) { 316. 			instr->spe--; 317. 			You("produce soft music."); 318. 			put_monsters_to_sleep((int)u.ulevel*5); 319. 		}  320.  		exercise(A_DEX, TRUE); 321. 		break; 322. 	      case TOOLED_HORN:	/* Awaken monsters or scare monsters */ 323. 		You("produce a frightful, grave sound."); 324. 		awaken_monsters((int)u.ulevel*30); 325. 		exercise(A_WIS, FALSE); 326. 		break; 327. 	      case FROST_HORN:	/* Idem wand of cold */ 328. 	      case FIRE_HORN:	/* Idem wand of fire */ 329. 		if (instr->spe > 0) { 330. 			instr->spe--; 331. 			if (!getdir(NULL)) { 332. 				if (!Blind) 333. 				    pline("%s glows then fades.",  334.  					  The(xname(instr))); 335. 			} else { 336. 				if (!u.dx && !u.dy && !u.dz) { 337. 					if((damage = zapyourself(instr))) 338. 					  losehp(damage,  339.  		self_pronoun("using a magical horn on %sself", "him"),  340.  					  NO_KILLER_PREFIX); 341. 					makeknown(instr->otyp); 342. 					return(2); 343. 				}  344.  				buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1, rn1(6,6), u.ux, u.uy, u.dx, u.dy); 345. 				makeknown(instr->otyp); 346. 				return(2); 347. 			}  348.  		}  349.  		break; 350. 	      case BUGLE:	/* Awaken & attract soldiers */ 351. 		You("extract a loud noise from %s.", the(xname(instr))); 352. 		awaken_soldiers; 353. 		exercise(A_WIS, FALSE); 354. 		break; 355. 	      case WOODEN_HARP:	/* May calm Nymph */ 356. 		if (rn2(ACURR(A_DEX)) + u.ulevel > 25) 357. 		  calm_nymphs((int)u.ulevel*3); 358. 		exercise(A_DEX, TRUE); 359. 		break; 360. 	      case MAGIC_HARP:	/* Charm monsters */ 361. 		if (instr->spe > 0) { 362. 			pline("%s produces very attractive music.",  363.  			      The(xname(instr))); 364. 			instr->spe--; 365. 			charm_monsters(((int)u.ulevel - 1) / 3 + 1); 366. 		}  367.  		exercise(A_DEX, TRUE); 368. 		break; 369. 	      case LEATHER_DRUM:	/* Awaken monsters */ 370. 		You("beat a deafening row!"); 371. 		awaken_monsters((int)u.ulevel * 40); 372. 		exercise(A_WIS, FALSE); 373. 		break; 374. 	      case DRUM_OF_EARTHQUAKE:	/* create several pits */ 375. 		if (instr->spe > 0) { 376. 			You("produce a heavy, thunderous rolling!"); 377. 			pline("The entire dungeon is shaking around you!"); 378. 			instr->spe--; 379. 			do_earthquake(((int)u.ulevel - 1) / 3 + 1); 380. 			makeknown(DRUM_OF_EARTHQUAKE); 381. 		}  382.  		break; 383. 	      default: 384. 		impossible("What a weird instrument (%d)!",instr->otyp); 385. 		break; 386. 	}  387.  	return (2);		/* That takes time */ 388. }  389.   390.  #ifdef SYSV386MUSIC 391. /*  392.   * Play audible music on the machine's speaker if appropriate. 393.  */  394.   395.  static int 396. atconsole 397. {  398.      /*  399.       * Kluge alert: This code assumes that your [34]86 has no X terminals 400.      * attached and that the console tty type is AT386 (this is always true  401.       * under AT&T UNIX for these boxen). The theory here is that your remote 402.      * ttys will have terminal type `ansi' or something else other than 403.      * `AT386' or `xterm'. We'd like to do better than this, but testing 404.      * to see if we're running on the console physical terminal is quite 405.      * difficult given the presence of virtual consoles and other modern 406.      * UNIX impedimenta...  407. */ 408.      char	*termtype = getenv("TERM"); 409.  410.       return(!strcmp(termtype, "AT386") || !strcmp(termtype, "xterm")); 411. }  412.   413.  static void 414. speaker(instr, buf) 415. struct obj *instr; 416. char	*buf; 417. {  418.      /*  419.       * For this to work, you need to have installed the PD speaker-control 420.      * driver for PC-compatible UNIX boxes that I (eric@snark.uu.net) 421.      * posted to comp.sources.unix in Feb 1990. A copy may be included 422.      * with your nethack distribution. 423.      */  424.      int	fd; 425.  426.      if ((fd = open("/dev/speaker", 1)) != -1) 427.     {  428.  	/* emit a prefix to modify instrumental `timbre' */ 429. 	switch (instr->otyp) 430. 	{  431.  	case WOODEN_FLUTE: 432. 	case MAGIC_FLUTE: 433. 	    (void) write(fd, ">ol", 1); /* up one octave & lock */ 434. 	    break; 435. 	case TOOLED_HORN: 436. 	case FROST_HORN: 437. 	case FIRE_HORN: 438. 	    (void) write(fd, "<<ol", 2); /* drop two octaves & lock */ 439. 	    break; 440. 	case BUGLE: 441. 	    (void) write(fd, "ol", 2); /* octave lock */ 442. 	    break; 443. 	case WOODEN_HARP: 444. 	case MAGIC_HARP: 445. 	    (void) write(fd, "l8mlol", 4); /* fast, legato, octave lock */ 446. 	    break; 447. 	}  448.  	(void) write(fd, buf, strlen(buf)); 449. 	(void) close(fd); 450.     }  451.  }  452.  #endif /* SYSV386MUSIC */ 453.  454.  /*  455.   * So you want music...  456. */ 457.   458.  int 459. do_play_instrument(instr) 460. struct obj *instr; 461. {  462.      char buf[BUFSZ], *s, c = 'y'; 463.     int x,y; 464.     boolean ok; 465.  466.      if (Underwater) { 467. 	You("can't 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. 	getlin("What tune are you playing? [what 5 notes]", buf); 475. 	for (s=buf; *s; s++) *s = highc(*s); 476. 	You("extract a strange sound from %s!", the(xname(instr))); 477. #ifdef SYSV386MUSIC 478. 	/* if user is at the console, play through the console speaker */ 479. 	if (atconsole) 480. 	    speaker(instr, buf); 481. #endif /* SYSV386MUSIC */ 482. #ifdef MAC 483. 	mac_speaker ( instr, buf ) ; 484. #endif 485. 	/* Check if there was the Stronghold drawbridge near 486. 	 * and if the tune conforms to what we're waiting for. 487. 	 */  488.  	if(Is_stronghold(&u.uz)) { 489. 	    exercise(A_WIS, TRUE);		/* just for trying */ 490. 	    if(!strcmp(buf,tune)) { 491. 		/* Search for the drawbridge */ 492. 		for(y=u.uy-1; y<=u.uy+1; y++) 493. 		    for(x=u.ux-1;x<=u.ux+1;x++) 494. 			if(isok(x,y)) 495. 			if(find_drawbridge(&x,&y)) { 496. 			    if(levl[x][y].typ == DRAWBRIDGE_DOWN) 497. 				close_drawbridge(x,y); 498. 			    else 499. 				open_drawbridge(x,y); 500. 			    return 0; 501. 			}  502.  	    } else if(flags.soundok) { 503. 		if (u.uevent.uheard_tune < 1) u.uevent.uheard_tune = 1; 504. 		/* Okay, it wasn't the right tune, but perhaps 505. 		 * we can give the player some hints like in the 506. 		 * Mastermind game */ 507. 		ok = FALSE; 508. 		for(y = u.uy-1; y <= u.uy+1 && !ok; y++) 509. 		    for(x = u.ux-1; x <= u.ux+1 && !ok; x++) 510. 			if(isok(x,y)) 511. 			if(IS_DRAWBRIDGE(levl[x][y].typ) ||  512.  			   is_drawbridge_wall(x,y) >= 0) 513. 				ok = TRUE; 514. 		if(ok) { /* There is a drawbridge near */ 515. 		    int tumblers, gears; 516. 		    boolean matched[5]; 517.  518.  		    tumblers = gears = 0; 519. 		    for(x=0; x < 5; x++) 520. 			matched[x] = FALSE; 521.  522.  		    for(x=0; x < (int)strlen(buf); x++) 523. 			if(x < 5) { 524. 			    if(buf[x] == tune[x]) { 525. 				gears++; 526. 				matched[x] = TRUE; 527. 			    } else 528. 				for(y=0; y < 5; y++) 529. 				    if(!matched[y] &&  530.  				       buf[x] == tune[y] &&  531.  				       buf[y] != tune[y]) { 532. 					tumblers++; 533. 					matched[y] = TRUE; 534. 					break; 535. 				    }  536.  			}  537.  		    if(tumblers) 538. 			if(gears) 539. 			    You("hear %d tumbler%s click and %d gear%s turn.",  540.  				tumblers, plur(tumblers), gears, plur(gears)); 541. 			else 542. 			    You("hear %d tumbler%s click.",  543.  				tumblers, plur(tumblers)); 544. 		    else if(gears) { 545. 			You("hear %d gear%s turn.", gears, plur(gears)); 546. 			if (gears == 5) u.uevent.uheard_tune = 2; 547. 		    }  548.  		}  549.  	    }  550.  	  }  551.  	return 1; 552.     } else 553. 	    return do_improvisation(instr); 554. }  555.   556.  /*music.c*/