abstract
| - 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: 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*/
|