1 /* $Id$ */
2 /* File: spells1.c */
3 
4 /* Purpose: Spell code (part 1) */
5 
6 /*
7  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
8  *
9  * This software may be copied and distributed for educational, research, and
10  * not for profit purposes provided that this copyright and statement are
11  * included in all such copies.
12  */
13 
14 #define SERVER
15 
16 #include "angband.h"
17 
18 
19 /* 1/x chance of reducing stats (for elemental attacks) */
20 #define HURT_CHANCE 16
21 
22 /* chance of equipments getting hurt from attacks, in percent [2] */
23 #define HARM_EQUIP_CHANCE	0
24 
25 /* macro to determine the way stat gets reduced by element attacks */
26 #define	DAM_STAT_TYPE(inv) \
27 	(magik(inv*25) ? STAT_DEC_NORMAL : STAT_DEC_TEMPORARY)
28 
29 /*
30  * Maximum lower limit for player teleportation.	[30]
31  * This should make teleportation of high-lv players look 'more random'.
32  * To disable, comment it out.
33  */
34 #define TELEPORT_MIN_LIMIT	30
35 
36 /* Default radius of Space-Time anchor.	[12] */
37 #define ST_ANCHOR_DIS	12
38 
39 /* Limitation for teleport radius on the wilderness.	[20] */
40 #define WILDERNESS_TELEPORT_RADIUS	40
41 
42 /* Macro to test in project_p() whether we are hurt by a PvP
43    (player vs player) or a normal PvM (player vs monster) attack */
44 #define IS_PVP	(who < 0 && who >= -NumPlayers)
45 /* Similar purpose macro (also for take_hit)
46    (Note: While i > 0 can also mean special PROJECTOR_... causes,
47    i < 0 is exclusively reserved for monsters.) */
48 #define IS_PLAYER(i)	(i > 0 && i <= NumPlayers)
49 #define IS_MONSTER(i)	(i < 0)
50 
51 /* Take damage before applying polymorph effect?
52    Traditionally, polymorph would cancel damage instead. - C. Blue */
53 #define DAMAGE_BEFORE_POLY
54 
55 /* Don't allow (ball spell) explosions to extend the effective
56    reach of the caster over MAX_RANGE? */
57 #define NO_EXPLOSION_OUT_OF_MAX_RANGE
58 
59 /* Typical resistance check for all GF_OLD_ and GF_TURN_ attacks */
60 #define RES_OLD(lev, dam) ((lev) > randint(((dam) - 5) < 1 ? 1 : ((dam) - 5)) + 5)
61 
62 /* Sleep power of any GF_OLD_SLEEP spell [500] */
63 #define GF_OLD_SLEEP_DUR 300
64 
65 
66  /*
67   * Potions "smash open" and cause an area effect when
68   * (1) they are shattered while in the player's inventory,
69   * due to cold (etc) attacks;
70   * (2) they are thrown at a monster, or obstacle;
71   * (3) they are shattered by a "cold ball" or other such spell
72   * while lying on the floor.
73   *
74   * Arguments:
75   *	who   ---  who caused the potion to shatter (0=player)
76   *		  potions that smash on the floor are assumed to
77   *		  be caused by no-one (who = 1), as are those that
78   *		  shatter inside the player inventory.
79   *		  (Not anymore -- I changed this; TY)
80   *	y, x  --- coordinates of the potion (or player if
81   *		  the potion was in her inventory);
82   *	o_ptr --- pointer to the potion object.
83   */
84 /*
85  * Copy & Pasted from ToME :)	- Jir -
86  * NOTE:
87  * seemingly TV_POTION2 are not haldled right (ToME native bug?).
88  */
potion_smash_effect(int who,worldpos * wpos,int y,int x,int o_sval)89 bool potion_smash_effect(int who, worldpos *wpos, int y, int x, int o_sval) {
90 	int	 radius = 2;
91 	int	 dt = 0;
92 	int	 dam = 0;
93 	bool	ident = FALSE;
94 	bool	angry = FALSE;
95 	int	flg = (PROJECT_NORF | PROJECT_JUMP | PROJECT_ITEM | PROJECT_KILL | PROJECT_SELF | PROJECT_NODO);
96 
97 	switch (o_sval) {
98 		case SV_POTION_SLIME_MOLD:
99 		case SV_POTION_WATER:   /* perhaps a 'water' attack? */
100 		case SV_POTION_APPLE_JUICE:
101 			return TRUE;
102 
103 		case SV_POTION_INFRAVISION:
104 		case SV_POTION_DETECT_INVIS:
105 		case SV_POTION_SLOW_POISON:
106 		case SV_POTION_CURE_POISON:
107 		case SV_POTION_RESIST_HEAT:
108 		case SV_POTION_RESIST_COLD:
109 		case SV_POTION_RESTORE_EXP:
110 		case SV_POTION_ENLIGHTENMENT:
111 		case SV_POTION_STAR_ENLIGHTENMENT:
112 		case SV_POTION_SELF_KNOWLEDGE:
113 		case SV_POTION_RESISTANCE:
114 		case SV_POTION_INVULNERABILITY:
115 //		case SV_POTION_NEW_LIFE:
116 			/* All of the above potions have no effect when shattered */
117 			return FALSE;
118 
119 		case SV_POTION_EXPERIENCE:
120 			dt = GF_EXP;
121 			dam = 1; /* level */
122 			ident = TRUE;
123 			break;
124 		case SV_POTION_BOLDNESS:
125 			radius = 3;
126 			dt = GF_REMFEAR;
127 //			ident = TRUE;
128 			dam = 1; /* dummy */
129 			break;
130 		case SV_POTION_SALT_WATER:
131 			dt = GF_OLD_CONF;
132 			dam = damroll(10, 5);
133 			ident = TRUE;
134 			angry = TRUE;
135 
136 			/* terraform hack: melt ice^^ (Ding's suggestion) */
137 			{
138 				cave_type **zcave;
139 				if (!(zcave = getcave(wpos))) return TRUE; //paranoia
140 				if (zcave[y][x].feat == FEAT_ICE_WALL) { //100% chance for now, beats fire magic o_O
141 					if (who < 0 && who > PROJECTOR_UNUSUAL) msg_print(-who, "The ice wall melts.");
142 					cave_set_feat_live(wpos, y, x, FEAT_SHAL_WATER);
143 				}
144 			}
145 
146 			break;
147 		case SV_POTION_LOSE_MEMORIES:
148 			dt = GF_OLD_CONF;
149 			dam = damroll(10, 11);
150 			ident = TRUE;
151 			angry = TRUE;
152 			break;
153 		case SV_POTION_DEC_STR:
154 			radius = 1;
155 			dt = GF_DEC_STR;
156 			dam = 1; /* dummy */
157 			ident = TRUE;
158 			angry = TRUE;
159 			break;
160 		case SV_POTION_DEC_INT:
161 			angry = TRUE;
162 			break;
163 		case SV_POTION_DEC_WIS:
164 			angry = TRUE;
165 			break;
166 		case SV_POTION_DEC_DEX:
167 			radius = 1;
168 			dt = GF_DEC_DEX;
169 			dam = 1; /* dummy */
170 			ident = TRUE;
171 			angry = TRUE;
172 			break;
173 		case SV_POTION_DEC_CON:
174 			radius = 1;
175 			dt = GF_DEC_CON;
176 			dam = 1; /* dummy */
177 			ident = TRUE;
178 			angry = TRUE;
179 			break;
180 		case SV_POTION_DEC_CHR:
181 			angry = TRUE;
182 			break;
183 		case SV_POTION_RES_STR:
184 			radius = 1;
185 			dt = GF_RES_STR;
186 			dam = 1; /* dummy */
187 			break;
188 		case SV_POTION_RES_INT:
189 			break;
190 		case SV_POTION_RES_WIS:
191 			break;
192 		case SV_POTION_RES_DEX:
193 			radius = 1;
194 			dt = GF_RES_DEX;
195 			dam = 1; /* dummy */
196 			break;
197 		case SV_POTION_RES_CON:
198 			radius = 1;
199 			dt = GF_RES_CON;
200 			dam = 1; /* dummy */
201 			break;
202 		case SV_POTION_RES_CHR:
203 			break;
204 		case SV_POTION_INC_STR:
205 			radius = 1;
206 			dt = GF_INC_STR;
207 			dam = 1; /* dummy */
208 			ident = TRUE;
209 			break;
210 		case SV_POTION_INC_INT:
211 			break;
212 		case SV_POTION_INC_WIS:
213 			break;
214 		case SV_POTION_INC_DEX:
215 			radius = 1;
216 			dt = GF_INC_DEX;
217 			dam = 1; /* dummy */
218 			ident = TRUE;
219 			break;
220 		case SV_POTION_INC_CON:
221 			radius = 1;
222 			dt = GF_INC_CON;
223 			dam = 1; /* dummy */
224 			ident = TRUE;
225 			break;
226 		case SV_POTION_INC_CHR:
227 			break;
228 		case SV_POTION_AUGMENTATION:
229 			radius = 1;
230 			dt = GF_AUGMENTATION;
231 			dam = 1; /* dummy */
232 			ident = TRUE;
233 			break;
234 		case SV_POTION_HEROISM:
235 		case SV_POTION_BERSERK_STRENGTH:
236 			radius = 1;
237 			dt = GF_HERO_MONSTER;
238 			dam = damroll(2, 10);
239 			ident = TRUE;
240 			break;
241 		case SV_POTION_SLOWNESS:
242 			radius = 1;
243 			dt = GF_OLD_SLOW;
244 			dam = damroll(10, 5);
245 			ident = TRUE;
246 			angry = TRUE;
247 			break;
248 		case SV_POTION_POISON:
249 			dt = GF_POIS;
250 			dam = 7;
251 			ident = TRUE;
252 			angry = TRUE;
253 			break;
254 		case SV_POTION_BLINDNESS:
255 			radius = 1;
256 			dam = damroll(3, 5);
257 			dt = GF_BLIND;
258 			ident = TRUE;
259 			angry = TRUE;
260 			break;
261 		case SV_POTION_CONFUSION: /* Booze */
262 			radius = 1;
263 			dam = damroll(10, 8);
264 			dt = GF_OLD_CONF;
265 			ident = TRUE;
266 			angry = TRUE;
267 			break;
268 		case SV_POTION_SLEEP:
269 			dt = GF_OLD_SLEEP;
270 			dam = damroll(10, 8);
271 			angry = TRUE;
272 			ident = TRUE;
273 			break;
274 		case SV_POTION_RUINATION:
275 			radius = 1;
276 			dt = GF_RUINATION;
277 			ident = TRUE;
278 			angry = TRUE;
279 			dam = 1; /* dummy */
280 			break;
281 		case SV_POTION_DETONATIONS:
282 			radius = 3;
283 //			dt = GF_DISINTEGRATE; /* GF_ROCKET;/* was GF_SHARD */
284 			dt = GF_DETONATION; /* GF_DETONATION like GF_ROCKET does partially DISI ;) - C. Blue */
285 			dam = damroll(45, 25);
286 			aggravate_monsters_floorpos(wpos, y, x);
287 			angry = TRUE;
288 			ident = TRUE;
289 			flg |= PROJECT_LODF; /* obsolete because of PROJECT_JUMP, but just in case */
290 #ifdef USE_SOUND_2010
291 			if (who < 0 && who > PROJECTOR_UNUSUAL) sound(-who, "detonation", NULL, SFX_TYPE_MISC, FALSE);
292 #endif
293 			break;
294 		case SV_POTION_DEATH:
295 //			dt = GF_DEATH_RAY;	/* !! */	/* not implemented yet. */
296 			dt = GF_NETHER_WEAK; /* special damage type solemnly for potion smash effect */
297 			dam = damroll(30,30);
298 			angry = TRUE;
299 			radius = 2;
300 			ident = TRUE;
301 			break;
302 		case SV_POTION_SPEED:
303 			dt = GF_OLD_SPEED;
304 			dam = damroll(5, 3);
305 			ident = TRUE;
306 			break;
307 		case SV_POTION_CURE_LIGHT:
308 			dt = GF_OLD_HEAL;
309 			dam = damroll(2,3);
310 			ident = TRUE;
311 			break;
312 		case SV_POTION_CURE_SERIOUS:
313 			dt = GF_OLD_HEAL;
314 			dam = damroll(4,3);
315 			ident = TRUE;
316 			break;
317 		case SV_POTION_CURE_CRITICAL:
318 			dt = GF_OLD_HEAL;
319 			dam = damroll(6,3);
320 			ident = TRUE;
321 			break;
322 		case SV_POTION_CURING:
323 			dt = GF_CURING; //GF_OLD_HEAL;
324 			dam = 0x4 + 0x8 + 0x10 + 0x20; //damroll(5,10);
325 			ident = TRUE;
326 			break;
327 		case SV_POTION_HEALING:
328 			dt = GF_OLD_HEAL;
329 			dam = damroll(10,10);
330 			ident = TRUE;
331 			break;
332 		case SV_POTION_STAR_HEALING:
333 			dt = GF_OLD_HEAL;
334 			dam = damroll(30,20);
335 			radius = 1;
336 			ident = TRUE;
337 			break;
338 		case SV_POTION_LIFE:
339 			dt = GF_LIFEHEAL;
340 			dam = damroll(30,20);
341 			radius = 1;
342 			ident = TRUE;
343 			break;
344 #if 0 /* silly. people DRINK these */
345 		case SV_POTION_RESTORE_MANA:   /* MANA */
346 			dt = GF_MANA;
347 			dam = damroll(8,10);
348 			radius = 1;
349 			ident = TRUE;
350 			break;
351 		case SV_POTION_STAR_RESTORE_MANA:   /* MANA */
352 			dt = GF_MANA;
353 			dam = damroll(12,10);
354 			radius = 1;
355 			ident = TRUE;
356 			break;
357 #endif
358 		default:
359 			/* Do nothing */  ;
360 			return FALSE;
361 	}
362 
363 	/* doh! project halves the dam ?! */
364 	if (dt != GF_CURING) dam *= 2;
365 
366 	(void) project(who, radius, wpos, y, x, dam, dt,
367 	    flg, "");
368 
369 	if (ident && who < 0 && who > PROJECTOR_UNUSUAL) {
370 		player_type *p_ptr = Players[-who];
371 		object_type forge;
372 		int lev;
373 
374 		invcopy(&forge, lookup_kind(TV_POTION, o_sval));
375 		lev = k_info[forge.k_idx].level;
376 
377 		/* Combine / Reorder the pack (later) */
378 		p_ptr->notice |= (PN_COMBINE | PN_REORDER);
379 
380 		/* The player is now aware of the object */
381 		if (!object_aware_p(-who, &forge)) {
382 			object_aware(-who, &forge);
383 			if (!(p_ptr->mode & MODE_PVP)) gain_exp(-who, (lev + (p_ptr->lev >> 1)) / p_ptr->lev);
384 		}
385 
386 		/* Window stuff */
387 		p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
388 	}
389 
390 	/* XXX	those potions that explode need to become "known" */
391 	return angry;
392 }
393 
394 
395 /*
396  * Helper function -- return a "nearby" race for polymorphing
397  *
398  * Note that this function is one of the more "dangerous" ones...
399  */
poly_r_idx(int r_idx)400 s16b poly_r_idx(int r_idx) {
401 	monster_race *r_ptr = &r_info[r_idx];
402 	int i, r, lev1, lev2;
403 
404 	/* Hack -- Uniques never polymorph */
405 	if (r_ptr->flags1 & RF1_UNIQUE) return (r_idx);
406 
407 	get_mon_num_hook = dungeon_aux;
408 	get_mon_num_prep(0, reject_uniques);
409 
410 	/* Allowable range of "levels" for resulting monster */
411 	lev1 = r_ptr->level - ((randint(20)/randint(9))+1);
412 	lev2 = r_ptr->level + ((randint(20)/randint(9))+1);
413 
414 	/* Pick a (possibly new) non-unique race */
415 	for (i = 0; i < 1000; i++) {
416 		/* Pick a new race, using a level calculation */
417 		/* Don't base this on "dlev" */
418 		/*r = get_mon_num((dlev + r_ptr->level) / 2 + 5, (dlev + r_ptr->level) / 2);*/
419 		r = get_mon_num(r_ptr->level + 5, r_ptr->level);
420 
421 		/* Handle failure */
422 		if (!r) break;
423 
424 		/* Obtain race */
425 		r_ptr = &r_info[r];
426 
427 		/* Ignore unique monsters */
428 //		if (r_ptr->flags1 & RF1_UNIQUE) continue;
429 
430 		/* Ignore monsters with incompatible levels */
431 		if ((r_ptr->level < lev1) || (r_ptr->level > lev2)) continue;
432 
433 		/* Use that index */
434 		r_idx = r;
435 
436 		/* Done */
437 		break;
438 	}
439 
440 	/* Result */
441 	return (r_idx);
442 }
443 
444 /*
445  * It is radius-based now.
446  *
447  * TODO:
448  * - give some messages
449  * - allow monsters to have st-anchor?
450  */
451 //bool check_st_anchor(struct worldpos *wpos)
check_st_anchor(struct worldpos * wpos,int y,int x)452 bool check_st_anchor(struct worldpos *wpos, int y, int x) {
453 	int i;
454 //	dun_level *l_ptr = getfloor(wpos);
455 
456 	for (i = 1; i <= NumPlayers; i++) {
457 		player_type *q_ptr = Players[i];
458 
459 		/* Skip disconnected players */
460 		if (q_ptr->conn == NOT_CONNECTED) continue;
461 
462 		/* Skip players not on this depth */
463 		if (!inarea(&q_ptr->wpos, wpos)) continue;
464 
465 		/* Maybe CAVE_ICKY/CAVE_STCK can be checked here */
466 
467 //		if (!q_ptr->st_anchor) continue;
468 //		if (!q_ptr->anti_tele) continue;
469 //		if ((!q_ptr->res_tele) && (rand_int(100) < 67)) continue;
470 		if (!q_ptr->resist_continuum) continue;
471 
472 		/* Compute distance */
473 		if (distance(y, x, q_ptr->py, q_ptr->px) > ST_ANCHOR_DIS)
474 			continue;
475 
476 //		if(istown(wpos) && randint(100)>q_ptr->lev) continue;
477 
478 		return TRUE;
479 	  }
480 
481 	/* Assume no st_anchor */
482 	return FALSE;
483 }
484 
485 
486 /*
487  * Teleport a monster, normally up to "dis" grids away.
488  *
489  * Attempt to move the monster at least "dis/2" grids away.
490  *
491  * But allow variation to prevent infinite loops.
492  */
teleport_away(int m_idx,int dis)493 bool teleport_away(int m_idx, int dis) {
494 	int		oy, ox, d, i, min;
495 	int		ny = 0, nx = 0, max_dis = 200, tries = 5000;
496 #ifdef USE_SOUND_2010
497 	int org_dis = dis;
498 #endif
499 
500 	bool		look = TRUE;
501 
502 	monster_type	*m_ptr = &m_list[m_idx];
503 	monster_race	*r_ptr = race_inf(m_ptr);
504 	dun_level *l_ptr;
505 	struct worldpos *wpos;
506 	cave_type **zcave;
507 
508 	/* Paranoia */
509 	if (!m_ptr->r_idx) return FALSE;
510 
511 	if (r_ptr->flags9 & RF9_IM_TELE) return FALSE;
512 
513 	/* Save the old location */
514 	oy = m_ptr->fy;
515 	ox = m_ptr->fx;
516 
517 	/* Space/Time Anchor */
518 	if (check_st_anchor(&m_ptr->wpos, oy, ox)) return FALSE;
519 
520 
521 	wpos = &m_ptr->wpos;
522 	if (!(zcave = getcave(wpos))) return FALSE;
523 	l_ptr = getfloor(wpos);
524 
525 	/* No teleporting/blinking out of any vaults (!) */
526 	if (zcave[oy][ox].info & CAVE_ICKY) return FALSE;
527 
528 	/* set distance according to map size, to avoid 'No empty field' failures for very small maps! */
529 	if (l_ptr && distance(1, 1, l_ptr->wid, l_ptr->hgt) < max_dis)
530 		max_dis = distance(1, 1, l_ptr->wid, l_ptr->hgt);
531 
532 	/* Verify max distance */
533 	if (dis > max_dis) dis = max_dis;
534 
535 	/* Minimum distance */
536 	min = dis / 2;
537 
538 	/* Look until done */
539 	while (look) {
540 		/* Verify max distance once here */
541 		if (dis > max_dis) dis = max_dis;
542 
543 		/* Try several locations */
544 		for (i = 0; i < 500; i++) {
545 			/* Pick a (possibly illegal) location */
546 			while (--tries) {
547 				ny = rand_spread(oy, dis);
548 				nx = rand_spread(ox, dis);
549 				d = distance(oy, ox, ny, nx);
550 				if ((d >= min) && (d <= dis)) break;
551 			}
552 			if (!tries) return FALSE;
553 
554 			/* Ignore illegal locations */
555 			if (!in_bounds4(l_ptr, ny, nx)) continue;
556 
557 			/* Require "empty" floor space */
558 			if (!cave_empty_bold(zcave, ny, nx)) continue;
559 
560 			/* Hack -- no teleport onto glyph of warding */
561 			if (zcave[ny][nx].feat == FEAT_GLYPH) continue;
562 			if (zcave[ny][nx].feat == FEAT_RUNE) continue;
563 			/* No teleporting into vaults and such */
564 			if (zcave[ny][nx].info & CAVE_ICKY) continue;
565 
566 			/* No teleportation onto protected grid (8-town-houses) */
567 			if (zcave[ny][nx].info & CAVE_PROT) continue;
568 			if (f_info[zcave[ny][nx].feat].flags1 & FF1_PROTECTED) continue;
569 			/* Not onto (dungeon) stores */
570 			if (zcave[ny][nx].feat == FEAT_SHOP) continue;
571 
572 			/* Space/Time Anchor */
573 			if (check_st_anchor(&m_ptr->wpos, ny, nx)) return FALSE;
574 
575 			/* This grid looks good */
576 			look = FALSE;
577 
578 			/* Stop looking */
579 			break;
580 		}
581 
582 		/* Increase the maximum distance */
583 		dis = dis * 2;
584 
585 		/* Decrease the minimum distance */
586 		min = min / 2;
587 	}
588 
589 	/* Update the new location */
590 	zcave[ny][nx].m_idx = m_idx;
591 	cave_midx_debug(wpos, ny, nx, m_idx);
592 
593 	/* Update the old location */
594 	zcave[oy][ox].m_idx = 0;
595 
596 	/* Move the monster */
597 	m_ptr->fy = ny;
598 	m_ptr->fx = nx;
599 
600 	/* Update the monster (new location) */
601 	update_mon(m_idx, TRUE);
602 
603 	/* Redraw the old grid */
604 	everyone_lite_spot(wpos, oy, ox);
605 
606 	/* Redraw the new grid */
607 	everyone_lite_spot(wpos, ny, nx);
608 
609 #ifdef USE_SOUND_2010
610 	if (org_dis <= 20 && org_dis >= 10) sound_near_monster(m_idx, "blink", NULL, SFX_TYPE_COMMAND);
611 	else if (org_dis > 20) sound_near_monster(m_idx, "teleport", NULL, SFX_TYPE_COMMAND);
612 #endif
613 
614 	/* Succeeded. */
615 	return TRUE;
616 }
617 
618 
619 /*
620  * Teleport monster next to the player
621  */
teleport_to_player(int Ind,int m_idx)622 void teleport_to_player(int Ind, int m_idx) {
623 	player_type *p_ptr = Players[Ind];
624 	int ny = 0, nx = 0, oy, ox, d, i, min;
625 	int dis = 2, max_dis = 200;
626 	bool look = TRUE;
627 
628 	monster_type *m_ptr = &m_list[m_idx];
629 //	int attempts = 200;
630 	int attempts = 5000;
631 
632 	struct worldpos *wpos = &m_ptr->wpos;
633 	dun_level *l_ptr;
634 	cave_type **zcave;
635 //	if(p_ptr->resist_continuum) {msg_print("The space-time continuum can't be disrupted."); return;}
636 
637 	/* Paranoia */
638 	if (!m_ptr->r_idx) return;
639 
640 	/* "Skill" test */
641 //	if (randint(100) > m_ptr->level) return;	/* not here */
642 
643 	if(!(zcave = getcave(wpos))) return;
644 	l_ptr = getfloor(wpos);
645 
646 	/* Save the old location */
647 	oy = m_ptr->fy;
648 	ox = m_ptr->fx;
649 
650 	/* Hrm, I cannot remember/see why it's commented out..
651 	 * maybe pets and golems need it? */
652 //	if (check_st_anchor(wpos)) return;
653 	if (check_st_anchor(wpos, oy, ox)) return;
654 
655 	/* set distance according to map size, to avoid 'No empty field' failures for very small maps! */
656 	if (l_ptr && distance(1, 1, l_ptr->wid, l_ptr->hgt) < max_dis)
657 		max_dis = distance(1, 1, l_ptr->wid, l_ptr->hgt);
658 
659 	/* Verify max distance */
660 	if (dis > max_dis) dis = max_dis;
661 
662 	/* Minimum distance */
663 	min = dis / 2;
664 
665 	/* Look until done */
666 	while (look) {
667 		/* Verify max distance */
668 		if (dis > max_dis) dis = max_dis;
669 
670 		/* Try several locations */
671 		for (i = 0; i < 500; i++) {
672 			/* Pick a (possibly illegal) location */
673 			while (--attempts) {
674 				ny = rand_spread(p_ptr->py, dis);
675 				nx = rand_spread(p_ptr->px, dis);
676 				d = distance(p_ptr->py, p_ptr->px, ny, nx);
677 				if ((d >= min) && (d <= dis)) break;
678 			}
679 			if (!attempts) return;
680 
681 			/* Ignore illegal locations */
682 			if (!in_bounds(ny, nx)) continue;
683 
684 			/* Require "empty" floor space */
685 			if (!cave_empty_bold(zcave, ny, nx)) continue;
686 
687 			/* Hack -- no teleport onto glyph of warding */
688 			if (zcave[ny][nx].feat == FEAT_GLYPH) continue;
689 			if (zcave[ny][nx].feat == FEAT_RUNE) continue;
690 #if 0
691 			if (cave[ny][nx].feat == FEAT_MINOR_GLYPH) continue;
692 
693 			/* ...nor onto the Pattern */
694 			if ((cave[ny][nx].feat >= FEAT_PATTERN_START) &&
695 				(cave[ny][nx].feat <= FEAT_PATTERN_XTRA2)) continue;
696 #endif	/* 0 */
697 
698 			/* No teleporting into vaults and such */
699 			/* if (cave[ny][nx].info & (CAVE_ICKY)) continue; */
700 			if (zcave[ny][nx].info & CAVE_ICKY) continue;
701 
702 			/* No teleportation onto protected grid (8-town-houses) */
703 			if (zcave[ny][nx].info & CAVE_PROT) continue;
704 			if (f_info[zcave[ny][nx].feat].flags1 & FF1_PROTECTED) continue;
705 			/* Not onto (dungeon) stores */
706 			if (zcave[ny][nx].feat == FEAT_SHOP) continue;
707 
708 			if (check_st_anchor(wpos, ny, nx)) return;
709 
710 			/* This grid looks good */
711 			look = FALSE;
712 
713 			/* Stop looking */
714 			break;
715 		}
716 
717 		/* Increase the maximum distance */
718 		dis = dis * 2;
719 
720 		/* Decrease the minimum distance */
721 		min = min / 2;
722 	}
723 
724 #ifdef USE_SOUND_2010
725 	sound(Ind, "blink", NULL, SFX_TYPE_COMMAND, FALSE);
726 #else
727 //	sound(SOUND_TPOTHER);
728 #endif
729 
730 	/* Update the new location */
731 	zcave[ny][nx].m_idx = m_idx;
732 	cave_midx_debug(wpos, ny, nx, m_idx);
733 
734 	/* Update the old location */
735 	zcave[oy][ox].m_idx = 0;
736 
737 	/* Move the monster */
738 	m_ptr->fy = ny;
739 	m_ptr->fx = nx;
740 
741 	/* Update the monster (new location) */
742 	update_mon(m_idx, TRUE);
743 
744 	/* Redraw the old grid */
745 	everyone_lite_spot(wpos, oy, ox);
746 
747 	/* Redraw the new grid */
748 	everyone_lite_spot(wpos, ny, nx);
749 }
750 
751 
752 /*
753  * Teleport the player to a location up to "dis" grids away.
754  *
755  * If no such spaces are readily available, the distance may increase.
756  * Try very hard to move the player at least a quarter that distance.
757  */
teleport_player(int Ind,int dis,bool ignore_pvp)758 bool teleport_player(int Ind, int dis, bool ignore_pvp) {
759 	player_type *p_ptr = Players[Ind];
760 #if defined(USE_SOUND_2010) || defined(ENABLE_SELF_FLASHING)
761 	int org_dis = dis;
762 #endif
763 	int d, i, min, ox, oy, x = p_ptr->py, y = p_ptr->px;
764 	int xx , yy, m_idx, max_dis = 150, tries = 3000; /* (max_dis was 200 at some point) */
765 	worldpos *wpos = &p_ptr->wpos;
766 	dun_level *l_ptr;
767 
768 	bool look = TRUE;
769 	bool left_shop = (dis == 1) || istown(wpos) //istown hack: prevent teleporting people who can't swim into the lake in Bree
770 	    || isdungeontown(wpos); //for IDDC random towns to avoid lava/water item destruction on logging in
771 
772 	/* Space/Time Anchor */
773 	cave_type **zcave;
774 	if(!(zcave = getcave(wpos))) return FALSE;
775 	l_ptr = getfloor(wpos);
776 
777 	if ((p_ptr->global_event_temp & PEVF_NOTELE_00)) return FALSE;
778 	if (l_ptr && (l_ptr->flags2 & LF2_NO_TELE)) return FALSE;
779 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_TELE)) return FALSE;
780 
781 	/* Hack -- Teleportation when died is always allowed */
782 	if (!p_ptr->death) {
783 		if (p_ptr->mode & MODE_PVP) {
784 #ifdef HOSTILITY_ABORTS_RUNNING
785  #if 1
786 			/* hack: cut down phase door range in pvp, since rules dont allow running anymore */
787 			if (dis == 10) dis = 5;
788 //			if (dis <= 20) dis /= 2;
789  #else
790 			if (ignore_pvp) dis /= 2; /* phase door spell by default works in pvp */
791  #endif
792 #endif
793 
794 			if (!ignore_pvp && p_ptr->pvp_prevent_tele) {
795 				msg_print(Ind, "\377yThere's no easy way out of this fight!");
796 				s_printf("%s TELEPORT_FAIL: pvp_prevent_tele for %s.\n", showtime(), p_ptr->name);
797 				return FALSE;
798 			}
799 		}
800 		if (p_ptr->anti_tele || check_st_anchor(wpos, p_ptr->py, p_ptr->px)) {
801 			msg_print(Ind, "\377oYou are surrounded by an anti-teleportation field!");
802 			s_printf("%s TELEPORT_FAIL: Anti-Tele for %s.\n", showtime(), p_ptr->name);
803 			return FALSE;
804 		}
805 		if (zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) {
806 			msg_print(Ind, "\377RThis location suppresses teleportation!");
807 			s_printf("%s TELEPORT_FAIL: Cave-Stck for %s.\n", showtime(), p_ptr->name);
808 			return FALSE;
809 		}
810 
811 #ifdef AUTO_RET_NEW
812 		/* Don't allow phase/teleport for auto-retaliation methods */
813 		if (p_ptr->auto_retaliaty) {
814 			msg_print(Ind, "\377yYou cannot use means of self-translocation for auto-retaliation.");
815 			return FALSE;
816 		}
817 #endif
818 
819 //		if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_MAGIC)) return;
820 		/* Hack -- on the wilderness one cannot teleport very far */
821 		/* Double death isnt nice */
822 		if (!wpos->wz && !istown(wpos) && dis > WILDERNESS_TELEPORT_RADIUS)
823 			dis = WILDERNESS_TELEPORT_RADIUS;
824 	}
825 
826 	/* set distance according to map size, to avoid 'No empty field' failures for very small maps! */
827 	if (l_ptr && distance(1, 1, l_ptr->wid, l_ptr->hgt) < max_dis)
828 		max_dis = distance(1, 1, l_ptr->wid, l_ptr->hgt);
829 
830 	/* Verify max distance */
831 	if (dis > max_dis) dis = max_dis;
832 
833 	/* Verify max distance once here */
834 	if (dis > max_dis) dis = max_dis;
835 
836 	/* Minimum distance */
837 	min = dis / 2;
838 
839 #ifdef TELEPORTATION_MIN_LIMIT
840 	if (min > TELEPORT_MIN_LIMIT) min = TELEPORT_MIN_LIMIT;
841 #endif	// TELEPORTATION_MIN_LIMIT
842 
843 	/* Look until done */
844 	while (look && tries) {
845 		/* Verify max distance */
846 		if (dis > max_dis) dis = max_dis;
847 
848 		/* Try several locations */
849 		for (i = 0; i < 500; i++) {
850 			/* Pick a (possibly illegal) location */
851 			while (--tries) {
852 				y = rand_spread(p_ptr->py, dis);
853 				x = rand_spread(p_ptr->px, dis);
854 
855 				d = distance(p_ptr->py, p_ptr->px, y, x);
856 				//plog(format("y%d x%d d%d min%d dis%d", y, x, d, min, dis));
857 				if ((d >= min) && (d <= dis)) break;
858 			}
859 			/* Avoid server hang-up on 100%-tree-maps */
860 			if (!tries) break;
861 
862 			/* Ignore illegal locations */
863 			if (!in_bounds4(l_ptr, y, x)) continue;
864 
865 			/* Require floor space if not ghost */
866 			if (!p_ptr->ghost && !cave_naked_bold(zcave, y, x)) continue;
867 
868 			/* never teleport onto perma-walls (happens to ghosts in khazad) */
869 			if (cave_perma_bold(zcave, y, x)) continue;
870 
871 			/* Require empty space if a ghost */
872 			if (p_ptr->ghost && zcave[y][x].m_idx) continue;
873 
874 			/* No teleporting into vaults and such */
875 			if (zcave[y][x].info & CAVE_ICKY) continue;
876 			/* This prevents teleporting into broken vaults where layouts overlap :/ annoying bug */
877 			if (zcave[y][x].info & CAVE_STCK) continue;
878 			/* No teleporting into monster nests (experimental, 2008-05-26) */
879 			if (zcave[y][x].info & CAVE_NEST_PIT) continue;
880 
881 			/* Prevent landing onto a store entrance */
882 			if (zcave[y][x].feat == FEAT_SHOP) continue;
883 
884 			if (left_shop) {
885 				if (zcave[y][x].feat == FEAT_SHAL_LAVA ||
886 				    zcave[y][x].feat == FEAT_DEEP_LAVA)
887 					if (!(p_ptr->immune_fire || (p_ptr->resist_fire && p_ptr->oppose_fire)))
888 						continue;
889 				if (zcave[y][x].feat == FEAT_DEEP_WATER)
890 					//if (!(p_ptr->immune_water || p_ptr->res_water ||
891 					if (!(p_ptr->can_swim || p_ptr->levitate || p_ptr->ghost || p_ptr->tim_wraith))
892 						continue;
893 			}
894 
895 			/* Never break into st-anchor */
896 			if (!p_ptr->death && check_st_anchor(wpos, y, x)) return FALSE;
897 
898 			/* This grid looks good */
899 			look = FALSE;
900 
901 			/* Stop looking */
902 			break;
903 		}
904 
905 		/* Increase the maximum distance */
906 		dis = dis * 2;
907 
908 		/* Decrease the minimum distance */
909 		min = min / 2;
910 	}
911 
912 	/* No empty field on this map o_O */
913 	if (!tries) {
914 		s_printf("%s TELEPORT_FAIL: No empty field found for %s.\n", showtime(), p_ptr->name);
915 		msg_print(Ind, "oThe teleportation spell strangely fizzles!");
916 		return FALSE;
917 	}
918 
919 	break_cloaking(Ind, 7);
920 	stop_precision(Ind);
921 	stop_shooting_till_kill(Ind);
922 
923 	store_exit(Ind);
924 
925 	/* Save the old location */
926 	oy = p_ptr->py;
927 	ox = p_ptr->px;
928 
929 #ifdef USE_SOUND_2010
930 	/* note: currently 10 is the usual phase door distance, and spells can get it up to 12. */
931 	if (org_dis <= 20 && org_dis >= 7) sound(Ind, "phase_door", NULL, SFX_TYPE_COMMAND, TRUE);
932 	else if (org_dis > 20) {
933 		sound(Ind, "teleport", NULL, SFX_TYPE_COMMAND, TRUE);
934  #ifdef TELEPORT_SURPRISES
935 		p_ptr->teleported = 3;
936  #endif
937 	}
938 #else
939  #ifdef TELEPORT_SURPRISES
940 	if (org_dis > 20) p_ptr->teleported = 3;
941  #endif
942 #endif
943 
944 	/* Move the player */
945 	p_ptr->py = y;
946 	p_ptr->px = x;
947 
948 	grid_affects_player(Ind);
949 
950 	/* The player isn't on his old spot anymore */
951 	zcave[oy][ox].m_idx = 0;
952 
953 	/* The player is on his new spot */
954 	zcave[y][x].m_idx = 0 - Ind;
955 	cave_midx_debug(wpos, y, x, -Ind);
956 
957 	/* Redraw the old spot */
958 	everyone_lite_spot(wpos, oy, ox);
959 
960 	/* Don't leave me alone Daisy! */
961 	if (!p_ptr->ghost) {
962 		for (d = 1; d <= 9; d++) {
963 			if (d == 5) continue;
964 
965 			xx = ox + ddx[d];
966 			yy = oy + ddy[d];
967 
968 			if (!in_bounds4(l_ptr, yy, xx)) continue;
969 
970 			if ((m_idx = zcave[yy][xx].m_idx) > 0) {
971 				monster_race *r_ptr = race_inf(&m_list[m_idx]);
972 
973 				if ((r_ptr->flags6 & RF6_TPORT) &&
974 				    !((r_ptr->flags3 & RF3_RES_TELE) || (r_ptr->flags9 & RF9_IM_TELE))) {
975 					/*
976 					 * The latter limitation is to avoid
977 					 * totally unkillable suckers...
978 					 */
979 					if (!(m_list[m_idx].csleep) && mon_will_run(Ind, m_idx) == FALSE) {
980 						/* "Skill" test */
981 						if (randint(100) < r_ptr->level)
982 							teleport_to_player(Ind, m_idx);
983 					}
984 				}
985 			}
986 		}
987 	}
988 
989 #ifdef ENABLE_SELF_FLASHING
990 	/* flicker player for a moment, to allow for easy location */
991 	/* not for phase door, except when our view panel has changed from it */
992 	if (p_ptr->flash_self >= 0 &&
993 	    (org_dis > 20 || !local_panel(Ind)))
994 		p_ptr->flash_self = cfg.fps / FLASH_SELF_DIV;
995 #endif
996 
997 	/* Redraw the new spot */
998 	everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
999 
1000 	/* Check for new panel (redraw map) */
1001 	verify_panel(Ind);
1002 
1003 	/* Update stuff */
1004 	p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
1005 
1006 	/* Update the monsters */
1007 	p_ptr->update |= (PU_DISTANCE);
1008 
1009 	/* Window stuff */
1010 	p_ptr->window |= (PW_OVERHEAD);
1011 
1012 	/* Handle stuff XXX XXX XXX */
1013 	if (!p_ptr->death) handle_stuff(Ind);
1014 
1015 	return TRUE;
1016 }
1017 
1018 
1019 /*
1020  * Force teleportation of a player
1021  *  - mikaelh
1022  */
teleport_player_force(int Ind,int dis)1023 void teleport_player_force(int Ind, int dis) {
1024 	bool anti_tele, death;
1025 	player_type *p_ptr = Players[Ind];
1026 
1027 	/* Turn off anti-tele */
1028 	anti_tele = p_ptr->anti_tele;
1029 	/* set death flag as hack to escape no-tele vault grids */
1030 	death = p_ptr->death;
1031 
1032 	/* hacks */
1033 	p_ptr->anti_tele = FALSE; /* actually already covered by p_ptr->death below */
1034 	p_ptr->death = TRUE;
1035 
1036 	teleport_player(Ind, dis, TRUE);
1037 
1038 	/* Restore anti-tele */
1039 	p_ptr->anti_tele = anti_tele;
1040 	/* restore death flag */
1041 	p_ptr->death = death;
1042 }
1043 
1044 
1045 /*
1046  * Teleport player to a grid near the given location
1047  *
1048  * This function is slightly obsessive about correctness.
1049  * (Not anymore: This function allows teleporting into vaults (!))
1050  */
teleport_player_to(int Ind,int ny,int nx)1051 void teleport_player_to(int Ind, int ny, int nx) {
1052 	player_type *p_ptr = Players[Ind];
1053 
1054 	int y, x, oy, ox, dis = 1, ctr = 0;
1055 	struct worldpos *wpos = &p_ptr->wpos;
1056 	int tries = 3000;
1057 	dun_level *l_ptr;
1058 	cave_type **zcave;
1059 	bool town = istown(wpos);//prevent teleporting people who can't swim into the lake in Bree
1060 
1061 	if (!(zcave = getcave(wpos))) return;
1062 	if (p_ptr->anti_tele) return;
1063 	if (zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) return;
1064 	l_ptr = getfloor(wpos);
1065 
1066 	if ((p_ptr->global_event_temp & PEVF_NOTELE_00)) return;
1067 	if (l_ptr && (l_ptr->flags2 & LF2_NO_TELE)) return;
1068 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_TELE)) return;
1069 //	if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_MAGIC)) return;
1070 
1071 	if (ny < 1) ny = 1;
1072 	if (nx < 1) nx = 1;
1073 	if (ny > MAX_HGT - 2) ny = MAX_HGT - 2;
1074 	if (nx > MAX_WID - 2) nx = MAX_WID - 2;
1075 
1076 	/* Space/Time Anchor */
1077 	if (check_st_anchor(wpos, ny, nx)) return;
1078 
1079 	/* Find a usable location */
1080 	while (tries) {
1081 		/* Pick a nearby legal location */
1082 		while (--tries) {
1083 			y = rand_spread(ny, dis);
1084 			x = rand_spread(nx, dis);
1085 			if (in_bounds4(l_ptr, y, x)) break;
1086 
1087 			/* Occasionally advance the distance */
1088 			if (++ctr > (4 * dis * dis + 4 * dis + 1)) {
1089 				ctr = 0;
1090 				dis++;
1091 			}
1092 		}
1093 		if (!tries) return;
1094 
1095 		if (town) {
1096 			if (zcave[y][x].feat == FEAT_SHAL_LAVA ||
1097 			    zcave[y][x].feat == FEAT_DEEP_LAVA)
1098 				if (!(p_ptr->immune_fire || (p_ptr->resist_fire && p_ptr->oppose_fire))) {
1099 					/* Occasionally advance the distance */
1100 					if (++ctr > (4 * dis * dis + 4 * dis + 1)) {
1101 						ctr = 0;
1102 						dis++;
1103 					}
1104 					continue;
1105 				}
1106 			if (zcave[y][x].feat == FEAT_DEEP_WATER)
1107 				//if (!(p_ptr->immune_water || p_ptr->res_water ||
1108 				if (!(p_ptr->can_swim || p_ptr->levitate || p_ptr->ghost || p_ptr->tim_wraith)) {
1109 					/* Occasionally advance the distance */
1110 					if (++ctr > (4 * dis * dis + 4 * dis + 1)) {
1111 						ctr = 0;
1112 						dis++;
1113 					}
1114 					continue;
1115 				}
1116 		}
1117 
1118 		/* Cant telep in houses */
1119 		if (((wpos->wz == 0) && !(zcave[y][x].info & CAVE_ICKY)) || (wpos->wz)) {
1120 			/* No tele-to into no-tele vaults */
1121 			if (cave_naked_bold(zcave, y, x) &&
1122 			    !(zcave[y][x].info & CAVE_STCK)) {
1123 				/* Never break into st-anchor */
1124 				if (!check_st_anchor(wpos, y, x)) {
1125 					/* tele-to success */
1126 					break;
1127 				}
1128 			}
1129 		}
1130 
1131 		/* Occasionally advance the distance */
1132 		if (++ctr > (4 * dis * dis + 4 * dis + 1)) {
1133 			ctr = 0;
1134 			dis++;
1135 		}
1136 	}
1137 
1138 	store_exit(Ind);
1139 
1140 	/* Log, to distinguish MOVE_BODY vs TELE_TO related kills just in case */
1141 	s_printf("TELE_TO: '%s' was teleported to %d,%d", p_ptr->name, x, y);
1142 	if ((zcave[y][x].info & CAVE_ICKY)) s_printf(" (ICKY)");
1143 	if ((zcave[y][x].info & CAVE_STCK)) s_printf(" (STCK)");
1144 	s_printf(".\n");
1145 
1146 	/* Save the old location */
1147 	oy = p_ptr->py;
1148 	ox = p_ptr->px;
1149 
1150 	/* Move the player */
1151 	p_ptr->py = y;
1152 	p_ptr->px = x;
1153 
1154 	grid_affects_player(Ind);
1155 
1156 	/* The player isn't here anymore */
1157 	zcave[oy][ox].m_idx = 0;
1158 
1159 	/* The player is now here */
1160 	zcave[y][x].m_idx = 0 - Ind;
1161 	cave_midx_debug(wpos, y, x, -Ind);
1162 
1163 	/* Redraw the old spot */
1164 	everyone_lite_spot(wpos, oy, ox);
1165 
1166 #ifdef ENABLE_SELF_FLASHING
1167 #if 0 /* not for tele-to - let's regarded it as a 'blink' here */
1168 	/* flicker player for a moment, to allow for easy location */
1169 	if (p_ptr->flash_self >= 0) p_ptr->flash_self = cfg.fps / FLASH_SELF_DIV;
1170 #else /* exception when our view panel has changed from this tele-to */
1171 	if (p_ptr->flash_self >= 0 && !local_panel(Ind)) p_ptr->flash_self = cfg.fps / FLASH_SELF_DIV;
1172 #endif
1173 #endif
1174 
1175 	/* Redraw the new spot */
1176 	everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
1177 
1178 	/* Check for new panel (redraw map) */
1179 	verify_panel(Ind);
1180 
1181 	/* Update stuff */
1182 	p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
1183 
1184 	/* Update the monsters */
1185 	p_ptr->update |= (PU_DISTANCE);
1186 
1187 	/* Window stuff */
1188 	p_ptr->window |= (PW_OVERHEAD);
1189 
1190 	/* Handle stuff XXX XXX XXX */
1191 	handle_stuff(Ind);
1192 
1193 #ifdef USE_SOUND_2010
1194 	sound(Ind, "blink", NULL, SFX_TYPE_COMMAND, TRUE);
1195 #endif
1196 }
teleport_player_to_force(int Ind,int ny,int nx)1197 void teleport_player_to_force(int Ind, int ny, int nx) {
1198 	bool anti_tele, death;
1199 	player_type *p_ptr = Players[Ind];
1200 
1201 	/* Turn off anti-tele */
1202 	anti_tele = p_ptr->anti_tele;
1203 	/* set death flag as hack to escape no-tele vault grids */
1204 	death = p_ptr->death;
1205 
1206 	/* hacks */
1207 	p_ptr->anti_tele = FALSE; /* actually already covered by p_ptr->death below */
1208 	p_ptr->death = TRUE;
1209 
1210 	teleport_player_to(Ind, ny, nx);
1211 
1212 	/* Restore anti-tele */
1213 	p_ptr->anti_tele = anti_tele;
1214 	/* restore death flag */
1215 	p_ptr->death = death;
1216 }
1217 
1218 
1219 
1220 /*
1221  * Teleport the player one level up or down (random when legal)
1222  *
1223  * Note that keeping the "players_on_depth" array correct is VERY important,
1224  * otherwise levels with players still on them might be destroyed, or empty
1225  * levels could be kept around, wasting memory.
1226  */
1227 
1228  /* in the wilderness, teleport to a neighboring wilderness level.
1229   * 'force' : TRUE only for level-unstaticing, ie administration work.
1230   *           (can transport players out of dungeons in ways that are not 'legal' (ironman etc).
1231   * New: Disallow entering/exiting dungeons this way.
1232   */
teleport_player_level(int Ind,bool force)1233 void teleport_player_level(int Ind, bool force) {
1234 	player_type *p_ptr = Players[Ind];
1235 	struct worldpos *wpos = &p_ptr->wpos;
1236 	struct worldpos new_depth, old_wpos;
1237 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
1238 	char *msg = "\377rCritical bug!";
1239 	cave_type **zcave;
1240 	int tries = 100;
1241 
1242 	if (!(zcave = getcave(wpos))) return;
1243 	if ((zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) && !force) return;
1244 //	if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_MAGIC)) return;
1245 
1246 	if ((p_ptr->global_event_temp & PEVF_NOTELE_00)) return;
1247 	if (l_ptr && (l_ptr->flags2 & LF2_NO_TELE)) return;
1248 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_TELE)) return;
1249 
1250 	/* Space/Time Anchor */
1251 	if (p_ptr->anti_tele && !force) return;
1252 	if (check_st_anchor(&p_ptr->wpos, p_ptr->py, p_ptr->px) && !force) return;
1253 
1254 	wpcopy(&old_wpos, wpos);
1255 	wpcopy(&new_depth, wpos);
1256 
1257 	/* If in the wilderness, teleport to a random neighboring level.
1258 	   This is especially important to prevent player from entering dungeons
1259 	   that have NO_ENTRY_WOR or similar flags (eg Valinor)! - C. Blue */
1260 	if (wpos->wz == 0) {
1261 		/* get a valid neighbor */
1262 		do {
1263 			switch (rand_int(4)) {
1264 			case DIR_NORTH:
1265 				if (new_depth.wy < MAX_WILD_Y - 1)
1266 					new_depth.wy++;
1267 				msg = "A gust of wind blows you north.";
1268 				break;
1269 			case DIR_EAST:
1270 				if (new_depth.wx < MAX_WILD_X - 1)
1271 					new_depth.wx++;
1272 				msg = "A gust of wind blows you east.";
1273 				break;
1274 			case DIR_SOUTH:
1275 				if (new_depth.wy > 0)
1276 					new_depth.wy--;
1277 				msg = "A gust of wind blows you south.";
1278 				break;
1279 			case DIR_WEST:
1280 				if (new_depth.wx > 0)
1281 					new_depth.wx--;
1282 				msg = "A gust of wind blows you west.";
1283 				break;
1284 			}
1285 		} while (inarea(wpos, &new_depth) && --tries);
1286 		if (!tries) {
1287 			msg = "There is a large magical discharge in the air.";
1288 			return;
1289 		}
1290 
1291 		p_ptr->new_level_method = LEVEL_OUTSIDE_RAND;
1292 		/* update the players new wilderness location */
1293 
1294 		/* update the players wilderness map */
1295 		if (!p_ptr->ghost)
1296 			p_ptr->wild_map[(new_depth.wx + new_depth.wy * MAX_WILD_X) / 8] |=
1297 			    (1 << ((new_depth.wx + new_depth.wy * MAX_WILD_X) % 8));
1298 	/* sometimes go down */
1299 	} else if ((can_go_down(wpos, 0x1) && wpos->wz > 1 &&
1300 	    ((!can_go_up(wpos, 0x1) || wpos->wz >= -1 || (rand_int(100) < 50)) ||
1301 	     (wpos->wz < 0 && wild_info[wpos->wy][wpos->wx].dungeon->flags2 & DF2_IRON)))
1302 	    || (force && can_go_down_simple(wpos))) {
1303 		new_depth.wz--;
1304 		msg = "You sink through the floor.";
1305 		p_ptr->new_level_method = (new_depth.wz || (istown(&new_depth)) ? LEVEL_RAND : LEVEL_OUTSIDE_RAND);
1306 	}
1307 	/* else go up */
1308 	else if ((can_go_up(wpos, 0x1) && wpos->wz < -1 &&
1309 	    !(wpos->wz > 0 && wild_info[wpos->wy][wpos->wx].tower->flags2 & DF2_IRON))
1310 	    || (force && can_go_up_simple(wpos))) {
1311 		new_depth.wz++;
1312 		msg = "You rise up through the ceiling.";
1313 		p_ptr->new_level_method = (new_depth.wz || (istown(&new_depth)) ? LEVEL_RAND : LEVEL_OUTSIDE_RAND);
1314 	} else {
1315 		msg = "There is a large magical discharge in the air.";
1316 		return;
1317 	}
1318 
1319 	/* Tell the player */
1320 	msg_print(Ind, msg);
1321 
1322 #ifdef USE_SOUND_2010
1323 	sound(Ind, "teleport", NULL, SFX_TYPE_COMMAND, TRUE);
1324 #endif
1325 
1326 	/* Remove the player */
1327 	zcave[p_ptr->py][p_ptr->px].m_idx = 0;
1328 
1329 	/* Show that he's left */
1330 	everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
1331 
1332 	/* Forget his lite and viewing area */
1333 	forget_lite(Ind);
1334 	forget_view(Ind);
1335 
1336 	/* Change the wpos */
1337 	wpcopy(wpos, &new_depth);
1338 
1339 	/* One less player here */
1340 	new_players_on_depth(&old_wpos, -1, TRUE);
1341 
1342 	/* One more player here */
1343 	new_players_on_depth(wpos, 1, TRUE);
1344 
1345 	p_ptr->new_level_flag = TRUE;
1346 }
1347 
1348 /* Like teleport_player_level() but does this for ALL players on a wpos at once
1349    so they end up together again. Added for quest_prepare_zcave(). - C. Blue
1350    Note: This bypasses all teleportation-preventing aspects.
1351    New: Disallow entering/exiting dungeons this way. */
teleport_players_level(struct worldpos * wpos)1352 void teleport_players_level(struct worldpos *wpos) {
1353 	int i, method = LEVEL_OUTSIDE_RAND, tries = 100;
1354 	player_type *p_ptr;
1355 	struct worldpos new_wpos, old_wpos;
1356 	char *msg = "\377rCritical bug!";
1357 	cave_type **zcave;
1358 
1359 	if (!(zcave = getcave(wpos))) return;
1360 
1361 	wpcopy(&old_wpos, wpos);
1362 	wpcopy(&new_wpos, wpos);
1363 
1364 	/* If in the wilderness, teleport to a random neighboring level.
1365 	   This is especially important to prevent player from entering dungeons
1366 	   that have NO_ENTRY_WOR or similar flags (eg Valinor)! - C. Blue */
1367 	if (wpos->wz == 0) {
1368 		/* get a valid neighbor */
1369 		do {
1370 			switch (rand_int(4)) {
1371 			case DIR_NORTH:
1372 				if (new_wpos.wy < MAX_WILD_Y - 1)
1373 					new_wpos.wy++;
1374 				msg = "A sudden magical gust of wind blows you north.";
1375 				break;
1376 			case DIR_EAST:
1377 				if (new_wpos.wx < MAX_WILD_X - 1)
1378 					new_wpos.wx++;
1379 				msg = "A sudden magical gust of wind blows you east.";
1380 				break;
1381 			case DIR_SOUTH:
1382 				if (new_wpos.wy > 0)
1383 					new_wpos.wy--;
1384 				msg = "A sudden magical gust of wind blows you south.";
1385 				break;
1386 			case DIR_WEST:
1387 				if (new_wpos.wx > 0)
1388 					new_wpos.wx--;
1389 				msg = "A sudden magical gust of wind blows you west.";
1390 				break;
1391 			}
1392 		} while (inarea(wpos, &new_wpos) && --tries);
1393 		if (!tries) {
1394 			msg = "There is a large magical discharge in the air.";
1395 			s_printf("Warning: teleport_players_level() failed.");
1396 			return;
1397 		}
1398 
1399 		method = LEVEL_OUTSIDE_RAND;
1400 	/* sometimes go down */
1401 	} else if ((can_go_down(wpos, 0x1) && wpos->wz > 1 &&
1402 	    ((!can_go_up(wpos, 0x1) || wpos->wz >= -1 || (rand_int(100) < 50)) ||
1403 	     (wpos->wz < 0 && wild_info[wpos->wy][wpos->wx].dungeon->flags2 & DF2_IRON)))
1404 	    || (can_go_down_simple(wpos))) {
1405 		new_wpos.wz--;
1406 		msg = "Some arcane magic suddenly makes you sink through the floor.";
1407 		method = (new_wpos.wz || (istown(&new_wpos)) ? LEVEL_RAND : LEVEL_OUTSIDE_RAND);
1408 	}
1409 	/* else go up */
1410 	else if ((can_go_up(wpos, 0x1) && wpos->wz < -1 &&
1411 	    !(wpos->wz > 0 && wild_info[wpos->wy][wpos->wx].tower->flags2 & DF2_IRON))
1412 	    || (can_go_up_simple(wpos))) {
1413 		new_wpos.wz++;
1414 		msg = "Some arcane magic suddenly makes You rise up through the ceiling.";
1415 		method = (new_wpos.wz || (istown(&new_wpos)) ? LEVEL_RAND : LEVEL_OUTSIDE_RAND);
1416 	} else {
1417 		msg = "There is a large magical discharge in the air.";
1418 		s_printf("Warning: teleport_players_level() failed.");
1419 		return;
1420 	}
1421 
1422 	for (i = 1; i <= NumPlayers; i++) {
1423 		p_ptr = Players[i];
1424 		if (!inarea(&p_ptr->wpos, wpos)) continue;
1425 
1426 		p_ptr->new_level_method = method;
1427 
1428 		/* update the players new wilderness location */
1429 
1430 		/* update the players wilderness map */
1431 		if(!p_ptr->ghost)
1432 			p_ptr->wild_map[(new_wpos.wx + new_wpos.wy * MAX_WILD_X) / 8] |=
1433 			    (1 << ((new_wpos.wx + new_wpos.wy * MAX_WILD_X) % 8));
1434 
1435 		/* Tell the player */
1436 		msg_print(i, msg);
1437 
1438 #ifdef USE_SOUND_2010
1439 		sound(i, "teleport", NULL, SFX_TYPE_COMMAND, TRUE);
1440 #endif
1441 
1442 		/* Remove the player */
1443 		zcave[p_ptr->py][p_ptr->px].m_idx = 0;
1444 
1445 		/* Show that he's left */
1446 		everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
1447 
1448 		/* Forget his lite and viewing area */
1449 		forget_lite(i);
1450 		forget_view(i);
1451 
1452 		/* One less player here */
1453 		new_players_on_depth(&old_wpos, -1, TRUE);
1454 
1455 		/* Change the wpos */
1456 		wpcopy(&p_ptr->wpos, &new_wpos);
1457 
1458 		p_ptr->new_level_flag = TRUE;
1459 
1460 		/* One more player here */
1461 		new_players_on_depth(&new_wpos, 1, TRUE);
1462 	}
1463 }
1464 
1465 #ifndef EXTENDED_TERM_COLOURS
1466 /*
1467  * Return a color to use for the bolt/ball spells
1468  */
spell_color(int type)1469 byte spell_color(int type)
1470 {
1471 	/* Hack -- fake monochrome */
1472 	if (!use_color) return (TERM_WHITE);
1473 
1474 	/* Analyze */
1475 	switch (type)	/* colourful ToME ones :) */
1476 	{
1477 		case GF_MISSILE:	return (TERM_SLATE);
1478 		case GF_ACID:		return (TERM_ACID);
1479 		case GF_ELEC:		return (TERM_ELEC);
1480 		case GF_FIRE:		return (TERM_FIRE);
1481 		case GF_COLD:		return (TERM_COLD);
1482 		case GF_POIS:		return (TERM_POIS);
1483 		case GF_UNBREATH:	return (randint(7) < 3 ? TERM_L_GREEN : TERM_GREEN);
1484 //		case GF_HOLY_ORB:	return (TERM_L_DARK);
1485 		case GF_HOLY_ORB:	return (randint(6) == 1 ? TERM_ORANGE : TERM_L_DARK);
1486 		case GF_HOLY_FIRE:	return (randint(3) != 1 ? TERM_ORANGE : (randint(2) == 1 ? TERM_YELLOW : TERM_WHITE));
1487 		case GF_HELL_FIRE:	return (randint(5) == 1 ? TERM_RED : TERM_L_DARK);
1488 		case GF_MANA:		return (randint(5) != 1 ? TERM_VIOLET : TERM_L_BLUE);
1489 		case GF_ARROW:		return (TERM_L_UMBER);
1490 		case GF_WATER:		return (randint(4) == 1 ? TERM_L_BLUE : TERM_BLUE);
1491 		case GF_WAVE:		return (randint(4) == 1 ? TERM_L_BLUE : TERM_BLUE);
1492 		case GF_VAPOUR:		return (randint(10) == 1 ? TERM_BLUE : TERM_L_BLUE);
1493 		case GF_NETHER_WEAK:
1494 		case GF_NETHER:		return (randint(4) == 1 ? TERM_L_GREEN : TERM_L_DARK);
1495 		case GF_CHAOS:		return (TERM_MULTI);
1496 		case GF_DISENCHANT:	return (randint(4) != 1 ? TERM_ORANGE : TERM_BLUE);
1497 		case GF_NEXUS:		return (randint(5) < 3 ? TERM_L_RED : TERM_VIOLET);
1498 		case GF_CONFUSION:	return (TERM_CONF);
1499 		case GF_SOUND:		return (TERM_SOUN);
1500 		case GF_SHARDS:		return (TERM_SHAR);
1501 		case GF_FORCE:		return (randint(5) < 3 ? TERM_L_WHITE : TERM_ORANGE);
1502 		case GF_INERTIA:	return (randint(5) < 3 ? TERM_SLATE : TERM_L_WHITE);
1503 		case GF_GRAVITY:	return (randint(3) == 1? TERM_L_UMBER : TERM_UMBER);
1504 		case GF_TIME:		return (randint(3) == 1? TERM_GREEN : TERM_L_BLUE);
1505 		case GF_LITE_WEAK:	return (TERM_LITE);
1506 		case GF_LITE:		return (TERM_LITE);
1507 		case GF_DARK_WEAK:	return (TERM_DARKNESS);
1508 		case GF_DARK:		return (TERM_DARKNESS);
1509 		case GF_PLASMA:		return (randint(5) == 1? TERM_RED : TERM_L_RED);
1510 		case GF_METEOR:		return (randint(3) == 1? TERM_RED : TERM_UMBER);
1511 		case GF_ICE:		return (randint(4) == 1? TERM_L_BLUE : TERM_WHITE);
1512 		case GF_INFERNO:
1513 		case GF_DETONATION:
1514 		case GF_ROCKET:		return (randint(6) < 4 ? TERM_L_RED : (randint(4) == 1 ? TERM_RED : TERM_L_UMBER));
1515 		case GF_NUKE:		return (mh_attr(2));
1516 		case GF_DISINTEGRATE:   return (randint(3) != 1 ? TERM_L_DARK : (randint(2) == 1 ? TERM_ORANGE : TERM_VIOLET));
1517 		case GF_PSI:		return (randint(5) != 1 ? (rand_int(2) ? (rand_int(2) ? TERM_YELLOW : TERM_L_BLUE) : 127) : TERM_WHITE);
1518 		/* new spell - the_sandman */
1519 		case GF_CURSE:		return (randint(2) == 1 ? TERM_DARKNESS : TERM_L_DARK);
1520 		case GF_OLD_DRAIN:	return (TERM_DARKNESS);
1521 		/* Druids stuff */
1522 		case GF_HEALINGCLOUD:	return (TERM_LITE);//return (randint(5) > 1 ? TERM_WHITE : TERM_L_BLUE);
1523 		case GF_WATERPOISON:	return (TERM_COLD);//return (randint(2) == 1 ? TERM_L_BLUE : (randint(2) == 1 ? TERM_BLUE : (randint(2) == 1 ? TERM_GREEN : TERM_L_GREEN)));
1524 		case GF_ICEPOISON:	return (TERM_SHAR);//return (randint(3) > 1 ? TERM_UMBER : (randint(2) == 1 ? TERM_GREEN : TERM_SLATE));
1525 		/* To remove some hacks? */
1526 		case GF_THUNDER:	return (randint(3) != 1 ? TERM_ELEC : (randint(2) == 1 ? TERM_YELLOW : TERM_LITE));
1527 		case GF_ANNIHILATION:	return (randint(2) == 1 ? TERM_DARKNESS : TERM_L_DARK);
1528 	}
1529 
1530 	/* Standard "color" */
1531 	return (TERM_WHITE);
1532 }
1533 
1534 /* returns whether a spell type's colours require server-side animation or not.
1535    (for efficient animations in process_effects()) - C. Blue */
spell_color_animation(int type)1536 bool spell_color_animation(int type)
1537 {
1538 	/* Hack -- fake monochrome */
1539 	if (!use_color) return FALSE;
1540 
1541 	/* Analyze */
1542 	switch (type)	/* colourful ToME ones :) */
1543 	{
1544 		case GF_MISSILE:	return FALSE;
1545 		case GF_ACID:		return FALSE;
1546 		case GF_ELEC:		return FALSE;
1547 		case GF_FIRE:		return FALSE;
1548 		case GF_COLD:		return FALSE;
1549 		case GF_POIS:		return FALSE;
1550 		case GF_UNBREATH:	return TRUE;//(randint(7)<3?TERM_L_GREEN:TERM_GREEN);
1551 //		case GF_HOLY_ORB:	return FALSE;
1552 		case GF_HOLY_ORB:	return TRUE;//(randint(6)==1?TERM_ORANGE:TERM_L_DARK);
1553 		case GF_HOLY_FIRE:	return TRUE;//(randint(3)!=1?TERM_ORANGE:(randint(2)==1?TERM_YELLOW:TERM_WHITE));
1554 		case GF_HELL_FIRE:	return TRUE;//(randint(5)==1?TERM_RED:TERM_L_DARK);
1555 		case GF_MANA:		return TRUE;//(randint(5)!=1?TERM_VIOLET:TERM_L_BLUE);
1556 		case GF_ARROW:		return FALSE;
1557 		case GF_WATER:		return TRUE;//(randint(4)==1?TERM_L_BLUE:TERM_BLUE);
1558 		case GF_WAVE:		return TRUE;//(randint(4)==1?TERM_L_BLUE:TERM_BLUE);
1559 		case GF_VAPOUR:		return TRUE;
1560 		case GF_NETHER_WEAK:
1561 		case GF_NETHER:		return TRUE;//(randint(4)==1?TERM_SLATE:TERM_L_DARK);
1562 		case GF_CHAOS:		return FALSE;
1563 		case GF_DISENCHANT:	return TRUE;//(randint(4)==1?TERM_ORANGE:TERM_BLUE;//TERM_L_BLUE:TERM_VIOLET);
1564 		case GF_NEXUS:		return TRUE;//(randint(5)<3?TERM_L_RED:TERM_VIOLET);
1565 		case GF_CONFUSION:	return FALSE;
1566 		case GF_SOUND:		return FALSE;//(randint(4)==1?TERM_VIOLET:TERM_WHITE);
1567 		case GF_SHARDS:		return FALSE;//(randint(5)<3?TERM_UMBER:TERM_SLATE);
1568 		case GF_FORCE:		return TRUE;//(randint(5)<3?TERM_L_WHITE:TERM_ORANGE);
1569 		case GF_INERTIA:	return TRUE;//(randint(5)<3?TERM_SLATE:TERM_L_WHITE);
1570 		case GF_GRAVITY:	return TRUE;//(randint(3)==1?TERM_L_UMBER:TERM_UMBER);
1571 		case GF_TIME:		return TRUE;//(randint(3)==1?TERM_GREEN:TERM_L_BLUE);
1572 		case GF_LITE_WEAK:	return FALSE;
1573 		case GF_LITE:		return FALSE;
1574 		case GF_DARK_WEAK:	return FALSE;
1575 		case GF_DARK:		return FALSE;
1576 		case GF_PLASMA:		return TRUE;//(randint(5)==1?TERM_RED:TERM_L_RED);
1577 		case GF_METEOR:		return TRUE;//(randint(3)==1?TERM_RED:TERM_UMBER);
1578 		case GF_ICE:		return TRUE;//(randint(4)==1?TERM_L_BLUE:TERM_WHITE);
1579 		case GF_INFERNO:
1580 		case GF_DETONATION:
1581 		case GF_ROCKET:		return TRUE;//(randint(6)<4?TERM_L_RED:(randint(4)==1?TERM_RED:TERM_L_UMBER));
1582 		case GF_NUKE:		return TRUE;//(mh_attr(2));
1583 		case GF_DISINTEGRATE:   return TRUE;//(randint(3)!=1?TERM_L_DARK:(randint(2)==1?TERM_VIOLET:TERM_L_ORANGE));//TERM_ORANGE:TERM_L_UMBER));
1584 		case GF_PSI:		return TRUE;//(randint(5)!=1?(rand_int(2)?(rand_int(2)?TERM_YELLOW:TERM_L_BLUE):127):TERM_WHITE);
1585 		/* new spell - the_sandman */
1586 		case GF_CURSE:		return TRUE;//(randint(2)==1?TERM_DARKNESS:TERM_L_DARK);
1587 		case GF_OLD_DRAIN:	return FALSE;
1588 		/* Druids stuff */
1589 		case GF_HEALINGCLOUD:	return FALSE;//return (randint(5)>1?TERM_WHITE:TERM_L_BLUE);
1590 		case GF_WATERPOISON:	return FALSE;//return (randint(2)==1?TERM_L_BLUE:(randint(2)==1?TERM_BLUE:(randint(2)==1?TERM_GREEN:TERM_L_GREEN)));
1591 		case GF_ICEPOISON:	return FALSE;//return (randint(3)>1?TERM_UMBER:(randint(2)==1?TERM_GREEN:TERM_SLATE));
1592 		/* To remove some hacks? */
1593 		case GF_THUNDER:	return TRUE;//(randint(3)!=1?TERM_ELEC:(randint(2)==1?TERM_YELLOW:TERM_LITE));
1594 		case GF_ANNIHILATION:	return TRUE;//(randint(2)==1?TERM_DARKNESS:TERM_L_DARK);
1595 	}
1596 
1597 	/* Standard "color" */
1598 	return FALSE;
1599 }
1600 #else
1601 /*
1602  * Return a color to use for the bolt/ball spells
1603  */
spell_color(int type)1604 byte spell_color(int type)
1605 {
1606 	/* Hack -- fake monochrome */
1607 	if (!use_color) return (TERM_WHITE);
1608 
1609 	/* Analyze */
1610 	switch (type)	/* colourful ToME ones :) */
1611 	{
1612 		case GF_MISSILE:	return (TERM_SLATE);
1613 		case GF_ACID:		return (TERM_ACID);
1614 		case GF_ELEC:		return (TERM_ELEC);
1615 		case GF_FIRE:		return (TERM_FIRE);
1616 		case GF_COLD:		return (TERM_COLD);
1617 		case GF_POIS:		return (TERM_POIS);
1618 		case GF_UNBREATH:	return (TERM_UNBREATH);
1619 //		case GF_HOLY_ORB:	return (TERM_L_DARK);
1620 		case GF_HOLY_ORB:	return (TERM_HOLYORB);
1621 		case GF_HOLY_FIRE:	return (TERM_HOLYFIRE);
1622 		case GF_HELL_FIRE:	return (TERM_HELLFIRE);
1623 		case GF_MANA:		return (TERM_MANA);
1624 		case GF_ARROW:		return (TERM_L_UMBER);
1625 		case GF_VAPOUR:		return (TERM_L_BLUE);//animate with some dark blue maybe?
1626 		case GF_WATER:		return (TERM_WATE);
1627 		case GF_WAVE:		return (TERM_WATE);
1628 		case GF_NETHER_WEAK:
1629 		case GF_NETHER:		return (TERM_NETH);
1630 		case GF_CHAOS:		return (TERM_MULTI);
1631 		case GF_DISENCHANT:	return (TERM_DISE);
1632 		case GF_NEXUS:		return (TERM_NEXU);
1633 		case GF_CONFUSION:	return (TERM_CONF);
1634 		case GF_SOUND:		return (TERM_SOUN);
1635 		case GF_SHARDS:		return (TERM_SHAR);
1636 		case GF_FORCE:		return (TERM_FORC);
1637 		case GF_INERTIA:	return (TERM_INER);
1638 		case GF_GRAVITY:	return (TERM_GRAV);
1639 		case GF_TIME:		return (TERM_TIME);
1640 		case GF_LITE_WEAK:	return (TERM_LITE);
1641 		case GF_LITE:		return (TERM_LITE);
1642 		case GF_DARK_WEAK:	return (TERM_DARKNESS);
1643 		case GF_DARK:		return (TERM_DARKNESS);
1644 		case GF_PLASMA:		return (TERM_PLAS);
1645 		case GF_METEOR:		return (TERM_METEOR);
1646 		case GF_ICE:		return (TERM_ICE);
1647 		case GF_INFERNO:
1648 		case GF_DETONATION:
1649 		case GF_ROCKET:		return (TERM_DETO);
1650 		case GF_NUKE:		return (TERM_NUKE);
1651 		case GF_DISINTEGRATE:   return (TERM_DISI);
1652 		case GF_PSI:		return (TERM_PSI);
1653 		/* new spell - the_sandman */
1654 		case GF_CURSE:		return (TERM_CURSE);
1655 		case GF_OLD_DRAIN:	return (TERM_DARKNESS);
1656 		/* Druids stuff */
1657 		case GF_HEALINGCLOUD:	return (TERM_LITE);//return (randint(5)>1?TERM_WHITE:TERM_L_BLUE);
1658 		case GF_WATERPOISON:	return (TERM_COLD);//return (randint(2)==1?TERM_L_BLUE:(randint(2)==1?TERM_BLUE:(randint(2)==1?TERM_GREEN:TERM_L_GREEN)));
1659 		case GF_ICEPOISON:	return (TERM_SHAR);//return (randint(3)>1?TERM_UMBER:(randint(2)==1?TERM_GREEN:TERM_SLATE));
1660 		/* To remove some hacks? */
1661 		case GF_THUNDER:	return (TERM_THUNDER);
1662 		case GF_ANNIHILATION:	return (TERM_ANNI);
1663 	}
1664 
1665 	/* Standard "color" */
1666 	return (TERM_WHITE);
1667 }
1668 #endif
1669 
1670 /*
1671  * Decreases players hit points and sets death flag if necessary
1672  *
1673  * XXX XXX XXX Invulnerability needs to be changed into a "shield"
1674  *
1675  * XXX XXX XXX Hack -- this function allows the user to save (or quit)
1676  * the game when he dies, since the "You die." message is shown before
1677  * setting the player to "dead".
1678  */
1679 /* Poison/Cut timed damages, curse damages etc can bypass the shield.
1680  * It's hack; in the future, this function should be called with flags
1681  * that tells 'what kind of damage'.
1682  */
1683 bool bypass_invuln = FALSE;
take_hit(int Ind,int damage,cptr hit_from,int Ind_attacker)1684 void take_hit(int Ind, int damage, cptr hit_from, int Ind_attacker) {
1685 	cptr hit_from_real = hit_from; /* non-hallucinated attacker */
1686 	player_type *p_ptr = Players[Ind];
1687 
1688 	// The "number" that the character is displayed as before the hit
1689 	int old_num, new_num;
1690 
1691 	/* Amulet of Immortality */
1692 	if (p_ptr->admin_invuln) return;
1693 
1694 	/* Heavenly invulnerability? */
1695 	if (p_ptr->martyr && !bypass_invuln) {
1696 		break_cloaking(Ind, 0); /* still notice! paranoia though, rogues can't use martyr */
1697 		return;
1698 	}
1699 
1700 	/* Paranoia */
1701 	if (p_ptr->death) return;
1702 
1703 	/* towns are safe-zones from ALL hostile actions - except blood bond */
1704 	if (IS_PLAYER(Ind_attacker)) {
1705 		if ((istown(&p_ptr->wpos) || istown(&Players[Ind_attacker]->wpos)) &&
1706 		    (!check_blood_bond(Ind_attacker, Ind) ||
1707 		     p_ptr->afk || Players[Ind_attacker]->afk))
1708 			return;
1709 	}
1710 
1711 	if (!p_ptr->no_alert) {
1712 		if (((p_ptr->alert_afk_dam && p_ptr->afk)
1713 #ifdef ALERT_OFFPANEL_DAM
1714 		    /* new: alert when we're off-panel (cmd_locate) */
1715 		    || (p_ptr->alert_offpanel_dam && (p_ptr->panel_row_old != p_ptr->panel_row || p_ptr->panel_col_old != p_ptr->panel_col))
1716 #endif
1717 		    )
1718 		    /* don't alert about 0-damage terrain effect */
1719 		    && (damage || -Ind_attacker != PROJECTOR_TERRAIN)
1720 #ifdef USE_SOUND_2010
1721 		    ) {
1722 			Send_warning_beep(Ind);
1723 			//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
1724 #else
1725 		    && p_ptr->paging == 0) {
1726 			p_ptr->paging = 1;
1727 #endif
1728 		}
1729 
1730 		/* warn if taking (continuous) damage while inside a store! */
1731 		if (p_ptr->store_num != -1) {
1732 #ifdef USE_SOUND_2010
1733 			Send_warning_beep(Ind);
1734 			//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
1735 #else
1736 			if (p_ptr->paging == 0) p_ptr->paging = 1;
1737 #endif
1738 			/* continuous-damage message only */
1739 			if (bypass_invuln) msg_print(Ind, "\377RWarning - you are taking damage!");
1740 		}
1741 	}
1742 
1743 	// The "number" that the character is displayed as before the hit
1744 	/* Now displays corresponding to mana amount if disruption shield
1745 	is acitavted (C. Blue) */
1746 /*	if (!p_ptr->tim_manashield)
1747 	{
1748 */		old_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
1749 		if (old_num >= 7) old_num = 10;
1750 /*	}
1751 	else if (p_ptr->msp > 0)
1752 	{
1753 
1754 		old_num = (p_ptr->csp * 95) / (p_ptr->msp*10);
1755 		if (old_num >= 7) old_num = 10;
1756 	} */
1757 
1758 	/* for MODE_PVP only: prevent easy fleeing from PvP encounter >=) */
1759 	if (IS_PLAYER(Ind_attacker) ||
1760 	    (!p_ptr->wpos.wx && !p_ptr->wpos.wy && p_ptr->wpos.wz == 1)) {
1761 		p_ptr->pvp_prevent_tele = PVP_COOLDOWN_TELEPORT;
1762 		p_ptr->redraw |= PR_DEPTH;
1763 	}
1764 
1765 	// This is probably unused
1766 	// int warning = (p_ptr->mhp * hitpoint_warn / 10);
1767 
1768 	/* Hack -- player is secured inside a store/house except in dungeons */
1769 	/* XXX make sure it doesn't "leak"!
1770 	 * Glitchy side-effect: Player stops suffering from poison/cuts while in a store!
1771 	 * ..to fix that, bypass_invuln check has been added. */
1772 	if (p_ptr->store_num != -1 && !p_ptr->wpos.wz && !bypass_invuln) return;
1773 
1774 	/* Silyl admin games -- only in totally safe environment! */
1775 	if (p_ptr->admin_set_defeat &&
1776 	    -Ind_attacker != PROJECTOR_TERRAIN &&
1777 	    ge_special_sector &&
1778 	    (p_ptr->wpos.wx == WPOS_ARENA_X && p_ptr->wpos.wy == WPOS_ARENA_Y &&
1779 	    p_ptr->wpos.wz == WPOS_ARENA_Z)) {
1780 		p_ptr->admin_set_defeat--;
1781 		p_ptr->chp = -1;
1782 		p_ptr->deathblow = 1;
1783 		break_cloaking(Ind, 0);
1784 		goto destined_defeat;
1785 	}
1786 
1787 	/* Disturb - except when in PvP! */
1788 	if (strcmp(hit_from, "life draining") &&
1789 	    !IS_PLAYER(Ind_attacker)
1790 	    /* hack: no longer disturb on crossing terrain that we're immune to: */
1791 	    && (damage || -Ind_attacker != PROJECTOR_TERRAIN))
1792 		disturb(Ind, 1, 0);
1793 
1794 	/* Mega-Hack -- Apply "invulnerability" */
1795 	if (p_ptr->invuln && (!bypass_invuln) && !p_ptr->invuln_applied) {
1796 		/* 1 in 2 chance to fully deflect the damage */
1797 		if (magik(40)) {
1798 			msg_print(Ind, "The attack is fully deflected by a magic shield.");
1799 			if (-Ind_attacker != PROJECTOR_TERRAIN) break_cloaking(Ind, 0);
1800 			return;
1801 		}
1802 
1803 		/* Otherwise damage is reduced by the shield */
1804 		damage = (damage + 1) / 2;
1805 	}
1806 
1807 	if (IS_PLAYER(Ind_attacker)) {
1808 		Players[Ind_attacker]->test_count++;
1809 		Players[Ind_attacker]->test_dam += damage;
1810 	}
1811 
1812 	/* Re allowed by evileye for power */
1813 #if 1
1814 	//if (p_ptr->tim_manashield)
1815 	if (p_ptr->tim_manashield && (!bypass_invuln)) {
1816 		if (p_ptr->csp > 0) {
1817 			int taken;
1818 
1819 			switch(p_ptr->pclass) {
1820 			case CLASS_MAGE:
1821 			taken = (damage * 2 ) / 2;//mana shield works with a ratio of SP<->damage points
1822 			break;
1823 			default:
1824 			taken = (damage * 2 ) / 1;
1825 			break;
1826 			}
1827 
1828 			if (p_ptr->csp < taken) {
1829 				switch(p_ptr->pclass) {
1830 				case CLASS_MAGE:
1831 				damage = ((taken - p_ptr->csp) / 2) * 2;
1832 				break;
1833 				default:
1834 				damage = ((taken - p_ptr->csp) / 2) * 1;
1835 				break;
1836 				}
1837 
1838 				p_ptr->csp = 0;
1839 				/* mana shield stops on empty mana! */
1840 				set_tim_manashield(Ind, 0);
1841 			} else {
1842 				damage = 0;
1843 				p_ptr->csp -= taken;
1844 			}
1845 
1846 			/* Display the spellpoints */
1847 			p_ptr->redraw |= (PR_MANA);
1848 		}
1849 	}
1850 #endif
1851 
1852 	/* Admin silly stuff */
1853 	if (IS_PLAYER(Ind_attacker) && Players[Ind_attacker]->admin_godly_strike) {
1854 		Players[Ind_attacker]->admin_godly_strike--;
1855 		damage = p_ptr->chp + 1;
1856 	}
1857 
1858 	/* Hurt the player */
1859 	p_ptr->chp -= damage;
1860 	p_ptr->deathblow = damage;
1861 
1862 	/* for cloaking as well as shadow running:
1863 	   floor damage (like in nether realm) ain't supposed to break it! - C. Blue */
1864 //both ifs should work properly.
1865 	if (-Ind_attacker != PROJECTOR_TERRAIN) break_cloaking(Ind, 0);
1866 //	if (strcmp(hit_from, "hazardous environment")) break_cloaking(Ind, 0);
1867 
1868 destined_defeat:
1869 
1870 	/* Update health bars */
1871 	update_health(0 - Ind);
1872 
1873 	/* Display the hitpoints */
1874 	p_ptr->redraw |= (PR_HP);
1875 
1876 	/* Figure out of if the player's "number" has changed */
1877 	/* Now displays corresponding to mana amount if disruption shield
1878 	is acitavted (C. Blue) */
1879 /*	if (!p_ptr->tim_manashield)
1880 	{
1881 */		new_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
1882 		if (new_num > TURN_CHAR_INTO_NUMBER) new_num = 10;
1883 /*	}
1884 	else
1885 	{
1886 		new_num = (p_ptr->csp * 95) / (p_ptr->msp*10);
1887 		if (new_num >= 7) new_num = 10;
1888 	}
1889 */
1890 	/* If so then refresh everyone's view of this player */
1891 	if (new_num != old_num)
1892 		everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
1893 
1894 	/* Window stuff */
1895 	p_ptr->window |= (PW_PLAYER);
1896 
1897 	/* Dead player */
1898 	if (p_ptr->chp < 0) {
1899 		if (IS_PLAYER(Ind_attacker)) {
1900 			if (check_blood_bond(Ind, Ind_attacker)) {
1901 				player_type *p2_ptr = Players[Ind_attacker];
1902 				p_ptr->chp = p_ptr->mhp;
1903 				p2_ptr->chp = p2_ptr->mhp;
1904 				p_ptr->csp = p_ptr->msp;
1905 				p2_ptr->csp = p2_ptr->msp;
1906 				p_ptr->redraw |= PR_HP | PR_MANA;
1907 				p2_ptr->redraw |= PR_HP | PR_MANA;
1908 
1909 				s_printf("BLOOD_BOND: %s won the blood bond against %s\n", p2_ptr->name, p_ptr->name);
1910 				msg_broadcast_format(0, "\374\377c*** %s won the blood bond against %s. ***", p2_ptr->name, p_ptr->name);
1911 
1912 				remove_hostility(Ind, p2_ptr->name);
1913 				remove_hostility(Ind_attacker, p_ptr->name);
1914 
1915 				remove_blood_bond(Ind, Ind_attacker);
1916 				remove_blood_bond(Ind_attacker, Ind);
1917 
1918 				target_set(Ind, 0);
1919 				target_set(Ind_attacker, 0);
1920 
1921 				/* Remove stun/KO */
1922 				set_stun(Ind, 0);
1923 				set_stun(Ind_attacker, 0);
1924 
1925 				teleport_player(Ind, 4, TRUE);
1926 
1927 				return;
1928 			}
1929 		/* get real killer (for log file and scoreboard) in case we're hallucinating */
1930 		} else if (p_ptr->image && IS_MONSTER(Ind_attacker)) {
1931 			/* get real monster name, in case we're hallucinating */
1932 			hit_from_real = r_name + race_inf(&m_list[-Ind_attacker])->name;
1933 		}
1934 
1935 		/* Note cause of death */
1936 		/* To preserve the players original (pre-ghost) cause
1937 		   of death, use died_from_list.  To preserve the original
1938 		   depth, use died_from_depth. */
1939 
1940 		(void)strcpy(p_ptr->died_from, hit_from); /* todo: blindness/no esp (fuzzy like for spell hits) */
1941 		(void)strcpy(p_ptr->really_died_from, hit_from_real);
1942 		if (!p_ptr->ghost) {
1943 			strcpy(p_ptr->died_from_list, hit_from_real);
1944 			p_ptr->died_from_depth = getlevel(&p_ptr->wpos);
1945 			/* Hack to remember total winning */
1946 			if (p_ptr->total_winner) strcat(p_ptr->died_from_list, "\001");
1947 		}
1948 
1949 		/* No longer a winner */
1950 //		p_ptr->total_winner = FALSE;
1951 
1952 		/* Note death */
1953 		p_ptr->death = TRUE;
1954 		p_ptr->deathblow = damage;
1955 
1956 		/* Dead */
1957 		return;
1958 	}
1959 
1960 	if (p_ptr->warning_rest != 3 && !p_ptr->warning_rest_cooldown
1961 	    && p_ptr->max_plv >= 3
1962 	    && p_ptr->chp * 10 / p_ptr->mhp <= 5) {
1963 		msg_print(Ind, "\374\377oHINT: Press \377RSHIFT+r\377o to rest, so your hit points will");
1964 		msg_print(Ind, "\374\377o      regenerate faster. (Also true for mana and stamina.)");
1965 		p_ptr->warning_rest++;
1966 		p_ptr->warning_rest_cooldown = 3;//minutes
1967 		acc_set_flags(p_ptr->accountname, ACC_WARN_REST, TRUE);
1968 		s_printf("warning_rest: %s\n", p_ptr->name);
1969 	}
1970 }
1971 
1972 
1973 /* Decrease player's sanity. This is a copy of the function above. */
1974 void take_sanity_hit(int Ind, int damage, cptr hit_from) {
1975 	player_type *p_ptr = Players[Ind];
1976 #if 0
1977 	int old_csane = p_ptr->csane;
1978 	int warning = (p_ptr->msane * hitpoint_warn / 10);
1979 #endif	// 0
1980 
1981 	/* Heavenly invulnerability? */
1982 	if (p_ptr->martyr && !bypass_invuln) return;
1983 
1984 	/* Amulet of Immortality */
1985 	if (p_ptr->admin_invuln) return;
1986 
1987 	/* Paranoia */
1988 	if (p_ptr->death) return;
1989 
1990 	/* Hack -- player is secured inside a store/house except in dungeons */
1991 	if (p_ptr->store_num != -1 && !p_ptr->wpos.wz && !bypass_invuln) return;
1992 
1993 	/* For 'Arena Monster Challenge' event: */
1994 	if (safe_area(Ind)) {
1995 		msg_print(Ind, "\377wYou feel disturbed, but the feeling passes.");
1996 		return;
1997 	}
1998 
1999 #if 0 //Ind_attacker not available - players cannot cast insanity-draining effects on other players anyway
2000 	/* towns are safe-zones from ALL hostile actions - except blood bond */
2001 	if (IS_PLAYER(Ind_attacker)) {
2002 		if ((istown(&p_ptr->wpos) || istown(&Players[Ind_attacker]->wpos)) &&
2003 		    (!check_blood_bond(Ind_attacker, Ind) ||
2004 		     p_ptr->afk || Players[Ind_attacker]->afk))
2005 			return;
2006 	}
2007 #endif
2008 
2009 	if (((p_ptr->alert_afk_dam && p_ptr->afk)
2010 #ifdef ALERT_OFFPANEL_DAM
2011 	    /* new: alert when we're off-panel (cmd_locate) */
2012 	    || (p_ptr->alert_offpanel_dam && (p_ptr->panel_row_old != p_ptr->panel_row || p_ptr->panel_col_old != p_ptr->panel_col))
2013 #endif
2014 	    )
2015 #ifdef USE_SOUND_2010
2016 	    ) {
2017 		Send_warning_beep(Ind);
2018 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
2019 #else
2020 	    && p_ptr->paging == 0) {
2021 		p_ptr->paging = 1;
2022 #endif
2023 	}
2024 
2025 	/* warn if taking (continuous) damage while inside a store! */
2026 	if (p_ptr->store_num != -1) {
2027 #ifdef USE_SOUND_2010
2028 		Send_warning_beep(Ind);
2029 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
2030 #else
2031 		if (p_ptr->paging == 0) p_ptr->paging = 1;
2032 #endif
2033 		//there's already a message given, usually..
2034 		//msg_print(Ind, "\377RWarning - you are taking sanity damage!");
2035 	}
2036 
2037 #ifdef USE_SOUND_2010
2038 	sound(Ind, "insanity", NULL, SFX_TYPE_MISC, FALSE);
2039 #endif
2040 
2041 	/* Mega-Hack -- Apply "invulnerability" */
2042 	if (p_ptr->invuln && (!bypass_invuln) && !p_ptr->invuln_applied) {
2043 		/* 1 in 2 chance to fully deflect the damage */
2044 		if (magik(40)) {
2045 			msg_print(Ind, "The attack is fully deflected by a magic shield.");
2046 			return;
2047 		}
2048 
2049 		/* Otherwise damage is reduced by the shield */
2050 		damage = (damage + 1) / 2;
2051 	}
2052 
2053 
2054 	/* Disturb */
2055 	disturb(Ind, 1, 0);
2056 
2057 	/* Having WEIRD_MIND or EMPTY_MIND form helps, as well as being mindcrafter */
2058 	if(p_ptr->reduce_insanity == 1) damage = (damage * (9 + rand_int(4))) / 12;
2059 	if(p_ptr->reduce_insanity == 2) damage = (damage * (6 + rand_int(7))) / 12;
2060 
2061 	/* Hurt the player */
2062 	p_ptr->csane -= damage;
2063 
2064 	/* Display the hitpoints */
2065 	p_ptr->redraw |= (PR_SANITY);
2066 
2067 	/* Window stuff */
2068 	p_ptr->window |= (PW_PLAYER);
2069 
2070 	/* Dead player */
2071 	if (p_ptr->csane < 0) {
2072 		/* Hack -- Note death */
2073 		msg_print(Ind, "\377vYou turn into an unthinking vegetable.");
2074 /*		msg_print(Ind, "\377RYou die.");
2075 		msg_print(Ind, NULL); - already in xtra2.c (C. Blue)*/
2076 
2077 
2078 		/* Note cause of death */
2079 		/* To preserve the players original (pre-ghost) cause
2080 		   of death, use died_from_list.  To preserve the original
2081 		   depth, use died_from_depth. */
2082 
2083 		(void)strcpy(p_ptr->died_from, "insanity");
2084 		(void)strcpy(p_ptr->really_died_from, hit_from);
2085 		if (!p_ptr->ghost) {
2086 			strcpy(p_ptr->died_from_list, "insanity");
2087 			p_ptr->died_from_depth = getlevel(&p_ptr->wpos);
2088 			/* Hack to remember total winning */
2089 			if (p_ptr->total_winner) strcat(p_ptr->died_from_list, "\001");
2090 		}
2091 
2092 		/* No longer a winner */
2093 //		p_ptr->total_winner = FALSE;
2094 
2095 		/* Note death */
2096 		p_ptr->death = TRUE;
2097 		p_ptr->deathblow = damage;
2098 
2099 		/* This way, player dies without becoming a ghost. */
2100 //		ptr->ghost = 1;
2101 
2102 		/* Dead */
2103 		break_cloaking(Ind, 0);
2104 		break_shadow_running(Ind);
2105 		stop_precision(Ind);
2106 		stop_shooting_till_kill(Ind);
2107 		return;
2108 	}
2109 
2110 	/* Insanity warning (better message needed!) */
2111 	if (p_ptr->csane < p_ptr->msane / 8) {
2112 		/* Message */
2113 		msg_print(Ind, "\377fYou can hardly suppress screaming out insane laughters!");
2114 		msg_print(Ind, NULL);
2115 		break_cloaking(Ind, 0);
2116 		break_shadow_running(Ind);
2117 		stop_precision(Ind);
2118 	} else if (p_ptr->csane < p_ptr->msane / 4) {
2119 		/* Message */
2120 		msg_print(Ind, "\377RYou feel severly disturbed and paranoid..");
2121 		msg_print(Ind, NULL);
2122 		stop_precision(Ind);
2123 	} else if (p_ptr->csane < p_ptr->msane / 2) {
2124 		/* Message */
2125 		msg_print(Ind, "\377rYou feel insanity creep into your mind..");
2126 		msg_print(Ind, NULL);
2127 	}
2128 }
2129 
2130 /* Decrease player's exp. This is another copy of the function above.
2131  * if mode is 'TRUE', it's permanent.
2132  * if fatal, player dies if runs out of exp.
2133  *
2134  * if not permanent nor fatal, use lose_exp instead.
2135  * - Jir -
2136  */
2137 void take_xp_hit(int Ind, int damage, cptr hit_from, bool mode, bool fatal, bool disturb) {
2138 	player_type *p_ptr = Players[Ind];
2139 
2140 	/* Amulet of Immortality */
2141 	if (p_ptr->admin_invuln) return;
2142 
2143 	/* Paranoia */
2144 	if (p_ptr->death) return;
2145 
2146 	if (disturb) {
2147 		break_cloaking(Ind, 0);
2148 		stop_precision(Ind);
2149 	}
2150 
2151 	if (p_ptr->lev == 99) {
2152 		//msg_print(Ind, "You are impervious to life force drain!");
2153 		return;
2154 	}
2155 
2156 	/* arena is safe, although this may be doubtful */
2157 	if (safe_area(Ind)) return;
2158 
2159 #if 0
2160 	/* Hack -- player is secured inside a store/house except in dungeons */
2161 	if (p_ptr->store_num != -1 && !p_ptr->wpos.wz && !bypass_invuln) return;
2162 
2163 	if (((p_ptr->alert_afk_dam && p_ptr->afk)
2164  #ifdef ALERT_OFFPANEL_DAM
2165 	    /* new: alert when we're off-panel (cmd_locate) */
2166 	    || (p_ptr->alert_offpanel_dam && (p_ptr->panel_row_old != p_ptr->panel_row || p_ptr->panel_col_old != p_ptr->panel_col))
2167  #endif
2168 	    )
2169  #ifdef USE_SOUND_2010
2170 	    ) {
2171 		Send_warning_beep(Ind);
2172 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
2173  #else
2174 	    && p_ptr->paging == 0) {
2175 		p_ptr->paging = 1;
2176  #endif
2177 	}
2178 
2179 	/* warn if taking (continuous) damage while inside a store! */
2180 	if (p_ptr->store_num != -1) {
2181  #ifdef USE_SOUND_2010
2182 		Send_warning_beep(Ind);
2183 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
2184  #else
2185 		if (p_ptr->paging == 0) p_ptr->paging = 1;
2186  #endif
2187 		/* continuous-damage message only */
2188 		if (bypass_invuln) msg_print(Ind, "\377RWarning - your experience is getting drained!");
2189 	}
2190 #endif
2191 
2192 	/* Disturb */
2193 //	disturb(Ind, 1, 0);
2194 
2195 	/* Hurt the player */
2196 	p_ptr->exp -= damage;
2197 	if (mode && p_ptr->max_exp) {
2198 		p_ptr->max_exp -= damage;
2199 		/* don't reduce max_exp to zero, in case someone insane
2200 		   tries to cheeze events requiring 0 exp this way ;) */
2201 		if (p_ptr->max_exp < 1) p_ptr->max_exp = 1;
2202 	}
2203 
2204 	check_experience(Ind);
2205 
2206 	/* Dead player */
2207 	if (fatal && p_ptr->exp == 0) {
2208 		/* Hack -- Note death */
2209 /*		msg_print(Ind, "\377RYou die.");
2210 		msg_print(Ind, NULL); - what's so 'hacky' about this?
2211 		It's in xtra2.c anyways, so gone here now. C. Blue */
2212 
2213 		/* Note cause of death */
2214 		/* To preserve the players original (pre-ghost) cause
2215 		   of death, use died_from_list.  To preserve the original
2216 		   depth, use died_from_depth. */
2217 
2218 		(void)strcpy(p_ptr->died_from, hit_from);
2219 		if (!p_ptr->ghost) {
2220 			strcpy(p_ptr->died_from_list, hit_from);
2221 			p_ptr->died_from_depth = getlevel(&p_ptr->wpos);
2222 			/* Hack to remember total winning */
2223 			if (p_ptr->total_winner) strcat(p_ptr->died_from_list, "\001");
2224 		}
2225 
2226 		/* No longer a winner */
2227 //		p_ptr->total_winner = FALSE;
2228 
2229 		/* Note death */
2230 		p_ptr->death = TRUE;
2231 		p_ptr->deathblow = 0;
2232 
2233 		/* Dead */
2234 		break_cloaking(Ind, 0);
2235 		break_shadow_running(Ind);
2236 		stop_precision(Ind);
2237 		stop_shooting_till_kill(Ind);
2238 		return;
2239 	}
2240 }
2241 
2242 
2243 
2244 /*
2245  * Note that amulets, rods, and high-level spell books are immune
2246  * to "inventory damage" of any kind.  Also sling ammo and shovels.
2247  */
2248 
2249 
2250 /*
2251  * Does a given class of objects (usually) hate acid?
2252  * Note that acid can either melt or corrode something.
2253  */
2254 static bool hates_acid(object_type *o_ptr)
2255 {
2256 	/* Analyze the type */
2257 	switch (o_ptr->tval) {
2258 	/* Wearable items */
2259 	case TV_ARROW:
2260 	case TV_BOLT:
2261 	case TV_BOW:
2262 	case TV_BOOMERANG:
2263 	case TV_SWORD:
2264 	case TV_BLUNT:
2265 	case TV_POLEARM:
2266 	case TV_AXE:
2267 	case TV_HELM:
2268 	case TV_CROWN:
2269 	case TV_SHIELD:
2270 	case TV_BOOTS:
2271 	case TV_GLOVES:
2272 	case TV_CLOAK:
2273 	case TV_SOFT_ARMOR:
2274 	case TV_HARD_ARMOR:
2275 	case TV_DRAG_ARMOR:
2276 
2277 	case TV_LITE:
2278 		return (TRUE);
2279 
2280 	/* Staffs/Scrolls are wood/paper */
2281 	case TV_STAFF:
2282 	case TV_SCROLL:
2283 	case TV_PARCHMENT:
2284 	case TV_BOOK:
2285 		return (TRUE);
2286 
2287 	/* Ouch */
2288 	case TV_CHEST:
2289 		return (TRUE);
2290 
2291 	/* Junk is useless */
2292 	case TV_SKELETON:
2293 	case TV_JUNK:
2294 		return (TRUE);
2295 	}
2296 
2297 	return (FALSE);
2298 }
2299 
2300 /*
2301  * Does a given object (usually) hate electricity?
2302  */
2303 static bool hates_elec(object_type *o_ptr)
2304 {
2305 	switch (o_ptr->tval) {
2306 	case TV_RING:
2307 	case TV_WAND:
2308 		return (TRUE);
2309 	}
2310 
2311 	return (FALSE);
2312 }
2313 
2314 /*
2315  * Does a given object (usually) hate fire?
2316  * Blunt/Polearm weapons have wooden shafts.
2317  * Arrows/Bows are mostly wooden.
2318  */
2319 bool hates_fire(object_type *o_ptr)
2320 {
2321 	/* Analyze the type */
2322 	switch (o_ptr->tval) {
2323 	/* Wearable */
2324 	case TV_GLOVES:
2325 		if (o_ptr->sval == SV_SET_OF_GAUNTLETS) return FALSE;
2326 	case TV_ARROW:
2327 	case TV_BOW:
2328 	case TV_BLUNT:
2329 	case TV_POLEARM:
2330 	case TV_AXE:
2331 	case TV_BOOTS:
2332 	case TV_CLOAK:
2333 	case TV_SOFT_ARMOR:
2334 		return (TRUE);
2335 	case TV_HELM:
2336 		if (o_ptr->sval == SV_HARD_LEATHER_CAP || o_ptr->sval == SV_CLOTH_CAP) return TRUE;
2337 		return FALSE;
2338 	case TV_BOOMERANG:
2339 		if (o_ptr->sval == SV_BOOM_S_METAL || o_ptr->sval == SV_BOOM_METAL) return(FALSE);
2340 		return (TRUE);
2341 
2342 	/* Chests */
2343 	case TV_CHEST:
2344 		if (o_ptr->sval == SV_CHEST_RUINED ||
2345 		    o_ptr->sval == SV_CHEST_SMALL_WOODEN || o_ptr->sval == SV_CHEST_LARGE_WOODEN) return(TRUE);
2346 		return (FALSE);
2347 
2348 	/* Staffs/Scrolls burn */
2349 	case TV_STAFF:
2350 	case TV_SCROLL:
2351 	case TV_PARCHMENT:
2352 	case TV_BOOK:
2353 		return (TRUE);
2354 
2355 	/* Potions evaporate */
2356 	case TV_POTION:
2357 	case TV_POTION2:
2358 	case TV_FLASK:
2359 	case TV_BOTTLE: //just melts
2360 		return (TRUE);
2361 
2362 	/* Junk, partially */
2363 	case TV_SKELETON:
2364 		return TRUE;
2365 	}
2366 
2367 	return (FALSE);
2368 }
2369 
2370 /*
2371  * Does a given object (usually) hate cold?
2372  */
2373 static bool hates_cold(object_type *o_ptr)
2374 {
2375 	switch (o_ptr->tval) {
2376 	case TV_POTION:
2377 	case TV_POTION2:
2378 	case TV_FLASK:
2379 	//case TV_BOTTLE:  <- empty! unlike potions..
2380 		return (TRUE);
2381 	}
2382 
2383 	return (FALSE);
2384 }
2385 
2386 /*
2387  * Does a given object (usually) hate impact?
2388  */
2389 static bool hates_impact(object_type *o_ptr)
2390 {
2391 	switch (o_ptr->tval) {
2392 	case TV_POTION:
2393 	case TV_POTION2:
2394 	case TV_FLASK:
2395 	case TV_BOTTLE:
2396 	case TV_EGG:
2397 		return (TRUE);
2398 	}
2399 
2400 	return (FALSE);
2401 }
2402 
2403 /*
2404  * Does a given object (usually) hate water?
2405  */
2406 bool hates_water(object_type *o_ptr)
2407 {
2408 	switch (o_ptr->tval) {
2409 //	case TV_POTION:		/* dilutes */
2410 //	case TV_POTION2:	/* dilutes */
2411 	case TV_SCROLL:		/* fades */
2412 	case TV_BOOK:
2413 		return (TRUE);
2414 	}
2415 
2416 	return (FALSE);
2417 }
2418 
2419 /*
2420  * Does a given object rust from water? (for equip_damage()) - C. Blue
2421  */
2422 static bool can_rust(object_type *o_ptr)
2423 {
2424 	switch (o_ptr->tval) {
2425 #if 0
2426 	case TV_GLOVES: if (o_ptr->sval == SV_LEATHER_GLOVES || o_ptr->sval == SV_SET_OF_ELVEN_GLOVES) return FALSE;
2427 	case TV_BOOMERANG: if (o_ptr->sval == SV_BOOM_WOOD || o_ptr->sval == SV_BOOM_S_WOOD) return(FALSE); else return(TRUE);
2428 	case TV_CROWN: if (o_ptr->sval == SV_IRON_CROWN) return(TRUE); else return(FALSE);
2429 	case TV_SHIELD: if (o_ptr->sval == SV_SMALL_LEATHER_SHIELD || o_ptr->sval == SV_LARGE_LEATHER_SHIELD) return(FALSE); else return(TRUE);
2430 	case TV_HARD_ARMOR: if (o_ptr->sval == SV_MITHRIL_CHAIN_MAIL || o_ptr->sval == SV_MITHRIL_PLATE_MAIL || o_ptr->sval == SV_ADAMANTITE_PLATE_MAIL) return (FALSE); else return(TRUE);
2431 	case TV_HELM: if (o_ptr->sval == SV_HARD_LEATHER_CAP) return(FALSE); else return(TRUE);
2432 #else
2433 	case TV_GLOVES:
2434 	case TV_BOOMERANG:
2435 	case TV_CROWN:
2436 	case TV_SHIELD:
2437 	case TV_HARD_ARMOR:
2438 	case TV_HELM:
2439 #endif
2440 	case TV_SWORD:
2441 // :)	case TV_BLUNT:
2442 	case TV_POLEARM:
2443 	case TV_AXE:
2444 		return (TRUE);
2445 	}
2446 
2447 	return (FALSE);
2448 }
2449 
2450 
2451 
2452 /*
2453  * Melt something
2454  */
2455 static int set_acid_destroy(object_type *o_ptr)
2456 {
2457 	u32b f1, f2, f3, f4, f5, f6, esp;
2458 
2459 	if (!hates_acid(o_ptr)) return (FALSE);
2460 	/* Extract the flags */
2461 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2462 	if (f3 & TR3_IGNORE_ACID) return (FALSE);
2463 	return (TRUE);
2464 }
2465 
2466 /*
2467  * Electrical damage
2468  */
2469 static int set_elec_destroy(object_type *o_ptr)
2470 {
2471 	u32b f1, f2, f3, f4, f5, f6, esp;
2472 
2473 	if (!hates_elec(o_ptr)) return (FALSE);
2474 	/* Extract the flags */
2475 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2476 	if (f3 & TR3_IGNORE_ELEC) return (FALSE);
2477 	return (TRUE);
2478 }
2479 
2480 /*
2481  * Burn something
2482  */
2483 static int set_fire_destroy(object_type *o_ptr)
2484 {
2485 	u32b f1, f2, f3, f4, f5, f6, esp;
2486 
2487 	if (!hates_fire(o_ptr)) return (FALSE);
2488 	/* Extract the flags */
2489 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2490 	if (f3 & TR3_IGNORE_FIRE) return (FALSE);
2491 	return (TRUE);
2492 }
2493 
2494 /*
2495  * Freeze things
2496  */
2497 int set_cold_destroy(object_type *o_ptr)
2498 {
2499 	u32b f1, f2, f3, f4, f5, f6, esp;
2500 
2501 	if (!hates_cold(o_ptr)) return (FALSE);
2502 	/* Extract the flags */
2503 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2504 	if (f3 & TR3_IGNORE_COLD) return (FALSE);
2505 	return (TRUE);
2506 }
2507 
2508 /*
2509  * Crash things
2510  */
2511 int set_impact_destroy(object_type *o_ptr)
2512 {
2513 	u32b f1, f2, f3, f4, f5, f6, esp;
2514 
2515 	if (!hates_impact(o_ptr)) return (FALSE);
2516 	/* Extract the flags */
2517 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2518 	/* Hack -- borrow flag */
2519 //	if (f3 & TR3_IGNORE_COLD) return (FALSE);
2520 	return (TRUE);
2521 }
2522 
2523 /*
2524  * Soak something
2525  */
2526 int set_water_destroy(object_type *o_ptr)
2527 {
2528 	u32b f1, f2, f3, f4, f5, f6, esp;
2529 
2530 	if (!hates_water(o_ptr)) return (FALSE);
2531 	/* Extract the flags */
2532 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2533 	if (f5 & TR5_IGNORE_WATER) return (FALSE);
2534 	return (TRUE);
2535 }
2536 
2537 /*
2538  * Rust
2539  */
2540 static int set_rust_destroy(object_type *o_ptr)
2541 {
2542 	u32b f1, f2, f3, f4, f5, f6, esp;
2543 
2544 	if (!can_rust(o_ptr)) return (FALSE);
2545 	/* Extract the flags */
2546 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2547 	if ((f3 & TR3_IGNORE_ACID) || (f5 & TR5_IGNORE_WATER)) return (FALSE);
2548 	return (TRUE);
2549 }
2550 
2551 /*
2552  * Burn/Crash things
2553  */
2554 /*
2555  * Does a given object (usually) hate GF_ROCKET damage,
2556  * ie hates_fire() or hates_impact()?
2557  * (Note: Add shards too in case hates_shards() is ever added to the game)
2558  */
2559 int set_rocket_destroy(object_type *o_ptr)
2560 {
2561 	u32b f1, f2, f3, f4, f5, f6, esp;
2562 
2563 	if (!hates_impact(o_ptr)) {
2564 		if (!hates_fire(o_ptr)) return (FALSE);
2565 		/* Extract the flags */
2566 		object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2567 		if (f3 & TR3_IGNORE_FIRE) return (FALSE);
2568 	}
2569 	return (TRUE);
2570 }
2571 
2572 /*
2573  * Every things
2574  */
2575 int set_all_destroy(object_type *o_ptr)
2576 {
2577 	if (artifact_p(o_ptr)) return (FALSE);
2578 //	if (is_realm_book(o_ptr) && o_ptr->sval >= SV_BOOK_MIN_GOOD) return (FALSE);
2579 	if (is_realm_book(o_ptr)) {
2580 		u32b f1, f2, f3, f4, f5, f6, esp;
2581 		object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2582 		/* Hack^2 -- use this as a sign of being 'high books' */
2583 		if (f3 & TR3_IGNORE_ELEC) return (FALSE);
2584 	}
2585 	return (TRUE);
2586 }
2587 
2588 
2589 
2590 /*
2591  * This seems like a pretty standard "typedef"
2592  */
2593 //typedef int (*inven_func)(object_type *);
2594 
2595 /*
2596  * Destroys a type of item on a given percent chance
2597  * Note that missiles are no longer necessarily all destroyed
2598  * Destruction taken from "melee.c" code for "stealing".
2599  * Returns number of items destroyed.
2600  */
2601 int inven_damage(int Ind, inven_func typ, int perc) {
2602 	player_type	*p_ptr = Players[Ind];
2603 	int		i, j, k, amt;
2604 	object_type	*o_ptr;
2605 	char		o_name[ONAME_LEN];
2606 
2607 	if (safe_area(Ind)) return(FALSE);
2608 	/* secret dungeon master is unaffected (potion shatter effects might be bad) */
2609 	if (p_ptr->admin_dm) return(FALSE);
2610 
2611 	/* Count the casualties */
2612 	k = 0;
2613 
2614 	/* Scan through the slots backwards */
2615 	for (i = 0; i < INVEN_TOTAL; i++) {
2616 		/* Hack -- equipments are harder to be harmed */
2617 		if (i >= INVEN_PACK && i != INVEN_AMMO && !magik(HARM_EQUIP_CHANCE))
2618 			continue;
2619 
2620 		/* Get the item in that slot */
2621 		o_ptr = &p_ptr->inventory[i];
2622 
2623 		/* Hack -- for now, skip artifacts */
2624 		if (artifact_p(o_ptr)) continue;
2625 
2626 		/* Give this item slot a shot at death */
2627 		if ((*typ)(o_ptr)) {
2628 			/* Count the casualties */
2629 			for (amt = j = 0; j < o_ptr->number; ++j) {
2630 				if (rand_int(100) < perc) amt++;
2631 			}
2632 
2633 			/* Some casualities */
2634 			if (amt) {
2635 				/* Get a description */
2636 				object_desc(Ind, o_name, o_ptr, FALSE, 3);
2637 
2638 				/* Message */
2639 				msg_format(Ind, "\376\377o%sour %s (%c) %s destroyed!",
2640 						   ((o_ptr->number > 1) ?
2641 							((amt == o_ptr->number) ? "All of y" :
2642 							 (amt > 1 ? "Some of y" : "One of y")) : "Y"),
2643 						   o_name, index_to_label(i),
2644 						   ((amt > 1) ? "were" : "was"));
2645 
2646 				/* Potions smash open */
2647 				if (k_info[o_ptr->k_idx].tval == TV_POTION &&
2648 					typ != set_water_destroy)	/* MEGAHACK */
2649 //					&& typ != set_cold_destroy)
2650 				{
2651 //					(void)potion_smash_effect(0, &p_ptr->wpos, p_ptr->py, p_ptr->px, o_ptr->sval);
2652 					bypass_invuln = TRUE;
2653 					(void)potion_smash_effect(PROJECTOR_POTION, &p_ptr->wpos, p_ptr->py, p_ptr->px, o_ptr->sval);
2654 					bypass_invuln = FALSE;
2655 				}
2656 
2657 				/* Destroy "amt" items */
2658 				if (o_ptr->tval == TV_WAND) (void)divide_charged_item(o_ptr, amt);
2659 				inven_item_increase(Ind, i, -amt);
2660 				inven_item_optimize(Ind, i);
2661 
2662 				/* Count the casualties */
2663 				k += amt;
2664 			}
2665 		}
2666 	}
2667 
2668 	/* Return the casualty count */
2669 	return (k);
2670 }
2671 
2672 
2673 
2674 
2675 /*
2676  * Acid, water or fire has hit the player, attempt to affect some armor. - C. Blue
2677  * Note that the "base armor" of an object never changes.
2678  * If any armor is damaged (or resists), the player takes less damage. <- not implemented atm
2679  */
2680 /* Hack -- 'water' means it was water damage (and not acid).
2681  * TODO: add IGNORE_WATER flags */
2682 int equip_damage(int Ind, int typ) {
2683 	player_type	*p_ptr = Players[Ind];
2684 	object_type	*o_ptr = NULL;
2685 	char		o_name[ONAME_LEN];
2686 	int		shield_bonus = 0;
2687 	u32b dummy, f2, f5;
2688 
2689 	if (safe_area(Ind)) return(FALSE);
2690 	if (p_ptr->admin_dm) return(FALSE);
2691 
2692 	/* Pick a (possibly empty) inventory slot */
2693 #if !defined(NEW_SHIELDS_NO_AC) || !defined(USE_NEW_SHIELDS)
2694 //	switch (rand_int(is_weapon(p_ptr->inventory[INVEN_ARM].tval) ? 5 : 6)) { /* in case of DUAL_WIELD */
2695 	switch (rand_int(p_ptr->inventory[INVEN_ARM].tval == TV_SHIELD ? 6 : 5)) { /* in case of DUAL_WIELD */
2696 #else
2697 	switch (rand_int(5)) {
2698 #endif
2699 	case 0: o_ptr = &p_ptr->inventory[INVEN_BODY]; break;
2700 	case 1: o_ptr = &p_ptr->inventory[INVEN_OUTER]; break;
2701 	case 2: o_ptr = &p_ptr->inventory[INVEN_HANDS]; break;
2702 	case 3: o_ptr = &p_ptr->inventory[INVEN_HEAD]; break;
2703 	case 4: o_ptr = &p_ptr->inventory[INVEN_FEET]; break;
2704 	case 5: o_ptr = &p_ptr->inventory[INVEN_ARM];
2705 #ifdef USE_NEW_SHIELDS
2706 		shield_bonus = o_ptr->to_a;
2707 #endif
2708 		break;
2709 	}
2710 
2711 	/* Nothing to damage */
2712 	if (!o_ptr->k_idx) return (FALSE);
2713 
2714 	switch (typ) {
2715 	case GF_WATER:
2716 		if (!set_rust_destroy(o_ptr)) return(FALSE); else break; /* for some equipped items set_rust_destroy and set_water_destroy may be different */
2717 	case GF_ACID:
2718 		if (!set_acid_destroy(o_ptr)) return(FALSE); else break;
2719 	case GF_FIRE:
2720 		if (!set_fire_destroy(o_ptr)) return(FALSE); else break;
2721 	default: return(FALSE);
2722 	}
2723 
2724 	/* hack: not disenchantable -> cannot be damaged either */
2725 	object_flags(o_ptr, &dummy, &f2, &dummy, &dummy, &f5, &dummy, &dummy);
2726 	if ((f2 & TR2_RES_DISEN) || (f5 & TR5_IGNORE_DISEN)) return FALSE;
2727 
2728 	/* No damage left to be done */
2729 	if (o_ptr->ac + o_ptr->to_a + shield_bonus <= 0) return (FALSE);
2730 
2731 	/* Describe */
2732 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
2733 
2734 	/* Message */
2735 	msg_format(Ind, "\376\377oYour %s is damaged!", o_name);
2736 
2737 	/* Damage the item */
2738 	o_ptr->to_a--;
2739 
2740 	/* Calculate bonuses */
2741 	p_ptr->update |= (PU_BONUS);
2742 
2743 	/* Window stuff */
2744 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
2745 
2746 	/* Item was damaged */
2747 	return (TRUE);
2748 }
2749 
2750 /*
2751  * Acid or water has hit the player but he blocked it. Damage the shield! - C. Blue
2752  * Note that the "base armor" of an object never changes.
2753  */
2754 #ifndef NEW_SHIELDS_NO_AC
2755 int shield_takes_damage(int Ind, int typ) {
2756 	player_type	*p_ptr = Players[Ind];
2757 	object_type	*o_ptr = &p_ptr->inventory[INVEN_ARM];
2758 	char		o_name[ONAME_LEN];
2759 	u32b dummy, f2, f5;
2760 
2761 	if (safe_area(Ind)) return(FALSE);
2762 	if (p_ptr->admin_dm) return(FALSE);
2763 
2764 	/* Nothing to damage */
2765 	if (!o_ptr->k_idx) return (FALSE);
2766 
2767 	switch (typ) {
2768 	case GF_WATER:
2769 		if (p_ptr->immune_water || !set_rust_destroy(o_ptr))
2770 			return(FALSE);
2771 		else break; /* for some equipped items set_rust_destroy and set_water_destroy may be different */
2772 	case GF_ACID:
2773 		if (p_ptr->immune_acid || !set_acid_destroy(o_ptr))
2774 			return(FALSE);
2775 		else break;
2776 	case GF_FIRE:
2777 		if (p_ptr->immune_fire || !set_fire_destroy(o_ptr))
2778 			return(FALSE);
2779 		else break;
2780 	default: return(FALSE);
2781 	}
2782 
2783 	/* hack: not disenchantable -> cannot be damaged either */
2784 	object_flags(o_ptr, &dummy, &f2, &dummy, &dummy, &f5, &dummy, &dummy);
2785 	if ((f2 & TR2_RES_DISEN) || (f5 & TR5_IGNORE_DISEN)) return FALSE;
2786 
2787 	/* No damage left to be done */
2788  #ifdef USE_NEW_SHIELDS
2789 	if (o_ptr->ac + o_ptr->to_a * 2 <= 0) return (FALSE);
2790  #else
2791 	if (o_ptr->ac + o_ptr->to_a <= 0) return (FALSE);
2792  #endif
2793 
2794 	/* Describe */
2795 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
2796 
2797 	/* Message */
2798 	msg_format(Ind, "\376\377oYour %s is damaged!", o_name);
2799 
2800 	/* Damage the item */
2801 	o_ptr->to_a--;
2802 
2803 	/* Calculate bonuses */
2804 	p_ptr->update |= (PU_BONUS);
2805 
2806 	/* Window stuff */
2807 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
2808 
2809 	/* Item was damaged */
2810 	return (TRUE);
2811 }
2812 #endif
2813 
2814 int weapon_takes_damage(int Ind, int typ, int slot) {
2815 	player_type	*p_ptr = Players[Ind];
2816 	object_type	*o_ptr = &p_ptr->inventory[slot];
2817 	char		o_name[ONAME_LEN];
2818 	u32b dummy, f2, f5;
2819 
2820 	if (safe_area(Ind)) return(FALSE);
2821 	if (p_ptr->admin_dm) return(FALSE);
2822 
2823 	/* Nothing to damage */
2824 	if (!o_ptr->k_idx) return (FALSE);
2825 
2826 	switch (typ) {
2827 	case GF_WATER:
2828 		/* hack -- decrease the variety of damaging attacks a bit, mercifully */
2829 		if (o_ptr->tval == TV_BLUNT || o_ptr->tval == TV_POLEARM) return(FALSE);
2830 
2831 		if (p_ptr->immune_water || !set_rust_destroy(o_ptr))
2832 			return(FALSE);
2833 		break; /* for some equipped items set_rust_destroy and set_water_destroy may be different */
2834 	case GF_ACID:
2835 		/* hack -- decrease the variety of damaging attacks a bit, mercifully */
2836 		if (o_ptr->tval == TV_BLUNT || o_ptr->tval == TV_POLEARM) return(FALSE);
2837 
2838 		if (p_ptr->immune_acid || !set_acid_destroy(o_ptr))
2839 			return(FALSE);
2840 		break;
2841 	case GF_FIRE:
2842 		/* hack -- decrease the variety of damaging attacks a bit, mercifully */
2843 		if (o_ptr->tval == TV_SWORD || o_ptr->tval == TV_AXE) return(FALSE);
2844 
2845 		if (p_ptr->immune_fire || !set_fire_destroy(o_ptr))
2846 			return(FALSE);
2847 		break;
2848 	default: return(FALSE);
2849 	}
2850 
2851 	/* hack: not disenchantable -> cannot be damaged either */
2852 	object_flags(o_ptr, &dummy, &f2, &dummy, &dummy, &f5, &dummy, &dummy);
2853 	if ((f2 & TR2_RES_DISEN) || (f5 & TR5_IGNORE_DISEN)) return FALSE;
2854 
2855 	/* No damage left to be done */
2856 	if (o_ptr->to_d <= -10) return (FALSE);
2857 
2858 	/* Describe */
2859 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
2860 
2861 	/* Message */
2862 	msg_format(Ind, "\376\377oYour %s is damaged!", o_name);
2863 
2864 	/* Damage the item */
2865 	o_ptr->to_d--;
2866 
2867 	/* Calculate bonuses */
2868 	p_ptr->update |= (PU_BONUS);
2869 
2870 	/* Window stuff */
2871 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
2872 
2873 	/* Item was damaged */
2874 	return (TRUE);
2875 }
2876 
2877 
2878 /*
2879  * Hurt the player with Acid
2880  */
2881 int acid_dam(int Ind, int dam, cptr kb_str, int Ind_attacker)
2882 {
2883 	player_type *p_ptr = Players[Ind];
2884 
2885 	int inv, hurt_eq;
2886 
2887 	dam -= p_ptr->reduc_acid * dam / 100;
2888 
2889 	inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
2890 
2891 	/* this is SO much softer than MAngband, heh. I think it's good tho - C. Blue */
2892 	hurt_eq = (dam < 30) ? 15 : (dam < 60) ? 33 : 100;
2893 	if (p_ptr->resist_acid && p_ptr->oppose_acid) hurt_eq = (hurt_eq + 2) / 3;
2894 	else if (p_ptr->resist_acid || p_ptr->oppose_acid) hurt_eq = (hurt_eq + 1) / 2;
2895 
2896 	/* Total Immunity */
2897 	if (p_ptr->immune_acid || (dam <= 0)) return(0);
2898 
2899 	/* Resist the damage */
2900 	if (p_ptr->suscep_acid) dam = dam * 2;
2901 	if (p_ptr->resist_acid) dam = (dam + 2) / 3;
2902 	if (p_ptr->oppose_acid) dam = (dam + 2) / 3;
2903 
2904 	/* Don't kill inventory in bloodbond... */
2905 	int breakable = 1;
2906 	if (IS_PLAYER(Ind_attacker)) {
2907 		if (check_blood_bond(Ind, Ind_attacker)) {
2908 			breakable = 0;
2909 		}
2910 	}
2911 
2912 	if ((!(p_ptr->oppose_acid || p_ptr->resist_acid)) &&
2913 		randint(HURT_CHANCE) == 1 && breakable)
2914 		(void) do_dec_stat(Ind, A_CHR, DAM_STAT_TYPE(inv));
2915 
2916 	/* If any armor gets hit, defend the player */
2917 	/* let's tone it down a bit; since immunity completely protects all eq,
2918 	   let's have resistance work similar - C. Blue */
2919 //		if (magik(33) && equip_damage(Ind, GF_ACID)) dam = (dam + 1) / 2;
2920 //		if (magik(50) && equip_damage(Ind, GF_ACID)) dam = (dam + 1) / 2;
2921 //		if (equip_damage(Ind, GF_ACID)) dam = (dam + 1) / 2;
2922 	if (magik(hurt_eq) && breakable) equip_damage(Ind, GF_ACID);
2923 
2924 	/* Take damage */
2925 //	take_hit(Ind, dam, kb_str, Ind_attacker);
2926 
2927 	/* Inventory damage */
2928 	if (!(p_ptr->oppose_acid && p_ptr->resist_acid) && breakable)
2929 		inven_damage(Ind, set_acid_destroy, inv);
2930 
2931 	return(dam);
2932 }
2933 
2934 /*
2935  * Hurt the player with electricity
2936  */
2937 int elec_dam(int Ind, int dam, cptr kb_str, int Ind_attacker)
2938 {
2939 	player_type *p_ptr = Players[Ind];
2940 
2941 	int inv;
2942 
2943 	dam -= p_ptr->reduc_elec * dam / 100;
2944 
2945 	inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
2946 
2947 	/* Total immunity */
2948 	if (p_ptr->immune_elec || (dam <= 0)) return(0);
2949 
2950 	/* Resist the damage */
2951 	if (p_ptr->suscep_elec) dam = dam * 2;
2952 	if (p_ptr->oppose_elec) dam = (dam + 2) / 3;
2953 	if (p_ptr->resist_elec) dam = (dam + 2) / 3;
2954 
2955 	/* Don't kill inventory in bloodbond... */
2956 	int breakable = 1;
2957 	if (IS_PLAYER(Ind_attacker)) {
2958 		if (check_blood_bond(Ind, Ind_attacker)) {
2959 			breakable = 0;
2960 		}
2961 	}
2962 
2963 	if ((!(p_ptr->oppose_elec || p_ptr->resist_elec)) &&
2964 		randint(HURT_CHANCE) == 1 && breakable)
2965 		(void) do_dec_stat(Ind, A_DEX, DAM_STAT_TYPE(inv));
2966 
2967 	/* Take damage */
2968 //	take_hit(Ind, dam, kb_str, Ind_attacker);
2969 
2970 	/* Inventory damage */
2971 	if (!(p_ptr->oppose_elec && p_ptr->resist_elec) && breakable)
2972 		inven_damage(Ind, set_elec_destroy, inv);
2973 
2974 	return(dam);
2975 }
2976 
2977 /*
2978  * Hurt the player with Fire
2979  */
2980 int fire_dam(int Ind, int dam, cptr kb_str, int Ind_attacker)
2981 {
2982 	player_type *p_ptr = Players[Ind];
2983 
2984 	int inv, hurt_eq;
2985 
2986 	dam -= p_ptr->reduc_fire * dam / 100;
2987 
2988 	inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
2989 
2990 	hurt_eq = (dam < 30) ? 15 : (dam < 60) ? 33 : 100;
2991 	if (p_ptr->resist_fire && p_ptr->oppose_fire) hurt_eq = (hurt_eq + 2) / 3;
2992 	else if (p_ptr->resist_fire || p_ptr->oppose_fire) hurt_eq = (hurt_eq + 1) / 2;
2993 
2994 	/* Totally immune */
2995 	if (p_ptr->immune_fire || (dam <= 0)) return(0);
2996 
2997 	/* Resist the damage */
2998 	if (p_ptr->suscep_fire) dam = dam * 2;
2999 	if (p_ptr->resist_fire) dam = (dam + 2) / 3;
3000 	if (p_ptr->oppose_fire) dam = (dam + 2) / 3;
3001 
3002 	/* Don't kill inventory in bloodbond... */
3003 	int breakable = 1;
3004 	if (IS_PLAYER(Ind_attacker)) {
3005 		if (check_blood_bond(Ind, Ind_attacker)) {
3006 			breakable = 0;
3007 		}
3008 	}
3009 
3010 	if ((!(p_ptr->oppose_fire || p_ptr->resist_fire)) &&
3011 		randint(HURT_CHANCE) == 1 && breakable)
3012 		(void) do_dec_stat(Ind, A_STR, DAM_STAT_TYPE(inv));
3013 
3014 	if (magik(hurt_eq) && breakable) equip_damage(Ind, GF_FIRE);
3015 
3016 	/* Take damage */
3017 //	take_hit(Ind, dam, kb_str, Ind_attacker);
3018 
3019 	/* Inventory damage */
3020 	if (!(p_ptr->resist_fire && p_ptr->oppose_fire) && breakable)
3021 		inven_damage(Ind, set_fire_destroy, inv);
3022 
3023 	return(dam);
3024 }
3025 
3026 /*
3027  * Hurt the player with Cold
3028  */
3029 int cold_dam(int Ind, int dam, cptr kb_str, int Ind_attacker)
3030 {
3031 	player_type *p_ptr = Players[Ind];
3032 
3033 	int inv;
3034 
3035 	dam -= p_ptr->reduc_cold * dam / 100;
3036 
3037 	inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
3038 
3039 	/* Total immunity */
3040 	if (p_ptr->immune_cold || (dam <= 0)) return(0);
3041 
3042 	/* Resist the damage */
3043 	if (p_ptr->suscep_cold) dam = dam * 2;
3044 	if (p_ptr->resist_cold) dam = (dam + 2) / 3;
3045 	if (p_ptr->oppose_cold) dam = (dam + 2) / 3;
3046 
3047 	/* Don't kill inventory in bloodbond... */
3048 	int breakable = 1;
3049 	if (IS_PLAYER(Ind_attacker)) {
3050 		if (check_blood_bond(Ind, Ind_attacker)) {
3051 			breakable = 0;
3052 		}
3053 	}
3054 
3055 	if ((!(p_ptr->oppose_cold || p_ptr->resist_cold)) &&
3056 		randint(HURT_CHANCE) == 1 && breakable)
3057 		(void) do_dec_stat(Ind, A_STR, DAM_STAT_TYPE(inv));
3058 
3059 	/* Take damage */
3060 //	take_hit(Ind, dam, kb_str, Ind_attacker);
3061 
3062 	/* Inventory damage */
3063 	if (!(p_ptr->resist_cold && p_ptr->oppose_cold) && breakable)
3064 		inven_damage(Ind, set_cold_destroy, inv);
3065 
3066 	return(dam);
3067 }
3068 
3069 
3070 
3071 
3072 
3073 /*
3074  * Increases a stat by one randomized level		-RAK-
3075  *
3076  * Note that this function (used by stat potions) now restores
3077  * the stat BEFORE increasing it.
3078  */
3079 bool inc_stat(int Ind, int stat)
3080 {
3081 	player_type *p_ptr = Players[Ind];
3082 
3083 	int value, gain;
3084 
3085 	/* Then augment the current/max stat */
3086 	value = p_ptr->stat_cur[stat];
3087 
3088 	/* Cannot go above 18/100 */
3089 	if (value < 18 + 100) {
3090 		/* Gain one (sometimes two) points */
3091 		if (value < 18) {
3092 			gain = ((rand_int(100) < 75) ? 1 : 2);
3093 			value += gain;
3094 		}
3095 		/* Gain 1/6 to 1/3 of distance to 18/100 */
3096 		else if (value < 18+98) {
3097 			/* Approximate gain value */
3098 			gain = (((18+100) - value) / 2 + 3) / 2;
3099 
3100 			/* Paranoia */
3101 			if (gain < 1) gain = 1;
3102 
3103 			/* 4 points at once is too much */
3104 			if (gain > 17) gain = 17;
3105 
3106 			/* Apply the bonus */
3107 			value += randint(gain) + gain / 2;
3108 
3109 			/* Maximal value */
3110 			if (value > 18+99) value = 18 + 99;
3111 		}
3112 
3113 		/* Gain one point at a time */
3114 		else value++;
3115 
3116 		/* Save the new value */
3117 		p_ptr->stat_cur[stat] = value;
3118 
3119 		/* Bring up the maximum too */
3120 		if (value > p_ptr->stat_max[stat])
3121 			p_ptr->stat_max[stat] = value;
3122 
3123 		/* Recalculate bonuses */
3124 		p_ptr->update |= (PU_BONUS);
3125 
3126 		/* Success */
3127 		return (TRUE);
3128 	}
3129 
3130 	/* Nothing to gain */
3131 	return (FALSE);
3132 }
3133 
3134 
3135 
3136 /*
3137  * Decreases a stat by an amount indended to vary from 0 to 100 percent.
3138  *
3139  * Amount could be a little higher in extreme cases to mangle very high
3140  * stats from massive assaults.  -CWS
3141  *
3142  * Note that "permanent" means that the *given* amount is permanent,
3143  * not that the new value becomes permanent.  This may not work exactly
3144  * as expected, due to "weirdness" in the algorithm, but in general,
3145  * if your stat is already drained, the "max" value will not drop all
3146  * the way down to the "cur" value.
3147  */
3148 bool dec_stat(int Ind, int stat, int amount, int mode)
3149 {
3150 	player_type *p_ptr = Players[Ind];
3151 
3152 	int cur, max, loss = 0, same, res = FALSE;
3153 
3154 	if (safe_area(Ind)) return(FALSE);
3155 
3156 	/* Acquire current value */
3157 	cur = p_ptr->stat_cur[stat];
3158 	max = p_ptr->stat_max[stat];
3159 
3160 	/* Note when the values are identical */
3161 	same = (cur == max);
3162 
3163 	/* Damage "current" value */
3164 	if (cur > 3) {
3165 		/* Handle "low" values */
3166 		if (cur <= 18) {
3167 			if (amount > 90) loss++;
3168 			if (amount > 50) loss++;
3169 			if (amount > 20) loss++;
3170 			loss++;
3171 			cur -= loss;
3172 		}
3173 		/* Handle "high" values */
3174 		else {
3175 			/* Hack -- Decrement by a random amount between one-quarter */
3176 			/* and one-half of the stat bonus times the percentage, with a */
3177 			/* minimum damage of half the percentage. -CWS */
3178 			loss = (((cur-18) / 2 + 1) / 2 + 1);
3179 
3180 			/* Paranoia */
3181 			if (loss < 1) loss = 1;
3182 
3183 			/* Randomize the loss */
3184 			loss = ((randint(loss) + loss) * amount) / 100;
3185 
3186 			/* Maximal loss */
3187 			if (loss < amount/2) loss = amount/2;
3188 
3189 			/* Lose some points */
3190 			cur = cur - loss;
3191 
3192 			/* Hack -- Only reduce stat to 17 sometimes */
3193 			if (cur < 18) cur = (amount <= 20) ? 18 : 17;
3194 		}
3195 
3196 		/* Prevent illegal values */
3197 		if (cur < 3) cur = 3;
3198 
3199 		/* Something happened */
3200 		if (cur != p_ptr->stat_cur[stat]) res = TRUE;
3201 	}
3202 
3203 	/* Damage "max" value */
3204 	if ((mode == STAT_DEC_PERMANENT) && (max > 3)) {
3205 		/* Handle "low" values */
3206 		if (max <= 18) {
3207 			if (amount > 90) max--;
3208 			if (amount > 50) max--;
3209 			if (amount > 20) max--;
3210 			max--;
3211 		}
3212 		/* Handle "high" values */
3213 		else {
3214 			/* Hack -- Decrement by a random amount between one-quarter */
3215 			/* and one-half of the stat bonus times the percentage, with a */
3216 			/* minimum damage of half the percentage. -CWS */
3217 			loss = (((max-18) / 2 + 1) / 2 + 1);
3218 			loss = ((randint(loss) + loss) * amount) / 100;
3219 			if (loss < amount/2) loss = amount/2;
3220 
3221 			/* Lose some points */
3222 			max = max - loss;
3223 
3224 			/* Hack -- Only reduce stat to 17 sometimes */
3225 			if (max < 18) max = (amount <= 20) ? 18 : 17;
3226 		}
3227 
3228 		/* Hack -- keep it clean */
3229 		if (same || (max < cur)) max = cur;
3230 
3231 		/* Something happened */
3232 		if (max != p_ptr->stat_max[stat]) res = TRUE;
3233 	}
3234 
3235 	/* Apply changes */
3236 	if (res) {
3237 		/* Actually set the stat to its new value. */
3238 		p_ptr->stat_cur[stat] = cur;
3239 		p_ptr->stat_max[stat] = max;
3240 
3241 		if (mode == STAT_DEC_TEMPORARY) {
3242 			u16b dectime;
3243 
3244 			/* a little crude, perhaps */
3245 			dectime = rand_int(getlevel(&p_ptr->wpos)*50) + 50;
3246 
3247 			/* prevent overflow, stat_cnt = u16b */
3248 			/* or add another temporary drain... */
3249 			if ( ((p_ptr->stat_cnt[stat]+dectime)<p_ptr->stat_cnt[stat]) ||
3250 				(p_ptr->stat_los[stat]>0) )
3251 
3252 			{
3253 				p_ptr->stat_cnt[stat] += dectime;
3254 				p_ptr->stat_los[stat] += loss;
3255 			}
3256 			else
3257 			{
3258 				p_ptr->stat_cnt[stat] = dectime;
3259 				p_ptr->stat_los[stat] = loss;
3260 			}
3261 		}
3262 
3263 		/* Recalculate bonuses */
3264 //WIS drain -> Sanity changes;	p_ptr->update |= (PU_BONUS); */
3265 		p_ptr->update |= (PU_BONUS | PU_MANA | PU_HP | PU_SANITY);
3266 	}
3267 
3268 	/* Done */
3269 	return (res);
3270 }
3271 
3272 
3273 /*
3274  * Restore a stat.  Return TRUE only if this actually makes a difference.
3275  */
3276 bool res_stat(int Ind, int stat)
3277 {
3278 	player_type *p_ptr = Players[Ind];
3279 
3280 	/* temporary drain is gone */
3281 	p_ptr->stat_los[stat] = 0;
3282 	p_ptr->stat_cnt[stat] = 0;
3283 
3284 	/* Restore if needed */
3285 	if (p_ptr->stat_cur[stat] != p_ptr->stat_max[stat])
3286 	{
3287 		/* Restore */
3288 		p_ptr->stat_cur[stat] = p_ptr->stat_max[stat];
3289 
3290 		/* Recalculate bonuses */
3291 //		p_ptr->update |= (PU_BONUS);
3292 		p_ptr->update |= (PU_BONUS | PU_MANA | PU_HP | PU_SANITY);
3293 
3294 		/* Success */
3295 		return (TRUE);
3296 	}
3297 
3298 	/* Nothing to restore */
3299 	return (FALSE);
3300 }
3301 
3302 
3303 
3304 
3305 /*
3306  * Apply disenchantment to the player's stuff
3307  *
3308  * XXX XXX XXX This function is also called from the "melee" code
3309  *
3310  *
3311  * If "mode is set to 0 then a random slot will be used, if not the "mode"
3312  * slot will be used.
3313  *
3314  * Return "TRUE" if the player notices anything
3315  */
3316 bool apply_disenchant(int Ind, int mode)
3317 {
3318 	player_type *p_ptr = Players[Ind];
3319 	int			t = mode;
3320 	object_type		*o_ptr;
3321 	char		o_name[ONAME_LEN];
3322 	u32b f1, f2, f3, f4, f5, f6, esp;
3323 
3324 	if (safe_area(Ind)) return(FALSE);
3325 
3326 	/* Unused */
3327 //	mode = mode;
3328 
3329 	if(!mode) mode = randint(9);
3330 	else if(mode < 1 || mode > 9) return (FALSE);
3331 
3332 	/* Pick a random slot */
3333 	switch (mode) {
3334 		case 1: t = INVEN_WIELD; break;
3335 		case 2: t = INVEN_BOW; break;
3336 		case 3: t = INVEN_BODY; break;
3337 		case 4: t = INVEN_OUTER; break;
3338 		case 5: t = INVEN_ARM; break;
3339 		case 6: t = INVEN_HEAD; break;
3340 		case 7: t = INVEN_HANDS; break;
3341 		case 8: t = INVEN_FEET; break;
3342 		case 9: t = INVEN_AMMO; break;
3343 	}
3344 
3345 	/* Get the item */
3346 	o_ptr = &p_ptr->inventory[t];
3347 
3348 	/* No item, nothing happens */
3349 	if (!o_ptr->k_idx) return (FALSE);
3350 
3351 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
3352 
3353 	/* Describe the object */
3354 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
3355 
3356 	/* Special treatment for new ego-type: Ethereal (ammunition):
3357 	   Ethereal items don't get disenchanted, but rather disappear completely! */
3358 	if (o_ptr->name2 == EGO_ETHEREAL || o_ptr->name2b == EGO_ETHEREAL) {
3359 		int i = randint(o_ptr->number / 5);
3360 		if (!i) i = 1;
3361 		msg_format(Ind, "\376\377o%s of your %s (%c) %s away!",
3362 		    (o_ptr->number == i ? "All" : (i != 1 ? "Some" : "One")), o_name, index_to_label(t),
3363 		    ((i != 1) ? "fade" : "fades"));
3364 		inven_item_increase(Ind, t, -i);
3365 		inven_item_optimize(Ind, t);
3366 		/* Recalculate bonuses */
3367 		p_ptr->update |= (PU_BONUS);
3368 		/* Window stuff */
3369 		p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3370 		/* Notice */
3371 		return (TRUE);
3372 	}
3373 
3374 	/* Nothing to disenchant */
3375 	if ((o_ptr->to_h <= 0) && (o_ptr->to_d <= 0) && (o_ptr->to_a <= 0)) {
3376 		/* Nothing to notice */
3377 		return (FALSE);
3378 	}
3379 
3380 	if ((f2 & TR2_RES_DISEN) || (f5 & TR5_IGNORE_DISEN)) {
3381 		msg_format(Ind, "Your %s (%c) %s unaffected!",
3382 				   o_name, index_to_label(t),
3383 				   ((o_ptr->number != 1) ? "are" : "is"));
3384 		/* Notice */
3385 		return (TRUE);
3386 	}
3387 
3388 	/* Artifacts have 70%(randart) or 80%(trueart) chance to resist */
3389 	if ((artifact_p(o_ptr) && (rand_int(100) < 70)) ||
3390 	    (true_artifact_p(o_ptr) && (rand_int(100) < 80))) {
3391 		/* Message */
3392 		msg_format(Ind, "Your %s (%c) resist%s!",
3393 				   o_name, index_to_label(t),
3394 				   ((o_ptr->number != 1) ? "" : "s"));
3395 
3396 		/* Notice */
3397 		return (TRUE);
3398 	}
3399 
3400 	/* Disenchant tohit */
3401 	if (o_ptr->to_h > 0) {
3402 		if (o_ptr->to_h > 0) o_ptr->to_h--;
3403 		if ((o_ptr->to_h > 7) && (rand_int(100) < 33)) o_ptr->to_h--;
3404 		if ((o_ptr->to_h > 15) && (rand_int(100) < 25)) o_ptr->to_h--;
3405 	}
3406 	/* Disenchant todam */
3407 	if (o_ptr->to_d > 0) {
3408 		if (o_ptr->to_d > 0) o_ptr->to_d--;
3409 		if ((o_ptr->to_d > 7) && (rand_int(100) < 33)) o_ptr->to_d--;
3410 		if ((o_ptr->to_d > 15) && (rand_int(100) < 25)) o_ptr->to_d--;
3411 	}
3412 	/* Disenchant toac */
3413 	if (o_ptr->to_a > 0) {
3414 		if (o_ptr->to_a > 0) o_ptr->to_a--;
3415 		if ((o_ptr->to_a > 7) && (rand_int(100) < 33)) o_ptr->to_a--;
3416 		if ((o_ptr->to_a > 15) && (rand_int(100) < 25)) o_ptr->to_a--;
3417 	}
3418 	/* Message */
3419 	msg_format(Ind, "\376\377oYour %s (%c) %s disenchanted!",
3420 			   o_name, index_to_label(t),
3421 			   ((o_ptr->number != 1) ? "were" : "was"));
3422 
3423 	/* Recalculate bonuses */
3424 	p_ptr->update |= (PU_BONUS);
3425 
3426 	/* Window stuff */
3427 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3428 
3429 	/* ? */
3430 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3431 
3432 	/* Notice */
3433 	return (TRUE);
3434 }
3435 
3436 
3437 /*
3438  * Apply 'discharging' ie electricity damage to the player's stuff - C. Blue
3439  * the reason for adding this is, to bring electricity on par with other base elements.
3440  *
3441  * Return "TRUE" if the player notices anything
3442  */
3443 bool apply_discharge(int Ind, int dam)
3444 {
3445 	player_type *p_ptr = Players[Ind];
3446 
3447 	int	i, chance = 95;
3448 	bool	damaged_any = FALSE, damaged;
3449 	object_type *o_ptr;
3450 	char	o_name[ONAME_LEN];
3451 	u32b fx, f2, f3;
3452 
3453 	if (safe_area(Ind)) return(FALSE);
3454 
3455 	if ((p_ptr->oppose_elec && p_ptr->resist_elec) ||
3456 	    p_ptr->immune_elec) return(FALSE);
3457 
3458 	/* note: used same values as in elec_dam */
3459 	if (dam >= 30) chance -= 10;
3460 	if (dam >= 60) chance -= 10;
3461 
3462 	/* Scan through the slots backwards */
3463 //	for (i = 0; i < INVEN_PACK; i++)
3464 	for (i = 0; i < INVEN_TOTAL; i++)	/* Let's see what will happen.. */
3465 	{
3466 		/* Hack -- equipments are harder to be harmed */
3467 		if (i >= INVEN_PACK && i != INVEN_AMMO && !magik(HARM_EQUIP_CHANCE))
3468 			continue;
3469 
3470 		/* Get the item */
3471 		o_ptr = &p_ptr->inventory[i];
3472 		/* No item, nothing happens */
3473 		if (!o_ptr->k_idx) return (FALSE);
3474 
3475 		if (magik(chance)) continue;
3476 //		if (o_ptr->tval == TV_AMULET && magik(50)) continue; /* further reduce chance? */
3477 
3478 		object_flags(o_ptr, &fx, &f2, &f3, &fx, &fx, &fx, &fx);
3479 
3480 		/* Hack -- for now, skip artifacts */
3481 		if (artifact_p(o_ptr) ||
3482 		    (f3 & TR3_IGNORE_ELEC) ||
3483 		    (f2 & TR2_IM_ELEC) ||
3484 		    (f2 & TR2_RES_ELEC)) continue;
3485 
3486 		damaged = FALSE;
3487 
3488 		/* Get the item in that slot */
3489 		o_ptr = &p_ptr->inventory[i];
3490 
3491 		/* Describe the object */
3492 		object_desc(Ind, o_name, o_ptr, FALSE, 0);
3493 
3494 		/* damage it */
3495 		if (o_ptr->tval != TV_ROD && o_ptr->tval != TV_LITE && o_ptr->tval != TV_POTION && o_ptr->tval != TV_FOOD) {
3496 			if (o_ptr->timeout) damaged = TRUE;
3497 			if (o_ptr->timeout > 1000) o_ptr->timeout -= 80 + rand_int(41);
3498 			else if (o_ptr->timeout > 100) o_ptr->timeout -= 15 + rand_int(11);
3499 			else if (o_ptr->timeout > 10) o_ptr->timeout -= 3 + rand_int(3);
3500 			else if (o_ptr->timeout) o_ptr->timeout--;
3501 		} else if (o_ptr->tval == TV_ROD) {
3502 			if (o_ptr->pval < 30000) {
3503 				o_ptr->pval += 5;
3504 				damaged = TRUE;
3505 			}
3506 		}
3507 
3508 		if (o_ptr->pval) switch (o_ptr->tval) {
3509 		case TV_AMULET: if (o_ptr->pval < 2) break; /* stop at +1 */
3510 		case TV_STAFF:
3511 		case TV_WAND:
3512 			o_ptr->pval--;
3513 			damaged = TRUE;
3514 			break;
3515 		} else if (o_ptr->bpval > 1 && o_ptr->tval == TV_AMULET) {
3516 			o_ptr->bpval--;
3517 			damaged = TRUE;
3518 		}
3519 
3520 		/* Special treatment for new ego-type: Ethereal (ammunition): */
3521 		if (is_ammo(o_ptr->tval) && (o_ptr->name2 == EGO_ETHEREAL || o_ptr->name2b == EGO_ETHEREAL)) {
3522 			msg_format(Ind, "\376\377o%s %s (%c) fades away!",
3523 			    o_ptr->number == 1 ? "Your" : "One of your", o_name, index_to_label(i));
3524 			inven_item_increase(Ind, i, -1);
3525 			inven_item_optimize(Ind, i);
3526 			p_ptr->update |= (PU_BONUS);
3527 			damaged_any = TRUE;
3528 		}
3529 		/* Message */
3530 		else if (damaged) {
3531 			msg_format(Ind, "\376\377oYour %s (%c) %s discharged!",
3532 			    o_name, index_to_label(i), ((o_ptr->number != 1) ? "were" : "was"));
3533 			damaged_any = TRUE;
3534 		}
3535 	}
3536 
3537 	/* Window stuff */
3538 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3539 
3540 	/* ? */
3541 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3542 
3543 	return (damaged_any);
3544 }
3545 bool apply_discharge_item(int o_idx, int dam)
3546 {
3547 	int	chance = 95;
3548 	bool	damaged = FALSE;
3549 	object_type *o_ptr = &o_list[o_idx];
3550 	u32b fx, f2, f3;
3551 
3552 	/* No item, nothing happens */
3553 	if (!o_ptr->k_idx) return (FALSE);
3554 
3555 	/* note: used same values as in elec_dam */
3556 	if (dam >= 30) chance -= 10;
3557 	if (dam >= 60) chance -= 10;
3558 
3559 	if (magik(chance)) return(FALSE);
3560 //	if (o_ptr->tval == TV_AMULET && magik(50)) return(FALSE); /* further reduce chance? */
3561 
3562 	object_flags(o_ptr, &fx, &f2, &f3, &fx, &fx, &fx, &fx);
3563 
3564 	/* Hack -- for now, skip artifacts */
3565 	if (artifact_p(o_ptr) ||
3566 	    (f3 & TR3_IGNORE_ELEC) ||
3567 	    (f2 & TR2_IM_ELEC) ||
3568 	    (f2 & TR2_RES_ELEC)) return(FALSE);
3569 
3570 	/* damage it */
3571 	if (o_ptr->tval != TV_ROD && o_ptr->tval != TV_LITE && o_ptr->tval != TV_POTION && o_ptr->tval != TV_FOOD) {
3572 		if (o_ptr->timeout) damaged = TRUE;
3573 		if (o_ptr->timeout > 1000) o_ptr->timeout -= 80 + rand_int(41);
3574 		else if (o_ptr->timeout > 100) o_ptr->timeout -= 15 + rand_int(11);
3575 		else if (o_ptr->timeout > 10) o_ptr->timeout -= 3 + rand_int(3);
3576 		else if (o_ptr->timeout) o_ptr->timeout--;
3577 	} else if (o_ptr->tval == TV_ROD) {
3578 		if (o_ptr->pval < 30000) {
3579 			o_ptr->pval += 5;
3580 			damaged = TRUE;
3581 		}
3582 	}
3583 
3584 	if (o_ptr->pval) switch (o_ptr->tval) {
3585 	case TV_AMULET: if (o_ptr->pval < 2) break; /* stop at +1 */
3586 	case TV_STAFF:
3587 	case TV_WAND:
3588 		o_ptr->pval--;
3589 		damaged = TRUE;
3590 		break;
3591 	} else if (o_ptr->bpval > 1 && o_ptr->tval == TV_AMULET) {
3592 		o_ptr->bpval--;
3593 		damaged = TRUE;
3594 	}
3595 
3596 	/* Special treatment for new ego-type: Ethereal (ammunition): */
3597 	if (is_ammo(o_ptr->tval) && (o_ptr->name2 == EGO_ETHEREAL || o_ptr->name2b == EGO_ETHEREAL)) {
3598 		if (o_ptr->number == 1) delete_object_idx(o_idx, TRUE);
3599 		else o_ptr->number--;
3600 		damaged = TRUE;
3601 	}
3602 
3603 	return (damaged);
3604 }
3605 
3606 
3607 /*
3608  * Apply Nexus
3609  */
3610 static void apply_nexus(int Ind, monster_type *m_ptr, int Ind_attacker)
3611 {
3612 	player_type *p_ptr = Players[Ind];
3613 	int max1, cur1, max2, cur2, ii, jj;
3614 
3615         int chance = (195 - p_ptr->skill_sav) / 2;
3616         if (p_ptr->res_tele) chance = 50;
3617 
3618 	if (p_ptr->martyr) return;
3619 
3620 	if (IS_PLAYER(Ind_attacker))
3621 		s_printf("APPLY_NEXUS_PY: %s by %s\n", p_ptr->name, Players[Ind_attacker]->name);
3622 
3623 	switch (randint((safe_area(Ind) || (p_ptr->mode & MODE_PVP)) ? 5 : 8)) { /* don't do baaad things in Monster Arena Challenge */
3624 		case 4: case 5:
3625 		{
3626 			if (p_ptr->anti_tele || magik(chance))
3627 			{
3628 				msg_print(Ind, "You resist the effects!");
3629 				break;
3630 			}
3631 
3632 			if (m_ptr)
3633 				teleport_player_to(Ind, m_ptr->fy, m_ptr->fx);
3634 			else
3635 				teleport_player(Ind, 200, TRUE);
3636 			break;
3637 		}
3638 
3639 		case 1: case 2: case 3:
3640 		{
3641 			if (p_ptr->anti_tele || magik(chance))
3642 			{
3643 				msg_print(Ind, "You resist the effects!");
3644 				break;
3645 			}
3646 
3647 			teleport_player(Ind, 200, TRUE);
3648 			break;
3649 		}
3650 
3651 		case 6:
3652 		{
3653 			if (rand_int(100) < p_ptr->skill_sav || magik(chance))
3654 			{
3655 				msg_print(Ind, "You resist the effects!");
3656 				break;
3657 			}
3658 
3659 			/* Teleport Level */
3660 			teleport_player_level(Ind, FALSE);
3661 			break;
3662 		}
3663 
3664 		case 7:
3665 		{
3666 			if (rand_int(100) < p_ptr->skill_sav)
3667 			{
3668 				msg_print(Ind, "You resist the effects!");
3669 				break;
3670 			}
3671 
3672 			msg_print(Ind, "\376\377oYour body starts to scramble...");
3673 			s_printf("NEXUS_SCRAMBLE: %s\n", p_ptr->name);
3674 
3675 			/* Pick a pair of stats */
3676 			ii = rand_int(6);
3677 			for (jj = ii; jj == ii; jj = rand_int(6)) /* loop */;
3678 
3679 			max1 = p_ptr->stat_max[ii];
3680 			cur1 = p_ptr->stat_cur[ii];
3681 			max2 = p_ptr->stat_max[jj];
3682 			cur2 = p_ptr->stat_cur[jj];
3683 
3684 			p_ptr->stat_max[ii] = max2;
3685 			p_ptr->stat_cur[ii] = cur2;
3686 			p_ptr->stat_max[jj] = max1;
3687 			p_ptr->stat_cur[jj] = cur1;
3688 
3689 			p_ptr->update |= (PU_BONUS | PU_MANA | PU_HP | PU_SANITY);
3690 
3691 			break;
3692 		}
3693 
3694 		case 8:
3695 		{
3696 			if (check_st_anchor(&p_ptr->wpos, p_ptr->py, p_ptr->px)) break;
3697 			if (p_ptr->anti_tele || magik(chance))
3698 			{
3699 				msg_print(Ind, "You resist the effects!");
3700 				break;
3701 			}
3702 
3703 			msg_print(Ind, "\376\377oYour backpack starts to scramble...");
3704 
3705 			if(m_ptr){
3706 				ii = 10 + m_ptr->level / 3;
3707 				if (ii > 50) ii = 50;
3708 			}
3709 			else
3710 				ii = 25;
3711 
3712 			do_player_scatter_items(Ind, 5, ii);
3713 
3714 			break;
3715 		}
3716 	}
3717 }
3718 
3719 
3720 /*
3721  * Apply Polymorph
3722  */
3723 
3724 /* Ho Ho Ho... I really want this to have a chance of turning people into
3725    a fruit bat,  but something tells me I should put that off until the next version...
3726 
3727    I CANT WAIT. DOING FRUIT BAT RIGHT NOW!!!
3728    -APD-
3729 */
3730 static void apply_morph(int Ind, int power, char * killer, int Ind_attacker)
3731 {
3732 	player_type *p_ptr = Players[Ind];
3733 #if 0
3734 	int max1, cur1, max2, cur2, ii, jj;
3735 #endif
3736 
3737 	if (p_ptr->martyr) return;
3738 
3739         if (IS_PLAYER(Ind_attacker))
3740     		s_printf("APPLY_MORPH_PY: %s by %s\n", p_ptr->name, Players[Ind_attacker]->name);
3741 
3742 	switch (randint(2)) {
3743 #if 1
3744 	case 1: msg_print(Ind, "You resist the effects!");
3745 		break;
3746 #else
3747 	case 1:
3748 		if (rand_int(40 + power*2) < p_ptr->skill_sav) {
3749 			msg_print(Ind, "You resist the effects!");
3750 			break;
3751 		}
3752 
3753 		msg_print(Ind, "\376\377oYour body starts to scramble...");
3754 		s_printf("MORPH_SCRAMBLE: %s\n", p_ptr->name);
3755 
3756 		/* Pick a pair of stats */
3757 		ii = rand_int(6);
3758 		for (jj = ii; jj == ii; jj = rand_int(6)) /* loop */;
3759 
3760 		max1 = p_ptr->stat_max[ii];
3761 		cur1 = p_ptr->stat_cur[ii];
3762 		max2 = p_ptr->stat_max[jj];
3763 		cur2 = p_ptr->stat_cur[jj];
3764 
3765 		p_ptr->stat_max[ii] = max2;
3766 		p_ptr->stat_cur[ii] = cur2;
3767 		p_ptr->stat_max[jj] = max1;
3768 		p_ptr->stat_cur[jj] = cur1;
3769 
3770 		p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SANITY);
3771 
3772 		break;
3773 #endif
3774 	case 2:
3775 		if (!p_ptr->fruit_bat) {
3776 			if (rand_int(10 + power * 4) < p_ptr->skill_sav) {
3777 				msg_print(Ind, "You resist the effects!");
3778 			} else {
3779 				s_printf("MORPH_FRUITBAT: %s\n", p_ptr->name);
3780 				/* FRUIT BAT!!!!!! */
3781 				if (p_ptr->body_monster) do_mimic_change(Ind, 0, TRUE);
3782 				msg_print(Ind, "\377yYou have been turned into a fruit bat!");
3783 				strcpy(p_ptr->died_from, killer);
3784 				strcpy(p_ptr->really_died_from, killer);
3785 				p_ptr->fruit_bat = -1;
3786 				p_ptr->deathblow = 0;
3787 				player_death(Ind);
3788 			}
3789 		} else if (p_ptr->fruit_bat == 2) {
3790 			/* no saving throw for being restored..... */
3791 			msg_print(Ind, "You have been restored!");
3792 			p_ptr->fruit_bat = 0;
3793 			p_ptr->update |= (PU_BONUS | PU_HP);
3794 		} else {
3795 			msg_print(Ind, "You feel certain you are a fruit bat!");
3796 		}
3797 	}
3798 }
3799 
3800 
3801 
3802 /* For project_..():
3803    Decrease the damage over the radius. */
3804 static int radius_damage(int dam, int div, int typ) {
3805 	switch (typ) {
3806 	/* When these are cast as 'ball spells' they'd be gimped too much probably: */
3807 	case GF_TELEPORT_PLAYER: //Kurzel - This and many others (buffs) could go here (pending approval..)!
3808 	case GF_OLD_SLOW:
3809 	case GF_OLD_CONF:
3810 	case GF_OLD_SLEEP:
3811 	case GF_TURN_ALL:
3812 
3813 	/* These must not be reduced, since 'dam' stores the functionality */
3814 	case GF_RECALL_PLAYER: /* not for recall (dam is timeout) - mikaelh */
3815 	case GF_CURE_PLAYER:
3816 	case GF_RESTORE_PLAYER:
3817 	case GF_CURING:
3818 	case GF_RESURRECT_PLAYER:
3819 
3820 		return (dam);
3821 	}
3822 
3823 	/* default: half damage per grid of distance */
3824 	return (dam / div);
3825 }
3826 
3827 
3828 
3829 /*
3830  * Hack -- track "affected" monsters
3831  */
3832 static int project_m_n;
3833 static int project_m_x;
3834 static int project_m_y;
3835 
3836 
3837 
3838 /*
3839  * We are called from "project()" to "damage" terrain features
3840  *
3841  * We are called both for "beam" effects and "ball" effects.
3842  *
3843  * The "r" parameter is the "distance from ground zero".
3844  *
3845  * Note that we determine if the player can "see" anything that happens
3846  * by taking into account: blindness, line-of-sight, and illumination.
3847  *
3848  * We return "TRUE" if the effect of the projection is "obvious".
3849  *
3850  * XXX XXX XXX We also "see" grids which are "memorized", probably a hack
3851  *
3852  * XXX XXX XXX Perhaps we should affect doors?
3853  */
3854 static bool project_f(int Ind, int who, int r, struct worldpos *wpos, int y, int x, int dam, int typ) {
3855 	bool obvious = FALSE;
3856 //	bool quiet = ((Ind <= 0) ? TRUE : FALSE);
3857 	bool quiet = ((Ind <= 0 || who <= PROJECTOR_UNUSUAL) ? TRUE : FALSE);
3858 	int div;
3859 
3860 	player_type *p_ptr = (quiet ? NULL : Players[Ind]);
3861 
3862 	byte *w_ptr = (quiet ? NULL : &p_ptr->cave_flag[y][x]);
3863 	cave_type *c_ptr;
3864 	cave_type **zcave;
3865 
3866 
3867 	if (!(zcave = getcave(wpos))) return(FALSE);
3868 	c_ptr = &zcave[y][x];
3869 
3870 	/* Extract radius */
3871 	div = r + 1;
3872 	/* Decrease damage */
3873 	dam = radius_damage(dam, div, typ);
3874 
3875 	/* XXX XXX */
3876 	who = who ? who : 0;
3877 
3878 
3879 	/* Analyze the type */
3880 	switch (typ) {
3881 		/* Ignore most effects */
3882 		case GF_ACID:
3883 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
3884 			/* Destroy trees */
3885 			if (c_ptr->feat == FEAT_TREE || c_ptr->feat == FEAT_BUSH) {
3886 #if 0 /* no msg spam maybe */
3887 				/* Hack -- special message */
3888 				if (!quiet && player_can_see_bold(Ind, y, x)) {
3889 					msg_print(Ind, "The tree decays!");
3890 					/* Notice */
3891 					note_spot(Ind, y, x);
3892 					obvious = TRUE;
3893 				}
3894 #endif
3895 				/* Destroy the tree */
3896 				cave_set_feat_live(wpos, y, x, FEAT_DEAD_TREE);
3897 			}
3898 
3899 			/* Burn grass et al */
3900 			if (c_ptr->feat == FEAT_GRASS || c_ptr->feat == FEAT_IVY ||
3901 			    c_ptr->feat == FEAT_WEB ||
3902 			    c_ptr->feat == FEAT_CROP || c_ptr->feat == FEAT_FLOWER /* :( */)
3903 				cave_set_feat_live(wpos, y, x, FEAT_DIRT);//(was FEAT_MUD) or maybe FEAT_ASH?
3904 
3905 			break;
3906 
3907 		case GF_NUKE:
3908 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
3909 			/* damage organic material */
3910 			if (c_ptr->feat == FEAT_GRASS || c_ptr->feat == FEAT_IVY ||
3911 			    /*c_ptr->feat == FEAT_WEB ||*/
3912 			    c_ptr->feat == FEAT_CROP || c_ptr->feat == FEAT_FLOWER /* :( */)
3913 				cave_set_feat_live(wpos, y, x, FEAT_DIRT);
3914 			break;
3915 
3916 		case GF_ICE:
3917 		case GF_ICEPOISON:
3918 		case GF_SHARDS:
3919 		case GF_FORCE:
3920 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
3921 			/* Shred certain feats */
3922 			if (c_ptr->feat == FEAT_WEB || c_ptr->feat == FEAT_FLOWER /* :( */)
3923 				cave_set_feat_live(wpos, y, x, FEAT_DIRT);
3924 			break;
3925 		case GF_ELEC:
3926 		case GF_COLD:
3927 		case GF_THUNDER:	/* a gestalt now, to remove hacky tri-bolt on thunderstorm */
3928 		case GF_SOUND:
3929 		case GF_MANA: /* <- no web/flower destructing abilities at this time? :-p */
3930 		case GF_HOLY_ORB:
3931 		case GF_CURSE:		/* new spell - the_sandman */
3932 		/* Druidry: */
3933 		case GF_HEALINGCLOUD:
3934 			break;
3935 
3936 		case GF_EARTHQUAKE:
3937 			earthquake(wpos, y, x, 0);
3938 			break;
3939 
3940 		case GF_STONE_WALL:
3941 			/* Require a "naked" floor grid */
3942 			if (!cave_naked_bold(zcave, y, x)) break;
3943 			if (!allow_terraforming(wpos, FEAT_WALL_EXTRA)) break;
3944 			/* Beware of the houses in town */
3945 			if ((wpos->wz == 0) && (zcave[y][x].info & CAVE_ICKY)) break;
3946 			/* Not if it's an open house door - mikaelh */
3947 			if (c_ptr->feat == FEAT_HOME_OPEN) break;
3948 
3949 			/* Place a wall */
3950 			if (c_ptr->feat != FEAT_WALL_EXTRA) c_ptr->info &= ~CAVE_NEST_PIT; /* clear teleport protection for nest grid if changed */
3951 			cave_set_feat_live(wpos, y, x, FEAT_WALL_EXTRA);
3952 
3953 			/* Notice */
3954 			if (!quiet) note_spot(Ind, y, x);
3955 			/* Redraw */
3956 			everyone_lite_spot(wpos, y, x);
3957 			break;
3958 
3959 		/* Burn trees and grass */
3960 		case GF_HOLY_FIRE:
3961 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
3962 			/* Holy Fire doesn't destroy trees! */
3963 			/* spider webs (Cirith Ungol!) */
3964 			if (c_ptr->feat == FEAT_WEB)
3965 				cave_set_feat_live(wpos, y, x, FEAT_ASH);
3966 
3967 #if 1			/* FEAT_ICE_WALL are tunneable, so probably no harm in making them meltable too */
3968 			if (c_ptr->feat == FEAT_ICE_WALL && !rand_int((410 - (dam < 370 ? dam : 370)) / 4))
3969 				cave_set_feat_live(wpos, y, x, FEAT_SHAL_WATER);
3970 #endif
3971 			break;
3972 
3973 		case GF_FIRE:
3974 		case GF_METEOR:
3975 		case GF_PLASMA:
3976 		case GF_HELL_FIRE:
3977 		case GF_INFERNO:
3978 		//GF_DETONATION and GF_ROCKET disintegrate anyway
3979 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
3980 			/* Destroy trees */
3981 			if (c_ptr->feat == FEAT_TREE ||
3982 			    c_ptr->feat == FEAT_BUSH ||
3983 			    c_ptr->feat == FEAT_DEAD_TREE) {
3984 #if 0 /* no need for message spam maybe - and spot is note'd in cave_set_feat_live already */
3985 				/* Hack -- special message */
3986 				if (!quiet && player_can_see_bold(Ind, y, x)) {
3987 					msg_print(Ind, "The tree burns to the ground!");
3988 					/* Notice */
3989 					note_spot(Ind, y, x);
3990 					obvious = TRUE;
3991 				}
3992 #endif
3993 				/* Destroy the tree */
3994 				cave_set_feat_live(wpos, y, x, FEAT_ASH);
3995 			}
3996 
3997 			/* Burn grass, spider webs (Cirith Ungol!) and more.. */
3998 			if (c_ptr->feat == FEAT_GRASS || c_ptr->feat == FEAT_IVY ||
3999 			    c_ptr->feat == FEAT_WEB ||
4000 			    c_ptr->feat == FEAT_CROP || c_ptr->feat == FEAT_FLOWER /* :( */)
4001 				cave_set_feat_live(wpos, y, x, FEAT_ASH);
4002 
4003 			/* misc flavour: turn mud to dirt and/or shallow water into nothing (steam)? */
4004 			//if (c_ptr->feat == FEAT_MUD) cave_set_feat_live(wpos, y, x, FEAT_DIRT);
4005 			if (c_ptr->feat == FEAT_SHAL_WATER) cave_set_feat_live(wpos, y, x, FEAT_MUD);
4006 
4007 #if 1			/* FEAT_ICE_WALL are tunneable, so probably no harm in making them meltable too */
4008 			if (c_ptr->feat == FEAT_ICE_WALL && !rand_int((410 - (dam < 370 ? dam : 370)) / 4))
4009 				cave_set_feat_live(wpos, y, x, FEAT_SHAL_WATER);
4010 #endif
4011 			break;
4012 
4013 		/* Destroy Traps (and Locks) */
4014 		case GF_KILL_TRAP:
4015 		{
4016 			struct c_special *cs_ptr;
4017 			/* Destroy invisible traps */
4018 //			if (c_ptr->feat == FEAT_INVIS)
4019 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
4020 				/* Hack -- special message */
4021 				if (!quiet && player_can_see_bold(Ind, y, x)) {
4022 					msg_print(Ind, "There is a bright flash of light!");
4023 					obvious = TRUE;
4024 				}
4025 
4026 				/* Destroy the trap */
4027 //				c_ptr->feat = FEAT_FLOOR;
4028 				cs_erase(c_ptr, cs_ptr);
4029 
4030 				if (!quiet) {
4031 					/* Notice */
4032 					note_spot(Ind, y, x);
4033 
4034 					/* Redraw */
4035 					if (c_ptr->o_idx && !c_ptr->m_idx)
4036 						/* Make sure no traps are displayed on the screen anymore - mikaelh */
4037 						everyone_clear_ovl_spot(wpos, y, x);
4038 					else
4039 						everyone_lite_spot(wpos, y, x);
4040 				}
4041 			}
4042 
4043 			/* Secret / Locked doors are found and unlocked */
4044 			else if ((c_ptr->feat == FEAT_SECRET) ||
4045 			    ((c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) &&
4046 			    (c_ptr->feat <= FEAT_DOOR_HEAD + 0x07))) {
4047 				/* Notice */
4048 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4049 					msg_print(Ind, "Click!");
4050 					obvious = TRUE;
4051 				}
4052 
4053 				/* Unlock the door */
4054 				c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
4055 
4056 				/* Clear mimic feature */
4057 				if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
4058 					cs_erase(c_ptr, cs_ptr);
4059 
4060 				if (!quiet) {
4061 					/* Notice */
4062 					note_spot(Ind, y, x);
4063 
4064 					/* Redraw */
4065 					if (c_ptr->o_idx && !c_ptr->m_idx)
4066 						/* Make sure no traps are displayed on the screen anymore - mikaelh */
4067 						everyone_clear_ovl_spot(wpos, y, x);
4068 					else
4069 						everyone_lite_spot(wpos, y, x);
4070 				}
4071 			}
4072 
4073 			break;
4074 		}
4075 
4076 		/* Destroy Doors (and traps) */
4077 		case GF_KILL_DOOR:
4078 		{
4079 			byte feat = twall_erosion(wpos, y, x);
4080 			struct c_special *cs_ptr;
4081 
4082 			/* Destroy invisible traps */
4083 //			if (c_ptr->feat == FEAT_INVIS)
4084 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
4085 				/* Hack -- special message */
4086 				if (!quiet && player_can_see_bold(Ind, y, x)) {
4087 					msg_print(Ind, "There is a bright flash of light!");
4088 					obvious = TRUE;
4089 				}
4090 
4091 				/* Destroy the feature */
4092 //				c_ptr->feat = FEAT_FLOOR;
4093 				cs_erase(c_ptr, cs_ptr);
4094 
4095 				/* Forget the wall */
4096 				everyone_forget_spot(wpos, y, x);
4097 
4098 				if (!quiet) {
4099 					/* Notice */
4100 					note_spot(Ind, y, x);
4101 
4102 					/* Redraw */
4103 					if (c_ptr->o_idx && !c_ptr->m_idx)
4104 						/* Make sure no traps are displayed on the screen anymore - mikaelh */
4105 						everyone_clear_ovl_spot(wpos, y, x);
4106 					else
4107 						everyone_lite_spot(wpos, y, x);
4108 				}
4109 			}
4110 
4111 			/* Destroy all visible traps and open doors */
4112 			if ((c_ptr->feat == FEAT_OPEN) ||
4113 			    (c_ptr->feat == FEAT_BROKEN)) {
4114 				/* Hack -- special message */
4115 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4116 					msg_print(Ind, "There is a bright flash of light!");
4117 					obvious = TRUE;
4118 				}
4119 
4120 				/* Destroy the feature */
4121 				cave_set_feat_live(wpos, y, x, feat);
4122 				/* Forget the wall */
4123 				everyone_forget_spot(wpos, y, x);
4124 
4125 				if (!quiet) {
4126 					/* Notice */
4127 					note_spot(Ind, y, x);
4128 
4129 					/* Redraw */
4130 					if (c_ptr->o_idx && !c_ptr->m_idx)
4131 						/* Make sure no traps are displayed on the screen anymore - mikaelh */
4132 						everyone_clear_ovl_spot(wpos, y, x);
4133 					else
4134 						everyone_lite_spot(wpos, y, x);
4135 				}
4136 			}
4137 
4138 			/* Destroy all closed doors */
4139 			if ((c_ptr->feat >= FEAT_DOOR_HEAD) &&
4140 			    (c_ptr->feat <= FEAT_DOOR_TAIL)) {
4141 				/* Hack -- special message */
4142 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4143 					msg_print(Ind, "There is a bright flash of light!");
4144 					obvious = TRUE;
4145 				}
4146 
4147 				/* Destroy the feature */
4148 				cave_set_feat_live(wpos, y, x, feat);
4149 
4150 				/* Forget the wall */
4151 				everyone_forget_spot(wpos, y, x);
4152 
4153 				if (!quiet) {
4154 					/* Notice */
4155 					note_spot(Ind, y, x);
4156 
4157 					/* Redraw */
4158 					everyone_lite_spot(wpos, y, x);
4159 
4160 					/* Update some things */
4161 					p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
4162 				}
4163 			}
4164 			break;
4165 		}
4166 
4167 		/* Destroy walls (and doors) */
4168 		case GF_KILL_WALL:
4169 		{
4170 			byte feat = twall_erosion(wpos, y, x);
4171 
4172 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
4173 			/* Non-walls (etc) */
4174 			if (cave_los(zcave, y, x)) break;
4175 			/* Permanent walls */
4176 			if ((c_ptr->feat >= FEAT_PERM_EXTRA || c_ptr->feat == FEAT_PERM_CLEAR)
4177 			    && !(c_ptr->feat >= FEAT_SANDWALL && c_ptr->feat <= FEAT_SANDWALL_K)) break;
4178 
4179 			/* the_sandman: sandwalls are stm-able too? */
4180 			/* fixed it and also added the treasures in sandwalls - mikaelh */
4181 			/* Sandwall */
4182 			if (c_ptr->feat == FEAT_SANDWALL) {
4183 				/* Message */
4184 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4185 					msg_print(Ind, "The sandwall collapses!");
4186 					obvious = TRUE;
4187 				}
4188 
4189 				/* Destroy the wall */
4190 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_SAND : feat);
4191 			}
4192 			/* Sandwall with treasure */
4193 			else if (c_ptr->feat == FEAT_SANDWALL_H || c_ptr->feat == FEAT_SANDWALL_K) {
4194 				/* Message */
4195 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4196 					msg_print(Ind, "The sandwall collapses!");
4197 					if (!istown(wpos)) msg_print(Ind, "You have found something!");
4198 					obvious = TRUE;
4199 				}
4200 
4201 				/* Destroy the wall */
4202 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_SAND : feat);
4203 
4204 				/* Place some gold */
4205 				if (!istown(wpos)) place_gold(wpos, y, x, 0);
4206 			}
4207 			/* Granite */
4208 			else if (c_ptr->feat >= FEAT_WALL_EXTRA) {
4209 				/* Message */
4210 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4211 					msg_print(Ind, "The wall turns into mud!");
4212 					obvious = TRUE;
4213 				}
4214 
4215 				/* Destroy the wall */
4216 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_MUD : feat);
4217 			}
4218 			/* Quartz / Magma with treasure */
4219 			else if (c_ptr->feat >= FEAT_MAGMA_H) {
4220 				/* Message */
4221 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4222 					msg_print(Ind, "The vein turns into mud!");
4223 					if (!istown(wpos)) msg_print(Ind, "You have found something!");
4224 					obvious = TRUE;
4225 				}
4226 
4227 				/* Destroy the wall */
4228 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_MUD : feat);
4229 
4230 				/* Place some gold */
4231 				if (!istown(wpos)) place_gold(wpos, y, x, 0);
4232 			}
4233 
4234 			/* Quartz / Magma */
4235 			else if (c_ptr->feat >= FEAT_MAGMA) {
4236 				/* Message */
4237 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4238 					msg_print(Ind, "The vein turns into mud!");
4239 					obvious = TRUE;
4240 				}
4241 
4242 				/* Destroy the wall */
4243 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_MUD : feat);
4244 			}
4245 
4246 			/* Rubble */
4247 			else if (c_ptr->feat == FEAT_RUBBLE) {
4248 				/* Message */
4249 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4250 					msg_print(Ind, "The rubble turns into mud!");
4251 					obvious = TRUE;
4252 				}
4253 
4254 				/* Destroy the rubble */
4255 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_MUD : feat);
4256 
4257 				/* Hack -- place an object */
4258 				if (rand_int(100) < 10) {
4259 					/* Found something */
4260 					if (!quiet && player_can_see_bold(Ind, y, x) && !istown(wpos)) {
4261 						msg_print(Ind, "There was something buried in the rubble!");
4262 						obvious = TRUE;
4263 					}
4264 
4265 					/* Place object */
4266 					if (!istown(wpos)) {
4267 						place_object_restrictor = RESF_NONE;
4268 						place_object(wpos, y, x, FALSE, FALSE, FALSE, make_resf(p_ptr) | RESF_LOW, default_obj_theme, p_ptr->luck, ITEM_REMOVAL_NORMAL);
4269 					}
4270 				}
4271 			}
4272 
4273 			/* House doors are immune */
4274 			else if (c_ptr->feat == FEAT_HOME) {
4275 				/* Message */
4276 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4277 					msg_print(Ind, "The door resists.");
4278 					obvious = TRUE;
4279 				}
4280 			}
4281 
4282 			/* Destroy doors (and secret doors) */
4283 			else if (c_ptr->feat >= FEAT_DOOR_HEAD) {
4284 				/* Hack -- special message */
4285 				if (!quiet && (*w_ptr & CAVE_MARK)) {
4286 					msg_print(Ind, "The door turns into mud!");
4287 					obvious = TRUE;
4288 				}
4289 
4290 				/* Destroy the feature */
4291 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_MUD : feat);
4292 			}
4293 
4294 			/* Forget the wall */
4295 			everyone_forget_spot(wpos, y, x);
4296 
4297 			if (!quiet) {
4298 				/* Notice */
4299 				note_spot(Ind, y, x);
4300 
4301 				/* Redraw */
4302 				everyone_lite_spot(wpos, y, x);
4303 
4304 				/* Update some things */
4305 				p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS);
4306 			}
4307 
4308 			break;
4309 		}
4310 
4311 		/* Make doors */
4312 		case GF_MAKE_DOOR:
4313 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
4314 			/* Require a "naked" floor grid */
4315 			if (!cave_naked_bold(zcave, y, x)) break;
4316 
4317 			/* Create a closed door */
4318 			c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
4319 
4320 			if (!quiet) {
4321 				/* Notice */
4322 				note_spot(Ind, y, x);
4323 				/* Redraw */
4324 				everyone_lite_spot(wpos, y, x);
4325 				/* Observe */
4326 				if (*w_ptr & CAVE_MARK) obvious = TRUE;
4327 				/* Update some things */
4328 				p_ptr->update |= (PU_VIEW | PU_LITE | PU_MONSTERS);
4329 			}
4330 			break;
4331 
4332 		/* Make traps */
4333 		case GF_MAKE_TRAP:
4334 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
4335 			/* Require a "naked" floor grid */
4336 			if ((zcave[y][x].feat != FEAT_MORE && zcave[y][x].feat != FEAT_LESS) && cave_perma_bold(zcave, y, x)) break;
4337 
4338 			/* Place a trap */
4339 			place_trap(wpos, y, x, dam);
4340 
4341 			if (!quiet) {
4342 				/* Notice */
4343 				note_spot(Ind, y, x);
4344 				/* Redraw */
4345 				everyone_lite_spot(wpos, y, x);
4346 			}
4347 			break;
4348 
4349 		/* Lite up the grid */
4350 		case GF_LITE_WEAK:
4351 		case GF_LITE:
4352 			/* don't ruin the mood :> (allow turning on light inside houses though) */
4353 			if ((!(wpos->wz == 0 && (season_halloween || season_newyearseve))) || (c_ptr->info & CAVE_ICKY)) {
4354 				/* Turn on the light */
4355 				c_ptr->info |= CAVE_GLOW;
4356 
4357 				if (!quiet) {
4358 					/* Notice */
4359 					note_spot_depth(wpos, y, x);
4360 					/* Redraw */
4361 					everyone_lite_spot(wpos, y, x);
4362 					/* Observe */
4363 					if (player_can_see_bold(Ind, y, x)) obvious = TRUE;
4364 				}
4365 			}
4366 
4367 			/* Mega-Hack -- Update the monster in the affected grid */
4368 			/* This allows "spear of light" (etc) to work "correctly" */
4369 			if (c_ptr->m_idx > 0) update_mon(c_ptr->m_idx, FALSE);
4370 			break;
4371 
4372 		/* Darken the grid */
4373 		case GF_DARK_WEAK:
4374 		case GF_DARK:
4375 			/* Notice */
4376 			if (!quiet && player_can_see_bold(Ind, y, x)) obvious = TRUE;
4377 
4378 			/* Turn off the light. */
4379 			c_ptr->info &= ~CAVE_GLOW;
4380 
4381 			/* Hack -- Forget "boring" grids */
4382 //			if (c_ptr->feat <= FEAT_INVIS)
4383 			if (cave_plain_floor_grid(c_ptr)) {
4384 				/* Forget the wall */
4385 				everyone_forget_spot(wpos, y, x);
4386 				if (!quiet)
4387 					/* Notice */
4388 					note_spot(Ind, y, x);
4389 			}
4390 			if (!quiet)
4391 				/* Redraw */
4392 				everyone_lite_spot(wpos, y, x);
4393 
4394 			/* Mega-Hack -- Update the monster in the affected grid */
4395 			/* This allows "spear of light" (etc) to work "correctly" */
4396 			if (c_ptr->m_idx > 0) update_mon(c_ptr->m_idx, FALSE);
4397 
4398 			/* All done */
4399 			break;
4400 
4401 		case GF_KILL_GLYPH:
4402 		{
4403 			byte feat = twall_erosion(wpos, y, x);
4404 			if (!allow_terraforming(wpos, FEAT_TREE)) break;
4405 			if (c_ptr->feat == FEAT_GLYPH || c_ptr->feat == FEAT_RUNE)
4406 				cave_set_feat_live(wpos, y, x, (feat == FEAT_FLOOR) ? FEAT_DIRT : feat);
4407 		}
4408 
4409 		/* from PernA	- Jir - */
4410 #if 0
4411 		case GF_MAKE_GLYPH:
4412 			/* Require a "naked" floor grid */
4413 			if (!cave_clean_bold(zcave, y, x)) break;
4414 			if((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
4415 			cave_set_feat_live(&p_ptr->wpos, y, x, FEAT_GLYPH);
4416 			break;
4417 #endif
4418 
4419 		// GF_ROCKET and GF_DISINTEGRATE are handled in project()
4420 
4421 		case GF_WATER:
4422 		case GF_WAVE:
4423 		case GF_VAPOUR:
4424 		case GF_WATERPOISON:	//New druid stuff
4425 		{
4426 			int p1 = 0;
4427 			int p2 = 0;
4428 			int f1 = FEAT_NONE;
4429 			int f2 = FEAT_NONE;
4430 			int f = FEAT_NONE;
4431 			int k;
4432 
4433 			if (!allow_terraforming(wpos, FEAT_SHAL_WATER)) break;
4434 			/* "Permanent" features will stay */
4435 			if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
4436 			/* Needs more than 30 damage */
4437 			if (dam < 30) break;
4438 
4439 			bool old_rand = Rand_quick;
4440 			u32b tmp_seed = Rand_value;
4441 
4442 			if ((c_ptr->feat == FEAT_FLOOR) ||
4443 			    (c_ptr->feat == FEAT_DIRT) ||
4444 			    (c_ptr->feat == FEAT_GRASS)) {
4445 				/* p1 % chance to create this feat */
4446 				p1 = 20; f1 = FEAT_SHAL_WATER;
4447 
4448 				if (c_ptr->feat == FEAT_DIRT)
4449 					/* reduce feat1 chance */
4450 					p1 = 10;
4451 					/* p2 % chance to create this feat */
4452 					p2 = 15; f2 = FEAT_MUD;
4453 			}
4454 			else if (c_ptr->feat == FEAT_SHAL_LAVA) {
4455 				/* 15% chance to convert it to normal floor */
4456 				p1 = 15; f1 = FEAT_VOLCANIC;//FEAT_ROCKY, FEAT_ASH
4457 			}
4458 
4459 			/* Use the stored/quick RNG */
4460 			Rand_quick = TRUE;
4461 			//using fixed seed here to make sure that repeated casting won't cover 100% of the area with water:
4462 			Rand_value = (3623 * wpos->wy + 29753) * (2843 * wpos->wx + 48869) + (1741 * y + 22109) * y * x + (x + 96779) * x + 42 + wpos->wz;
4463 
4464 			k = rand_int(100);
4465 
4466 			/* Restore RNG */
4467 			Rand_quick = old_rand;
4468 			Rand_value = tmp_seed;
4469 
4470 			if (k < p1) f = f1;
4471 			else if (k < p1 + p2) f = f2;
4472 
4473 			if (f) {
4474 //uses static array set in generate.c, fix!	if (f == FEAT_FLOOR) place_floor_live(wpos, y, x);
4475 //				else
4476 				cave_set_feat_live(wpos, y, x, f);
4477 				/* Notice */
4478 				if (!quiet) note_spot(Ind, y, x);
4479 				/* Redraw */
4480 				everyone_lite_spot(wpos, y, x);
4481 //				if (seen) obvious = TRUE;
4482 			}
4483 			break;
4484 		}
4485 	}
4486 
4487 	/* Return "Anything seen?" */
4488 	return (obvious);
4489 }
4490 
4491 
4492 
4493 /*
4494  * We are called from "project()" to "damage" objects
4495  *
4496  * We are called both for "beam" effects and "ball" effects.
4497  *
4498  * Perhaps we should only SOMETIMES damage things on the ground.
4499  *
4500  * The "r" parameter is the "distance from ground zero".
4501  *
4502  * Note that we determine if the player can "see" anything that happens
4503  * by taking into account: blindness, line-of-sight, and illumination.
4504  *
4505  * XXX XXX XXX We also "see" grids which are "memorized", probably a hack
4506  *
4507  * We return "TRUE" if the effect of the projection is "obvious".
4508  */
4509 static bool project_i(int Ind, int who, int r, struct worldpos *wpos, int y, int x, int dam, int typ)
4510 {
4511 	player_type *p_ptr = NULL;
4512 	u16b this_o_idx, next_o_idx = 0;
4513 	bool	obvious = FALSE;
4514 	bool quiet = ((Ind <= 0 || Ind >= 0 - PROJECTOR_UNUSUAL) ? TRUE : FALSE);
4515 	u32b f1, f2, f3, f4, f5, f6, esp;
4516 	char	o_name[ONAME_LEN];
4517 	int o_sval = 0;
4518 	bool is_potion = FALSE, is_basic_potion = FALSE, is_meltable = FALSE;
4519 
4520 	int		div;
4521 	cave_type **zcave;
4522 	cave_type *c_ptr;
4523 	object_type *o_ptr;
4524 	object_kind *k_ptr;
4525 
4526 	if (!(zcave = getcave(wpos))) return(FALSE);
4527 	c_ptr = &zcave[y][x];
4528 //	o_ptr = &o_list[c_ptr->o_idx];
4529 
4530 	/* Nothing here */
4531 	if (!c_ptr->o_idx) return (FALSE);
4532 
4533 	/* Set the player pointer */
4534 	if (!quiet) p_ptr = Players[Ind];
4535 
4536 	/* Extract radius */
4537 	div = r + 1;
4538 
4539 	/* Adjust damage */
4540 	dam = radius_damage(dam, div, typ);
4541 
4542 
4543 	/* XXX XXX */
4544 	who = who ? who : 0;
4545 
4546 	/* Scan all objects in the grid */
4547     for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
4548 	bool	is_art = FALSE;
4549 	bool	ignore = FALSE;
4550 	bool	plural = FALSE;
4551 	bool	do_kill = FALSE;
4552 	bool	do_smash_effect = FALSE;
4553 
4554 	cptr	note_kill = NULL;
4555 
4556 	/* Acquire object */
4557 	o_ptr = &o_list[this_o_idx];
4558 	k_ptr = &k_info[o_ptr->k_idx];
4559 	/* Check for (nothing), execute hack to protect such items */
4560 	if (nothing_test(o_ptr, NULL, wpos, x, y, 3)) {
4561 //		s_printf("NOTHINGHACK: spell doesn't meet item at wpos %d,%d,%d.\n", wpos->wx, wpos->wy, wpos->wz);
4562 		return(FALSE);
4563 	}
4564 
4565 	/* Acquire next object */
4566 	next_o_idx = o_ptr->next_o_idx;
4567 
4568 	/* Extract the flags */
4569 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
4570 
4571 	/* get object name */
4572 	if ((Ind >= 0) && ((0 - Ind) > PROJECTOR_UNUSUAL))
4573 		object_desc(Ind, o_name, o_ptr, FALSE, 0);
4574 
4575 	/* Get the "plural"-ness */
4576 	if (o_ptr->number > 1) plural = TRUE;
4577 
4578 	/* Check for artifact */
4579 	if (artifact_p(o_ptr)) is_art = TRUE;
4580 
4581 	/* Stormbringer is artifact-like - C. Blue */
4582 	if (o_ptr->name2 == EGO_STORMBRINGER) is_art = TRUE;
4583 
4584 	o_sval = o_ptr->sval;
4585 	/* potion_smash_effect only takes sval as parameter, so it can't handle TV_POTION2 at this time.
4586 	   For this reason, add is_basic_potion: It determines whether smash effect is applied. */
4587 	is_potion = ((k_info[o_ptr->k_idx].tval == TV_POTION) || (k_info[o_ptr->k_idx].tval == TV_POTION2));
4588 	is_basic_potion = (k_info[o_ptr->k_idx].tval == TV_POTION);
4589 	is_meltable = (k_info[o_ptr->k_idx].tval == TV_BOTTLE);
4590 
4591 	/* Analyze the type */
4592 	switch (typ) {
4593 		/* Identify */
4594 		case GF_IDENTIFY:
4595 		{
4596 			do_kill = FALSE;
4597 
4598 			/* Identify it fully */
4599 			if (!quiet) object_aware(Ind, o_ptr);
4600 			object_known(o_ptr);
4601 			break;
4602 		}
4603 
4604 		/* Acid -- Lots of things */
4605 		case GF_ACID:
4606 		{
4607 			if (hates_acid(o_ptr)) {
4608 				do_kill = TRUE;
4609 				note_kill = (plural ? " melt!" : " melts!");
4610 				if (f3 & TR3_IGNORE_ACID) ignore = TRUE;
4611 			}
4612 			break;
4613 		}
4614 
4615 		/* Elec -- Rings and Wands, and now much more to make IM_ELEC better, and elec less laughed at */
4616 		case GF_ELEC:
4617 		{
4618 			if (hates_elec(o_ptr))
4619 			{
4620 				do_kill = TRUE;
4621 				note_kill = (plural ? " are destroyed!" : " is destroyed!");
4622 				if (f3 & TR3_IGNORE_ELEC) ignore = TRUE;
4623 			}
4624 			else apply_discharge_item(this_o_idx, dam);
4625 			break;
4626 		}
4627 
4628 		/* Fire -- Flammable objects */
4629 		case GF_FIRE:
4630 		{
4631 			do_smash_effect = TRUE;
4632 			if (hates_fire(o_ptr)) {
4633 				do_kill = TRUE;
4634 				if (is_meltable)
4635 					note_kill = (plural ? " melt!" : " melts!");
4636 				else if (is_potion)
4637 					note_kill = (plural ? " evaporate!" : " evaporates!");
4638 				else
4639 					note_kill = (plural ? " burn up!" : " burns up!");
4640 				if (f3 & TR3_IGNORE_FIRE) ignore = TRUE;
4641 			}
4642 			break;
4643 		}
4644 
4645 		/* Cold -- potions and flasks */
4646 		case GF_COLD:
4647 		{
4648 			if (hates_cold(o_ptr)) {
4649 				note_kill = (plural ? " shatter!" : " shatters!");
4650 				do_kill = TRUE;
4651 				if (f3 & TR3_IGNORE_COLD) ignore = TRUE;
4652 #ifdef USE_SOUND_2010
4653 				else if (!quiet) sound(Ind, "shatter_potion", NULL, SFX_TYPE_MISC, FALSE);
4654 #endif
4655 			}
4656 			break;
4657 		}
4658 
4659 		/* Cold -- potions and flasks */
4660 		case GF_WATER:
4661 		case GF_WAVE:
4662 		//case GF_VAPOUR:
4663 		case GF_WATERPOISON:
4664 		{
4665 			if (hates_water(o_ptr)) {
4666 				note_kill = (plural ? " are soaked!" : " is soaked!");
4667 				do_kill = TRUE;
4668 				if (f5 & TR5_IGNORE_WATER) ignore = TRUE;
4669 			}
4670 			break;
4671 		}
4672 
4673 		/* Fire + Elec + a bit Force */
4674 		case GF_PLASMA:
4675 		{
4676 			do_smash_effect = TRUE;
4677 			ignore = TRUE;
4678 
4679 			if (hates_fire(o_ptr)) {
4680 				do_kill = TRUE;
4681 				if (!(f3 & TR3_IGNORE_FIRE)) {
4682 					ignore = FALSE;
4683 					if (is_meltable)
4684 						note_kill = (plural ? " melt!" : " melts!");
4685 					else if (is_potion)
4686 						note_kill = (plural ? " evaporate!" : " evaporates!");
4687 					else
4688 						note_kill = (plural ? " burn up!" : " burns up!");
4689 				}
4690 			}
4691 
4692 			if (hates_elec(o_ptr)) {
4693 				do_kill = TRUE;
4694 				if (!(f3 & TR3_IGNORE_ELEC)) {
4695 					ignore = FALSE;
4696 					note_kill = (plural ? " are destroyed!" : " is destroyed!");
4697 				}
4698 			}
4699 			else apply_discharge_item(this_o_idx, dam / 2);
4700 
4701 			/* Note: Force item destruction is probably already covered
4702 			   by applied fire item destruction above */
4703 
4704 			break;
4705 		}
4706 
4707 		/* Fire + Impact */
4708 		case GF_METEOR:
4709 		{
4710 			do_smash_effect = TRUE;
4711 			ignore = TRUE;
4712 			if (hates_fire(o_ptr)) {
4713 				do_kill = TRUE;
4714 				if (!(f3 & TR3_IGNORE_FIRE)) {
4715 					ignore = FALSE;
4716 					if (is_meltable)
4717 						note_kill = (plural ? " melt!" : " melts!");
4718 					else if (is_potion)
4719 						note_kill = (plural ? " evaporate!" : " evaporates!");
4720 					else
4721 						note_kill = (plural ? " burn up!" : " burns up!");
4722 				}
4723 			}
4724 			if (hates_impact(o_ptr)) {
4725 				do_kill = TRUE;
4726 				if (!(f3 & TR3_IGNORE_COLD)) {
4727 					ignore = FALSE;
4728 					note_kill = (plural ? " shatter!" : " shatters!");
4729 #ifdef USE_SOUND_2010
4730 					if (!quiet) sound(Ind, "shatter_potion", NULL, SFX_TYPE_MISC, FALSE);
4731 #endif
4732 				}
4733 			}
4734 			break;
4735 		}
4736 
4737 		/* Hack -- break potions and such */
4738 		case GF_ICE:
4739 		case GF_ICEPOISON:
4740 		{
4741 			if (hates_cold(o_ptr) || hates_impact(o_ptr)) {
4742 				note_kill = (plural ? " shatter!" : " shatters!");
4743 				do_kill = TRUE;
4744 #ifdef USE_SOUND_2010
4745 				if (!quiet) sound(Ind, "shatter_potion", NULL, SFX_TYPE_MISC, FALSE);
4746 #endif
4747 			}
4748 			break;
4749 		}
4750 
4751 		case GF_SHARDS:
4752 		case GF_FORCE:
4753 		case GF_SOUND:
4754 		case GF_THUNDER:
4755 		{
4756 			if (hates_impact(o_ptr)) {
4757 				note_kill = (plural ? " shatter!" : " shatters!");
4758 				do_kill = TRUE;
4759 #ifdef USE_SOUND_2010
4760 				if (!quiet) sound(Ind, "shatter_potion", NULL, SFX_TYPE_MISC, FALSE);
4761 #endif
4762 			}
4763 			break;
4764 		}
4765 
4766 		/* Mana -- destroys everything -- except IGNORE_MANA items :p */
4767 		case GF_ANNIHILATION:
4768 		case GF_MANA:
4769 		{
4770 			if (!(f5 & (TR5_IGNORE_MANA | TR5_RES_MANA))) {
4771 				do_smash_effect = TRUE;
4772 				do_kill = TRUE;
4773 				note_kill = (plural ? " are destroyed!" : " is destroyed!");
4774 			}
4775 			break;
4776 		}
4777 
4778 		case GF_DISINTEGRATE:
4779 		{
4780 			do_smash_effect = FALSE;
4781 			do_kill = TRUE;
4782 			note_kill = is_potion ? (plural ? " evaporate!" : " evaporates!")
4783 						: (plural ? " is pulverized!" : " is pulverized!");
4784 //			note_kill = (plural ? " evaporate!" : " evaporates!");
4785 			break;
4786 		}
4787 
4788 		case GF_DISENCHANT:
4789 		{
4790 			if ((f2 & TR2_RES_DISEN) || (f5 & TR5_IGNORE_DISEN)) break;
4791 			if (artifact_p(o_ptr) && magik(100)) break;
4792 
4793 			if (o_ptr->timeout) o_ptr->timeout /= 2;
4794 
4795 			if (o_ptr->to_h > k_ptr->to_h) o_ptr->to_h--;
4796 			if (o_ptr->to_d > k_ptr->to_d) o_ptr->to_d--;
4797 			if (o_ptr->to_a > k_ptr->to_a) o_ptr->to_a--;
4798 
4799 			switch (o_ptr->tval) {
4800 			case TV_ROD: break;
4801 			case TV_WAND:
4802 			case TV_STAFF:
4803 				o_ptr->pval = 0;
4804 				break;
4805 			default:
4806 				/* changed from >0 to >1 to make items retain a slice of their actual abilities */
4807 				if ((o_ptr->pval > 1 || o_ptr->bpval > 1)
4808 				    && !is_ammo(o_ptr->tval)
4809 				    && o_ptr->tval != TV_CHEST
4810 				    && o_ptr->tval != TV_BOOK
4811 				    && (o_ptr->tval != TV_RING || o_ptr->sval != SV_RING_POLYMORPH)) {
4812 					if (o_ptr->pval > 1) {
4813 						if (o_ptr->bpval > 1 && rand_int(2)) o_ptr->bpval--;
4814 						else o_ptr->pval--;
4815 					} else o_ptr->bpval--;
4816 				}
4817 				break;
4818 			}
4819 			break;
4820 		}
4821 
4822 		case GF_INFERNO:
4823 		case GF_DETONATION:
4824 		case GF_ROCKET:
4825 		{
4826 			do_smash_effect = TRUE; /* allow coolness, while preventing exploiting via m_ptr->hit_proj_id; */
4827 			do_kill = TRUE;
4828 			note_kill = is_potion ? (plural ? " evaporate!" : " evaporates!")
4829 						: (plural ? " is pulverized!" : " is pulverized!");
4830 //			note_kill = (plural ? " evaporate!" : " evaporates!");
4831 			break;
4832 		}
4833 
4834 		/* Holy Orb -- destroys cursed non-artifacts */
4835 		case GF_HOLY_ORB:
4836 		case GF_HOLY_FIRE:
4837 		{
4838 			do_smash_effect = TRUE;
4839 			if (cursed_p(o_ptr)
4840 //should be enabled maybe?    || hates_fire(o_ptr)
4841 			    ) {
4842 				do_kill = TRUE;
4843 				note_kill = (plural ? " are destroyed!" : " is destroyed!");
4844 			}
4845 			break;
4846 		}
4847 
4848 		case GF_HELL_FIRE:
4849 			do_smash_effect = TRUE;
4850 			if (hates_fire(o_ptr)) {
4851 				do_kill = TRUE;
4852 				if (is_meltable)
4853 					note_kill = (plural ? " melt!" : " melts!");
4854 				else if (is_potion)
4855 					note_kill = (plural ? " evaporate!" : " evaporates!");
4856 				else
4857 					note_kill = (plural ? " burn up!" : " burns up!");
4858 				if (f3 & TR3_IGNORE_FIRE) ignore = TRUE;
4859 			} else if (!cursed_p(o_ptr) && magik(10)) {
4860 				note_kill = (plural ? " are destroyed!" : " is destroyed!");
4861 				do_kill = TRUE;
4862 			}
4863 			break;
4864 
4865 		/* Unlock chests */
4866 		case GF_KILL_TRAP:
4867 		case GF_KILL_DOOR:
4868 		{
4869 			/* Chests are noticed only if trapped or locked */
4870 			if (o_ptr->tval == TV_CHEST)
4871 			{
4872 				/* Disarm/Unlock traps */
4873 				if (o_ptr->pval > 0)
4874 				{
4875 					/* Disarm or Unlock */
4876 					o_ptr->pval = (0 - o_ptr->pval);
4877 
4878 					/* Identify */
4879 					object_known(o_ptr);
4880 
4881 					/* Notice */
4882 //					if (!quiet && p_ptr->obj_vis[c_ptr->o_idx])
4883 					if (!quiet && p_ptr->obj_vis[this_o_idx])
4884 					{
4885 						msg_print(Ind, "Click!");
4886 						obvious = TRUE;
4887 					}
4888 				}
4889 			}
4890 
4891 			break;
4892 		}
4893 
4894 		/* Nexus, Gravity -- teleports the object away */
4895 		case GF_NEXUS:
4896 		case GF_GRAVITY:
4897 		{
4898 			int j, dist = (typ == GF_NEXUS ? 80 : 15);
4899 			object_type tmp_obj = *o_ptr;
4900 			if (check_st_anchor(wpos, y, x)) break;
4901 //			if (seen) obvious = TRUE;
4902 
4903 			do_smash_effect = TRUE;
4904 
4905 			/* no tricks to get stuff out of suspended guild halls ;> */
4906 			if ((c_ptr->info & CAVE_GUILD_SUS)) break;
4907 
4908 			note_kill = (plural ? " disappear!" : " disappears!");
4909 
4910 			for (j = 0; j < 10; j++) {
4911 				s16b cx = x + dist - rand_int(dist * 2);
4912 				s16b cy = y + dist - rand_int(dist * 2);
4913 				if (!in_bounds(cy, cx)) continue;
4914 				if (!cave_floor_bold(zcave, cy, cx) ||
4915 					cave_perma_bold(zcave, cy, cx)) continue;
4916 
4917 //				(void)floor_carry(cy, cx, &tmp_obj);
4918 				drop_near(&tmp_obj, 0, wpos, cy, cx);
4919 
4920 				/* XXX not working? */
4921 				if (!quiet && note_kill)
4922 					msg_format_near_site(y, x, wpos, 0, TRUE, "\377oThe %s%s", o_name, note_kill);
4923 
4924 				delete_object_idx(this_o_idx, FALSE);
4925 				break;
4926 			}
4927 			break;
4928 		}
4929 
4930 	}
4931 
4932 
4933 	/* Attempt to destroy the object */
4934 //	if (is_basic_potion && do_smash_effect) potion_smash_effect(who, wpos, y, x, o_sval);
4935 
4936 //	if(do_kill && (wpos->wz))
4937 	if (do_kill) {
4938 		/* Effect "observed" */
4939 //		if (!quiet && p_ptr->obj_vis[c_ptr->o_idx])
4940 		if (!quiet && p_ptr->obj_vis[this_o_idx]) {
4941 			obvious = TRUE;
4942 		}
4943 
4944 		/* Artifacts, and other objects, get to resist */
4945 		if (is_art || ignore) {
4946 			/* Observe the resist */
4947 //			if (!quiet && p_ptr->obj_vis[c_ptr->o_idx])
4948 			if (!quiet && p_ptr->obj_vis[this_o_idx]) {
4949 				msg_format(Ind, "The %s %s unaffected!",
4950 				    o_name, (plural ? "are" : "is"));
4951 			}
4952 		}
4953 
4954 		/* Kill it */
4955 		else {
4956 			/* Describe if needed */
4957 //			if (!quiet && p_ptr->obj_vis[c_ptr->o_idx] && note_kill)
4958 			if (!quiet && p_ptr->obj_vis[this_o_idx] && note_kill) {
4959 				msg_format(Ind, "\377oThe %s%s", o_name, note_kill);
4960 			}
4961 
4962 			/* Delete the object */
4963 //			delete_object(wpos, y, x);
4964 			delete_object_idx(this_o_idx, TRUE);
4965 
4966 			/* Potions produce effects when 'shattered' */
4967 			if (is_basic_potion && do_smash_effect) {
4968 				/* prevent mass deto exploit */
4969 				if (mon_hit_proj_id == mon_hit_proj_id2) {
4970 					mon_hit_proj_id++;
4971 					(void)potion_smash_effect(who, wpos, y, x, o_sval);
4972 					mon_hit_proj_id2++;
4973 				} else (void)potion_smash_effect(who, wpos, y, x, o_sval);
4974 			}
4975 
4976 			if (!quiet) {
4977 				/* Redraw */
4978 				everyone_lite_spot(wpos, y, x);
4979 			}
4980 		}
4981 	}
4982     }
4983 
4984 	/* Return "Anything seen?" */
4985 	return (obvious);
4986 }
4987 
4988 
4989 #if 0 /* commented out in project_m */
4990 /*
4991  * Psionic attacking of high level demons/undead can backlash
4992  */
4993 static bool psi_backlash(int Ind, int m_idx, int dam)
4994 {
4995 	monster_type *m_ptr = &m_list[m_idx];
4996 	monster_race *r_ptr = race_inf(m_ptr);
4997 	char m_name[MNAME_LEN];
4998 	player_type *p_ptr;
4999 
5000 	if (!Ind) return FALSE;
5001 
5002 	p_ptr = Players[Ind];
5003 
5004 	if ((r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) &&
5005 		(r_ptr->level > p_ptr->lev/2) && !rand_int(2))
5006 	{
5007 		monster_desc(Ind, m_name, m_idx, 0);
5008 		msg_format(Ind, "%^s's corrupted mind backlashes your attack!",
5009 				   m_name);
5010 		project(0 - Ind, m_idx, 0, p_ptr->py, p_ptr->px ,dam / 3, GF_PSI, 0, "");
5011 		return TRUE;
5012 	}
5013 	return FALSE;
5014 }
5015 #endif
5016 
5017 
5018 /*
5019  * Helper function for "project()" below.
5020  *
5021  * Handle a beam/bolt/ball causing damage to a monster.
5022  *
5023  * This routine takes a "source monster" (by index) which is mostly used to
5024  * determine if the player is causing the damage, and a "radius" (see below),
5025  * which is used to decrease the power of explosions with distance, and a
5026  * location, via integers which are modified by certain types of attacks
5027  * (polymorph and teleport being the obvious ones), a default damage, which
5028  * is modified as needed based on various properties, and finally a "damage
5029  * type" (see below).
5030  *
5031  * Note that this routine can handle "no damage" attacks (like teleport) by
5032  * taking a "zero" damage, and can even take "parameters" to attacks (like
5033  * confuse) by accepting a "damage", using it to calculate the effect, and
5034  * then setting the damage to zero.  Note that the "damage" parameter is
5035  * divided by the radius, so monsters not at the "epicenter" will not take
5036  * as much damage (or whatever)...
5037  *
5038  * Note that "polymorph" is dangerous, since a failure in "place_monster()"'
5039  * may result in a dereference of an invalid pointer.  XXX XXX XXX
5040  *
5041  * Various messages are produced, and damage is applied.
5042  *
5043  * Just "casting" a substance (i.e. plasma) does not make you immune, you must
5044  * actually be "made" of that substance, or "breathe" big balls of it.
5045  *
5046  * We assume that "Plasma" monsters, and "Plasma" breathers, are immune
5047  * to plasma.
5048  *
5049  * We assume "Nether" is an evil, necromantic force, so it doesn't hurt undead,
5050  * and hurts evil less.  If can breath nether, then it resists it as well.
5051  *
5052  * Damage reductions use the following formulas:
5053  *   Note that "dam = dam * 6 / (randint(6) + 6);"
5054  *	 gives avg damage of .655, ranging from .858 to .500
5055  *   Note that "dam = dam * 5 / (randint(6) + 6);"
5056  *	 gives avg damage of .544, ranging from .714 to .417
5057  *   Note that "dam = dam * 4 / (randint(6) + 6);"
5058  *	 gives avg damage of .444, ranging from .556 to .333
5059  *   Note that "dam = dam * 3 / (randint(6) + 6);"
5060  *	 gives avg damage of .327, ranging from .427 to .250
5061  *   Note that "dam = dam * 2 / (randint(6) + 6);"
5062  *	 gives something simple.
5063  *
5064  * In this function, "result" messages are postponed until the end, where
5065  * the "note" string is appended to the monster name, if not NULL.  So,
5066  * to make a spell have "no effect" just set "note" to NULL.  You should
5067  * also set "notice" to FALSE, or the player will learn what the spell does.
5068  *
5069  * We attempt to return "TRUE" if the player saw anything "useful" happen.
5070  *
5071  * IMPORTANT: Keep approx_damage() in sync with this.
5072  */
5073 static bool project_m(int Ind, int who, int y_origin, int x_origin, int r, struct worldpos *wpos, int y, int x, int dam, int typ, int flg)
5074 {
5075 	int i = 0, div, k, k_elec, k_sound, k_lite;
5076 
5077 	monster_type *m_ptr;
5078 	monster_race *r_ptr;
5079 
5080 	cptr name;
5081 
5082 	/* Is the monster "seen"? */
5083 	bool seen;
5084 	/* Were the "effects" obvious (if seen)? */
5085 	bool obvious = FALSE;
5086 
5087 	/* do not notice things the player did to themselves by ball spell */
5088 	/* fix me XXX XXX XXX */
5089 
5090 	int priest_spell = 0;
5091 	/* the_sandman: the priest spell? (0 or 1) */
5092 	if (dam == 9999 && typ == GF_OLD_DRAIN) {
5093 		priest_spell = 1;
5094 		dam = 2;	// the real damage
5095 	}
5096 
5097 	/* Polymorph setting (true or false) */
5098 	int do_poly = 0;
5099 	/* Teleport setting (max distance) */
5100 	int do_dist = 0;
5101 	/* Blindness setting (amount to confuse) */
5102 	int do_blind = 0;
5103 	/* Confusion setting (amount to confuse) */
5104 	int do_conf = 0;
5105 	/* Stunning setting (amount to stun) */
5106 	int do_stun = 0;
5107 	/* Sleep amount (amount to sleep) */
5108 	int do_sleep = 0;
5109 	/* Fear amount (amount to fear) */
5110 	int do_fear = 0;
5111 
5112 	/* Hold the monster name */
5113 	char m_name[MNAME_LEN];
5114 
5115 	bool resist = FALSE;
5116 	/* Assume no note */
5117 	cptr note = NULL;
5118 
5119 	/* Assume a default death */
5120 	cptr note_dies = " dies";
5121 	bool quiet; /* no message output */
5122 	bool quiet_dam = FALSE; /* no damage message output */
5123 
5124 	int plev = 25; /* replacement dummy for when a monster isn't
5125 			  affected by a real player but by eg a trap */
5126 
5127 	cave_type **zcave;
5128 	cave_type *c_ptr;
5129 	player_type *p_ptr = NULL;
5130 
5131 
5132 	if (!(zcave = getcave(wpos))) return(FALSE);
5133 	c_ptr = &zcave[y][x];
5134 
5135 	/* hack -- by trap */
5136 	quiet = ((Ind <= 0 || who <= PROJECTOR_UNUSUAL) ? TRUE : (0 - Ind == c_ptr->m_idx ? TRUE : FALSE));
5137 
5138 //	if(quiet) return(FALSE);
5139 	if (Ind <= 0 || 0 - Ind == c_ptr->m_idx) return(FALSE);
5140 	if (!quiet) {
5141 		p_ptr = Players[Ind];
5142 		plev = p_ptr->lev;
5143 	}
5144 
5145 	/* Nobody here */
5146 	if (c_ptr->m_idx <= 0) return (FALSE);
5147 
5148 	/* Acquire monster pointer */
5149 	m_ptr = &m_list[c_ptr->m_idx];
5150 
5151 	/* Prevent recursively afflicted potion_smash_effect() hits */
5152 	if (mon_hit_proj_id != mon_hit_proj_id2) {
5153 		if (m_ptr->hit_proj_id == mon_hit_proj_id) return(FALSE);
5154 		else m_ptr->hit_proj_id = mon_hit_proj_id;
5155 	}
5156 
5157 	/* Acquire race pointer */
5158 	r_ptr = race_inf(m_ptr);
5159 
5160 	/* Acquire name */
5161 	name = r_name_get(m_ptr);
5162 
5163 	/* Never affect projector */
5164 	if ((who > 0) && (c_ptr->m_idx == who)) return (FALSE);
5165 
5166 	/* Never hurt golem */
5167 	if (who < 0 && who > PROJECTOR_UNUSUAL) {
5168 //if (IS_PVP) {
5169 		if (Players[-who]->id == m_ptr->owner) return (FALSE);
5170 	}
5171 
5172 	/* Set the "seen" flag */
5173 	if (!quiet) {
5174 		seen = p_ptr->mon_vis[c_ptr->m_idx];
5175 		/* Cannot 'hear' if too far */
5176 		if (!seen && distance(p_ptr->py, p_ptr->px, y, x) > MAX_SIGHT)
5177 			quiet = TRUE;
5178 	}
5179 	else seen = FALSE;
5180 
5181 
5182 	/* Get the monster name (BEFORE polymorphing) */
5183 	if (!quiet) monster_desc(Ind, m_name, c_ptr->m_idx, 0);
5184 
5185 
5186 	/* Handle reflection - it's back, though weaker - C. Blue */
5187 	if ((r_ptr->flags2 & RF2_REFLECTING) &&
5188 	    (flg & PROJECT_KILL) && !(flg & (PROJECT_NORF | PROJECT_JUMP)) /* only for fire_bolt() */
5189 	    && magik(50)) {
5190 		if (seen) msg_print(Ind, "Your attack was deflected.");
5191 		return TRUE; /* notice */
5192 	}
5193 
5194 #ifdef USE_BLOCKING
5195 	/* handle blocking (deflection) */
5196         if (strchr("hHJkpPty", r_ptr->d_char) && /* leaving out Yeeks (else Serpent Man 'J') */
5197             !(r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags8 & RF8_NO_BLOCK) &&
5198 	    (flg & PROJECT_KILL) && !(flg & (PROJECT_NORF | PROJECT_JUMP | PROJECT_NODF)) /* only for fire_bolt() */
5199             && !rand_int(52 - r_ptr->level / 3)) { /* small chance to block spells */
5200 		if (seen) {
5201 			char hit_desc[MAX_CHARS];
5202 	                sprintf(hit_desc, "\377%c%s blocks.", COLOUR_BLOCK_MON, m_name);
5203     		        hit_desc[0] = toupper(hit_desc[0]);
5204 	                msg_print(Ind, hit_desc);
5205 		}
5206 		return TRUE; /* notice */
5207         }
5208 #endif
5209 
5210 
5211 	/* Extract radius */
5212 	div = r + 1;
5213 
5214 	/* Decrease damage */
5215 	dam = radius_damage(dam, div, typ);
5216 
5217 
5218 	/* Mega-Hack */
5219 	project_m_n++;
5220 	project_m_x = x;
5221 	project_m_y = y;
5222 
5223 
5224 
5225 	/* Some monsters get "destroyed" */
5226 	if ((r_ptr->flags3 & RF3_DEMON) ||
5227 		(r_ptr->flags3 & RF3_UNDEAD) ||
5228 		(r_ptr->flags2 & RF2_STUPID) ||
5229 		(strchr("AEvg", r_ptr->d_char)))
5230 	{
5231 		/* Special note at death */
5232 		note_dies = " is destroyed";
5233 	}
5234 
5235 
5236 	/* Hack: GF_LIFEHEAL might heal or kill a monster */
5237 	if (typ == GF_LIFEHEAL) {
5238 		if (r_ptr->flags3 & RF3_UNDEAD) {
5239 			typ = GF_HOLY_FIRE;
5240 		} else {
5241 			typ = GF_OLD_HEAL;
5242 		}
5243 	}
5244 
5245 
5246 	/* Analyze the damage type */
5247 	switch (typ) {
5248 		/* psionic mana drain */
5249 		case GF_SILENCE:
5250 			/* hacks: extract power (probability for succeeding) */
5251 			i = dam % 100; /* 1..51 (school 10..50) */
5252 			k = dam - (i * 100);
5253 			/* calculate resistance % chance based on skill level and monster level */
5254 			i += 18;
5255 			i *= i;
5256 			i = i / (r_ptr->level ? r_ptr->level : 1);
5257 			if (i > 69) i = 69; /* cap at 95% */
5258 			i = (i * 138) / 100; /* finalize calculation */
5259 			i = 100 - i;
5260 #ifdef TEST_SERVER
5261 			s_printf("GF_SILENCE: chance i=%d, duration k=%d\n", i, k);
5262 #endif
5263 			/* test resistance */
5264 			if (!((r_ptr->flags4 & RF4_SPELLCASTER_MASK) |
5265 			    (r_ptr->flags5 & RF5_SPELLCASTER_MASK) |
5266 			    (r_ptr->flags6 & RF6_SPELLCASTER_MASK) |
5267 			    (r_ptr->flags0 & RF0_SPELLCASTER_MASK)) ||
5268 			    (r_ptr->level >= 98 && (r_ptr->flags1 & RF1_UNIQUE)) ||
5269 			     m_ptr->silenced != 0) { /* successful attempt also leads to cooldown! */
5270 				note = " is unaffected";
5271 			} else if (((r_ptr->flags1 & RF1_UNIQUE) && magik(50)) ||
5272 			    ((r_ptr->flags2 & RF2_POWERFUL) && magik(50)) ||
5273 			    magik(i)) {
5274 				/* hack: A few turns of immunity from another attempt! */
5275 				m_ptr->silenced = -k;
5276 				note = " resists the effect";
5277 			} else {
5278 				/* extract and apply duration */
5279 				m_ptr->silenced = k;
5280 				note = " loses psychic energy";
5281 			}
5282 			/* no real HP damage */
5283 			dam = 0; quiet_dam = TRUE;
5284 			break;
5285 		/* PSIONICS */
5286 		case GF_PSI:
5287 		{
5288 			if (seen) obvious = TRUE;
5289 			note_dies = " collapses, a mindless husk,";
5290 
5291 			/* Check resist/immunity */
5292 			if ((r_ptr->flags9 & RF9_IM_PSI) || (r_ptr->flags2 & RF2_EMPTY_MIND) ||
5293 			    (r_ptr->flags3 & RF3_NONLIVING))
5294 			{
5295 				note = " is unaffected";
5296 				dam = 0;
5297 				quiet_dam = TRUE;
5298 				break;
5299 			} else if ((r_ptr->flags9 & RF9_RES_PSI) && rand_int(3)) {
5300 				resist = TRUE;
5301 			} else if ((r_ptr->flags3 & RF3_UNDEAD) && rand_int(2)) {
5302 				resist = TRUE;
5303 			} else if ((r_ptr->flags2 & RF2_STUPID) ||
5304 			    ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags2 & RF2_CAN_SPEAK))) {
5305 				resist = TRUE;
5306 			} else if (r_ptr->flags2 & RF2_WEIRD_MIND) {
5307 				if (rand_int(5)) resist = TRUE;
5308 				else {
5309 					note = " resists somewhat";
5310 					dam = (dam * 3 + 1) / 4;
5311 				}
5312 			} else if (!rand_int(20)) {
5313 				resist = TRUE;
5314 			}
5315 
5316 			/* Check backlash vs caster */
5317 //			if (psi_backlash(Ind, c_ptr->m_idx, dam)) resist = TRUE;
5318 
5319 			/* Check susceptibility */
5320 #if 0
5321 /* vs f-im evil: similar dam to ood, somewhat more than (holy) ff (at 0 s.pow).
5322    however: max mana cost is only 15 instead of 25(ff:30). */
5323 	/* note: could be && !(uni && powerful), but some hi-lv
5324 	   uniques might need powerful flag, strangely lacking it:
5325 	   nodens, mephistopheles, kronos, mouth of sauron */
5326 			if ((r_ptr->flags2 & RF2_SMART) &&
5327 			    !(r_ptr->flags1 & RF1_UNIQUE)) {
5328 			if ((r_ptr->flags2 & RF2_SMART) &&
5329 			    !((r_ptr->flags1 & RF1_UNIQUE) &&
5330 			    (r_ptr->flags2 & RF2_POWERFUL))) {
5331 #endif /* fine for now maybe: */
5332 			if (r_ptr->flags2 & RF2_SMART) {
5333 				if (!resist) {
5334 					note = " is hit hard";
5335 					dam += dam / 2;
5336 				}
5337 			}
5338 			if (((m_ptr->confused > 0) && !rand_int(3)) ||
5339 			    ((m_ptr->confused > 20) && !rand_int(3)) ||
5340 			    ((m_ptr->confused > 50) && !rand_int(3))) {
5341 				resist = FALSE;
5342 				dam = dam * (3 + randint(7)) / 4;
5343 			}
5344 
5345 			/* Apply resistance, damage, and effects */
5346 			if (resist) {
5347 				note = " resists";
5348 				dam /= 2;
5349 				if (!(r_ptr->flags3 & RF3_NO_CONF) && !rand_int(10)) do_conf = randint(8);
5350 			} else if (randint(dam > 20 ? 20 : dam) > randint(r_ptr->level)) {
5351 				do_stun = randint(6);
5352 				do_conf = randint(20);
5353 				if (!(r_ptr->flags3 & RF3_NO_SLEEP)) do_sleep = rand_int(2) ? 5 + randint(randint(60)) : 0;
5354 				if (!(r_ptr->flags3 & RF3_NO_FEAR)) do_fear = randint(15);
5355 			}
5356   			break;
5357 		}
5358 		/* Mindcrafter's charm spell, makes monsters ignore you and your teammates (mostly..) */
5359 		case GF_CHARMIGNORE: {
5360 			int res = 1;
5361 
5362 			/* No "real" damage */
5363 			dam = 0;
5364 			quiet_dam = TRUE;
5365 
5366 			/* paranoia */
5367 			if (Ind < 1) break;
5368 
5369 			/* don't affect sleeping targets maybe */
5370 			if (m_ptr->csleep) break;
5371 
5372 			/* don't affect hurt monsters! */
5373 			if (m_ptr->hp < m_ptr->maxhp) {
5374 				note = " seems too agitated to be charmed";
5375 				break;
5376 			}
5377 
5378 			/* not successfully charmed? */
5379 			if ((r_ptr->flags9 & RF9_IM_PSI) ||
5380 			    (r_ptr->flags1 & RF1_UNIQUE) ||
5381 			    (r_ptr->flags3 & RF3_UNDEAD) ||
5382 			    (r_ptr->flags2 & RF2_EMPTY_MIND) ||
5383 			    (r_ptr->flags3 & RF3_NONLIVING)) {
5384 				note = " is unaffected";
5385 				break;
5386 			}
5387 			if (r_ptr->flags2 & RF2_SMART) res <<= 1;
5388 			if (r_ptr->flags3 & RF3_NO_CONF) res <<= 1;
5389 			if (r_ptr->flags1 & RF1_UNIQUE) res <<= 1;
5390 			if (r_ptr->flags2 & RF2_POWERFUL) res <<= 1;
5391 			if (magik(100 - 100 / res)) {
5392 				note = " resists the effect";
5393 				break;
5394 			}
5395 
5396 			/* remember who charmed us */
5397 			m_ptr->charmedignore = Ind;
5398 
5399 			/* count our victims, just for optimization atm */
5400 			p_ptr->mcharming++;
5401 			note = " seems to forget you were an enemy";
5402 			break;
5403 		}
5404 
5405 		/* Earthquake the area */
5406 		case GF_EARTHQUAKE:
5407 		{
5408 			dam = 0;
5409 			break;
5410 		}
5411 
5412 			/* Magic Missile -- pure damage */
5413 		case GF_MISSILE:
5414 		{
5415 			if (seen) obvious = TRUE;
5416 			break;
5417 		}
5418 
5419 
5420 		/* Acid */
5421 		case GF_ACID:
5422 		{
5423 			if (seen) obvious = TRUE;
5424 			if (r_ptr->flags3 & RF3_IM_ACID)
5425 			{
5426 				note = " is immune";
5427 				dam = 0;
5428 #ifdef OLD_MONSTER_LORE
5429 				if (seen) r_ptr->r_flags3 |= RF3_IM_ACID;
5430 #endif
5431 			}
5432 			else if (r_ptr->flags9 & RF9_RES_ACID)
5433 			{
5434 				note = " resists";
5435 				dam /= 4;
5436 #ifdef OLD_MONSTER_LORE
5437 				if (seen) r_ptr->r_flags9 |= RF9_RES_ACID;
5438 #endif
5439 			}
5440 			else if (r_ptr->flags9 & RF9_SUSCEP_ACID)
5441 			{
5442 				note = " is hit hard";
5443 				dam *= 2;
5444 #ifdef OLD_MONSTER_LORE
5445 				if (seen) r_ptr->r_flags9 |= RF9_SUSCEP_ACID;
5446 #endif
5447 			}
5448 			break;
5449 		}
5450 
5451 		/* Electricity */
5452 		case GF_ELEC:
5453 		{
5454 			if (seen) obvious = TRUE;
5455 			if (r_ptr->flags3 & RF3_IM_ELEC)
5456 			{
5457 				note = " is immune";
5458 				dam = 0;
5459 #ifdef OLD_MONSTER_LORE
5460 				if (seen) r_ptr->r_flags3 |= RF3_IM_ELEC;
5461 #endif
5462 			}
5463 			else if (r_ptr->flags9 & RF9_RES_ELEC)
5464 			{
5465 				note = " resists";
5466 				dam /= 4;
5467 #ifdef OLD_MONSTER_LORE
5468 				if (seen) r_ptr->r_flags9 |= RF9_RES_ELEC;
5469 #endif
5470 			}
5471 			else if (r_ptr->flags9 & RF9_SUSCEP_ELEC)
5472 			{
5473 				note = " is hit hard";
5474 				dam *= 2;
5475 #ifdef OLD_MONSTER_LORE
5476 				if (seen) r_ptr->r_flags9 |= RF9_SUSCEP_ELEC;
5477 #endif
5478 			}
5479 			break;
5480 		}
5481 
5482 		/* Fire damage */
5483 		case GF_FIRE:
5484 		{
5485 			if (seen) obvious = TRUE;
5486 			if (r_ptr->flags3 & RF3_IM_FIRE)
5487 			{
5488 				note = " is immune";
5489 				dam = 0;
5490 #ifdef OLD_MONSTER_LORE
5491 				if (seen) r_ptr->r_flags3 |= RF3_IM_FIRE;
5492 #endif
5493 			}
5494 			else if (r_ptr->flags9 & RF9_RES_FIRE)
5495 			{
5496 				note = " resists";
5497 				dam /= 4;
5498 #ifdef OLD_MONSTER_LORE
5499 				if (seen) r_ptr->r_flags9 |= RF9_RES_FIRE;
5500 #endif
5501 			}
5502 			else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
5503 			{
5504 				note = " is hit hard";
5505 				dam *= 2;
5506 #ifdef OLD_MONSTER_LORE
5507 				if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_FIRE;
5508 #endif
5509 			}
5510 			break;
5511 		}
5512 
5513 		/* Cold */
5514 		case GF_COLD:
5515 		{
5516 			if (seen) obvious = TRUE;
5517 			if (r_ptr->flags3 & RF3_IM_COLD)
5518 			{
5519 				note = " is immune";
5520 				dam = 0;
5521 #ifdef OLD_MONSTER_LORE
5522 				if (seen) r_ptr->r_flags3 |= RF3_IM_COLD;
5523 #endif
5524 			}
5525 			else if (r_ptr->flags9 & RF9_RES_COLD)
5526 			{
5527 				note = " resists";
5528 				dam /= 4;
5529 #ifdef OLD_MONSTER_LORE
5530 				if (seen) r_ptr->r_flags9 |= RF9_RES_COLD;
5531 #endif
5532 			}
5533 			else if (r_ptr->flags3 & RF3_SUSCEP_COLD)
5534 			{
5535 				note = " is hit hard";
5536 				dam *= 2;
5537 #ifdef OLD_MONSTER_LORE
5538 				if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_COLD;
5539 #endif
5540 			}
5541 			break;
5542 		}
5543 
5544 		/* Poison */
5545 		case GF_POIS:
5546 		{
5547 			if (seen) obvious = TRUE;
5548 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
5549 			    (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
5550 			    (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
5551 			{
5552 				note = " is immune";
5553 				dam = 0;
5554 #ifdef OLD_MONSTER_LORE
5555 				if (seen) r_ptr->r_flags3 |= RF3_IM_POIS;
5556 #endif
5557 			}
5558 			else if (r_ptr->flags9 & RF9_RES_POIS)
5559 			{
5560 				note = " resists";
5561 				dam /= 4;
5562 #ifdef OLD_MONSTER_LORE
5563 				if (seen) r_ptr->r_flags9 |= RF9_RES_POIS;
5564 #endif
5565 			}
5566 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
5567 			{
5568 				note = " is hit hard";
5569 				dam *= 2;
5570 #ifdef OLD_MONSTER_LORE
5571 				if (seen) r_ptr->r_flags9 |= RF9_SUSCEP_POIS;
5572 #endif
5573 			}
5574 			break;
5575 		}
5576 
5577 		/* Thick Poison */
5578 		case GF_UNBREATH:
5579 		{
5580 			if (seen) obvious = TRUE;
5581 //			if (magik(15)) do_pois = (10 + randint(11) + r) / (r + 1);
5582 			if ((r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
5583 				(r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)) ||
5584 				(m_ptr->r_idx == RI_MORGOTH)) /* <- Morgoth */
5585 			{
5586 				note = " is immune";
5587 				dam = 0;
5588 //				do_pois = 0;
5589 			}
5590 			else if (r_ptr->flags3 & RF3_IM_POIS)
5591 			{
5592 				note = " resists";
5593 				dam = (dam * 2) / 4;
5594 #ifdef OLD_MONSTER_LORE
5595 				if (seen) r_ptr->r_flags3 |= RF3_IM_POIS;
5596 #endif
5597 			}
5598 			else if (r_ptr->flags9 & RF9_RES_POIS)
5599 			{
5600 				note = " resists slightly";
5601 				dam = (dam * 3) / 4;
5602 #ifdef OLD_MONSTER_LORE
5603 				if (seen) r_ptr->r_flags9 |= RF9_RES_POIS;
5604 #endif
5605 			}
5606 #if 0
5607 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
5608 			{
5609 				note = " is hit hard";
5610 				dam *= 2;
5611 #ifdef OLD_MONSTER_LORE
5612 				if (seen) r_ptr->r_flags9 |= RF9_SUSCEP_POIS;
5613 #endif
5614 			}
5615 #endif
5616 			break;
5617 		}
5618 
5619 		case GF_HELL_FIRE:
5620 		{
5621 			if (seen) obvious = TRUE;
5622 			if (r_ptr->flags3 & (RF3_GOOD))
5623 			{
5624 				if (r_ptr->flags3 & RF3_IM_FIRE)
5625 				{
5626 					note = " resists";
5627 					dam *= 2; dam /= 2;//(randint(4)+3);
5628 #ifdef OLD_MONSTER_LORE
5629 					if (seen) r_ptr->r_flags3 |= RF3_IM_FIRE;
5630 #endif
5631 				}
5632 				else if (r_ptr->flags9 & RF9_RES_FIRE)
5633 				{
5634 					note = " is hit";
5635 					dam = (dam * 3) / 2;
5636 #ifdef OLD_MONSTER_LORE
5637 					if (seen) r_ptr->r_flags9 |= RF9_RES_FIRE;
5638 #endif
5639 				}
5640 #if 0
5641 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
5642 				{
5643 					note = " is hit hard";
5644 					dam *= 2;
5645 #ifdef OLD_MONSTER_LORE
5646 					if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_FIRE;
5647 #endif
5648 				}
5649 #endif
5650 				else
5651 				{
5652 					dam *= 2;
5653 					note = " is hit hard";
5654 					//note = " is hit";
5655 				}
5656 #ifdef OLD_MONSTER_LORE
5657 				if (seen) r_ptr->r_flags3 |= (RF3_GOOD);
5658 #endif
5659 			}
5660 			else
5661 			{
5662 				if (r_ptr->flags3 & RF3_IM_FIRE)
5663 				{
5664 					note = " resists a lot";
5665 					dam *= 2; dam /= 4;//(randint(6)+10);
5666 #ifdef OLD_MONSTER_LORE
5667 					if (seen) r_ptr->r_flags3 |= RF3_IM_FIRE;
5668 #endif
5669 				}
5670 				else if (r_ptr->flags9 & RF9_RES_FIRE)
5671 				{
5672 					note = " resists";
5673 					dam = (dam * 3) / 4;
5674 #ifdef OLD_MONSTER_LORE
5675 					if (seen) r_ptr->r_flags9 |= RF9_RES_FIRE;
5676 #endif
5677 				}
5678 #if 0
5679 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
5680 				{
5681 					note = " resists slightly";
5682 					dam /= 2;
5683 #ifdef OLD_MONSTER_LORE
5684 					if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_FIRE;
5685 #endif
5686 				}
5687 #endif
5688 				else
5689 				{
5690 					note = " is hit";
5691 					//dam *= 5; dam /= (randint(3)+4);
5692 				}
5693 			}
5694 			if (r_ptr->flags3 & (RF3_EVIL)) dam = (dam * 2) / 3;
5695 			break;
5696 		}
5697 
5698 		/* Holy Orb -- hurts Evil */
5699 		case GF_HOLY_ORB:
5700 		{
5701 			if (seen) obvious = TRUE;
5702 			if (r_ptr->flags3 & (RF3_GOOD))
5703 			{
5704 				dam = 0;
5705 				note = " is immune";
5706 #ifdef OLD_MONSTER_LORE
5707 				if (seen) r_ptr->r_flags3 |= (RF3_GOOD);
5708 #endif
5709 			}
5710 			if (r_ptr->flags3 & RF3_EVIL)
5711 			{
5712 				note = " is hit hard";
5713 				dam *= 2;
5714 #ifdef OLD_MONSTER_LORE
5715 				if (seen) r_ptr->r_flags3 |= RF3_EVIL;
5716 #endif
5717 			}
5718 			break;
5719 		}
5720 
5721 		/* Holy Fire -- hurts Evil, Good are immune, others _resist_ */
5722 		case GF_HOLY_FIRE:
5723 		{
5724 			if (seen) obvious = TRUE;
5725 			if (r_ptr->flags3 & (RF3_GOOD)) {
5726 				dam = 0;
5727 				note = " is immune";
5728 #ifdef OLD_MONSTER_LORE
5729 				if (seen) r_ptr->r_flags3 |= (RF3_GOOD);
5730 #endif
5731 			} else if (r_ptr->flags3 & (RF3_EVIL)) {
5732 				if (r_ptr->flags3 & RF3_IM_FIRE) {
5733 					note = " resists";
5734 					dam *= 2; dam = (dam * 2) / 3;//(randint(4)+3);
5735 #ifdef OLD_MONSTER_LORE
5736 					if (seen) r_ptr->r_flags3 |= RF3_IM_FIRE;
5737 #endif
5738 				} else if (r_ptr->flags9 & RF9_RES_FIRE) {
5739 					note = " is hit";
5740 					dam = (dam * 6) / 4;
5741 #ifdef OLD_MONSTER_LORE
5742 					if (seen) r_ptr->r_flags9 |= RF9_RES_FIRE;
5743 #endif
5744 				}
5745 #if 0
5746 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE) {
5747 					note = " is hit hard";
5748 					dam *= 2;
5749  #ifdef OLD_MONSTER_LORE
5750 					if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_FIRE;
5751  #endif
5752 				}
5753 #endif
5754 				else {
5755 					dam *= 2;
5756 					note = " is hit hard";
5757 					//note = " is hit";
5758 				}
5759 #ifdef OLD_MONSTER_LORE
5760 				if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
5761 #endif
5762 			} else {
5763 				if (r_ptr->flags3 & RF3_IM_FIRE) {
5764 					note = " resists a lot";
5765 					dam *= 2; dam /= 3;//(randint(6)+10);
5766 #ifdef OLD_MONSTER_LORE
5767 					if (seen) r_ptr->r_flags3 |= RF3_IM_FIRE;
5768 #endif
5769 				} else if (r_ptr->flags9 & RF9_RES_FIRE) {
5770 					note = " resists";
5771 					dam = (dam * 3) / 4;
5772 #ifdef OLD_MONSTER_LORE
5773 					if (seen) r_ptr->r_flags9 |= RF9_RES_FIRE;
5774 #endif
5775 				}
5776 #if 0
5777 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE) {
5778 					note = " resists slightly";
5779 					dam /= 2;
5780 #ifdef OLD_MONSTER_LORE
5781 					if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_FIRE;
5782 #endif
5783 				}
5784 #endif
5785 				else {
5786 					note = " resists somewhat";
5787 //					dam *= 5; dam /= (randint(3)+4);
5788 				}
5789 			}
5790 			break;
5791 		}
5792 
5793 		/* Arrow -- XXX no defense */
5794 		case GF_ARROW:
5795 		{
5796 			if (seen) obvious = TRUE;
5797 			break;
5798 		}
5799 
5800 		/* Plasma -- Fire/Elec/Force */
5801 		case GF_PLASMA:
5802 		{
5803 			if (seen) obvious = TRUE;
5804 
5805 			do_stun = randint(15) / div;
5806 
5807 			if ((r_ptr->flags3 & RF3_IM_FIRE) && (r_ptr->flags3 & RF3_IM_ELEC)) {
5808 				note = " resists a lot";
5809 				dam /= 9;
5810 			} else {
5811 				if (r_ptr->flags3 & RF3_IM_FIRE) {
5812 					note = " resists a lot";
5813 					dam /= 4;
5814 				} else if (prefix(name, "Plasma") ||
5815 				    (r_ptr->flags4 & RF4_BR_PLAS) ||
5816 				    (r_ptr->flags3 & RF3_RES_PLAS)) {
5817 					note = " resists";
5818 					dam *= 3; dam /= (randint(6) + 6);
5819 				} else if (r_ptr->flags9 & RF9_RES_FIRE) {
5820 					note = " resists somewhat";
5821 					dam *= 3;
5822 					dam /= 5;
5823 				} else if (r_ptr->flags3 & RF3_SUSCEP_FIRE) {
5824 					note = " is hit hard";
5825 					dam = (dam * 3) / 2;
5826 				}
5827 
5828 				if ((r_ptr->flags9 & RF9_RES_ELEC) || (r_ptr->flags3 & RF3_IM_ELEC)) {
5829 					dam *= 4;
5830 					dam /= 5;
5831 				} else if (r_ptr->flags9 & RF9_SUSCEP_ELEC) dam = (dam * 4) / 3;
5832 			}
5833 
5834 			//todo maybe: stun effect? might be op?
5835 
5836 			break;
5837 		}
5838 
5839 		/* Nether -- see above */
5840 		case GF_NETHER_WEAK:
5841 		case GF_NETHER:
5842 			if (seen) obvious = TRUE;
5843 			if (r_ptr->flags3 & RF3_UNDEAD) {
5844 				note = " is immune";
5845 				dam = 0;
5846 #ifdef OLD_MONSTER_LORE
5847 				if (seen) r_ptr->r_flags3 |= RF3_UNDEAD;
5848 #endif
5849 			} else if ((r_ptr->flags4 & RF4_BR_NETH) || (r_ptr->flags3 & RF3_RES_NETH)) {
5850 				note = " resists";
5851 				dam *= 3; dam /= (randint(6) + 6);
5852 			}
5853 //			else if (r_ptr->flags3 & RF3_EVIL)
5854 			else if (r_ptr->flags3 & RF3_DEMON) {
5855 				dam /= 2;
5856 				note = " resists somewhat";
5857 #ifdef OLD_MONSTER_LORE
5858 //				if (seen) r_ptr->r_flags3 |= RF3_EVIL;
5859 				if (seen) r_ptr->r_flags3 |= RF3_DEMON;
5860 #endif
5861 			}
5862 			break;
5863 
5864 		/* Water (acid) damage -- Water spirits/elementals are immune */
5865 		case GF_WATER:
5866 		case GF_VAPOUR:
5867 		{
5868 			if (seen) obvious = TRUE;
5869 			if (r_ptr->flags9 & RF9_IM_WATER) {
5870 				note = " is immune";
5871 				dam = 0;
5872 			} else if (r_ptr->flags7 & RF7_AQUATIC) {
5873 				note = " resists a lot";
5874 				dam /= 9;
5875 			} else if (r_ptr->flags3 & RF3_RES_WATE) {
5876 				note = " resists";
5877 				dam /= 4;
5878 			}
5879 			break;
5880 		}
5881 
5882 		/* Wave = Water + Force */
5883 		case GF_WAVE:
5884 		{
5885 			if (seen) obvious = TRUE;
5886 			if (r_ptr->flags9 & RF9_IM_WATER) {
5887 				note = " is immune";
5888 				dam = 0;
5889 			} else if (r_ptr->flags7 & RF7_AQUATIC) {
5890 				note = " resists a lot";
5891 				dam /= 9;
5892 			} else if (r_ptr->flags3 & RF3_RES_WATE) {
5893 				note = " resists";
5894 				dam /= 4;
5895 			} else do_stun = randint(15) / div;
5896 			break;
5897 		}
5898 
5899 		/* Chaos -- Chaos breathers resist */
5900 		case GF_CHAOS:
5901 		{
5902 			if (seen) obvious = TRUE;
5903 			if (rand_int(r_ptr->level) < 15) do_poly = TRUE;
5904 			do_conf = (5 + randint(11)) / div;
5905 			if ((r_ptr->flags4 & RF4_BR_CHAO) || (r_ptr->flags9 & RF9_RES_CHAOS)) {
5906 				note = " resists";
5907 				dam *= 3; dam /= randint(6) + 6;
5908 				do_poly = FALSE;
5909 			}
5910 			break;
5911 		}
5912 
5913 		/* Shards -- Shard breathers resist */
5914 		case GF_SHARDS:
5915 			if (seen) obvious = TRUE;
5916 			if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS)) {
5917 				note = " resists";
5918 				dam *= 3; dam /= (randint(6) + 6);
5919 			}
5920 			break;
5921 
5922 		/* Rocket: Shard resistance helps (PernA) */
5923 		case GF_INFERNO:
5924 		case GF_DETONATION:
5925 		case GF_ROCKET:
5926 #if 0
5927 //			if (magik(12)) do_cut = (10 + randint(15) +r) / (r + 1);
5928 			if ((r_ptr->flags4 & (RF4_BR_SHAR)) || (r_ptr->flags9 & RF9_RES_SHARDS) ||
5929 			    (r_ptr->flags3 & RF3_IM_FIRE) || prefix(name, "Plasma") ||
5930 			    (r_ptr->flags4 & RF4_BR_PLAS) || (r_ptr->flags3 & RF3_RES_PLAS) ||
5931 			    (r_ptr->flags9 & RF9_RES_FIRE)) {
5932 				note = " resists somewhat";
5933 				dam /= 2;
5934 //				do_cut = 0;
5935 			}
5936 #else /* more distinct */
5937 		{
5938 			int res1 = 0, res2 = 0, res3 = 0; //shard,sound,fire
5939 			if ((r_ptr->flags4 & (RF4_BR_SHAR)) || (r_ptr->flags9 & RF9_RES_SHARDS))
5940 				res1 = 1;
5941 			if ((r_ptr->flags4 & RF4_BR_PLAS) || (r_ptr->flags3 & RF3_RES_PLAS) || prefix(name, "Plasma")) {
5942 				res2 = res3 = 1;
5943 			}
5944 			if ((r_ptr->flags4 & (RF4_BR_SOUN)) || (r_ptr->flags9 & RF9_RES_SOUND))
5945 				res2 = 1;
5946 			if (r_ptr->flags3 & RF3_IM_FIRE)
5947 				res3 = 3;
5948 			else if (r_ptr->flags9 & RF9_RES_FIRE)
5949 				res3 = 1;
5950 
5951 			switch (res1 + res2 + res3) {
5952 			case 0: break;
5953 			case 1: case 2:
5954 				note = " resists somewhat";
5955 				dam = (dam * 3 + 3) / 4;
5956 //				do_cut = 0;
5957 				break;
5958 			default:
5959 				note = " resists";
5960 				dam /= 2;
5961 				break;
5962 			}
5963 		}
5964 #endif
5965 			if (seen) obvious = TRUE;
5966 			break;
5967 
5968 		/* Sound -- Sound breathers resist */
5969 		case GF_STUN:
5970 			do_stun = (10 + randint(15)) / div;
5971 			break;
5972 
5973 		/* Sound -- Sound breathers resist */
5974 		case GF_SOUND:
5975 			if (seen) obvious = TRUE;
5976 			do_stun = randint(15) / div;
5977 			if ((r_ptr->flags4 & RF4_BR_SOUN) || (r_ptr->flags9 & RF9_RES_SOUND)) {
5978 				note = " resists";
5979 				dam *= 3; dam /= (randint(6) + 6);
5980 			} else if (r_ptr->flags3 & RF3_NO_STUN) {
5981 				note = " resists somewhat";
5982 				dam /= 2;
5983 			}
5984 			break;
5985 
5986 		/* Confusion */
5987 		case GF_CONFUSION:
5988 			if (seen) obvious = TRUE;
5989 			do_conf = (10 + randint(15)) / div;
5990 			if ((r_ptr->flags4 & RF4_BR_CONF) ||
5991 			    (r_ptr->flags4 & RF4_BR_CHAO) || (r_ptr->flags9 & RF9_RES_CHAOS)) {
5992 				note = " resists";
5993 				dam *= 3; dam /= (randint(6) + 6);
5994 			} else if (r_ptr->flags3 & RF3_NO_CONF) {
5995 				note = " resists somewhat";
5996 				dam /= 2;
5997 			}
5998 			break;
5999 
6000 		/* Disenchantment -- Breathers and Disenchanters resist */
6001 		case GF_DISENCHANT:
6002 		{
6003 			if (seen) obvious = TRUE;
6004 			if ((r_ptr->flags4 & RF4_BR_DISE) ||
6005 			    prefix(name, "Disen") ||
6006 			    (r_ptr->flags3 & RF3_RES_DISE)) {
6007 				note = " resists";
6008 				dam *= 3; dam /= (randint(6) + 6);
6009 			}
6010 			break;
6011 		}
6012 
6013 		/* Nexus -- Breathers and Existers resist */
6014 		case GF_NEXUS:
6015 		{
6016 			if (seen) obvious = TRUE;
6017 			if ((r_ptr->flags4 & RF4_BR_NEXU) ||
6018 				prefix(name, "Nexus") ||
6019 				(r_ptr->flags3 & RF3_RES_NEXU))
6020 			{
6021 				note = " resists";
6022 				dam *= 3; dam /= (randint(6) + 6);
6023 			}
6024 			break;
6025 		}
6026 
6027 		/* Force */
6028 		case GF_FORCE:
6029 		{
6030 			if (seen) obvious = TRUE;
6031 			do_stun = randint(15) / div;
6032 			if (r_ptr->flags4 & RF4_BR_WALL) {
6033 				note = " resists";
6034 				dam *= 3; dam /= (randint(6) + 6);
6035 			}
6036 			break;
6037 		}
6038 
6039 		/* Inertia -- breathers resist */
6040 		case GF_INERTIA: //Slowing effect -- NOTE: KEEP CONSISTENT WITH GF_CURSE AND GF_OLD_SLOW
6041 		{
6042 			if (seen) obvious = TRUE;
6043 			if (r_ptr->flags4 & RF4_BR_INER) {
6044 				note = " resists";
6045 				dam *= 3; dam /= (randint(6) + 6);
6046 			}
6047 			/* Powerful monsters can resist */
6048 			else if (r_ptr->flags1 & RF1_UNIQUE) {
6049 			} else if (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) + 10) { /* cannot randint higher? (see 'resist' branch below) */
6050 			} else if (RES_OLD(r_ptr->level, dam)) {
6051 			} else if (m_ptr->mspeed >= 100 && m_ptr->mspeed > m_ptr->speed - 10) /* Normal monsters slow down */
6052 //			else if (m_ptr->mspeed >= 100) /* Normal monsters slow down */
6053 			{
6054 //				if (m_ptr->mspeed > 100) m_ptr->mspeed -= 10;
6055 				m_ptr->mspeed -= 10;
6056 				note = " starts moving slower";
6057 			}
6058 
6059 			break;
6060 		}
6061 
6062 		/* Time -- breathers resist */
6063 		case GF_TIME:
6064 		{
6065 			if (seen) obvious = TRUE;
6066 			if ((r_ptr->flags4 & RF4_BR_TIME) || (r_ptr->flags9 & RF9_RES_TIME)
6067 			    || (r_ptr->flags3 & RF3_DEMON) || (r_ptr->flags3 & RF3_NONLIVING)
6068 			    || (r_ptr->flags3 & RF3_UNDEAD) || (r_ptr->d_char == 'A'))
6069 			{
6070 				note = " resists";
6071 				dam *= 3; dam /= (randint(6) + 6);
6072 			}
6073 #if 1 /* fixed & sanified */
6074 			else if (!quiet && rand_int(3) == 0) { /* only occur if a player cast this */
6075 				long t = m_ptr->hp / 10, tp = damroll(2, plev);
6076 
6077 				note = " loses precious seconds to you";
6078 				m_ptr->energy -= m_ptr->energy / 4;
6079 
6080 				if (t > dam) t = dam;
6081 				if (t > tp) t = tp;
6082 				p_ptr->energy += (t * level_speed(&p_ptr->wpos)) / 500;
6083 				/* Prevent too much energy, preventing overflow too. */
6084 				limit_energy(p_ptr);
6085 			}
6086 #endif
6087 			break;
6088 		}
6089 
6090 		/* Gravity -- breathers resist */
6091 		case GF_GRAVITY:
6092 		{
6093 			bool resist_tele = FALSE;
6094 //			dun_level		*l_ptr = getfloor(wpos);
6095 
6096 			if (seen) obvious = TRUE;
6097 
6098 			if ((r_ptr->flags3 & RF3_RES_TELE) || (r_ptr->flags9 & RF9_IM_TELE)) {
6099 				if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags9 & RF9_IM_TELE)) {
6100 #ifdef OLD_MONSTER_LORE
6101 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6102 #endif
6103 					note = " resists";
6104 					resist_tele = TRUE;
6105 				} else if (m_ptr->level > randint(100)) {
6106 #ifdef OLD_MONSTER_LORE
6107 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6108 #endif
6109 					note = " resists";
6110 					resist_tele = TRUE;
6111 				}
6112 			}
6113 
6114 			if (!resist_tele) do_dist = 10;
6115 			else do_dist = 0;
6116 
6117 			if ((r_ptr->flags4 & RF4_BR_GRAV) ||
6118 			    (r_ptr->flags7 & RF7_CAN_FLY)) {
6119 				note = " resists";
6120 				dam *= 3; dam /= (randint(6) + 6);
6121 				do_dist = 0;
6122 			}
6123 
6124 			//todo maybe: stun effect? might be op?
6125 
6126 			break;
6127 		}
6128 
6129 		/* Pure damage */
6130 		case GF_MANA:
6131 		{
6132 			if (r_ptr->flags9 & RF9_RES_MANA) {
6133 				dam /= 3;
6134 				note = " resists";
6135 			} else if (r_ptr->flags4 & RF4_BR_MANA) {
6136 				dam /= 2;
6137 				note = " resists somewhat";
6138 			}
6139 			if (seen) obvious = TRUE;
6140 			break;
6141 		}
6142 
6143 			/* Meteor -- powerful magic missile */
6144 		case GF_METEOR:
6145 		{
6146 			if (seen) obvious = TRUE;
6147 			do_stun = randint(15) / div;
6148 			break;
6149 		}
6150 
6151 		/* Ice -- Cold + Cuts + Stun */
6152 		case GF_ICE:
6153 		{
6154 			if (seen) obvious = TRUE;
6155 			do_stun = randint(15) / div;
6156 			k = dam;
6157 
6158 			dam = (k * 3) / 5;/* 60% COLD damage */
6159 			if (r_ptr->flags3 & RF3_IM_COLD)
6160 			{
6161 				note = " is immune to cold";
6162 				dam = 0;
6163 #ifdef OLD_MONSTER_LORE
6164 				if (seen) r_ptr->r_flags3 |= RF3_IM_COLD;
6165 #endif
6166 			}
6167 			else if (r_ptr->flags9 & RF9_RES_COLD)
6168 			{
6169 				note = " resists cold";
6170 				dam /= 4;
6171 #ifdef OLD_MONSTER_LORE
6172 				if (seen) r_ptr->r_flags9 |= RF9_RES_COLD;
6173 #endif
6174 			}
6175 			else if (r_ptr->flags3 & RF3_SUSCEP_COLD)
6176 			{
6177 				note = " is hit hard by cold";
6178 				dam *= 2;
6179 #ifdef OLD_MONSTER_LORE
6180 				if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_COLD;
6181 #endif
6182 			}
6183 
6184 			k = (k * 2) / 5;/* 40% SHARDS damage */
6185 			if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS))
6186 			{
6187 				//note = " resists";
6188 				k = (k * 3) / (randint(6) + 6);
6189 			}
6190 			dam = dam + k;
6191 			break;
6192 		}
6193 
6194 		/* Thunder -- Elec + Sound + Light */
6195 		case GF_THUNDER:
6196 		{
6197 			if (seen) obvious = TRUE;
6198 
6199 			k_elec = dam / 3; /* 33% ELEC damage */
6200 			if (r_ptr->flags3 & RF3_IM_ELEC)
6201 			{
6202 				note = " is immune to lightning";
6203 				k_elec = 0;
6204 #ifdef OLD_MONSTER_LORE
6205 				if (seen) r_ptr->r_flags3 |= RF3_IM_ELEC;
6206 #endif
6207 			}
6208 			else if (r_ptr->flags9 & RF9_RES_ELEC)
6209 			{
6210 				note = " resists lightning";
6211 				k_elec /= 4;
6212 #ifdef OLD_MONSTER_LORE
6213 				if (seen) r_ptr->r_flags9 |= RF9_RES_ELEC;
6214 #endif
6215 			}
6216 			else if (r_ptr->flags9 & RF9_SUSCEP_ELEC)
6217 			{
6218 				note = " is hit hard by lightning";
6219 				k_elec *= 2;
6220 #ifdef OLD_MONSTER_LORE
6221 				if (seen) r_ptr->r_flags3 |= RF3_SUSCEP_ELEC;
6222 #endif
6223 			}
6224 
6225 			k_sound = dam / 3; /* 33% SOUND damage */
6226 			do_stun = randint(15) / div;
6227 			if ((r_ptr->flags4 & RF4_BR_SOUN) || (r_ptr->flags9 & RF9_RES_SOUND))
6228 			{
6229 				//note = " resists";
6230 				k_sound *= 3;
6231 				k_sound /= (randint(6) + 6);
6232 			}
6233 
6234 			k_lite = dam / 3; /* 33% LIGHT damage */
6235 			do_blind = damroll(3, (k_lite / 20)) + 1;
6236 			if (r_ptr->d_char == 'A') {
6237 				//note = " is immune";
6238 				k_lite = do_blind = 0;
6239 			} else if ((r_ptr->flags4 & RF4_BR_LITE) || (r_ptr->flags9 & RF9_RES_LITE)) {
6240 				//note = " resists";
6241 				k_lite *= 2;
6242 				k_lite /= (randint(6) + 6);
6243 				do_blind = 0;
6244 			} else if (r_ptr->flags3 & RF3_HURT_LITE) {
6245 #ifdef OLD_MONSTER_LORE
6246 				if (seen) r_ptr->r_flags3 |= RF3_HURT_LITE;
6247 #endif
6248 				//note = " cringes from the light";
6249 				//note_dies = " shrivels away in the light";
6250 				dam *= 2;
6251 			}
6252 
6253 			dam = k_elec + k_sound + k_lite;
6254 			break;
6255 		}
6256 
6257 		/* Drain Life */
6258 		case GF_OLD_DRAIN:
6259 			if (seen) obvious = TRUE;
6260 
6261 			/* Prevent internal overflow (int) - allow up to 35% leech */
6262 			if (m_ptr->hp > 9362)
6263 				dam = (m_ptr->hp / 100) * dam;
6264 			else if (m_ptr->hp > 936)
6265 				dam = ((m_ptr->hp / 10) * dam) / 10;
6266 			else
6267 				dam = (m_ptr->hp * dam) / 100;
6268 			/* Make it have an effect on low-HP monsters such as townies */
6269 			if (!dam) dam = 1;
6270 
6271 			if (typ == GF_OLD_DRAIN) p_ptr->ret_dam = dam;
6272 			else p_ptr->ret_dam = 0; /* paranoia */
6273 
6274 			if ((r_ptr->flags3 & RF3_UNDEAD) ||
6275 //				(r_ptr->flags3 & RF3_DEMON) ||
6276 				(r_ptr->flags3 & RF3_NONLIVING) ||
6277 				(r_ptr->flags1 & RF1_UNIQUE) ||
6278 				(strchr("Egv", r_ptr->d_char)))
6279 			{
6280 #ifdef OLD_MONSTER_LORE
6281 				if (r_ptr->flags3 & RF3_UNDEAD) {
6282 					if (seen) r_ptr->r_flags3 |= RF3_UNDEAD;
6283 				}
6284 //				if (r_ptr->flags3 & RF3_DEMON) {
6285 //					if (seen) r_ptr->r_flags3 |= RF3_DEMON;
6286 //				}
6287 				if (r_ptr->flags3 & RF3_NONLIVING) {
6288 					if (seen) r_ptr->r_flags3 |= RF3_NONLIVING;
6289 				}
6290 				if (r_ptr->flags1 & RF1_UNIQUE) {
6291 					if (seen) r_ptr->r_flags1 |= RF1_UNIQUE;
6292 				}
6293 #endif
6294 
6295 				note = " is unaffected";
6296 				obvious = FALSE;
6297 				dam = 0;
6298 				quiet_dam = TRUE;
6299 				p_ptr->ret_dam = 0;
6300 			}
6301 
6302 			/* the_sandman: return 15% of the damage to player. This is special
6303 			   since (we're not using the upto 35% rule because for the spell
6304 			   (drain cloud) it will be too much) we aim for balance
6305 			   HACK: the priest_spell variable is defined above.
6306 			*/
6307 			if (priest_spell) {
6308 				//msg_format(Ind, "\377gYou are healed for %d hit points", (dam * 15) / 100);
6309 				if (dam) hp_player_quiet(Ind, (dam * 15) / 100, TRUE);
6310 				p_ptr->ret_dam = 0;
6311 			}
6312 
6313 			break;
6314 
6315 		case GF_ANNIHILATION:
6316 			i = dam - 1;
6317 			if (seen) obvious = TRUE;
6318 			if (m_ptr->hp > 9362)
6319 				dam = (m_ptr->hp / 100) * dam;
6320 			else if (m_ptr->hp > 936)
6321 				dam = ((m_ptr->hp / 10) * dam) / 10;
6322 			else
6323 				dam = (m_ptr->hp * dam) / 100;
6324 			/* Make it have an effect on low-HP monsters such as townies */
6325 			if (!dam) dam = 1;
6326 
6327 			if (dam > i * 200) {
6328 				dam = i * 200;
6329 				if ((r_ptr->flags1 & RF1_UNIQUE) ||
6330 				(r_ptr->flags3 & RF3_UNDEAD) ||
6331 				(r_ptr->flags3 & RF3_NONLIVING)) {
6332 				note = " resists";
6333 				dam *= 3; dam /= (randint(6) + 6);
6334 				}
6335 			}
6336 
6337 			if (dam < i * 10 + 100) {
6338 				dam = i * 10 + 100;
6339 				if ((r_ptr->flags1 & RF1_UNIQUE) ||
6340 				(r_ptr->flags3 & RF3_UNDEAD) ||
6341 				(r_ptr->flags3 & RF3_NONLIVING)) {
6342 				note = " resists";
6343 				dam *= 3; dam /= (randint(6) + 6);
6344 				}
6345 			}
6346 		break;
6347 
6348 		/* Polymorph monster (Use "dam" as "power") */
6349 		case GF_OLD_POLY:
6350 			if (seen) obvious = TRUE;
6351 
6352 			/* Attempt to polymorph (see below) */
6353 			do_poly = TRUE;
6354 
6355 			/* Powerful monsters can resist */
6356 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
6357 				(r_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
6358 			{
6359 				note = " is unaffected";
6360 				do_poly = FALSE;
6361 				obvious = FALSE;
6362 			}
6363 
6364 			/* No "real" damage */
6365 			dam = 0;
6366 			quiet_dam = TRUE;
6367 
6368 			break;
6369 
6370 		/* Clone monsters (Ignore "dam") */
6371 		case GF_OLD_CLONE:
6372 			if (seen) obvious = TRUE;
6373 
6374 			/* Heal fully */
6375 			m_ptr->hp = m_ptr->maxhp;
6376 
6377 			/* Speed up */
6378 			if (m_ptr->mspeed < 150) m_ptr->mspeed += 10;
6379 
6380 			/* Attempt to clone. */
6381 			if (multiply_monster(c_ptr->m_idx)) {
6382 				note = " spawns";
6383 			}
6384 
6385 			/* No "real" damage */
6386 			dam = 0;
6387 			quiet_dam = TRUE;
6388 
6389 			break;
6390 
6391 		/* Heal Monster (use "dam" as amount of healing) */
6392 		case GF_OLD_HEAL:
6393 		{
6394 			if (seen) obvious = TRUE;
6395 
6396 			/* Wake up */
6397 			m_ptr->csleep = 0;
6398 
6399 			/* Heal */
6400 			m_ptr->hp += dam;
6401 
6402 			/* No overflow */
6403 			if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
6404 
6405 			/* Redraw (later) if needed */
6406 			update_health(c_ptr->m_idx);
6407 
6408 			/* Message */
6409 			note = " looks healthier";
6410 
6411 			/* No "real" damage */
6412 			dam = 0;
6413 			quiet_dam = TRUE;
6414 			break;
6415 		}
6416 
6417 
6418 		/* Heroism/Berserk Strength for monsters */
6419 		case GF_HERO_MONSTER:
6420 		{
6421 			if (seen) obvious = TRUE;
6422 
6423 			/* Wake up */
6424 			m_ptr->csleep = 0;
6425 
6426 			/* Heal */
6427 			m_ptr->hp += dam;
6428 
6429 			/* No overflow */
6430 			if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
6431 
6432 			/* Redraw (later) if needed */
6433 			update_health(c_ptr->m_idx);
6434 
6435 			/* Message */
6436 			note = " looks healthier";
6437 
6438 			/* No "real" damage */
6439 			dam = 0;
6440 			quiet_dam = TRUE;
6441 
6442 			/* No 'break;' here =) */
6443 		}
6444 
6445 
6446 		/* Remove monster's fear */
6447 		case GF_REMFEAR:
6448 		{
6449 			if (m_ptr->monfear) {
6450 				m_ptr->monfear = 0;
6451 				/* Message */
6452 				note = " becomes courageous again";
6453 				if (seen) obvious = TRUE;
6454 			}
6455 
6456 			/* No "real" damage */
6457 			dam = 0;
6458 			quiet_dam = TRUE;
6459 			break;
6460 		}
6461 
6462 
6463 		/* Speed Monster (Ignore "dam") */
6464 		case GF_OLD_SPEED:
6465 			if ((r_ptr->flags7 & RF7_NO_DEATH) || m_ptr->mspeed >= 150) {
6466 				note = "is unaffected";
6467 			} else {
6468 				if (seen) obvious = TRUE;
6469 
6470 				/* Speed up */
6471 				m_ptr->mspeed += 10;
6472 				note = " starts moving faster";
6473 			}
6474 
6475 			/* No "real" damage */
6476 			dam = 0;
6477 			quiet_dam = TRUE;
6478 			break;
6479 
6480 
6481 		/* Slow Monster (Use "dam" as "power") */
6482 		case GF_OLD_SLOW: //Slowing effect -- NOTE: KEEP CONSISTENT WITH GF_INERTIA AND GF_CURSE
6483 		{
6484 			if (seen) obvious = TRUE;
6485 
6486 			/* Powerful monsters can resist */
6487 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
6488 			    (r_ptr->flags4 & RF4_BR_INER)) {
6489 				note = " is unaffected";
6490 				obvious = FALSE;
6491 			} else if (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) + 10) { /* cannot randint higher? (see 'resist' branch below) */
6492 				note = " resists easily"; /* vs damaging it's "resists a lot" and vs effects it's "resists easily" :-o */
6493 				obvious = FALSE;
6494 			} else if (RES_OLD(r_ptr->level, dam)) {
6495 				note = " resists";
6496 				obvious = FALSE;
6497 			}
6498 			else if (m_ptr->mspeed >= 100 && m_ptr->mspeed > m_ptr->speed - 10) /* Normal monsters slow down */
6499 //			else if (m_ptr->mspeed >= 100) /* Normal monsters slow down */
6500 			{
6501 //				if (m_ptr->mspeed > 100) m_ptr->mspeed -= 10;
6502 				m_ptr->mspeed -= 10;
6503 				note = " starts moving slower";
6504 			} else {
6505 				note = " is unaffected";
6506 				obvious = FALSE;
6507 			}
6508 
6509 			/* No "real" damage */
6510 			dam = 0;
6511 			quiet_dam = TRUE;
6512 			break;
6513 		}
6514 
6515 
6516 		/* Sleep (Use "dam" as "power") */
6517 		case GF_OLD_SLEEP:
6518 		{
6519 			if (seen) obvious = TRUE;
6520 
6521 			/* Attempt a saving throw */
6522 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
6523 				(r_ptr->flags3 & RF3_NO_SLEEP) ||
6524 				RES_OLD(r_ptr->level, dam))
6525 			{
6526 				note = " resists";
6527 				if (r_ptr->flags1 & RF1_UNIQUE) note = " is unaffected";
6528 				/* Memorize a flag */
6529 				if (r_ptr->flags3 & RF3_NO_SLEEP) {
6530 #ifdef OLD_MONSTER_LORE
6531 					if (seen) r_ptr->r_flags3 |= RF3_NO_SLEEP;
6532 #endif
6533 					note = " is unaffected";
6534 				}
6535 
6536 				/* No obvious effect */
6537 				obvious = FALSE;
6538 			} else {
6539 				/* Go to sleep (much) later */
6540 				note = " falls asleep";
6541 				do_sleep = GF_OLD_SLEEP_DUR;
6542 			}
6543 
6544 			/* No "real" damage */
6545 			dam = 0;
6546 			quiet_dam = TRUE;
6547 			break;
6548 		}
6549 
6550 
6551 		/* Confusion (Use "dam" as "power") */
6552 		case GF_OLD_CONF:
6553 		{
6554 			if (seen) obvious = TRUE;
6555 
6556 			/* Get confused later */
6557 			do_conf = damroll(3, (dam / 2)) + 1;
6558 
6559 			/* Attempt a saving throw */
6560 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
6561 				(r_ptr->flags3 & RF3_NO_CONF) ||
6562 				RES_OLD(r_ptr->level, dam))
6563 			{
6564 				/* No obvious effect */
6565 				note = " resists";
6566 				obvious = FALSE;
6567 
6568 				if (r_ptr->flags1 & RF1_UNIQUE) note = " is unaffected";
6569 
6570 				/* Memorize a flag */
6571 				if (r_ptr->flags3 & RF3_NO_CONF) {
6572 #ifdef OLD_MONSTER_LORE
6573 					if (seen) r_ptr->r_flags3 |= RF3_NO_CONF;
6574 #endif
6575 					note = " is unaffected";
6576 				}
6577 
6578 				/* Resist */
6579 				do_conf = 0;
6580 			}
6581 
6582 			/* No "real" damage */
6583 			dam = 0;
6584 			quiet_dam = TRUE;
6585 			break;
6586 		}
6587 
6588 		/* Confusion (Use "dam" as "power") */
6589 		case GF_BLIND:
6590 		{
6591 			if (seen) obvious = TRUE;
6592 
6593 			/* Get blinded later */
6594 			do_blind = dam;
6595 
6596 			/* No "real" damage */
6597 			dam = 0;
6598 			quiet_dam = TRUE;
6599 			break;
6600 		}
6601 
6602 		/* The new cursing spell - basically slow/blind/conf all in one. the_sandman */
6603 		/* Following the pattern, use "dam" as "power". */
6604 		case GF_CURSE:
6605 		{
6606 			/* Assume no obvious effect */
6607 			obvious = FALSE;
6608 			int curse = randint(3);
6609 			if (curse == 1) { //Slowing effect -- NOTE: KEEP CONSISTENT WITH GF_INERTIA AND GF_OLD_SLOW
6610 /*				if (((r_ptr->flags1 & RF1_UNIQUE) && magik(r_ptr->level * 4)) ||
6611 					magik(r_ptr->level * 2)) {*/
6612 				if ((r_ptr->flags1 & RF1_UNIQUE) ||
6613 				    (r_ptr->flags4 & RF4_BR_INER)) {
6614 					note = " is unaffected";
6615 				} else if (RES_OLD(r_ptr->level, dam / 3)) {
6616 					note = " resists";
6617 				} else if (m_ptr->mspeed > 100 && m_ptr->mspeed > m_ptr->speed - 10) {
6618 					m_ptr->mspeed -= 10;
6619 					note = " starts moving slower";
6620 					if (seen) obvious = TRUE;
6621 				} else {
6622 					note = " is unaffected";
6623 				}
6624 				dam = 0;
6625 				quiet_dam = TRUE;
6626 				break;
6627 			} else if (curse == 2) { //Conf
6628 				/* Get confused later */
6629 				do_conf = damroll(3, (dam / 2)) + 1;
6630 
6631 				/* Attempt a saving throw */
6632 				if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags3 & RF3_NO_CONF) ||
6633 				  RES_OLD(r_ptr->level, dam / 3))
6634 				{
6635 					note = " resists";
6636 					if (r_ptr->flags1 & RF1_UNIQUE) note = " is unaffected";
6637 
6638 					/* Memorize a flag */
6639 					if (r_ptr->flags3 & RF3_NO_CONF) {
6640 #ifdef OLD_MONSTER_LORE
6641 						if (seen) r_ptr->r_flags3 |= RF3_NO_CONF;
6642 #endif
6643 						note = " is unaffected";
6644 					}
6645 					/* Resist */
6646 					do_conf = 0;
6647 				}
6648 				//let's do some actual damage, too?
6649 //				dam = 0;
6650 //				quiet_dam = TRUE;
6651 				break;
6652 			} else { //Blind
6653 				do_blind = dam;
6654 				dam = 0;
6655 				quiet_dam = TRUE;
6656 				/* No obvious effect */
6657 				obvious = FALSE;
6658 			}
6659 			break;
6660 		}
6661 
6662 		/* Healing Cloud damages undead beings - the_sandman */
6663 		case GF_HEALINGCLOUD:
6664 		{
6665 			if (r_ptr->flags3 & RF3_UNDEAD) {
6666 #ifdef OLD_MONSTER_LORE
6667 				if (seen) r_ptr->r_flags3 |= RF3_UNDEAD;
6668 #endif
6669 				if (seen) obvious = TRUE;
6670 				note = " crackles in the light";
6671 				note_dies = " evaporates into thin air";
6672 			} else {
6673 				dam = 0;
6674 				quiet = TRUE;
6675 			}
6676 			break;
6677 		}
6678 
6679 		/* Vapour + poison ownage - the_sandman */
6680 		case GF_WATERPOISON:
6681 		{
6682 			switch (randint(2)) {
6683 				case 1: { // Poison!
6684 					if (seen) obvious = TRUE;
6685 					if ((r_ptr->flags3 & RF3_IM_POIS) ||
6686 					  (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
6687 					  (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
6688 					{
6689 						note = " is immune";
6690 						dam = 0;
6691 #ifdef OLD_MONSTER_LORE
6692 						if (seen) r_ptr->r_flags3 |= RF3_IM_POIS;
6693 #endif
6694 					} else if (r_ptr->flags9 & RF9_RES_POIS) {
6695 						note = " resists";
6696 						dam /= 4;
6697 #ifdef OLD_MONSTER_LORE
6698 						if (seen) r_ptr->flags9 |= RF9_RES_POIS;
6699 #endif
6700 					} else if (r_ptr->flags9 & RF9_SUSCEP_POIS) {
6701 						note = " is hit hard";
6702 						dam *= 2;
6703 #ifdef OLD_MONSTER_LORE
6704 						if (seen) r_ptr->flags9 |= RF9_SUSCEP_POIS;
6705 #endif
6706 					}
6707 					break;
6708 				}
6709 				default: { // Water
6710 					if (seen) obvious = TRUE;
6711 					if (r_ptr->flags9 & RF9_IM_WATER) {
6712 						note = " is immune";
6713 						dam = 0;
6714 					} else if (r_ptr->flags7 & RF7_AQUATIC) {
6715 						note = " resists a lot";
6716 						dam /= 9;
6717 					} else if (r_ptr->flags3 & RF3_RES_WATE) {
6718 						note = " resists";
6719 						dam /= 4;
6720 					}
6721 					break;
6722 				}
6723 			}
6724 			break;
6725 		}
6726 
6727 		/* Random between ice (shards+water) and poison. At the moment its 3:1:1 shards:water:poison chance
6728 				- the_sandman */
6729 		case GF_ICEPOISON:
6730 		{
6731 			switch (randint(5)) {
6732 				case 1:  // Shards
6733 				case 3:
6734 				case 5: {
6735 					if (seen) obvious = TRUE;
6736 					if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS))
6737 					{
6738 							note = " resists";
6739 							dam *= 3; dam /= (randint(6) + 6);
6740 					}
6741 					break;
6742 				}
6743 				case 2: { // Water
6744 					if (seen) obvious = TRUE;
6745 					if (r_ptr->flags9 & RF9_IM_WATER) {
6746 						note = " is immune";
6747 						dam = 0;
6748 					} else if (r_ptr->flags7 & RF7_AQUATIC) {
6749 						note = " resists a lot";
6750 						dam /= 9;
6751 					} else if (r_ptr->flags3 & RF3_RES_WATE) {
6752 						note = " resists";
6753 						dam /= 4;
6754 					}
6755 					break;
6756 				}
6757 				default: { // Poison
6758 					if (seen) obvious = TRUE;
6759 					if ((r_ptr->flags3 & RF3_IM_POIS) ||
6760 					  (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
6761 					  (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
6762 					{
6763 						note = " is immune";
6764 						dam = 0;
6765 #ifdef OLD_MONSTER_LORE
6766 						if (seen) r_ptr->r_flags3 |= RF3_IM_POIS;
6767 #endif
6768 					}
6769 					else if (r_ptr->flags9 & RF9_RES_POIS)
6770 					{
6771 						note = " resists";
6772 						dam /= 4;
6773 #ifdef OLD_MONSTER_LORE
6774 						if (seen) r_ptr->r_flags9 |= RF9_RES_POIS;
6775 #endif
6776 					}
6777 					else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
6778 					{
6779 						note = " is hit hard";
6780 						dam *= 2;
6781 #ifdef OLD_MONSTER_LORE
6782 						if (seen) r_ptr->r_flags9 |= RF9_SUSCEP_POIS;
6783 #endif
6784 					}
6785 					break;
6786 				}
6787 			}
6788 			break;
6789 		}
6790 
6791 		/* Lite, but only hurts susceptible creatures */
6792 		case GF_LITE_WEAK:
6793 		{
6794 			/* Hurt by light */
6795 			if (r_ptr->flags3 & RF3_HURT_LITE) {
6796 				/* Obvious effect */
6797 				if (seen) obvious = TRUE;
6798 
6799 #ifdef OLD_MONSTER_LORE
6800 				/* Memorize the effects */
6801 				if (seen) r_ptr->r_flags3 |= RF3_HURT_LITE;
6802 #endif
6803 
6804 				/* Special effect */
6805 				note = " cringes from the light";
6806 				note_dies = " shrivels away in the light";
6807 			}
6808 
6809 			/* Normally no damage */
6810 			else {
6811 				/* No damage */
6812 				dam = 0;
6813 				quiet = TRUE;
6814 			}
6815 
6816 			break;
6817 		}
6818 
6819 
6820 
6821 		/* Lite -- opposite of Dark */
6822 		case GF_LITE:
6823 		{
6824 			if (seen) obvious = TRUE;
6825 
6826 			/* Get blinded later */
6827 			do_blind = damroll(3, (dam / 20)) + 1;
6828 
6829 			if (r_ptr->d_char == 'A') {
6830 				note = " is immune";
6831 				dam = do_blind = 0;
6832 			} else if ((r_ptr->flags4 & RF4_BR_LITE) || (r_ptr->flags9 & RF9_RES_LITE)) {
6833 				note = " resists";
6834 				dam *= 3; dam /= (randint(6) + 6);
6835 				do_blind = 0;
6836 			} else if (r_ptr->flags3 & RF3_HURT_LITE) {
6837 #ifdef OLD_MONSTER_LORE
6838 				if (seen) r_ptr->r_flags3 |= RF3_HURT_LITE;
6839 #endif
6840 				note = " cringes from the light";
6841 				note_dies = " shrivels away in the light";
6842 				dam *= 2;
6843 			}
6844 			break;
6845 		}
6846 
6847 
6848 		/* Dark -- opposite of Lite */
6849 		case GF_DARK:
6850 		{
6851 			if (seen) obvious = TRUE;
6852 
6853 			/* Get blinded later */
6854 			do_blind = damroll(3, (dam / 20)) + 1;
6855 
6856 			if ((r_ptr->flags4 & RF4_BR_DARK) || (r_ptr->flags9 & RF9_RES_DARK)
6857 			    || (r_ptr->flags3 & RF3_UNDEAD)) {
6858 				note = " resists";
6859 				dam *= 3; dam /= (randint(6) + 6);
6860 				do_blind = 0;
6861 			}
6862 			break;
6863 		}
6864 
6865 		/* Stone to Mud */
6866 		case GF_KILL_WALL:
6867 		{
6868 			/* Hurt by rock remover */
6869 			if (r_ptr->flags3 & RF3_HURT_ROCK) {
6870 				/* Notice effect */
6871 				if (seen) obvious = TRUE;
6872 
6873 #ifdef OLD_MONSTER_LORE
6874 				/* Memorize the effects */
6875 				if (seen) r_ptr->r_flags3 |= RF3_HURT_ROCK;
6876 #endif
6877 
6878 				/* Cute little message */
6879 				note = " loses some skin";
6880 				note_dies = " dissolves";
6881 			}
6882 
6883 			/* Usually, ignore the effects */
6884 			else {
6885 				/* No damage */
6886 				dam = 0;
6887 				quiet = TRUE;
6888 			}
6889 
6890 			break;
6891 		}
6892 
6893 
6894 		/* Teleport undead (Use "dam" as "power") */
6895 		case GF_AWAY_UNDEAD:
6896 		{
6897 			/* Only affect undead */
6898 			if (!(r_ptr->flags9 & RF9_IM_TELE) &&
6899 				(r_ptr->flags3 & (RF3_UNDEAD)))
6900 			{
6901 				bool resists_tele = FALSE;
6902 
6903 				if ((r_ptr->flags3 & (RF3_RES_TELE)) || (r_ptr->flags9 & RF9_IM_TELE)) {
6904 					if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags9 & RF9_IM_TELE)) {
6905 #ifdef OLD_MONSTER_LORE
6906 						if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6907 #endif
6908 						note = " is unaffected";
6909 						resists_tele = TRUE;
6910 					} else if (m_ptr->level > randint(100)) {
6911 #ifdef OLD_MONSTER_LORE
6912 						if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6913 #endif
6914 						note = " resists";
6915 						resists_tele = TRUE;
6916 					}
6917 				}
6918 
6919 				if (!resists_tele) {
6920 					if (seen) obvious = TRUE;
6921 #ifdef OLD_MONSTER_LORE
6922 					if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
6923 #endif
6924 					do_dist = dam;
6925 				}
6926 			}
6927 
6928 			/* No "real" damage */
6929 			dam = 0;
6930 			quiet_dam = TRUE;
6931 			break;
6932 		}
6933 
6934 
6935 		/* Teleport evil (Use "dam" as "power") */
6936 		case GF_AWAY_EVIL:
6937 		{
6938 			/* Only affect undead */
6939 			if (!(r_ptr->flags9 & RF9_IM_TELE) &&
6940 			    !(r_ptr->flags3 & (RF3_EVIL))) {
6941 				bool resists_tele = FALSE;
6942 
6943 				if ((r_ptr->flags3 & (RF3_RES_TELE)) || (r_ptr->flags9 & RF9_IM_TELE)) {
6944 					if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags9 & RF9_IM_TELE)) {
6945 #ifdef OLD_MONSTER_LORE
6946 						if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6947 #endif
6948 						note = " is unaffected";
6949 						resists_tele = TRUE;
6950 					} else if (m_ptr->level > randint(100)) {
6951 #ifdef OLD_MONSTER_LORE
6952 						if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6953 #endif
6954 						note = " resists";
6955 						resists_tele = TRUE;
6956 					}
6957 				}
6958 
6959 				if (!resists_tele) {
6960 					if (seen) obvious = TRUE;
6961 #ifdef OLD_MONSTER_LORE
6962 					if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
6963 #endif
6964 					do_dist = dam;
6965 				}
6966 			}
6967 
6968 			/* No "real" damage */
6969 			dam = 0;
6970 			quiet_dam = TRUE;
6971 			break;
6972 		}
6973 
6974 
6975 		/* Teleport monster (Use "dam" as "power") */
6976 		case GF_AWAY_ALL:
6977 		{
6978 			bool resists_tele = FALSE;
6979 //			dun_level		*l_ptr = getfloor(wpos);
6980 
6981 			if (!(r_ptr->flags9 & RF9_IM_TELE) &&
6982 			    !(r_ptr->flags3 & (RF3_RES_TELE))) {
6983 				if (r_ptr->flags1 & (RF1_UNIQUE)) {
6984 #ifdef OLD_MONSTER_LORE
6985 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6986 #endif
6987 					note = " is unaffected";
6988 					resists_tele = TRUE;
6989 				} else if (m_ptr->level > randint(100)) {
6990 #ifdef OLD_MONSTER_LORE
6991 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
6992 #endif
6993 					note = " resists";
6994 					resists_tele = TRUE;
6995 				}
6996 
6997 				if (!resists_tele) {
6998 					/* Obvious */
6999 					if (seen) obvious = TRUE;
7000 					/* Prepare to teleport */
7001 					do_dist = dam;
7002 				}
7003 			}
7004 
7005 			/* No "real" damage */
7006 			dam = 0;
7007 			quiet_dam = TRUE;
7008 			break;
7009 		}
7010 
7011 
7012 		/* Turn undead (Use "dam" as "power") */
7013 		case GF_TURN_UNDEAD:
7014 		{
7015 			/* Only affect undead */
7016 			if (r_ptr->flags3 & RF3_UNDEAD) {
7017 #ifdef OLD_MONSTER_LORE
7018 				/* Learn about type */
7019 				if (seen) r_ptr->r_flags3 |= RF3_UNDEAD;
7020 #endif
7021 
7022 				/* Obvious */
7023 				if (seen) obvious = TRUE;
7024 
7025 				/* Apply some fear */
7026 				do_fear = damroll(3, (dam / 2)) + 1;
7027 
7028 				/* Attempt a saving throw */
7029 				if (RES_OLD(r_ptr->level, dam)) {
7030 					/* No obvious effect */
7031 					note = " is unaffected";
7032 					obvious = FALSE;
7033 					do_fear = 0;
7034 				}
7035 			}
7036 
7037 			/* No "real" damage */
7038 			dam = 0;
7039 			quiet_dam = TRUE;
7040 			break;
7041 		}
7042 
7043 
7044 		/* Turn evil (Use "dam" as "power") */
7045 		case GF_TURN_EVIL:
7046 		{
7047 			/* Only affect evil */
7048 			if (r_ptr->flags3 & RF3_EVIL) {
7049 #ifdef OLD_MONSTER_LORE
7050 				/* Learn about type */
7051 				if (seen) r_ptr->r_flags3 |= RF3_EVIL;
7052 #endif
7053 
7054 				/* Obvious */
7055 				if (seen) obvious = TRUE;
7056 
7057 				/* Apply some fear */
7058 				do_fear = damroll(3, (dam / 2)) + 1;
7059 
7060 				/* Attempt a saving throw */
7061 				if (RES_OLD(r_ptr->level, dam)) {
7062 					/* No obvious effect */
7063 					note = " is unaffected";
7064 					obvious = FALSE;
7065 					do_fear = 0;
7066 				}
7067 			}
7068 
7069 			/* No "real" damage */
7070 			dam = 0;
7071 			quiet_dam = TRUE;
7072 			break;
7073 		}
7074 
7075 
7076 		/* Turn monster (Use "dam" as "power") */
7077 		case GF_TURN_ALL:
7078 		{
7079 			/* Obvious */
7080 			if (seen) obvious = TRUE;
7081 
7082 			/* Apply some fear */
7083 			do_fear = damroll(3, (dam / 2)) + 1;
7084 
7085 			/* Attempt a saving throw */
7086 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
7087 			    (r_ptr->flags3 & RF3_NO_FEAR)) {
7088 				/* No obvious effect */
7089 				note = " is unaffected";
7090 				obvious = FALSE;
7091 				do_fear = 0;
7092 			} else if (RES_OLD(r_ptr->level, dam)) {
7093 				note = " resists the effect";
7094 				obvious = FALSE;
7095 				do_fear = 0;
7096 			}
7097 
7098 			/* No "real" damage */
7099 			dam = 0;
7100 			quiet_dam = TRUE;
7101 			break;
7102 		}
7103 
7104 
7105 		/* Dispel undead */
7106 		case GF_DISP_UNDEAD:
7107 		{
7108 			/* Only affect undead */
7109 			if (r_ptr->flags3 & RF3_UNDEAD) {
7110 #ifdef OLD_MONSTER_LORE
7111 				/* Learn about type */
7112 				if (seen) r_ptr->r_flags3 |= RF3_UNDEAD;
7113 #endif
7114 
7115 				/* Obvious */
7116 				if (seen) obvious = TRUE;
7117 
7118 				/* Message */
7119 				note = " shudders";
7120 				note_dies = " dissolves";
7121 			}
7122 			/* Ignore other monsters */
7123 			else {
7124 				/* No damage */
7125 				dam = 0;
7126 				quiet = TRUE;
7127 			}
7128 
7129 			break;
7130 		}
7131 
7132 
7133 		/* Dispel evil */
7134 		case GF_DISP_EVIL:
7135 		{
7136 			/* Only affect evil */
7137 			if (r_ptr->flags3 & RF3_EVIL) {
7138 #ifdef OLD_MONSTER_LORE
7139 				/* Learn about type */
7140 				if (seen) r_ptr->r_flags3 |= RF3_EVIL;
7141 #endif
7142 
7143 				/* Obvious */
7144 				if (seen) obvious = TRUE;
7145 
7146 				/* Message */
7147 				note = " shudders";
7148 				note_dies = " dissolves";
7149 			}
7150 			/* Ignore other monsters */
7151 			else {
7152 				/* No damage */
7153 				dam = 0;
7154 				quiet = TRUE;
7155 			}
7156 
7157 			break;
7158 		}
7159 
7160 		case GF_DISP_DEMON:
7161 		{
7162 			/* Only affect evil */
7163 			if (r_ptr->flags3 & RF3_DEMON) {
7164 #ifdef OLD_MONSTER_LORE
7165 				/* Learn about type */
7166 				if (seen) r_ptr->r_flags3 |= RF3_DEMON;
7167 #endif
7168 
7169 				/* Obvious */
7170 				if (seen) obvious = TRUE;
7171 
7172 				/* Message */
7173 				note = " shudders";
7174 				note_dies = " dissolves";
7175 			}
7176 			/* Ignore other monsters */
7177 			else {
7178 				/* No damage */
7179 				dam = 0;
7180 				quiet = TRUE;
7181 			}
7182 
7183 			break;
7184 		}
7185 
7186 		/* Dispel monster */
7187 		case GF_DISP_ALL:
7188 		{
7189 			/* Obvious */
7190 			if (seen) obvious = TRUE;
7191 
7192 			/* Message */
7193 			note = " shudders";
7194 			note_dies = " dissolves";
7195 
7196 			break;
7197 		}
7198 
7199 		/* Nuclear waste */
7200 		case GF_NUKE:
7201 		{
7202 			if (seen) obvious = TRUE;
7203 
7204 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
7205 			  (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
7206 			  (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
7207 			{
7208 				note = " is immune";
7209 				dam = 0;
7210 #ifdef OLD_MONSTER_LORE
7211 				if (seen) r_ptr->r_flags3 |= (RF3_IM_POIS);
7212 #endif
7213 			} else if (r_ptr->flags9 & (RF9_RES_POIS)) {
7214 				note = " resists";
7215 				dam *= 3; dam /= (randint(6) + 6 );
7216 #ifdef OLD_MONSTER_LORE
7217 				if (seen) r_ptr->r_flags9 |= (RF9_RES_POIS);
7218 #endif
7219 			}
7220 			else if (randint(3) == 1) do_poly = TRUE;
7221 			break;
7222 		}
7223 
7224 
7225 		/* Pure damage */
7226 		case GF_DISINTEGRATE:
7227 		{
7228 			if (seen) obvious = TRUE;
7229 			if (r_ptr->flags3 & (RF3_HURT_ROCK)) {
7230 #ifdef OLD_MONSTER_LORE
7231 				if (seen) r_ptr->r_flags3 |= (RF3_HURT_ROCK);
7232 #endif
7233 				note = " loses some skin";
7234 				note_dies = " evaporates";
7235 				dam *= 2;
7236 			}
7237 
7238 			if (r_ptr->flags1 & RF1_UNIQUE) {
7239 				if (rand_int(m_ptr->level + 10) > rand_int(plev)) {
7240 					note = " resists";
7241 					dam >>= 3;
7242 				}
7243 			}
7244 			break;
7245 		}
7246 		case GF_HOLD:
7247 		case GF_DOMINATE:
7248 			if(!quiet){
7249 				if((!(r_ptr->flags1 & (RF1_UNIQUE|RF1_NEVER_MOVE)) &&
7250 					!(r_ptr->flags9 & RF9_IM_PSI) && !(r_ptr->flags7 & RF7_MULTIPLY)) ||
7251 					is_admin(p_ptr))
7252 					m_ptr->owner = p_ptr->id;
7253 				note = " starts following you";
7254 			}
7255 			dam = 0;
7256 			quiet_dam = TRUE;
7257 			break;
7258 
7259 		/* Teleport monster TO */
7260 		case GF_TELE_TO:
7261 		{
7262 			bool resists_tele = FALSE;
7263 //			dun_level		*l_ptr = getfloor(wpos);
7264 
7265 			/* Teleport to nowhere..? */
7266 			if (quiet) break;
7267 
7268 			if (!(r_ptr->flags9 & RF9_IM_TELE) &&
7269 			    !(r_ptr->flags3 & (RF3_RES_TELE))) {
7270 				if (r_ptr->flags1 & (RF1_UNIQUE)) {
7271 #ifdef OLD_MONSTER_LORE
7272 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
7273 #endif
7274 					note = " is unaffected";
7275 					resists_tele = TRUE;
7276 				} else if (m_ptr->level > randint(100)) {
7277 #ifdef OLD_MONSTER_LORE
7278 					if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
7279 #endif
7280 					note = " resists";
7281 					resists_tele = TRUE;
7282 				}
7283 			} else {
7284 #ifdef OLD_MONSTER_LORE
7285 				if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
7286 #endif
7287 				note = " is unaffected";
7288 				resists_tele = TRUE;
7289 			}
7290 
7291 			if (!resists_tele) {
7292 				/* Obvious */
7293 				if (seen) obvious = TRUE;
7294 
7295 				/* Prepare to teleport */
7296 //				do_dist = dam;
7297 				teleport_to_player(Ind, c_ptr->m_idx);
7298 
7299 				/* Hack -- get new location */
7300 				y = m_ptr->fy;
7301 				x = m_ptr->fx;
7302 
7303 				/* Hack -- get new grid */
7304 				c_ptr = &zcave[y][x];
7305 			}
7306 
7307 			/* No "real" damage */
7308 			dam = 0;
7309 			quiet_dam = TRUE;
7310 			break;
7311 		}
7312 
7313 		/* Hand of Doom */
7314 		case GF_HAND_DOOM:
7315 		{
7316 #if 0	/* okay, do that! ;) */
7317 			if (r_ptr->r_flags1 & RF1_UNIQUE) {
7318 				note = " resists";
7319 				dam = 0;
7320 			} else
7321 #endif	// 0
7322 			{
7323 				int dummy = (((s32b) ((65 + randint(25)) * (m_ptr->hp))) / 100);
7324 //				msg_print(Ind, "You feel your life fade away!");
7325 
7326 				if (m_ptr->hp - dummy < 1) dummy = m_ptr->hp - 1;
7327 
7328 				dam = dummy;
7329 			}
7330 			break;
7331 		}
7332 
7333 		/* Sleep (Use "dam" as "power") */
7334 		case GF_STASIS:
7335 			if (seen) obvious = TRUE;
7336 
7337 			/* Attempt a saving throw */
7338 			if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
7339 			    RES_OLD(r_ptr->level, dam)) {
7340 				note = " is unaffected";
7341 				obvious = FALSE;
7342 			} else {
7343 				/* Go to sleep (much) later */
7344 				note = " is suspended";
7345 				do_sleep = GF_OLD_SLEEP_DUR;
7346 			}
7347 
7348 			/* No "real" damage */
7349 			dam = 0;
7350 			quiet_dam = TRUE;
7351 			break;
7352 
7353 		/* Decrease strength */
7354 		case GF_DEC_STR:
7355 			if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NO_DEATH)) {
7356 				msg_print_near_monster(c_ptr->m_idx, "is unaffected");
7357 			} else {
7358 				for (i = 0; i < 4; i++) {
7359 					if ((m_ptr->blow[i].d_dice > 1) && (m_ptr->blow[i].org_d_dice - m_ptr->blow[i].d_dice < 3)) {
7360 						m_ptr->blow[i].d_dice -= 1;
7361 						msg_print_near_monster(c_ptr->m_idx, "appears weaker");
7362 					}
7363 					else if ((m_ptr->blow[i].d_side > 1) && (m_ptr->blow[i].org_d_side - m_ptr->blow[i].d_side < 3)) {
7364 						m_ptr->blow[i].d_side -= 1;
7365 						msg_print_near_monster(c_ptr->m_idx, "appears weaker");
7366 					}
7367 				}
7368 			}
7369 			dam = 0;
7370 			quiet = TRUE;
7371 			break;
7372 
7373 		/* Decrease dexterity */
7374 		case GF_DEC_DEX:
7375 			if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NO_DEATH)) {
7376 				msg_print_near_monster(c_ptr->m_idx, "is unaffected");
7377 			} else {
7378 				if ((m_ptr->org_ac - m_ptr->ac < m_ptr->org_ac / 2) && (m_ptr->org_ac - m_ptr->ac < 30)) {
7379 					if (m_ptr->ac) msg_print_near_monster(c_ptr->m_idx, "appears clumsy");
7380 					if (m_ptr->ac) m_ptr->ac--;
7381 					if (m_ptr->ac) m_ptr->ac--;
7382 					if (m_ptr->ac) m_ptr->ac--;
7383 				}
7384 			}
7385 			dam = 0;
7386 			quiet = TRUE;
7387 			break;
7388 
7389 		/* Decrease dexterity */
7390 		case GF_DEC_CON:
7391 			if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NO_DEATH)) {
7392 				msg_print_near_monster(c_ptr->m_idx, "is unaffected");
7393 			} else {
7394 				if ((m_ptr->org_maxhp - m_ptr->maxhp < m_ptr->org_maxhp / 2) && (m_ptr->org_maxhp - m_ptr->maxhp < 20)) {
7395 					if (m_ptr->maxhp > 1) msg_print_near_monster(c_ptr->m_idx, "appears less healthy");
7396 					if (m_ptr->maxhp > 50) m_ptr->maxhp -= 10;
7397 					if (m_ptr->maxhp > 30) m_ptr->maxhp -= 6;
7398 					if (m_ptr->maxhp > 10) m_ptr->maxhp -= 3;
7399 					if (m_ptr->maxhp > 1) m_ptr->maxhp -= 1;
7400 					if (m_ptr->maxhp < m_ptr->hp) m_ptr->hp = m_ptr->maxhp;
7401 				}
7402 			}
7403 			dam = 0;
7404 			quiet = TRUE;
7405 			break;
7406 
7407 		/* Restore strength */
7408 		case GF_RES_STR:
7409 			dam = 0; /* hack :) */
7410 			for (i = 0; i < 4; i++) {
7411 			/*	  if (m_ptr->blow[i].d_dice < r_ptr->blow[i].d_dice) m_ptr->blow[i].d_dice = r_ptr->blow[i].d_dice;
7412 					if (m_ptr->blow[i].d_side < r_ptr->blow[i].d_side) m_ptr->blow[i].d_side = r_ptr->blow[i].d_side;
7413 			*/	if (m_ptr->blow[i].d_dice < r_ptr->blow[i].org_d_dice) {
7414 					m_ptr->blow[i].d_dice = r_ptr->blow[i].org_d_dice;
7415 					dam = 1;
7416 				}
7417 				if (m_ptr->blow[i].d_side < r_ptr->blow[i].org_d_side) {
7418 					m_ptr->blow[i].d_side = r_ptr->blow[i].org_d_side;
7419 					dam = 1;
7420 				}
7421 			}
7422 			if (dam) msg_print_near_monster(c_ptr->m_idx, "appears less weak");
7423 			dam = 0;
7424 			quiet = TRUE;
7425 			break;
7426 
7427 		/* Restore dexterity */
7428 		case GF_RES_DEX:
7429 			/*if (m_ptr->ac < r_ptr->ac) {
7430 				m_ptr->ac = r_ptr->ac;*/
7431 			if (m_ptr->ac < m_ptr->org_ac) {
7432 				m_ptr->ac = m_ptr->org_ac;
7433 				msg_print_near_monster(c_ptr->m_idx, "appears less clumsy");
7434 			}
7435 			dam = 0;
7436 			quiet = TRUE;
7437 			break;
7438 
7439 		/* Restore constitution */
7440 		case GF_RES_CON:
7441 			/*if (m_ptr->hp < r_ptr->hside * r_ptr->hdice) {
7442 				m_ptr->hp = r_ptr->hside * r_ptr->hdice;*/
7443 			if (m_ptr->maxhp < m_ptr->org_maxhp) {
7444 				m_ptr->hp += m_ptr->org_maxhp - m_ptr->maxhp;
7445 				m_ptr->maxhp = m_ptr->org_maxhp;
7446 				msg_print_near_monster(c_ptr->m_idx, "appears less sick");
7447 			}
7448 			dam = 0;
7449 			quiet = TRUE;
7450 			break;
7451 
7452 		/* Increase strength! */
7453 		case GF_INC_STR:
7454 			if (!(r_ptr->flags7 & RF7_NO_DEATH))
7455 				for (i = 0; i < 4; i++) { /* increase the value which has less effect on total damage output - C. Blue :) */
7456 					/* do a 'restore strenght' before increasing it */
7457 					if (m_ptr->blow[i].d_dice < r_ptr->blow[i].org_d_dice) m_ptr->blow[i].d_dice = r_ptr->blow[i].org_d_dice;
7458 					if (m_ptr->blow[i].d_side < r_ptr->blow[i].org_d_side) m_ptr->blow[i].d_side = r_ptr->blow[i].org_d_side;
7459 
7460 					if (m_ptr->blow[i].d_dice > m_ptr->blow[i].d_side) {
7461 						m_ptr->blow[i].d_dice++;
7462 						msg_print_near_monster(c_ptr->m_idx, "appears stronger");
7463 					}
7464 					else if (m_ptr->blow[i].d_side > 0 && m_ptr->blow[i].d_dice > 0) {
7465 						m_ptr->blow[i].d_side++;
7466 						msg_print_near_monster(c_ptr->m_idx, "appears stronger");
7467 					}
7468 				}
7469 			dam = 0;
7470 			quiet = TRUE;
7471 			break;
7472 
7473 		/* Increase dexterity! */
7474 		case GF_INC_DEX:
7475 			if (!(r_ptr->flags7 & RF7_NO_DEATH)) {
7476 				if (m_ptr->ac < m_ptr->org_ac) m_ptr->ac = m_ptr->org_ac;
7477 				m_ptr->ac += 5;
7478 				msg_print_near_monster(c_ptr->m_idx, "appears more dextrous");
7479 			}
7480 			dam = 0;
7481 			quiet = TRUE;
7482 			break;
7483 
7484 		/* Increase constitution! */
7485 		case GF_INC_CON:
7486 			if (!(r_ptr->flags7 & RF7_NO_DEATH)) {
7487 				if (m_ptr->maxhp < m_ptr->org_maxhp) { /* include a restore con here */
7488 					m_ptr->hp += m_ptr->org_maxhp - m_ptr->maxhp;
7489 					m_ptr->maxhp = m_ptr->org_maxhp;
7490 				}
7491 
7492 				m_ptr->hp += ((r_ptr->hside * r_ptr->hdice) / 10) + 2;
7493 				m_ptr->maxhp += ((r_ptr->hside * r_ptr->hdice) / 10) + 2;
7494 				msg_print_near_monster(c_ptr->m_idx, "appears healthier");
7495 			}
7496 
7497 			dam = 0;
7498 			quiet = TRUE;
7499 			break;
7500 
7501 		/* Augmentation! (who'd do such a thing, silyl..) */
7502 		case GF_AUGMENTATION:
7503 			if (!(r_ptr->flags7 & RF7_NO_DEATH)) {
7504 				msg_print_near_monster(c_ptr->m_idx, "appears more powerful!");
7505 				for (i = 0; i < 4; i++) { /* increase the value which has less effect on total damage output - C. Blue :) */
7506 					if (m_ptr->blow[i].d_dice < r_ptr->blow[i].org_d_dice) m_ptr->blow[i].d_dice = r_ptr->blow[i].org_d_dice;
7507 					if (m_ptr->blow[i].d_side < r_ptr->blow[i].org_d_side) m_ptr->blow[i].d_side = r_ptr->blow[i].org_d_side;
7508 
7509 					if (m_ptr->blow[i].d_dice > m_ptr->blow[i].d_side) m_ptr->blow[i].d_dice++;
7510 					else if (m_ptr->blow[i].d_side > 0 && m_ptr->blow[i].d_dice > 0) m_ptr->blow[i].d_side++;
7511 				}
7512 
7513 				if (m_ptr->ac < m_ptr->org_ac) m_ptr->ac = m_ptr->org_ac;
7514 
7515 				m_ptr->ac += 5;
7516 
7517 				if (m_ptr->maxhp < m_ptr->org_maxhp) {
7518 					m_ptr->hp += m_ptr->org_maxhp - m_ptr->maxhp;
7519 					m_ptr->maxhp = m_ptr->org_maxhp;
7520 				}
7521 
7522 				m_ptr->hp += ((r_ptr->hside * r_ptr->hdice) / 10) + 2;
7523 				m_ptr->maxhp += ((r_ptr->hside * r_ptr->hdice) / 10) + 2;
7524 			}
7525 
7526 			dam = 0;
7527 			quiet = TRUE;
7528 			break;
7529 
7530 		/* Ruination! (now we're talking) */
7531 		case GF_RUINATION:
7532 			if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NO_DEATH)) {
7533 				msg_print_near_monster(c_ptr->m_idx, "is unaffected");
7534 			} else {
7535 				msg_print_near_monster(c_ptr->m_idx, "appears less powerful.");
7536 				for (i = 0; i < 4; i++) {
7537 					if ((m_ptr->blow[i].d_dice > 1) && (m_ptr->blow[i].org_d_dice - m_ptr->blow[i].d_dice < 3)) {
7538 						m_ptr->blow[i].d_dice -= 1;
7539 					}
7540 					else if ((m_ptr->blow[i].d_side > 1) && (m_ptr->blow[i].org_d_side - m_ptr->blow[i].d_side < 3)) {
7541 						m_ptr->blow[i].d_side -= 1;
7542 					}
7543 				}
7544 
7545 				if ((m_ptr->org_ac - m_ptr->ac < m_ptr->org_ac / 2) && (m_ptr->org_ac - m_ptr->ac < 30)) {
7546 					if (m_ptr->ac) m_ptr->ac -= 1;
7547 					if (m_ptr->ac) m_ptr->ac -= 1;
7548 					if (m_ptr->ac) m_ptr->ac -= 1;
7549 				}
7550 
7551 				if ((m_ptr->org_maxhp - m_ptr->maxhp < m_ptr->org_maxhp / 2) && (m_ptr->org_maxhp - m_ptr->maxhp < 20)) {
7552 					if (m_ptr->hp > 50) m_ptr->hp -= 10;
7553 					if (m_ptr->hp > 30) m_ptr->hp -= 6;
7554 					if (m_ptr->hp > 10) m_ptr->hp -= 3;
7555 					if (m_ptr->hp > 1) m_ptr->hp -= 1;
7556 					if (m_ptr->maxhp < m_ptr->hp) m_ptr->hp = m_ptr->maxhp;
7557 				}
7558 			}
7559 			dam = 0;
7560 			quiet = TRUE;
7561 			break;
7562 
7563 		/* Give experience! (dam -> +levels) */
7564 		case GF_EXP:
7565 			if (!(r_ptr->flags7 & RF7_NO_DEATH) && m_ptr->level < MONSTER_LEVEL_MAX) {
7566 				msg_print_near_monster(c_ptr->m_idx, "appears more experienced");
7567 				if (dam < 1) dam = 1;
7568 				m_ptr->exp = MONSTER_EXP(m_ptr->level + dam);
7569 				monster_check_experience(c_ptr->m_idx, FALSE);
7570 			}
7571 			dam = 0;
7572 			quiet = TRUE;
7573 			break;
7574 
7575 		case GF_CURING:
7576 			if (m_ptr->confused) {
7577 				m_ptr->confused = 0;
7578 				msg_print_near_monster(c_ptr->m_idx, "is no longer confused.");
7579 			}
7580 			if (m_ptr->stunned) {
7581 				m_ptr->stunned = 0;
7582 				msg_print_near_monster(c_ptr->m_idx, "is no longer stunned.");
7583 			}
7584 
7585 			dam = 0; /* hack :) */
7586 			for (i = 0; i < 4; i++) {
7587 				if (m_ptr->blow[i].d_dice < r_ptr->blow[i].org_d_dice) {
7588 					m_ptr->blow[i].d_dice = r_ptr->blow[i].org_d_dice;
7589 					dam = 1;
7590 				}
7591 				if (m_ptr->blow[i].d_side < r_ptr->blow[i].org_d_side) {
7592 					m_ptr->blow[i].d_side = r_ptr->blow[i].org_d_side;
7593 					dam = 1;
7594 				}
7595 			}
7596 			if (dam) msg_print_near_monster(c_ptr->m_idx, "appears less weak");
7597 
7598 			if (m_ptr->ac < m_ptr->org_ac) {
7599 				m_ptr->ac = m_ptr->org_ac;
7600 				msg_print_near_monster(c_ptr->m_idx, "appears less clumsy");
7601 			}
7602 
7603 			if (m_ptr->maxhp < m_ptr->org_maxhp) {
7604 				m_ptr->hp += m_ptr->org_maxhp - m_ptr->maxhp;
7605 				m_ptr->maxhp = m_ptr->org_maxhp;
7606 				msg_print_near_monster(c_ptr->m_idx, "appears less sick");
7607 			}
7608 			dam = 0;
7609 			quiet = TRUE;
7610 			break;
7611 
7612 		/* Default */
7613 		default:
7614 			/* No damage */
7615 			dam = 0;
7616 			quiet_dam = TRUE;
7617 			break;
7618 	}
7619 
7620 	/* "Unique" monsters cannot be polymorphed */
7621 	if (r_ptr->flags1 & RF1_UNIQUE) do_poly = FALSE;
7622 	/* nor IM_TELE monsters.. */
7623 	if (r_ptr->flags9 & RF9_IM_TELE) do_poly = FALSE;
7624 
7625 	/* No polymorphing in Bree - mikaelh */
7626 	if (in_bree(wpos)) do_poly = FALSE;
7627 
7628 
7629 	/* "Unique" monsters can only be "killed" by the player */
7630 	if (r_ptr->flags1 & RF1_UNIQUE) {
7631 		/* Uniques may only be killed by the player */
7632 		if ((who > 0) && (dam > m_ptr->hp)) dam = m_ptr->hp;
7633 	}
7634 
7635 
7636 	/* Check for death */
7637 	if ((dam > m_ptr->hp) &&
7638 	    /* Some mosnters are immune to death */
7639 	    !(r_ptr->flags7 & RF7_NO_DEATH)) {
7640 		/* Extract method of death */
7641 		note = note_dies;
7642 	}
7643 
7644 
7645 	/* hack: No polymorphing in IDDC, because live-spawning isn't possible.
7646 	   So polymorphing would just remove the monsters completely everytime. */
7647 	if (do_poly && in_irondeepdive(wpos)) do_poly = FALSE;
7648 
7649 #ifndef DAMAGE_BEFORE_POLY
7650 	/* Mega-Hack -- Handle "polymorph" -- monsters get a saving throw */
7651 	if (do_poly && (randint(90) > r_ptr->level)) {
7652 		/* Default -- assume no polymorph */
7653 		if (!do_sleep) note = " is unaffected";
7654 
7655 		/* Pick a "new" monster race */
7656 		i = poly_r_idx(m_ptr->r_idx);
7657 
7658 		/* Handle polymorh */
7659 		if (i != m_ptr->r_idx) {
7660 			int clone, clone_summoning;
7661 
7662 			/* Obvious */
7663 			if (seen) obvious = TRUE;
7664 
7665 			/* Monster polymorphs */
7666 			note = " changes";
7667 
7668 			/* Turn off the damage */
7669 			dam = 0;
7670 			quiet_dam = TRUE;
7671 
7672 			/* Save clone status - mikaelh */
7673 			clone = m_list[c_ptr->m_idx].clone;
7674 			clone_summoning = m_list[c_ptr->m_idx].clone_summoning;
7675 
7676 			/* "Kill" the "old" monster */
7677 			delete_monster_idx(c_ptr->m_idx, TRUE);
7678 
7679 			/* Create a new monster (no groups) */
7680 			(void)place_monster_aux(wpos, y, x, i, FALSE, FALSE, clone, clone_summoning);
7681 
7682 			/* XXX XXX XXX Hack -- Assume success */
7683 			if(!quiet && c_ptr->m_idx == 0) {
7684 				msg_format(Ind, "%^s disappears!", m_name);
7685 				return(FALSE);
7686 			}
7687 
7688 			/* Hack -- Get new monster */
7689 			m_ptr = &m_list[c_ptr->m_idx];
7690 
7691 			/* Hack -- Get new race */
7692 			r_ptr = race_inf(m_ptr);
7693 		}
7694 	}
7695 #endif
7696 
7697 	/* Handle "teleport" */
7698 	if (do_dist) {
7699 		/* Obvious */
7700 		if (seen) obvious = TRUE;
7701 
7702 		/* Message */
7703 		note = " disappears";
7704 
7705 		/* Teleport */
7706 		/* TODO: handle failure (eg. st-anchor)	*/
7707 
7708 //		teleport_away(c_ptr->m_idx, do_dist);
7709 		m_ptr->do_dist = do_dist;
7710 
7711 		/* Hack -- get new location */
7712 		y = m_ptr->fy;
7713 		x = m_ptr->fx;
7714 
7715 		/* Hack -- get new grid */
7716 		c_ptr = &zcave[y][x];
7717 	}
7718 
7719 	/* Sound and Impact breathers never stun */
7720 	if (do_stun &&
7721 	    !(r_ptr->flags4 & RF4_BR_SOUN) &&
7722 	    !(r_ptr->flags4 & RF4_BR_PLAS) &&
7723 	    !(r_ptr->flags4 & RF4_BR_WALL) &&
7724 	    !(r_ptr->flags3 & RF3_NO_STUN)) {
7725 		/* Obvious */
7726 		if (seen) obvious = TRUE;
7727 
7728 #if 0
7729 		/* Get stunned */
7730 		if (m_ptr->stunned) {
7731 			if (!do_sleep) note = " is more dazed";
7732 			i = m_ptr->stunned + (do_stun / 2);
7733 		} else {
7734 			if (!do_sleep) note = " is dazed";
7735 			i = do_stun;
7736 		}
7737 #else
7738 		if (m_ptr->stunned > 100) {
7739 			note = " is knocked out";
7740 			i = m_ptr->stunned + (do_stun / 4);
7741 		} else if (m_ptr->stunned > 50) {
7742 			if (!do_sleep) note = " is heavily dazed";
7743 			i = m_ptr->stunned + (do_stun / 3);
7744 		} else if (m_ptr->stunned) {
7745 			if (!do_sleep) note = " is more dazed";
7746 			i = m_ptr->stunned + (do_stun / 2);
7747 		} else {
7748 			if (!do_sleep) note = " is dazed";
7749 			i = do_stun;
7750 		}
7751 #endif
7752 
7753 		/* Apply stun */
7754 		m_ptr->stunned = (i < 200) ? i : 200;
7755 	}
7756 
7757 	/* Confusion and Chaos breathers (and sleepers) never confuse */
7758 	if (do_conf &&
7759 	    !(r_ptr->flags3 & RF3_NO_CONF) &&
7760 	    !(r_ptr->flags4 & RF4_BR_CONF) &&
7761 	    !(r_ptr->flags4 & RF4_BR_CHAO) &&
7762 	    !(r_ptr->flags9 & RF9_RES_CHAOS)) {
7763 		/* Obvious */
7764 		if (seen) obvious = TRUE;
7765 
7766 		/* Already partially confused */
7767 		if (m_ptr->confused) {
7768 			if (!do_sleep) note = " looks more confused";
7769 			i = m_ptr->confused + (do_conf / 2);
7770 		}
7771 		/* Was not confused */
7772 		else {
7773 			if (!do_sleep) note = " looks confused";
7774 			i = do_conf;
7775 		}
7776 
7777 		/* Apply confusion */
7778 		m_ptr->confused = (i < 200) ? i : 200;
7779 	}
7780 
7781 	/* Blindness (confusion): Not for uniques or powerful monsters */
7782 	if (do_blind &&
7783 	     !(r_ptr->flags2 & RF2_POWERFUL) &&
7784 	    !(r_ptr->flags2 & RF2_PASS_WALL) && /* Ethereal monsters */
7785 	    !((r_ptr->flags4 & RF4_BR_LITE) && (r_ptr->flags4 & RF4_BR_DARK)) &&
7786 	    !(r_ptr->flags3 & RF3_UNDEAD) &&
7787 	    !(r_ptr->flags3 & RF3_NONLIVING) &&
7788 	    !(r_ptr->flags3 & RF3_DEMON) &&
7789 	    !(r_ptr->flags3 & RF3_DRAGON) &&
7790 	    !(r_ptr->flags3 & RF3_DRAGONRIDER) &&
7791 	    !(r_ptr->flags1 & RF1_UNIQUE) &&
7792 	    (m_ptr->level < 45))
7793 /*	    !((r_ptr->flags3 & RF3_DEMON) && (m_ptr->level >= 40)) &&
7794 	    !((r_ptr->flags3 & RF3_DRAGON) && (m_ptr->level >= 40)) &&
7795 	    !((r_ptr->flags3 & RF3_DRAGONRIDER) && (m_ptr->level >= 40)) &&
7796 	    !(r_ptr->flags1 & RF1_UNIQUE))*/
7797 /*	    !(((r_ptr->flags3 & RF3_DEMON) ||
7798 	    (r_ptr->flags3 & RF3_DRAGON) ||
7799 	    (r_ptr->flags3 & RF3_DRAGONRIDER) ||
7800 	    (r_ptr->flags1 & RF1_UNIQUE)) &&
7801 	    RES_OLD(r_ptr->level, dam))  <- this line would require a " resists." note btw. */
7802 	{
7803 		/* Obvious */
7804 		if (seen) obvious = TRUE;
7805 
7806 		/* Not too confused yet? */
7807 		if (m_ptr->confused < do_blind) {
7808 			i = do_blind;
7809 			if (!do_sleep) {
7810 				/* Already confused */
7811 				if (m_ptr->confused) {
7812 					note = " looks more confused";
7813 				}
7814 				/* Was not confused */
7815 				else {
7816 					note = " gropes around blindly";
7817 				}
7818 			}
7819 		}
7820 
7821 		/* Apply confusion */
7822 		m_ptr->confused = (i < 200) ? i : 200;
7823 	} else if (do_blind) {
7824 		if (note == NULL) {
7825 		/* No obvious effect */
7826 			note = " is unaffected";
7827 			obvious = FALSE;
7828 		}
7829 	}
7830 
7831 	/* Fear */
7832 	if (do_fear) {
7833 		/* Increase fear */
7834 		i = m_ptr->monfear + do_fear;
7835 
7836 		/* Set fear */
7837 		m_ptr->monfear = (i < 200) ? i : 200;
7838 		m_ptr->monfear_gone = 0;
7839 	}
7840 
7841 
7842 	/* If another monster did the damage, hurt the monster by hand */
7843 	if (who > 0 || who <= PROJECTOR_UNUSUAL) {
7844 		/* Redraw (later) if needed */
7845 		update_health(c_ptr->m_idx);
7846 
7847 		/* Some mosnters are immune to death */
7848 		if (r_ptr->flags7 & RF7_NO_DEATH) dam = 0;
7849 
7850 		/* Wake the monster up */
7851 		m_ptr->csleep = 0;
7852 
7853 		/* Hurt the monster */
7854 		m_ptr->hp -= dam;
7855 
7856 		/* Dead monster */
7857 		if (m_ptr->hp < 0) {
7858 			/* Since a non-player killed it, there will be no reward/loot */
7859 			if (r_ptr->flags1 & RF1_UNIQUE) m_ptr->clone = 90; /* still allow some experience to be gained */
7860 			else m_ptr->clone = 75;
7861 
7862 			/* Generate treasure, etc */
7863 			if (!quiet) monster_death(Ind, c_ptr->m_idx);
7864 
7865 			/* Delete the monster */
7866 			delete_monster_idx(c_ptr->m_idx, FALSE);
7867 
7868 			/* Give detailed messages if destroyed */
7869 			/* DEG Death message with damage. */
7870 			if ((r_ptr->flags1 & RF1_UNIQUE) && (!quiet && note))
7871 				msg_format(Ind, "%^s%s by \377e%d \377wdamage.", m_name, note, dam);
7872 			else if (!quiet && note)
7873 				msg_format(Ind, "%^s%s by \377g%d \377wdamage.", m_name, note, dam);
7874 
7875 #ifdef DAMAGE_BEFORE_POLY
7876 			do_poly = FALSE;
7877 #endif
7878 		}
7879 
7880 		/* Damaged monster */
7881 		else {
7882 			/* Give detailed messages if visible or destroyed */
7883 			if (!quiet && note && seen) msg_format(Ind, "%^s%s.", m_name, note);
7884 
7885 			/* Hack -- Pain message */
7886 			else if (!quiet && dam > 0) message_pain(Ind, c_ptr->m_idx, dam);
7887 
7888 			/* Hack -- handle sleep */
7889 			if (do_sleep) m_ptr->csleep = do_sleep;
7890 		}
7891 	}
7892 
7893 	/* If the player did it, give him experience, check fear */
7894 	else {
7895 		bool fear = FALSE;
7896 
7897 		if (m_ptr->questor && (m_ptr->questor_invincible || (r_ptr->flags7 & RF7_NO_DEATH) || !(m_ptr->questor_hostile & 0x1))) return obvious;
7898 
7899 		if (p_ptr->admin_godly_strike) {
7900 			p_ptr->admin_godly_strike--;
7901 			if (!(r_ptr->flags1 & RF1_UNIQUE)) dam = m_ptr->hp + 1;
7902 		}
7903 
7904 		/* Hurt the monster, check for fear and death */
7905 		if (!quiet && mon_take_hit(Ind, c_ptr->m_idx, dam, &fear, note_dies))
7906 		{
7907 			/* Dead monster */
7908 #ifdef DAMAGE_BEFORE_POLY
7909 			do_poly = FALSE;
7910 #endif
7911 		}
7912 
7913 		/* Damaged monster */
7914 		else {
7915 			/* Give detailed messages if visible or destroyed */
7916 			/* DEG Changed for added damage message. */
7917 			if (!quiet && seen) {
7918 				if (note) {
7919 					if (!quiet_dam) {
7920 						if (r_ptr->flags1 & RF1_UNIQUE) {
7921 							if (p_ptr->r_killed[m_ptr->r_idx] == 1) {
7922 								msg_format(Ind, "\377D%^s%s and takes \377e%d \377Ddamage.", m_name, note, dam);
7923 								if (p_ptr->warn_unique_credit) Send_beep(Ind);
7924 							} else
7925 								msg_format(Ind, "%^s%s and takes \377e%d \377wdamage.", m_name, note, dam);
7926 						} else
7927 							msg_format(Ind, "%^s%s and takes \377g%d \377wdamage.", m_name, note, dam);
7928 					} else {
7929 						msg_format(Ind, "%^s%s.", m_name, note);
7930 					}
7931 				}
7932 				/* Hack -- Pain message */
7933 				else if (dam > 0) message_pain(Ind, c_ptr->m_idx, dam);
7934 
7935 				/* Take note */
7936 				if (fear || do_fear) {
7937 #ifdef USE_SOUND_2010
7938 #else
7939 					sound(Ind, SOUND_FLEE);
7940 #endif
7941 					/* Message */
7942 					if (m_ptr->r_idx != RI_MORGOTH)
7943 						msg_format(Ind, "%^s flees in terror!", m_name);
7944 					else
7945 						msg_format(Ind, "%^s retreats!", m_name);
7946 				}
7947 			}
7948 #if 0 /* see above */
7949 			/* Take note */
7950 			if (!quiet && (fear || do_fear) && (p_ptr->mon_vis[c_ptr->m_idx])) {
7951 #ifdef USE_SOUND_2010
7952 #else
7953 				sound(Ind, SOUND_FLEE);
7954 #endif
7955 
7956 				/* Message */
7957 				if (m_ptr->r_idx != RI_MORGOTH)
7958 					msg_format(Ind, "%^s flees in terror!", m_name);
7959 				else
7960 					msg_format(Ind, "%^s retreats!", m_name);
7961 			}
7962 #endif
7963 
7964 			/* Hack -- handle sleep */
7965 			if (do_sleep) m_ptr->csleep = do_sleep;
7966 
7967 #ifdef ANTI_SEVEN_EXPLOIT /* code part: 'monster gets hit by a projection' */
7968 			/* isn't there any player in our casting-los? */
7969 			/* only ball spells/explosions, NOT clouds/walls/beams/bolts/traps/etc */
7970 //			if ((flg & PROJECT_JUMP) && (flg & PROJECT_KILL) && !(flg & PROJECT_STAY) &&
7971 //			if ((flg & PROJECT_KILL) && !(flg & PROJECT_STAY) &&
7972 			if ((flg & PROJECT_KILL) && /* well, why not for lasting effects too actually */
7973 			    /* some sanity/efficiency checks:.. */
7974 			    y_origin && x_origin && dam) {
7975 				/* first, make sure we don't have another potential target in our LOS.
7976 				   If we have, we can just go for him and ignore whoever shot us previously.
7977 				   NOTE: this stuff should probably be evaluated in monster target choosing
7978 				         code already, for efficiency. */
7979 				bool got_potential_target = FALSE;
7980 				int p;
7981 				/* make sure only monsters who NEED to use this actually do use it.. (Morgoth doesn't) */
7982 				if ((r_ptr->flags2 & RF2_PASS_WALL) && (r_ptr->flags2 & RF2_KILL_WALL)) {
7983 					got_potential_target = TRUE;
7984 				}
7985 				else if ((r_ptr->flags2 & RF2_PASS_WALL) || (r_ptr->flags2 & RF2_KILL_WALL)) {
7986 					if (!m_ptr->closest_player || m_ptr->closest_player > NumPlayers ||
7987 					    !inarea(&Players[m_ptr->closest_player]->wpos, &m_ptr->wpos))
7988 						got_potential_target = TRUE;
7989 					else if (projectable_wall_perm(&m_ptr->wpos, m_ptr->fy, m_ptr->fx,
7990 					    Players[m_ptr->closest_player]->py, Players[m_ptr->closest_player]->px, MAX_RANGE)) {
7991 						got_potential_target = TRUE;
7992 					}
7993 				}
7994 				if (!got_potential_target) {
7995 					for (p = 1; p <= NumPlayers; p++) {
7996 						if (inarea(&Players[p]->wpos, &m_ptr->wpos) &&
7997 						    projectable_wall(&m_ptr->wpos, m_ptr->fy, m_ptr->fx, Players[p]->py, Players[p]->px, MAX_RANGE)) {
7998 							got_potential_target = TRUE;
7999 							break;
8000 						}
8001 					}
8002 				}
8003 				/* Ok, noone else to go after, so we have to go for the one who actually hit us */
8004 				if (!got_potential_target) {
8005 					/* if we got hit by anything closer than last time, go for this one instead */
8006 					p = distance(m_ptr->fy, m_ptr->fx, y_origin, x_origin);
8007 					/* paranoia probably, but doesn't cost much: avoid silliness */
8008 					if (!p) m_ptr->previous_direction = 0;
8009 					/* start ANTI_SEVEN_EXPLOIT: */
8010 					else {
8011 						if (m_ptr->previous_direction == 0) {
8012 							/* note: instead of closest dis to ANY player we just save m_ptr->cdis
8013 							   at this time - relatively ineffective but also not mattering much probably.  */
8014 							m_ptr->cdis_on_damage = m_ptr->cdis;
8015 							/* start behaving special */
8016 							m_ptr->previous_direction = -1;
8017 							/* accept any epicenter of damage (which is closer than 999,999: always TRUE) */
8018 							m_ptr->damage_tx = 999;
8019 							m_ptr->damage_ty = 999;
8020 							m_ptr->damage_dis = 999;
8021 						}
8022 						if (p < m_ptr->damage_dis) {
8023 							m_ptr->damage_ty = y_origin;
8024 							m_ptr->damage_tx = x_origin;
8025 							m_ptr->damage_dis = p;
8026 							m_ptr->p_tx = p_ptr->px;
8027 							m_ptr->p_ty = p_ptr->py;
8028 						}
8029 					}
8030 				}
8031 			}
8032 #endif
8033 		}
8034 	}
8035 
8036 #ifdef DAMAGE_BEFORE_POLY
8037 	/* Mega-Hack -- Handle "polymorph" -- monsters get a saving throw */
8038 	if (do_poly && (randint(90) > r_ptr->level)) {
8039 		/* Default -- assume no polymorph */
8040 		if (!do_sleep) note = " is unaffected";
8041 
8042 		/* Pick a "new" monster race */
8043 		i = poly_r_idx(m_ptr->r_idx);
8044 
8045 		/* Handle polymorh */
8046 		if (i != m_ptr->r_idx) {
8047 			int clone, clone_summoning;
8048 
8049 			/* Obvious */
8050 			if (seen) obvious = TRUE;
8051 
8052 			/* Monster polymorphs */
8053 			note = " changes";
8054 
8055 			/* Save clone status - mikaelh */
8056 			clone = m_list[c_ptr->m_idx].clone;
8057 			clone_summoning = m_list[c_ptr->m_idx].clone_summoning;
8058 
8059 			/* "Kill" the "old" monster */
8060 			delete_monster_idx(c_ptr->m_idx, TRUE);
8061 
8062 			/* Create a new monster (no groups) */
8063 			(void)place_monster_aux(wpos, y, x, i, FALSE, FALSE, clone, clone_summoning);
8064 
8065 			/* XXX XXX XXX Hack -- Assume success */
8066 			if (!quiet) {
8067 				if (c_ptr->m_idx == 0) {
8068 					msg_format(Ind, "%^s disappears!", m_name);
8069 					return (FALSE);
8070 				} else msg_format(Ind, "%^s changes!", m_name);
8071 			}
8072 		}
8073 	}
8074 #endif
8075 
8076 	/* Update the monster XXX XXX XXX */
8077 	update_mon(c_ptr->m_idx, FALSE);
8078 
8079 	if (!quiet) {
8080 		/* Hack -- Redraw the monster grid anyway */
8081 		everyone_lite_spot(wpos, y, x);
8082 	}
8083 
8084 	/* Return "Anything seen?" */
8085 	return (obvious);
8086 }
8087 
8088 
8089 
8090 
8091 
8092 
8093 /*
8094  * Helper function for "project()" below.
8095  *
8096  * Handle a beam/bolt/ball causing damage to the player.
8097  *
8098  * This routine takes a "source monster" (by index), a "distance", a default
8099  * "damage", and a "damage type".  See "project_m()" above.
8100  *
8101  * If "rad" is non-zero, then the blast was centered elsewhere, and the damage
8102  * is reduced (see "project_m()" above).  This can happen if a monster breathes
8103  * at the player and hits a wall instead.
8104  *
8105  * We return "TRUE" if any "obvious" effects were observed.  XXX XXX Actually,
8106  * we just assume that the effects were obvious, for historical reasons.
8107  */
8108 /*
8109  * Megahack -- who < -999 means 'by something strange'.		- Jir -
8110  *
8111  * NOTE: unlike the note above, 'rad' doesn't seem to be used for damage-
8112  * reducing purpose, I don't know why.
8113  */
8114 //static bool project_p(int Ind, int who, int r, struct worldpos *wpos, int y, int x, int dam, int typ, int rad)
8115 static bool project_p(int Ind, int who, int r, struct worldpos *wpos, int y, int x, int dam, int typ, int rad, int flg, char *attacker)
8116 {
8117 	player_type *p_ptr;
8118 	monster_race *r_ptr;
8119 
8120 	int k = 0;
8121 	int div, k_elec, k_sound, k_lite;
8122 	bool kinetic_shield = FALSE;
8123 	/* Hack -- assume obvious */
8124 	bool obvious = TRUE;
8125 	/* Player blind-ness */
8126 	bool blind;
8127 	/* Player needs a "description" (he is blind) */
8128 	bool fuzzy = FALSE;
8129 	/* Player is damaging herself (eg. by shattering potion) */
8130 	bool self = FALSE;
8131 
8132 	/* Source monster */
8133 	monster_type *m_ptr = NULL;
8134 	/* Monster name (for attacks) */
8135 	char m_name[MNAME_LEN], m_name_gen[MNAME_LEN];
8136 	/* Monster name (for damage) */
8137 	char killer[MNAME_LEN];
8138 	/* Colour of the damage, either r (standard) or e (unique monster) */
8139 	char damcol = 'o';
8140 	int psi_resists = 0, hack_dam = 0;
8141 	/* Hack -- messages */
8142 //	cptr act = NULL;
8143 	/* For resist_time: Limit randomization of effect */
8144 	int time_influence_choices;
8145 	/* Another player casting attack spell on us? */
8146 	bool friendly_player = FALSE;
8147 
8148 	/* Bad player number */
8149 	if (Ind <= 0) return (FALSE);
8150 
8151 	p_ptr = Players[Ind];
8152 
8153 	/* Player has already been hit, return - mikaelh */
8154 	if (p_ptr->got_hit) return (FALSE);
8155 
8156 	r_ptr = &r_info[p_ptr->body_monster];
8157 
8158 	/* Catch healing hacks */
8159 	if (typ == GF_HEAL_PLAYER) {
8160 		hack_dam = dam & 0x3C00;
8161 		dam = dam & 0x03FF;
8162 	}
8163 
8164 	/* shadow running protects from taking ranged damage - C. Blue
8165 	   note: currently thereby also affecting friendly effects' 'damage'. */
8166 	if (p_ptr->shadow_running) dam /= 3;
8167 
8168 	blind = (p_ptr->blind ? TRUE : FALSE);
8169 
8170 	/* Player is not here */
8171 	if ((x != p_ptr->px) || (y != p_ptr->py) || (!inarea(wpos,&p_ptr->wpos))) return (FALSE);
8172 
8173 	/* Player cannot hurt himself */
8174 	if (0 - who == Ind) {
8175 		if (flg & (PROJECT_SELF | PROJECT_PLAY)) self = TRUE;
8176 		else return (FALSE);
8177 	}
8178 
8179 	/* Mega-Hack -- Players cannot hurt other players */
8180 	if (cfg.use_pk_rules == PK_RULES_NEVER && who <= 0 &&
8181 	    who > PROJECTOR_UNUSUAL
8182 	    && !(flg & PROJECT_PLAY)) /* except if it's an explicitely player-affecting spell! */
8183 		return (FALSE);
8184 
8185 	/* Store/house is safe -- NOT in dungeon! */
8186 	if (p_ptr->store_num != -1 && istown(wpos)) return(FALSE);
8187 
8188 	/* Extract radius */
8189 	div = r + 1;
8190 
8191 	/* Damage decrease over radius */
8192 	dam = radius_damage(dam, div, typ);
8193 
8194 	/* Hack -- always do at least one point of damage */
8195 	if (dam <= 0) dam = 1;
8196 
8197 	/* Hack -- Never do excessive damage */
8198 	if (dam > MAGICAL_CAP) dam = MAGICAL_CAP;
8199 
8200 	/* If the player is blind, be more descriptive */
8201 	if (blind) fuzzy = TRUE;
8202 
8203 	/* If the player is hit by a trap, be more descritive */
8204 	if (who <= PROJECTOR_UNUSUAL) fuzzy = TRUE;
8205 
8206 	if (who > 0) {
8207 		/* Get the source monster */
8208 		m_ptr = &m_list[who];
8209 
8210 		/* Get the monster name for actions */
8211 		monster_desc(Ind, m_name, who, 0);
8212 		monster_desc(Ind, m_name_gen, who, 0x02);
8213 
8214 		/* Get the monster's killing name */
8215 		monster_desc(Ind, killer, who, 0x88);
8216 
8217 		/* Get the monster's real name */
8218 		monster_desc(Ind, p_ptr->really_died_from, who, 0x100);
8219 
8220 		/* Unique monsters cause different damage message colour */
8221 		if (race_inf(m_ptr)->flags1 & RF1_UNIQUE) damcol = 'L';
8222 	}
8223 	/* hack -- by trap */
8224 	else if (who == PROJECTOR_TRAP) {
8225 		if (attacker) {
8226 			sprintf(killer, "a%s %s", is_a_vowel(attacker[0]) ? "n" : "", attacker);
8227 			sprintf(m_name, "a%s %s", is_a_vowel(attacker[0]) ? "n" : "", attacker);
8228 			sprintf(m_name_gen, "the %s", attacker);
8229 		} else {
8230 			/* Hopefully never. */
8231 			/* OUTDATED: Actually this can happen if player's not on the trap (eg. door traps) */
8232 			sprintf(killer, "a mysterious accident");
8233 			sprintf(m_name, "something");
8234 			sprintf(m_name_gen, "the");
8235 		}
8236 	}
8237 	/* hack -- by shattering potion */
8238 	else if (who == PROJECTOR_POTION) {
8239 		/* TODO: add potion name */
8240 		sprintf(killer, "an evaporating potion");
8241 		sprintf(m_name, "an evaporating potion");
8242 		sprintf(m_name_gen, "the");
8243 	}
8244 	/* hack -- by malformed invocation (runespell backlash) */
8245 	else if (who == PROJECTOR_RUNE) {
8246 		sprintf(killer, "a malformed invocation");
8247 		sprintf(m_name, "a malformed invocation");
8248 		sprintf(m_name_gen, "the");
8249 	}
8250 	/* hack -- another player who has logged out */
8251 	else if (who == PROJECTOR_PLAYER) {
8252 		sprintf(killer, "another player");
8253 		sprintf(m_name, "another player");
8254 		sprintf(m_name_gen, "its");
8255 
8256 		/* Assume they were friendly */
8257 		friendly_player = TRUE;
8258 
8259 		/* Will hurt other players if it was a damaging spell!
8260 		   So we should just exit here. Only drawback might be,
8261 		   that in PvP a player cannot die from his opponent's
8262 		   remaining nox cloud after he killed him ;). - C. Blue */
8263 		return FALSE;
8264 	}
8265 	else if (who == PROJECTOR_TERRAIN) {
8266 		dun_level *l_ptr = getfloor(wpos);
8267 		if ((l_ptr && (l_ptr->flags2 & LF2_FAIR_TERRAIN_DAM)) ||
8268 		    (in_sector00(wpos) && (sector00flags2 & LF2_FAIR_TERRAIN_DAM)))
8269 			dam = (p_ptr->mhp * (8 + rand_int(5))) / 15 + 1;
8270 			/* (4hp is lvl 1 char's min); maybe TODO: give high level players a slight advantage (cause higher loss if they die) */
8271 
8272 		sprintf(killer, "hazardous environment");
8273 		sprintf(m_name, "hazardous environment");
8274 		sprintf(m_name_gen, "the");
8275 	}
8276 	/* hack -- by shattering potion */
8277 	else if (who <= PROJECTOR_UNUSUAL) {
8278 		/* TODO: add potion name */
8279 		sprintf(killer, "something weird");
8280 		sprintf(m_name, "something");
8281 		sprintf(m_name_gen, "some");
8282 	}
8283 	else if (self) {
8284 		sprintf(killer, p_ptr->male ? "himself" : "herself");
8285 		sprintf(m_name, "It's yourself who");
8286 		sprintf(m_name_gen, "your own");
8287 
8288 		/* Do not apply Stair-GoI/deflection etc. on one's own helpful self-affecting spells */
8289 		if ((typ == GF_HEAL_PLAYER) || (typ == GF_AWAY_ALL) ||
8290 		    (typ == GF_WRAITH_PLAYER) || (typ == GF_SPEED_PLAYER) ||
8291 		    (typ == GF_SHIELD_PLAYER) || (typ == GF_RECALL_PLAYER) ||
8292 		    (typ == GF_BLESS_PLAYER) || (typ == GF_REMFEAR_PLAYER) ||
8293 		    (typ == GF_REMCONF_PLAYER) || (typ == GF_REMIMAGE_PLAYER) ||
8294 		    (typ == GF_SATHUNGER_PLAYER) || (typ == GF_RESFIRE_PLAYER) ||
8295 		    (typ == GF_RESCOLD_PLAYER) || (typ == GF_CUREPOISON_PLAYER) ||
8296 		    (typ == GF_SEEINVIS_PLAYER) || (typ == GF_SEEMAP_PLAYER) ||
8297 		    (typ == GF_CURECUT_PLAYER) || (typ == GF_CURESTUN_PLAYER) ||
8298 		    (typ == GF_DETECTCREATURE_PLAYER) || (typ == GF_DETECTDOOR_PLAYER) ||
8299 		    (typ == GF_DETECTTRAP_PLAYER) || (typ == GF_TELEPORTLVL_PLAYER) ||
8300 		    (typ == GF_RESPOIS_PLAYER) || (typ == GF_RESELEC_PLAYER) ||
8301 		    (typ == GF_RESACID_PLAYER) || (typ == GF_HPINCREASE_PLAYER) ||
8302 		    (typ == GF_HERO_PLAYER) || (typ == GF_SHERO_PLAYER) || (typ == GF_MINDBOOST_PLAYER) ||
8303 		    (typ == GF_TELEPORT_PLAYER) || (typ == GF_ZEAL_PLAYER) ||
8304 		    (typ == GF_RESTORE_PLAYER) || (typ == GF_REMCURSE_PLAYER) ||
8305 		    (typ == GF_CURE_PLAYER) || (typ == GF_RESURRECT_PLAYER) ||
8306 		    (typ == GF_SANITY_PLAYER) || (typ == GF_SOULCURE_PLAYER) ||
8307                     (typ == GF_OLD_HEAL) || (typ == GF_OLD_SPEED) || (typ == GF_PUSH) ||
8308 		    (typ == GF_HEALINGCLOUD) || /* Also not a hostile spell */
8309 		    (typ == GF_MINDBOOST_PLAYER) || (typ == GF_IDENTIFY) ||
8310 		    (typ == GF_SLOWPOISON_PLAYER) || (typ == GF_CURING) ||
8311 		    (typ == GF_OLD_POLY)) /* may (un)polymorph himself */
8312 			friendly_player = TRUE;
8313 	}
8314 	else if (IS_PVP) {
8315 //		strcpy(killer, p_ptr->play_vis[0 - who] ? Players[0 - who]->name : "It");
8316 //		strcpy(m_name, p_ptr->play_vis[0 - who] ? Players[0 - who]->name : "It");
8317 		sprintf(killer, "%s", p_ptr->play_vis[0 - who] ? Players[0 - who]->name : "It");
8318 		sprintf(m_name, "%s", p_ptr->play_vis[0 - who] ? Players[0 - who]->name : "It");
8319 		if (p_ptr->play_vis[0 - who]) {
8320 			if (Players[0 - who]->name[strlen(Players[0 - who]->name) - 1] != 's')
8321 				sprintf(m_name_gen, "%s's", Players[0 - who]->name);
8322 			else
8323 				sprintf(m_name_gen, "%s'", Players[0 - who]->name);
8324 		} else
8325 			sprintf(m_name_gen, "its");
8326 		strcpy(p_ptr->really_died_from, Players[0 - who]->name);
8327 
8328 		/* Do not become hostile if it was a friendly spell */
8329 		if ((typ != GF_HEAL_PLAYER) && (typ != GF_AWAY_ALL) &&
8330 		    (typ != GF_WRAITH_PLAYER) && (typ != GF_SPEED_PLAYER) &&
8331 		    (typ != GF_SHIELD_PLAYER) && (typ != GF_RECALL_PLAYER) &&
8332 		    (typ != GF_BLESS_PLAYER) && (typ != GF_REMFEAR_PLAYER) &&
8333 		    (typ != GF_REMCONF_PLAYER) && (typ != GF_REMIMAGE_PLAYER) &&
8334 		    (typ != GF_SATHUNGER_PLAYER) && (typ != GF_RESFIRE_PLAYER) &&
8335 		    (typ != GF_RESCOLD_PLAYER) && (typ != GF_CUREPOISON_PLAYER) &&
8336 		    (typ != GF_SEEINVIS_PLAYER) && (typ != GF_SEEMAP_PLAYER) &&
8337 		    (typ != GF_CURECUT_PLAYER) && (typ != GF_CURESTUN_PLAYER) &&
8338 		    (typ != GF_DETECTCREATURE_PLAYER) && (typ != GF_DETECTDOOR_PLAYER) &&
8339 		    (typ != GF_DETECTTRAP_PLAYER) && (typ != GF_TELEPORTLVL_PLAYER) &&
8340 		    (typ != GF_RESPOIS_PLAYER) && (typ != GF_RESELEC_PLAYER) &&
8341 		    (typ != GF_RESACID_PLAYER) && (typ != GF_HPINCREASE_PLAYER) &&
8342 		    (typ != GF_HERO_PLAYER) && (typ != GF_SHERO_PLAYER) && (typ != GF_MINDBOOST_PLAYER) &&
8343 		    (typ != GF_TELEPORT_PLAYER) && (typ != GF_ZEAL_PLAYER) &&
8344 		    (typ != GF_RESTORE_PLAYER) && (typ != GF_REMCURSE_PLAYER) &&
8345 		    (typ != GF_CURE_PLAYER) && (typ != GF_RESURRECT_PLAYER) &&
8346 		    (typ != GF_SANITY_PLAYER) && (typ != GF_SOULCURE_PLAYER) &&
8347                     (typ != GF_OLD_HEAL) && (typ != GF_OLD_SPEED) && (typ != GF_PUSH) &&
8348 		    (typ != GF_HEALINGCLOUD) && /* Also not a hostile spell */
8349 		    (typ != GF_MINDBOOST_PLAYER) && (typ != GF_IDENTIFY) &&
8350 		    (typ != GF_SLOWPOISON_PLAYER) && (typ != GF_CURING) &&
8351 		    (typ != GF_OLD_POLY)) /* Non-hostile players may (un)polymorph each other */
8352 		{ /* If this was intentional, make target hostile */
8353 			if (check_hostile(0 - who, Ind)) {
8354 				/* Make target hostile if not already */
8355 				if (!check_hostile(Ind, 0 - who)) {
8356 					bool result = FALSE;
8357 
8358 					if (Players[Ind]->pvpexception < 2)
8359 						result = add_hostility(Ind, killer, FALSE);
8360 
8361 					/* Log it if no blood bond - mikaelh */
8362 					if (!player_list_find(p_ptr->blood_bond, Players[0 - who]->id)) {
8363 						s_printf("%s attacked %s (spell; result %d).\n", p_ptr->name, Players[0 - who]->name, result);
8364 					}
8365 				}
8366 			}
8367 
8368 			/* Hostile players hit each other */
8369 			if (check_hostile(Ind, 0 - who)) {
8370 #ifdef EXPERIMENTAL_PVP_SPELL_DAM
8371 				int __dam = randint(dam);
8372 				if (randint(1)) __dam *= -1;
8373 				dam += __dam;
8374 #else
8375 				/* XXX Reduce damage to 1/3 */
8376 				dam = (dam + PVP_SPELL_DAM_REDUCTION - 1) / PVP_SPELL_DAM_REDUCTION;
8377 #endif
8378 			}
8379 
8380 			/* people not in the same party hit each other */
8381 			else if (!Players[0 - who]->party || !p_ptr->party ||
8382 				(!player_in_party(Players[0 - who]->party, Ind)))
8383 			{
8384 #if 0			/* NO - C. Blue */
8385 #else			/* changed it to YES..  - still C. Blue - but added an if..*/
8386 			if (check_hostile(0 - who, Ind)) {
8387 #ifdef EXPERIMENTAL_PVP_SPELL_DAM
8388 				int __dam = randint(dam);
8389 				if (randint(1)) __dam *= -1;
8390 				dam += __dam;
8391 #else
8392 				/* XXX Reduce damage by 1/3 */
8393 				dam = (dam + PVP_SPELL_DAM_REDUCTION - 1) / PVP_SPELL_DAM_REDUCTION;
8394 #endif
8395 #ifdef KURZEL_PK
8396 				if (!magik(NEUTRAL_FIRE_CHANCE))
8397 #else
8398 				if ((cfg.use_pk_rules == PK_RULES_DECLARE &&
8399 				    !(p_ptr->pkill & PKILL_KILLER)) &&
8400 				    !magik(NEUTRAL_FIRE_CHANCE))
8401 #endif
8402 //#endif (<- use this endif, if above #if 0 becomes #if 1 again)			/* Just return without harming: */
8403 					return(FALSE);
8404 			} else { return(FALSE); }
8405 #endif /* ..and remove this one accordingly */
8406 			} else {
8407 				/* Players in the same party can't harm each others */
8408 #if FRIEND_FIRE_CHANCE
8409  #ifdef EXPERIMENTAL_PVP_SPELL_DAM
8410 				int __dam = randint(dam);
8411 				if (randint(1)) __dam *= -1;
8412 				dam += __dam;
8413  #else
8414 				dam = (dam + PVP_SPELL_DAM_REDUCTION - 1) / PVP_SPELL_DAM_REDUCTION;
8415  #endif
8416 				if (!magik(FRIEND_FIRE_CHANCE))
8417 #endif
8418 				return(FALSE);
8419 			}
8420 		/* If it's a support spell (friendly), remember the caster's level for henc anti-cheeze
8421 		   to prevent him from getting exp until the supporting effects surely have run out: */
8422 		} else if (typ != GF_OLD_POLY) {
8423 			if (p_ptr->supp < Players[0 - who]->max_lev) p_ptr->supp = Players[0 - who]->max_lev;
8424 			if (p_ptr->supp_top < Players[0 - who]->max_plv) p_ptr->supp_top = Players[0 - who]->max_plv;
8425 			p_ptr->support_timer = cfg.spell_stack_limit ? cfg.spell_stack_limit : 200;
8426 
8427 			friendly_player = TRUE;
8428 		/* It's a non-hostile, yet possibly damaging spell which isn't
8429 		   affected by 'friendly fire' rules or pvp rules, but counts
8430 		   more like 'an accident' if it really damages someone. Usually
8431 		   it is probably a supportive spell though. (eg GF_HEALINGCLOUD) */
8432 		} else {
8433 			friendly_player = TRUE;
8434 		}
8435 	}
8436 
8437 
8438 	/* PvP often gives same message output as fuzzy */
8439 	if (!strcmp(attacker,"") || !strcmp(m_name,"")) fuzzy = TRUE;
8440 
8441 	/* Ghost-check (also checks for admin status) */
8442 	/* GHOST CHECK */
8443 	if ((p_ptr->ghost && ((typ == GF_HEAL_PLAYER) || /*(typ == GF_AWAY_ALL) ||*/
8444 	    (typ == GF_WRAITH_PLAYER) || (typ == GF_SPEED_PLAYER) ||
8445 	    /*(typ == GF_SHIELD_PLAYER) || (typ == GF_RECALL_PLAYER) ||*/
8446 	    (typ == GF_BLESS_PLAYER) || (typ == GF_REMFEAR_PLAYER) ||
8447 	    (typ == GF_REMCONF_PLAYER) || (typ == GF_REMIMAGE_PLAYER) ||
8448 	    (typ == GF_SATHUNGER_PLAYER) || /*(typ == GF_RESFIRE_PLAYER) ||
8449 	    (typ == GF_RESCOLD_PLAYER) ||*/ (typ == GF_CUREPOISON_PLAYER) ||
8450 	    (typ == GF_SEEINVIS_PLAYER) || (typ == GF_SEEMAP_PLAYER) ||
8451 	    (typ == GF_CURECUT_PLAYER) || /*(typ == GF_CURESTUN_PLAYER) ||*/
8452 	    (typ == GF_DETECTCREATURE_PLAYER) || (typ == GF_DETECTDOOR_PLAYER) ||
8453 	    (typ == GF_DETECTTRAP_PLAYER) || /*(typ == GF_TELEPORTLVL_PLAYER) ||
8454 	    (typ == GF_RESPOIS_PLAYER) || (typ == GF_RESELEC_PLAYER) ||
8455 	    (typ == GF_RESACID_PLAYER) ||*/ (typ == GF_HPINCREASE_PLAYER) ||
8456 	    (typ == GF_HERO_PLAYER) || (typ == GF_SHERO_PLAYER) ||
8457 	    /*(typ == GF_TELEPORT_PLAYER) ||*/ (typ == GF_ZEAL_PLAYER) || (typ == GF_REMCURSE_PLAYER) ||
8458 	    (typ == GF_RESTORE_PLAYER) || (typ == GF_CURING) ||
8459 	    (typ == GF_CURE_PLAYER) || /*(typ == GF_RESURRECT_PLAYER) ||
8460 	    (typ == GF_SANITY_PLAYER) || (typ == GF_SOULCURE_PLAYER) ||*/
8461 	    (typ == GF_OLD_HEAL) || (typ == GF_OLD_SPEED) ||
8462 	    (typ == GF_HEALINGCLOUD) || /* shoo ghost, shoo */
8463 	    (typ == GF_IDENTIFY) || (typ == GF_SLOWPOISON_PLAYER) ||
8464 	    (typ == GF_OLD_POLY) || (typ == GF_MINDBOOST_PLAYER)))
8465 	    ||
8466 	    /* ADMIN CHECK */
8467 	    (is_admin(p_ptr) && ((typ == GF_HEAL_PLAYER) || (typ == GF_AWAY_ALL) ||
8468 	    (typ == GF_WRAITH_PLAYER) || (typ == GF_SPEED_PLAYER) ||
8469 	    (typ == GF_SHIELD_PLAYER) || (typ == GF_RECALL_PLAYER) ||
8470 	    (typ == GF_BLESS_PLAYER) || (typ == GF_REMFEAR_PLAYER) ||
8471 	    (typ == GF_REMCONF_PLAYER) || (typ == GF_REMIMAGE_PLAYER) ||
8472 	    (typ == GF_SATHUNGER_PLAYER) || (typ == GF_RESFIRE_PLAYER) ||
8473 	    (typ == GF_RESCOLD_PLAYER) || (typ == GF_CUREPOISON_PLAYER) ||
8474 	    (typ == GF_SEEINVIS_PLAYER) || (typ == GF_SEEMAP_PLAYER) ||
8475 	    (typ == GF_CURECUT_PLAYER) || (typ == GF_CURESTUN_PLAYER) ||
8476 	    (typ == GF_DETECTCREATURE_PLAYER) || (typ == GF_DETECTDOOR_PLAYER) ||
8477 	    (typ == GF_DETECTTRAP_PLAYER) || (typ == GF_TELEPORTLVL_PLAYER) ||
8478 	    (typ == GF_RESPOIS_PLAYER) || (typ == GF_RESELEC_PLAYER) ||
8479 	    (typ == GF_RESACID_PLAYER) || (typ == GF_HPINCREASE_PLAYER) ||
8480 	    (typ == GF_HERO_PLAYER) || (typ == GF_SHERO_PLAYER) ||
8481 	    (typ == GF_TELEPORT_PLAYER) || (typ == GF_ZEAL_PLAYER) ||
8482 	    (typ == GF_RESTORE_PLAYER) || (typ == GF_REMCURSE_PLAYER) ||
8483 	    (typ == GF_CURE_PLAYER) || (typ == GF_RESURRECT_PLAYER) ||
8484 	    (typ == GF_SANITY_PLAYER) || (typ == GF_SOULCURE_PLAYER) ||
8485 	    (typ == GF_OLD_HEAL) || (typ == GF_OLD_SPEED) ||
8486 	    (typ == GF_HEALINGCLOUD) || (typ == GF_MINDBOOST_PLAYER) ||
8487 	    (typ == GF_SLOWPOISON_PLAYER) || (typ == GF_CURING) ||
8488 	    (typ == GF_OLD_POLY) || (typ == GF_IDENTIFY))))
8489 	{ /* No effect on ghosts / admins */
8490 #if 0 //redundant?
8491 		/* Skip non-connected players */
8492 		if (p_ptr->conn != NOT_CONNECTED) {
8493 			/* Disturb */
8494 			disturb(Ind, 1, 0);
8495 		}
8496 #endif
8497 		/* Return "Anything seen?" */
8498 		return (obvious);
8499 	}
8500 
8501 
8502 
8503 #ifndef NEW_DODGING
8504 	/* Bolt attack from a monster, a player or a trap */
8505 //	if ((!rad) && get_skill(p_ptr, SKILL_DODGE) && (who > 0))
8506 	/* Hack -- HIDE(direct) spell cannot be dodged */
8507 	if (!friendly_player &&
8508 	    get_skill(p_ptr, SKILL_DODGE) && !(flg & PROJECT_HIDE | PROJECT_JUMP | PROJECT_NODO))
8509 	{
8510 		if ((!rad) && (who >= PROJECTOR_TRAP)) {
8511 			//		int chance = (p_ptr->dodge_level - ((r_info[who].level * 5) / 6)) / 3;
8512 			/* Hack -- let's use 'dam' for now */
8513 			int chance = (p_ptr->dodge_level - dam / 6) / 3;
8514 
8515 			if ((chance > 0) && magik(chance)) {
8516 //				msg_print(Ind, "You dodge a magical attack!");
8517 				msg_format(Ind, "\377%cYou dodge the projectile!", COLOUR_DODGE_GOOD);
8518 				return (TRUE);
8519 			}
8520 		}
8521 		/* MEGAHACK -- allow to dodge 'bolt' traps */
8522 		else if ((rad < 2) && (who == PROJECTOR_TRAP)) {
8523 			/* Hack -- let's use 'dam' for now */
8524 			int chance = (p_ptr->dodge_level - dam / 4) / 4;
8525 
8526 			if ((chance > 0) && magik(chance)) {
8527 				msg_format(Ind, "\377%cYou dodge a magical attack!", COLOUR_DODGE_GOOD);
8528 				return (TRUE);
8529 			}
8530 		}
8531 	}
8532 #else
8533 	/* Bolt attack from a monster, a player or a trap */
8534 //	if (!p_ptr->blind && !(flg & (PROJECT_HIDE | PROJECT_GRID | PROJECT_JUMP)) && magik(apply_dodge_chance(Ind, getlevel(wpos) + 1000))) { /* hack - more difficult to dodge ranged attacks */
8535 	if (!friendly_player &&
8536 	    !p_ptr->blind && !(flg & (PROJECT_HIDE | PROJECT_JUMP | PROJECT_STAY | PROJECT_NODO)) && magik(apply_dodge_chance(Ind, getlevel(wpos)))) {
8537 		if ((!rad) && (who >= PROJECTOR_TRAP)) {
8538 			msg_format(Ind, "\377%cYou dodge %s projectile!", COLOUR_DODGE_GOOD, m_name_gen);
8539 			return (TRUE);
8540 		}
8541 		/* MEGAHACK -- allow to dodge 'bolt' traps */
8542 		else if ((rad < 2) && (who == PROJECTOR_TRAP)) {
8543 			msg_format(Ind, "\377%cYou dodge %s magical attack!", COLOUR_DODGE_GOOD, m_name_gen);
8544 			return (TRUE);
8545 		}
8546 	}
8547 #endif
8548 
8549 
8550 	/* Reflection */
8551 #if 0
8552 	/* Effects done by the plane cannot bounce */
8553 	if (!friendly_player && p_ptr->reflect && !a_rad && !(randint(10) == 1) && ((who != -101) && (who != -100))) {
8554 				int t_y, t_x;
8555 		int max_attempts = 10;
8556 
8557 		if (blind) msg_print("Something bounces!");
8558 		else msg_print("The attack bounces!");
8559 
8560 		/* Choose 'new' target */
8561 		do {
8562 			t_y = m_list[who].fy - 1 + randint(3);
8563 			t_x = m_list[who].fx - 1 + randint(3);
8564 			max_attempts--;
8565 		} while (max_attempts && in_bounds2(t_y, t_x) &&
8566 		    !(player_has_los_bold(t_y, t_x)));
8567 
8568 		if (max_attempts < 1) {
8569 			t_y = m_list[who].fy;
8570 			t_x = m_list[who].fx;
8571 		}
8572 
8573 		project(0, 0, t_y, t_x, dam, typ, (PROJECT_STOP|PROJECT_KILL), "");
8574 
8575 		disturb(1, 0);
8576 		return(TRUE);
8577 	}
8578 #endif
8579 	/* pre-calc kinetic shield mana tax before doing the reflection check below */
8580 	if (!friendly_player && p_ptr->kinetic_shield && (typ == GF_ARROW || typ == GF_MISSILE)
8581 	    && p_ptr->csp >= dam / 7 &&
8582 	    !rad && who != PROJECTOR_POTION && who != PROJECTOR_TERRAIN &&
8583 	    (flg & PROJECT_KILL) && !(flg & (PROJECT_NORF | PROJECT_JUMP | PROJECT_STAY | PROJECT_NODF))) {
8584 		/* drain mana */
8585 		p_ptr->csp -= dam / 7;
8586 		p_ptr->redraw |= PR_MANA;
8587 		/* test for success */
8588 		if (rand_int(2) == 0) kinetic_shield = TRUE;
8589 	}
8590 	/* Effects done by the plane cannot bounce,
8591 	   balls / clouds / storms / walls (and beams atm too) cannot bounce - C. Blue */
8592 	if (!friendly_player && (
8593 	    /* kinetic shield? (same as reflect basically) */
8594 	    kinetic_shield
8595 	    /* reflect? */
8596 	    || (p_ptr->reflect &&
8597 	    !rad && who != PROJECTOR_POTION && who != PROJECTOR_TERRAIN &&
8598 	    (flg & PROJECT_KILL) && !(flg & (PROJECT_NORF | PROJECT_JUMP | PROJECT_STAY | PROJECT_NODF)) &&
8599 	    rand_int(20) < ((typ == GF_ARROW || typ == GF_MISSILE) ? 15 : 9))
8600 #ifdef USE_BLOCKING
8601 	    /* using a shield? requires USE_BLOCKING */
8602 	    || (magik(apply_block_chance(p_ptr, p_ptr->shield_deflect / 5)) &&
8603 	    !rad && who != PROJECTOR_POTION && who != PROJECTOR_TERRAIN &&
8604 	    (flg & PROJECT_KILL) && !(flg & (PROJECT_NORF | PROJECT_JUMP | PROJECT_STAY | PROJECT_NODF)) &&
8605 	    rand_int(20) < ((typ == GF_ARROW || typ == GF_MISSILE) ? 15 : 9))
8606 #endif
8607 	    ))
8608 	{
8609 		int t_y, t_x, ay, ax;
8610 		int max_attempts = 10;
8611 
8612 		if (blind) msg_print(Ind, "Something bounces!");
8613 		else {
8614 			if (p_ptr->play_vis[0 - who])
8615 				msg_format(Ind, "%s attack bounces!", m_name_gen);
8616 			else
8617 				msg_print(Ind, "Its attack bounces!");
8618 		}
8619 
8620 /*		if ((who != PROJECTOR_TRAP) && who)  isn't this wrong? */
8621 		if (who && (who > PROJECTOR_UNUSUAL)) { /* can only hit a monster or a player when bouncing */
8622 			if (who < 0) {
8623 				ay = Players[-who]->py;
8624 				ax = Players[-who]->px;
8625 			} else {
8626 				ay = m_list[who].fy;
8627 				ax = m_list[who].fx;
8628 			}
8629 
8630 
8631 			/* Choose 'new' target */
8632 			do {
8633 				t_y = ay - 1 + randint(3);
8634 				t_x = ax - 1 + randint(3);
8635 				max_attempts--;
8636 			}
8637 #if 0
8638 			while (max_attempts && in_bounds2(wpos, t_y, t_x) &&
8639 					!(player_has_los_bold(Ind, t_y, t_x)));
8640 #else	// 0
8641 			while (max_attempts && (!in_bounds2(wpos, t_y, t_x) ||
8642 					!(player_has_los_bold(Ind, t_y, t_x))));
8643 #endif	// 0
8644 
8645 			if (max_attempts < 1) {
8646 				t_y = ay;
8647 				t_x = ax;
8648 			}
8649 
8650 //			project(0, 0, wpos, t_y, t_x, dam, typ, (PROJECT_STOP|PROJECT_KILL));
8651 			project(0 - Ind, 0, wpos, t_y, t_x, dam, typ, (PROJECT_STOP|PROJECT_KILL), "");
8652 		}
8653 
8654 		disturb(Ind, 1, 0);
8655 		return TRUE;
8656 	}
8657 
8658 
8659 #ifdef USE_BLOCKING
8660 	/* Bolt attacks: Took cover behind a shield? requires USE_BLOCKING */
8661 	if (!friendly_player &&  /* cannot take cover from clouds or LOS projections (latter might be subject to change?) - C. Blue */
8662 	     /* jump for LOS projecting, stay for clouds; !norf was already checked above -- not sure if fire_beam was covered (PROJECT_BEAM)! */
8663 	    !rad && (flg & PROJECT_KILL) &&
8664 	    !(flg & (PROJECT_NORF | PROJECT_JUMP | PROJECT_STAY | PROJECT_NODF))
8665 	    ) /* requires stances to * 2 etc.. post-king -> best stance */
8666 	{
8667 		if (p_ptr->shield_deflect && magik(apply_block_chance(p_ptr, p_ptr->shield_deflect) / ((flg & PROJECT_LODF) ? 2 : 1))) {
8668 			if (blind) msg_format(Ind, "\377%cSomething glances off your shield!", COLOUR_BLOCK_GOOD);
8669 			else msg_format(Ind, "\377%cYou deflect %s attack!", COLOUR_BLOCK_GOOD, m_name_gen);
8670  #ifdef USE_SOUND_2010
8671                         if (p_ptr->sfx_defense) sound(Ind, "block_shield", NULL, SFX_TYPE_ATTACK, FALSE);//not block_shield_projectile (silly for magical attacks)
8672  #endif
8673 
8674  #ifndef NEW_SHIELDS_NO_AC
8675 			/* if we hid behind the shield from an acidic attack, damage the shield probably! */
8676 			if (magik((dam < 5 ? 5 : (dam < 50 ? 10 : 25)))) shield_takes_damage(Ind, typ);
8677  #endif
8678 
8679 			disturb(Ind, 1, 0);
8680 			return TRUE;
8681 		}
8682 	}
8683 	/* Ball attacks: Took cover behind a shield? requires USE_BLOCKING */
8684 	else if (!friendly_player && /* cannot take cover from clouds or LOS projections (latter might be subject to change?) - C. Blue */
8685 	     /* jump for LOS projecting, stay for clouds; !norf was already checked above -- not sure if fire_beam was covered (PROJECT_BEAM)! */
8686 	    (flg & PROJECT_KILL) && (flg & PROJECT_NORF) && !(flg & (PROJECT_JUMP | PROJECT_STAY | PROJECT_NODF))) /* PROJECT_STAY to exempt 'cloud' spells! */
8687 	    /* requires stances to * 2 etc.. post-king -> best stance */
8688 	{
8689 		if (p_ptr->shield_deflect && magik(apply_block_chance(p_ptr, p_ptr->shield_deflect) / ((flg & PROJECT_LODF) ? 4 : 2))) {
8690 			if (blind) msg_format(Ind, "\377%cSomething hurls along your shield!", COLOUR_BLOCK_GOOD);
8691 			else msg_format(Ind, "\377%cYou cover before %s attack!", COLOUR_BLOCK_GOOD, m_name_gen);
8692 
8693  #ifndef NEW_SHIELDS_NO_AC
8694 			/* if we hid behind the shield from an acidic attack, damage the shield probably! */
8695 			if (magik((dam < 5 ? 5 : (dam < 50 ? 10 : 25)))) shield_takes_damage(Ind, typ);
8696  #endif
8697 
8698 			disturb(Ind, 1, 0);
8699 			return TRUE;
8700 		}
8701 	}
8702 #endif
8703 
8704 	/* Test for stair GOI already, to prevent not only damage but according effects too! - C. Blue */
8705 	/* Mega-Hack -- Apply "invulnerability" */
8706 	if (!friendly_player && p_ptr->invuln && (!bypass_invuln)) {
8707 		/* 1 in 2 chance to fully deflect the damage */
8708 		if (magik(40)) {
8709 			msg_print(Ind, "The attack is fully deflected by a magic shield.");
8710 			if (who != PROJECTOR_TERRAIN) break_cloaking(Ind, 0);
8711 			return(TRUE);
8712 		}
8713 		dam = (dam + 1) / 2;
8714 
8715 		/* prevent multiple damage cutting */
8716 		p_ptr->invuln_applied = TRUE;
8717 	}
8718 
8719 
8720 	/* Analyze the damage */
8721 	switch (typ) {
8722 	/* Psionics */
8723 	case GF_PSI:
8724 		if (rand_int(100) < p_ptr->skill_sav) psi_resists++;
8725 		if (p_ptr->mindboost && magik(p_ptr->mindboost_power)) psi_resists++;
8726 		if ((p_ptr->shero || p_ptr->berserk) && (rand_int(100) >= p_ptr->skill_sav)) psi_resists--;
8727 		if (p_ptr->confused) psi_resists--;
8728 		if (p_ptr->image) psi_resists--;
8729 		if (p_ptr->stun) psi_resists--;
8730 		if ((p_ptr->afraid) && (rand_int(100) >= p_ptr->skill_sav)) psi_resists--;
8731 
8732 		if (psi_resists > 0) {
8733 			/* No side effects */
8734 
8735 			/* Reduce damage */
8736 			for (k = 0; k < psi_resists ; k++) {
8737 				dam = dam * 4 / (4 + randint(5));
8738 			}
8739 
8740 			/* Telepathy reduces damage */
8741 			if (p_ptr->telepathy) dam = dam * (3 + randint(6)) / 9;
8742 		} else {
8743 			/* Telepathy increases damage */
8744 			if (p_ptr->telepathy) dam = dam * (6 + randint(6)) / 6;
8745 		}
8746 		if (p_ptr->pclass == CLASS_MINDCRAFTER) dam /= 2;
8747 
8748 		if (fuzzy) msg_format(Ind, "Your mind is hit by mental energy for \377%c%d \377wdamage!", damcol, dam);
8749 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8750 
8751 		if (psi_resists <= 0) {
8752 			/* Unresisted */
8753 			if (!p_ptr->resist_conf &&
8754 			    !(p_ptr->mindboost && magik(p_ptr->mindboost_power)))
8755 				//set_confused(Ind, p_ptr->confused + rand_int(20) + 10);    too long for pvp?
8756 				set_confused(Ind, p_ptr->confused + rand_int(5) + 5);
8757 
8758 			/* At the moment:
8759 			   No sleep/stun/fear effects (like it has on monsters), or image(hallu)
8760 			*/
8761 		}
8762 		take_hit(Ind, dam, killer, -who);
8763 		if (!IS_PVP) take_sanity_hit(Ind, dam / 8, killer); /* note: traps deal ~130..320 damage (depth 0..100) */
8764 		break;
8765 
8766 	/* Standard damage -- hurts inventory too */
8767 	case GF_ACID:
8768 		dam = acid_dam(Ind, dam, killer, -who);
8769 		if (who == PROJECTOR_TERRAIN && dam == 0) ;
8770 		else if (fuzzy) msg_format(Ind, "You are hit by acid for \377%c%d \377wdamage!", damcol, dam);
8771 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8772 		take_hit(Ind, dam, killer, -who);
8773 		break;
8774 
8775 	/* Standard damage -- hurts inventory too */
8776 	case GF_FIRE:
8777 		dam = fire_dam(Ind, dam, killer, -who);
8778 		if (who == PROJECTOR_TERRAIN && dam == 0) ;
8779 		else if (fuzzy) msg_format(Ind, "You are hit by fire for \377%c%d \377wdamage!", damcol, dam);
8780 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8781 		take_hit(Ind, dam, killer, -who);
8782 		break;
8783 
8784 	/* Standard damage -- hurts inventory too */
8785 	case GF_COLD:
8786 		dam = cold_dam(Ind, dam, killer, -who);
8787 		if (who == PROJECTOR_TERRAIN && dam == 0) ;
8788 		else if (fuzzy) msg_format(Ind, "You are hit by cold for \377%c%d \377wdamage!", damcol, dam);
8789 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8790 		take_hit(Ind, dam, killer, -who);
8791 		break;
8792 
8793 	/* Standard damage -- hurts inventory too */
8794 	case GF_ELEC:
8795 		dam = elec_dam(Ind, dam, killer, -who);
8796 		apply_discharge(Ind, dam);
8797 		if (who == PROJECTOR_TERRAIN && dam == 0) ;
8798 		else if (fuzzy) msg_format(Ind, "You are hit by lightning for \377%c%d \377wdamage!", damcol, dam);
8799 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8800 		take_hit(Ind, dam, killer, -who);
8801 		break;
8802 
8803 	/* Standard damage -- also poisons player */
8804 	case GF_POIS:
8805 		if (p_ptr->immune_poison) {
8806 			dam = 0;
8807 			if (who == PROJECTOR_TERRAIN) ;
8808 			else if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
8809 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8810 		} else {
8811 			if (p_ptr->resist_pois) dam = (dam + 2) / 3;
8812 			if (p_ptr->oppose_pois) dam = (dam + 2) / 3;
8813 			if (p_ptr->suscep_pois) dam = (dam + 2) * 2;
8814 
8815 			if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
8816 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8817 			take_hit(Ind, dam, killer, -who);
8818 			if (!(p_ptr->resist_pois || p_ptr->oppose_pois) && dam > 0) {
8819 				/* don't poison for too long in pvp */
8820 				if (IS_PVP) {
8821 					if (p_ptr->poisoned < 10) (void)set_poisoned(Ind, p_ptr->poisoned + rand_int(4), -who);
8822 				} else {
8823 					(void)set_poisoned(Ind, p_ptr->poisoned + rand_int(dam) + 10, -who);
8824 				}
8825 			}
8826 		}
8827 		break;
8828 
8829 		/* Standard damage */
8830 	case GF_MISSILE:
8831 		if (p_ptr->biofeedback) dam /= 2;
8832 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
8833 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8834 		take_hit(Ind, dam, killer, -who);
8835 		break;
8836 
8837 #ifdef ARCADE_SERVER
8838                 case GF_PUSH:
8839           //    msg_print(Ind, "You are pushed by something!");
8840                 msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8841                 (void)set_pushed(Ind, dam);
8842 		break;
8843 #endif
8844 
8845 	case GF_HELL_FIRE:
8846 		if (p_ptr->body_monster && (r_ptr->flags3 & RF3_GOOD)) dam *= 2;
8847 		if (p_ptr->suscep_good) dam = (dam * 3) / 4;
8848 		if (p_ptr->suscep_evil) dam *= 2;
8849 		if (p_ptr->immune_fire) dam /= 2;
8850 		else {
8851 			if (p_ptr->resist_fire) dam = ((dam + 2) * 3) / 4;
8852 			if (p_ptr->oppose_fire) dam = ((dam + 2) * 3) / 4;
8853 			if (p_ptr->suscep_fire) dam = ((dam + 2) * 5) / 3;
8854 		}
8855 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
8856 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8857 		take_hit(Ind, dam, killer, -who);
8858 		break;
8859 
8860 		/* Holy Orb -- Player only takes partial damage */
8861 	case GF_HOLY_ORB:
8862 		if (p_ptr->suscep_evil) dam = (dam * 3) / 4;
8863 		if (p_ptr->suscep_good) dam *= 2;
8864 		if (p_ptr->body_monster && (r_ptr->flags3 & RF3_GOOD)) dam /= 4;
8865 		if (p_ptr->pclass == CLASS_PRIEST) dam = 0;
8866 		if (p_ptr->pclass == CLASS_PALADIN) dam /= 2;
8867 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
8868 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8869 		take_hit(Ind, dam, killer, -who);
8870 		break;
8871 
8872 	case GF_HOLY_FIRE:
8873 		if (p_ptr->suscep_evil) dam = (dam * 3) / 4;
8874 		if (p_ptr->suscep_good) dam *= 2;
8875 		if (p_ptr->body_monster && (r_ptr->flags3 & RF3_GOOD)) dam /= 4;
8876 		if (p_ptr->immune_fire) dam /= 2;
8877 		else {
8878 			if (p_ptr->resist_fire) dam = ((dam + 2) * 3) / 4;
8879 				if (p_ptr->oppose_fire) dam = ((dam + 2) * 3) / 4;
8880 			if (p_ptr->suscep_fire) dam = ((dam + 2) * 4) / 3;
8881 		}
8882 		if (p_ptr->pclass == CLASS_PRIEST) dam = 0;
8883 		if (p_ptr->pclass == CLASS_PALADIN) dam /= 2;
8884 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
8885 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8886 		take_hit(Ind, dam, killer, -who);
8887 		break;
8888 
8889 		/* Arrow -- XXX no dodging */
8890 	case GF_ARROW:
8891 		if (p_ptr->biofeedback) dam /= 2;
8892 		if (fuzzy) msg_format(Ind, "You are hit by something sharp for \377%c%d \377wdamage!", damcol, dam);
8893 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8894 		take_hit(Ind, dam, killer, -who);
8895 		break;
8896 
8897 		/* Plasma -- Fire/Lightning/Force */
8898 	case GF_PLASMA:
8899 		{
8900 			bool ignore_fire = p_ptr->oppose_fire || p_ptr->resist_fire || p_ptr->immune_fire;
8901 			bool ignore_elec = p_ptr->oppose_elec || p_ptr->resist_elec || p_ptr->immune_elec;
8902 			bool inven_fire = (p_ptr->oppose_fire && p_ptr->resist_fire) || p_ptr->immune_fire;
8903 			bool inven_elec = (p_ptr->oppose_elec && p_ptr->resist_elec) || p_ptr->immune_elec;
8904 
8905 			if (p_ptr->immune_fire && p_ptr->immune_elec) dam = (dam + 8) / 9;
8906 			else {
8907 				if (p_ptr->immune_fire) dam = (dam + 3) / 4;
8908 				else if (p_ptr->resist_plasma) {
8909 					dam *= 3;
8910 					dam = (dam + 6) / (randint(6) + 6);
8911 				}
8912 				else if (p_ptr->resist_fire || p_ptr->oppose_fire) {
8913 					dam *= 3;
8914 					dam = (dam + 4) / 5;
8915 				} else if (p_ptr->suscep_fire) dam = (dam * 3) / 2;
8916 
8917 				if (p_ptr->resist_elec || p_ptr->oppose_elec || p_ptr->immune_elec)
8918 					dam = ((dam + 4) * 4) / 5;
8919 				else if (p_ptr->suscep_elec) dam = (dam * 4) / 3;
8920 			}
8921 
8922 
8923 			if (fuzzy) msg_format(Ind, "You are hit by something hot for \377%c%d \377wdamage!", damcol, dam);
8924 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8925 
8926 			take_hit(Ind, dam, killer, -who);
8927 
8928 			if (!p_ptr->resist_sound) {
8929 				int k = (randint((dam > 40) ? 35 : (dam * 3 / 4 + 5)));
8930 				(void)set_stun(Ind, p_ptr->stun + k);
8931 			}
8932 
8933 			/* Reduce stats */
8934 			if (!ignore_fire && !ignore_elec) {
8935 				if (randint(HURT_CHANCE) == 1) {
8936 					if (rand_int(3)) (void) do_dec_stat(Ind, A_STR, DAM_STAT_TYPE((dam < 30) ? 1 : (dam < 60) ? 2 : 3));
8937 					else (void) do_dec_stat(Ind, A_DEX, DAM_STAT_TYPE((dam < 30) ? 1 : (dam < 60) ? 2 : 3));
8938 				}
8939 			} else if (ignore_elec) {
8940 				if (randint(HURT_CHANCE) == 1)
8941 					(void) do_dec_stat(Ind, A_STR, DAM_STAT_TYPE((dam < 30) ? 1 : (dam < 60) ? 2 : 3));
8942 			} else if (ignore_fire) {
8943 				if (randint(HURT_CHANCE) == 1)
8944 					(void) do_dec_stat(Ind, A_DEX, DAM_STAT_TYPE((dam < 30) ? 1 : (dam < 60) ? 2 : 3));
8945 			}
8946 
8947 			/* Don't kill inventory in bloodbond... */
8948 			if (IS_PVP && check_blood_bond(Ind, -who)) break;
8949 
8950 			/* Inventory damage */
8951 			if (inven_fire && inven_elec) break;
8952 			if (!inven_fire && !inven_elec) {
8953 				if (rand_int(3)) inven_damage(Ind, set_fire_destroy, (dam < 30) ? 1 : (dam < 60) ? 2 : 3);
8954 				else inven_damage(Ind, set_elec_destroy, (dam < 30) ? 1 : (dam < 60) ? 2 : 3);
8955 			} else if (inven_elec) inven_damage(Ind, set_fire_destroy, (dam < 30) ? 1 : (dam < 60) ? 2 : 3);
8956 			else inven_damage(Ind, set_elec_destroy, (dam < 30) ? 1 : (dam < 60) ? 2 : 3);
8957 
8958 			break;
8959 		}
8960 
8961 		/* Nether -- drain experience */
8962 	case GF_NETHER_WEAK:
8963 		/* potion smash effect of a Potion of Death */
8964 		if (p_ptr->suscep_life || p_ptr->ghost) {
8965 			dam = 0;
8966 			if (who == PROJECTOR_TERRAIN) ;
8967 			else if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
8968 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8969 			break;
8970 		}
8971 	case GF_NETHER:
8972 		if (p_ptr->immune_neth) {
8973 			dam = 0;
8974 			if (who == PROJECTOR_TERRAIN) ;
8975 			else if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
8976 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8977 		} else if (p_ptr->resist_neth) {
8978 			dam *= 6; dam /= (randint(6) + 6);
8979 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
8980 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8981 			take_hit(Ind, dam, killer, -who); /* Prevent going down to level 1 and then taking full damage -> instakill */
8982 		} else {
8983 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
8984 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
8985 			take_hit(Ind, dam, killer, -who); /* Prevent going down to level 1 and then taking full damage -> instakill */
8986 
8987 			if (p_ptr->lev == 99 || (p_ptr->mode & MODE_PVP)) {
8988 				msg_print(Ind, "You are unaffected!");
8989 			} else if (p_ptr->hold_life && (rand_int(100) < 75)) {
8990 				msg_print(Ind, "You keep hold of your life force!");
8991 			} else if (p_ptr->hold_life) {
8992 				msg_print(Ind, "You feel your life slipping away!");
8993 				lose_exp(Ind, 200 + (p_ptr->exp/1000) * MON_DRAIN_LIFE);
8994 			} else {
8995 				msg_print(Ind, "You feel your life draining away!");
8996 				lose_exp(Ind, 200 + (p_ptr->exp/100) * MON_DRAIN_LIFE);
8997 			}
8998 		}
8999 		break;
9000 
9001 		/* Water -- stun/confuse */
9002 	case GF_WATER:
9003 	case GF_WAVE:
9004 		if (p_ptr->immune_water) {
9005 			dam = 0;
9006 			//doesn't make much sense--  if (who == PROJECTOR_TERRAIN) ; else
9007 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9008 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9009 			take_hit(Ind, dam, killer, -who);
9010 		} else {
9011 			if (p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC))
9012 			{
9013 				dam = (dam + 3) / 4;
9014 			}
9015 			else if (p_ptr->resist_water)
9016 			{
9017 				dam = (dam + 2) / 3;
9018 			}
9019 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9020 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9021 			if (TOOL_EQUIPPED(p_ptr) != SV_TOOL_TARPAULIN && magik(20 + dam / 20) &&
9022 				!(p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)))
9023 			{
9024 				if (!p_ptr->resist_water || magik(50)) {
9025 					/* Don't kill inventory in bloodbond... */
9026 					int breakable = 1;
9027 					if (IS_PVP) {
9028 						if (check_blood_bond(Ind, -who)) {
9029 							breakable = 0;
9030 						}
9031 					}
9032 					if (breakable) {
9033 						inven_damage(Ind, set_water_destroy, 1);
9034 						if (magik(50)) equip_damage(Ind, GF_WATER);
9035 					}
9036 				}
9037 			}
9038 			take_hit(Ind, dam, killer, -who);
9039 			if ((!p_ptr->resist_water) &&
9040 				!(p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)))
9041 			{
9042 					if (!p_ptr->resist_sound)
9043 				{
9044 					if (IS_PVP) {
9045 						(void)set_stun(Ind, p_ptr->stun + randint(10));
9046 					} else { /* pvm */
9047 						(void)set_stun(Ind, p_ptr->stun + randint(40));
9048 					}
9049 				}
9050 				if (!p_ptr->resist_conf &&
9051 				    !(p_ptr->mindboost && magik(p_ptr->mindboost_power)))
9052 				{
9053 					if (IS_PVP) {
9054 //						(void)set_confused(Ind, p_ptr->confused + randint(2));
9055 					} else { /* pvm */
9056 						(void)set_confused(Ind, p_ptr->confused + randint(5) + 5);
9057 					}
9058 				}
9059 			}
9060 		}
9061 		break;
9062 
9063 	case GF_VAPOUR:
9064 		if (p_ptr->immune_water) {
9065 			dam = 0;
9066 			//not really needed-- if (who == PROJECTOR_TERRAIN) ; else
9067 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9068 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9069 			take_hit(Ind, dam, killer, -who);
9070 		} else {
9071 			if (p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC))
9072 				dam = (dam + 3) / 4;
9073 			else if (p_ptr->resist_water)
9074 				dam = (dam + 2) / 3;
9075 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9076 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9077 
9078 			/* no item damage */
9079 
9080 			take_hit(Ind, dam, killer, -who);
9081 
9082 			/* no stun/conf */
9083 		}
9084 		break;
9085 
9086 		/* Stun */
9087 	case GF_STUN:
9088 		if (fuzzy) msg_print(Ind, "You are hit by something!");
9089 		if (!p_ptr->resist_sound)
9090 		{
9091 			(void)set_stun(Ind, p_ptr->stun + randint(40));
9092 		}
9093 		dam = 0;
9094 		break;
9095 
9096 		/* Chaos -- many effects */
9097 	case GF_CHAOS:
9098 		if (p_ptr->resist_chaos) {
9099 //			dam *= 6; dam /= (randint(7) + 8);
9100 			dam *= 6; dam /= (randint(6) + 6);
9101 		}
9102 		if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9103 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9104 
9105 		take_hit(Ind, dam, killer, -who); /* Prevent going down to level 1 and then taking full damage -> instakill */
9106 
9107 		if (!p_ptr->resist_conf)
9108 			(void)set_confused(Ind, p_ptr->confused + rand_int(20) + 10);
9109 		if (!p_ptr->resist_chaos && !(p_ptr->mode & MODE_PVP))
9110 			(void)set_image(Ind, p_ptr->image + randint(10));
9111 		if (!p_ptr->resist_neth && !p_ptr->resist_chaos) {
9112 			if (p_ptr->lev == 99 || (p_ptr->mode & MODE_PVP)) {
9113 				msg_print(Ind, "You are unaffected!");
9114 			} else if (p_ptr->hold_life && (rand_int(100) < 75)) {
9115 				msg_print(Ind, "You keep hold of your life force!");
9116 			} else if (p_ptr->hold_life) {
9117 				msg_print(Ind, "You feel your life slipping away!");
9118 				lose_exp(Ind, 500 + (p_ptr->exp/1000) * MON_DRAIN_LIFE);
9119 			} else {
9120 				msg_print(Ind, "You feel your life draining away!");
9121 				lose_exp(Ind, 5000 + (p_ptr->exp/100) * MON_DRAIN_LIFE);
9122 			}
9123 		}
9124 		break;
9125 
9126 		/* Shards -- mostly cutting */
9127 	case GF_SHARDS:
9128 		if (p_ptr->biofeedback) dam /= 2;
9129 		if (p_ptr->resist_shard)
9130 			dam *= 6; dam /= (randint(6) + 6);
9131 		if (fuzzy) msg_format(Ind, "You are hit by something sharp for \377%c%d \377wdamage!", damcol, dam);
9132 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9133 		take_hit(Ind, dam, killer, -who);
9134 		if ((!p_ptr->resist_shard) && (!p_ptr->no_cut))
9135 			(void)set_cut(Ind, p_ptr->cut + dam, -who);
9136 		break;
9137 
9138 		/* Sound -- mostly stunning */
9139 	case GF_SOUND:
9140 		/* Making the stun effect's power depend on body mass of the monster, giving gold dragons more respect again;
9141 		   or more dependant on the damage to better fit certain monstes - C. Blue
9142 		   body masses: 90k kavlax, 110k mature gold d, 170k mature d turtle / ancient d, 190k ancient d turtle / wyrms
9143 		   hp: 500 drakes + mature turtle, 620 mature gold d + ancient turtle, 700 ancient turtle, 1.3k kavlax, 1.5k ancient d, 5k wyrms */
9144 		if (p_ptr->biofeedback) dam /= 2;
9145 		if (p_ptr->resist_sound)
9146 		{
9147 			dam *= 5; dam /= (randint(6) + 6);
9148 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9149 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9150 		}
9151 		else
9152 		{
9153 			int k = (randint((dam > 90) ? 35 : (dam / 3 + 5)));
9154 			/* for medium dragons/turtles */
9155 			if (dam > 100 && p_ptr->stun < 35) k = 35;
9156 			/* for kavlax, ancient things, wyrms, and (unfortunately? dunno..) also aether vortex/hound */
9157 			if (dam > 200 && p_ptr->stun < 50) k = 50;
9158 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9159 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9160 			(void)set_stun(Ind, p_ptr->stun + k);
9161 		}
9162 		take_hit(Ind, dam, killer, -who);
9163 		break;
9164 
9165 		/* Pure confusion */
9166 	case GF_CONFUSION:
9167 		if (p_ptr->resist_conf || p_ptr->resist_chaos)
9168 		{
9169 			dam *= 5; dam /= (randint(6) + 6);
9170 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9171 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9172 		}
9173 		else
9174 		{
9175 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9176 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9177 			(void)set_confused(Ind, p_ptr->confused + randint(20) + 10);
9178 		}
9179 		take_hit(Ind, dam, killer, -who);
9180 		break;
9181 
9182 		/* Disenchantment -- see above */
9183 	case GF_DISENCHANT:
9184 		if (p_ptr->resist_disen)
9185 		{
9186 			dam *= 6; dam /= (randint(6) + 6);
9187 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9188 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9189 		}
9190 		else
9191 		{
9192 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9193 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9194 			(void)apply_disenchant(Ind, 0);
9195 		}
9196 		take_hit(Ind, dam, killer, -who);
9197 		break;
9198 
9199 		/* Nexus -- see above */
9200 	case GF_NEXUS:
9201 		if (p_ptr->resist_nexus)
9202 		{
9203 			dam *= 6; dam /= (randint(6) + 6);
9204 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9205 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9206 		}
9207 		else
9208 		{
9209 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9210 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9211 			apply_nexus(Ind, m_ptr, -who);
9212 		}
9213 		take_hit(Ind, dam, killer, -who);
9214 		break;
9215 
9216 		/* Force -- mostly stun */
9217 	case GF_FORCE:
9218 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9219 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9220 		if (!p_ptr->resist_sound)
9221 		{
9222 			(void)set_stun(Ind, p_ptr->stun + randint(20));
9223 		}
9224 		take_hit(Ind, dam, killer, -who);
9225 		break;
9226 
9227 		/* Inertia -- slowness */
9228 	case GF_INERTIA:
9229 		if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9230 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9231 		if (p_ptr->mindboost && magik(p_ptr->mindboost_power))
9232 		{ /* resist the effect */
9233 		} else if (!p_ptr->free_act) {
9234 			(void)set_slow(Ind, p_ptr->slow + rand_int(4) + 4);
9235 		} else {
9236 			(void)set_slow(Ind, p_ptr->slow + rand_int(3) + 2);
9237 		}
9238 		take_hit(Ind, dam, killer, -who);
9239 		break;
9240 
9241 		/* Lite -- blinding */
9242 	case GF_LITE:
9243 		if (p_ptr->suscep_lite) {
9244 			dam *= 2;
9245 		}
9246 		if (p_ptr->resist_lite) {
9247 			dam *= 4; dam /= (randint(6) + 6);
9248 		}
9249 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9250 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9251 		if (!p_ptr->resist_lite && !blind && !p_ptr->resist_blind) {
9252 			(void)set_blind(Ind, p_ptr->blind + randint(5) + 2);
9253 		}
9254 		take_hit(Ind, dam, killer, -who);
9255 		break;
9256 
9257 		/* Dark -- blinding */
9258 	case GF_DARK:
9259 		if (p_ptr->resist_dark) {
9260 			dam *= 4; dam /= (randint(6) + 6);
9261 		}
9262 		if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9263 		else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9264 		if (!p_ptr->resist_dark && !blind && !p_ptr->resist_blind) {
9265 			(void)set_blind(Ind, p_ptr->blind + randint(5) + 2);
9266 		}
9267 		take_hit(Ind, dam, killer, -who);
9268 		break;
9269 
9270 		/* Time -- bolt fewer effects XXX */
9271 	case GF_TIME:
9272 			if (p_ptr->resist_time) {
9273 				dam *= 6;
9274 				dam /= (randint(6) + 6);
9275 			}
9276 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9277 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9278 			take_hit(Ind, dam, killer, -who); /* Prevent going down to level 1 and then taking full damage -> instakill */
9279 
9280 			if ((p_ptr->mode & MODE_PVP)) break;
9281 			else if (p_ptr->resist_time) {
9282 				/* a little hack for high-elven runemasters: super low time damage has no drain effects */
9283 				if (flg & PROJECT_RNAF) break;
9284 
9285 				time_influence_choices = randint(9);
9286 			}
9287 			/* hack: very little time damage won't result in ruination */
9288 			else if (dam < 10) time_influence_choices = randint(9);
9289 			else time_influence_choices = randint(10);
9290 
9291 			switch (time_influence_choices) {
9292 			case 1: case 2: case 3: case 4: case 5:
9293 				if (p_ptr->resist_time) {
9294 					/* let's disable it for now to improve time resistance: */
9295 					if (magik(25)) {
9296 						if (p_ptr->lev == 99) msg_print(Ind, "You are unaffected!");
9297 						else {
9298 							msg_print(Ind, "You feel life has clocked back.");
9299 							lose_exp(Ind, (p_ptr->exp / 100) * MON_DRAIN_LIFE / 4);
9300 						}
9301 					} else {
9302 						msg_print(Ind, "You feel as if life has clocked back, but the feeling passes.");
9303 					}
9304 				} else {
9305 					if (p_ptr->lev == 99) msg_print(Ind, "You are unaffected.");
9306 					else {
9307 						msg_print(Ind, "You feel life has clocked back.");
9308 						lose_exp(Ind, 100 + (p_ptr->exp / 100) * MON_DRAIN_LIFE);
9309 					}
9310 				}
9311 				break;
9312 
9313 			case 6: case 7: case 8: case 9:
9314 				/* Sustenance slightly helps (50%) */
9315 				do_dec_stat_time(Ind, rand_int(6), STAT_DEC_NORMAL, 50, p_ptr->resist_time ? 1 : 2, TRUE);
9316 				break;
9317 
9318 			case 10:
9319 				msg_print(Ind, "You're not as powerful as you used to be...");
9320 				for (k = 0; k < 6; k++) {
9321 					/* Sustenance slightly helps (50%) */
9322 					do_dec_stat_time(Ind, rand_int(6), STAT_DEC_NORMAL, 50, p_ptr->resist_time ? 1 : 3, FALSE);
9323 				}
9324 				break;
9325 			}
9326 
9327 			break;
9328 
9329 		/* Gravity -- stun plus slowness plus teleport */
9330 	case GF_GRAVITY:
9331 			/* Feather fall (flying implies it, so flying is covered too) lets us resist gravity */
9332 			if (p_ptr->feather_fall) {
9333 				dam *= 6; dam /= (randint(6) + 6);
9334 			}
9335 			if (fuzzy) msg_format(Ind, "You are hit by something strange for \377%c%d \377wdamage!", damcol, dam);
9336 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9337 			msg_print(Ind, "Gravity warps around you.");
9338 			if (!p_ptr->martyr) teleport_player(Ind, 5, TRUE);
9339 			(void)set_slow(Ind, p_ptr->slow + rand_int(4) + 3);
9340 			if (!p_ptr->resist_sound) {
9341 				int k = (randint((dam > 90) ? 35 : (dam / 3 + 5)));
9342 				(void)set_stun(Ind, p_ptr->stun + k);
9343 			}
9344 			take_hit(Ind, dam, killer, -who);
9345 			break;
9346 
9347 		/* Pure damage */
9348 	case GF_MANA:
9349 			if (p_ptr->resist_mana) { dam *= 6; dam /= (randint(6) + 6); }
9350 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9351 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9352 			take_hit(Ind, dam, killer, -who);
9353 			break;
9354 
9355 		/* Pure damage */
9356 	case GF_METEOR:
9357 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9358 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9359 			take_hit(Ind, dam, killer, -who);
9360 			if (!p_ptr->resist_sound) (void)set_stun(Ind, p_ptr->stun + 25 + randint(15));
9361 			break;
9362 
9363 		/* Ice -- cold plus stun plus cuts */
9364 	case GF_ICE:
9365 			k = dam;
9366 			dam = (k * 3) / 5;/* 60% COLD damage, total cold damage is saved in 'dam' */
9367 			k = (k * 2) / 5;/* 40% SHARDS damage, total shard damage is saved in 'k' */
9368 			if (p_ptr->biofeedback) k = (k * 2) / 3;
9369 			if (p_ptr->resist_shard) k *= 6; k /= (randint(6) + 6);
9370 			dam = cold_dam(Ind, dam, killer, -who);
9371 			dam = dam + k;
9372 			if (fuzzy) msg_format(Ind, "You are hit by something sharp for \377%c%d \377wdamage!", damcol, dam);
9373 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9374 			take_hit(Ind, dam, killer, -who);
9375 			if ((!p_ptr->resist_shard) && (!p_ptr->no_cut))
9376 				(void)set_cut(Ind, p_ptr->cut + damroll(5, 8), -who);
9377 			if (!p_ptr->resist_sound)
9378 				(void)set_stun(Ind, p_ptr->stun + randint(15));
9379 			break;
9380 
9381 		/* Thunder -- elec plus sound plus light */
9382 	case GF_THUNDER:
9383 			k_elec = dam / 3; /* 33% ELEC damage, total elec damage is saved in 'k_elec' */
9384 			k_elec = elec_dam(Ind, k_elec, killer, -who);
9385 			k_sound = dam / 3; /* 33% SOUND damage, total sound damage is saved in 'k_sound' */
9386 			if (p_ptr->biofeedback) k_sound /= 2;
9387 			if (p_ptr->resist_sound)
9388 			{
9389 				k_sound *= 5;
9390 				k_sound /= (randint(6) + 6);
9391 			}
9392 			k_lite = dam / 3; /* 33% LIGHT damage, total light damage is saved in 'k_site' */
9393 			if (p_ptr->suscep_lite) {
9394 				k_lite *= 2;
9395 			}
9396 			if (p_ptr->resist_lite) {
9397 				k_lite *= 4; k_lite /= (randint(6) + 6);
9398 			}
9399 			dam = k_elec + k_sound + k_lite;
9400 			if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9401 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9402 			take_hit(Ind, dam, killer, -who);
9403 			if (!p_ptr->resist_sound)
9404 				(void)set_stun(Ind, p_ptr->stun + randint(15));
9405 			if (!p_ptr->resist_lite && !blind && !p_ptr->resist_blind)
9406 				(void)set_blind(Ind, p_ptr->blind + randint(5) + 2);
9407 			break;
9408 
9409 		/* Druid's early tox spell: 50% poison, 50% water. No side effects from the water attk */
9410 	case GF_WATERPOISON:
9411 			switch (randint(2)) {
9412 				case 1: { // Poison!
9413 					if (p_ptr->immune_poison) {
9414 						dam = 0;
9415 						//not really needed-- if (who == PROJECTOR_TERRAIN) ; else
9416 						if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
9417 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9418 					} else {
9419 						if (p_ptr->resist_pois) dam = (dam + 2) / 3;
9420 						if (p_ptr->oppose_pois) dam = (dam + 2) / 3;
9421 						if (p_ptr->suscep_pois) dam = (dam + 2) * 2;
9422 						if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
9423 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9424 						take_hit(Ind, dam, killer, -who);
9425 						if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
9426 						{
9427 							(void)set_poisoned(Ind, p_ptr->poisoned + rand_int(dam) + 10, -who);
9428 						}
9429 					}
9430 				}
9431 				default: { // Water
9432 					if (p_ptr->immune_water) {
9433 						dam = 0;
9434 						//not really needed-- if (who == PROJECTOR_TERRAIN) ; else
9435 						if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9436 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9437 					} else {
9438 						if (p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)) {
9439 							dam = (dam + 3) / 4;
9440 						} else if (p_ptr->resist_water) {
9441 							dam = (dam + 2) / 3;
9442 						}
9443 						if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9444 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9445 						if (TOOL_EQUIPPED(p_ptr) != SV_TOOL_TARPAULIN && magik(20 + dam / 20) &&
9446 							!(p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)))
9447 						{
9448 							if (!p_ptr->resist_water || magik(50)) {
9449 								/* Don't kill inventory in bloodbond... */
9450 								int breakable = 1;
9451 								if (IS_PVP) {
9452 									if (check_blood_bond(Ind, -who)) {
9453 										breakable = 0;
9454 									}
9455 								}
9456 								if (breakable) {
9457 									inven_damage(Ind, set_water_destroy, 1);
9458 									if (magik(50)) equip_damage(Ind, GF_WATER);
9459 								}
9460 							}
9461 						}
9462 					}
9463 					take_hit(Ind, dam, killer, -who);
9464 				}
9465 			}
9466 			break;
9467 
9468 		/* Druid's higher tox spell: 60%shards, 10%water, 10%poison. No side effects from water/shards. */
9469 	case GF_ICEPOISON:
9470 			switch (randint(5)) {
9471 				case 1:  // Shards
9472 				case 3:
9473 				case 5: {
9474 					if (p_ptr->biofeedback) dam /= 2;
9475 					if (p_ptr->resist_shard) {
9476 						dam *= 6; dam /= (randint(6) + 6);
9477 					}
9478 					if (fuzzy) msg_format(Ind, "You are hit by something sharp for \377%c%d \377wdamage!", damcol, dam);
9479 					else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9480 					take_hit(Ind, dam, killer, -who);
9481 					break;
9482 				}
9483 				case 2: { // Water
9484 					if (p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)) {
9485 						dam = (dam + 3) / 4;
9486 					}
9487 					if (p_ptr->immune_water) {
9488 						dam = 0;
9489 						//not really needed-- if (who == PROJECTOR_TERRAIN) ; else
9490 						if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9491 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9492 					} else {
9493 						if (p_ptr->resist_water) {
9494 							dam = (dam + 2) / 3;
9495 						}
9496 						if (fuzzy) msg_format(Ind, "You are hit by something for \377%c%d \377wdamage!", damcol, dam);
9497 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9498 						if (TOOL_EQUIPPED(p_ptr) != SV_TOOL_TARPAULIN && magik(20 + dam / 20) &&
9499 							!(p_ptr->body_monster && (r_ptr->flags7 & RF7_AQUATIC)))
9500 						{
9501 							if (!p_ptr->resist_water || magik(50)) {
9502 								/* Don't kill inventory in bloodbond... */
9503 								int breakable = 1;
9504 								if (IS_PVP) {
9505 									if (check_blood_bond(Ind, -who)) {
9506 										breakable = 0;
9507 									}
9508 								}
9509 								if (breakable) {
9510 									inven_damage(Ind, set_water_destroy, 1);
9511 									if (magik(25)) equip_damage(Ind, GF_WATER);
9512 								}
9513 							}
9514 						}
9515 						take_hit(Ind, dam, killer, -who);
9516 					}
9517 					break;
9518 				}
9519 				default: { // Poison
9520 					if (p_ptr->immune_poison) {
9521 						dam = 0;
9522 						//not really needed-- if (who == PROJECTOR_TERRAIN) ; else
9523 						if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
9524 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9525 					} else {
9526 						if (p_ptr->resist_pois) dam = (dam + 2) / 3;
9527 						if (p_ptr->oppose_pois) dam = (dam + 2) / 3;
9528 						if (p_ptr->suscep_pois) dam = (dam + 2) * 2;
9529 						if (fuzzy) msg_format(Ind, "You are hit by poison for \377%c%d \377wdamage!", damcol, dam);
9530 						else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9531 						take_hit(Ind, dam, killer, -who);
9532 						if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) {
9533 							(void)set_poisoned(Ind, p_ptr->poisoned + rand_int(dam) + 10, -who);
9534 						}
9535 					}
9536 					break;
9537 				}
9538 			}
9539 			break;
9540 
9541 	case GF_CURSE: {
9542 			int curse = randint(3);
9543 			if (curse == 1) { //Slow
9544 				if (fuzzy) msg_print(Ind, "Your body seems difficult to move!");
9545 				else msg_format(Ind, "%s curses at you, slowing your movements!", killer);
9546 				if (p_ptr->pspeed <= 100) {
9547 					/* unaffected */
9548 				} else if (p_ptr->mindboost && magik(p_ptr->mindboost_power)) {
9549 					/* resist the effect */
9550 				} else if (!p_ptr->free_act) {
9551 					(void)set_slow(Ind, p_ptr->slow + rand_int(3) + 4);
9552 				} else {
9553 					(void)set_slow(Ind, p_ptr->slow + rand_int(3) + 2);
9554 				}
9555 				dam = 0;
9556 			} else if (curse == 2) { //Conf
9557 				dam = damroll(3, (dam / 2)) + 1;
9558 				if (p_ptr->resist_conf || p_ptr->resist_chaos){
9559 					if (fuzzy) msg_format(Ind, "Your mind is hit by confusion for \377%c%d \377wdamage!", damcol, dam);
9560 					else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9561 					dam *= 5; dam /= (randint(6) + 6);
9562 				}else{
9563 					if (fuzzy) msg_format(Ind, "Your mind is hit by confusion for \377%c%d \377wdamage!", damcol, dam);
9564 					else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
9565 					if (!(p_ptr->mindboost && magik(p_ptr->mindboost_power)))
9566 						(void)set_confused(Ind, p_ptr->confused + randint(5) + 5);
9567 				}
9568 				take_hit(Ind, dam, killer, -who);
9569 			} else { //Blind
9570 				if (fuzzy) msg_print(Ind, "Your eyes suddenly burn!");
9571 				else msg_format(Ind, "%s casts a spell, burning your eyes!", killer);
9572 				if (!blind && !p_ptr->resist_blind) (void)set_blind(Ind, p_ptr->blind + randint(5) + 2);
9573 				dam = 0;
9574 			}
9575 			break;
9576 		}
9577 
9578 		/* Teleport other -- Teleports */
9579 	case GF_AWAY_ALL:
9580 		{
9581 			if (p_ptr->martyr) break;
9582 
9583 			if (IS_PVP) {
9584 				/* protect players in inns */
9585 				cave_type **zcave;
9586 				cave_type *c_ptr;
9587 				if ((zcave = getcave(wpos))) {
9588 					c_ptr = &zcave[p_ptr->py][p_ptr->px];
9589 					if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) break;
9590 				}
9591 
9592 				/* protect AFK players */
9593 				if (p_ptr->afk) break;
9594 
9595 				/* Log PvP teleports - mikaelh */
9596 				s_printf("%s teleported (GF_AWAY_ALL) %s at (%d,%d,%d).\n", Players[0 - who]->name, p_ptr->name,
9597 					p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
9598 
9599 				/* Tell the one who caused it */
9600 				msg_format(0 - who, "You teleport %s away.", Players[0 - who]->play_vis[Ind] ? p_ptr->name : "It");
9601 			}
9602 
9603 			if (fuzzy) msg_print(Ind, "Someone teleports you away!");
9604 			else msg_format(Ind, "%^s teleports you away!", killer);
9605 			teleport_player(Ind, 200, TRUE);
9606 			break;
9607 		}
9608 
9609 	case GF_WRAITH_PLAYER:
9610 		{
9611 			if (fuzzy) msg_print(Ind, "You feel less constant!");
9612 			else msg_format(Ind, "%^s turns you into a wraith!", killer);
9613 			set_tim_wraith(Ind, dam);
9614 			break;
9615 		}
9616 
9617 	case GF_BLESS_PLAYER:
9618 		{
9619 			if (dam < 18) p_ptr->blessed_power = 8;
9620 			else if (dam < 33) p_ptr->blessed_power = 14;
9621 			else p_ptr->blessed_power = 20;
9622 			(void)set_blessed(Ind, dam);
9623 			break;
9624 		}
9625 
9626 		/* a special family, actually cumulative.. hacky, yeah */
9627 	case GF_REMFEAR_PLAYER:		/* just fear */
9628 			set_afraid(Ind, 0);
9629 			/* Stay bold for some turns */
9630 			(void)set_res_fear(Ind, dam);
9631 			break;
9632 	case GF_REMCONF_PLAYER:		/* confusion, and ALSO fear */
9633 			set_afraid(Ind, 0);
9634 			/* Stay bold for some turns */
9635 			(void)set_res_fear(Ind, dam);
9636 
9637 			set_confused(Ind, 0);
9638 			break;
9639 	case GF_REMIMAGE_PLAYER:	/* hallu, and ALSO conf/fear */
9640 			set_afraid(Ind, 0);
9641 			/* Stay bold for some turns */
9642 			(void)set_res_fear(Ind, dam);
9643 
9644 			set_confused(Ind, 0);
9645 
9646 			set_image(Ind, 0);
9647 			break;
9648 
9649 	case GF_REMCURSE_PLAYER: /* only remove one curse */
9650 #ifdef NEW_REMOVE_CURSE
9651 		if (dam) remove_curse_aux(Ind, 0x1 + 0x2, -who);
9652 		else remove_curse_aux(Ind, 0x2, -who);
9653 #endif
9654 		break;
9655 
9656 	case GF_HPINCREASE_PLAYER:
9657 		{
9658 			(void)hp_player(Ind, dam);
9659 			break;
9660 		}
9661 
9662 	case GF_HERO_PLAYER:
9663 		{
9664 			(void)set_hero(Ind, dam); /* removed stacking */
9665 			break;
9666 		}
9667 
9668 	case GF_SHERO_PLAYER:
9669 		{
9670 			(void)set_shero(Ind, dam); /* removed stacking */
9671 			break;
9672 		}
9673 
9674 	case GF_SATHUNGER_PLAYER:
9675 		{
9676 		    if (!p_ptr->suscep_life) {
9677 			if (p_ptr->male)
9678 			msg_format_near(Ind, "\377y%s looks like he is going to explode.", p_ptr->name);
9679 			else
9680 			msg_format_near(Ind, "\377y%s looks like she is going to explode.", p_ptr->name);
9681 			(void)set_food(Ind, PY_FOOD_MAX - 1);
9682 		    }
9683 			break;
9684 		}
9685 
9686 	case GF_RESFIRE_PLAYER:
9687 		{
9688 			(void)set_oppose_fire(Ind, dam); /* removed stacking */
9689 			break;
9690 		}
9691 
9692 	case GF_RESELEC_PLAYER:
9693 		{
9694 			(void)set_oppose_elec(Ind, dam); /* removed stacking */
9695 			break;
9696 		}
9697 
9698 	case GF_RESPOIS_PLAYER:
9699 		{
9700 			(void)set_oppose_pois(Ind, dam); /* removed stacking */
9701 			break;
9702 		}
9703 
9704 	case GF_RESACID_PLAYER:
9705 		{
9706 			(void)set_oppose_acid(Ind, dam); /* removed stacking */
9707 			break;
9708 		}
9709 
9710 	case GF_RESCOLD_PLAYER:
9711 		{
9712 			(void)set_oppose_cold(Ind, dam); /* removed stacking */
9713 			break;
9714 		}
9715 
9716 	case GF_CUREPOISON_PLAYER:
9717 		{
9718 			(void)set_poisoned(Ind, 0, 0);
9719 			break;
9720 		}
9721 
9722 	case GF_SLOWPOISON_PLAYER:
9723 			if (p_ptr->poisoned && !p_ptr->slow_poison) p_ptr->slow_poison = 1;
9724 			break;
9725 
9726 	case GF_SEEINVIS_PLAYER:
9727 		{
9728 			(void)set_tim_invis(Ind, dam); /* removed stacking */
9729 			break;
9730 		}
9731 
9732 	case GF_ZEAL_PLAYER:
9733 		{
9734 			(void)set_zeal(Ind, dam, 9 + randint(5));
9735 			break;
9736 		}
9737 	case GF_SEEMAP_PLAYER:
9738 		{
9739 			map_area(Ind);
9740 			break;
9741 		}
9742 	case GF_DETECTCREATURE_PLAYER:
9743 		{
9744  			(void)detect_creatures(Ind);
9745 			break;
9746 		}
9747 
9748 	case GF_CURESTUN_PLAYER:
9749 		{
9750 			(void)set_stun(Ind, p_ptr->stun - dam);
9751 			break;
9752 		}
9753 
9754 	case GF_DETECTDOOR_PLAYER:
9755 		{
9756 			(void)detect_sdoor(Ind, DEFAULT_RADIUS);
9757 			break;
9758 		}
9759 
9760 	case GF_DETECTTRAP_PLAYER:
9761 		{
9762 			(void)detect_trap(Ind, DEFAULT_RADIUS);
9763 			break;
9764 		}
9765 
9766 	case GF_CURECUT_PLAYER:
9767 		{
9768 			(void)set_cut(Ind, p_ptr->cut - dam, -who);
9769 			break;
9770 		}
9771 
9772 	case GF_TELEPORTLVL_PLAYER:
9773 		{
9774 			if (p_ptr->martyr) break;
9775 			teleport_player_level(Ind, FALSE);
9776 			break;
9777 		}
9778 
9779 	case GF_HEAL_PLAYER:
9780 		{
9781 			/* hacks */
9782 			if (hack_dam & 0x2000) /* CCW */
9783 				(void)set_stun(Ind, 0);
9784 			if (hack_dam & 0x1000) /* CSW */
9785 				(void)set_confused(Ind, 0);
9786 			if (hack_dam & 0x800) { /* CLW */
9787 				(void)set_blind(Ind, 0);
9788 				(void)set_cut(Ind, 0, 0);
9789 			}
9790 			if (hack_dam & 0x400) { /* holy curing PBAoE */
9791 				if (Ind != -who) dam = (dam * 3) / 2; /* heals allies for 3/4 of the self-heal amount */
9792 			}
9793 
9794 #if 0 /* causes a prob with 'Cure Wounds' spell - targetting cannot determine if to skip vampires or not -_- */
9795 			if (p_ptr->ghost || (r_ptr->flags3 & RF3_UNDEAD) || p_ptr->suscep_life) {
9796 				if (rand_int(100) < p_ptr->skill_sav)
9797 					msg_print(Ind, "You shudder, but you resist the effect!");
9798 				else {
9799 					/* Message */
9800 					msg_print(Ind, "You somehow feel.. cleaned!");
9801 					dam /= 3; /* full dam is too harsh */
9802 
9803 					/* Don't let the player get killed by it - mikaelh */
9804 					if (p_ptr->chp <= dam) dam = p_ptr->chp - 1;
9805 					take_hit(Ind, dam, killer, -who);
9806 				}
9807 			} else
9808 #endif
9809 			{
9810 				//(spammy) msg_format_near(Ind, "\377g%s has been healed for %d hit points!.", p_ptr->name, dam);
9811 				if (IS_PLAYER(-who) /* paranoia? */
9812 				     && -who != Ind) { /* don't notify ourselves about healing ourselves */
9813 					msg_format(-who, "\377w%s has been healed for \377g%d\377w hit points.", p_ptr->name, dam);
9814 					msg_format(Ind, "\377g%s heals you for %d hit points", Players[-who]->name, dam);
9815 				} else msg_format(Ind, "\377gYou are healed for %d hit points", dam);
9816 
9817 				hp_player_quiet(Ind, dam, FALSE);
9818 				dam = 0;
9819 			}
9820 			break;
9821 		}
9822 
9823 		/* The druid spell; Note that it _damages_ undead-players instead of healing :-) - the_sandman */
9824 	case GF_HEALINGCLOUD:
9825 		{
9826 			if (p_ptr->ghost || (r_ptr->flags3 & RF3_UNDEAD) || p_ptr->suscep_life) {
9827 				if (rand_int(100) < p_ptr->skill_sav)
9828 					msg_print(Ind, "You shudder, but you resist the effect!");
9829 				else {
9830 					/* Message */
9831 					msg_print(Ind, "You somehow feel.. cleaned!");
9832 					dam /= 3; /* full dam is too harsh */
9833 
9834 					/* Don't let the player get killed by it - mikaelh */
9835 					if (p_ptr->chp <= dam) dam = p_ptr->chp - 1;
9836 					take_hit(Ind, dam, killer, -who);
9837 				}
9838 			} else {
9839 				/* Healed */
9840 				msg_format(Ind, "\377gYou are healed for %d points.", dam);
9841 				//(spammy) msg_format_near(Ind, "\377g%s has been healed for %d hit points.", p_ptr->name, dam);
9842 
9843 				hp_player_quiet(Ind, dam, FALSE);
9844 				dam = 0;
9845 			}
9846 			break;
9847 		}
9848 
9849 	case GF_SPEED_PLAYER:
9850 		{
9851 			if (dam > 10) dam = 10; /* cap speed bonus for others */
9852 			if (dam > p_ptr->lev / 3) dam = p_ptr->lev / 3; /* works less well for low level targets */
9853 			if (dam < 1) dam = 1;
9854 
9855 			if (fuzzy) msg_print(Ind, "You feel faster!");
9856 			else msg_format(Ind, "%^s speeds you up!", killer);
9857 			(void)set_fast(Ind, 10 + (dam * 5), dam); /* removed stacking */
9858 			break;
9859 		}
9860 
9861 	case GF_EXTRA_STATS:
9862 		{
9863 			do_xtra_stats(Ind, 10 + (dam * 5), (int)(dam/10));
9864 			break;
9865 		}
9866 
9867 	case GF_EXTRA_SPR:
9868 		{
9869 			dam = dam - 30;
9870 			if (dam < 0) break;
9871 			do_focus_shot(Ind, 200 + dam * 5, (dam/6));
9872 			break;
9873 		}
9874 
9875 	case GF_SHIELD_PLAYER:
9876 		{
9877 			if (dam > 10) dam = 10; /* cap AC bonus for others - Kurzel */
9878 			if (fuzzy) msg_print(Ind, "You feel protected!");
9879 			else msg_format(Ind, "%^s shields you!", killer);
9880 
9881 			(void)set_shield(Ind, 10 + (dam * 5), dam, SHIELD_NONE, 0, 0); /* removed stacking */
9882 			break;
9883 		}
9884 
9885 	case GF_TELEPORT_PLAYER:
9886 		{
9887 			if (p_ptr->martyr) break;
9888 
9889 			if (IS_PVP) {
9890 				/* protect players in inns */
9891 				cave_type **zcave;
9892 				cave_type *c_ptr;
9893 				if ((zcave = getcave(wpos))) {
9894 					c_ptr = &zcave[p_ptr->py][p_ptr->px];
9895 					if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) break;
9896 				}
9897 
9898 				/* protect AFK players */
9899 				if (p_ptr->afk) break;
9900 
9901 				/* Log PvP teleports - mikaelh */
9902 				s_printf("%s teleported (GF_TELEPORT_PLAYER) %s at (%d,%d,%d).\n", Players[0 - who]->name, p_ptr->name,
9903 					p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
9904 
9905 				/* Tell the one who caused it */
9906 				msg_format(0 - who, "You teleport %s away.", Players[0 - who]->play_vis[Ind] ? p_ptr->name : "It");
9907 			}
9908 
9909 			if (fuzzy) msg_print(Ind, "Someone teleports you away!");
9910 			else msg_format(Ind, "%^s teleports you away!", killer);
9911 
9912 			teleport_player(Ind, dam, TRUE);
9913 			break;
9914 		}
9915 
9916 	case GF_RECALL_PLAYER:
9917 			dam = 0;
9918 			if (p_ptr->afk) break;
9919 
9920 			/* prevent silly things */
9921 			if (in_irondeepdive(&p_ptr->wpos) && !irondeepdive_bottom(&p_ptr->wpos)) {
9922 				msg_print(Ind, "\377oThere is some static discharge in the air around you, but nothing happens.");
9923 				break;
9924 			}
9925 
9926 			if (!p_ptr->word_recall) {
9927 #ifdef SEPARATE_RECALL_DEPTHS
9928 				p_ptr->recall_pos.wz = get_recall_depth(&p_ptr->wpos, p_ptr);
9929 #else
9930 				p_ptr->recall_pos.wz = p_ptr->max_dlv;
9931 #endif
9932 				p_ptr->word_recall = dam;
9933 				if (fuzzy) msg_print(Ind, "\377oThe air around you suddenly becomes charged!");
9934 				else msg_format(Ind, "\377o%^s charges the air around you!", killer);
9935 			} else {
9936 				p_ptr->word_recall = 0;
9937 				if (fuzzy) msg_print(Ind, "\377oA tension leaves the air around you!");
9938 				else msg_format(Ind, "\377o%^s dispels the tension from the air around you!", killer);
9939 			}
9940 			p_ptr->redraw |= (PR_DEPTH);
9941 			break;
9942 
9943 	case GF_RESTORE_PLAYER:
9944 			if (dam & 0x1) { /* Restore food */
9945 				set_food(Ind, PY_FOOD_MAX - 1);
9946 			}
9947 			if (dam & 0x2) { /* Restore exp */
9948 				(void)restore_level(Ind);
9949 			}
9950 			if (dam & 0x4) { /* Restore stats */
9951 				(void)do_res_stat(Ind, A_STR);
9952 				(void)do_res_stat(Ind, A_CON);
9953 				(void)do_res_stat(Ind, A_DEX);
9954 				(void)do_res_stat(Ind, A_WIS);
9955 				(void)do_res_stat(Ind, A_INT);
9956 				(void)do_res_stat(Ind, A_CHR);
9957 			}
9958 			if (dam & 0x8) { /* Black breath (herbal tea) */
9959 				if (p_ptr->black_breath) {
9960 					msg_print(Ind, "The hold of the Black Breath on you is broken!");
9961 					p_ptr->black_breath = FALSE;
9962 				}
9963 			}
9964 			break;
9965 	case GF_CURING:
9966 	case GF_CURE_PLAYER:
9967 			if (dam & 0x1) { /* Slow Poison */
9968 				if (p_ptr->poisoned && !p_ptr->slow_poison) p_ptr->slow_poison = 1;
9969 			}
9970 			if (dam & 0x2) { /* Ungorge */
9971 				if (p_ptr->food >= PY_FOOD_MAX) set_food(Ind, PY_FOOD_MAX - 1);
9972 			}
9973 			if (dam & 0x4) { /* Neutralise Poison */
9974 				(void)set_poisoned(Ind, 0, 0);
9975 			}
9976 			if (dam & 0x8) { /* Close cuts */
9977 				(void)set_cut(Ind, 0, 0);
9978 			}
9979 			if (dam & 0x10) { /* Remove conf/blind/stun */
9980 				(void)set_confused(Ind, 0);
9981 				(void)set_blind(Ind, 0);
9982 				(void)set_stun(Ind, 0);
9983 			}
9984 			if (dam & 0x20) { /* Remove hallu */
9985 				set_image(Ind, 0);
9986 			}
9987 			if (dam & 0x40) { /* Restore stats */
9988 				(void)do_res_stat(Ind, A_STR);
9989 				(void)do_res_stat(Ind, A_CON);
9990 				(void)do_res_stat(Ind, A_DEX);
9991 				(void)do_res_stat(Ind, A_WIS);
9992 				(void)do_res_stat(Ind, A_INT);
9993 				(void)do_res_stat(Ind, A_CHR);
9994 			}
9995 			if (dam & 0x80) { /* Restore exp */
9996 				(void)restore_level(Ind);
9997 			}
9998 			break;
9999 	case GF_RESURRECT_PLAYER:
10000 			//if (p_ptr->ghost)
10001 				resurrect_player(Ind, dam);
10002 			break;
10003 	case GF_SANITY_PLAYER:
10004 			msg_format(Ind, "%s waves over your eyes, murmuring some words..", killer);
10005 			set_afraid(Ind, 0);
10006 			/* Stay bold for some turns */
10007 			(void)set_res_fear(Ind, dam);
10008 			(void)set_confused(Ind, 0);
10009 			(void)set_image(Ind, 0);
10010 
10011 			if (dam > 0) {
10012 #if 1
10013 				/* Testing new version that increases sanity - mikaelh */
10014 				p_ptr->csane += dam;
10015 				if (p_ptr->csane > p_ptr->msane) p_ptr->csane = p_ptr->msane;
10016 				p_ptr->update |= PU_SANITY;
10017 				p_ptr->redraw |= PR_SANITY;
10018 				p_ptr->window |= (PW_PLAYER);
10019 #else
10020 				if (p_ptr->csane < p_ptr->msane * dam / 12) {
10021 					p_ptr->csane = p_ptr->msane * dam / 12;
10022 					/* the_sandman mika's addition, really */
10023 					if (p_ptr->csane>p_ptr->msane) p_ptr->csane = p_ptr->msane;
10024 							p_ptr->update |= PU_SANITY;
10025 							p_ptr->redraw |= PR_SANITY;
10026 							p_ptr->window |= (PW_PLAYER);
10027 				}
10028 #endif
10029 				/* Give feedback to the healer so he knows when he may stop - C. Blue */
10030 				if (p_ptr->csane == p_ptr->msane) msg_format_near(Ind, "%s appears to be in full command of %s mental faculties.", p_ptr->name, p_ptr->male ? "his" : "her");
10031 			}
10032 			break;
10033 	case GF_SOULCURE_PLAYER:
10034 			/* priest variant hurts undead, druid tea is fine */
10035 			if (p_ptr->suscep_life) {
10036 				msg_print(Ind, "You feel a calming warmth touching your soul.");
10037 				take_hit(Ind, (p_ptr->chp / 3) * 2, killer, -who);
10038 			}
10039 			if (p_ptr->black_breath) {
10040 				msg_print(Ind, "The hold of the Black Breath on you is broken!");
10041 				p_ptr->black_breath = FALSE;
10042 			}
10043 			break;
10044 	case GF_MINDBOOST_PLAYER:
10045 		{
10046 			if (dam > 95) dam = 95;
10047 			set_mindboost(Ind, dam, 15 + randint(6));
10048 			break;
10049 		}
10050 
10051 	case GF_OLD_CONF:
10052 
10053 		if (fuzzy || self) msg_print(Ind, "You hear puzzling noises!");
10054 		else msg_format(Ind, "%^s creates a mesmerising illusion!", killer);
10055 
10056 		if (p_ptr->resist_conf ||
10057 		    (p_ptr->mindboost && magik(p_ptr->mindboost_power)))
10058 		{
10059 			msg_print(Ind, "You disbelieve the feeble spell.");
10060 		}
10061 		else if (rand_int(100 + dam*6) < p_ptr->skill_sav)
10062 		{
10063 			msg_print(Ind, "You disbelieve the feeble spell.");
10064 		}
10065 		//else set_confused(Ind, p_ptr->confused + dam); too much for pvp
10066 		else set_confused(Ind, p_ptr->confused + 2 + rand_int(3));
10067 
10068 		dam = 0;
10069 		break;
10070 
10071 	case GF_OLD_SLOW:
10072 
10073 		if (fuzzy || self) msg_print(Ind, "Something drains power from your muscles!");
10074 		else msg_format(Ind, "%^s drains power from your muscles!", killer);
10075 
10076 		if (p_ptr->free_act)
10077 		{
10078 			msg_print(Ind, "You are unaffected!");
10079 		}
10080 		else if (rand_int(100 + dam*6) < p_ptr->skill_sav ||
10081 		    (p_ptr->mindboost && magik(p_ptr->mindboost_power)))
10082 		{
10083 			msg_print(Ind, "You resist the effects!");
10084 		}
10085 		//else set_slow(Ind, p_ptr->slow + dam); too much for pvp..
10086 		else set_slow(Ind, p_ptr->slow + 2 + rand_int(3));
10087 
10088 		dam = 0;
10089 		break;
10090 
10091 	case GF_TURN_ALL:
10092 
10093 		if (fuzzy || self) msg_print(Ind, "Something mumbles, and you hear scary noises!");
10094 		else msg_format(Ind, "%^s casts a fearful illusion!", killer);
10095 
10096 		if (p_ptr->resist_fear)
10097 		{
10098 			msg_print(Ind, "You refuse to be frightened.");
10099 		}
10100 		else if (rand_int(100 + dam*6) < p_ptr->skill_sav)
10101 		{
10102 			msg_print(Ind, "You refuse to be frightened.");
10103 		}
10104 		else
10105 		{
10106 			//(void)set_afraid(Ind, p_ptr->afraid + dam);  too much for pvp
10107 			(void)set_afraid(Ind, p_ptr->afraid + 2 + rand_int(3));
10108 		}
10109 
10110 		dam = 0;
10111 		break;
10112 
10113 	case GF_OLD_POLY:
10114 			s_printf("PLAYER_POLY: %s -> %s ", Players[0 - who]->name, p_ptr->name);
10115 			if (p_ptr->afk) break;
10116 			if (fuzzy || self) msg_print(Ind, "You feel bizzare!");
10117 			else msg_format(Ind, "%^s polymorphs you!", killer);
10118 			if (p_ptr->resist_nexus) {
10119 				s_printf("resists\n");
10120 				msg_print(Ind, "You resist the effects!");
10121 			} else {
10122 				s_printf("morphs\n");
10123 				msg_print(Ind, "The magic continuum twists around you!");
10124 				apply_morph(Ind, dam, killer, -who);
10125 			}
10126 			break;
10127 
10128 		/* PernA ones */
10129 		/* Rocket -- stun, cut, fire, raw impact */
10130 	case GF_INFERNO:
10131 	case GF_DETONATION:
10132 	case GF_ROCKET:
10133 		{
10134 			bool ignore_heat = (p_ptr->resist_fire && p_ptr->oppose_fire) || p_ptr->immune_fire;
10135 			if (p_ptr->resist_shard)
10136 				dam = (dam * 5) / 6;
10137 			if (p_ptr->resist_sound)
10138 				dam = (dam * 5) / 6;
10139 			if (p_ptr->immune_fire)
10140 				dam = (dam * 3) / 4;
10141 			else if (p_ptr->resist_fire || p_ptr->oppose_fire)
10142 				dam = (dam * 4) / 5;
10143 
10144 			if (fuzzy) msg_format(Ind, "There is an explosion around you of \377%c%d \377wdamage!", damcol, dam);
10145 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
10146 
10147 			if (!p_ptr->resist_shard && !p_ptr->no_cut)
10148 				(void)set_cut(Ind, p_ptr->cut + ( dam / 2), -who );
10149 			if (!p_ptr->resist_sound)
10150 				(void)set_stun(Ind, p_ptr->stun + randint(20));
10151 
10152 			if (!p_ptr->resist_shard || !p_ptr->resist_sound || !ignore_heat) {
10153 				/* Don't kill inventory in bloodbond... */
10154 				int breakable = 1;
10155 				if (IS_PVP) {
10156 					if (check_blood_bond(Ind, -who)) {
10157 						breakable = 0;
10158 					}
10159 				}
10160 				if (breakable) {
10161 					if (p_ptr->resist_shard && p_ptr->resist_sound) inven_damage(Ind, set_fire_destroy, 3);
10162 					else if (ignore_heat) inven_damage(Ind, set_impact_destroy, 3);
10163 					else inven_damage(Ind, set_rocket_destroy, 4);
10164 				}
10165 			}
10166 
10167 			take_hit(Ind, dam, killer, -who);
10168 			break;
10169 		}
10170 
10171 		/* Standard damage -- also poisons / mutates player */
10172 	case GF_NUKE:
10173 		{
10174 			if (p_ptr->immune_poison) {
10175 				dam = 0;
10176 				if (who == PROJECTOR_TERRAIN) ; else /* RL-Doom? ;) */
10177 				if (fuzzy) msg_format(Ind, "You are hit by radiation for \377%c%d \377wdamage!", damcol, dam);
10178 				else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
10179 			} else {
10180 				if (p_ptr->resist_pois) dam = (2 * dam + 2) / 5;
10181 				if (p_ptr->oppose_pois) dam = (2 * dam + 2) / 5;
10182 				if (p_ptr->suscep_pois) dam = (5 * dam + 2) / 3;
10183 				if (fuzzy) msg_format(Ind, "You are hit by radiation for \377%c%d \377wdamage!", damcol, dam);
10184 				else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
10185 				take_hit(Ind, dam, killer, -who);
10186 				if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
10187 				{
10188 					set_poisoned(Ind, p_ptr->poisoned + rand_int(dam) + 10, -who);
10189 
10190 #if 0	// dang, later..
10191 					if (randint(5) == 1) { /* 6 */
10192 						msg_print("You undergo a freakish metamorphosis!");
10193 						if (randint(4)==1) /* 4 */
10194 							do_poly_self();
10195 						else
10196 							corrupt_player();
10197 					}
10198 #endif	// 0
10199 
10200 					if (randint(6) == 1) {
10201 						/* Don't kill inventory in bloodbond... */
10202 						int breakable = 1;
10203 						if (IS_PVP) {
10204 							if (check_blood_bond(Ind, -who))
10205 								breakable = 0;
10206 						}
10207 						if (breakable) inven_damage(Ind, set_acid_destroy, 2);
10208 					}
10209 				}
10210 			}
10211 			break;
10212 		}
10213 
10214 		/* Standard damage */
10215 	case GF_DISINTEGRATE:
10216 		{
10217 			if (p_ptr->body_monster && (r_ptr->flags3 & RF3_HURT_ROCK)) dam = (dam * 3) / 2;
10218 			if (fuzzy) msg_format(Ind, "You are hit by pure energy for \377%c%d \377wdamage!", damcol, dam);
10219 			else msg_format(Ind, "%s \377%c%d \377wdamage!", attacker, damcol, dam);
10220 			take_hit(Ind, dam, killer, -who);
10221 			break;
10222 		}
10223 
10224 		/* GF_BLIND - C. Blue */
10225 	case GF_BLIND:
10226 		{
10227 			if (p_ptr->resist_blind)
10228 			{
10229 				msg_print(Ind, "You are unaffected!");
10230 			}
10231 			else if (rand_int(100 + dam*6) < p_ptr->skill_sav)
10232 			{
10233 				msg_print(Ind, "You resist the effects!");
10234 			}
10235 			else if (!p_ptr->blind)
10236 			{
10237 				(void)set_blind(Ind, dam);
10238 			}
10239 			break;
10240 		}
10241 
10242 		/* For shattering potions, but maybe work for wands too? */
10243 	case GF_OLD_HEAL:
10244 		{
10245 			if (fuzzy) msg_print(Ind, "You are hit by something invigorating!");
10246 			(void)hp_player(Ind, dam);
10247 			dam = 0;
10248 			break;
10249 		}
10250 
10251 	case GF_OLD_SPEED:
10252 		{
10253 			if (fuzzy) msg_print(Ind, "You are hit by something!");
10254 			(void)set_fast(Ind, p_ptr->fast + randint(5), 10); /* not removed stacking */
10255 			dam = 0;
10256 			break;
10257 		}
10258 
10259 	case GF_TELE_TO:
10260 		{
10261 //			bool resists_tele = FALSE;
10262 //			dun_level		*l_ptr = getfloor(wpos);
10263                         int chance = (195 - p_ptr->skill_sav) / 2;
10264                         if (p_ptr->res_tele) chance = 50;
10265 
10266 			if (p_ptr->martyr) break;
10267 
10268 			if (IS_PVP) {
10269 				/* protect players in inns */
10270 				cave_type **zcave;
10271 				cave_type *c_ptr;
10272 				if ((zcave = getcave(wpos))) {
10273 					c_ptr = &zcave[p_ptr->py][p_ptr->px];
10274 					if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) break;
10275 				}
10276 
10277 				/* protect AFK players */
10278 				if (p_ptr->afk) break;
10279 
10280 				/* Log PvP teleports - mikaelh */
10281 				s_printf("%s teleported (GF_TELE_TO) %s at (%d,%d,%d).\n", Players[0 - who]->name, p_ptr->name,
10282 					p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
10283 
10284 				/* Tell the one who caused it */
10285 				msg_format(0 - who, "You command %s to return.", Players[0 - who]->play_vis[Ind] ? p_ptr->name : "It");
10286 			}
10287 
10288 			/* Teleport to nowhere..? */
10289 			if (who >= 0 || who <= PROJECTOR_UNUSUAL) break;
10290 
10291 			if (p_ptr->anti_tele)
10292 			{
10293 				msg_print(Ind, "You are unaffected!");
10294 			}
10295 			else if (magik(chance))
10296 			{
10297 				msg_print(Ind, "You resist the effect!");
10298 			}
10299 			else
10300 			{
10301 				player_type *q_ptr = Players[0 - who];
10302 
10303 				msg_format(Ind, "%^s commands you to return.", q_ptr->name);
10304 
10305 				/* Prepare to teleport */
10306 				teleport_player_to(Ind, q_ptr->py, q_ptr->px);
10307 
10308 			}
10309 
10310 			/* No "real" damage */
10311 			dam = 0;
10312 			break;
10313 		}
10314 
10315 		/* Hand of Doom */
10316 	case GF_HAND_DOOM:
10317 		{
10318 			/* Teleport to nowhere..? */
10319 			if (who >= 0 || who <= PROJECTOR_UNUSUAL) break;
10320 
10321 			msg_format(Ind, "%^s invokes the Hand of Doom!",
10322 					Players[0 - who]->name);
10323 
10324 			if (rand_int(100) < p_ptr->skill_sav)
10325 			{
10326 				msg_print(Ind, "You resist the effects!");
10327 			}
10328 			else
10329 			{
10330 				int dummy = (((s32b) ((65 + randint(25)) * (p_ptr->chp))) / 100);
10331 				if (p_ptr->chp - dummy < 1) dummy = p_ptr->chp - 1;
10332 				msg_print(Ind, "You feel your life fade away!");
10333 				bypass_invuln = TRUE;
10334 				take_hit(Ind, dummy, Players[0-who]->name, -who);
10335 				bypass_invuln = FALSE;
10336 				curse_equipment(Ind, 100, 20);
10337 			}
10338 			break;
10339 		}
10340 
10341 	case GF_AWAY_UNDEAD:
10342 		{
10343 			if (p_ptr->martyr) break;
10344 
10345 			if (IS_PVP) {
10346 				/* protect players in inns */
10347 				cave_type **zcave;
10348 				cave_type *c_ptr;
10349 				if ((zcave = getcave(wpos))) {
10350 					c_ptr = &zcave[p_ptr->py][p_ptr->px];
10351 					if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) break;
10352 				}
10353 
10354 				/* protect AFK players */
10355 				if (p_ptr->afk) break;
10356 
10357 				/* Log PvP teleports - mikaelh */
10358 				s_printf("%s teleported (GF_AWAY_UNDEAD) %s at (%d,%d,%d).\n", Players[0 - who]->name, p_ptr->name,
10359 					p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
10360 			}
10361 
10362 		    if (p_ptr->ghost || p_ptr->suscep_life) {
10363 
10364 			/* Only affect undead */
10365 			if (p_ptr->res_tele)
10366 			{
10367 				msg_print(Ind, "You are unaffected!");
10368 			}
10369 //			else if (p_ptr->lev+50 < randint(150))
10370 			else if (rand_int(100) < p_ptr->skill_sav)
10371 			{
10372 				teleport_player(Ind, dam, TRUE);
10373 			}
10374 			else
10375 			{
10376 				msg_print(Ind, "You resist the effect!");
10377 			}
10378 
10379 		    }
10380 
10381 			/* No "real" damage */
10382 			dam = 0;
10383 			break;
10384 		}
10385 
10386 		/* Teleport evil (Use "dam" as "power") */
10387 	case GF_AWAY_EVIL:
10388 		{
10389 			if (p_ptr->martyr) break;
10390 
10391 			if (IS_PVP) {
10392 				/* protect players in inns */
10393 				cave_type **zcave;
10394 				cave_type *c_ptr;
10395 				if ((zcave = getcave(wpos))) {
10396 					c_ptr = &zcave[p_ptr->py][p_ptr->px];
10397 					if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) break;
10398 				}
10399 
10400 				/* protect AFK players */
10401 				if (p_ptr->afk) break;
10402 
10403 				/* Log PvP teleports - mikaelh */
10404 				s_printf("%s teleported (GF_AWAY_EVIL) %s at (%d,%d,%d).\n", Players[0 - who]->name, p_ptr->name,
10405 					p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
10406 			}
10407 
10408 			if (p_ptr->suscep_good) {
10409 				/* Only affect evil */
10410 				if (p_ptr->res_tele)
10411 					msg_print(Ind, "You are unaffected!");
10412 //				else if (p_ptr->lev+50 < randint(150))
10413 				else if (rand_int(100) < p_ptr->skill_sav)
10414 					teleport_player(Ind, dam, TRUE);
10415 				else
10416 					msg_print(Ind, "You resist the effect!");
10417 			}
10418 			/* No "real" damage */
10419 			dam = 0;
10420 			break;
10421 		}
10422 #if 0	//already defined above for affecting ALL players!
10423 		/* Teleport monster (Use "dam" as "power") */
10424 	case GF_AWAY_ALL:
10425 		{
10426 			if (p_ptr->martyr) break;
10427 
10428 			if (p_ptr->body_monster) {
10429 				bool resists_tele = FALSE;
10430 				dun_level *l_ptr = getfloor(wpos);
10431 
10432 				if (p_ptr->res_tele)
10433 					msg_print(Ind, "You are unaffected!");
10434 //				else if (p_ptr->lev+50 < randint(150))
10435 				else if (rand_int(100) < p_ptr->skill_sav)
10436 					teleport_player(Ind, dam, TRUE);
10437 				else
10438 					msg_print(Ind, "You resist the effect!");
10439 			}
10440 
10441 			/* No "real" damage */
10442 			dam = 0;
10443 			break;
10444 		}
10445 #endif
10446 
10447 			/* Turn undead (Use "dam" as "power") */
10448 	case GF_TURN_UNDEAD:
10449 		{
10450 			if (p_ptr->body_monster){
10451 
10452 			/* Only affect undead */
10453 			if (p_ptr->ghost || (r_ptr->flags3 & RF3_UNDEAD))
10454 			{
10455 				if (p_ptr->resist_fear && !p_ptr->ghost)
10456 				{
10457 					msg_print(Ind, "You are unaffected!");
10458 				}
10459 				/* Attempt a saving throw */
10460 				//else if (RES_OLD(p_ptr->lev, dam))
10461 				else if (rand_int(100) < p_ptr->skill_sav)
10462 				{
10463 					msg_print(Ind, "You resist the effect!");
10464 				} else {
10465 					(void)set_afraid(Ind, p_ptr->afraid + damroll(3, (dam / 2)) + 1);
10466 				}
10467 			}
10468 
10469 			}
10470 			/* No "real" damage */
10471 			dam = 0;
10472 			break;
10473 		}
10474 
10475 
10476 			/* Turn evil (Use "dam" as "power") */
10477 	case GF_TURN_EVIL:
10478 		{
10479 			/* Only affect evil */
10480 			if (p_ptr->suscep_good) {
10481 				if (p_ptr->resist_fear)
10482 					msg_print(Ind, "You are unaffected!");
10483 				else if (rand_int(100) < p_ptr->skill_sav)
10484 //				else if (RES_OLD(p_ptr->lev, dam))
10485 				{
10486 					msg_print(Ind, "You resist the effect!");
10487 				} else {
10488 					(void)set_afraid(Ind, p_ptr->afraid + damroll(3, (dam / 2)) + 1);
10489 				}
10490 			}
10491 			/* No "real" damage */
10492 			dam = 0;
10493 			break;
10494 		}
10495 
10496 #if 0	//already defined above for affecting ALL players!
10497 		/* Turn monster (Use "dam" as "power") */
10498 	case GF_TURN_ALL:
10499 		{
10500 			if (p_ptr->body_monster){
10501 
10502 			/* Attempt a saving throw */
10503 			if ((p_ptr->resist_fear) ||
10504 			{
10505 				/* No obvious effect */
10506 				msg_print(Ind, "You are unaffected!");
10507 			}
10508 			else if (rand_int(100) < p_ptr->skill_sav)
10509 //			else if (RES_OLD(p_ptr->lev, dam))
10510 			{
10511 				msg_print(Ind, "You resist the effect!");
10512 			}
10513 			else
10514 			{
10515 				(void)set_afraid(Ind, p_ptr->afraid + damroll(3, (dam / 2)) + 1);
10516 			}
10517 			}
10518 			/* No "real" damage */
10519 			dam = 0;
10520 			break;
10521 		}
10522 #endif
10523 
10524 			/* Dispel undead */
10525 	case GF_DISP_UNDEAD:
10526 		{
10527 			if (p_ptr->body_monster){
10528 			/* Only affect undead */
10529 
10530 			if (p_ptr->ghost || (r_ptr->flags3 & RF3_UNDEAD))
10531 			{
10532 				if (rand_int(100) < p_ptr->skill_sav)
10533 				{
10534 					msg_print(Ind, "You shudder, but you resist the effect!");
10535 				}
10536 				else
10537 				{
10538 				/* Message */
10539 				msg_print(Ind, "You shudder!");
10540 				dam /= 3; /* full dam is too harsh */
10541 				take_hit(Ind, dam, killer, -who);
10542 				}
10543 			}
10544 
10545 			/* Ignore other monsters */
10546 			else
10547 			{
10548 				/* No damage */
10549 				dam = 0;
10550 			}
10551 			}
10552 			break;
10553 		}
10554 
10555 
10556 			/* Dispel evil */
10557 	case GF_DISP_EVIL:
10558 		{
10559 			/* Only affect evil */
10560 			if (p_ptr->suscep_good) {
10561 				if (rand_int(100) < p_ptr->skill_sav)
10562 					msg_print(Ind, "You shudder, but you resist the effect!");
10563 				else {
10564 					msg_print(Ind, "You shudder!");
10565 					dam /= 3; /* full dam is too harsh */
10566 					take_hit(Ind, dam, killer, -who);
10567 				}
10568 			}
10569 
10570 			/* Ignore other monsters */
10571 			else
10572 			{
10573 				/* No damage */
10574 				dam = 0;
10575 			}
10576 			break;
10577 		}
10578 
10579 	case GF_DISP_DEMON:
10580 		{
10581 			if (p_ptr->body_monster){
10582 			/* Only affect evil */
10583 			if (r_ptr->flags3 & RF3_DEMON)
10584 			{
10585 				if (rand_int(100) < p_ptr->skill_sav)
10586 				{
10587 					msg_print(Ind, "You shudder, but you resist the effect!");
10588 				}
10589 				else
10590 				{
10591 				/* Message */
10592 				msg_print(Ind, "You shudder!");
10593 				dam /= 3; /* full dam is too harsh */
10594 				take_hit(Ind, dam, killer, -who);
10595 				}
10596 			}
10597 
10598 			/* Ignore other monsters */
10599 			else
10600 			{
10601 				/* No damage */
10602 				dam = 0;
10603 			}
10604 			}
10605 			break;
10606 		}
10607 
10608 			/* Dispel monster */
10609 	case GF_DISP_ALL:
10610 	{
10611 #if 0 /* well, since Maiar use it, let's make it work on all players (for PvP/BB) */
10612 		if (p_ptr->body_monster) {
10613 			if (rand_int(100) < p_ptr->skill_sav)
10614 				msg_print(Ind, "You shudder, but you resist the effect!");
10615 			else {
10616 				/* Message */
10617 				msg_print(Ind, "You shudder!");
10618 				dam /= 4; /* full dam is too harsh */
10619 				take_hit(Ind, dam, killer, -who);
10620 			}
10621 		}
10622 #else
10623 		if (rand_int(100) < p_ptr->skill_sav)
10624 			msg_print(Ind, "You shudder, but you resist the effect!");
10625 		else {
10626 			/* Message */
10627 			msg_print(Ind, "You shudder!");
10628 			take_hit(Ind, dam, killer, -who);
10629 		}
10630 #endif
10631 		break;
10632 	}
10633 
10634 	/* Default */
10635 	default:
10636 
10637 		/* No damage */
10638 		dam = 0;
10639 
10640 		break;
10641 
10642 	}
10643 
10644 	/* Damage messages in pvp fights - mikaelh */
10645 	if (who < 0 && who > PROJECTOR_UNUSUAL && dam > 0)
10646 //	if (IS_PVP && dam > 0)
10647 	{
10648 		if (check_hostile(-who, Ind))
10649 			msg_format(-who, "%s is hit for \377y%d \377wdamage.", p_ptr->name, dam);
10650 	}
10651 
10652 	/* Player was hit - mikaelh */
10653 	p_ptr->got_hit = TRUE;
10654 
10655 #if 0 //redundant?
10656 	/* Skip non-connected players */
10657 	if (p_ptr->conn != NOT_CONNECTED && (dam || who != PROJECTOR_TERRAIN)) {
10658 		/* Disturb */
10659 		disturb(Ind, 1, 0);
10660 	}
10661 #endif
10662 
10663 	/* Return "Anything seen?" */
10664 	return (obvious);
10665 }
10666 
10667 
10668 
10669 
10670 
10671 
10672 
10673 
10674 
10675 /*
10676  * Find the char to use to draw a moving bolt
10677  * It is moving (or has moved) from (x,y) to (nx,ny).
10678  * If the distance is not "one", we (may) return "*".
10679  */
10680 static char bolt_char(int y, int x, int ny, int nx)
10681 {
10682 	if ((ny == y) && (nx == x)) return '*';
10683 	if (ny == y) return '-';
10684 	if (nx == x) return '|';
10685 	if ((ny-y) == (x-nx)) return '/';
10686 	if ((ny-y) == (nx-x)) return '\\';
10687 	return '*';
10688 }
10689 
10690 
10691 
10692 /*
10693  * Generic "beam"/"bolt"/"ball" projection routine.  -BEN-
10694  *
10695  * Input:
10696  *   who: Index of "source" monster (or "zero" if "player")
10697  *   rad: Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
10698  *   y,x: Target location (or location to travel "towards")
10699  *   dam: Base damage roll to apply to affected monsters (or player)
10700  *   typ: Type of damage to apply to monsters (and objects)
10701  *   flg: Extra bit flags (see PROJECT_xxxx in "defines.h")
10702   *
10703  * Return:
10704  *   TRUE if any "effects" of the projection were observed, else FALSE
10705  *
10706  * Allows a monster (or player) to project a beam/bolt/ball of a given kind
10707  * towards a given location (optionally passing over the heads of interposing
10708  * monsters), and have it do a given amount of damage to the monsters (and
10709  * optionally objects) within the given radius of the final location.
10710  *
10711  * A "bolt" travels from source to target and affects only the target grid.
10712  * A "beam" travels from source to target, affecting all grids passed through.
10713  * A "ball" travels from source to the target, exploding at the target, and
10714  *   affecting everything within the given radius of the target location.
10715  *
10716  * Traditionally, a "bolt" does not affect anything on the ground, and does
10717  * not pass over the heads of interposing monsters, much like a traditional
10718  * missile, and will "stop" abruptly at the "target" even if no monster is
10719  * positioned there, while a "ball", on the other hand, passes over the heads
10720  * of monsters between the source and target, and affects everything except
10721  * the source monster which lies within the final radius, while a "beam"
10722  * affects every monster between the source and target, except for the casting
10723  * monster (or player), and rarely affects things on the ground.
10724  *
10725  * Two special flags allow us to use this function in special ways, the
10726  * "PROJECT_HIDE" flag allows us to perform "invisible" projections, while
10727  * the "PROJECT_JUMP" flag allows us to affect a specific grid, without
10728  * actually projecting from the source monster (or player).
10729  *
10730  * The player will only get "experience" for monsters killed by himself
10731  * Unique monsters can only be destroyed by attacks from the player
10732  *
10733  * Only 256 grids can be affected per projection, limiting the effective
10734  * "radius" of standard ball attacks to nine units (diameter nineteen).
10735  *
10736  * One can project in a given "direction" by combining PROJECT_THRU with small
10737  * offsets to the initial location (see "line_spell()"), or by calculating
10738  * "virtual targets" far away from the player.
10739  *
10740  * One can also use PROJECT_THRU to send a beam/bolt along an angled path,
10741  * continuing until it actually hits somethings (useful for "stone to mud").
10742  *
10743  * Bolts and Beams explode INSIDE walls, so that they can destroy doors.
10744  *
10745  * Balls must explode BEFORE hitting walls, or they would affect monsters
10746  * on both sides of a wall.  Some bug reports indicate that this is still
10747  * happening in 2.7.8 for Windows, though it appears to be impossible.
10748  *
10749  * We "pre-calculate" the blast area only in part for efficiency.
10750  * More importantly, this lets us do "explosions" from the "inside" out.
10751  * This results in a more logical distribution of "blast" treasure.
10752  * It also produces a better (in my opinion) animation of the explosion.
10753  * It could be (but is not) used to have the treasure dropped by monsters
10754  * in the middle of the explosion fall "outwards", and then be damaged by
10755  * the blast as it spreads outwards towards the treasure drop location.
10756  *
10757  * Walls and doors are included in the blast area, so that they can be
10758  * "burned" or "melted" in later versions.
10759  *
10760  * This algorithm is intended to maximize simplicity, not necessarily
10761  * efficiency, since this function is not a bottleneck in the code.
10762  *
10763  * We apply the blast effect from ground zero outwards, in several passes,
10764  * first affecting features, then objects, then monsters, then the player.
10765  * This allows walls to be removed before checking the object or monster
10766  * in the wall, and protects objects which are dropped by monsters killed
10767  * in the blast, and allows the player to see all affects before he is
10768  * killed or teleported away.  The semantics of this method are open to
10769  * various interpretations, but they seem to work well in practice.
10770  *
10771  * We process the blast area from ground-zero outwards to allow for better
10772  * distribution of treasure dropped by monsters, and because it provides a
10773  * pleasing visual effect at low cost.
10774  *
10775  * Note that the damage done by "ball" explosions decreases with distance.
10776  * This decrease is rapid, grids at radius "dist" take "1/dist" damage.
10777  *
10778  * Notice the "napalm" effect of "beam" weapons.  First they "project" to
10779  * the target, and then the damage "flows" along this beam of destruction.
10780  * The damage at every grid is the same as at the "center" of a "ball"
10781  * explosion, since the "beam" grids are treated as if they ARE at the
10782  * center of a "ball" explosion.
10783  *
10784  * Currently, specifying "beam" plus "ball" means that locations which are
10785  * covered by the initial "beam", and also covered by the final "ball", except
10786  * for the final grid (the epicenter of the ball), will be "hit twice", once
10787  * by the initial beam, and once by the exploding ball.  For the grid right
10788  * next to the epicenter, this results in 150% damage being done.  The center
10789  * does not have this problem, for the same reason the final grid in a "beam"
10790  * plus "bolt" does not -- it is explicitly removed.  Simply removing "beam"
10791  * grids which are covered by the "ball" will NOT work, as then they will
10792  * receive LESS damage than they should.  Do not combine "beam" with "ball".
10793  *
10794  * The array "gy[],gx[]" with current size "grids" is used to hold the
10795  * collected locations of all grids in the "blast area" plus "beam path".
10796  *
10797  * Note the rather complex usage of the "gm[]" array.  First, gm[0] is always
10798  * zero.  Second, for N>1, gm[N] is always the index (in gy[],gx[]) of the
10799  * first blast grid (see above) with radius "N" from the blast center.  Note
10800  * that only the first gm[1] grids in the blast area thus take full damage.
10801  * Also, note that gm[rad+1] is always equal to "grids", which is the total
10802  * number of blast grids.
10803  *
10804  * Note that once the projection is complete, (y2,x2) holds the final location
10805  * of bolts/beams, and the "epicenter" of balls.
10806  *
10807  * Note also that "rad" specifies the "inclusive" radius of projection blast,
10808  * so that a "rad" of "one" actually covers 5 or 9 grids, depending on the
10809  * implementation of the "distance" function.  Also, a bolt can be properly
10810  * viewed as a "ball" with a "rad" of "zero".
10811  *
10812  * Note that if no "target" is reached before the beam/bolt/ball travels the
10813  * maximum distance allowed (MAX_RANGE), no "blast" will be induced.  This
10814  * may be relevant even for bolts, since they have a "1x1" mini-blast.
10815  *
10816  * Some people have requested an "auto-explode ball attacks at max range"
10817  * option, which should probably be handled by this function.  XXX XXX XXX
10818  *
10819  * Note that for consistency, we "pretend" that the bolt actually takes "time"
10820  * to move from point A to point B, even if the player cannot see part of the
10821  * projection path.  Note that in general, the player will *always* see part
10822  * of the path, since it either starts at the player or ends on the player.
10823  *
10824  * Hack -- we assume that every "projection" is "self-illuminating".
10825  */
10826 #if 0
10827 bool lua_project(int who, int rad, struct worldpos *wpos, int y, int x, int dam, int typ, int flg, char attacker[80])
10828 {
10829 	return(project(who, rad, wpos, y, x, dam, typ, flg, attacker));
10830 }
10831 #endif
10832 bool project(int who, int rad, struct worldpos *wpos_tmp, int y, int x, int dam, int typ, int flg, char *attacker)
10833 {
10834 	int	i, j, t;
10835 	int	 y1, x1, y2, x2;
10836 	int	/*y0, x0,*/ y9, x9;
10837 	int	dist, dist_hack = 0, true_dist = 0;
10838 	int	who_can_see[26], num_can_see = 0;
10839 	int	terrain_resistance = -1, terrain_damage = -1;
10840 	bool	old_tacit = suppress_message, suppress_explosion = FALSE;
10841 
10842 #ifdef OPTIMIZED_ANIMATIONS
10843 	int path_y[MAX_RANGE];
10844 	int path_x[MAX_RANGE];
10845 	int path_num = 0;
10846 #endif
10847 
10848 	struct worldpos wpos_fix, *wpos = &wpos_fix;
10849 	/* copy wpos in case it was a monster's wpos that gets erased from mon_take_hit() if monster dies */
10850 	wpos_fix = *wpos_tmp;
10851 
10852 	/* Affected location(s) */
10853 	cave_type *c_ptr, *c_ptr2;
10854 
10855 	/* Assume the player sees nothing */
10856 	bool notice = FALSE;
10857 
10858 	/* Assume the player has seen nothing */
10859 	/*bool visual = FALSE;*/
10860 
10861 	/* Assume the player has seen no blast grids */
10862 	bool drawn = FALSE;
10863 
10864 	/* Is the player blind? */
10865 	/* Blindness is currently ignored for this function */
10866 	/*bool blind;*/
10867 
10868 	/* Number of grids in the "blast area" (including the "beam" path) */
10869 	int grids = 0;
10870 
10871 	int effect = 0;
10872 
10873 	bool players_only = FALSE; /* spell affects players only */
10874 
10875 	/* Coordinates of the affected grids */
10876 //	byte gx[256], gy[256];
10877 //	byte gx[tdi[PREPARE_RADIUS]], gy[tdi[PREPARE_RADIUS]];
10878 	byte gx[512], gy[512];
10879 
10880 	/* Encoded "radius" info (see above) */
10881 //	byte gm[16];
10882 	byte gm[PREPARE_RADIUS];
10883 
10884 	/* for cave_proj(): allow it to travel onto certain terrain,
10885 	   but not really much further - C. Blue */
10886 	bool broke_on_terrain1 = FALSE, broke_on_terrain2 = FALSE;
10887 
10888 	dun_level *l_ptr;
10889 	cave_type **zcave;
10890 
10891 	if (!(zcave = getcave(wpos))) return(FALSE);
10892 	l_ptr = getfloor(wpos);
10893 
10894 	/* Spells which never affect monsters, read:
10895 	   Spells which we want to exclude from merely _waking monsters up_!
10896 	   Note: Bolt spells will still be 'stopped' when hitting a monster. */
10897 	if ((typ == GF_HEAL_PLAYER) || (typ == GF_WRAITH_PLAYER) ||
10898 	    (typ == GF_SPEED_PLAYER) || (typ == GF_SHIELD_PLAYER) ||
10899 	    (typ == GF_RECALL_PLAYER) || (typ == GF_BLESS_PLAYER) ||
10900 	    (typ == GF_REMFEAR_PLAYER) || (typ == GF_SATHUNGER_PLAYER) ||
10901 	    (typ == GF_REMCONF_PLAYER) || (typ == GF_REMIMAGE_PLAYER) ||
10902 	    (typ == GF_RESFIRE_PLAYER) || (typ == GF_RESCOLD_PLAYER) ||
10903 	    (typ == GF_CUREPOISON_PLAYER) || (typ == GF_SEEINVIS_PLAYER) ||
10904 	    (typ == GF_SEEMAP_PLAYER) || (typ == GF_CURECUT_PLAYER) ||
10905 	    (typ == GF_CURESTUN_PLAYER) || (typ == GF_DETECTCREATURE_PLAYER) ||
10906 	    (typ == GF_DETECTDOOR_PLAYER) || (typ == GF_DETECTTRAP_PLAYER) ||
10907 	    (typ == GF_TELEPORTLVL_PLAYER) || (typ == GF_RESPOIS_PLAYER) ||
10908 	    (typ == GF_RESELEC_PLAYER) || (typ == GF_RESACID_PLAYER) ||
10909 	    (typ == GF_HPINCREASE_PLAYER) || (typ == GF_HERO_PLAYER) ||
10910 	    (typ == GF_SHERO_PLAYER) || (typ == GF_TELEPORT_PLAYER) ||
10911 	    (typ == GF_ZEAL_PLAYER) || (typ == GF_MINDBOOST_PLAYER) ||
10912 	    (typ == GF_RESTORE_PLAYER) || (typ == GF_REMCURSE_PLAYER) ||
10913 	    (typ == GF_CURE_PLAYER) || (typ == GF_RESURRECT_PLAYER) ||
10914 	    (typ == GF_SANITY_PLAYER) || (typ == GF_SOULCURE_PLAYER) ||
10915 	    (typ == GF_IDENTIFY) || (typ == GF_SLOWPOISON_PLAYER))
10916 		players_only = TRUE;
10917 
10918 
10919 #ifdef PROJECTION_FLUSH_LIMIT
10920 	count_project++;
10921 #endif	// PROJECTION_FLUSH_LIMIT
10922 
10923 	/* Location of player */
10924 	/*y0 = py;
10925 	x0 = px;*/
10926 
10927 
10928 	/* Hack -- Jump to target */
10929 	if (flg & PROJECT_JUMP) {
10930 		x1 = x;
10931 		y1 = y;
10932 
10933 		/* Clear the flag (well, needed?) */
10934 //		flg &= ~(PROJECT_JUMP);
10935 	}
10936 
10937 	/* Hack -- Start at a player */
10938 	else if (who < 0 && who > PROJECTOR_UNUSUAL)
10939 //	else if (IS_PVP)
10940 	{
10941 		x1 = Players[0 - who]->px;
10942 		y1 = Players[0 - who]->py;
10943 	}
10944 
10945 	/* Start at a monster */
10946 	else if (who > 0) {
10947 		x1 = m_list[who].fx;
10948 		y1 = m_list[who].fy;
10949 	}
10950 #if 1
10951 	/* Oops */
10952 	else {
10953 		x1 = x;
10954 		y1 = y;
10955 	}
10956 #endif	/* 0 */
10957 
10958 	/* Default "destination" */
10959 	y2 = y; x2 = x;
10960 
10961 
10962 	/* Hack -- verify stuff */
10963 	if ((flg & PROJECT_THRU) && (x1 == x2) && (y1 == y2))
10964 		flg &= ~PROJECT_THRU;
10965 
10966 
10967 
10968 	/* Hack -- Assume there will be no blast (max radius 16) */
10969 //	for (dist = 0; dist < 16; dist++) gm[dist] = 0;
10970 	for (dist = 0; dist < PREPARE_RADIUS; dist++) gm[dist] = 0;
10971 
10972 
10973 	/* Hack -- Handle stuff */
10974 	/*handle_stuff();*/
10975 
10976 
10977 #ifdef DOUBLE_LOS_SAFETY
10978 	/* Use projectable..() check to pre-determine if the line of fire is ok
10979 	   and we may skip redundant checking that appears further below. */
10980 	bool ok_DLS;
10981 	if (IS_PVP) { /* ..but we're not a monster? */
10982  #ifndef PY_PROJ_WALL
10983 		ok_DLS = projectable(wpos, y1, x1, y2, x2, MAX_RANGE);
10984  #else
10985 		ok_DLS = projectable_wall(wpos, y1, x1, y2, x2, MAX_RANGE);
10986  #endif
10987 	} else { /* Catch indirect attack spells! Those are RF4_ROCKET and RF4_BR_DISI. */
10988 		/* Monsters always could target players in walls (even if the projection explodes _before_ the wall)
10989 		   so we only need to use projectable_wall() here. */
10990 		ok_DLS = projectable_wall(wpos, y1, x1, y2, x2, MAX_RANGE);
10991 	}
10992 	/* hack: catch non 'dir == 5' projections, aka manually directed */
10993 	if (x1 == x2 || y1 == y2 || ABS(x2 - x1) == ABS(y2 - y1)) ok_DLS = FALSE;
10994 #endif
10995 
10996 
10997 	/* Start at the source */
10998 	x = x9 = x1;
10999 	y = y9 = y1;
11000 	dist = 0;
11001 
11002 	/* Project until done */
11003 	while (TRUE) {
11004 		/* Gather beam grids */
11005 		if (flg & PROJECT_BEAM) {
11006 			if (project_time_effect & EFF_WALL) {
11007 				effect = new_effect(who, typ, dam, project_time, project_interval, wpos, y, x, 0, project_time_effect);
11008 				if (effect != -1) zcave[y][x].effect = effect;
11009 			}
11010 			gy[grids] = y;
11011 			gx[grids] = x;
11012 			grids++;
11013 #if DEBUG_LEVEL > 1
11014 			if(grids > 500) s_printf("grids %d\n", grids);
11015 #endif	/* DEBUG_LEVEL */
11016 		}
11017 
11018 		/* Check the grid */
11019 		c_ptr = &zcave[y][x];
11020 
11021 		/* XXX XXX Hack -- Display "beam" grids */
11022 		if (!(flg & PROJECT_HIDE) &&
11023 		    dist && (flg & PROJECT_BEAM))
11024 #ifdef PROJECTION_FLUSH_LIMIT
11025 			if (count_project < PROJECTION_FLUSH_LIMIT)
11026 #endif	// PROJECTION_FLUSH_LIMIT
11027 		{
11028 			/* Hack -- Visual effect -- "explode" the grids */
11029 			for (j = 1; j < NumPlayers + 1; j++) {
11030 				player_type *p_ptr = Players[j];
11031 				int dispx, dispy;
11032 				byte attr;
11033 
11034 				if (p_ptr->conn == NOT_CONNECTED)
11035 					continue;
11036 
11037 				if(!inarea(&p_ptr->wpos, wpos))
11038 					continue;
11039 
11040 				if (p_ptr->blind)
11041 					continue;
11042 
11043 				if (!panel_contains(y, x))
11044 					continue;
11045 
11046 				if (!player_has_los_bold(j, y, x))
11047 					continue;
11048 
11049 				dispx = x - p_ptr->panel_col_prt;
11050 				dispy = y - p_ptr->panel_row_prt;
11051 
11052 				attr = spell_color(typ);
11053 
11054 				p_ptr->scr_info[dispy][dispx].c = '*';
11055 				p_ptr->scr_info[dispy][dispx].a = attr;
11056 
11057 				Send_char(j, dispx, dispy, attr, '*');
11058 			}
11059 		}
11060 
11061 
11062 		/* Analyze whether the projection can overcome terrain in its way - C. Blue */
11063 		/* Check: Fire vs Trees */
11064 		if (allow_terraforming(wpos, FEAT_TREE)) {
11065 			switch (c_ptr->feat) {
11066 			case FEAT_TREE: terrain_resistance = 50; break;
11067 			case FEAT_IVY: terrain_resistance = 0; break;
11068 			case FEAT_BUSH: terrain_resistance = 20; break;
11069 			case FEAT_DEAD_TREE: terrain_resistance = 30; break;
11070 			default: terrain_resistance = -1; break;
11071 			}
11072 			switch (typ) {
11073 			case GF_FIRE: terrain_damage = 100; break;
11074 			case GF_METEOR: terrain_damage = 150; break;
11075 			case GF_PLASMA: terrain_damage = 120; break;
11076 			case GF_HELL_FIRE: terrain_damage = 130; break;
11077 			default: terrain_damage = -1; break;
11078 			}
11079 		}
11080 
11081 		/* Accordingly, stop the projection or have it go on unhindered */
11082 		if (terrain_damage >= 0 && terrain_resistance >= 0 &&
11083 		    magik(terrain_damage - terrain_resistance)) {
11084 			/* go on unhindered by terrain, destroy terrain even */
11085 		} else {
11086 			/* Never pass through walls */
11087 			if (flg & PROJECT_GRAV) { /* Running along the floor?.. */
11088 				if (dist && !cave_floor_bold(zcave, y, x)) break;
11089 #ifndef PROJ_MON_ON_WALL
11090 			} else if (IS_PVP) { /* ..or rather levitating through the air? */
11091 				if (dist && !cave_contact(zcave, y, x)
11092  #ifdef DOUBLE_LOS_SAFETY
11093 				    && !ok_DLS
11094  #endif
11095 				    ) break;
11096 #endif
11097 			} else { /* monsters can target certain non-los grid types directly */
11098 				if (dist) {
11099 #ifdef PROJ_ON_WALL
11100 					if (broke_on_terrain1) break;
11101 #else
11102  #ifdef DOUBLE_LOS_SAFETY
11103 					if ((!cave_proj(zcave, y, x) && !ok_DLS)
11104  #else
11105 					if (!cave_proj(zcave, y, x)
11106  #endif
11107 					    || broke_on_terrain1) break;
11108 #endif
11109 					else if (!cave_contact(zcave, y, x)
11110 #ifdef DOUBLE_LOS_SAFETY
11111 					    && !ok_DLS
11112 #endif
11113 					    ) {
11114 #ifndef PROJ_MON_ON_WALL
11115 						/* if there isn't a player on the grid, we can't target it */
11116 						if (zcave[y][x].m_idx >= 0) break;
11117 #else
11118 						/* if there isn't a player/monster on the grid, we can't target it */
11119 						if (zcave[y][x].m_idx == 0) break;
11120 #endif
11121 						/* can't travel any further for sure now */
11122 						broke_on_terrain1 = TRUE;
11123 					}
11124 				}
11125 			}
11126 		}
11127 
11128 
11129 		/* Check for arrival at "final target" (if desired) */
11130 		if (!(flg & PROJECT_THRU) && (x == x2) && (y == y2)) break;
11131 
11132 		/* If allowed, and we have moved at all, stop when we hit anybody */
11133 		/* -AD- Only stop if it isn't a party member */
11134 		if ((c_ptr->m_idx != 0) && dist && (flg & PROJECT_STOP)) {
11135 			if (who > 0) {
11136 				/* hit first player (ignore monster) */
11137 				if (c_ptr->m_idx < 0) break;
11138 			}
11139 			else if (who < 0) {
11140 				/* always hit monsters */
11141 				if (c_ptr->m_idx > 0) break;
11142 
11143 				/* Hostile players hit each other */
11144 				if (check_hostile(0 - who, 0 - c_ptr->m_idx)) break;
11145 
11146 				/* If player hits himself, he hits others too */
11147 				if (flg & PROJECT_PLAY) break;
11148 
11149 #if 0 /* covered by PROJECT_PLAY above now */
11150 				/* Always affect players (regardless of hostility/party state): */
11151 				if (typ == GF_OLD_POLY) break;
11152 #endif
11153 
11154 #if 0				/* neutral people hit each other ..NOT! - C. Blue FF$$$ */
11155 				if (!Players[0 - who]->party) break;
11156 
11157 				/* people not in the same party hit each other ..NOT! - C. Blue */
11158 				if (!player_in_party(Players[0 - who]->party, 0 - c_ptr->m_idx))
11159 #if FRIEND_FIRE_CHANCE
11160 					if (!magik(FRIEND_FIRE_CHANCE))
11161 #endif
11162 						break;
11163 #endif
11164 			}
11165 //			else break;	// Huh? always break? XXX XXX
11166 		}
11167 
11168 
11169 		/* Calculate the new location */
11170 		y9 = y;
11171 		x9 = x;
11172 		mmove2(&y9, &x9, y1, x1, y2, x2);
11173 #ifdef DOUBLE_LOS_SAFETY
11174 		/* After we reached our target we have no more need for double-los-safety */
11175 		if (y9 == y2 && x9 == x2) ok_DLS = FALSE;
11176 #endif
11177 
11178 
11179 		/* Keep track of the distance traveled */
11180 		dist++;
11181 
11182 		/* Distance stuff: The 'dist > MAX_RANGE' part is basically obsolete
11183 		   now that distance() is used to achieve 'true' distance. */
11184 
11185 		/* Distance to target too great?
11186 		   Use distance() to form a 'natural' circle shaped radius instead of a square shaped radius,
11187 		   monsters do this too */
11188 		if ((true_dist = distance(y1, x1, y9, x9)) > MAX_RANGE) break;
11189 
11190 		/* Nothing can travel furthur than the maximal distance */
11191 		if (dist > MAX_RANGE) break;
11192 
11193 		/* Hack -- Balls explode BEFORE reaching walls or doors */
11194 		if (flg & PROJECT_GRAV) { /* Running along the floor?.. */
11195 			if (!cave_floor_bold(zcave, y9, x9) && (rad > 0)) break;
11196 #ifndef PROJ_MON_ON_WALL
11197 		} else if (IS_PVP) { /* ..or rather levitating through the air? */
11198 			if (!cave_contact(zcave, y9, x9)
11199  #ifdef DOUBLE_LOS_SAFETY
11200 			    && !ok_DLS
11201  #endif
11202 			     && (rad > 0)) break;
11203 #endif
11204 		} else { /* monsters can target certain non-los grid types directly */
11205 			if (rad > 0) {
11206 #ifdef PROJ_ON_WALL
11207 				if (broke_on_terrain2) break;
11208 #else
11209  #ifdef DOUBLE_LOS_SAFETY
11210 				if ((!cave_proj(zcave, y9, x9) && !ok_DLS)
11211  #else
11212 				if (!cave_proj(zcave, y9, x9)
11213  #endif
11214 				    || broke_on_terrain2) break;
11215 #endif
11216 				else if (!cave_contact(zcave, y9, x9)
11217 #ifdef DOUBLE_LOS_SAFETY
11218 				    && !ok_DLS
11219 #endif
11220 				    ) {
11221 #ifndef PROJ_MON_ON_WALL
11222 					/* if there isn't a player on the grid, we can't target it */
11223 					if (zcave[y9][x9].m_idx >= 0) break;
11224 #else
11225 					/* if there isn't a player/monster on the grid, we can't target it */
11226 					if (zcave[y9][x9].m_idx == 0) break;
11227 #endif
11228 					/* can't travel any further for sure now */
11229 					broke_on_terrain2 = TRUE;
11230 				}
11231 			}
11232 		}
11233 
11234 
11235 		/* Only do visual effects (and delay) if requested */
11236 		if (!(flg & PROJECT_HIDE))
11237 #ifndef OPTIMIZED_ANIMATIONS
11238 			if (count_project < PROJECTION_FLUSH_LIMIT)
11239 #endif	// PROJECTION_FLUSH_LIMIT
11240 		{
11241 #ifdef PROJECTION_FLUSH_LIMIT
11242 			for (j = 1; j < NumPlayers + 1; j++) {
11243 				player_type *p_ptr = Players[j];
11244 				int dispy, dispx;
11245 				char ch;
11246 				byte attr;
11247 
11248 				if (p_ptr->conn == NOT_CONNECTED)
11249 					continue;
11250 
11251 				if (!inarea(&p_ptr->wpos, wpos))
11252 					continue;
11253 
11254 				if (p_ptr->blind)
11255 					continue;
11256 
11257 				if (!panel_contains(y9, x9))
11258 					continue;
11259 
11260 				if (!player_has_los_bold(j, y9, x9))
11261 					continue;
11262 
11263 				dispx = x9 - p_ptr->panel_col_prt;
11264 				dispy = y9 - p_ptr->panel_row_prt;
11265 
11266 				ch = bolt_char(y, x, y9, x9);
11267 				attr = spell_color(typ);
11268 
11269 				p_ptr->scr_info[dispy][dispx].c = ch;
11270 				p_ptr->scr_info[dispy][dispx].a = attr;
11271 
11272 				Send_char(j, dispx, dispy, attr, ch);
11273 
11274 				/* Hack -- Show bolt char */
11275 				if (dist % 2) Send_flush(j);
11276 			}
11277 #else /* OPTIMIZED_ANIMATIONS */
11278 			/* Save the path */
11279 			if (path_num < MAX_RANGE) {
11280 				path_y[path_num] = y9;
11281 				path_x[path_num] = x9;
11282 				path_num++;
11283 			}
11284 #endif /* OPTIMIZED_ANIMATIONS */
11285 		}
11286 
11287 		/* Clean up */
11288 		everyone_lite_spot(wpos, y9, x9);
11289 
11290 		/* Save the new location */
11291 		y = y9;
11292 		x = x9;
11293 	}
11294 
11295 	if (project_time_effect & EFF_WALL) {
11296 		flg &= ~(PROJECT_STAY);
11297 		project_time = 0;
11298 		project_interval = 0;
11299 		project_time_effect = 0;
11300 	}
11301 
11302 	/* Hack: Usually, elemental bolt spells will not hurt floor/item if they already hurt a monster/player.
11303 	         Some bolt spells (poly) don't need this flag, since they don't hurt items/floor at all. */
11304 	if ((flg & PROJECT_EVSG) && zcave[y][x].m_idx != 0)
11305                 flg &= ~(PROJECT_GRID | PROJECT_ITEM);
11306 
11307 	/* hack: FF1_BLOCK_CONTACT grids prevent explosions,
11308 	   since those would carry over on the other side if it's
11309 	   just a wall of thickness 1 and possibly hit monsters there. */
11310 	if (f_info[zcave[y9][x9].feat].flags1 & FF1_BLOCK_CONTACT) suppress_explosion = TRUE;
11311 
11312 #ifdef OPTIMIZED_ANIMATIONS
11313 	if (path_num) {
11314 		/* Pick a random spot along the path */
11315 		i = rand_int(path_num);
11316 		y9 = path_y[i];
11317 		x9 = path_x[i];
11318 
11319 		for (j = 1; j < NumPlayers + 1; j++) {
11320 			player_type *p_ptr = Players[j];
11321 			int dispy, dispx;
11322 			char ch;
11323 			byte attr;
11324 
11325 			if (p_ptr->conn == NOT_CONNECTED)
11326 				continue;
11327 
11328 			if (!inarea(&p_ptr->wpos, wpos))
11329 				continue;
11330 
11331 			if (p_ptr->blind)
11332 				continue;
11333 
11334 			if (!panel_contains(y9, x9))
11335 				continue;
11336 
11337 			if (!player_has_los_bold(j, y9, x9))
11338 				continue;
11339 
11340 			dispx = x9 - p_ptr->panel_col_prt;
11341 			dispy = y9 - p_ptr->panel_row_prt;
11342 
11343 			ch = bolt_char(y, x, y9, x9);
11344 			attr = spell_color(typ);
11345 
11346 			p_ptr->scr_info[dispy][dispx].c = ch;
11347 			p_ptr->scr_info[dispy][dispx].a = attr;
11348 
11349 			Send_char(j, dispx, dispy, attr, ch);
11350 
11351 			/* Flush once */
11352 			Send_flush(j);
11353 		}
11354 
11355 		/* Redraw later */
11356 		everyone_lite_later_spot(wpos, y9, x9);
11357 	}
11358 #endif /* OPTIMIZED_ANIMATIONS */
11359 
11360 	/* Save the "blast epicenter" */
11361 	y2 = y;
11362 	x2 = x;
11363 
11364 	/* Start the "explosion" */
11365 	gm[0] = 0;
11366 
11367 	/* Hack -- make sure beams get to "explode" */
11368 	gm[1] = grids;
11369 
11370 	/* Ported hack for reflection */
11371 	dist_hack = dist;
11372 
11373 	/* If we found a "target", explode there */
11374 	if (true_dist <= MAX_RANGE && !suppress_explosion) {
11375 		/* Mega-Hack -- remove the final "beam" grid */
11376 //		if ((flg & PROJECT_BEAM) && (grids > 0)) grids--;
11377 
11378 		dist = 0;
11379 
11380 		for (i = 0; i <= tdi[rad]; i++) {
11381 			/* Encode some more "radius" info */
11382 			if (i == tdi[dist]) {
11383 				gm[++dist] = grids;
11384 #if DEBUG_LEVEL > 2
11385 				s_printf("dist:%d  i:%d\n", dist, i);
11386 #endif
11387 				if (dist > rad) break;
11388 			}
11389 
11390 			y = y2 + tdy[i];
11391 			x = x2 + tdx[i];
11392 
11393 			/* Ignore "illegal" locations */
11394 			if (!in_bounds3(wpos, l_ptr, y, x)) continue;
11395 
11396 #ifdef NO_EXPLOSION_OUT_OF_MAX_RANGE
11397 			/* Don't create explosions that exceed MAX_RANGE from the caster */
11398 			if (distance(y, x, y1, x1) > MAX_RANGE) continue;
11399 #endif
11400 
11401 #if 1
11402 			if ((typ == GF_DISINTEGRATE) ||
11403 			    /* Reduce disintegration effect of rockets to radius 1 - C. Blue */
11404 			    ((typ == GF_ROCKET || typ == GF_DETONATION) && (ABS(y - y2) <= 1) && (ABS(x - x2) <= 1)) )
11405 			{
11406 				c_ptr2 = &zcave[y][x];
11407 				if (cave_valid_bold(zcave,y,x))
11408 //						&& (cave[y][x].feat < FEAT_PATTERN_START
11409 //						 || cave[y][x].feat > FEAT_PATTERN_XTRA2))
11410 				{
11411 					if (
11412 						//(c_ptr->feat != FEAT_WATER) &&
11413 						(c_ptr2->feat != FEAT_SHAL_WATER) &&
11414 						(c_ptr2->feat != FEAT_DEEP_WATER) &&
11415 						(c_ptr2->feat != FEAT_TAINTED_WATER) &&
11416 						(c_ptr2->feat != FEAT_DEEP_LAVA) &&
11417 						(c_ptr2->feat != FEAT_SHAL_LAVA) &&
11418 						//(c_ptr2->feat != FEAT_ASH) &&
11419 						(c_ptr2->feat != FEAT_MUD) &&
11420 						(c_ptr2->feat != FEAT_DIRT) &&
11421 						(c_ptr2->feat != FEAT_HOME_OPEN) &&
11422 						(c_ptr2->feat != FEAT_HOME))
11423 					{
11424 						if (allow_terraforming(wpos, FEAT_TREE)) {
11425 							if (randint(2) == 1)
11426 								cave_set_feat_live(wpos, y, x, FEAT_FLOOR);
11427 							else
11428 								cave_set_feat_live(wpos, y, x, FEAT_ASH);
11429 						}
11430 					}
11431 
11432 				/* Update some things -- similar to GF_KILL_WALL */
11433 //				p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS);
11434 				}
11435 			}
11436 #endif	/* 1 */
11437 			/* else */ /* HERE!!!!*/
11438 			/* Ball explosions are stopped by walls */
11439 			if (!los(wpos, y2, x2, y, x)) continue;
11440 
11441 			/* Save this grid */
11442 			gy[grids] = y;
11443 			gx[grids] = x;
11444 			grids++;
11445 			if(grids > 500) printf("grids %d\n", grids);
11446 		}
11447 
11448 #if 0
11449 		/* Determine the blast area, work from the inside out */
11450 		for (dist = 0; dist <= rad; dist++) {
11451 			/* Scan the maximal blast area of radius "dist" */
11452 			for (y = y2 - dist; y <= y2 + dist; y++) {
11453 				for (x = x2 - dist; x <= x2 + dist; x++) {
11454 					/* Ignore "illegal" locations */
11455 					if (!in_bounds2(wpos, y, x)) continue;
11456 
11457 					/* Enforce a "circular" explosion */
11458 					if (distance(y2, x2, y, x) != dist) continue;
11459 
11460  #if 0
11461 					if (typ == GF_DISINTEGRATE) {
11462 						if (cave_valid_bold(y,x) &&
11463 						    (cave[y][x].feat < FEAT_PATTERN_START
11464 						    || cave[y][x].feat > FEAT_PATTERN_XTRA2))
11465 							cave_set_feat_live(y, x, FEAT_FLOOR);
11466 
11467 						/* Update some things -- similar to GF_KILL_WALL */
11468 						p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS);
11469 					}
11470  #endif	/* 0 */
11471 					/* else */ /* HERE!!!!*/
11472 					/* Ball explosions are stopped by walls */
11473 					if (!los(wpos, y2, x2, y, x)) continue;
11474 
11475 					/* Save this grid */
11476 					gy[grids] = y;
11477 					gx[grids] = x;
11478 					grids++;
11479 					if(grids>500) printf("grids %d\n", grids);
11480 				}
11481 			}
11482 
11483 			/* Encode some more "radius" info */
11484 			gm[dist+1] = grids;
11485 		}
11486 #endif	// 0
11487 	}
11488 
11489 	/* Speed -- ignore "non-explosions" */
11490 	if (!grids) return (FALSE);
11491 
11492 #ifndef OPTIMIZED_ANIMATIONS
11493 	/* Display the "blast area" */
11494 	if (!(flg & PROJECT_HIDE))
11495 #ifdef PROJECTION_FLUSH_LIMIT
11496 		if (count_project < PROJECTION_FLUSH_LIMIT)
11497 #endif	// PROJECTION_FLUSH_LIMIT
11498 	{
11499 		/* Then do the "blast", from inside out */
11500 		for (t = 0; t <= rad; t++) {
11501 			/* Reset who can see */
11502 			num_can_see = 0;
11503 
11504 			/* Dump everything with this radius */
11505 			for (i = gm[t]; i < gm[t+1]; i++) {
11506 				/* Extract the location */
11507 				y = gy[i];
11508 				x = gx[i];
11509 
11510 				for (j = 1; j < NumPlayers + 1; j++) {
11511 					player_type *p_ptr = Players[j];
11512 					int dispy, dispx;
11513 					byte attr;
11514 					int k;
11515 					bool flag = TRUE;
11516 
11517 					if (p_ptr->conn == NOT_CONNECTED)
11518 						continue;
11519 
11520 					if (!inarea(&p_ptr->wpos, wpos))
11521 						continue;
11522 
11523 					if (p_ptr->blind)
11524 						continue;
11525 
11526 					if (!panel_contains(y, x))
11527 						continue;
11528 
11529 					if (!player_has_los_bold(j, y, x))
11530 						continue;
11531 
11532 					attr = spell_color(typ);
11533 
11534 					dispx = x - p_ptr->panel_col_prt;
11535 					dispy = y - p_ptr->panel_row_prt;
11536 
11537 					p_ptr->scr_info[dispy][dispx].c = '*';
11538 					p_ptr->scr_info[dispy][dispx].a = attr;
11539 
11540 					Send_char(j, dispx, dispy, attr, '*');
11541 
11542 					drawn = TRUE;
11543 
11544 					for (k = 0; k < num_can_see; k++) {
11545 						if (who_can_see[k] == j)
11546 							flag = FALSE;
11547 					}
11548 
11549 					if (flag) who_can_see[num_can_see++] = j;
11550 				}
11551 			}
11552 
11553 			/* Flush each "radius" seperately */
11554 			for (j = 0; j < num_can_see; j++) {
11555 				/* Show this radius and delay */
11556 				Send_flush(who_can_see[j]);
11557 			}
11558 		}
11559 
11560 		/* Flush the erasing */
11561 		if (drawn) {
11562 			/* Erase the explosion drawn above */
11563 			for (i = 0; i < grids; i++) {
11564 				/* Extract the location */
11565 				y = gy[i];
11566 				x = gx[i];
11567 
11568 				/* Erase if needed */
11569 				everyone_lite_spot(wpos, y, x);
11570 			}
11571 
11572 			/* Flush the explosion */
11573 			for (j = 0; j < num_can_see; j++) {
11574 				/* Show this radius and delay */
11575 				Send_flush(who_can_see[j]);
11576 			}
11577 		}
11578 	}
11579 #endif
11580 
11581 
11582 	/* Check features */
11583 	if (flg & PROJECT_GRID) {
11584 		/* Start with "dist" of zero */
11585 		dist = 0;
11586 
11587 		/* Effect ? */
11588 		if (flg & PROJECT_STAY) {
11589 			/* I believe it's not right */
11590 //			effect = new_effect(typ, dam, project_time, py, px, rad, project_time_effect);
11591 			/* MEGAHACK -- quick hack to make fire_wall work
11592 			 * this should be rewritten!	- Jir -
11593 			 *
11594 			 * It registers the 'wall' as if it was a ball:
11595 			 *
11596 			 *	   |--dist_hack--|
11597 			 * (y,x) *------+------* (y2,x2)
11598 			 *			  +pseudo 'centre'
11599 			 */
11600 			if (rad == 0) {
11601 #if 1 /* Kurzel's patch commented this out - but this is required for fireworks! */
11602 				effect = new_effect(who, typ, dam, project_time, project_interval, wpos,
11603 				    (y + y2) / 2, (x + x2) / 2, dist_hack / 2 + 1,
11604 				    project_time_effect);
11605 #endif
11606 #ifdef ARCADE_SERVER
11607 #if 0
11608                                                 if (project_time_effect & EFF_CROSSHAIR_A || project_time_effect & EFF_CROSSHAIR_B ||
11609                                         	    project_time_effect & EFF_CROSSHAIR_C) {
11610 	                                                msg_broadcast(0, "making an effect");
11611     	        	                                player_type *pfft_ptr = Players[project_interval];
11612         	                                        pfft_ptr->e = effect;
11613                                                 }
11614 #endif
11615 #endif
11616 			} else {
11617 				effect = new_effect(who, typ, dam, project_time, project_interval, wpos,
11618 						y2, x2, rad, project_time_effect);
11619 			}
11620 			project_interval = 0;
11621 			project_time = 0;
11622 			project_time_effect = 0;
11623 		}
11624 
11625 		/* Now hurt the cave grids (and objects) from the inside out */
11626 		for (i = 0; i < grids; i++) {
11627 			/* Hack -- Notice new "dist" values */
11628 			if (gm[dist+1] == i) dist++;
11629 
11630 			/* Get the grid location */
11631 			y = gy[i];
11632 			x = gx[i];
11633 
11634 			if(!in_bounds(y,x)) continue;
11635 			/* Affect the feature */
11636 			if ((flg & PROJECT_STAY) || (flg & PROJECT_FULL)) dist = 0;
11637 			if (project_f(0 - who, who, dist, wpos, y, x, dam, typ)) notice = TRUE;
11638 
11639 			/* Effect ? */
11640 			if (flg & PROJECT_STAY) {
11641 				if (effect != -1) /* check that we're not out of effects - mikaelh */
11642 				{
11643 					zcave[y][x].effect = effect;
11644 					everyone_lite_spot(wpos, y, x);
11645 				}
11646 			}
11647 		}
11648 	}
11649 
11650 	/* PROJECT_DUMY means we don't have to project on floor/items/monsters/players,
11651 	   because the effect was just for visual entertainment.. - C. Blue */
11652 	if (flg & PROJECT_DUMY) return(FALSE);
11653 
11654 	/* Check objects */
11655 	if (flg & PROJECT_ITEM) {
11656 		/* Start with "dist" of zero */
11657 		dist = 0;
11658 
11659 		/* Now hurt the cave grids (and objects) from the inside out */
11660 		for (i = 0; i < grids; i++) {
11661 			/* Hack -- Notice new "dist" values */
11662 			if (gm[dist+1] == i) dist++;
11663 
11664 			/* Get the grid location */
11665 			y = gy[i];
11666 			x = gx[i];
11667 
11668 			if(!in_bounds(y,x)) continue;
11669 			/* Affect the object */
11670 			if ((flg & PROJECT_STAY) || (flg & PROJECT_FULL)) dist = 0;
11671 			if (project_i(0 - who, who, dist, wpos, y, x, dam, typ)) notice = TRUE;
11672 		}
11673 	}
11674 
11675 
11676 	/* Check monsters */
11677 	/* eww, hope traps won't kill the server here..	- Jir - */
11678 	if ((flg & PROJECT_KILL) && !players_only) {
11679 		/* Start with "dist" of zero */
11680 		dist = 0;
11681 
11682 		/* Mega-Hack */
11683 		project_m_n = 0;
11684 		project_m_x = 0;
11685 		project_m_y = 0;
11686 
11687 		if (who < 0 && who > PROJECTOR_UNUSUAL &&
11688 //		if (IS_PVP &&
11689 		    Players[0 - who]->taciturn_messages)
11690 			suppress_message = TRUE;
11691 
11692 		/* Now hurt the monsters, from inside out */
11693 		for (i = 0; i < grids; i++) {
11694 			/* Hack -- Notice new "dist" values */
11695 			if (gm[dist+1] == i) dist++;
11696 
11697 			/* Get the grid location */
11698 			y = gy[i];
11699 			x = gx[i];
11700 
11701 			/* paranoia */
11702 			if (!in_bounds2(wpos, y, x)) continue;
11703 
11704 #ifndef PROJ_MON_ON_WALL
11705 			/* Walls protect monsters */
11706 //			if (!cave_floor_bold(zcave, y, x)) continue;
11707 			/* Monsters can be hit on dark pits */
11708 			if (!cave_contact(zcave, y, x)) continue;
11709 #else
11710 			/* Walls only protect monsters if it's not the very epicenter of the blast. */
11711 			if (!cave_contact(zcave, y, x) && y != y2 && x != x2) continue;
11712 #endif
11713 
11714 			/* Affect the monster */
11715 //			if (project_m(0-who, who, y2, x2, dist, wpos, y, x, dam, typ)) notice = TRUE;
11716 
11717 			if (zcave[y][x].m_idx <= 0) continue;
11718 
11719 //			if (grids <= 1 && (zcave[y][x].m_idx > 0))
11720 /*			if (grids <= 1)
11721 			{
11722 				monster_type *m_ptr = &m_list[zcave[y][x].m_idx];
11723 				monster_race *ref_ptr = race_inf(m_ptr);
11724 				monster_race *ref_ptr = race_inf(&m_list[zcave[y][x].m_idx]);
11725 			}
11726 */
11727 			if ((flg & PROJECT_STAY) || (flg & PROJECT_FULL)) dist = 0;
11728 			if (project_m(0 - who, who, y2, x2, dist, wpos, y, x, dam, typ, flg)) notice = TRUE;
11729 		}
11730 
11731 		/* Mega-Hack */
11732 		if ((who < 0) && (project_m_n == 1) && (who > PROJECTOR_UNUSUAL))
11733 //		if (IS_PVP && project_m_n == 1)
11734 		{
11735 			/* Location */
11736 			x = project_m_x;
11737 			y = project_m_y;
11738 
11739 			/* Still here */
11740 			if (who < 0) {
11741 				player_type *p_ptr = Players[0 - who];
11742 				int m_idx = zcave[y][x].m_idx;
11743 
11744 				/* Hack - auto-track monster */
11745 				if (m_idx > 0) {
11746 					if (p_ptr->mon_vis[m_idx]) health_track(0 - who, m_idx);
11747 				} else {
11748 					if (p_ptr->play_vis[0 - m_idx]) health_track(0 - who, m_idx);
11749 				}
11750 			}
11751 		}
11752 
11753 		suppress_message = old_tacit;
11754 	}
11755 
11756 	/* Check player */
11757 	if (flg & PROJECT_KILL) {
11758 		/* Start with "dist" of zero */
11759 		dist = 0;
11760 
11761 		/* Clear the got_hit flags - mikaelh */
11762 		for (i = 1; i <= NumPlayers; i++) {
11763 			player_type *p_ptr = Players[i];
11764 
11765 			if (p_ptr->conn == NOT_CONNECTED)
11766 				continue;
11767 
11768 			p_ptr->got_hit = FALSE;
11769 		}
11770 
11771 		/* Now see if the player gets hurt */
11772 		for (i = 0; i < grids; i++) {
11773 			/* Who is at the location */
11774 			int player_idx;
11775 
11776 			/* Hack -- Notice new "dist" values */
11777 			if (gm[dist+1] == i) dist++;
11778 
11779 			/* Get the grid location */
11780 			y = gy[i];
11781 			x = gx[i];
11782 
11783 			/* Set the player index */
11784 			/* paranoia */
11785 			if (!in_bounds2(wpos, y, x)) continue;
11786 
11787 			player_idx = 0 - zcave[y][x].m_idx;
11788 
11789 			/* Affect the player */
11790 			if ((flg & PROJECT_STAY) || (flg & PROJECT_FULL)) dist = 0;
11791 			if (project_p(player_idx, who, dist, wpos, y, x, dam, typ, rad, flg, attacker)) notice = TRUE;
11792 			/* reset stair-goi helper flag (used by project_p()) again */
11793 			if (player_idx >= 1 && player_idx <= NumPlayers) Players[player_idx]->invuln_applied = FALSE;
11794 		}
11795 	}
11796 
11797 #ifdef OPTIMIZED_ANIMATIONS
11798 	/* Display the "blast area" */
11799 	if (!(flg & PROJECT_HIDE))
11800 #ifdef PROJECTION_FLUSH_LIMIT
11801 			if (count_project < PROJECTION_FLUSH_LIMIT)
11802 #endif	// PROJECTION_FLUSH_LIMIT
11803 	{
11804 		/* Then do the "blast", from inside out */
11805 		for (t = 0; t <= rad; t++) {
11806 			/* Reset who can see */
11807 			num_can_see = 0;
11808 
11809 			/* Dump everything with this radius */
11810 			for (i = gm[t]; i < gm[t+1]; i++) {
11811 				/* Extract the location */
11812 				y = gy[i];
11813 				x = gx[i];
11814 
11815 				for (j = 1; j < NumPlayers + 1; j++) {
11816 					player_type *p_ptr = Players[j];
11817 					int dispy, dispx;
11818 					byte attr;
11819 					int k;
11820 					bool flag = TRUE;
11821 
11822 					if (p_ptr->conn == NOT_CONNECTED)
11823 						continue;
11824 
11825 					if (!inarea(&p_ptr->wpos, wpos))
11826 						continue;
11827 
11828 					if (p_ptr->blind)
11829 						continue;
11830 
11831 					if (!panel_contains(y, x))
11832 						continue;
11833 
11834 					if (!player_has_los_bold(j, y, x))
11835 						continue;
11836 
11837 					attr = spell_color(typ);
11838 
11839 					dispx = x - p_ptr->panel_col_prt;
11840 					dispy = y - p_ptr->panel_row_prt;
11841 
11842 					p_ptr->scr_info[dispy][dispx].c = '*';
11843 					p_ptr->scr_info[dispy][dispx].a = attr;
11844 
11845 					Send_char(j, dispx, dispy, attr, '*');
11846 
11847 					drawn = TRUE;
11848 
11849 					for (k = 0; k < num_can_see; k++) {
11850 						if (who_can_see[k] == j)
11851 							flag = FALSE;
11852 					}
11853 
11854 					if (flag)
11855 						who_can_see[num_can_see++] = j;
11856 				}
11857 			}
11858 		}
11859 
11860 		/* Flush the whole thing */
11861 		for (j = 0; j < num_can_see; j++) {
11862 			/* Show this radius and delay */
11863 			Send_flush(who_can_see[j]);
11864 		}
11865 
11866 		/* Flush the erasing */
11867 		if (drawn) {
11868 			/* Erase the explosion drawn above */
11869 			for (i = 0; i < grids; i++) {
11870 				/* Extract the location */
11871 				y = gy[i];
11872 				x = gx[i];
11873 
11874 				/* Erase a bit later */
11875 				everyone_lite_later_spot(wpos, y, x);
11876 			}
11877 		}
11878 	}
11879 #endif
11880 
11881 	/* Return "something was noticed" */
11882 	return (notice);
11883 }
11884 
11885 /* Check whether player is actually in an area that offers unusual safety from various
11886    attacks and effects. This is used for special events like Arena Monster Challenge - C. Blue */
11887 int safe_area(int Ind) {
11888 	player_type *p_ptr = Players[Ind];
11889 //	dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
11890 
11891 	/* For 'Arena Monster Challenge' event: */
11892 	if (ge_special_sector &&
11893 	    (p_ptr->wpos.wx == WPOS_ARENA_X && p_ptr->wpos.wy == WPOS_ARENA_Y && p_ptr->wpos.wz == WPOS_ARENA_Z))
11894 		return 1;
11895 
11896 	/* default: usual situation - not safe */
11897 	return 0;
11898 }
11899 
11900 
11901 /* Helper function for monster_is_safe() to determine how damaging a
11902  * projection is and if we should therefore try to move out of it. - C. Blue
11903  * IMPORTANT: Keep in sync with project_m(). */
11904 int approx_damage(int m_idx, int dam, int typ) {
11905 	int j = 0, k, k_elec, k_sound, k_lite;
11906 
11907 	monster_type *m_ptr = &m_list[m_idx];
11908 	monster_race *r_ptr = race_inf(m_ptr);
11909 	cptr name = r_name_get(m_ptr);
11910 
11911 	if (dam == 9999 && typ == GF_OLD_DRAIN) dam = 2; /* Priest drain-life spell hack */
11912 
11913 #if 0
11914 	int do_poly = 0;
11915 	int do_dist = 0;
11916 	int do_blind = 0;
11917 	int do_conf = 0;
11918 	int do_stun = 0;
11919 	int do_sleep = 0;
11920 //	int do_fear = 0;
11921 #endif
11922 
11923 	bool resist = FALSE;
11924 
11925 	/* Hack: GF_LIFEHEAL might heal or kill a monster */
11926 	if (typ == GF_LIFEHEAL) {
11927 		if (r_ptr->flags3 & RF3_UNDEAD) {
11928 			typ = GF_HOLY_FIRE;
11929 		} else {
11930 			typ = GF_OLD_HEAL;
11931 		}
11932 	}
11933 
11934 	switch (typ) {
11935 		case GF_SILENCE:
11936 			if (!((r_ptr->flags4 & RF4_SPELLCASTER_MASK) |
11937 			    (r_ptr->flags5 & RF5_SPELLCASTER_MASK) |
11938 			    (r_ptr->flags6 & RF6_SPELLCASTER_MASK) |
11939 			    (r_ptr->flags0 & RF0_SPELLCASTER_MASK)) ||
11940 			    (r_ptr->level >= 98 && (r_ptr->flags1 & RF1_UNIQUE)))
11941 			        dam = 0;
11942 			else if ((r_ptr->flags1 & RF1_UNIQUE) ||
11943 			    (r_ptr->flags2 & RF2_POWERFUL))
11944 				dam /= 2;
11945 #if 0 /* 0 => use 'dam' as 'avoidance' factor although there is no real damage here */
11946 			dam = 0;
11947 #endif
11948 			break;
11949 
11950 		case GF_PSI:
11951 			if ((r_ptr->flags9 & RF9_IM_PSI) || (r_ptr->flags2 & RF2_EMPTY_MIND) ||
11952 			    (r_ptr->flags3 & RF3_NONLIVING))
11953 			{
11954 				dam = 0;
11955 				break;
11956 			} else if (r_ptr->flags9 & RF9_RES_PSI) {
11957 				resist = TRUE;
11958 			} else if (r_ptr->flags3 & RF3_UNDEAD) {
11959 				resist = TRUE;
11960 			} else if ((r_ptr->flags2 & RF2_STUPID) ||
11961 			    ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags2 & RF2_CAN_SPEAK))) {
11962 				resist = TRUE;
11963 			} else if (r_ptr->flags2 & RF2_WEIRD_MIND)
11964 				dam = (dam * 3 + 1) / 4;
11965 
11966 			if ((r_ptr->flags2 & RF2_SMART) && !resist) dam += dam / 2;
11967 
11968 			if (resist) dam /= 2;
11969 			break;
11970 
11971 		case GF_CHARMIGNORE:
11972 			dam = 0;
11973 			break;
11974 
11975 		case GF_EARTHQUAKE:
11976 			dam = 0;
11977 			break;
11978 
11979 		case GF_MISSILE:
11980 			break;
11981 
11982 		case GF_ACID:
11983 			if (r_ptr->flags3 & RF3_IM_ACID)
11984 				dam = 0;
11985 			else if (r_ptr->flags9 & RF9_RES_ACID)
11986 				dam /= 4;
11987 			else if (r_ptr->flags9 & RF9_SUSCEP_ACID)
11988 				dam *= 2;
11989 			break;
11990 
11991 		case GF_ELEC:
11992 			if (r_ptr->flags3 & RF3_IM_ELEC)
11993 				dam = 0;
11994 			else if (r_ptr->flags9 & RF9_RES_ELEC)
11995 				dam /= 4;
11996 			else if (r_ptr->flags9 & RF9_SUSCEP_ELEC)
11997 				dam *= 2;
11998 			break;
11999 
12000 		case GF_FIRE:
12001 			if (r_ptr->flags3 & RF3_IM_FIRE)
12002 				dam = 0;
12003 			else if (r_ptr->flags9 & RF9_RES_FIRE)
12004 				dam /= 4;
12005 			else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
12006 				dam *= 2;
12007 			break;
12008 
12009 		case GF_COLD:
12010 			if (r_ptr->flags3 & RF3_IM_COLD)
12011 				dam = 0;
12012 			else if (r_ptr->flags9 & RF9_RES_COLD)
12013 				dam /= 4;
12014 			else if (r_ptr->flags3 & RF3_SUSCEP_COLD)
12015 				dam *= 2;
12016 			break;
12017 
12018 		case GF_POIS:
12019 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
12020 			    (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
12021 			    (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
12022 				dam = 0;
12023 			else if (r_ptr->flags9 & RF9_RES_POIS)
12024 				dam /= 4;
12025 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
12026 				dam *= 2;
12027 			break;
12028 
12029 		case GF_UNBREATH:
12030 //			if (magik(15)) do_pois = (10 + randint(11) + r) / (r + 1);
12031 			if ((r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
12032 				(r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)) ||
12033 				(m_ptr->r_idx == RI_MORGOTH)) /* <- Morgoth */
12034 				dam = 0;
12035 //				do_pois = 0;
12036 			else if (r_ptr->flags3 & RF3_IM_POIS)
12037 				dam = (dam * 2) / 4;
12038 			else if (r_ptr->flags9 & RF9_RES_POIS)
12039 				dam = (dam * 3) / 4;
12040 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
12041 				dam = (dam * 3) / 2;
12042 			break;
12043 
12044 		case GF_HELL_FIRE:
12045 			if (r_ptr->flags3 & (RF3_GOOD)) {
12046 				if (r_ptr->flags3 & RF3_IM_FIRE) {
12047 					dam *= 2; dam /= 2;//(randint(4)+3);
12048 				} else if (r_ptr->flags9 & RF9_RES_FIRE)
12049 					dam = (dam * 3) / 2;
12050 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
12051 					dam *= 2;
12052 				else
12053 					dam *= 2;
12054 			} else {
12055 				if (r_ptr->flags3 & RF3_IM_FIRE) {
12056 					dam *= 2; dam /= 4;//(randint(6)+10);
12057 				} else if (r_ptr->flags9 & RF9_RES_FIRE)
12058 					dam = (dam * 3) / 4;
12059 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
12060 					dam /= 2;
12061 				else ;
12062 					//dam *= 5; dam /= (randint(3)+4);
12063 			}
12064 			if (r_ptr->flags3 & (RF3_EVIL)) dam = (dam * 2) / 3;
12065 			break;
12066 
12067 		case GF_HOLY_ORB:
12068 			if (r_ptr->flags3 & (RF3_GOOD))
12069 				dam = 0;
12070 			if (r_ptr->flags3 & RF3_EVIL)
12071 				dam *= 2;
12072 			break;
12073 
12074 		case GF_HOLY_FIRE:
12075 			if (r_ptr->flags3 & (RF3_GOOD))
12076 				dam = 0;
12077 			else if (r_ptr->flags3 & (RF3_EVIL)) {
12078 				if (r_ptr->flags3 & RF3_IM_FIRE) {
12079 					dam *= 2; dam = (dam * 2) / 3;//(randint(4)+3);
12080 				} else if (r_ptr->flags9 & RF9_RES_FIRE)
12081 					dam = (dam * 6) / 4;
12082 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
12083 					dam *= 2;
12084 				else
12085 					dam *= 2;
12086 			} else {
12087 				if (r_ptr->flags3 & RF3_IM_FIRE) {
12088 					dam *= 2; dam /= 3;//(randint(6)+10);
12089 				} else if (r_ptr->flags9 & RF9_RES_FIRE)
12090 					dam = (dam * 3) / 4;
12091 				else if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
12092 					dam /= 2;
12093 				else ;
12094 //					dam *= 5; dam /= (randint(3)+4);
12095 			}
12096 			break;
12097 
12098 		case GF_ARROW:
12099 			break;
12100 
12101 		case GF_PLASMA:
12102 			if (r_ptr->flags3 & RF3_IM_FIRE)
12103 				dam /= 5;
12104 			else if (prefix(name, "Plasma") ||
12105 			    (r_ptr->flags4 & RF4_BR_PLAS) ||
12106 			    (r_ptr->flags3 & RF3_RES_PLAS))
12107 				dam /= 3;
12108 			else if (r_ptr->flags9 & RF9_RES_FIRE)
12109 				dam = (dam * 3) / 5;
12110 			break;
12111 
12112 		case GF_NETHER_WEAK:
12113 		case GF_NETHER:
12114 			if (r_ptr->flags3 & RF3_UNDEAD)
12115 				dam = 0;
12116 			else if ((r_ptr->flags4 & RF4_BR_NETH) || (r_ptr->flags3 & RF3_RES_NETH))
12117 				dam /= 3;
12118 			else if (r_ptr->flags3 & RF3_DEMON)
12119 				dam /= 2;
12120 #if 0
12121 			else if (r_ptr->flags3 & RF3_EVIL)
12122 				dam /= 2;
12123 #endif
12124 			break;
12125 
12126 		case GF_WATER:
12127 		case GF_VAPOUR:
12128 			if (r_ptr->flags9 & RF9_IM_WATER)
12129 				dam = 0;
12130 			else if (r_ptr->flags7 & RF7_AQUATIC)
12131 				dam /= 9;
12132 			else if (r_ptr->flags3 & RF3_RES_WATE)
12133 				dam /= 4;
12134 			break;
12135 
12136 		case GF_WAVE:
12137 			if (r_ptr->flags9 & RF9_IM_WATER)
12138 				dam = 0;
12139 			else if (r_ptr->flags7 & RF7_AQUATIC)
12140 				dam /= 9;
12141 			else if (r_ptr->flags3 & RF3_RES_WATE)
12142 				dam /= 4;
12143 			else
12144 				//do_stun = 7;
12145 			break;
12146 
12147 		case GF_CHAOS:
12148 			//if (r_ptr->level / 2 < 15) ;//do_poly = TRUE;
12149 			//do_conf = 10;
12150 			if ((r_ptr->flags4 & RF4_BR_CHAO) || (r_ptr->flags9 & RF9_RES_CHAOS)) {
12151 				dam /= 3;
12152 				//do_conf = 0;
12153 				//do_poly = FALSE;
12154 			}
12155 			break;
12156 
12157 		case GF_SHARDS:
12158 			if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS))
12159 				dam /= 3;
12160 			break;
12161 		case GF_INFERNO:
12162 		case GF_DETONATION:
12163 		case GF_ROCKET:
12164 		{
12165 			int res1 = 0, res2 = 0, res3 = 0; //shard,sound,fire
12166 			if ((r_ptr->flags4 & (RF4_BR_SHAR)) || (r_ptr->flags9 & RF9_RES_SHARDS))
12167 				res1 = 1;
12168 			if ((r_ptr->flags4 & RF4_BR_PLAS) || (r_ptr->flags3 & RF3_RES_PLAS) || prefix(name, "Plasma")) {
12169 				res2 = res3 = 1;
12170 			}
12171 			if ((r_ptr->flags4 & (RF4_BR_SOUN)) || (r_ptr->flags9 & RF9_RES_SOUND))
12172 				res2 = 1;
12173 			if (r_ptr->flags3 & RF3_IM_FIRE)
12174 				res3 = 3;
12175 			else if (r_ptr->flags9 & RF9_RES_FIRE)
12176 				res3 = 1;
12177 
12178 			switch (res1 + res2 + res3) {
12179 			case 0: break;
12180 			case 1: case 2:
12181 				dam = (dam * 3 + 3) / 4;
12182 //				do_cut = 0;
12183 				break;
12184 			default:
12185 				dam /= 2;
12186 				break;
12187 			}
12188 		}
12189 			break;
12190 
12191 		case GF_STUN:
12192 			//do_stun = 18;
12193 			if (r_ptr->flags9 & RF9_RES_SOUND) ;//do_stun /= 4;
12194 			break;
12195 
12196 		case GF_SOUND:
12197 			//do_stun = 18;
12198 			if ((r_ptr->flags4 & RF4_BR_SOUN) || (r_ptr->flags9 & RF9_RES_SOUND)) {
12199 				dam /= 3;
12200 				//do_stun = 0;
12201 			}
12202 			break;
12203 
12204 		case GF_CONFUSION:
12205 			//do_conf = 18;
12206 			if ((r_ptr->flags4 & RF4_BR_CONF) ||
12207 				(r_ptr->flags4 & RF4_BR_CHAO) || (r_ptr->flags9 & RF9_RES_CHAOS))
12208 				dam /= 3;
12209 			else if (r_ptr->flags3 & RF3_NO_CONF)
12210 				dam /= 2;
12211 			break;
12212 
12213 		case GF_DISENCHANT:
12214 			if ((r_ptr->flags4 & RF4_BR_DISE) ||
12215 			    prefix(name, "Disen") ||
12216 			    (r_ptr->flags3 & RF3_RES_DISE))
12217 				dam /= 3;
12218 			break;
12219 
12220 		case GF_NEXUS:
12221 			if ((r_ptr->flags4 & RF4_BR_NEXU) ||
12222 			    prefix(name, "Nexus") ||
12223 			    (r_ptr->flags3 & RF3_RES_NEXU))
12224 				dam /= 3;
12225 			break;
12226 
12227 		case GF_FORCE:
12228 			//do_stun = 8;
12229 			if (r_ptr->flags4 & RF4_BR_WALL) dam /= 3;
12230 			break;
12231 
12232 		case GF_INERTIA:
12233 			if (r_ptr->flags4 & RF4_BR_INER) dam /= 3;
12234 			break;
12235 
12236 		case GF_TIME: //Note: Also steals energy!
12237 			if ((r_ptr->flags4 & RF4_BR_TIME) || (r_ptr->flags9 & RF9_RES_TIME)
12238 			    || (r_ptr->flags3 & RF3_DEMON) || (r_ptr->flags3 & RF3_NONLIVING)
12239 			    || (r_ptr->flags3 & RF3_UNDEAD))
12240 				dam /= 3;
12241 			break;
12242 
12243 		case GF_GRAVITY:
12244 		{
12245 			bool resist_tele = FALSE;
12246 			if ((r_ptr->flags3 & RF3_RES_TELE) || (r_ptr->flags9 & RF9_IM_TELE)) {
12247 				if ((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags9 & RF9_IM_TELE))
12248 					resist_tele = TRUE;
12249 			}
12250 
12251 			if (!resist_tele) ;//do_dist = 10;
12252 			else ;//do_dist = 0;
12253 
12254 			if (r_ptr->flags4 & RF4_BR_GRAV) {
12255 				dam /= 3;
12256 				//do_dist = 0;
12257 			}
12258 			break;
12259 		}
12260 
12261 		case GF_MANA:
12262 			if (r_ptr->flags9 & RF9_RES_MANA)
12263 				dam /= 3;
12264 			else if (r_ptr->flags4 & RF4_BR_MANA)
12265 				dam /= 2;
12266 			break;
12267 
12268 		case GF_METEOR:
12269 			break;
12270 
12271 		case GF_ICE:
12272 			//do_stun = 8;
12273 			k = dam;
12274 
12275 			dam = (k * 3) / 5;/* 60% COLD damage */
12276 			if (r_ptr->flags3 & RF3_IM_COLD)
12277 				dam = 0;
12278 			else if (r_ptr->flags9 & RF9_RES_COLD)
12279 				dam /= 4;
12280 			else if (r_ptr->flags3 & RF3_SUSCEP_COLD)
12281 				dam *= 2;
12282 
12283 			k = (k * 2) / 5;/* 40% SHARDS damage */
12284 			if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS))
12285 				k /= 3;
12286 			dam = dam + k;
12287 			break;
12288 
12289 		case GF_THUNDER:
12290 			k_elec = dam / 3; /* 33% ELEC damage */
12291 			if (r_ptr->flags3 & RF3_IM_ELEC)
12292 				k_elec = 0;
12293 			else if (r_ptr->flags9 & RF9_RES_ELEC)
12294 				k_elec /= 4;
12295 			else if (r_ptr->flags9 & RF9_SUSCEP_ELEC)
12296 				k_elec *= 2;
12297 
12298 			k_sound = dam / 3; /* 33% SOUND damage */
12299 			//do_stun = 8;
12300 			if ((r_ptr->flags4 & RF4_BR_SOUN) || (r_ptr->flags9 & RF9_RES_SOUND)) {
12301 				k_sound /= 3;
12302 				//do_stun = 0;
12303 			}
12304 
12305 			k_lite = dam / 3; /* 33% LIGHT damage */
12306 			//do_blind = damroll(3, (k_lite / 20)) + 1;
12307 			if (r_ptr->d_char == 'A') {
12308 				k_lite = 0;
12309 				//do_blind = 0;
12310 			} else if ((r_ptr->flags4 & RF4_BR_LITE) || (r_ptr->flags9 & RF9_RES_LITE)) {
12311 				k_lite /= 4;
12312 				//do_blind = 0;
12313 			} else if (r_ptr->flags3 & RF3_HURT_LITE) {
12314 				k_lite *= 2;
12315 			}
12316 
12317 			dam = k_elec + k_sound + k_lite;
12318 			break;
12319 
12320 		case GF_OLD_DRAIN:
12321 			if (m_ptr->hp > 9362)
12322 				dam = (m_ptr->hp / 100) * dam;
12323 			else if (m_ptr->hp > 936)
12324 				dam = ((m_ptr->hp / 10) * dam) / 10;
12325 			else
12326 				dam = (m_ptr->hp * dam) / 100;
12327 
12328 			if ((r_ptr->flags3 & RF3_UNDEAD) ||
12329 //			    (r_ptr->flags3 & RF3_DEMON) ||
12330 			    (r_ptr->flags3 & RF3_NONLIVING) ||
12331 			    (r_ptr->flags1 & RF1_UNIQUE) ||
12332 			    (strchr("Egv", r_ptr->d_char)))
12333 				dam = 0;
12334 			break;
12335 
12336 		case GF_ANNIHILATION:
12337 			j = dam - 1;
12338 			if (m_ptr->hp > 9362)
12339 				dam = (m_ptr->hp / 100) * dam;
12340 			else if (m_ptr->hp > 936)
12341 				dam = ((m_ptr->hp / 10) * dam) / 10;
12342 			else
12343 				dam = (m_ptr->hp * dam) / 100;
12344 
12345 			if (dam > j * 200) {
12346 				dam = j * 200;
12347 				if ((r_ptr->flags1 & RF1_UNIQUE) ||
12348 				    (r_ptr->flags3 & RF3_UNDEAD) ||
12349 				    (r_ptr->flags3 & RF3_NONLIVING)) {
12350 					dam /= 3;
12351 				}
12352 			}
12353 
12354 			if (dam < j * 10 + 100) {
12355 				dam = j * 10 + 100;
12356 				if ((r_ptr->flags1 & RF1_UNIQUE) ||
12357 				    (r_ptr->flags3 & RF3_UNDEAD) ||
12358 				    (r_ptr->flags3 & RF3_NONLIVING)) {
12359 					dam /= 3;
12360 				}
12361 			}
12362 
12363 			break;
12364 
12365 		case GF_OLD_POLY:
12366 			//do_poly = TRUE;
12367 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
12368 			    (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) / 2 + 10))
12369 				;//do_poly = FALSE;
12370 
12371 			dam = 0;
12372 			break;
12373 
12374 		case GF_OLD_CLONE:
12375 		case GF_OLD_HEAL:
12376 		case GF_HERO_MONSTER:
12377 		case GF_REMFEAR:
12378 		case GF_OLD_SPEED:
12379 			dam = 0;
12380 			break;
12381 
12382 		case GF_OLD_SLOW:
12383 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
12384 			    (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) + 10) ||
12385 			    (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) / 2 + 10) || /* RES_OLD() */
12386 			    !(m_ptr->mspeed >= 100 && m_ptr->mspeed > m_ptr->speed - 10))
12387 				dam = 0;
12388 			break;
12389 
12390 		case GF_OLD_SLEEP:
12391 			if (!((r_ptr->flags1 & RF1_UNIQUE) ||
12392 			    (r_ptr->flags3 & RF3_NO_SLEEP) ||
12393 			    (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) / 2 + 10))) /* RES_OLD() */
12394 				;//do_sleep = GF_OLD_SLEEP_DUR;
12395 			dam = 0;
12396 			break;
12397 
12398 		case GF_OLD_CONF:
12399 			//do_conf = damroll(3, (dam / 2)) + 1;
12400 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
12401 			    (r_ptr->flags3 & RF3_NO_CONF) ||
12402 			    (r_ptr->level > ((dam - 10) < 1 ? 1 : (dam - 10)) / 2 + 10)) /* RES_OLD() */
12403 				;//do_conf = 0;
12404 			dam = 0;
12405 			break;
12406 
12407 		case GF_BLIND:
12408 			//do_blind = dam;
12409 			dam = 0;
12410 			break;
12411 
12412 		case GF_CURSE:
12413 			//do_conf = (damroll(3, (dam / 2)) + 1) / 3;
12414 			//do_blind = dam / 3;
12415 			if ((r_ptr->flags1 & RF1_UNIQUE) ||
12416 			    (r_ptr->level > ((dam / 3 - 10) < 1 ? 1 : (dam / 3 - 10)) / 2 + 10)) /* RES_OLD */
12417 				;//do_blind = do_conf = 0;
12418 			if (r_ptr->flags3 & RF3_NO_CONF) ;//do_conf = 0;
12419 			dam /= 3;
12420 			break;
12421 
12422 		case GF_HEALINGCLOUD:
12423 			if (!(r_ptr->flags3 & RF3_UNDEAD))
12424 				dam = 0;
12425 			break;
12426 
12427 		case GF_WATERPOISON:
12428 			k = dam / 2;
12429 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
12430 			  (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
12431 			  (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
12432 				k = 0;
12433 			else if (r_ptr->flags9 & RF9_RES_POIS)
12434 				k /= 4;
12435 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
12436 				k *= 2;
12437 			j = k;
12438 
12439 			k = dam / 2;
12440 			if (r_ptr->flags9 & RF9_IM_WATER)
12441 				k = 0;
12442 			else if (r_ptr->flags7 & RF7_AQUATIC)
12443 				k /= 9;
12444 			else if (r_ptr->flags3 & RF3_RES_WATE)
12445 				k /= 4;
12446 			dam = j + k;
12447 			break;
12448 
12449 		case GF_ICEPOISON:
12450 			k = (dam * 3) / 5;
12451 			if ((r_ptr->flags4 & RF4_BR_SHAR) || (r_ptr->flags9 & RF9_RES_SHARDS))
12452 				k /= 3;
12453 			j = k;
12454 
12455 			k = dam / 5;
12456 			if (r_ptr->flags9 & RF9_IM_WATER)
12457 				k = 0;
12458 			else if (r_ptr->flags7 & RF7_AQUATIC)
12459 				k /= 9;
12460 			else if (r_ptr->flags3 & RF3_RES_WATE)
12461 				k /= 4;
12462 			j += k;
12463 
12464 			k = dam / 5;
12465 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
12466 			    (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
12467 			    (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
12468 				k = 0;
12469 			else if (r_ptr->flags9 & RF9_RES_POIS)
12470 				k /= 4;
12471 			else if (r_ptr->flags9 & RF9_SUSCEP_POIS)
12472 				k *= 2;
12473 			dam = j + k;
12474 			break;
12475 
12476 		case GF_LITE_WEAK:
12477 			if (!(r_ptr->flags3 & RF3_HURT_LITE))
12478 				dam = 0;
12479 			break;
12480 
12481 		case GF_LITE:
12482 			//do_blind = damroll(3, (dam / 20)) + 1;
12483 
12484 			if (r_ptr->d_char == 'A') {
12485 				dam = 0;
12486 				//do_blind = 0;
12487 			} else if ((r_ptr->flags4 & RF4_BR_LITE) || (r_ptr->flags9 & RF9_RES_LITE)) {
12488 				dam /= 3;
12489 				//do_blind = 0;
12490 			} else if (r_ptr->flags3 & RF3_HURT_LITE) {
12491 				dam *= 2;
12492 			}
12493 			break;
12494 
12495 		case GF_DARK:
12496 			//do_blind = damroll(3, (dam / 20)) + 1;
12497 			if ((r_ptr->flags4 & RF4_BR_DARK) || (r_ptr->flags9 & RF9_RES_DARK)
12498 			    || (r_ptr->flags3 & RF3_UNDEAD)) {
12499 				dam /= 3;
12500 				//do_blind = 0;
12501 			}
12502 			break;
12503 
12504 		case GF_KILL_WALL:
12505 			if (!(r_ptr->flags3 & RF3_HURT_ROCK))
12506 				dam = 0;
12507 			break;
12508 
12509 		case GF_AWAY_UNDEAD:
12510 		case GF_AWAY_EVIL:
12511 		case GF_AWAY_ALL:
12512 		case GF_TURN_UNDEAD:
12513 		case GF_TURN_EVIL:
12514 		case GF_TURN_ALL:
12515 			dam = 0;
12516 			break;
12517 
12518 		case GF_DISP_UNDEAD:
12519 			if (!(r_ptr->flags3 & RF3_UNDEAD))
12520 				dam = 0;
12521 			break;
12522 		case GF_DISP_EVIL:
12523 			if (!(r_ptr->flags3 & RF3_EVIL))
12524 				dam = 0;
12525 			break;
12526 		case GF_DISP_DEMON:
12527 			if (!(r_ptr->flags3 & RF3_DEMON))
12528 				dam = 0;
12529 			break;
12530 		case GF_DISP_ALL:
12531 			break;
12532 
12533 		case GF_NUKE:
12534 			if ((r_ptr->flags3 & RF3_IM_POIS) ||
12535 			  (r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)) ||
12536 			  (r_ptr->d_char == 'A') || ((r_ptr->d_char == 'U') && (r_ptr->flags3 & RF3_DEMON)))
12537 				dam = 0;
12538 			else if (r_ptr->flags9 & (RF9_RES_POIS))
12539 				dam /= 3;
12540 			break;
12541 
12542 		case GF_DISINTEGRATE:
12543 			if (r_ptr->flags3 & (RF3_HURT_ROCK))
12544 				dam *= 2;
12545 			if (r_ptr->flags1 & RF1_UNIQUE)
12546 				dam >>= 1;
12547 			break;
12548 
12549 		case GF_HOLD:
12550 		case GF_DOMINATE:
12551 		case GF_TELE_TO:
12552 		case GF_HAND_DOOM:
12553 		case GF_STASIS:
12554 		case GF_DEC_STR:
12555 		case GF_DEC_DEX:
12556 		case GF_DEC_CON:
12557 		case GF_RES_STR:
12558 		case GF_RES_DEX:
12559 		case GF_RES_CON:
12560 		case GF_INC_STR:
12561 		case GF_INC_DEX:
12562 		case GF_INC_CON:
12563 		case GF_AUGMENTATION:
12564 		case GF_RUINATION:
12565 		default:
12566 			/* No damage */
12567 			dam = 0;
12568 			break;
12569 	}
12570 
12571 #if 0
12572 	/* maybe TODO: */
12573 	int do_poly = 0;
12574 	int do_dist = 0;
12575 	int do_blind = 0;
12576 	int do_conf = 0;
12577 	int do_stun = 0;
12578 	int do_sleep = 0;
12579 //	int do_fear = 0;
12580 #endif
12581 
12582 	return (dam);
12583 }
12584