Source:NetHack 3.1.0/explode.c

Below is the full text to explode.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.1	90/11/06 2.   /*	Copyright (C) 1990 by Ken Arromdee */ 3.   /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   /* Note: Arrays are column first, while the screen is row first */ 8.   static int expl[3][3] = 9.   { S_explode1, S_explode4, S_explode7, 10.    S_explode2, S_explode5, S_explode8, 11.    S_explode3, S_explode6, S_explode9 }; 12.   13.   /* Note: I had to choose one of three possible kinds of "type" when writing 14.   * this function: a wand type (like in zap.c), an adtyp, or an object type. 15.   * Wand types get complex because they must be converted to adtyps for 16.   * determining such things as fire resistance. Adtyps get complex in that 17.   * they don't supply enough information--was it a player or a monster that 18.   * did it, and with a wand, spell, or breath weapon? Object types share both 19.   * these disadvantages....  20. */ 21.   void 22.  explode(x, y, type, dam, olet) 23.  int x, y;  24. int type; /* the same as in zap.c */ 25.  int dam; 26.  char olet; 27.  {  28.   	int i, j, k;  29. boolean starting = 1; 30.  	boolean visible, any_shield; 31.  	int uhurt = 0; /* 0=unhurt, 1=items damaged, 2=you and items damaged */ 32.  	const char *str; 33.  	int idamres, idamnonres; 34.  	struct monst *mtmp; 35.  	uchar adtyp; 36.  	int explmask[3][3]; 37.  		/* 0=normal explosion, 1=do shieldeff, 2=do nothing */ 38.  	boolean shopdamage = FALSE; 39.   40.   	switch(abs(type) % 10) { 41.  		default: impossible("explosion base type %d?", type); return; 42.   43.   		case 1: str = (olet == SCROLL_CLASS ? "tower of flame" : "fireball"); adtyp = AD_FIRE; break; 44.  		/* case 3: str = "ball of cold"; adtyp = AD_COLD; break; */ 45.  		/* case 5: str = "ball lightning"; adtyp = AD_ELEC; break; */ 46.  		/* case 7: str = "acid ball"; adtyp = AD_ACID; break; */ 47.  	}  48.    49.   	any_shield = visible = FALSE; 50.  	for(i=0; i<3; i++) for(j=0; j<3; j++) { 51.  		if (!isok(i+x-1, j+y-1)) { 52.  			explmask[i][j] = 2; 53.  			continue; 54.  		}  55.   		if (i+x-1 == u.ux && j+y-1 == u.uy) { 56.  		    switch(adtyp) { 57.  			case AD_FIRE: 58.  				explmask[i][j] = Fire_resistance ? 1 : 0; 59.   				break; 60.  			/* case AD_COLD: */ 61.  			/* case AD_ELEC: */ 62.  			/* case AD_DISN: */ 63.  			/* case AD_ACID: */ 64.  			default: 65.  				impossible("explosion type %d?", adtyp); 66.  				explmask[i][j] = 0; 67.  				break; 68.  		    }  69.   		}  70.   		/* can be both you and mtmp if you're swallowed */ 71.  		if (mtmp = m_at(i+x-1, j+y-1)) { 72.  		    switch(adtyp) { 73.  			case AD_FIRE: 74.  				explmask[i][j] = resists_fire(mtmp->data) 75.  					? 1 : 0;  76.   				break; 77.  			/* case AD_COLD: */ 78.  			/* case AD_ELEC: */ 79.  			/* case AD_DISN: */ 80.  			/* case AD_ACID: */ 81.  			default: 82.  				impossible("explosion type %d?", adtyp); 83.  				explmask[i][j] = 0; 84.  				break; 85.  		    }  86.   		} else if (i+x-1 != u.ux || j+j-1 != u.uy) 87.  		    explmask[i][j] = 0; 88.   89.   		if (cansee(i+x-1, j+y-1)) visible = TRUE; 90.  		if (explmask[i][j] == 1) any_shield = TRUE; 91.  	}  92.    93.   	if (visible) { 94.  		/* Start the explosion */ 95.  		for(i=0; i<3; i++) for(j=0; j<3; j++) { 96.  			if (explmask[i][j] == 2) continue; 97.  			tmp_at(starting ? DISP_BEAM : DISP_CHANGE,  98.   					    cmap_to_glyph(expl[i][j])); 99.  			tmp_at(i+x-1, j+y-1); 100. 			starting = 0; 101. 		}  102.  		curs_on_u;	/* will flush screen and output */ 103.  104.  		if (any_shield) {	/* simulate a shield effect */ 105. 		    for (k = 0; k < SHIELD_COUNT; k++) { 106. 			for(i=0; i<3; i++) for(j=0; j<3; j++) { 107. 			    if (explmask[i][j] == 1) 108. 				/*  109.  				 * Bypass tmp_at and send the shield glyphs 110. 				 * directly to the buffered screen. tmp_at 111. 				 * will clean up the location for us later. 112. 				 */  113.  				show_glyph(i+x-1, j+y-1,  114.  					cmap_to_glyph(shield_static[k])); 115. 			}  116.  			curs_on_u;	/* will flush screen and output */ 117. 			delay_output; 118. 		    }  119.   120.  		    /* Cover last shield glyph with blast symbol. */ 121.  		    for(i=0; i<3; i++) for(j=0; j<3; j++) { 122. 			if (explmask[i][j] == 1) 123. 			    show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j])); 124. 		    }  125.   126.  		} else {		/* delay a little bit. */ 127.  		    delay_output; 128. 		    delay_output; 129. 		}  130.   131.  	} else You("hear a blast."); 132.  133.   134.  	for(i=0; i<3; i++) for(j=0; j<3; j++) { 135. 		if (explmask[i][j] == 2) continue; 136. 		if (i+x-1 == u.ux && j+y-1 == u.uy) 137. 			uhurt = (explmask[i][j] == 1) ? 1 : 2; 138.  		idamres = idamnonres = 0; 139. 		(void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1),  140.  				     type, &shopdamage); 141.  142.  		mtmp = m_at(i+x-1, j+y-1); 143. 		if (!mtmp) continue; 144. 		if (u.uswallow && mtmp == u.ustuck) { 145. 			if (is_animal(u.ustuck->data)) 146. 				pline("%s gets heartburn!",  147.  				      Monnam(u.ustuck)); 148. 			else 149. 				pline("%s gets toasted slightly!",  150.  				      Monnam(u.ustuck)); 151. 		} else 152. 		pline("%s is caught in the %s!",  153.  			cansee(i+x-1, j+y-1) ? Monnam(mtmp) : "It", str); 154.  155.  		idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp); 156. 		idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp); 157. 		/* Fire resistance protects monsters from burning scrolls, */ 158. 		/* but not from exploding potions. */ 159.  		idamnonres += destroy_mitem(mtmp, POTION_CLASS, (int) adtyp); 160. /*  161.  		idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp); 162. 		idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp); 163. */  164.  		if (explmask[i][j] == 1) { 165. 			golemeffects(mtmp, (int) adtyp, dam + idamres); 166. 			mtmp->mhp -= idamnonres; 167. 		} else { 168. 		/* call resist with 0 and do damage manually so 1) we can  169.  		 * get out the message before doing the damage, and 2) we can 170. 		 * call mondied, not killed, if it's not your blast 171. 		 */  172.  			int mdam = dam; 173.  174.  			if (resist(mtmp, olet, 0, FALSE)) { 175. 				pline("%s resists the magical blast!",  176.  					cansee(i+x-1,j+y-1) ? Monnam(mtmp)  177.  					: "It"); 178. 				mdam = dam/2; 179. 			}  180.  			if (mtmp == u.ustuck) 181. 				mdam *= 2; 182. 			if (resists_cold(mtmp->data) /* && adtyp == AD_FIRE */) 183. 				mdam *= 2; 184. 			mtmp->mhp -= mdam; 185. 			mtmp->mhp -= (idamres + idamnonres); 186. 		}  187.  		if (mtmp->mhp <= 0) { 188. 			if (type >= 0) killed(mtmp); 189. 			else mondied(mtmp); 190. 		}  191.  	}  192.   193.  	if (visible) tmp_at(DISP_END, 0); /* clear the explosion */ 194.  195.  	/* Do your injury last */ 196. 	if (uhurt) { 197. 	        if (type >= 0 && flags.verbose && olet != SCROLL_CLASS) 198. 			You("are caught in the %s!", str); 199. 		if (uhurt == 2) u.uhp -= dam; 200. 		if (u.uhp <= 0) { 201. 			char buf[BUFSZ]; 202.  203.  			if (type >= 0 && olet != SCROLL_CLASS) { 204. 			    killer_format = NO_KILLER_PREFIX; 205. 			    Sprintf(buf, "caught %sself in %s own %s.",  206.  				flags.female ? "her" : "him",  207.  				flags.female ? "her" : "his", str); 208. 			} else { 209. 			    killer_format = KILLED_BY; 210. 			    Strcpy(buf, str); 211. 			}  212.  			killer = buf; 213. 			/* done(adtyp == AD_FIRE ? BURNING : DIED); */ 214. 			done(BURNING); 215. 		}  216.  		exercise(A_STR, FALSE); 217. #if defined(POLYSELF) 218. 		ugolemeffects((int) adtyp, dam); 219. #endif 220. 		destroy_item(SCROLL_CLASS, (int) adtyp); 221. 		destroy_item(SPBOOK_CLASS, (int) adtyp); 222. 		destroy_item(POTION_CLASS, (int) adtyp); 223. /*  224.  		destroy_item(RING_CLASS, (int) adtyp); 225. 		destroy_item(WAND_CLASS, (int) adtyp); 226. */  227.  	}  228.  	if (shopdamage) { 229. 		pay_for_damage("burn away"); 230. /* (only if we ever add non-fire balls) 231. 		pay_for_damage(adtyp == AD_FIRE ? "burn away" :  232.  			       adtyp == AD_COLD ? "shatter" :  233.  			       adtyp == AD_DISN ? "disintegrate" : "destroy"); 234. */  235.  	}  236.  }  237.   238.  /*explode.c*/