PropertyValue
rdfs:label
  • Source:NetHack 3.3.0/explode.c
rdfs:comment
  • Below is the full text to explode.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/explode.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code
dcterms:subject
dbkwik:nethack/property/wikiPageUsesTemplate
abstract
  • Below is the full text to explode.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/explode.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)explode.c 3.3 97/06/14 */ 2. /* Copyright (C) 1990 by Ken Arromdee */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. #ifdef OVL0 8. 9. /* Note: Arrays are column first, while the screen is row first */ 10. static int expl[3][3] = { 11. { S_explode1, S_explode4, S_explode7 }, 12. { S_explode2, S_explode5, S_explode8 }, 13. { S_explode3, S_explode6, S_explode9 } 14. }; 15. 16. /* Note: I had to choose one of three possible kinds of "type" when writing 17. * this function: a wand type (like in zap.c), an adtyp, or an object type. 18. * Wand types get complex because they must be converted to adtyps for 19. * determining such things as fire resistance. Adtyps get complex in that 20. * they don't supply enough information--was it a player or a monster that 21. * did it, and with a wand, spell, or breath weapon? Object types share both 22. * these disadvantages.... 23. */ 24. void 25. explode(x, y, type, dam, olet) 26. int x, y; 27. int type; /* the same as in zap.c */ 28. int dam; 29. char olet; 30. { 31. int i, j, k, damu = dam; 32. boolean starting = 1; 33. boolean visible, any_shield; 34. int uhurt = 0; /* 0=unhurt, 1=items damaged, 2=you and items damaged */ 35. const char *str; 36. int idamres, idamnonres; 37. struct monst *mtmp; 38. uchar adtyp; 39. int explmask[3][3]; 40. /* 0=normal explosion, 1=do shieldeff, 2=do nothing */ 41. boolean shopdamage = FALSE; 42. 43. if (olet == WAND_CLASS) /* retributive strike */ 44. switch (Role_switch) { 45. case PM_PRIEST: 46. case PM_MONK: 47. case PM_WIZARD: damu /= 5; 48. break; 49. case PM_HEALER: 50. case PM_KNIGHT: damu /= 2; 51. break; 52. default: break; 53. } 54. 55. if (olet == MON_EXPLODE) { 56. str = killer; 57. adtyp = AD_PHYS; 58. } else 59. switch (abs(type) % 10) { 60. case 0: str = "magical blast"; 61. adtyp = AD_MAGM; 62. break; 63. case 1: str = olet == BURNING_OIL ? "burning oil" : 64. olet == SCROLL_CLASS ? "tower of flame" : 65. "fireball"; 66. adtyp = AD_FIRE; 67. break; 68. case 2: str = "ball of cold"; 69. adtyp = AD_COLD; 70. break; 71. case 4: str = (olet == WAND_CLASS) ? "death field" : 72. "disintegration field"; 73. adtyp = AD_DISN; 74. break; 75. case 5: str = "ball lightning"; 76. adtyp = AD_ELEC; 77. break; 78. case 6: str = "poison gas cloud"; 79. adtyp = AD_DRST; 80. break; 81. case 7: str = "splash of acid"; 82. adtyp = AD_ACID; 83. break; 84. default: impossible("explosion base type %d?", type); return; 85. } 86. 87. any_shield = visible = FALSE; 88. for (i=0; i<3; i++) for (j=0; j<3; j++) { 89. if (!isok(i+x-1, j+y-1)) { 90. explmask[i][j] = 2; 91. continue; 92. } else 93. explmask[i][j] = 0; 94. 95. if (i+x-1 == u.ux && j+y-1 == u.uy) { 96. switch(adtyp) { 97. case AD_PHYS: 98. explmask[i][j] = 0; 99. break; 100. case AD_MAGM: 101. explmask[i][j] = !!Antimagic; 102. break; 103. case AD_FIRE: 104. explmask[i][j] = !!Fire_resistance; 105. break; 106. case AD_COLD: 107. explmask[i][j] = !!Cold_resistance; 108. break; 109. case AD_DISN: 110. explmask[i][j] = (olet == WAND_CLASS) ? 111. !!(nonliving(youmonst.data) || is_demon(youmonst.data)) : 112. !!Disint_resistance; 113. break; 114. case AD_ELEC: 115. explmask[i][j] = !!Shock_resistance; 116. break; 117. case AD_DRST: 118. explmask[i][j] = !!Poison_resistance; 119. break; 120. case AD_ACID: 121. explmask[i][j] = !!Acid_resistance; 122. break; 123. default: 124. impossible("explosion type %d?", adtyp); 125. break; 126. } 127. } 128. /* can be both you and mtmp if you're swallowed */ 129. mtmp = m_at(i+x-1, j+y-1); 130. #ifdef STEED 131. if (!mtmp && i+x-1 == u.ux && j+y-1 == u.uy) 132. mtmp = u.usteed; 133. #endif 134. if (mtmp) { 135. if (mtmp->mhp < 1) explmask[i][j] = 2; 136. else switch(adtyp) { 137. case AD_PHYS: 138. break; 139. case AD_MAGM: 140. explmask[i][j] |= resists_magm(mtmp); 141. break; 142. case AD_FIRE: 143. explmask[i][j] |= resists_fire(mtmp); 144. break; 145. case AD_COLD: 146. explmask[i][j] |= resists_cold(mtmp); 147. break; 148. case AD_DISN: 149. explmask[i][j] |= (olet == WAND_CLASS) ? 150. (nonliving(mtmp->data) || is_demon(mtmp->data)) : 151. resists_disint(mtmp); 152. break; 153. case AD_ELEC: 154. explmask[i][j] |= resists_elec(mtmp); 155. break; 156. case AD_DRST: 157. explmask[i][j] |= resists_poison(mtmp); 158. break; 159. case AD_ACID: 160. explmask[i][j] |= resists_acid(mtmp); 161. break; 162. default: 163. impossible("explosion type %d?", adtyp); 164. break; 165. } 166. } 167. if (mtmp && cansee(i,j) && !canspotmon(mtmp)) 168. map_invisible(i, j); 169. else if (!mtmp && glyph_is_invisible(levl[i][j].glyph)) { 170. unmap_object(i, j); 171. newsym(i, j); 172. } 173. 174. if (cansee(i+x-1, j+y-1)) visible = TRUE; 175. if (explmask[i][j] == 1) any_shield = TRUE; 176. } 177. 178. if (visible) { 179. /* Start the explosion */ 180. for (i=0; i<3; i++) for (j=0; j<3; j++) { 181. if (explmask[i][j] == 2) continue; 182. tmp_at(starting ? DISP_BEAM : DISP_CHANGE, 183. cmap_to_glyph(expl[i][j])); 184. tmp_at(i+x-1, j+y-1); 185. starting = 0; 186. } 187. curs_on_u(); /* will flush screen and output */ 188. 189. if (any_shield) { /* simulate a shield effect */ 190. for (k = 0; k < SHIELD_COUNT; k++) { 191. for (i=0; i<3; i++) for (j=0; j<3; j++) { 192. if (explmask[i][j] == 1) 193. /* 194. * Bypass tmp_at() and send the shield glyphs 195. * directly to the buffered screen. tmp_at() 196. * will clean up the location for us later. 197. */ 198. show_glyph(i+x-1, j+y-1, 199. cmap_to_glyph(shield_static[k])); 200. } 201. curs_on_u(); /* will flush screen and output */ 202. delay_output(); 203. } 204. 205. /* Cover last shield glyph with blast symbol. */ 206. for (i=0; i<3; i++) for (j=0; j<3; j++) { 207. if (explmask[i][j] == 1) 208. show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j])); 209. } 210. 211. } else { /* delay a little bit. */ 212. delay_output(); 213. delay_output(); 214. } 215. 216. } else { 217. if (flags.soundok) You_hear("a blast."); 218. } 219. 220. if (dam) 221. for (i=0; i<3; i++) for (j=0; j<3; j++) { 222. if (explmask[i][j] == 2) continue; 223. if (i+x-1 == u.ux && j+y-1 == u.uy) 224. uhurt = (explmask[i][j] == 1) ? 1 : 2; 225. idamres = idamnonres = 0; 226. if (type >= 0) 227. (void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1), 228. type, &shopdamage); 229. 230. mtmp = m_at(i+x-1, j+y-1); 231. #ifdef STEED 232. if (!mtmp && i+x-1 == u.ux && j+y-1 == u.uy) 233. mtmp = u.usteed; 234. #endif 235. if (!mtmp) continue; 236. if (u.uswallow && mtmp == u.ustuck) { 237. if (is_animal(u.ustuck->data)) 238. pline("%s gets %s!", 239. Monnam(u.ustuck), 240. (adtyp == AD_FIRE) ? "heartburn" : 241. (adtyp == AD_COLD) ? "chilly" : 242. (adtyp == AD_DISN) ? ((olet == WAND_CLASS) ? 243. "irradiated by pure energy" : "perforated") : 244. (adtyp == AD_ELEC) ? "shocked" : 245. (adtyp == AD_DRST) ? "poisoned" : 246. (adtyp == AD_ACID) ? "an upset stomach" : 247. "fried"); 248. else 249. pline("%s gets slightly %s!", 250. Monnam(u.ustuck), 251. (adtyp == AD_FIRE) ? "toasted" : 252. (adtyp == AD_COLD) ? "chilly" : 253. (adtyp == AD_DISN) ? ((olet == WAND_CLASS) ? 254. "overwhelmed by pure energy" : "perforated") : 255. (adtyp == AD_ELEC) ? "shocked" : 256. (adtyp == AD_DRST) ? "intoxicated" : 257. (adtyp == AD_ACID) ? "burned" : 258. "fried"); 259. } else 260. pline("%s is caught in the %s!", 261. cansee(i+x-1, j+y-1) ? Monnam(mtmp) : "It", str); 262. 263. idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp); 264. idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp); 265. idamnonres += destroy_mitem(mtmp, POTION_CLASS, (int) adtyp); 266. idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp); 267. idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp); 268. 269. if (explmask[i][j] == 1) { 270. golemeffects(mtmp, (int) adtyp, dam + idamres); 271. mtmp->mhp -= idamnonres; 272. } else { 273. /* call resist with 0 and do damage manually so 1) we can 274. * get out the message before doing the damage, and 2) we can 275. * call mondied, not killed, if it's not your blast 276. */ 277. int mdam = dam; 278. 279. if (resist(mtmp, olet, 0, FALSE)) { 280. pline("%s resists the %s!", 281. cansee(i+x-1,j+y-1) ? Monnam(mtmp) : "It", 282. str); 283. mdam = dam/2; 284. } 285. if (mtmp == u.ustuck) 286. mdam *= 2; 287. if (resists_cold(mtmp) && adtyp == AD_FIRE) 288. mdam *= 2; 289. else if (resists_fire(mtmp) && adtyp == AD_COLD) 290. mdam *= 2; 291. mtmp->mhp -= mdam; 292. mtmp->mhp -= (idamres + idamnonres); 293. } 294. if (mtmp->mhp <= 0) { 295. /* KMH -- Don't blame the player for pets killing gas spores */ 296. if (!flags.mon_moving) killed(mtmp); 297. else monkilled(mtmp, "", (int)adtyp); 298. } 299. } 300. 301. if (visible) tmp_at(DISP_END, 0); /* clear the explosion */ 302. 303. /* Do your injury last */ 304. if (uhurt) { 305. if ((type >= 0 || adtyp == AD_PHYS) && /* gas spores */ 306. flags.verbose && olet != SCROLL_CLASS) 307. You("are caught in the %s!", str); 308. /* do property damage first, in case we end up leaving bones */ 309. if (adtyp == AD_FIRE) burn_away_slime(); 310. if (Invulnerable) { 311. damu = 0; 312. pline("You are unharmed!"); 313. } 314. if (adtyp == AD_FIRE) (void) burnarmor(&youmonst); 315. destroy_item(SCROLL_CLASS, (int) adtyp); 316. destroy_item(SPBOOK_CLASS, (int) adtyp); 317. destroy_item(POTION_CLASS, (int) adtyp); 318. destroy_item(RING_CLASS, (int) adtyp); 319. destroy_item(WAND_CLASS, (int) adtyp); 320. 321. ugolemeffects((int) adtyp, damu); 322. if (uhurt == 2) u.uhp -= damu, flags.botl = 1; 323. 324. if (u.uhp <= 0) { 325. char buf[BUFSZ]; 326. 327. if (olet == MON_EXPLODE) { 328. /* killer handled by caller */ 329. Strcpy(buf, str); 330. killer_format = KILLED_BY_AN; 331. } else if (type >= 0 && olet != SCROLL_CLASS) { 332. killer_format = NO_KILLER_PREFIX; 333. Sprintf(buf, "caught %sself in %s own %s.", 334. him[flags.female], his[flags.female], str); 335. } else { 336. killer_format = KILLED_BY; 337. Strcpy(buf, str); 338. } 339. killer = buf; 340. /* Known BUG: BURNING suppresses corpse in bones data, 341. but done does not handle killer reason correctly */ 342. /* done(adtyp == AD_FIRE ? BURNING : DIED); */ 343. done(BURNING); 344. } 345. exercise(A_STR, FALSE); 346. } 347. 348. if (shopdamage) { 349. pay_for_damage(adtyp == AD_FIRE ? "burn away" : 350. adtyp == AD_COLD ? "shatter" : 351. adtyp == AD_DISN ? "disintegrate" : "destroy"); 352. } 353. } 354. #endif /* OVL0 */ 355. #ifdef OVL1 356. 357. struct scatter_chain { 358. struct scatter_chain *next; /* pointer to next scatter item */ 359. struct obj *obj; /* pointer to the object */ 360. xchar ox; /* location of */ 361. xchar oy; /* item */ 362. schar dx; /* direction of */ 363. schar dy; /* travel */ 364. int range; /* range of object */ 365. boolean stopped; /* flag for in-motion/stopped */ 366. }; 367. 368. /* 369. * scflags: 370. * VIS_EFFECTS Add visual effects to display 371. * MAY_HITMON Objects may hit monsters 372. * MAY_HITYOU Objects may hit hero 373. * MAY_HIT Objects may hit you or monsters 374. * MAY_DESTROY Objects may be destroyed at random 375. * MAY_FRACTURE Stone objects can be fractured (statues, boulders) 376. */ 377. 378. void 379. scatter(sx,sy,blastforce,scflags, obj) 380. int sx,sy; /* location of objects to scatter */ 381. int blastforce; /* force behind the scattering */ 382. unsigned int scflags; 383. struct obj *obj; /* only scatter this obj */ 384. { 385. register struct obj *otmp; 386. register int tmp; 387. int farthest = 0; 388. uchar typ; 389. long qtmp; 390. boolean used_up; 391. boolean split_up = FALSE; 392. boolean individual_object = obj ? TRUE : FALSE; 393. struct monst *mtmp; 394. struct scatter_chain *stmp, *stmp2 = 0; 395. struct scatter_chain *schain = (struct scatter_chain *)0; 396. 397. while ((otmp = individual_object ? obj : level.objects[sx][sy]) != 0) { 398. if (otmp->quan > 1L) { 399. qtmp = otmp->quan - 1; 400. if (qtmp > LARGEST_INT) qtmp = LARGEST_INT; 401. qtmp = (long)rnd((int)qtmp); 402. (void) splitobj(otmp, qtmp); 403. if (qtmp < otmp->quan) 404. split_up = TRUE; 405. else 406. split_up = FALSE; 407. } 408. if (individual_object) { 409. if (split_up) { 410. if (otmp->where == OBJ_FLOOR) 411. obj = otmp->nexthere; 412. else 413. obj = otmp->nobj; 414. } else 415. obj = (struct obj *)0; 416. } 417. obj_extract_self(otmp); 418. used_up = FALSE; 419. 420. /* 9 in 10 chance of fracturing boulders or statues */ 421. if ((scflags & MAY_FRACTURE) 422. && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE)) 423. && rn2(10)) { 424. if (otmp->otyp == BOULDER) { 425. pline("%s breaks apart.",The(xname(otmp))); 426. fracture_rock(otmp); 427. place_object(otmp, sx, sy); /* put fragments on floor */ 428. } else { 429. struct trap *trap; 430. 431. if ((trap = t_at(sx,sy)) && trap->ttyp == STATUE_TRAP) 432. deltrap(trap); 433. pline("%s crumbles.",The(xname(otmp))); 434. (void) break_statue(otmp); 435. place_object(otmp, sx, sy); /* put fragments on floor */ 436. } 437. used_up = TRUE; 438. 439. /* 1 in 10 chance of destruction of obj; glass, egg destruction */ 440. } else if ((scflags & MAY_DESTROY) && (!rn2(10) 441. || (objects[otmp->otyp].oc_material == GLASS 442. || otmp->otyp == EGG))) { 443. if (breaks(otmp, (xchar)sx, (xchar)sy)) used_up = TRUE; 444. } 445. 446. if (!used_up) { 447. stmp = (struct scatter_chain *) 448. alloc(sizeof(struct scatter_chain)); 449. stmp->next = (struct scatter_chain *)0; 450. stmp->obj = otmp; 451. stmp->ox = sx; 452. stmp->oy = sy; 453. tmp = rn2(8); /* get the direction */ 454. stmp->dx = xdir[tmp]; 455. stmp->dy = ydir[tmp]; 456. tmp = blastforce - (otmp->owt/40); 457. if (tmp < 1) tmp = 1; 458. stmp->range = rnd(tmp); /* anywhere up to that determ. by wt */ 459. if (farthest < stmp->range) farthest = stmp->range; 460. stmp->stopped = FALSE; 461. if (!schain) 462. schain = stmp; 463. else 464. stmp2->next = stmp; 465. stmp2 = stmp; 466. } 467. } 468. 469. while (farthest-- > 0) { 470. for (stmp = schain; stmp; stmp = stmp->next) { 471. if ((stmp->range-- > 0) && (!stmp->stopped)) { 472. bhitpos.x = stmp->ox + stmp->dx; 473. bhitpos.y = stmp->oy + stmp->dy; 474. typ = levl[bhitpos.x][bhitpos.y].typ; 475. if(!isok(bhitpos.x, bhitpos.y)) { 476. bhitpos.x -= stmp->dx; 477. bhitpos.y -= stmp->dy; 478. stmp->stopped = TRUE; 479. } else if(!ZAP_POS(typ) || 480. closed_door(bhitpos.x, bhitpos.y)) { 481. bhitpos.x -= stmp->dx; 482. bhitpos.y -= stmp->dy; 483. stmp->stopped = TRUE; 484. } else if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 485. if (scflags & MAY_HITMON) { 486. stmp->range--; 487. if (ohitmon(mtmp, stmp->obj, 1, FALSE)) { 488. stmp->obj = (struct obj *)0; 489. stmp->stopped = TRUE; 490. } 491. } 492. } else if (bhitpos.x==u.ux && bhitpos.y==u.uy) { 493. if (scflags & MAY_HITYOU) { 494. int hitvalu, hitu; 495. 496. if (multi) nomul(0); 497. hitvalu = 8 + stmp->obj->spe; 498. if (bigmonst(youmonst.data)) hitvalu++; 499. /* could just use doname all the time, 500. * except thitu adds "an" to the front 501. */ 502. hitu = thitu(hitvalu, 503. dmgval(stmp->obj, &youmonst), 504. stmp->obj, 505. (stmp->obj->quan>1) ? doname(stmp->obj) 506. : xname(stmp->obj)); 507. if (hitu) { 508. stmp->range -= 3; 509. stop_occupation(); 510. } 511. } 512. } else { 513. if (scflags & VIS_EFFECTS) { 514. /* tmp_at(bhitpos.x, bhitpos.y); */ 515. /* delay_output(); */ 516. } 517. } 518. stmp->ox = bhitpos.x; 519. stmp->oy = bhitpos.y; 520. } 521. } 522. } 523. for (stmp = schain; stmp; stmp = stmp2) { 524. int x,y; 525. 526. stmp2 = stmp->next; 527. x = stmp->ox; y = stmp->oy; 528. if (stmp->obj) { 529. place_object(stmp->obj, x, y); 530. stackobj(stmp->obj); 531. } 532. free((genericptr_t)stmp); 533. newsym(x,y); 534. } 535. } 536. 537. 538. /* 539. * Splatter burning oil from x,y to the surrounding area. 540. * 541. * This routine should really take a how and direction parameters. 542. * The how is how it was caused, e.g. kicked verses thrown. The 543. * direction is which way to spread the flaming oil. Different 544. * "how"s would give different dispersal patterns. For example, 545. * kicking a burning flask will splatter differently from a thrown 546. * flask hitting the ground. 547. * 548. * For now, just perform a "regular" explosion. 549. */ 550. void 551. splatter_burning_oil(x, y) 552. int x, y; 553. { 554. /* ZT_SPELL(ZT_FIRE) = ZT_SPELL(AD_FIRE-1) = 10+(2-1) = 11 */ 555. #define ZT_SPELL_O_FIRE 11 /* value kludge, see zap.c */ 556. explode(x, y, ZT_SPELL_O_FIRE, d(4,4), BURNING_OIL); 557. } 558. 559. #endif /* OVL1 */ 560. 561. /*explode.c*/