Source:NetHack 3.4.0/explode.c

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