abstract
| - Below is the full text to music.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0 88/10/22 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. * 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. * 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. * Harp May calm nymph if player has enough dexterity. 21. * Magic harp Charm monsters: area of effect depends on player 22. * level. 23. * 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. 30. #include "hack.h" 31. 32. #ifdef MUSIC 33. 34. /* 35. * Wake every monster in range... 36. */ 37. 38. static void 39. awaken_monsters(distance) 40. int distance; 41. { 42. register struct monst *mtmp = fmon; 43. 44. while(mtmp) { 45. if (dist(mtmp->mx, mtmp->my) < distance/3) { 46. /* May scare some monsters */ 47. if (!resist(mtmp, SCROLL_SYM, 0, NOTELL)) 48. mtmp->mflee = 1; 49. } else if (dist(mtmp->mx, mtmp->my) < distance) { 50. mtmp->msleep = 0; 51. mtmp->mfroz = 0; 52. } 53. mtmp = mtmp->nmon; 54. } 55. } 56. 57. /* 58. * Make monsters fall asleep. Note that they may resist the spell. 59. */ 60. 61. static void 62. put_monsters_to_sleep(distance) 63. int distance; 64. { 65. register struct monst *mtmp = fmon; 66. 67. while(mtmp) { 68. if (dist(mtmp->mx, mtmp->my) < distance) 69. if(!mtmp->mfroz && !resist(mtmp, WAND_SYM, 0, NOTELL)) 70. mtmp->mfroz = 1; 71. mtmp = mtmp->nmon; 72. } 73. } 74. 75. /* 76. * Charm snakes in range. Note that the snakes are NOT tamed. 77. */ 78. 79. static void 80. charm_snakes(distance) 81. int distance; 82. { 83. register struct monst *mtmp = fmon; 84. 85. while (mtmp) { 86. if (mtmp->data->mlet == S_SNAKE && dist(mtmp->mx, mtmp->my) < distance) { 87. mtmp->mpeaceful = 1; 88. if (cansee(mtmp->mx, mtmp->my)) 89. pline("%s freezes and sways with the music, then seems quieter.",defmonnam(mtmp)); 90. } 91. mtmp = mtmp->nmon; 92. } 93. } 94. 95. /* 96. * Calm nymphs in range. 97. */ 98. 99. static void 100. calm_nymphs(distance) 101. int distance; 102. { 103. register struct monst *mtmp = fmon; 104. 105. while (mtmp) { 106. if (mtmp->data->mlet == S_NYMPH && dist(mtmp->mx, mtmp->my) < distance) { 107. mtmp->mpeaceful = 1; 108. if (cansee(mtmp->mx, mtmp->my)) 109. pline("%s listens cheerfully to the music, then seems quieter.",defmonnam(mtmp)); 110. } 111. mtmp = mtmp->nmon; 112. } 113. } 114. 115. /* Awake only soldiers of the level. */ 116. 117. static void 118. awaken_soldiers() { 119. #ifdef ARMY 120. #define IS_SOLDIER(dat) ((int)((dat) - mons) >= PM_UNARMORED_SOLDIER && \ 121. (int) ((dat) - mons) <= PM_CAPTAIN) 122. register struct monst *mtmp = fmon; 123. 124. while(mtmp) { 125. if (IS_SOLDIER(mtmp->data)) 126. mtmp->mpeaceful = mtmp->msleep = mtmp->mfroz = 0; 127. mtmp = mtmp->nmon; 128. } 129. #endif /* ARMY /**/ 130. } 131. 132. /* Charm monsters in range. Note that they may resist the spell. */ 133. 134. static void 135. charm_monsters(distance) 136. int distance; 137. { 138. register struct monst *mtmp = fmon; 139. 140. while(mtmp) { 141. if(dist(mtmp->mx, mtmp->my) <= distance) 142. if(!resist(mtmp, SCROLL_SYM, 0, NOTELL)) 143. (void) tamedog(mtmp, (struct obj *) 0); 144. mtmp = mtmp->nmon; 145. } 146. 147. } 148. 149. /* Generate earthquake :-) of desired force. 150. * That is: create random chasms (pits). 151. */ 152. 153. static void 154. do_earthquake(force) 155. int force; 156. { 157. register int x,y; 158. struct monst *mtmp; 159. struct trap *chasm; 160. int start_x, start_y, end_x, end_y; 161. 162. start_x = u.ux - (force * 2); 163. start_y = u.uy - (force * 2); 164. end_x = u.ux + (force * 2); 165. end_y = u.uy + (force * 2); 166. if (start_x < 1) start_x = 1; 167. if (start_y < 1) start_y = 1; 168. if (end_x >= COLNO) end_x = COLNO - 1; 169. if (end_y >= ROWNO) end_y = ROWNO - 1; 170. for (x=start_x; x<=end_x; x++) 171. for (y=start_y; y<=end_y; y++) 172. if (!rn2(14 - force)) { 173. switch (levl[x][y].typ) { 174. #ifdef FOUNTAINS 175. case FOUNTAIN : /* Make the fountain disappear */ 176. if (cansee(x,y)) 177. pline("The fountain falls into a chasm."); 178. goto do_pit; 179. #endif 180. #ifdef SINKS 181. case SINK : 182. if (cansee(x,y)) 183. pline("The kitchen sink falls into a chasm."); 184. goto do_pit; 185. #endif 186. #ifdef ALTARS 187. case ALTAR : 188. if (cansee(x,y)) 189. pline("The altar falls into a chasm."); 190. goto do_pit; 191. #endif 192. #ifdef THRONES 193. case THRONE : 194. if (cansee(x,y)) 195. pline("The throne falls into a chasm."); 196. /* Falls into next case */ 197. #endif 198. case ROOM : 199. case CORR : /* Make a pit */ 200. do_pit: chasm = maketrap(x,y,PIT); 201. chasm->tseen = 1; 202. 203. levl[x][y].doormask = 0; 204. 205. /* We have to check whether monsters or player 206. fall in a chasm... */ 207. 208. if (levl[x][y].mmask) { 209. mtmp = m_at(x,y); 210. if(!is_flyer(mtmp->data)) { 211. mtmp->mtrapped = 1; 212. if(cansee(x,y)) 213. pline("%s falls into a chasm!", 214. Monnam(mtmp)); 215. else if (flags.soundok && humanoid(mtmp->data)) 216. You("hear a scream!"); 217. if ((mtmp->mhp -= rnd(6)) <= 0) { 218. int saved_conf = u.umconf; 219. 220. if(!cansee(x,y)) 221. pline("It has died!"); 222. else { 223. You("destroy %s!", 224. mtmp->mtame ? 225. a_monnam(mtmp, "poor") : 226. mon_nam(mtmp)); 227. } 228. xkilled(mtmp,0); 229. u.umconf = saved_conf; 230. } 231. } 232. } else if (x == u.ux && y == u.uy) { 233. if (Levitation 234. #ifdef POLYSELF 235. || is_flyer(uasmon) 236. #endif 237. ) { 238. pline("A chasm opens up under you!"); 239. You("don't fall in!"); 240. } else { 241. You("fall into a chasm!"); 242. u.utrap = rn1(6,2); 243. u.utraptype = TT_PIT; 244. losehp(rnd(6),"fall into a chasm"); 245. selftouch("Falling, you"); 246. } 247. } else 248. newsym(x,y); 249. break; 250. case DOOR : /* Make the door collapse */ 251. if (levl[x][y].doormask == D_NODOOR) break; 252. if (cansee(x,y)) 253. pline("The door collapses."); 254. levl[x][y].doormask = D_NODOOR; 255. if (!levl[x][y].mmask && !(x == u.ux && y == u.uy)) 256. newsym(x,y); 257. break; 258. } 259. } 260. } 261. 262. /* 263. * The player is trying to extract something from his/her instrument. 264. */ 265. 266. static int 267. do_improvisation(instr) 268. struct obj *instr; 269. { 270. int damage; 271. 272. if (Confusion) 273. pline("What you produce is quite far from music..."); 274. else 275. You("start playing the %s.", xname(instr)); 276. switch (instr->otyp) { 277. case FLUTE: /* May charm snakes */ 278. if (rn2(ACURR(A_DEX)) + u.ulevel > 25) 279. charm_snakes((int)u.ulevel*3); 280. break; 281. case MAGIC_FLUTE: /* Make monster fall asleep */ 282. You("produce soft music."); 283. put_monsters_to_sleep((int)u.ulevel*5); 284. break; 285. case HORN: /* Awaken monsters or scare monsters */ 286. You("produce a frightful, grave sound."); 287. awaken_monsters((int)u.ulevel*30); 288. break; 289. case FROST_HORN: /* Idem wand of cold */ 290. case FIRE_HORN: /* Idem wand of fire */ 291. if (instr->spe > 0) { 292. instr->spe--; 293. if (!getdir(1)) { 294. if (!Blind) 295. pline("The %s glows then fades.", xname(instr)); 296. } else { 297. if (!u.dx && !u.dy && !u.dz) { 298. if((damage = zapyourself(instr))) 299. losehp(damage,"self-inflicted injury"); 300. makeknown(instr->otyp); 301. return(2); 302. } 303. buzz((instr->otyp == FROST_HORN) ? 3 : 1, rn1(6,6), u.ux, u.uy, u.dx, u.dy); 304. makeknown(instr->otyp); 305. return(2); 306. } 307. } 308. break; 309. case BUGLE: /* Awaken & attract soldiers */ 310. You("extract a loud noise from the %s.",xname(instr)); 311. awaken_soldiers(); 312. break; 313. case HARP: /* May calm Nymph */ 314. if (rn2(ACURR(A_DEX)) + u.ulevel > 25) 315. calm_nymphs((int)u.ulevel*3); 316. break; 317. case MAGIC_HARP: /* Charm monsters */ 318. if (instr->spe > 0) { 319. pline("The %s produces very attractive music.",xname(instr)); 320. instr->spe--; 321. charm_monsters(((int)u.ulevel - 1) / 3 + 1); 322. } 323. break; 324. case DRUM: /* Awaken monsters */ 325. You("beat a deafening row!"); 326. awaken_monsters((int)u.ulevel * 40); 327. break; 328. case DRUM_OF_EARTHQUAKE: /* create several pits */ 329. if (instr->spe > 0) { 330. You("produce a heavy, thunderous rolling!"); 331. pline("The entire dungeon is shaking around you!"); 332. do_earthquake(((int)u.ulevel - 1) / 3 + 1); 333. instr->spe--; 334. makeknown(DRUM_OF_EARTHQUAKE); 335. } 336. break; 337. default: 338. impossible("What a weird instrument (%d)!",instr->otyp); 339. break; 340. } 341. return (2); /* That takes time */ 342. } 343. 344. /* 345. * So you want music... 346. */ 347. 348. int 349. do_play_instrument(instr) 350. struct obj *instr; 351. { 352. #ifdef STRONGHOLD 353. char buf[BUFSZ], *s, c = 'y'; 354. int x,y; 355. boolean ok; 356. 357. if (instr->otyp != DRUM && instr->otyp != DRUM_OF_EARTHQUAKE) { 358. pline("Improvise? "); 359. c = yn(); 360. } 361. if (c == 'n') { 362. pline("What tune are you playing? [what 5 notes] "); 363. getlin(buf); 364. for(s=buf;*s;s++) 365. *s = (*s >='a' && *s<='z') ? 'A' + *s - 'a' : *s; 366. You("extract a strange sound from the %s!",xname(instr)); 367. /* Check if there was the Stronghold drawbridge near 368. * and if the tune conforms to what we're waiting for. 369. */ 370. if (dlevel == stronghold_level) 371. if (!strcmp(buf,tune)) { 372. /* Search for the drawbridge */ 373. for(y=u.uy-1; y<=u.uy+1; y++) 374. for(x=u.ux-1;x<=u.ux+1;x++) 375. if (find_drawbridge(&x,&y)) { 376. if (levl[x][y].typ == DRAWBRIDGE_DOWN) 377. close_drawbridge(x,y); 378. else 379. open_drawbridge(x,y); 380. return 0; 381. } 382. } else if (flags.soundok) { 383. /* Okay, it wasn't the right tune, but perhaps 384. * we can give the player some hints like in the 385. * Mastermind game */ 386. ok = FALSE; 387. for(y = u.uy-1; y <= u.uy+1 && !ok; y++) 388. for(x = u.ux-1; x <= u.ux+1 && !ok; x++) 389. if(IS_DRAWBRIDGE(levl[x][y].typ) || 390. is_drawbridge_wall(x,y) >= 0) 391. ok = TRUE; 392. if (ok) { /* There is a drawbridge near */ 393. int tumblers, gears; 394. boolean matched[5]; 395. 396. tumblers = gears = 0; 397. for(x=0; x < 5; x++) 398. matched[x] = FALSE; 399. 400. for(x=0; x < strlen(buf); x++) 401. if(x < 5) { 402. if(buf[x] == tune[x]) { 403. gears++; 404. matched[x] = TRUE; 405. } else 406. for(y=0; y < 5; y++) 407. if(!matched[y] && 408. buf[x] == tune[y] && 409. buf[y] != tune[y]) { 410. tumblers++; 411. matched[y] = TRUE; 412. break; 413. } 414. } 415. if(tumblers) 416. if(gears) 417. You("hear %d tumbler%s click and %d gear%s turn.", 418. tumblers, (tumblers > 1 ? "s" : ""), 419. gears, (gears > 1 ? "s" : "")); 420. else 421. You("hear %d tumbler%s click.", 422. tumblers, (tumblers > 1 ? "s" : "")); 423. else if(gears) 424. You("hear %d gear%s turn.", 425. gears, (gears > 1 ? "s" : "")); 426. } 427. } 428. return 1; 429. } else 430. #endif /* STRONGHOLD /**/ 431. return do_improvisation(instr); 432. } 433. 434. #endif /* MUSIC /**/
|