Source:NetHack 3.1.0/music.c
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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*/