1 /* $Id$ */
2 /* File: effects.c */
3 
4 /* Purpose: effects of various "objects" */
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 #include "party.h"
18 
19 
20 //#define IRON_TEAM_EXPERIENCE
21 /* todo before enabling: implement way to decrease party.experience again! */
22 
23 /*
24  * What % of exp points will be lost when resurrecting? [40]	- Jir -
25  *
26  * cf. GHOST_FADING in dungeon.c
27  */
28 #ifdef ENABLE_INSTANT_RES
29 #define GHOST_XP_LOST	35
30 #else
31 #define GHOST_XP_LOST	40
32 #endif
33 
34 /*
35  * What % of exp points will be lost on instant resurrection?
36  */
37 #define INSTANT_RES_XP_LOST	50
38 
39 /*
40  * Chance of an item teleporting away when player dies, in percent. [10]
41  * This is to balance death penalty after item stacking was implemented.
42  * To disable, comment it out.
43  */
44 #define DEATH_ITEM_SCATTER	0
45 
46 /* Chance of an item from the player's inventory getting lost (aka deleted)
47    when player dies, in percent [20]. - C. Blue (limited to 4) */
48 #define DEATH_PACK_ITEM_LOST	15
49 
50 /* Chance of an item from the player's equipment getting lost (aka deleted)
51    when player dies, in percent [10]. - C. Blue (limited to 1) */
52 #define DEATH_EQ_ITEM_LOST	10
53 
54 /* Reduce chance of inventory item destruction, to balance death for
55    characters relying heavily on certain types of items? */
56 #define DEATH_PACK_ITEM_NICE
57 
58 /* Loot item level is average of monster level and floor level - C. Blue
59    Note: Imho the more floor level is taken into account, the more will
60          melee chars who aim at high level weapons and armour be at a
61          disadvantage, compared to light armour dropping everywhere.
62          Also, floor level determines monster level of spawns anyway.
63          However, contra side of disabling this is cheezy high unique
64          farming on harmless floors via vaults for great loot -
65          probably only affects melee chars though.
66    Disabling this definition will cause loot to depend more on monster level. */
67 #define TRADITIONAL_LOOT_LEVEL
68 
69 /* Should be defined to allow finding top-level items on non-NR floors
70    in cases where you just cannot find monsters of high enough level so
71    that averaging floor and monster level would pass the test.
72    Details:
73    Without this, if TRADITIONAL_LOOT_LEVEL is on, no loot above klevel 108
74    could drop outside of NR anymore (Star Blade being highest normal monster
75    at 90).
76    Without TRADITIONAL_LOOT_LEVEL the situation becomes worse and usually no
77    loot above klevel 102 could drop anymore (again Star Blades lv90 assumed).
78    Note: Items of klevel > 115 usually cannot drop outside of NR, even with
79    this on.
80    EXCEPTIONS to all the above stuff:
81    Note2: Objects still get an extra boost from being 'good' or 'great', of +10
82    to object_level and from GREAT_OBJ which can even be +128. - C. Blue */
83 #define RANDOMIZED_LOOT_LEVEL
84 
85 /* Level 50 limit for non-kings:    RECOMMENDED!  */
86 #define KINGCAP_LEV
87 
88 /* exp limit for non-kings (level 50..69 depending on race/class) for non-kings: */
89 /*#define KINGCAP_EXP*/		/*  NOT RECOMMENDED to enable this!  */
90 
91 /* Does NOT have effect if KINGCAP_EXP is defined.
92    Total bonus skill points till level 50 for yeeks.
93    All other class/race combinations will get less, down to 0 for
94    max exp penalty of 472,5 %. Must be integer within 0..50. [25] */
95 #define WEAK_SKILLBONUS 0	/* NOT RECOMMENDED to set this > 0! */
96 
97 /* Show real killer name even when hallucinating? */
98 #define SHOW_REALLY_DIED_FROM
99 /* In addition to above, show real killer instead of "insanity"? */
100 #ifdef SHOW_REALLY_DIED_FROM
101  #define SHOW_REALLY_DIED_FROM_INSANITY
102 #endif
103 
104 /* Do player-kill messages of "Morgoth, Lord of Darkness" get some
105    special flavour? - C. Blue */
106 #define MORGOTH_FUNKY_KILL_MSGS
107 
108 /*
109  * Modifier of semi-promised artifact drops, in percent.
110  * It can happen that the quickest player will gather most of those
111  * artifact; this can be used to defuse it somewhat. Won't affect '101%' chances.
112  */
113 // #define SEMI_PROMISED_ARTS_MODIFIER	50
114 
115 /*
116  * If defined, a player cannot gain more than 1 level at once.
117  * It prevents so-called 'high-books cheeze'.
118  */
119 /* Prolly no longer needed, since a player cannot gain exp from books now */
120 //#define LEVEL_GAINING_LIMIT
121 
122 
123 /*
124  * Thresholds for scrolling.	[3,8] [2,4]
125  * XXX They should be client-side numerical options.	- Jir -
126  */
127 #ifndef ARCADE_SERVER
128 	#define TRAD_SCROLL_MARGIN_ROW	(p_ptr->wide_scroll_margin ? 5 : 2)
129 	#define	SCROLL_MARGIN_ROW	(p_ptr->screen_hgt >= 26 ? \
130 					(p_ptr->wide_scroll_margin ? p_ptr->screen_hgt / 5 : p_ptr->screen_hgt / 13) : \
131 					TRAD_SCROLL_MARGIN_ROW)
132 	#define	SCROLL_MARGIN_COL	(p_ptr->wide_scroll_margin ? p_ptr->screen_wid / 5 : p_ptr->screen_wid / 13)
133 	#define TRAD_SCROLL_MARGIN_COL	SCROLL_MARGIN_COL
134 #else
135 	#define SCROLL_MARGIN_ROW 8
136 	#define SCROLL_MARGIN_COL 20
137 	#define TRAD_SCROLL_MARGIN_ROW	SCROLL_MARGIN_ROW
138 	#define TRAD_SCROLL_MARGIN_COL	SCROLL_MARGIN_COL
139 #endif
140 
141 /* death_type definitions */
142 #define DEATH_PERMA	0
143 #define DEATH_INSANITY	1
144 #define DEATH_GHOST	2
145 #define DEATH_QUIT	3 /* suicide/retirement */
146 
147 
148 /* If during certain events, remember his/her account ID, for handing out a reward
149    to a different character which he chooses on next login! - C. Blue
150 */
buffer_account_for_event_deed(player_type * p_ptr,int death_type)151 static void buffer_account_for_event_deed(player_type *p_ptr, int death_type) {
152 	int i,j;
153 #if 0 /* why should this be enabled, hmm */
154 	for (i = 0; i < MAX_CONTENDER_BUFFERS; i++)
155 		if (ge_contender_buffer_ID[i] == p_ptr->account) return; /* player already has a buffer entry */
156 #endif
157 	for (i = 0; i < MAX_CONTENDER_BUFFERS; i++)
158 		if (ge_contender_buffer_ID[i] == 0) break;
159 	if (i == MAX_CONTENDER_BUFFERS) return; /* no free buffer entries anymore, sorry! */
160 	ge_contender_buffer_ID[i] = p_ptr->account;
161 	for (j = 0; j < MAX_GLOBAL_EVENTS; j++)
162 		switch (p_ptr->global_event_type[j]) {
163 		case GE_HIGHLANDER:
164 			if (p_ptr->global_event_progress[j][0] < 5) break; /* only rewarded if already in deathmatch phase! */
165 			if (death_type >= DEATH_QUIT) break; /* no reward for suiciding! */
166 			/* hand out the reward: */
167 			ge_contender_buffer_deed[i] = SV_DEED2_HIGHLANDER;
168 			return;
169 #if 1 /* since everyone can win, this is not that important */
170 		case GE_DUNGEON_KEEPER:
171 			if (death_type >= DEATH_QUIT) break; /* no reward for suiciding! */
172 			/* hand out the reward: */
173 			ge_contender_buffer_deed[i] = SV_DEED2_DUNGEONKEEPER;
174 			return;
175 #endif
176 		case GE_NONE:
177 		default:
178 			break;
179 		}
180 	ge_contender_buffer_ID[i] = 0; /* didn't find any event where player participated */
181 }
182 
buffer_account_for_achievement_deed(player_type * p_ptr,int achievement)183 static void buffer_account_for_achievement_deed(player_type *p_ptr, int achievement) {
184 	int i;
185 #if 0 /* why should this be enabled, hmm */
186 	for (i = 0; i < MAX_ACHIEVEMENT_BUFFERS; i++)
187 		if (achievement_buffer_ID[i] == p_ptr->account) return; /* player already has a buffer entry */
188 #endif
189 	for (i = 0; i < MAX_ACHIEVEMENT_BUFFERS; i++)
190 		if (achievement_buffer_ID[i] == 0) break;
191 	if (i == MAX_ACHIEVEMENT_BUFFERS) return; /* no free buffer entries anymore, sorry! */
192 	achievement_buffer_ID[i] = p_ptr->account;
193 	switch (achievement) {
194 	case ACHV_PVP_MAX:
195 		achievement_buffer_deed[i] = SV_DEED_PVP_MAX;
196 		break;
197 	case ACHV_PVP_MID:
198 		achievement_buffer_deed[i] = SV_DEED_PVP_MID;
199 		break;
200 	case ACHV_PVP_MASS:
201 		achievement_buffer_deed[i] = SV_DEED_PVP_MASS;
202 		break;
203 	default:
204 		break;
205 	}
206 }
207 
208 /*
209  * Set "p_ptr->tim_thunder", notice observable changes
210  */
set_tim_thunder(int Ind,int v,int p1,int p2)211 bool set_tim_thunder(int Ind, int v, int p1, int p2) {
212 	player_type *p_ptr = Players[Ind];
213 	bool notice = FALSE;
214 
215 	/* Hack -- Force good values */
216 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
217 
218 	/* Open */
219 	if (v) {
220 		if (!p_ptr->tim_thunder) {
221 			msg_print(Ind, "The air around you charges with lightning!");
222 			notice = TRUE;
223 		}
224 	}
225 
226 	/* Shut */
227 	else {
228 		if (p_ptr->tim_thunder) {
229 			msg_print(Ind, "The air around you discharges.");
230 			notice = TRUE;
231 			p1 = p2 = 0;
232 		}
233 	}
234 
235 	/* Use the value */
236 	p_ptr->tim_thunder = v;
237 	p_ptr->tim_thunder_p1 = p1;
238 	p_ptr->tim_thunder_p2 = p2;
239 
240 	/* Nothing to notice */
241 	if (!notice) return (FALSE);
242 
243 	/* Disturb */
244 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
245 
246 	/* Recalculate boni */
247 	p_ptr->update |= (PU_BONUS);
248 
249 	/* Update the monsters */
250 	p_ptr->update |= (PU_MONSTERS);
251 
252 	/* Handle stuff */
253 	handle_stuff(Ind);
254 
255 	/* Result */
256 	return (TRUE);
257 }
258 
259 /*
260  * Set "p_ptr->tim_regen", notice observable changes
261  */
set_tim_regen(int Ind,int v,int p)262 bool set_tim_regen(int Ind, int v, int p) {
263 	player_type *p_ptr = Players[Ind];
264 	bool notice = FALSE;
265 
266 	/* Hack -- Force good values */
267 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
268 
269 	/* Open */
270 	if (v) {
271 		if (!p_ptr->tim_regen) {
272 			msg_print(Ind, "Your body regeneration abilities greatly increase!");
273 			notice = TRUE;
274 		}
275 	}
276 
277 	/* Shut */
278 	else {
279 		if (p_ptr->tim_regen) {
280 			p = 0;
281 			msg_print(Ind, "Your body regeneration abilities becomes normal again.");
282 			notice = TRUE;
283 		}
284 	}
285 
286 	/* Use the value */
287 	p_ptr->tim_regen = v;
288 	p_ptr->tim_regen_pow = p;
289 
290 	/* Nothing to notice */
291 	if (!notice) return (FALSE);
292 
293 	/* Disturb */
294 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
295 
296 	/* Handle stuff */
297 	handle_stuff(Ind);
298 
299 	/* Result */
300 	return (TRUE);
301 }
302 
303 /*
304  * Set "p_ptr->tim_ffall"
305  */
set_tim_ffall(int Ind,int v)306 bool set_tim_ffall(int Ind, int v) {
307 	player_type *p_ptr = Players[Ind];
308 	bool notice = FALSE;
309 
310 	/* Hack -- Force good values */
311 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
312 
313 	/* Open */
314 	if (v) {
315 		if (!p_ptr->tim_ffall) {
316 			msg_print(Ind, "You feel very light.");
317 			notice = TRUE;
318 		}
319 	}
320 
321 	/* Shut */
322 	else {
323 		if (p_ptr->tim_ffall) {
324 			msg_print(Ind, "You are suddenly heavier.");
325 			notice = TRUE;
326 		}
327 	}
328 
329 	/* Use the value */
330 	p_ptr->tim_ffall = v;
331 
332 	/* Nothing to notice */
333 	if (!notice)
334 		return (FALSE);
335 
336 	/* Disturb */
337 	if (p_ptr->disturb_state)
338 		disturb(Ind, 0, 0);
339 
340 	/* Recalculate boni */
341 	p_ptr->update |= (PU_BONUS);
342 
343 	/* Result */
344 	return (TRUE);
345 }
346 
347 /*
348  * Set "p_ptr->tim_lev"
349  */
set_tim_lev(int Ind,int v)350 bool set_tim_lev(int Ind, int v) {
351 	player_type *p_ptr = Players[Ind];
352 	bool notice = FALSE;
353 
354 	/* Hack -- Force good values */
355 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
356 
357 	/* Open */
358 	if (v) {
359 		if (!p_ptr->tim_lev) {
360 			msg_print(Ind, "You feel light and your feet take off the ground.");
361 			notice = TRUE;
362 		}
363 	}
364 
365 	/* Shut */
366 	else {
367 		if (p_ptr->tim_lev) {
368 			msg_print(Ind, "You are suddenly a lot heavier.");
369 			notice = TRUE;
370 		}
371 	}
372 
373 	/* Use the value */
374 	p_ptr->tim_lev = v;
375 
376 	/* Nothing to notice */
377 	if (!notice)
378 		return (FALSE);
379 
380 	/* Disturb */
381 	if (p_ptr->disturb_state)
382 		disturb(Ind, 0, 0);
383 
384 	/* Recalculate boni */
385 	p_ptr->update |= (PU_BONUS);
386 
387 	/* Result */
388 	return (TRUE);
389 }
390 
391 /*
392  * Set "p_ptr->adrenaline", notice observable changes
393  * Note the interaction with biofeedback
394  */
set_adrenaline(int Ind,int v)395 bool set_adrenaline(int Ind, int v) {
396 	player_type *p_ptr = Players[Ind];
397 	bool notice = FALSE;
398 
399         int i;
400 
401 	/* Hack -- Force good values */
402 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
403 
404 	/* Open */
405 	if (v) {
406 		if (!p_ptr->adrenaline) {
407 			msg_print(Ind, "Adrenaline surges through your veins!");
408 			if (p_ptr->biofeedback) {
409 				msg_print(Ind, "You lose control of your blood flow!");
410 				i = randint(randint(v));
411 				take_hit(Ind, damroll(2, i),"adrenaline poisoning", 0);
412 				v = v - i + 1;
413 				p_ptr->biofeedback = 0;
414 			}
415 
416 			notice = TRUE;
417 		} else {
418 			/* Sudden crash */
419 			if (!rand_int(500) && (p_ptr->adrenaline >= v)) {
420 				msg_print(Ind, "Your adrenaline suddenly runs out!");
421 				v = 0;
422 			}
423 		}
424 
425 		while (v > 30 + randint(p_ptr->lev * 5)) {
426 			msg_print(Ind, "Your body can't handle that much adrenaline!");
427 			i = randint(randint(v));
428 			take_hit(Ind, damroll(3, i * 2),"adrenaline poisoning", 0);
429 			v = v - i + 1;
430 		}
431 	}
432 
433 	/* Shut */
434 	else {
435 		if (p_ptr->adrenaline) {
436 			if (!rand_int(5)) {
437 				msg_print(Ind, "Your adrenaline runs out, leaving you tired and weak.");
438 				do_dec_stat(Ind, A_CON, STAT_DEC_TEMPORARY);
439 			} else {
440 				msg_print(Ind, "Your heart slows down to normal.");
441 			}
442 			notice = TRUE;
443 		}
444 	}
445 
446 	/* Use the value */
447 	p_ptr->adrenaline = v;
448 
449 	/* Nothing to notice */
450 	if (!notice) return (FALSE);
451 
452 	/* Notice */
453 	p_ptr->update |= (PU_BONUS | PU_HP);
454 
455 	/* Disturb */
456 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
457 
458 	/* Handle stuff */
459 	handle_stuff(Ind);
460 
461 	/* Result */
462 	return (TRUE);
463 
464 }
465 /*
466  * Set "p_ptr->biofeedback", notice observable changes
467  * Note the interaction with adrenaline
468  */
set_biofeedback(int Ind,int v)469 bool set_biofeedback(int Ind, int v) {
470 	player_type *p_ptr = Players[Ind];
471 	bool notice = FALSE;
472 
473 	/* Hack -- Force good values */
474 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
475 
476 	/* Open */
477 	if (v) {
478 		if (!p_ptr->biofeedback) {
479 			msg_print(Ind, "Your pulse slows and your body prepares to resist damage.");
480 			if (p_ptr->adrenaline) {
481 				msg_print(Ind, "The adrenaline drains out of your veins.");
482 				p_ptr->adrenaline = 0;
483 				if (!rand_int(8)) {
484 					msg_print(Ind, "You start to tremble as your blood sugar crashes.");
485 					set_slow(Ind, p_ptr->slow + rand_int(rand_int(16)));
486 					if (!rand_int(5)) set_paralyzed(Ind, p_ptr->paralyzed + 1);
487 					if (!rand_int(3)) set_stun(Ind, p_ptr->stun + rand_int(30));
488 				}
489 			}
490 			notice = TRUE;
491 		}
492 	}
493 
494 	/* Shut */
495 	else {
496 		if (p_ptr->biofeedback) {
497 			msg_print(Ind, "Your veins return to normal.");
498 			notice = TRUE;
499 		}
500 	}
501 
502 	while (v > 35 + rand_int(rand_int(p_ptr->lev))) {
503 			msg_print(Ind, "You speed up your pulse to avoid fainting!");
504 			v -= 20;
505 	}
506 
507 	/* Use the value */
508 	p_ptr->biofeedback = v;
509 
510 	/* Nothing to notice */
511 	if (!notice) return (FALSE);
512 
513 	/* Notice */
514 	p_ptr->update |= (PU_BONUS | PU_HP);
515 
516 	/* Disturb */
517 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
518 
519 	/* Handle stuff */
520 	handle_stuff(Ind);
521 
522 	/* Result */
523 	return (TRUE);
524 
525 }
526 
527 
528 /*
529  * Set "p_ptr->tim_esp", notice observable changes
530  */
set_tim_esp(int Ind,int v)531 bool set_tim_esp(int Ind, int v) {
532 	player_type *p_ptr = Players[Ind];
533 	bool notice = FALSE;
534 
535 	/* Hack -- Force good values */
536 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
537 
538 	/* Open */
539 	if (v) {
540 		if (!p_ptr->tim_esp) {
541 			msg_print(Ind, "Your mind expands !");
542 			notice = TRUE;
543 		}
544 	}
545 
546 	/* Shut */
547 	else {
548 		if (p_ptr->tim_esp) {
549 			msg_print(Ind, "Your mind retracts.");
550 			notice = TRUE;
551 		}
552 	}
553 
554 	/* Use the value */
555 	p_ptr->tim_esp = v;
556 
557 	/* Nothing to notice */
558 	if (!notice) return (FALSE);
559 
560 	/* Disturb */
561 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
562 
563 	/* Recalculate boni */
564 	p_ptr->update |= (PU_BONUS | PU_MONSTERS);
565 
566 	/* Handle stuff */
567 	handle_stuff(Ind);
568 
569 	/* Result */
570 	return (TRUE);
571 }
572 
573 
574 /*
575  * Set "p_ptr->st_anchor", notice observable changes
576  */
set_st_anchor(int Ind,int v)577 bool set_st_anchor(int Ind, int v) {
578 	player_type *p_ptr = Players[Ind];
579 	bool notice = FALSE;
580 
581 	/* Hack -- Force good values */
582 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
583 
584 	/* Open */
585 	if (v) {
586 		if (!p_ptr->st_anchor) {
587 			//msg_print(Ind, "The Space/Time Continuum seems to solidify !");
588 			msg_print(Ind, "The air feels very still.");
589 			notice = TRUE;
590 		}
591 	}
592 
593 	/* Shut */
594 	else {
595 		if (p_ptr->st_anchor) {
596 			//msg_print(Ind, "The Space/Time Continuum seems more flexible.");
597 			msg_print(Ind, "The air feels fresh again.");
598 			notice = TRUE;
599 		}
600 	}
601 
602 	/* Use the value */
603 	p_ptr->st_anchor = v;
604 
605 	/* Nothing to notice */
606 	if (!notice) return (FALSE);
607 
608 	/* Disturb */
609 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
610 
611 	/* Recalculate boni */
612 	p_ptr->update |= (PU_BONUS);
613 
614 	/* Handle stuff */
615 	handle_stuff(Ind);
616 
617 	/* Result */
618 	return (TRUE);
619 }
620 
621 /*
622  * Set "p_ptr->prob_travel", notice observable changes
623  */
set_prob_travel(int Ind,int v)624 bool set_prob_travel(int Ind, int v) {
625 	player_type *p_ptr = Players[Ind];
626 	bool notice = FALSE;
627 
628 	/* Hack -- Force good values */
629 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
630 
631 	/* Open */
632 	if (v) {
633 		if (!p_ptr->prob_travel) {
634 			msg_print(Ind, "You feel instable !");
635 			notice = TRUE;
636 		}
637 	}
638 
639 	/* Shut */
640 	else {
641 		if (p_ptr->prob_travel) {
642 			msg_print(Ind, "You feel more stable.");
643 			notice = TRUE;
644 		}
645 	}
646 
647 	/* Use the value */
648 	p_ptr->prob_travel = v;
649 
650 	/* Nothing to notice */
651 	if (!notice) return (FALSE);
652 
653 	/* Disturb */
654 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
655 
656 	/* Recalculate boni */
657 	p_ptr->update |= (PU_BONUS);
658 
659 	/* Handle stuff */
660 	handle_stuff(Ind);
661 
662 	/* Result */
663 	return (TRUE);
664 }
665 
666 /*
667  * Set "p_ptr->brand", notice observable changes
668  */
set_brand(int Ind,int v,int t,int p)669 bool set_brand(int Ind, int v, int t, int p) {
670 	player_type *p_ptr = Players[Ind];
671 	bool notice = FALSE, plural;
672 	char weapons[20];
673 
674 	if (p_ptr->inventory[INVEN_WIELD].k_idx && /* dual-wield */
675 	    (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) {
676 		strcpy(weapons, "\377wYour weapons");
677 		plural = TRUE;
678 	} else if (p_ptr->inventory[INVEN_WIELD].k_idx ||
679 	    (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) {
680 		strcpy(weapons, "\377wYour weapon");
681 		plural = FALSE;
682 	} else {
683 		if (v) msg_print(Ind, "You are not wielding any melee weapons to brand."); /* failure */
684 		else { /* Shut */
685 			p_ptr->brand = 0;
686 			p_ptr->brand_t = 0;
687 			p_ptr->brand_d = 0;
688 		}
689 		return FALSE; /* don't notice anything */
690 	}
691 
692 	/* Hack -- Force good values */
693 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
694 
695 	/* Open */
696 	if (v) {
697 		if (!p_ptr->brand &&
698 		    (p_ptr->inventory[INVEN_WIELD].k_idx || /* dual-wield..*/
699 		    (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD))) {
700 			switch (t) {
701 			case BRAND_ELEC:
702 			case BRAND_BALL_ELEC:
703 				if (plural) msg_format(Ind, "%s sparkle with lightning!", weapons);
704 				else msg_format(Ind, "%s sparkles with lightning!", weapons);
705 				break;
706 			case BRAND_BALL_COLD:
707 			case BRAND_COLD:
708 				if (plural) msg_format(Ind, "%s freeze!", weapons);
709 				else msg_format(Ind, "%s freezes!", weapons);
710 				break;
711 			case BRAND_BALL_FIRE:
712 			case BRAND_FIRE:
713 				if (plural) msg_format(Ind, "%s burn!", weapons);
714 				else msg_format(Ind, "%s burns!", weapons);
715 				break;
716 			case BRAND_BALL_ACID:
717 			case BRAND_ACID:
718 				if (plural) msg_format(Ind, "%s drip acid!", weapons);
719 				else msg_format(Ind, "%s drips acid!", weapons);
720 				break;
721 			case BRAND_POIS:
722 				if (plural) msg_format(Ind, "%s are covered with venom!", weapons);
723 				else msg_format(Ind, "%s is covered with venom!", weapons);
724 				break;
725 			case BRAND_BASE:
726 				if (plural) msg_format(Ind, "%s glow in many colours!", weapons);
727 				else msg_format(Ind, "%s glows in many colours!", weapons);
728 				break;
729 			case BRAND_CHAO:
730 				if (plural) msg_format(Ind, "%s seem to twist and warp!", weapons); //used experimentally
731 				else msg_format(Ind, "%s seems to twist and warp!", weapons); //used experimentally
732 				break;
733 			case BRAND_VORP:
734 				if (plural) msg_format(Ind, "%s sharpen!", weapons); //not used
735 				else msg_format(Ind, "%s sharpens!", weapons); //not used
736 				break;
737 			case BRAND_BALL_SOUN:
738 				if (plural) msg_format(Ind, "%s vibrate!", weapons); //not used
739 				else msg_format(Ind, "%s vibrates!", weapons); //not used
740 				break;
741 			}
742 			notice = TRUE;
743 		}
744 	}
745 
746 	/* Shut */
747 	else {
748 		if (p_ptr->brand) {
749 			if (plural) msg_print(Ind, "\377oThe branding magic on your weapons ceases again.");
750 			else msg_print(Ind, "\377oThe branding magic on your weapon ceases again.");
751 			notice = TRUE;
752 			t = 0;
753 			p = 0;
754 		}
755 	}
756 
757 	/* Use the value */
758 	p_ptr->brand = v;
759 	p_ptr->brand_t = t;
760 	p_ptr->brand_d = p;
761 
762 
763 	/* Nothing to notice */
764 	if (!notice) return (FALSE);
765 
766 	/* Disturb */
767 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
768 
769 	/* Recalculate boni */
770 	p_ptr->update |= (PU_BONUS | PU_MONSTERS);
771 
772 	/* Handle stuff */
773 	handle_stuff(Ind);
774 
775 	/* Result */
776 	return (TRUE);
777 }
778 
779 /*
780  * Set "p_ptr->bow_brand_xxx", notice observable changes
781  */
set_bow_brand(int Ind,int v,int t,int p)782 bool set_bow_brand(int Ind, int v, int t, int p) {
783 	player_type *p_ptr = Players[Ind];
784 	bool notice = FALSE;
785 
786 	if (!p_ptr->inventory[INVEN_AMMO].k_idx) {
787 		if (v) msg_print(Ind, "Your quiver does not hold any ammunition to brand."); /* failure */
788 		else { /* Shut */
789 			p_ptr->bow_brand = 0;
790 			p_ptr->bow_brand_t = 0;
791 			p_ptr->bow_brand_d = 0;
792 		}
793 		return FALSE; /* don't notice anything */
794 	}
795 
796 	/* Hack -- Force good values */
797 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
798 
799 	/* Open */
800 	if (v) {
801 		if (!p_ptr->bow_brand) {
802 			switch (t) {
803 			case BRAND_ELEC:
804 			case BRAND_BALL_ELEC:
805 				msg_print(Ind, "\377oYour ammunition sparkles with lightnings!");
806 				break;
807 			case BRAND_BALL_COLD:
808 			case BRAND_COLD:
809 				msg_print(Ind, "\377oYour ammunition freezes!");
810 				break;
811 			case BRAND_BALL_FIRE:
812 			case BRAND_FIRE:
813 				msg_print(Ind, "\377oYour ammunition burns!");
814 				break;
815 			case BRAND_BALL_ACID:
816 			case BRAND_ACID:
817 				msg_print(Ind, "\377oYour ammunition drips acid!");
818 				break;
819 			case BRAND_POIS:
820 				msg_print(Ind, "\377oYour ammunition is covered with venom!");
821 				break;
822 			case BRAND_BASE:
823 				msg_print(Ind, "\377oYour ammunition glows in many colours!");
824 				break;
825 			case BRAND_CHAO:
826 				msg_print(Ind, "\377oYour ammunition seems to twist and warp!");
827 				break;
828 			case BRAND_VORP:
829 				msg_print(Ind, "\377oYour ammunition sharpens!");
830 				break;
831 			case BRAND_BALL_SOUN:
832 				msg_print(Ind, "\377oYour ammunition vibrates!");
833 				break;
834 			}
835 			notice = TRUE;
836 		}
837 	}
838 
839 	/* Shut */
840 	else {
841 		if (p_ptr->bow_brand) {
842 			msg_print(Ind, "\377oThe branding magic on your ammunition ceases again.");
843 			notice = TRUE;
844 			t = 0;
845 			p = 0;
846 		}
847 	}
848 
849 	/* Use the value */
850 	p_ptr->bow_brand = v;
851 	p_ptr->bow_brand_t = t;
852 	p_ptr->bow_brand_d = p;
853 
854 
855 	/* Nothing to notice */
856 	if (!notice) return (FALSE);
857 
858 	/* Disturb */
859 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
860 
861 	/* Recalculate boni */
862 	p_ptr->update |= (PU_BONUS | PU_MONSTERS);
863 
864 	/* Handle stuff */
865 	handle_stuff(Ind);
866 
867 	/* Result */
868 	return (TRUE);
869 }
870 
871 
872 /*
873  * Set "p_ptr->tim_mimic", notice observable changes
874  */
set_mimic(int Ind,int v,int p)875 bool set_mimic(int Ind, int v, int p) {
876 	player_type *p_ptr = Players[Ind];
877 	bool notice = FALSE;
878 
879 	/* force good values */
880 	if (v < 0) v = 0;
881 
882 	/* Open */
883 	if (v) {
884 		if (!p_ptr->tim_mimic) {
885 			msg_print(Ind, "Your image changes!");
886 			notice = TRUE;
887 		} else if (p_ptr->tim_mimic > 100 && v <= 100) {
888 			msg_print(Ind, "\376\377LThe magical force stabilizing your form starts to fade...");
889 		}
890 	}
891 
892 	/* Shut */
893 	else {
894 		if (p_ptr->tim_mimic && p_ptr->body_monster == p_ptr->tim_mimic_what) {
895 			msg_print(Ind, "\376\377LYour image changes back to normality.");
896 			do_mimic_change(Ind, 0, TRUE);
897 			notice = TRUE;
898 		}
899 	}
900 
901 	/* Use the value */
902 	p_ptr->tim_mimic = v;
903 
904 #if 0 /* once you might have mimicked other classes, now we will use it for polymorph rings! */
905 	/* Enforce good values */
906 	if (p < 0) p = 0;
907 	if (p >= MAX_CLASS) p = MAX_CLASS - 1;
908 	p_ptr->tim_mimic_what = p;
909 #endif
910 
911 	/* Nothing to notice */
912 	if (!notice) return (FALSE);
913 
914 	/* Disturb */
915 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
916 
917 	/* Recalculate boni */
918 	p_ptr->update |= (PU_BONUS | PU_MONSTERS);
919 
920 	/* Handle stuff */
921 	handle_stuff(Ind);
922 
923 	/* Result */
924 	return (TRUE);
925 }
926 
927 /*
928  * Set "p_ptr->tim_manashield", notice observable changes
929  */
set_tim_manashield(int Ind,int v)930 bool set_tim_manashield(int Ind, int v) {
931 	player_type *p_ptr = Players[Ind];
932 	bool notice = FALSE;
933 
934 	/* Hack -- Force good values */
935 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
936 
937 	/* Open */
938 	if (v) {
939 		if (!p_ptr->tim_manashield) {
940 			msg_print(Ind, "\376\377wA purple shimmering shield forms around your body!");
941 			notice = TRUE;
942 		} else if (p_ptr->tim_manashield > 15 && v <= 15) {
943 			msg_print(Ind, "\376\377vThe disruption shield starts to flicker and fade...");
944 		}
945 	}
946 
947 	/* Shut */
948 	else {
949 		if (p_ptr->tim_manashield) {
950 			msg_print(Ind, "\376\377vThe disruption shield fades away.");
951 			notice = TRUE;
952 		}
953 	}
954 
955 	/* Use the value */
956 	p_ptr->tim_manashield = v;
957 
958 	/* Nothing to notice */
959 	if (!notice) return (FALSE);
960 
961 	/* Disturb */
962 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
963 
964 	/* Recalculate boni */
965 	p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA);
966 
967 	/* update so everyone sees the colour animation */
968 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
969 
970 	/* Handle stuff */
971 	handle_stuff(Ind);
972 
973 	/* Result */
974 	return (TRUE);
975 }
976 
977 /*
978  * Set "p_ptr->tim_traps", notice observable changes
979  */
set_tim_traps(int Ind,int v)980 bool set_tim_traps(int Ind, int v) {
981 	player_type *p_ptr = Players[Ind];
982 	bool notice = FALSE;
983 
984 	/* Hack -- Force good values */
985 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
986 
987 	/* Open */
988 	if (v) {
989 		if (!p_ptr->tim_traps) {
990 			msg_print(Ind, "You can avoid all the traps !");
991 			notice = TRUE;
992 		}
993 	}
994 
995 	/* Shut */
996 	else {
997 		if (p_ptr->tim_traps) {
998 			msg_print(Ind, "You should worry about traps again.");
999 			notice = TRUE;
1000 		}
1001 	}
1002 
1003 	/* Use the value */
1004 	p_ptr->tim_traps = v;
1005 
1006 	/* Nothing to notice */
1007 	if (!notice) return (FALSE);
1008 
1009 	/* Disturb */
1010 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1011 
1012 	/* Recalculate boni */
1013 	p_ptr->update |= (PU_BONUS);
1014 
1015 	/* Handle stuff */
1016 	handle_stuff(Ind);
1017 
1018 	/* Result */
1019 	return (TRUE);
1020 }
1021 
1022 /*
1023  * Set "p_ptr->tim_invis", notice observable changes
1024  */
set_invis(int Ind,int v,int p)1025 bool set_invis(int Ind, int v, int p) {
1026 	player_type *p_ptr = Players[Ind];
1027 	bool notice = FALSE;
1028 
1029 	/* Hack -- Force good values */
1030 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1031 
1032 	/* Open */
1033 	if (v) {
1034 		if (!p_ptr->tim_invisibility && !p_ptr->invis) {
1035 			msg_format_near(Ind, "%s fades in the shadows!", p_ptr->name);
1036 			msg_print(Ind, "You fade in the shadow!");
1037 			notice = TRUE;
1038 		}
1039 	}
1040 
1041 	/* Shut */
1042 	else {
1043 		if (p_ptr->tim_invisibility && !p_ptr->invis) {
1044 			msg_format_near(Ind, "The shadows enveloping %s disipate.", p_ptr->name);
1045 			msg_print(Ind, "The shadows enveloping you disipate.");
1046 			notice = TRUE;
1047 		}
1048 		p = 0;
1049 	}
1050 
1051 	/* Use the value */
1052 	p_ptr->tim_invisibility = v;
1053 	p_ptr->tim_invis_power2 = p;
1054 
1055 	/* Nothing to notice */
1056 	if (!notice) return (FALSE);
1057 
1058 	/* Disturb */
1059 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1060 
1061 	/* Recalculate boni */
1062 	p_ptr->update |= (PU_BONUS | PU_MONSTERS);
1063 
1064 	/* Handle stuff */
1065 	handle_stuff(Ind);
1066 
1067 	/* Result */
1068 	return (TRUE);
1069 }
1070 
1071 /*
1072  * Set "p_ptr->fury", notice observable changes
1073  */
set_fury(int Ind,int v)1074 bool set_fury(int Ind, int v) {
1075 	player_type *p_ptr = Players[Ind];
1076 	bool notice = FALSE;
1077 
1078 	/* Hack -- Force good values */
1079 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1080 
1081 	/* Open */
1082 	if (v) {
1083 		if (!p_ptr->fury) {
1084 			msg_print(Ind, "You grow a fury!");
1085 			notice = TRUE;
1086 		}
1087 	}
1088 
1089 	/* Shut */
1090 	else {
1091 		if (p_ptr->fury) {
1092 			msg_print(Ind, "The fury stops.");
1093 			notice = TRUE;
1094 		}
1095 	}
1096 
1097 	/* Use the value */
1098 	p_ptr->fury = v;
1099 
1100 	/* Nothing to notice */
1101 	if (!notice) return (FALSE);
1102 
1103 	/* Disturb */
1104 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1105 
1106 	/* Recalculate boni + hit points */
1107 	p_ptr->update |= (PU_BONUS | PU_HP);
1108 
1109 	/* Handle stuff */
1110 	handle_stuff(Ind);
1111 
1112 	/* Result */
1113 	return (TRUE);
1114 }
1115 
1116 
1117 /*
1118  * Set "p_ptr->tim_meditation", notice observable changes
1119  */
set_tim_meditation(int Ind,int v)1120 bool set_tim_meditation(int Ind, int v) {
1121 	player_type *p_ptr = Players[Ind];
1122 	bool notice = FALSE;
1123 
1124 	/* Hack -- Force good values */
1125 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1126 
1127 	/* Open */
1128 	if (v) {
1129 		if (!p_ptr->tim_meditation) {
1130 			msg_format_near(Ind, "%s starts a calm meditation!", p_ptr->name);
1131 			msg_print(Ind, "You start a calm meditation!");
1132 			notice = TRUE;
1133 		}
1134 	}
1135 
1136 	/* Shut */
1137 	else {
1138 		if (p_ptr->tim_meditation) {
1139 			msg_format_near(Ind, "%s stops meditating.", p_ptr->name);
1140 			msg_print(Ind, "You stop your meditation.");
1141 			notice = TRUE;
1142 		}
1143 	}
1144 
1145 	/* Use the value */
1146 	p_ptr->tim_meditation = v;
1147 
1148 	/* Nothing to notice */
1149 	if (!notice) return (FALSE);
1150 
1151 	/* Disturb */
1152 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1153 
1154 	/* Recalculate boni */
1155 	p_ptr->update |= (PU_HP | PU_MANA);
1156 
1157 	/* Handle stuff */
1158 	handle_stuff(Ind);
1159 
1160 	/* Result */
1161 	return (TRUE);
1162 }
1163 
1164 /*
1165  * Set "p_ptr->tim_wraith", notice observable changes
1166  */
set_tim_wraith(int Ind,int v)1167 bool set_tim_wraith(int Ind, int v) {
1168 	player_type *p_ptr = Players[Ind];
1169 	bool notice = FALSE;
1170 	cave_type **zcave;
1171 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
1172 	if (!(zcave = getcave(&p_ptr->wpos))) return FALSE;
1173 
1174 	/* Hack -- Force good values */
1175 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1176 
1177 	/* Open */
1178 	if (v) {
1179 		if (!p_ptr->tim_wraith) {
1180 			if ((zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) ||
1181 			    (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_MAGIC)))
1182 			{
1183 				msg_print(Ind, "You feel different for a moment");
1184 				v = 0;
1185 			} else {
1186 				msg_format_near(Ind, "%s turns into a wraith!", p_ptr->name);
1187 				msg_print(Ind, "You turn into a wraith!");
1188 				notice = TRUE;
1189 
1190 				p_ptr->wraith_in_wall = TRUE;
1191 			}
1192 		}
1193 #if 0	// I can't remember what was it for..
1194 		// but for sure it's wrong
1195 //it was probably for the old hack to prevent wraithing in/around town and breaking into houses that way - C. Blue
1196 		else if(!p_ptr->wpos.wz && cave_floor_bold(zcave, p_ptr->py, p_ptr->px))
1197 			return(FALSE);
1198 #endif	// 0
1199 	}
1200 
1201 	/* Shut */
1202 	else {
1203 		if (p_ptr->tim_wraith) {
1204 			/* In town it only runs out if you are not on a wall
1205 			 * To prevent breaking into houses */
1206 			/* important! check for illegal spaces */
1207 			cave_type **zcave;
1208 			zcave = getcave(&p_ptr->wpos);
1209 
1210 			if (zcave && in_bounds(p_ptr->py, p_ptr->px)) {
1211 				/* if a worn item grants wraith form, don't let it run out */
1212 				u32b f1, f2, f3, f4, f5, f6, esp;
1213 				object_type *o_ptr;
1214 				int i;
1215 				/* Scan the usable inventory */
1216 				for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) {
1217 					o_ptr = &p_ptr->inventory[i];
1218 					/* Skip missing items */
1219 					if (!o_ptr->k_idx) continue;
1220 					/* Extract the item flags */
1221 					object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1222 					if (f3 & (TR3_WRAITH)) {
1223 					        //p_ptr->wraith_form = TRUE;
1224 					        v = 30000;
1225 					}
1226 				}
1227 				if (v != 30000) {
1228 					msg_format_near(Ind, "%s loses %s wraith powers.", p_ptr->name, p_ptr->male ? "his":"her");
1229 					msg_print(Ind, "You lose your wraith powers.");
1230 					notice = TRUE;
1231 
1232 					/* That will hopefully prevent game hinging when loading */
1233 					if (cave_floor_bold(zcave, p_ptr->py, p_ptr->px)) p_ptr->wraith_in_wall = FALSE;
1234 				}
1235 			}
1236 			else v = 1;
1237 		}
1238 	}
1239 
1240 	/* Use the value */
1241 	p_ptr->tim_wraith = v;
1242 
1243 	/* Nothing to notice */
1244 	if (!notice) return (FALSE);
1245 
1246 	/* Disturb */
1247 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1248 
1249 	/* Recalculate boni */
1250 	p_ptr->update |= (PU_BONUS);
1251 
1252 	/* Handle stuff */
1253 	handle_stuff(Ind);
1254 
1255 	/* Result */
1256 	return (TRUE);
1257 }
1258 
1259 /*
1260  * Set "p_ptr->blind", notice observable changes
1261  *
1262  * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to
1263  * memorize any terrain features which suddenly become "visible".
1264  * Note that blindness is currently the only thing which can affect
1265  * "player_can_see_bold()".
1266  */
set_blind(int Ind,int v)1267 bool set_blind(int Ind, int v) {
1268 	player_type *p_ptr = Players[Ind];
1269 	bool notice = FALSE;
1270 
1271 	if (p_ptr->martyr && v) return FALSE;
1272 
1273 	/* the admin wizard can not be blinded */
1274 	if (p_ptr->admin_wiz) return 1;
1275 
1276 /* instead put into dungeon.c for faster recovery
1277 	if (get_skill(p_ptr, SKILL_HCURING) >= 30) v /= 2;
1278 */
1279 	/* Hack -- Force good values */
1280 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1281 
1282 	/* Open */
1283 	if (v) {
1284 		if (!p_ptr->blind) {
1285 			disturb(Ind, 1, 0); /* stop running and searching */
1286 			msg_format_near(Ind, "%s gropes around blindly!", p_ptr->name);
1287 			msg_print(Ind, "You are blind!");
1288 			notice = TRUE;
1289 		}
1290 
1291 		break_shadow_running(Ind);
1292 	}
1293 
1294 	/* Shut */
1295 	else {
1296 		if (p_ptr->blind) {
1297 			msg_format_near(Ind, "%s can see again.", p_ptr->name);
1298 			msg_print(Ind, "You can see again.");
1299 			notice = TRUE;
1300 		}
1301 	}
1302 
1303 	/* Use the value */
1304 	p_ptr->blind = v;
1305 
1306 	/* Nothing to notice */
1307 	if (!notice) return (FALSE);
1308 
1309 	/* Disturb */
1310 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1311 
1312 	/* Forget stuff */
1313 	p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
1314 
1315 	/* Update stuff */
1316 	p_ptr->update |= (PU_VIEW | PU_LITE | PU_BONUS);
1317 
1318 	/* Update the monsters */
1319 	p_ptr->update |= (PU_MONSTERS);
1320 
1321 	/* Redraw map */
1322 	p_ptr->redraw |= (PR_MAP);
1323 
1324 	/* Redraw the "blind" */
1325 	p_ptr->redraw |= (PR_BLIND);
1326 
1327 	/* Window stuff */
1328 	p_ptr->window |= (PW_OVERHEAD);
1329 
1330 	/* Handle stuff */
1331 	handle_stuff(Ind);
1332 
1333 	/* Result */
1334 	return (TRUE);
1335 }
1336 
1337 
1338 /*
1339  * Set "p_ptr->confused", notice observable changes
1340  */
set_confused(int Ind,int v)1341 bool set_confused(int Ind, int v) {
1342 	player_type *p_ptr = Players[Ind];
1343 	bool notice = FALSE;
1344 
1345 	if (p_ptr->martyr && v) return FALSE;
1346 
1347 	/* Hack -- Force good values */
1348 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1349 
1350 	if (get_skill(p_ptr, SKILL_MIND) >= 30) v /= 2;
1351 
1352 	/* Open */
1353 	if (v) {
1354 		if (!p_ptr->confused) {
1355 			disturb(Ind, 1, 0); /* stop running and searching */
1356 			msg_format_near(Ind, "%s appears confused!", p_ptr->name);
1357 			msg_print(Ind, "You are confused!");
1358 			notice = TRUE;
1359 		}
1360 
1361 		break_cloaking(Ind, 0);
1362 		break_shadow_running(Ind);
1363 		stop_precision(Ind);
1364 		stop_shooting_till_kill(Ind);
1365 	}
1366 
1367 	/* Shut */
1368 	else {
1369 		if (p_ptr->confused) {
1370 			msg_format_near(Ind, "%s appears less confused now.", p_ptr->name);
1371 			msg_print(Ind, "You feel less confused now.");
1372 			notice = TRUE;
1373 		}
1374 	}
1375 
1376 	/* Use the value */
1377 	p_ptr->confused = v;
1378 
1379 	/* Nothing to notice */
1380 	if (!notice) return (FALSE);
1381 
1382 	/* Disturb */
1383 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1384 
1385 	/* Redraw the "confused" */
1386 	p_ptr->redraw |= (PR_CONFUSED);
1387 
1388 	p_ptr->update |= (PU_BONUS);
1389 
1390 	/* Handle stuff */
1391 	handle_stuff(Ind);
1392 
1393 	/* Result */
1394 	return (TRUE);
1395 }
1396 
1397 #ifdef ARCADE_SERVER
set_pushed(int Ind,int dir)1398 void set_pushed(int Ind, int dir) {
1399 	player_type *p_ptr = Players[Ind];
1400 	p_ptr->pushed = 20;
1401 	p_ptr->pushdir = dir;
1402 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1403 	handle_stuff(Ind);
1404 	return;
1405 }
1406 #endif
1407 
1408 /*
1409  * Set "p_ptr->poisoned", notice observable changes
1410  */
set_poisoned(int Ind,int v,int attacker)1411 bool set_poisoned(int Ind, int v, int attacker) {
1412 	player_type *p_ptr = Players[Ind];
1413 	bool notice = FALSE;
1414 
1415 	if (p_ptr->martyr && v) return FALSE;
1416 
1417 	/* Hack -- Force good values */
1418 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1419 
1420 /* instead put into dungeon.c for faster recovery
1421 	if (get_skill(p_ptr, SKILL_HCURING) >= 30) v /= 2;
1422 */
1423 	/* Open */
1424 	if (v) {
1425 		if (!p_ptr->poisoned) {
1426 			msg_print(Ind, "You are poisoned!");
1427 			notice = TRUE;
1428 
1429 			/* Remember who did it - mikaelh */
1430 			p_ptr->poisoned_attacker = attacker;
1431 		}
1432 	}
1433 
1434 	/* Shut */
1435 	else {
1436 		if (p_ptr->poisoned) {
1437 			msg_print(Ind, "You are no longer poisoned.");
1438 			notice = TRUE;
1439 
1440 			/* Forget who did it - mikaelh */
1441 			p_ptr->poisoned_attacker = 0;
1442 		}
1443 	}
1444 
1445 	/* Use the value */
1446 	p_ptr->poisoned = v;
1447 
1448 	/* Nothing to notice */
1449 	if (!notice) return (FALSE);
1450 
1451 	/* Disturb */
1452 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1453 
1454 	/* Redraw the "poisoned" */
1455 	p_ptr->redraw |= (PR_POISONED);
1456 
1457 	/* Handle stuff */
1458 	handle_stuff(Ind);
1459 
1460 	/* Result */
1461 	return (TRUE);
1462 }
1463 
1464 
1465 /*
1466  * Set "p_ptr->afraid", notice observable changes
1467  */
set_afraid(int Ind,int v)1468 bool set_afraid(int Ind, int v) {
1469 	player_type *p_ptr = Players[Ind];
1470 	bool notice = FALSE;
1471 
1472 	if (p_ptr->martyr && v) return FALSE;
1473 
1474 	/* Hack -- Force good values */
1475 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1476 
1477 	/* Open */
1478 	if (v) {
1479 		if (!p_ptr->afraid) {
1480 			msg_format_near(Ind, "%s cowers in fear!", p_ptr->name);
1481 			msg_print(Ind, "You are terrified!");
1482 			notice = TRUE;
1483 		}
1484 	}
1485 
1486 	/* Shut */
1487 	else {
1488 		if (p_ptr->afraid) {
1489 			msg_format_near(Ind, "%s appears bolder now.", p_ptr->name);
1490 			msg_print(Ind, "You feel bolder now.");
1491 			notice = TRUE;
1492 		}
1493 	}
1494 
1495 	/* Use the value */
1496 	p_ptr->afraid = v;
1497 
1498 	/* Nothing to notice */
1499 	if (!notice) return (FALSE);
1500 
1501 	/* Disturb */
1502 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1503 
1504 	/* Redraw the "afraid" */
1505 	p_ptr->redraw |= (PR_AFRAID);
1506 
1507 	/* Handle stuff */
1508 	handle_stuff(Ind);
1509 
1510 	/* Result */
1511 	return (TRUE);
1512 }
1513 
1514 
1515 /*
1516  * Set "p_ptr->paralyzed", notice observable changes
1517  */
set_paralyzed(int Ind,int v)1518 bool set_paralyzed(int Ind, int v) {
1519 	player_type *p_ptr = Players[Ind];
1520 	bool notice = FALSE;
1521 
1522 	if (p_ptr->martyr && v) return FALSE;
1523 
1524 	/* Hack -- Force good values */
1525 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1526 
1527 	/* Open */
1528 	if (v) {
1529 		if (!p_ptr->paralyzed) {
1530 			msg_format_near(Ind, "%s becomes rigid!", p_ptr->name);
1531 			msg_print(Ind, "You are paralyzed!");
1532 			notice = TRUE;
1533 			s_printf("%s EFFECT: Paralyzed %s.\n", showtime(), p_ptr->name);
1534 		}
1535 	}
1536 
1537 	/* Shut */
1538 	else {
1539 		if (p_ptr->paralyzed) {
1540 			msg_format_near(Ind, "%s can move again.", p_ptr->name);
1541 			msg_print(Ind, "You can move again.");
1542 			notice = TRUE;
1543 		}
1544 	}
1545 
1546 	/* Use the value */
1547 	p_ptr->paralyzed = v;
1548 
1549 	/* Nothing to notice */
1550 	if (!notice) return (FALSE);
1551 
1552 	/* Disturb */
1553 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1554 
1555 	/* Redraw the state */
1556 	p_ptr->redraw |= (PR_STATE);
1557 
1558 	p_ptr->update |= (PU_BONUS);
1559 
1560 	/* Handle stuff */
1561 	handle_stuff(Ind);
1562 
1563 	/* Result */
1564 	return (TRUE);
1565 }
1566 
1567 
1568 /*
1569  * Set "p_ptr->image", notice observable changes
1570  *
1571  * Note that we must redraw the map when hallucination changes.
1572  */
set_image(int Ind,int v)1573 bool set_image(int Ind, int v) {
1574 	player_type *p_ptr = Players[Ind];
1575 	bool notice = FALSE;
1576 
1577 	/* Hack -- Force good values */
1578 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1579 
1580 /* instead put into dungeon.c for faster recovery
1581 	if (get_skill(p_ptr, SKILL_MIND) >= 30) v /= 2;
1582 	if (get_skill(p_ptr, SKILL_HCURING) >= 50) v /= 2;
1583 */
1584 	/* Open */
1585 	if (v) {
1586 		if (!p_ptr->image) {
1587 			msg_format_near(Ind, "%s has been drugged.", p_ptr->name);
1588 			msg_print(Ind, "You feel drugged!");
1589 			notice = TRUE;
1590 		}
1591 	}
1592 
1593 	/* Shut */
1594 	else {
1595 		if (p_ptr->image) {
1596 			msg_format_near(Ind, "%s has recovered from %s drug induced stupor.", p_ptr->name, p_ptr->male ? "his" : "her");
1597 			msg_print(Ind, "You can see clearly again.");
1598 			notice = TRUE;
1599 		}
1600 	}
1601 
1602 	/* Use the value */
1603 	p_ptr->image = v;
1604 
1605 	/* Nothing to notice */
1606 	if (!notice) return (FALSE);
1607 
1608 	/* Disturb */
1609 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1610 
1611 	/* Redraw map */
1612 	p_ptr->redraw |= (PR_MAP);
1613 
1614 	/* Update monsters */
1615 	p_ptr->update |= (PU_MONSTERS);
1616 
1617 	/* Window stuff */
1618 	p_ptr->window |= (PW_OVERHEAD);
1619 
1620 	/* Handle stuff */
1621 	handle_stuff(Ind);
1622 
1623 	/* Result */
1624 	return (TRUE);
1625 }
1626 
1627 
1628 /*
1629  * Set "p_ptr->fast", notice observable changes
1630  */
set_fast(int Ind,int v,int p)1631 bool set_fast(int Ind, int v, int p) {
1632 	player_type *p_ptr = Players[Ind];
1633 	bool notice = FALSE;
1634 
1635 	if (p_ptr->mode & MODE_PVP) return(FALSE);
1636 
1637 	/* Hack -- Force good values */
1638 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1639 
1640 	/* Open */
1641 	if (v) {
1642 		if (!p_ptr->fast) {
1643 			if (p > 0) {
1644 				msg_format_near(Ind, "%s begins moving faster!", p_ptr->name);
1645 				msg_print(Ind, "You feel yourself moving faster!");
1646 			} else {
1647 				msg_format_near(Ind, "%s moves slower!", p_ptr->name);
1648 				msg_print(Ind, "You feel yourself moving slower!");
1649 			}
1650 			notice = TRUE;
1651 		}
1652 	}
1653 
1654 	/* Shut */
1655 	else {
1656 		if (p_ptr->fast) {
1657 			if (p > 0) {
1658 				msg_format_near(Ind, "%s slows down.", p_ptr->name);
1659 				msg_print(Ind, "You feel yourself slow down.");
1660 			} else {
1661 				msg_format_near(Ind, "%s moves faster.", p_ptr->name);
1662 				msg_print(Ind, "You feel yourself moving faster");
1663 			}
1664 			notice = TRUE;
1665 		}
1666 	}
1667 
1668 	/* Use the value */
1669 	p_ptr->fast = v;
1670 	p_ptr->fast_mod = p;
1671 
1672 	/* Nothing to notice */
1673 	if (!notice) return (FALSE);
1674 
1675 	/* Disturb */
1676 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1677 
1678 	/* Recalculate boni */
1679 	p_ptr->update |= (PU_BONUS);
1680 
1681 	/* Handle stuff */
1682 	handle_stuff(Ind);
1683 
1684 	/* Result */
1685 	return (TRUE);
1686 }
1687 
1688 
1689 /*
1690  * Set "p_ptr->slow", notice observable changes
1691  */
set_slow(int Ind,int v)1692 bool set_slow(int Ind, int v) {
1693 	player_type *p_ptr = Players[Ind];
1694 	bool notice = FALSE;
1695 
1696 	if (p_ptr->martyr && v) return FALSE;
1697 
1698 	/* Hack -- Force good values */
1699 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1700 
1701 	/* Open */
1702 	if (v) {
1703 		if (!p_ptr->slow) {
1704 			msg_format_near(Ind, "%s begins moving slower!", p_ptr->name);
1705 			msg_print(Ind, "You feel yourself moving slower!");
1706 			notice = TRUE;
1707 			s_printf("%s EFFECT: Slowed %s.\n", showtime(), p_ptr->name);
1708 		}
1709 	}
1710 
1711 	/* Shut */
1712 	else {
1713 		if (p_ptr->slow) {
1714 			msg_format_near(Ind, "%s speeds up.", p_ptr->name);
1715 			msg_print(Ind, "You feel yourself speed up.");
1716 			notice = TRUE;
1717 		}
1718 	}
1719 
1720 	/* Use the value */
1721 	p_ptr->slow = v;
1722 
1723 	/* Nothing to notice */
1724 	if (!notice) return (FALSE);
1725 
1726 	/* Disturb */
1727 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1728 
1729 	/* Recalculate boni */
1730 	p_ptr->update |= (PU_BONUS);
1731 
1732 	/* Handle stuff */
1733 	handle_stuff(Ind);
1734 
1735 	/* Result */
1736 	return (TRUE);
1737 }
1738 
1739 
1740 /*
1741  * Set "p_ptr->shield", notice observable changes
1742  */
set_shield(int Ind,int v,int p,s16b o,s16b d1,s16b d2)1743 bool set_shield(int Ind, int v, int p, s16b o, s16b d1, s16b d2) {
1744 	player_type *p_ptr = Players[Ind];
1745 	bool notice = FALSE;
1746 
1747 	/* Hack -- Force good values */
1748 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1749 
1750 	/* Open */
1751 	if (v) {
1752 		if (!p_ptr->shield) {
1753 			msg_print(Ind, "A mystic shield forms around your body!");
1754 			notice = TRUE;
1755 		}
1756 	}
1757 
1758 	/* Shut */
1759 	else {
1760 		if (p_ptr->shield) {
1761 			msg_print(Ind, "Your mystic shield crumbles away.");
1762 			notice = TRUE;
1763 		}
1764 	}
1765 
1766 
1767 	/* Use the value */
1768 	p_ptr->shield = v;
1769 	if (p_ptr->shield_power != p) notice = TRUE;
1770 	p_ptr->shield_power = p;
1771 	p_ptr->shield_opt = o;
1772 	p_ptr->shield_power_opt = d1;
1773 	p_ptr->shield_power_opt2 = d2;
1774 
1775 	/* Nothing to notice */
1776 	if (!notice) return (FALSE);
1777 
1778 	/* Disturb */
1779 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1780 
1781 	/* Recalculate boni */
1782 	p_ptr->update |= (PU_BONUS);
1783 
1784 	/* Handle stuff */
1785 	handle_stuff(Ind);
1786 
1787 	/* Result */
1788 	return (TRUE);
1789 }
1790 
1791 /*
1792  * Set "p_ptr->blessed", notice observable changes
1793  */
set_blessed(int Ind,int v)1794 bool set_blessed(int Ind, int v) {
1795 	player_type *p_ptr = Players[Ind];
1796 	bool notice = FALSE;
1797 
1798 	/* Hack -- Force good values */
1799 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1800 
1801 	/* Open */
1802 	if (v) {
1803 		if (!p_ptr->blessed) {
1804 			msg_format_near(Ind, "%s has become righteous.", p_ptr->name);
1805 			msg_print(Ind, "You feel righteous!");
1806 			notice = TRUE;
1807 		}
1808 	}
1809 
1810 	/* Shut */
1811 	else {
1812 		if (p_ptr->blessed) {
1813 			msg_format_near(Ind, "%s has become less righteous.", p_ptr->name);
1814 			msg_print(Ind, "The prayer has expired.");
1815 			notice = TRUE;
1816 			p_ptr->blessed_power = 0;
1817 		}
1818 	}
1819 
1820 	/* Use the value */
1821 	p_ptr->blessed = v;
1822 
1823 	/* Nothing to notice */
1824 	if (!notice) return (FALSE);
1825 
1826 	/* Disturb */
1827 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1828 
1829 	/* Recalculate boni */
1830 	p_ptr->update |= (PU_BONUS);
1831 
1832 	/* Handle stuff */
1833 	handle_stuff(Ind);
1834 
1835 	/* Result */
1836 	return (TRUE);
1837 }
1838 
set_res_fear(int Ind,int v)1839 bool set_res_fear(int Ind, int v) {
1840 	player_type *p_ptr = Players[Ind];
1841 	bool notice = FALSE;
1842 
1843 	/* Hack -- Force good values */
1844 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1845 
1846 	/* Open */
1847 	if (v) {
1848 		if (!p_ptr->res_fear_temp) {
1849 			notice = TRUE;
1850 		}
1851 	}
1852 
1853 	/* Shut */
1854 	else {
1855 		if (p_ptr->res_fear_temp) {
1856 			notice = TRUE;
1857 		}
1858 	}
1859 
1860 	/* Use the value */
1861 	p_ptr->res_fear_temp = v;
1862 
1863 	/* Nothing to notice */
1864 	if (!notice) return (FALSE);
1865 
1866 	/* Disturb */
1867 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1868 
1869 	/* Recalculate boni */
1870 	p_ptr->update |= (PU_BONUS);
1871 
1872 	/* Handle stuff */
1873 	handle_stuff(Ind);
1874 
1875 	/* Result */
1876 	return (TRUE);
1877 }
1878 
1879 /*
1880  * Set "p_ptr->hero", notice observable changes
1881  */
set_hero(int Ind,int v)1882 bool set_hero(int Ind, int v) {
1883 	player_type *p_ptr = Players[Ind];
1884 	bool notice = FALSE;
1885 
1886 	/* Hack -- Force good values */
1887 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1888 
1889 	/* Open */
1890 	if (v) {
1891 		if (!p_ptr->hero) {
1892 			msg_format_near(Ind, "%s has become a hero.", p_ptr->name);
1893 			msg_print(Ind, "You feel like a hero!");
1894 			notice = TRUE;
1895 		}
1896 	}
1897 
1898 	/* Shut */
1899 	else {
1900 		if (p_ptr->hero) {
1901 			msg_format_near(Ind, "%s has become less of a hero.", p_ptr->name);
1902 			msg_print(Ind, "The heroism wears off.");
1903 			notice = TRUE;
1904 		}
1905 	}
1906 
1907 	/* Use the value */
1908 	p_ptr->hero = v;
1909 
1910 	/* Nothing to notice */
1911 	if (!notice) return (FALSE);
1912 
1913 	/* Disturb */
1914 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1915 
1916 	/* Recalculate boni & hit points */
1917 	p_ptr->update |= (PU_BONUS | PU_HP);
1918 
1919 	/* Handle stuff */
1920 	handle_stuff(Ind);
1921 
1922 	/* Result */
1923 	return (TRUE);
1924 }
1925 
1926 
1927 /*
1928  * Set "p_ptr->shero", notice observable changes
1929  */
set_shero(int Ind,int v)1930 bool set_shero(int Ind, int v) {
1931 	player_type *p_ptr = Players[Ind];
1932 	bool notice = FALSE;
1933 
1934 	/* Hack -- Force good values */
1935 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1936 
1937 	/* Open */
1938 	if (v) {
1939 		if (!p_ptr->shero) {
1940 			msg_format_near(Ind, "%s has become a killing machine.", p_ptr->name);
1941 			msg_print(Ind, "You feel like a killing machine!");
1942 			notice = TRUE;
1943 		}
1944 	}
1945 
1946 	/* Shut */
1947 	else {
1948 		if (p_ptr->shero) {
1949 			msg_format_near(Ind, "%s has returned to being a wimp.", p_ptr->name);
1950 			msg_print(Ind, "You feel less Berserk.");
1951 			notice = TRUE;
1952 		}
1953 	}
1954 
1955 	/* Use the value */
1956 	p_ptr->shero = v;
1957 
1958 	/* Nothing to notice */
1959 	if (!notice) return (FALSE);
1960 
1961 	/* Disturb */
1962 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1963 
1964 	/* Recalculate boni + hit points */
1965 	p_ptr->update |= (PU_BONUS | PU_HP);
1966 
1967 	/* Handle stuff */
1968 	handle_stuff(Ind);
1969 
1970 	/* Result */
1971 	return (TRUE);
1972 }
1973 
1974 
set_berserk(int Ind,int v)1975 bool set_berserk(int Ind, int v) {
1976 	player_type *p_ptr = Players[Ind];
1977 	bool notice = FALSE;
1978 
1979 	/* Hack -- Force good values */
1980 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1981 
1982 	/* Open */
1983 	if (v) {
1984 		if (!p_ptr->berserk) {
1985 			msg_format_near(Ind, "%s has become a killing machine.", p_ptr->name);
1986 			msg_print(Ind, "You feel like a killing machine!");
1987 			notice = TRUE;
1988 		}
1989 	}
1990 
1991 	/* Shut */
1992 	else {
1993 		if (p_ptr->berserk) {
1994 			msg_format_near(Ind, "%s has returned to being a wimp.", p_ptr->name);
1995 			msg_print(Ind, "You feel less Berserk.");
1996 			notice = TRUE;
1997 		}
1998 	}
1999 
2000 	/* Use the value */
2001 	p_ptr->berserk = v;
2002 
2003 	/* Nothing to notice */
2004 	if (!notice) return (FALSE);
2005 
2006 	/* Disturb */
2007 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2008 
2009 	/* Recalculate boni + hit points */
2010 	p_ptr->update |= (PU_BONUS | PU_HP);
2011 
2012 	/* Handle stuff */
2013 	handle_stuff(Ind);
2014 
2015 	/* Result */
2016 	return (TRUE);
2017 }
2018 
2019 
set_melee_sprint(int Ind,int v)2020 bool set_melee_sprint(int Ind, int v) {
2021 	player_type *p_ptr = Players[Ind];
2022 	bool notice = FALSE;
2023 
2024 	/* Hack -- Force good values */
2025 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2026 
2027 	/* Open */
2028 	if (v) {
2029 		if (!p_ptr->melee_sprint) {
2030 			msg_format_near(Ind, "%s starts sprinting.", p_ptr->name);
2031 			msg_print(Ind, "You start sprinting!");
2032 			notice = TRUE;
2033 		}
2034 	}
2035 
2036 	/* Shut */
2037 	else {
2038 		if (p_ptr->melee_sprint) {
2039 			msg_format_near(Ind, "%s slows down.", p_ptr->name);
2040 			msg_print(Ind, "You slow down.");
2041 			notice = TRUE;
2042 		}
2043 	}
2044 
2045 	/* Use the value */
2046 	p_ptr->melee_sprint = v;
2047 
2048 	/* Nothing to notice */
2049 	if (!notice) return (FALSE);
2050 
2051 	/* Disturb */
2052 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2053 
2054 	/* Recalculate boni */
2055 	p_ptr->update |= (PU_BONUS);
2056 
2057 	/* Recalculate hitpoints */
2058 	p_ptr->update |= (PU_HP);
2059 
2060 	/* Handle stuff */
2061 	handle_stuff(Ind);
2062 
2063 	/* Result */
2064 	return (TRUE);
2065 }
2066 
2067 
2068 /*
2069  * Set "p_ptr->protevil", notice observable changes
2070  */
set_protevil(int Ind,int v)2071 bool set_protevil(int Ind, int v) {
2072 	player_type *p_ptr = Players[Ind];
2073 	bool notice = FALSE;
2074 
2075 	/* Hack -- Force good values */
2076 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2077 
2078 	/* Open */
2079 	if (v) {
2080 		if (!p_ptr->protevil) {
2081 			msg_print(Ind, "You feel safe from evil!");
2082 			notice = TRUE;
2083 		}
2084 	}
2085 
2086 	/* Shut */
2087 	else {
2088 		if (p_ptr->protevil) {
2089 			msg_print(Ind, "You no longer feel safe from evil.");
2090 			notice = TRUE;
2091 		}
2092 	}
2093 
2094 	/* Use the value */
2095 	p_ptr->protevil = v;
2096 
2097 	/* Nothing to notice */
2098 	if (!notice) return (FALSE);
2099 
2100 	/* Disturb */
2101 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2102 
2103 	/* Handle stuff */
2104 	handle_stuff(Ind);
2105 
2106 	/* Result */
2107 	return (TRUE);
2108 }
2109 
2110 
2111 /*
2112  * Set "p_ptr->zeal", notice observable changes
2113  */
set_zeal(int Ind,int p,int v)2114 bool set_zeal(int Ind, int p, int v) {
2115 	player_type *p_ptr = Players[Ind];
2116 	bool notice = FALSE;
2117 
2118 	/* Hack -- Force good values */
2119 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2120 
2121 	/* set EA */
2122 	p_ptr->zeal_power = p;
2123 
2124 	/* Open */
2125 	if (v) {
2126 		if (!p_ptr->zeal) {
2127 			msg_print(Ind, "You heed a holy call!");
2128 			notice = TRUE;
2129 		}
2130 	}
2131 
2132 	/* Shut */
2133 	else {
2134 		if (p_ptr->zeal) {
2135 			msg_print(Ind, "The holy call fades.");
2136 			notice = TRUE;
2137 		}
2138 	}
2139 
2140 	/* Use the value */
2141 	p_ptr->zeal = v;
2142 
2143 	/* Nothing to notice */
2144 	if (!notice) return (FALSE);
2145 
2146 	/* Redraw the Blows/Round */
2147 	p_ptr->update |= PU_BONUS;
2148 
2149 	/* Disturb */
2150 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2151 
2152 	/* Handle stuff */
2153 	handle_stuff(Ind);
2154 
2155 	/* Result */
2156 	return (TRUE);
2157 }
2158 
set_martyr(int Ind,int v)2159 bool set_martyr(int Ind, int v) {
2160 	player_type *p_ptr = Players[Ind];
2161 	bool notice = FALSE;
2162 
2163 	/* Hack: Negative v means initiate martyr */
2164 	if (v < 0) {
2165 		v = -v;
2166 		p_ptr->martyr_dur = v;
2167 	}
2168 
2169 	/* Hack -- Force good values */
2170 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2171 
2172 	/* Open */
2173 	if (v) {
2174 		if (!p_ptr->martyr) {
2175 			msg_print(Ind, "\377vYou feel the heavens grant your their powers.");
2176 			hp_player_quiet(Ind, 5000, FALSE); /* fully heal */
2177 			p_ptr->martyr_timeout = 1000;
2178 			notice = TRUE;
2179 			s_printf("MARTYRDOM: %s\n", p_ptr->name);
2180 		} else {
2181 			msg_print(Ind, "\377wYou burn in holy fire!");
2182 			/* assumes that martyr starts at -15 turns! : */
2183 			p_ptr->chp = (p_ptr->mhp * p_ptr->martyr) / p_ptr->martyr_dur;
2184 			/* Update health bars */
2185 			update_health(0 - Ind);
2186 			/* Redraw */
2187 			p_ptr->redraw |= (PR_HP);
2188 
2189 		    	/* update so everyone sees the colour animation */
2190 			everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2191 		}
2192 	}
2193 
2194 	/* Shut */
2195 	else {
2196 		if (p_ptr->martyr) {
2197 			/* Increased remaining HP (from 1), to buffer environmental influences
2198 			   like nether/fire hit from the ground in the Nether Realm;
2199 			   assumes that martyr starts at -15 turns! : */
2200 //			p_ptr->chp = (p_ptr->mhp >= 30 * 15) ? 30 : p_ptr->mhp / 15;
2201 			p_ptr->chp = (p_ptr->mhp <= 30 * p_ptr->martyr_dur) ? 30 : p_ptr->mhp / p_ptr->martyr_dur;
2202     		        /* Update health bars */
2203 	                update_health(0 - Ind);
2204 	                /* Redraw */
2205 	                p_ptr->redraw |= (PR_HP);
2206 
2207 			msg_print(Ind, "\377vYou collapse as your martyrium ends!");
2208 			notice = TRUE;
2209 		}
2210 	}
2211 
2212 	/* Use the value */
2213 	p_ptr->martyr = v;
2214 
2215 	/* Nothing to notice */
2216 	if (!notice) return (FALSE);
2217 
2218 	/* Disturb */
2219 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2220 
2221     	/* update so everyone sees the colour animation */
2222 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2223 
2224 	/* Handle stuff */
2225 	handle_stuff(Ind);
2226 
2227 	/* Result */
2228 	return (TRUE);
2229 }
2230 
2231 /*
2232  * Set "p_ptr->invuln", notice observable changes
2233  */
set_invuln(int Ind,int v)2234 bool set_invuln(int Ind, int v) {
2235 	player_type *p_ptr = Players[Ind];
2236 	bool notice = FALSE;
2237 
2238 	/* Hack -- Force good values */
2239 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2240 
2241 	/* Open */
2242 	if (v) {
2243 		if (!p_ptr->invuln) {
2244 			p_ptr->invuln_dur = v;
2245 			msg_print(Ind, "\377A powerful iridescent shield forms around your body!");
2246 			notice = TRUE;
2247 		} else if (p_ptr->invuln > 5 && v <= 5) {
2248 			msg_print(Ind, "\376\377vThe invulnerability shield starts to fade...");
2249 		}
2250 	}
2251 
2252 	/* Shut */
2253 	else {
2254 		if (p_ptr->invuln &&
2255 		    p_ptr->invuln_dur >= 5) { /* avoid spam on stair-GoI */
2256 			msg_print(Ind, "\376\377vThe invulnerability shield fades away.");
2257 		}
2258 		notice = TRUE;
2259 	}
2260 
2261 	/* Use the value */
2262 	p_ptr->invuln = v;
2263 
2264 	/* Nothing to notice */
2265 	if (!notice) return (FALSE);
2266 
2267 	/* Disturb */
2268 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2269 
2270 	/* Recalculate boni */
2271 	p_ptr->update |= (PU_BONUS);
2272 
2273 	/* update so everyone sees the colour animation */
2274 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2275 
2276 	/* Handle stuff */
2277 	handle_stuff(Ind);
2278 
2279 	/* Result */
2280 	return (TRUE);
2281 }
2282 
2283 /*
2284  * Set "p_ptr->invuln", but not notice observable changes
2285  * It should be used to protect players from recall-instadeath.  - Jir -
2286  * Note: known also as 'stair-GoI' (globe of invulnerability),
2287  * supposed to shortly protect players when they enter a new level. -C. Blue
2288  */
set_invuln_short(int Ind,int v)2289 bool set_invuln_short(int Ind, int v) {
2290 	player_type *p_ptr = Players[Ind];
2291 
2292 	/* not cumulative */
2293 	if (p_ptr->invuln > v) return (FALSE);
2294 
2295 	/* Hack -- Force good values */
2296 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2297 
2298 	/* Use the value */
2299 	p_ptr->invuln = v;
2300 	p_ptr->invuln_dur = v;
2301 
2302 	/* Recalculate boni */
2303 	p_ptr->update |= (PU_BONUS);
2304 
2305 	/* Handle stuff */
2306 	handle_stuff(Ind);
2307 
2308 	/* Result (never noticeable) */
2309 	return (FALSE);
2310 }
2311 
2312 /*
2313  * Set "p_ptr->tim_invis", notice observable changes
2314  */
set_tim_invis(int Ind,int v)2315 bool set_tim_invis(int Ind, int v) {
2316 	player_type *p_ptr = Players[Ind];
2317 	bool notice = FALSE;
2318 
2319 	/* Hack -- Force good values */
2320 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2321 
2322 	/* Open */
2323 	if (v) {
2324 		if (!p_ptr->tim_invis) {
2325 			msg_print(Ind, "Your eyes feel very sensitive!");
2326 			notice = TRUE;
2327 		}
2328 	}
2329 
2330 	/* Shut */
2331 	else {
2332 		if (p_ptr->tim_invis) {
2333 			msg_print(Ind, "Your eyes feel less sensitive.");
2334 			notice = TRUE;
2335 		}
2336 	}
2337 
2338 	/* Use the value */
2339 	p_ptr->tim_invis = v;
2340 
2341 	/* Nothing to notice */
2342 	if (!notice) return (FALSE);
2343 
2344 	/* Disturb */
2345 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2346 
2347 	/* Recalculate boni */
2348 	p_ptr->update |= (PU_BONUS);
2349 
2350 	/* Update the monsters */
2351 	p_ptr->update |= (PU_MONSTERS);
2352 
2353 	/* Handle stuff */
2354 	handle_stuff(Ind);
2355 
2356 	/* Result */
2357 	return (TRUE);
2358 }
2359 
2360 
2361 /*
2362  * Set "p_ptr->tim_infra", notice observable changes
2363  */
set_tim_infra(int Ind,int v)2364 bool set_tim_infra(int Ind, int v) {
2365 	player_type *p_ptr = Players[Ind];
2366 	bool notice = FALSE;
2367 
2368 	/* Hack -- Force good values */
2369 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2370 
2371 	/* Open */
2372 	if (v) {
2373 		if (!p_ptr->tim_infra) {
2374 			msg_print(Ind, "Your eyes begin to tingle!");
2375 			notice = TRUE;
2376 		}
2377 	}
2378 
2379 	/* Shut */
2380 	else {
2381 		if (p_ptr->tim_infra) {
2382 			msg_print(Ind, "Your eyes stop tingling.");
2383 			notice = TRUE;
2384 		}
2385 	}
2386 
2387 	/* Use the value */
2388 	p_ptr->tim_infra = v;
2389 
2390 	/* Nothing to notice */
2391 	if (!notice) return (FALSE);
2392 
2393 	/* Disturb */
2394 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2395 
2396 	/* Recalculate boni */
2397 	p_ptr->update |= (PU_BONUS);
2398 
2399 	/* Update the monsters */
2400 	p_ptr->update |= (PU_MONSTERS);
2401 
2402 	/* Handle stuff */
2403 	handle_stuff(Ind);
2404 
2405 	/* Result */
2406 	return (TRUE);
2407 }
2408 
2409 
2410 /*
2411  * Set "p_ptr->oppose_acid", notice observable changes
2412  */
set_oppose_acid(int Ind,int v)2413 bool set_oppose_acid(int Ind, int v) {
2414 	player_type *p_ptr = Players[Ind];
2415 	bool notice = FALSE;
2416 
2417 	/* Hack -- Force good values */
2418 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2419 
2420 	/* Open */
2421 	if (v) {
2422 		if (!p_ptr->oppose_acid) {
2423 			msg_print(Ind, "You feel resistant to acid!");
2424 			notice = TRUE;
2425 		}
2426 	}
2427 
2428 	/* Shut */
2429 	else {
2430 		if (p_ptr->oppose_acid) {
2431 			msg_print(Ind, "\377WYou feel less resistant to \377sacid.");
2432 			notice = TRUE;
2433 		}
2434 	}
2435 
2436 	/* Use the value */
2437 	p_ptr->oppose_acid = v;
2438 
2439 	/* Nothing to notice */
2440 	if (!notice) return (FALSE);
2441 
2442 	/* Disturb */
2443 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2444 
2445 	/* Handle stuff */
2446 	handle_stuff(Ind);
2447 
2448 	/* Result */
2449 	return (TRUE);
2450 }
2451 
2452 
2453 /*
2454  * Set "p_ptr->oppose_elec", notice observable changes
2455  */
set_oppose_elec(int Ind,int v)2456 bool set_oppose_elec(int Ind, int v) {
2457 	player_type *p_ptr = Players[Ind];
2458 	bool notice = FALSE;
2459 
2460 	/* Hack -- Force good values */
2461 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2462 
2463 	/* Open */
2464 	if (v) {
2465 		if (!p_ptr->oppose_elec) {
2466 			msg_print(Ind, "You feel resistant to electricity!");
2467 			notice = TRUE;
2468 		}
2469 	}
2470 
2471 	/* Shut */
2472 	else {
2473 		if (p_ptr->oppose_elec) {
2474 			msg_print(Ind, "\377WYou feel less resistant to \377belectricity.");
2475 			notice = TRUE;
2476 		}
2477 	}
2478 
2479 	/* Use the value */
2480 	p_ptr->oppose_elec = v;
2481 
2482 	/* Nothing to notice */
2483 	if (!notice) return (FALSE);
2484 
2485 	/* Disturb */
2486 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2487 
2488 	/* Handle stuff */
2489 	handle_stuff(Ind);
2490 
2491 	/* Result */
2492 	return (TRUE);
2493 }
2494 
2495 
2496 /*
2497  * Set "p_ptr->oppose_fire", notice observable changes
2498  */
set_oppose_fire(int Ind,int v)2499 bool set_oppose_fire(int Ind, int v) {
2500 	player_type *p_ptr = Players[Ind];
2501 	bool notice = FALSE;
2502 
2503 	/* Hack -- Force good values */
2504 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2505 
2506 	/* Open */
2507 	if (v) {
2508 		if (!p_ptr->oppose_fire) {
2509 			msg_print(Ind, "You feel resistant to fire!");
2510 			notice = TRUE;
2511 		}
2512 	}
2513 
2514 	/* Shut */
2515 	else {
2516 		if (p_ptr->oppose_fire) {
2517 			msg_print(Ind, "\377WYou feel less resistant to \377rfire.");
2518 			notice = TRUE;
2519 		}
2520 	}
2521 
2522 	/* Use the value */
2523 	p_ptr->oppose_fire = v;
2524 
2525 	/* Nothing to notice */
2526 	if (!notice) return (FALSE);
2527 
2528 	/* Disturb */
2529 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2530 
2531 	/* Handle stuff */
2532 	handle_stuff(Ind);
2533 
2534 	/* Result */
2535 	return (TRUE);
2536 }
2537 
2538 
2539 /*
2540  * Set "p_ptr->oppose_cold", notice observable changes
2541  */
set_oppose_cold(int Ind,int v)2542 bool set_oppose_cold(int Ind, int v) {
2543 	player_type *p_ptr = Players[Ind];
2544 	bool notice = FALSE;
2545 
2546 	/* Hack -- Force good values */
2547 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2548 
2549 	/* Open */
2550 	if (v) {
2551 		if (!p_ptr->oppose_cold) {
2552 			msg_print(Ind, "You feel resistant to cold!");
2553 			notice = TRUE;
2554 		}
2555 	}
2556 
2557 	/* Shut */
2558 	else {
2559 		if (p_ptr->oppose_cold) {
2560 			msg_print(Ind, "\377WYou feel less resistant to \377wcold.");
2561 			notice = TRUE;
2562 		}
2563 	}
2564 
2565 	/* Use the value */
2566 	p_ptr->oppose_cold = v;
2567 
2568 	/* Nothing to notice */
2569 	if (!notice) return (FALSE);
2570 
2571 	/* Disturb */
2572 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2573 
2574 	/* Handle stuff */
2575 	handle_stuff(Ind);
2576 
2577 	/* Result */
2578 	return (TRUE);
2579 }
2580 
2581 
2582 /*
2583  * Set "p_ptr->oppose_pois", notice observable changes
2584  */
set_oppose_pois(int Ind,int v)2585 bool set_oppose_pois(int Ind, int v) {
2586 	player_type *p_ptr = Players[Ind];
2587 	bool notice = FALSE;
2588 
2589 	/* Hack -- Force good values */
2590 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2591 
2592 	/* Open */
2593 	if (v) {
2594 		if (!p_ptr->oppose_pois) {
2595 			msg_print(Ind, "You feel resistant to poison!");
2596 			notice = TRUE;
2597 		}
2598 	}
2599 
2600 	/* Shut */
2601 	else {
2602 		if (p_ptr->oppose_pois) {
2603 			msg_print(Ind, "\377WYou feel less resistant to \377gpoison.");
2604 			notice = TRUE;
2605 		}
2606 	}
2607 
2608 	/* Use the value */
2609 	p_ptr->oppose_pois = v;
2610 
2611 	/* Nothing to notice */
2612 	if (!notice) return (FALSE);
2613 
2614 	/* Disturb */
2615 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2616 
2617 	/* Handle stuff */
2618 	handle_stuff(Ind);
2619 
2620 	/* Result */
2621 	return (TRUE);
2622 }
2623 
2624 
2625 /*
2626  * Set "p_ptr->stun", notice observable changes
2627  *
2628  * Note the special code to only notice "range" changes.
2629  */
set_stun(int Ind,int v)2630 bool set_stun(int Ind, int v) {
2631 	player_type *p_ptr = Players[Ind];
2632 	int old_aux, new_aux;
2633 	bool notice = FALSE;
2634 
2635 	if (p_ptr->martyr && v) return FALSE;
2636 
2637 	/* hack -- the admin wizard can not be stunned */
2638 //	if (p_ptr->admin_wiz) return TRUE;
2639 
2640 	/* Hack -- Force good values */
2641 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2642 
2643 #if 0 /* decided to make it just as combat skill working in dungeon.c to accelerate recovery! */
2644 	/* apply HCURING in a special way: halve the duration of highest stun level that actually gets reached */
2645 	if (get_skill(p_ptr, SKILL_HCURING) >= 40) v /= 2;
2646 #endif
2647 
2648 	/* Knocked out */
2649 	if (p_ptr->stun > 100) old_aux = 3;
2650 	/* Heavy stun */
2651 	else if (p_ptr->stun > 50) old_aux = 2;
2652 	/* Stun */
2653 	else if (p_ptr->stun > 0) old_aux = 1;
2654 	/* None */
2655 	else old_aux = 0;
2656 
2657 	/* Knocked out */
2658 	if (v > 100) new_aux = 3;
2659 	/* Heavy stun */
2660 	else if (v > 50) new_aux = 2;
2661 	/* Stun */
2662 	else if (v > 0) new_aux = 1;
2663 	/* None */
2664 	else new_aux = 0;
2665 
2666 	/* Increase stun */
2667 	if (new_aux > old_aux) {
2668 		/* Describe the state */
2669 		switch (new_aux) {
2670 			/* Stun */
2671 			case 1:
2672 			msg_format_near(Ind, "\377o%s appears stunned.", p_ptr->name);
2673 			msg_print(Ind, "\377oYou have been stunned.");
2674 			break;
2675 
2676 			/* Heavy stun */
2677 			case 2:
2678 			msg_format_near(Ind, "\377o%s is heavily stunned.", p_ptr->name);
2679 			msg_print(Ind, "\377oYou have been heavily stunned.");
2680 			break;
2681 
2682 			/* Knocked out */
2683 			case 3:
2684 			msg_format_near(Ind, "%s has been knocked out.", p_ptr->name);
2685 			msg_print(Ind, "\377rYou have been knocked out.");
2686 			s_printf("%s EFFECT: Knockedout %s.\n", showtime(), p_ptr->name);
2687 			p_ptr->energy = 0;/* paranoia, couldn't reproduce it so far - don't allow him a final action with his rest of energy */
2688 			break;
2689 		}
2690 
2691 		break_shadow_running(Ind);
2692 
2693 		/* Notice */
2694 		notice = TRUE;
2695 	}
2696 
2697 	/* Decrease cut */
2698 	else if (new_aux < old_aux) {
2699 		/* Describe the state */
2700 		switch (new_aux) {
2701 			/* None */
2702 			case 0:
2703 			msg_format_near(Ind, "\377o%s is no longer stunned.", p_ptr->name);
2704 			msg_print(Ind, "\377yYou are no longer stunned.");
2705 			if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2706 			break;
2707 		}
2708 
2709 		/* Notice */
2710 		notice = TRUE;
2711 	}
2712 
2713 	/* Use the value */
2714 	p_ptr->stun = v;
2715 
2716 	/* No change */
2717 	if (!notice) return (FALSE);
2718 
2719 	/* Disturb */
2720 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2721 
2722 	/* Recalculate boni */
2723 	p_ptr->update |= (PU_BONUS);
2724 
2725 	/* Redraw the "stun" */
2726 	p_ptr->redraw |= (PR_STUN);
2727 
2728 	/* Handle stuff */
2729 	handle_stuff(Ind);
2730 
2731 	/* Result */
2732 	return (TRUE);
2733 }
2734 
2735 
2736 /*
2737  * Set "p_ptr->cut", notice observable changes
2738  *
2739  * Note the special code to only notice "range" changes.
2740  */
set_cut(int Ind,int v,int attacker)2741 bool set_cut(int Ind, int v, int attacker) {
2742 	player_type *p_ptr = Players[Ind];
2743 	int old_aux, new_aux;
2744 	bool notice = FALSE;
2745 
2746 	if (p_ptr->martyr && v) return FALSE;
2747 
2748 	/* Hack -- Force good values */
2749 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2750 
2751 /* instead put into dungeon.c for faster recovery
2752 	if (get_skill(p_ptr, SKILL_HCURING) >= 40) v /= 2;
2753 */
2754 
2755 	/* p_ptr->no_cut? for mimic forms that cannot bleed */
2756 	if (p_ptr->no_cut) v = 0;
2757 
2758 	/* a ghost never bleeds */
2759 	if (v && p_ptr->ghost) v = 0;
2760 
2761 	/* Mortal wound */
2762 	if (p_ptr->cut > 1000) old_aux = 7;
2763 	/* Deep gash */
2764 	else if (p_ptr->cut > 200) old_aux = 6;
2765 	/* Severe cut */
2766 	else if (p_ptr->cut > 100) old_aux = 5;
2767 	/* Nasty cut */
2768 	else if (p_ptr->cut > 50) old_aux = 4;
2769 	/* Bad cut */
2770 	else if (p_ptr->cut > 25) old_aux = 3;
2771 	/* Light cut */
2772 	else if (p_ptr->cut > 10) old_aux = 2;
2773 	/* Graze */
2774 	else if (p_ptr->cut > 0) old_aux = 1;
2775 	/* None */
2776 	else old_aux = 0;
2777 
2778 	/* Mortal wound */
2779 	if (v > 1000) new_aux = 7;
2780 	/* Deep gash */
2781 	else if (v > 200) new_aux = 6;
2782 	/* Severe cut */
2783 	else if (v > 100) new_aux = 5;
2784 	/* Nasty cut */
2785 	else if (v > 50) new_aux = 4;
2786 	/* Bad cut */
2787 	else if (v > 25) new_aux = 3;
2788 	/* Light cut */
2789 	else if (v > 10) new_aux = 2;
2790 	/* Graze */
2791 	else if (v > 0) new_aux = 1;
2792 	/* None */
2793 	else new_aux = 0;
2794 
2795 	/* Increase cut */
2796 	if (new_aux > old_aux) {
2797 		/* Describe the state */
2798 		switch (new_aux) {
2799 			/* Graze */
2800 			case 1:
2801 			msg_print(Ind, "You have been given a graze.");
2802 			break;
2803 
2804 			/* Light cut */
2805 			case 2:
2806 			msg_print(Ind, "You have been given a light cut.");
2807 			break;
2808 
2809 			/* Bad cut */
2810 			case 3:
2811 			msg_print(Ind, "You have been given a bad cut.");
2812 			break;
2813 
2814 			/* Nasty cut */
2815 			case 4:
2816 			msg_print(Ind, "You have been given a nasty cut.");
2817 			break;
2818 
2819 			/* Severe cut */
2820 			case 5:
2821 			msg_print(Ind, "You have been given a severe cut.");
2822 			break;
2823 
2824 			/* Deep gash */
2825 			case 6:
2826 			msg_print(Ind, "You have been given a deep gash.");
2827 			break;
2828 
2829 			/* Mortal wound */
2830 			case 7:
2831 			msg_print(Ind, "You have been given a mortal wound.");
2832 			break;
2833 		}
2834 
2835 		/* Notice */
2836 		notice = TRUE;
2837 	}
2838 
2839 	/* Decrease cut */
2840 	else if (new_aux < old_aux) {
2841 		/* Describe the state */
2842 		switch (new_aux) {
2843 			/* None */
2844 			case 0:
2845 			msg_print(Ind, "You are no longer bleeding.");
2846 			if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2847 			p_ptr->cut_attacker = 0;
2848 			break;
2849 		}
2850 
2851 		/* Notice */
2852 		notice = TRUE;
2853 	}
2854 
2855 	/* Use the value */
2856 	p_ptr->cut = v;
2857 
2858 	/* Remember who did it - mikaelh */
2859 	p_ptr->cut_attacker = attacker;
2860 
2861 	/* No change */
2862 	if (!notice) return (FALSE);
2863 
2864 	/* Disturb */
2865 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2866 
2867 	/* Recalculate boni */
2868 	p_ptr->update |= (PU_BONUS);
2869 
2870 	/* Redraw the "cut" */
2871 	p_ptr->redraw |= (PR_CUT);
2872 
2873 	/* Handle stuff */
2874 	handle_stuff(Ind);
2875 
2876 	/* Result */
2877 	return (TRUE);
2878 }
2879 
set_mindboost(int Ind,int p,int v)2880 bool set_mindboost(int Ind, int p, int v) {
2881 	player_type *p_ptr = Players[Ind];
2882 	bool notice = FALSE;
2883 
2884 	/* Hack -- Force good values */
2885 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2886 
2887 
2888 	/* Redraw the Blows/Round if any */
2889 	if (v && p_ptr->mindboost_power != p) p_ptr->update |= PU_BONUS;
2890 
2891 	/* set boni/EA */
2892 	p_ptr->mindboost_power = p;
2893 
2894 	/* Open */
2895 	if (v) {
2896 		if (!p_ptr->mindboost) {
2897 			msg_print(Ind, "Your mind overflows!");
2898 			notice = TRUE;
2899 		}
2900 	}
2901 
2902 	/* Shut */
2903 	else {
2904 		if (p_ptr->mindboost) {
2905 			msg_print(Ind, "The mind returns to normal.");
2906 			notice = TRUE;
2907 		}
2908 	}
2909 
2910 	/* Use the value */
2911 	p_ptr->mindboost = v;
2912 
2913 	if (set_afraid(Ind, 0)) notice = TRUE;
2914 
2915 	/* Nothing to notice */
2916 	if (!notice) return (FALSE);
2917 
2918 	/* Redraw the Blows/Round if any */
2919 	p_ptr->update |= PU_BONUS;
2920 
2921 	/* Disturb */
2922 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2923 
2924 	/* Handle stuff */
2925 	handle_stuff(Ind);
2926 
2927 	/* Result */
2928 	return (TRUE);
2929 }
2930 
set_kinetic_shield(int Ind,int v)2931 bool set_kinetic_shield(int Ind, int v) {
2932 	player_type *p_ptr = Players[Ind];
2933 	bool notice = FALSE;
2934 
2935 	/* Hack -- Force good values */
2936 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2937 
2938 	/* Open */
2939 	if (v) {
2940 		if (!p_ptr->kinetic_shield) {
2941 			msg_print(Ind, "You create a kinetic barrier.");
2942 			notice = TRUE;
2943 		}
2944 	}
2945 
2946 	/* Shut */
2947 	else {
2948 		if (p_ptr->kinetic_shield) {
2949 			msg_print(Ind, "Your kinetic barrier destabilizes.");
2950 			notice = TRUE;
2951 		}
2952 	}
2953 
2954 	/* Use the value */
2955 	p_ptr->kinetic_shield = v;
2956 
2957 	/* Nothing to notice */
2958 	if (!notice) return (FALSE);
2959 
2960 	/* Disturb */
2961 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2962 
2963 	/* Handle stuff */
2964 	handle_stuff(Ind);
2965 
2966 	/* Result */
2967 	return (TRUE);
2968 }
2969 
2970 #ifdef ENABLE_MAIA
2971 /* timed hp bonus for RACE_MAIA.
2972    *fastest* path (SKILL_ASTRAL = lvl+2):
2973    +1 at lvl 39
2974    +2 at lvl 54
2975    +3 at lvl 60
2976 */
do_divine_hp(int Ind,int v,int p)2977 bool do_divine_hp(int Ind, int v, int p) {
2978         player_type *p_ptr = Players[Ind];
2979         bool notice = (FALSE);
2980 
2981         /* Hack -- Force good values */
2982         v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2983 
2984         /* Open */
2985         if (v) {
2986                 if (!p_ptr->divine_hp) {
2987                         msg_format_near(Ind, "%s prepares for aggression!", p_ptr->name);
2988                         msg_print(Ind, "You feel courageous.");
2989 			p_ptr->divine_hp_mod = p;
2990 
2991                         notice = (TRUE);
2992                 }
2993         }
2994 
2995         /* Shut */
2996         else { //v = 0;
2997                 if (p_ptr->divine_hp) {
2998 			p_ptr->divine_hp_mod = 0;
2999                         msg_format_near(Ind, "%s returns to %s normal self.", p_ptr->name, (p_ptr->male? "his" : "her"));
3000                         msg_print(Ind, "You no longer feel courageous.");
3001                         notice = (TRUE);
3002                 }
3003         }
3004 
3005         p_ptr->divine_hp = v;
3006 
3007         /* Nothing to notice */
3008         if (!notice) return (FALSE);
3009 
3010         /* Disturb */
3011         if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3012 
3013         /* Recalculate boni */
3014         p_ptr->update |= (PU_BONUS|PU_HP);
3015         /* Handle stuff */
3016         handle_stuff(Ind);
3017 
3018         /* Result */
3019         return (TRUE);
3020 }
3021 
3022 /*
3023    timed crit bonus for RACE_MAIA.
3024    *fastest* path (SKILL_ASTRAL = lvl+2):
3025    +2 at lvl 44, +2 per 5 levels thereafter
3026 */
do_divine_crit(int Ind,int v,int p)3027 bool do_divine_crit(int Ind, int v, int p) {
3028         player_type *p_ptr = Players[Ind];
3029         bool notice = (FALSE);
3030 
3031         /* Hack -- Force good values */
3032         v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3033 
3034         /* Open */
3035         if (v) {
3036                 if (!p_ptr->divine_crit) {
3037                         msg_format_near(Ind, "%s seems focussed.", p_ptr->name);
3038                         msg_print(Ind, "You focus your intentions.");
3039 			p_ptr->divine_crit_mod = p;
3040 
3041                         notice = (TRUE);
3042                 }
3043         }
3044 
3045         /* Shut */
3046         else { //v = 0;
3047                 if (p_ptr->divine_crit) {
3048 			p_ptr->divine_crit_mod = 0;
3049                         msg_format_near(Ind, "%s seems less focussed", p_ptr->name);
3050                         msg_print(Ind, "Your focus dissipates.");
3051                         notice = (TRUE);
3052                 }
3053         }
3054 
3055         p_ptr->divine_crit = v;
3056 
3057         /* Nothing to notice */
3058         if (!notice) return (FALSE);
3059 
3060         /* Disturb */
3061         if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3062 
3063         /* Recalculate boni */
3064         p_ptr->update |= (PU_BONUS);
3065         /* Handle stuff */
3066         handle_stuff(Ind);
3067 
3068         /* Result */
3069         return (TRUE);
3070 }
3071 
3072 /*
3073    timed time and mana res bonus for RACE_MAIA.
3074 */
do_divine_xtra_res_time(int Ind,int v)3075 bool do_divine_xtra_res_time(int Ind, int v) {
3076         player_type *p_ptr = Players[Ind];
3077         bool notice = (FALSE);
3078 
3079         /* Hack -- Force good values */
3080         v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3081 
3082         /* Open */
3083         if (v) {
3084                 if (!p_ptr->divine_xtra_res_time) {
3085 			msg_print(Ind, "You feel resistant to \377Btime\377w.");
3086                         notice = (TRUE);
3087                 }
3088         }
3089 
3090         /* Shut */
3091         else { //v = 0;
3092                 if (p_ptr->divine_xtra_res_time) {
3093 			msg_print(Ind, "You feel less resistant to \377Btime\377w.");
3094                         notice = (TRUE);
3095                 }
3096         }
3097 
3098         p_ptr->divine_xtra_res_time = v;
3099 
3100         /* Nothing to notice */
3101         if (!notice) return (FALSE);
3102 
3103         /* Disturb */
3104         if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3105 
3106         /* Recalculate boni */
3107         p_ptr->update |= (PU_BONUS);
3108 
3109         /* Handle stuff */
3110         handle_stuff(Ind);
3111 
3112         /* Result */
3113         return (TRUE);
3114 }
3115 #endif
3116 
3117 /*
3118  * Set "p_ptr->tim_deflect", notice observable changes
3119  */
set_tim_deflect(int Ind,int v)3120 bool set_tim_deflect(int Ind, int v) {
3121 	player_type *p_ptr = Players[Ind];
3122 	bool notice = FALSE;
3123 
3124 	/* Hack -- Force good values */
3125 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3126 
3127 	/* Open */
3128 	if (v) {
3129 		if (!p_ptr->tim_deflect) {
3130 			msg_print(Ind, "A deflective shield forms around your body!");
3131 			notice = TRUE;
3132 		}
3133 	}
3134 
3135 	/* Shut */
3136 	else {
3137 		if (p_ptr->tim_deflect) {
3138 			msg_print(Ind, "Your deflective shield crumbles away.");
3139 			notice = TRUE;
3140 		}
3141 	}
3142 
3143 
3144 	/* Use the value */
3145 	p_ptr->tim_deflect = v;
3146 
3147 	/* Nothing to notice */
3148 	if (!notice) return (FALSE);
3149 
3150 	/* Disturb */
3151 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3152 
3153 	/* Recalculate boni */
3154 	p_ptr->update |= (PU_BONUS);
3155 
3156 	/* Handle stuff */
3157 	handle_stuff(Ind);
3158 
3159 	/* Result */
3160 	return (TRUE);
3161 }
3162 
3163 /*
3164  * Set "p_ptr->sh_fire/cold/elec", notice observable changes
3165  */
set_sh_fire_tim(int Ind,int v)3166 bool set_sh_fire_tim(int Ind, int v) {
3167 	player_type *p_ptr = Players[Ind];
3168 	bool notice = FALSE;
3169 
3170 	/* Hack -- Force good values */
3171 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3172 
3173 	/* Open */
3174 	if (v) {
3175 		if (!p_ptr->sh_fire_tim) {
3176 			if (!p_ptr->sh_fire_fix) {
3177 				msg_print(Ind, "You are enveloped by scorching flames!");
3178 				notice = TRUE;
3179 			} else msg_print(Ind, "The scorching flames surrounding you are blazing high!");
3180 		}
3181 	}
3182 	/* Shut */
3183 	else {
3184 		if (p_ptr->sh_fire_tim && !p_ptr->sh_fire_fix) {
3185 			msg_print(Ind, "The scorching flames surrounding you cease.");
3186 			notice = TRUE;
3187 		}
3188 	}
3189 
3190 	/* Use the value */
3191 	p_ptr->sh_fire_tim = v;
3192 	/* Nothing to notice */
3193 	if (!notice) return (FALSE);
3194 	/* Disturb */
3195 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3196 	/* Recalculate boni */
3197 	p_ptr->update |= (PU_BONUS);
3198 	/* Handle stuff */
3199 	handle_stuff(Ind);
3200 	/* Result */
3201 	return (TRUE);
3202 }
set_sh_cold_tim(int Ind,int v)3203 bool set_sh_cold_tim(int Ind, int v) {
3204 	player_type *p_ptr = Players[Ind];
3205 	bool notice = FALSE;
3206 
3207 	/* Hack -- Force good values */
3208 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3209 
3210 	/* Open */
3211 	if (v) {
3212 		if (!p_ptr->sh_cold_tim) {
3213 			if (!p_ptr->sh_cold_fix) {
3214 				msg_print(Ind, "You are enveloped by freezing cold!");
3215 				notice = TRUE;
3216 			} else msg_print(Ind, "The frost around you blows colder even!");
3217 		}
3218 	}
3219 	/* Shut */
3220 	else {
3221 		if (p_ptr->sh_cold_tim && !p_ptr->sh_cold_fix) {
3222 			msg_print(Ind, "The scorching flames surrounding you cease.");
3223 			notice = TRUE;
3224 		}
3225 	}
3226 
3227 	/* Use the value */
3228 	p_ptr->sh_cold_tim = v;
3229 	/* Nothing to notice */
3230 	if (!notice) return (FALSE);
3231 	/* Disturb */
3232 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3233 	/* Recalculate boni */
3234 	p_ptr->update |= (PU_BONUS);
3235 	/* Handle stuff */
3236 	handle_stuff(Ind);
3237 	/* Result */
3238 	return (TRUE);
3239 }
set_sh_elec_tim(int Ind,int v)3240 bool set_sh_elec_tim(int Ind, int v) {
3241 	player_type *p_ptr = Players[Ind];
3242 	bool notice = FALSE;
3243 
3244 	/* Hack -- Force good values */
3245 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3246 
3247 	/* Open */
3248 	if (v) {
3249 		if (!p_ptr->sh_elec_tim) {
3250 			if (!p_ptr->sh_elec_fix) {
3251 				msg_print(Ind, "You are enveloped by sparkling static!");
3252 				notice = TRUE;
3253 			} else msg_print(Ind, "Static around you surges brightly!");
3254 		}
3255 	}
3256 	/* Shut */
3257 	else {
3258 		if (p_ptr->sh_elec_tim && !p_ptr->sh_elec_fix) {
3259 			msg_print(Ind, "The static sparkling around you ceases.");
3260 			notice = TRUE;
3261 		}
3262 	}
3263 
3264 	/* Use the value */
3265 	p_ptr->sh_elec_tim = v;
3266 	/* Nothing to notice */
3267 	if (!notice) return (FALSE);
3268 	/* Disturb */
3269 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3270 	/* Recalculate boni */
3271 	p_ptr->update |= (PU_BONUS);
3272 	/* Handle stuff */
3273 	handle_stuff(Ind);
3274 	/* Result */
3275 	return (TRUE);
3276 }
3277 
3278 
3279 
3280 /*
3281  * Set "p_ptr->food", notice observable changes
3282  *
3283  * The "p_ptr->food" variable can get as large as 20000, allowing the
3284  * addition of the most "filling" item, Elvish Waybread, which adds
3285  * 7500 food units, without overflowing the 32767 maximum limit.
3286  *
3287  * Perhaps we should disturb the player with various messages,
3288  * especially messages about hunger status changes.  XXX XXX XXX
3289  *
3290  * Digestion of food is handled in "dungeon.c", in which, normally,
3291  * the player digests about 20 food units per 100 game turns, more
3292  * when "fast", more when "regenerating", less with "slow digestion",
3293  * but when the player is "gorged", he digests 100 food units per 10
3294  * game turns, or a full 1000 food units per 100 game turns.
3295  *
3296  * Note that the player's speed is reduced by 10 units while gorged,
3297  * so if the player eats a single food ration (5000 food units) when
3298  * full (15000 food units), he will be gorged for (5000/100)*10 = 500
3299  * game turns, or 500/(100/5) = 25 player turns (if nothing else is
3300  * affecting the player speed).
3301  */
set_food(int Ind,int v)3302 bool set_food(int Ind, int v) {
3303 	player_type *p_ptr = Players[Ind];
3304 	int old_aux, new_aux;
3305 	bool notice = FALSE;
3306 
3307 	/* True Ghosts don't starve */
3308 	if ((p_ptr->ghost) || (get_skill(p_ptr, SKILL_HSUPPORT) >= 40) ||
3309 	    (p_ptr->prace == RACE_MAIA && p_ptr->ptrait))
3310 	{
3311 	    p_ptr->food = PY_FOOD_FULL - 1;
3312 	    return (FALSE);
3313 	}
3314 
3315 	/* Warrior does not need food badly */
3316 #ifdef ARCADE_SERVER
3317 	p_ptr->food = PY_FOOD_FULL - 1;
3318 	return (FALSE);
3319 #endif
3320 	/* Hack -- Force good values */
3321 	v = (v > 20000) ? 20000 : (v < 0) ? 0 : v;
3322 
3323 	/* Ents will never get gorged, but can still go hungry/thirsty */
3324 	if (p_ptr->prace == RACE_ENT && v >= PY_FOOD_MAX ) {
3325 		v = PY_FOOD_MAX - 1;
3326 	}
3327 
3328 	/* Fainting / Starving */
3329 	if (p_ptr->food < PY_FOOD_FAINT) old_aux = 0;
3330 	/* Weak */
3331 	else if (p_ptr->food < PY_FOOD_WEAK) old_aux = 1;
3332 	/* Hungry */
3333 	else if (p_ptr->food < PY_FOOD_ALERT) old_aux = 2;
3334 	/* Normal */
3335 	else if (p_ptr->food < PY_FOOD_FULL) old_aux = 3;
3336 	/* Full */
3337 	else if (p_ptr->food < PY_FOOD_MAX) old_aux = 4;
3338 	/* Gorged */
3339 	else old_aux = 5;
3340 
3341 	/* Fainting / Starving */
3342 	if (v < PY_FOOD_FAINT) new_aux = 0;
3343 	/* Weak */
3344 	else if (v < PY_FOOD_WEAK) new_aux = 1;
3345 	/* Hungry */
3346 	else if (v < PY_FOOD_ALERT) new_aux = 2;
3347 	/* Normal */
3348 	else if (v < PY_FOOD_FULL) new_aux = 3;
3349 	/* Full */
3350 	else if (v < PY_FOOD_MAX) new_aux = 4;
3351 	/* Gorged */
3352 	else new_aux = 5;
3353 
3354 	/* Food increase */
3355 	if (new_aux > old_aux) {
3356 		/* Describe the state */
3357 		switch (new_aux) {
3358 			/* Weak */
3359 			case 1:
3360 			msg_print(Ind, "You are still weak.");
3361 			break;
3362 
3363 			/* Hungry */
3364 			case 2:
3365 			msg_print(Ind, "You are still hungry.");
3366 			break;
3367 
3368 			/* Normal */
3369 			case 3:
3370 			msg_print(Ind, "You are no longer hungry.");
3371 			break;
3372 
3373 			/* Full */
3374 			case 4:
3375 			msg_print(Ind, "You are full!");
3376 			break;
3377 
3378 			/* Bloated */
3379 			case 5:
3380 			msg_print(Ind, "You have gorged yourself!");
3381 			break;
3382 		}
3383 
3384 		/* Change */
3385 		notice = TRUE;
3386 	}
3387 
3388 	/* Food decrease */
3389 	else if (new_aux < old_aux) {
3390 		/* Describe the state */
3391 		switch (new_aux) {
3392 			/* Fainting / Starving */
3393 			case 0:
3394 			msg_print(Ind, "\377RYou are getting faint from hunger!");
3395 			break;
3396 
3397 			/* Weak */
3398 			case 1:
3399 			msg_print(Ind, "You are getting weak from hunger!");
3400 			if (p_ptr->warning_hungry != 2) {
3401 				p_ptr->warning_hungry = 2;
3402 				if (p_ptr->prace == RACE_VAMPIRE) {
3403 					msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Drink some blood by killing monsters");
3404 					msg_print(Ind, "\374\377R         monsters in melee (close combat). Town monsters will work too.");
3405 				} else if (p_ptr->prace == RACE_ENT) {
3406 					msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Find something to drink or rest");
3407 					msg_print(Ind, "\374\377R         (\377oSHIFT+r\377R) on earth/dirt/grass/water floor tiles for a while.");
3408 				} else {
3409 					msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Press \377oSHIFT+e\377R to eat something");
3410 					msg_print(Ind, "\374\377R         or read a 'scroll of satisfy hunger' if you have one.");
3411 				}
3412 				s_printf("warning_hungry(weak): %s\n", p_ptr->name);
3413 			}
3414 			break;
3415 
3416 			/* Hungry */
3417 			case 2:
3418 			msg_print(Ind, "You are getting hungry.");
3419 			if (p_ptr->warning_hungry == 0) {
3420 				p_ptr->warning_hungry = 1;
3421 				if (p_ptr->prace == RACE_VAMPIRE) {
3422 					msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Drink some blood by killing some");
3423 					msg_print(Ind, "\374\377o         monsters in melee (close combat). Town monsters will work too.");
3424 				} else if (p_ptr->prace == RACE_ENT) {
3425 					msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Find something to drink or rest ");
3426 					msg_print(Ind, "\374\377o         (\377RSHIFT+r\377o) on earth/dirt/grass/water floor tiles for a while.");
3427 				} else {
3428 					msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Press \377RSHIFT+e\377o to eat something");
3429 					msg_print(Ind, "\374\377o         or read a 'scroll of satisfy hunger' if you have one.");
3430 				}
3431 				s_printf("warning_hungry(hungry): %s\n", p_ptr->name);
3432 			}
3433 			break;
3434 
3435 			/* Normal */
3436 			case 3:
3437 			msg_print(Ind, "You are no longer full.");
3438 			break;
3439 
3440 			/* Full */
3441 			case 4:
3442 			msg_print(Ind, "You are no longer gorged.");
3443 			break;
3444 		}
3445 
3446 		/* Change */
3447 		notice = TRUE;
3448 	}
3449 
3450 	/* Use the value */
3451 	p_ptr->food = v;
3452 
3453 	/* Nothing to notice */
3454 	if (!notice) return (FALSE);
3455 
3456 	/* Disturb */
3457 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3458 
3459 	/* Recalculate boni */
3460 	p_ptr->update |= (PU_BONUS);
3461 
3462 	/* Redraw hunger */
3463 	p_ptr->redraw |= (PR_HUNGER);
3464 
3465 	/* Handle stuff */
3466 	handle_stuff(Ind);
3467 
3468 	/* Result */
3469 	return (TRUE);
3470 }
3471 
3472 
3473 /*
3474  * Set "p_ptr->bless_temp_luck" - note: currently bless_temp_... aren't saved/loaded! (ie expire on logout)
3475  */
bless_temp_luck(int Ind,int pow,int dur)3476 bool bless_temp_luck(int Ind, int pow, int dur) {
3477 	player_type *p_ptr = Players[Ind];
3478 	bool notice = FALSE;
3479 
3480 	if (!p_ptr->bless_temp_luck) {
3481 		msg_print(Ind, "You feel luck is on your side.");
3482 		notice = TRUE;
3483 	}
3484 	if (!dur) {
3485 		msg_print(Ind, "Your lucky streak fades.");
3486 		notice = TRUE;
3487 	}
3488 
3489 	/* Use the value */
3490 	p_ptr->bless_temp_luck = dur;
3491 	p_ptr->bless_temp_luck_power = pow;
3492 
3493 	/* Nothing to notice */
3494 	if (!notice) return (FALSE);
3495 
3496 	/* Disturb */
3497 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3498 
3499 	/* Recalculate boni */
3500 	p_ptr->update |= (PU_BONUS);
3501 
3502 	/* Handle stuff */
3503 	handle_stuff(Ind);
3504 
3505 	/* Result */
3506 	return (TRUE);
3507 }
3508 
3509 #ifdef ENABLE_MAIA
3510 /* helper function to modify Maia skills when they get a trait - C. Blue
3511    NOTE: IF THIS IS CALLED TOO MANY TIMES IN A ROW IT
3512          _MIGHT_ DISCONNET THE CLIENT WITH A 'write error'. */
do_Maia_skill(int Ind,int s,int m)3513 static void do_Maia_skill(int Ind, int s, int m) {
3514 	/* Save old skill value */
3515 	s32b val = Players[Ind]->s_info[s].value, tmp_val = Players[Ind]->s_info[s].mod;
3516 
3517 	/* Release invested points */
3518 	respec_skill(Ind, s, FALSE, FALSE);
3519 
3520 	/* Modify skill, avoiding overflow (mod is u16b) */
3521 	tmp_val = (tmp_val * m) / 10;
3522 	/* Cap to 2.0 */
3523 	if (tmp_val > 2000) tmp_val = 2000;
3524 	Players[Ind]->s_info[s].mod = tmp_val;
3525 
3526 	/* Reinvest some of the points until old skill value is reached again */
3527 	tmp_val = -1;
3528 #if 0
3529 	while (((Players[Ind]->s_info[s].value / 1000 < val / 1000 && /* smooth: avoid "overskilling" */
3530 	    (Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod) / 1000 <= val / 1000) ||
3531 	    Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod <= val) /* no "underskilling" */
3532 #else
3533 	while (Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod <= val /* no "overskilling" */
3534 #endif
3535 	    /* avoid game maximum overflow - paranoia: */
3536 	    && Players[Ind]->s_info[s].value < 50000
3537 	    /* avoid cap overflow - extreme cases only (maxed auras): */
3538 	    && Players[Ind]->s_info[s].value / 1000 < Players[Ind]->max_plv + 2
3539 	    /* avoid getting stuck - paranoia (could waste 1 point actually if it really happened): */
3540 	    && Players[Ind]->s_info[s].value != tmp_val) {
3541 		/* make sure we don't loop forever in case we can't go higher */
3542 		tmp_val = Players[Ind]->s_info[s].value;
3543 		/* invest a point */
3544 		increase_skill(Ind, s, TRUE);
3545 	}
3546 
3547 	/* Update it after the re-increasing has been finished */
3548 	Send_skill_info(Ind, s, FALSE);
3549 }
3550 /* Change Maia skill chart after initiation */
shape_Maia_skills(int Ind)3551 void shape_Maia_skills(int Ind) {
3552 	player_type *p_ptr = Players[Ind];
3553 
3554 	switch (p_ptr->ptrait) {
3555 	case TRAIT_CORRUPTED:
3556 		/* Doh! */
3557 		p_ptr->s_info[SKILL_HOFFENSE].mod = 0;
3558 		p_ptr->s_info[SKILL_HCURING].mod = 0;
3559 		p_ptr->s_info[SKILL_HDEFENSE].mod = 0;
3560 		p_ptr->s_info[SKILL_HSUPPORT].mod = 0;
3561 
3562 		/* Yay */
3563 		do_Maia_skill(Ind, SKILL_AXE, 13);
3564 		do_Maia_skill(Ind, SKILL_MARTIAL_ARTS, 13);
3565 		do_Maia_skill(Ind, SKILL_FIRE, 17);
3566 		do_Maia_skill(Ind, SKILL_AIR, 17);
3567 		do_Maia_skill(Ind, SKILL_CONVEYANCE, 17);
3568 		do_Maia_skill(Ind, SKILL_UDUN, 20);
3569 		do_Maia_skill(Ind, SKILL_TRAUMATURGY, 30);
3570 		do_Maia_skill(Ind, SKILL_NECROMANCY, 30);
3571 		do_Maia_skill(Ind, SKILL_AURA_FEAR, 30);
3572 		do_Maia_skill(Ind, SKILL_AURA_SHIVER, 30);
3573 		do_Maia_skill(Ind, SKILL_AURA_DEATH, 30);
3574 		do_Maia_skill(Ind, SKILL_R_DARK, 17);
3575 		do_Maia_skill(Ind, SKILL_R_NETH, 17);
3576 		break;
3577 
3578 	case TRAIT_ENLIGHTENED:
3579 		/* Doh! */
3580 		p_ptr->s_info[SKILL_TRAUMATURGY].mod = 0;
3581 		p_ptr->s_info[SKILL_NECROMANCY].mod = 0;
3582 		p_ptr->s_info[SKILL_AURA_DEATH].mod = 0;
3583 
3584 		/* Yay */
3585 		do_Maia_skill(Ind, SKILL_AURA_FEAR, 30);
3586 		do_Maia_skill(Ind, SKILL_AURA_SHIVER, 30);
3587 		do_Maia_skill(Ind, SKILL_HOFFENSE, 21);
3588 		do_Maia_skill(Ind, SKILL_HCURING, 21);
3589 		do_Maia_skill(Ind, SKILL_HDEFENSE, 21);
3590 		do_Maia_skill(Ind, SKILL_HSUPPORT, 21);
3591 		do_Maia_skill(Ind, SKILL_DIVINATION, 17);
3592 		do_Maia_skill(Ind, SKILL_SWORD, 13);
3593 		do_Maia_skill(Ind, SKILL_BLUNT, 13);
3594 		do_Maia_skill(Ind, SKILL_POLEARM, 13);
3595 		do_Maia_skill(Ind, SKILL_R_LITE, 17);
3596 		do_Maia_skill(Ind, SKILL_R_MANA, 17);
3597 		break;
3598 	default: ;
3599 	}
3600 }
3601 #else /* shared player.pkg file */
shape_Maia_skills(int Ind)3602 void shape_Maia_skills(int Ind) { }
3603 #endif
3604 
3605 /*
3606  * Try to raise stats, esp. if low.		- Jir -
3607  */
check_training(int Ind)3608 static void check_training(int Ind) {
3609 	player_type *p_ptr = Players[Ind];
3610 	int train = get_skill_scale(p_ptr, SKILL_TRAINING, 50);
3611 	int i, chance, value, value2;
3612 
3613 	if (train < 1) return;
3614 
3615 	for (i = 0; i < 6; i++) {
3616 		value = p_ptr->stat_cur[i];
3617 		value2 = p_ptr->stat_ind[i];
3618 		chance = train;
3619 
3620 		value += (p_ptr->rp_ptr->r_adj[i]);
3621 		value += (p_ptr->cp_ptr->c_adj[i]);
3622 
3623 		if (value > 12) chance /= 2;
3624 		if (value > 17) chance /= 4;
3625 
3626 		/* Hack -- High stats, low chance */
3627 		if (magik(adj_str_hold[value2]) || !magik(chance)) continue;
3628 
3629 		/* Hack -- if restored, not increase */
3630 		if (!res_stat(Ind, i)) do_inc_stat(Ind, i);
3631 	}
3632 
3633 	/* Also, it can give an extra skill point */
3634 	if (magik(train)) p_ptr->skill_points++;
3635 }
3636 
3637 /*
3638  * Advance experience levels and print experience
3639  */
check_experience(int Ind)3640 void check_experience(int Ind) {
3641 	player_type *p_ptr = Players[Ind];
3642 	char str[160];
3643 
3644 	bool newlv = FALSE, reglv = FALSE;
3645 	int old_lev, i;
3646 	//long int i;
3647 #ifdef LEVEL_GAINING_LIMIT
3648 	int limit;
3649 #endif	// LEVEL_GAINING_LIMIT
3650 
3651 
3652 	/* paranoia -- fix the max level first */
3653 	if (p_ptr->lev > p_ptr->max_plv)
3654 		p_ptr->max_plv = p_ptr->lev;
3655 
3656 	/* Note current level */
3657 	old_lev = p_ptr->lev;
3658 
3659 	/* Hack -- lower limit */
3660 	if (p_ptr->exp < 0) p_ptr->exp = 0;
3661 
3662 	/* Hack -- lower limit */
3663 	if (p_ptr->max_exp < 0) p_ptr->max_exp = 0;
3664 
3665 #ifdef LEVEL_GAINING_LIMIT
3666 	/* upper limit */
3667  #ifndef ALT_EXPRATIO
3668 	limit = (s64b)((s64b)player_exp[p_ptr->max_plv] *
3669 			(s64b)p_ptr->expfact / 100L) - 1;
3670  #else
3671 	limit = (s64b)(player_exp[p_ptr->max_plv] - 1);
3672  #endif
3673 	/* Hack -- upper limit */
3674 	if (p_ptr->exp > limit) p_ptr->exp = limit;
3675 #endif	// LEVEL_GAINING_LIMIT
3676 
3677 	/* Hack -- upper limit */
3678 	if (p_ptr->exp > PY_MAX_EXP) p_ptr->exp = PY_MAX_EXP;
3679 
3680 	/* Hack -- upper limit */
3681 	if (p_ptr->max_exp > PY_MAX_EXP) p_ptr->max_exp = PY_MAX_EXP;
3682 
3683 
3684 	/* Hack -- maintain "max" experience */
3685 	if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp;
3686 
3687 	/* Redraw experience */
3688 	p_ptr->redraw |= (PR_EXP);
3689 
3690 
3691 	/* Lose levels while possible */
3692 #ifndef ALT_EXPRATIO
3693 	while ((p_ptr->lev > 1) &&
3694                (p_ptr->exp < ((s64b)((s64b)player_exp[p_ptr->lev-2] * (s64b)p_ptr->expfact / 100L))))
3695 #else
3696 	while ((p_ptr->lev > 1) &&
3697                (p_ptr->exp < (s64b)player_exp[p_ptr->lev-2]))
3698 #endif
3699 	{
3700 		/* Lose a level */
3701 		p_ptr->lev--;
3702 
3703 		clockin(Ind, 1);        /* Set player level */
3704 
3705 	}
3706 
3707 
3708 	/* Remember maximum level (the one displayed if life levels were restored right now) */
3709 #ifndef ALT_EXPRATIO
3710 	while ((p_ptr->max_lev > 1) &&
3711                (p_ptr->max_exp < ((s64b)((s64b)player_exp[p_ptr->max_lev-2] * (s64b)p_ptr->expfact / 100L))))
3712 #else
3713 	while ((p_ptr->max_lev > 1) &&
3714                (p_ptr->max_exp < (s64b)player_exp[p_ptr->max_lev-2]))
3715 #endif
3716 	{
3717 		/* Lose a level */
3718 		p_ptr->max_lev--;
3719 	}
3720 
3721 
3722 	/* Gain levels while possible */
3723 #ifndef ALT_EXPRATIO
3724 	while ((p_ptr->lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3725 			(p_ptr->exp >= ((s64b)(((s64b)player_exp[p_ptr->lev-1] * (s64b)p_ptr->expfact) / 100L))))
3726 #else
3727 	while ((p_ptr->lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3728 			(p_ptr->exp >= (s64b)player_exp[p_ptr->lev-1]))
3729 #endif
3730 	{
3731 		if (p_ptr->inval && p_ptr->lev >= 25) {
3732 			msg_print(Ind, "\377rYou cannot gain level further, wait for an admin to validate your account.");
3733 			break;
3734 //			return;
3735 		}
3736 
3737 		process_hooks(HOOK_PLAYER_LEVEL, "d", Ind);
3738 
3739 		/* Gain a level */
3740 		p_ptr->lev++;
3741 
3742 		clockin(Ind, 1);        /* Set player level */
3743 
3744 		/* Save the highest level */
3745 		if (p_ptr->lev > p_ptr->max_plv) {
3746 			p_ptr->max_plv = p_ptr->lev;
3747 
3748 			/* gain skill points */
3749 #ifdef KINGCAP_EXP
3750 			/* min cap level is 50. check how far this
3751 			character can come with the actual exp cap of
3752 			21240000 (TL Ranger level 50) and adjust skill
3753 			distribution so that characters gain 250..300
3754 			skill points in total (TLRanger..YeekWarrior)*/
3755 			for (i = 50; i < 69; i++) {
3756 				if ((((s64b)player_exp[i-1] * (s64b)p_ptr->expfact) / 100L) > 21240000) break;
3757 			}
3758 			i--;/* i now contains the maximum reachable level for
3759 			    this character, due to exp cap 21240000 */
3760 			/* now calculate his skills/level ratio.
3761 			It's (250+2.63*extraLevel) / personalCapLevel */
3762 			i = i - 50;/* i now contains the extraLevel above 50 */
3763 			i = ((250000 + (2630 * i)) / (50 + i));
3764 			if (i != ((i / 1000) * 1000)) i += 10;/* +1 against rounding probs */
3765 			i /= 10; /* i is now 500..4xx, containing the skills/levelup * 100 */
3766 			/* Give player all of his skill points except the last one: */
3767 			p_ptr->skill_points += SKILL_NB_BASE - 1;
3768 			/* Eventually give him the last one, depending on his skills/levelup ratio: */
3769 			if (rand_int(100) < (i - ((SKILL_NB_BASE - 1) * 100))) p_ptr->skill_points++;
3770 #endif
3771 #ifndef KINGCAP_EXP
3772 			p_ptr->skill_points += SKILL_NB_BASE;
3773 			if (WEAK_SKILLBONUS) {
3774 				/* calculate total bonus skill points for this
3775 				   player at level 50, save it in xsp: */
3776 				long xsp_mul = WEAK_SKILLBONUS * 1000000 / ((573000 / (100 + 35)) - 1000);
3777 				long xsp = ((573000 / (100 + p_ptr->expfact)) - 1) * xsp_mul;
3778 				xsp /= 1000000;
3779 				/* depending on his should-have-bonus give him an extra point randomly */
3780 				if (rand_int(100) < (xsp * 100 / 50)) p_ptr->skill_points++;
3781 			}
3782 #endif
3783                         if (is_older_than(&p_ptr->version, 4, 4, 8, 5, 0, 0)) p_ptr->redraw |= PR_STUDY;
3784 			p_ptr->update |= PU_SKILL_MOD;
3785 
3786 			newlv = TRUE;
3787 
3788 			/* give some stats, using Training skill */
3789 			check_training(Ind);
3790 		} else {
3791 			/* Player just regained a level he lost previously */
3792 			reglv = TRUE;
3793 		}
3794 
3795 #ifdef USE_SOUND_2010
3796 		/* see further below! */
3797 #else
3798 		sound(Ind, SOUND_LEVEL);
3799 #endif
3800 	}
3801 	/* log regaining of levels */
3802 	if (reglv) s_printf("%s has regained level %d.\n", p_ptr->name, p_ptr->lev);
3803 
3804 
3805 	/* Remember maximum level (the one displayed if life levels were restored right now) */
3806 #ifndef ALT_EXPRATIO
3807 	while ((p_ptr->max_lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3808 			(p_ptr->max_exp >= ((s64b)(((s64b)player_exp[p_ptr->max_lev-1] * (s64b)p_ptr->expfact) / 100L))))
3809 #else
3810 	while ((p_ptr->max_lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3811 			(p_ptr->max_exp >= (s64b)player_exp[p_ptr->max_lev-1]))
3812 #endif
3813 	{
3814 		/* Gain a level */
3815 		p_ptr->max_lev++;
3816 	}
3817 
3818 	/* Try to own items we previously couldn't own */
3819 	if (old_lev < p_ptr->lev) {
3820 		object_type *o_ptr;
3821 
3822 		for (i = 0; i < INVEN_PACK; i++) {
3823 			o_ptr = &p_ptr->inventory[i];
3824 			if (!o_ptr->k_idx) continue;
3825 			if (o_ptr->owner == p_ptr->id) continue;
3826 			can_use(Ind, o_ptr);
3827 		}
3828 	}
3829 
3830 	/* Redraw level-depending stuff.. */
3831 	if (old_lev != p_ptr->lev) {
3832 		/* Update some stuff */
3833 		p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SANITY);
3834 
3835 		/* Redraw some stuff */
3836 		p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_DEPTH | PR_STATE);
3837 			/* PR_STATE is only needed if player can unlearn
3838 			    techniques by dropping in levels */
3839 
3840 		/* Window stuff */
3841 		p_ptr->window |= (PW_PLAYER);
3842 
3843 		/* Window stuff - Items might be come (un)usable depending on level! */
3844 	        p_ptr->window |= (PW_INVEN | PW_EQUIP);
3845 	}
3846 
3847 	if (!newlv) {
3848 		/* Handle stuff */
3849 		handle_stuff(Ind);
3850 
3851 		return;
3852 	}
3853 
3854 
3855 	/* Message */
3856 	msg_format(Ind, "\374\377GWelcome to level %d. You have %d skill points.", p_ptr->lev, p_ptr->skill_points);
3857 	if (!is_admin(p_ptr)) {
3858 		if (p_ptr->lev == 99) l_printf("%s \\{U*** \\{g%s has attained level 99 \\{U***\n", showdate(), p_ptr->name);
3859 		else if (p_ptr->lev >= 90) l_printf("%s \\{g%s has attained level %d\n", showdate(), p_ptr->name, p_ptr->lev);
3860 		else if (old_lev < 80 && p_ptr->lev >= 80) l_printf("%s \\{g%s has attained level 80\n", showdate(), p_ptr->name);
3861 		else if (old_lev < 70 && p_ptr->lev >= 70) l_printf("%s \\{g%s has attained level 70\n", showdate(), p_ptr->name);
3862 		else if (old_lev < 60 && p_ptr->lev >= 60) l_printf("%s \\{g%s has attained level 60\n", showdate(), p_ptr->name);
3863 	}
3864 #ifdef USE_SOUND_2010
3865 	sound(Ind, "levelup", NULL, SFX_TYPE_MISC, FALSE);
3866 #endif
3867 
3868 	snprintf(str, 160, "\374\377G%s has attained level %d.", p_ptr->name, p_ptr->lev);
3869 	s_printf("%s has attained level %d.\n", p_ptr->name, p_ptr->lev);
3870 	clockin(Ind, 1);	/* Set player level */
3871 #ifdef TOMENET_WORLDS
3872 	if (cfg.worldd_lvlup) world_msg(str);
3873 #endif
3874 	msg_broadcast(Ind, str);
3875 
3876 
3877 	/* Disable certain warnings on reaching certain levels */
3878 	disable_lowlevel_warnings(p_ptr);
3879 
3880 	/* Give helpful msg about how to distribute skill points at first level-up */
3881 	if (p_ptr->newbie_hints && (old_lev == 1 || (p_ptr->skill_points == (p_ptr->max_plv - 1) * SKILL_NB_BASE))) {
3882 	    // && p_ptr->inval) /* (p_ptr->warning_skills) */
3883 		msg_print(Ind, "\374\377GHINT: Press \377gSHIFT+g\377G to distribute your skill points!");
3884 	}
3885 
3886 	if (p_ptr->warning_cloak == 2 && p_ptr->lev >= 15)
3887 		msg_print(Ind, "\374\377GHINT: You can press \377gSHIFT+v\377G to cloak your appearance.");
3888 
3889 	/* Tell player to use numpad to move diagonally */
3890 	if (old_lev < 2 && p_ptr->lev >= 2 && p_ptr->warning_numpadmove == 0) {
3891 		msg_print(Ind, "\374\377yHINT: Use the number pad keys to move, that way you can move \377odiagonally\377y too!");
3892 		msg_print(Ind, "\374\377y      (Or try using the \377orogue-like\377y key set, press \377o= 1 y\377y to enable it.)");
3893 		s_printf("warning_numpadmove: %s\n", p_ptr->name);
3894 		p_ptr->warning_numpadmove = 1;
3895 	}
3896 
3897 	/* Remind how to send chat messages */
3898 	if (old_lev < 3 && p_ptr->lev >= 3 && p_ptr->warning_chat == 0) {
3899 		p_ptr->warning_chat = 1;
3900 		msg_print(Ind, "\374\377oHINT: You can press '\377R:\377o' key to chat with other players, eg greet them!");
3901 		s_printf("warning_chat: %s\n", p_ptr->name);
3902 	}
3903 
3904 	/* Give warning message to use word-of-recall, aimed at newbies */
3905 	if (old_lev < 8 && p_ptr->lev >= 8 && p_ptr->warning_wor == 0) {
3906 		/* scan inventory for any potions */
3907 		bool found_items = FALSE;
3908 		int i;
3909 		for (i = 0; i < INVEN_PACK; i++) {
3910 			if (!p_ptr->inventory[i].k_idx) continue;
3911 			if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3912 			if (p_ptr->inventory[i].tval == TV_SCROLL &&
3913 			    p_ptr->inventory[i].sval == SV_SCROLL_WORD_OF_RECALL)
3914 				found_items = TRUE;
3915 		}
3916 		if (!found_items) {
3917 			msg_print(Ind, "\374\377yHINT: You can use scrolls of \377Rword-of-recall\377y to teleport out of a dungeon");
3918 			msg_print(Ind, "\374\377y      or back into it, making the tedious search for stairs obsolete!");
3919 			s_printf("warning_wor: %s\n", p_ptr->name);
3920 		}
3921 		p_ptr->warning_wor = 1;
3922 	}
3923 
3924 	/* Give warning message to get involved with macros, aimed at newbies */
3925 	if (old_lev < 10 && p_ptr->lev >= 10 && !p_ptr->warning_macros) {
3926 		/* scan inventory for any macroish inscriptions */
3927 		bool found_macroishness = FALSE;
3928 		int i;
3929 		for (i = 0; i < INVEN_PACK; i++)
3930 			if (p_ptr->inventory[i].k_idx &&
3931 			    p_ptr->inventory[i].note &&
3932 			    strstr(quark_str(p_ptr->inventory[i].note), "@"))
3933 				found_macroishness = TRUE;
3934 		/* give a warning if it seems as if this character doesn't use any macros ;) */
3935 		if (!found_macroishness) {
3936 			msg_print(Ind, "\374\377oHINT: Create '\377Rmacros\377o' aka hotkeys to ensure survival in critical situations!");
3937 			msg_print(Ind, "\374\377o      Press '\377R%\377o' and then '\377Rz\377o' to start the macro wizard.");
3938 			s_printf("warning_macros: %s\n", p_ptr->name);
3939 		}
3940 	}
3941 
3942 	/* Give warning message to stock wound curing potions, aimed at newbies */
3943 	if (old_lev < 12 && p_ptr->lev >= 12 && p_ptr->warning_potions == 0) {
3944 #if 1
3945 		/* scan inventory for any potions */
3946 		bool found_items = FALSE;
3947 		int i;
3948 		for (i = 0; i < INVEN_PACK; i++) {
3949 			if (!p_ptr->inventory[i].k_idx) continue;
3950 			if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3951 			if (p_ptr->inventory[i].tval == TV_POTION && (
3952 //				    p_ptr->inventory[i].sval == SV_POTION_CURE_LIGHT ||
3953 			    p_ptr->inventory[i].sval == SV_POTION_CURE_SERIOUS ||
3954 			    p_ptr->inventory[i].sval == SV_POTION_CURE_CRITICAL))
3955 				found_items = TRUE;
3956 		}
3957 		if (!found_items)
3958 #endif
3959 		{
3960 			msg_print(Ind, "\374\377oHINT: Buy potions of cure wounds from the \377Rtemple\377o in Bree. They will");
3961 			msg_print(Ind, "\374\377o      restore your hit points, ensuring your survival in critical situations.");
3962 			msg_print(Ind, "\374\377o      Ideally, create a \377Rmacro\377o for using them by a single key press!");
3963 			s_printf("warning_potions: %s\n", p_ptr->name);
3964 		}
3965 		p_ptr->warning_potions = 1;
3966 	}
3967 
3968 	/* Give warning message to utilize techniques */
3969 	if (old_lev < 15 && p_ptr->lev >= 15) {
3970 		if (p_ptr->warning_technique_melee == 0 && p_ptr->warning_technique_ranged == 0) {
3971 			msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Fighting Techniques' and 'Shooting Techniques'!");
3972 			msg_print(Ind, "\374\377y      You can also create macros for these. See the TomeNET guide for details.");
3973 			s_printf("warning_techniques: %s\n", p_ptr->name);
3974 		} else if (p_ptr->warning_technique_melee == 0) {
3975 			msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Fighting Techniques'!");
3976 			msg_print(Ind, "\374\377y      You can also create macros for these. See the TomeNET guide for details.");
3977 			s_printf("warning_technique_melee: %s\n", p_ptr->name);
3978 		} else if (p_ptr->warning_technique_ranged == 0) {
3979 			msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Shooting Techniques'!");
3980 			msg_print(Ind, "\374\377y      You can also create macros for these. See the TomeNET guide for details.");
3981 			s_printf("warning_technique_ranged: %s\n", p_ptr->name);
3982 		}
3983 		p_ptr->warning_technique_melee = p_ptr->warning_technique_ranged = 1;
3984 	}
3985 
3986 	/* Give warning message to get phase/tele means, aimed at newbies */
3987 	if (old_lev < 18 && p_ptr->lev >= 18 && p_ptr->warning_tele == 0) {
3988 #if 1
3989 		/* scan inventory for any scrolls/staves */
3990 		bool found_items = FALSE;
3991 		int i;
3992 		for (i = 0; i < INVEN_PACK; i++) {
3993 			if (!p_ptr->inventory[i].k_idx) continue;
3994 			if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3995 			if (p_ptr->inventory[i].tval == TV_SCROLL && (
3996 			    p_ptr->inventory[i].sval == SV_SCROLL_TELEPORT))
3997 				found_items = TRUE;
3998 			if (p_ptr->inventory[i].tval == TV_STAFF && (
3999 			    p_ptr->inventory[i].sval == SV_STAFF_TELEPORTATION))
4000 				found_items = TRUE;
4001 		}
4002 		if (!found_items)
4003 #endif
4004 		{
4005 			msg_print(Ind, "\374\377oHINT: Buy scrolls of teleportation from the \377RBlack Market\377o or a staff");
4006 			msg_print(Ind, "\374\377o      of teleportation from the \377RMagic Shop\377o to get out of trouble!");
4007 			msg_print(Ind, "\374\377o      Ideally, create a \377Rmacro\377o for using them by a single key press.");
4008 			s_printf("warning_tele: %s\n", p_ptr->name);
4009 		}
4010 		p_ptr->warning_tele = 1;
4011 	}
4012 
4013 	/* Introduce newly learned abilities (that depend on char level) */
4014 	/* those that depend on a race */
4015 	switch (p_ptr->prace) {
4016 	case RACE_DWARF:
4017 		if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn to climb mountains easily!");
4018 		break;
4019 	case RACE_ENT:
4020 		if (old_lev < 4 && p_ptr->lev >= 4) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4021 		if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou learn to telepathically sense animals!");
4022 		if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn to telepathically sense orcs!");
4023 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to telepathically sense trolls!");
4024 	if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn to telepathically sense giants!");
4025 		if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn to telepathically sense dragons!");
4026 		if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYou learn to telepathically sense demons!");
4027 		if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYou learn to telepathically sense evil!");
4028 	break;
4029 	case RACE_DRACONIAN:
4030 		if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou learn to telepathically sense dragons!");
4031 #ifndef ENABLE_DRACONIAN_TRAITS
4032 		if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou become more resistant to fire!");
4033 		if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou become more resistant to frost!");
4034 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou become more resistant to acid!");
4035 		if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou become more resistant to lightning!");
4036 #else
4037 		if (old_lev < 8 && p_ptr->lev >= 8) msg_print(Ind, "\374\377GYou learn how to breathe an element!");
4038 		switch (p_ptr->ptrait) {
4039 		case TRAIT_BLUE: /* Draconic Blue */
4040 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYour attacks are branded by lightning!");
4041 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou are enveloped in lightning!");
4042 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear electricity!");
4043 			break;
4044 		case TRAIT_WHITE: /* Draconic White */
4045 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou are enveloped by freezing air!");
4046 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear frost!");
4047 			break;
4048 		case TRAIT_RED: /* Draconic Red */
4049 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear fire!");
4050 			break;
4051 		case TRAIT_BLACK: /* Draconic Black */
4052 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear acid!");
4053 			break;
4054 		case TRAIT_GREEN: /* Draconic Green */
4055 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear poison!");
4056 			break;
4057 		case TRAIT_MULTI: /* Draconic Multi-hued */
4058 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to electricity!");
4059 			if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to frost!");
4060 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to fire!");
4061 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4062 			if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou develop intrinsic resistance to poison!");
4063 			break;
4064 		case TRAIT_BRONZE: /* Draconic Bronze */
4065 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to confusion!");
4066 			if (old_lev < 10 && p_ptr->lev >= 10) {
4067 				msg_print(Ind, "\374\377GYou develop intrinsic resistance to electricity!");
4068 				msg_print(Ind, "\374\377GYou develop intrinsic resistance to paralysis!");
4069 			}
4070 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4071 			break;
4072 		case TRAIT_SILVER: /* Draconic Silver */
4073 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to frost!");
4074 			if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4075 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to poison!");
4076 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4077 			break;
4078 		case TRAIT_GOLD: /* Draconic Gold */
4079 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to fire!");
4080 			if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4081 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4082 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4083 			break;
4084 		case TRAIT_LAW: /* Draconic Law */
4085 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to shards!");
4086 			if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to paralysis!");
4087 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4088 			break;
4089 		case TRAIT_CHAOS: /* Draconic Chaos */
4090 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to confusion!");
4091 			if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to chaos!");
4092 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to disenchantment!");
4093 			break;
4094 		case TRAIT_BALANCE: /* Draconic Balance */
4095 			if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to disenchantment!");
4096 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4097 			break;
4098 		case TRAIT_POWER: /* Draconic Power */
4099 			if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to blindness!");
4100 			if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4101 			break;
4102 		}
4103 #endif
4104 		if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to levitate!");
4105 		break;
4106 	case RACE_DARK_ELF:
4107 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4108 		break;
4109 	case RACE_VAMPIRE:
4110 		if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYour vision extends.");
4111 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour vision extends.");
4112 		if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYour vision extends.");
4113 		if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYour vision extends.");
4114 		if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYour vision extends.");
4115 		if (old_lev < 60 && p_ptr->lev >= 60) msg_print(Ind, "\374\377GYour vision extends.");
4116 		if (old_lev < 70 && p_ptr->lev >= 70) msg_print(Ind, "\374\377GYour vision extends.");
4117 		if (old_lev < 80 && p_ptr->lev >= 80) msg_print(Ind, "\374\377GYour vision extends.");
4118 		if (old_lev < 90 && p_ptr->lev >= 90) msg_print(Ind, "\374\377GYour vision extends.");
4119 //			if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to levitate!");
4120 		if (old_lev < 20 && p_ptr->lev >= 20) {
4121 			msg_print(Ind, "\374\377GYou are now able to turn into a vampire bat (#391)!");
4122 			msg_print(Ind, "\374\377G(Press '\377gm\377G' key and choose '\377guse innate power\377G' to polymorph.)");
4123 		}
4124 		break;
4125 #ifdef ENABLE_MAIA
4126 	case RACE_MAIA:
4127 		if (p_ptr->ptrait) break; /* In case we got *bad* exp drain for some unfathomable reason ;) */
4128 		if (old_lev < 12 && p_ptr->lev >= 12) msg_print(Ind, "\374\377GWe all have to pick our own path some time...");
4129 //			if (old_lev < 14 && p_ptr->lev >= 14) msg_print(Ind, "\374\377GYou are thirsty for blood: be it good or evil");
4130 		if (old_lev < 14 && p_ptr->lev >= 14) msg_print(Ind, "\374\377GYour soul thirsts for shaping, either enlightenment or corruption!");
4131 		if (old_lev <= 19 && p_ptr->lev >= 15 && old_lev < p_ptr->lev) {
4132 			/* Killed none? nothing happens except if we reached the threshold level */
4133 			if (p_ptr->r_killed[RI_CANDLEBEARER] == 0
4134 			    && p_ptr->r_killed[RI_DARKLING] == 0) {
4135 				/* Threshold level has been overstepped -> die */
4136 				if (old_lev == 19) {
4137 //						msg_print(Ind, "\377RYou don't deserve to live.");
4138 					msg_print(Ind, "\377RYour indecision proves you aren't ready yet to stay in this realm!");
4139 					strcpy(p_ptr->died_from, "indecisiveness");
4140 					p_ptr->deathblow = 0;
4141 					p_ptr->death = TRUE;
4142 				}
4143 				/* We're done here.. */
4144 				break;
4145 			}
4146 
4147 			/* Killed both? -> you die */
4148 			if (p_ptr->r_killed[RI_CANDLEBEARER] != 0 &&
4149 			    p_ptr->r_killed[RI_DARKLING] != 0) {
4150 				msg_print(Ind, "\377RYour indecision proves you aren't ready yet to stay in this realm!");
4151 				strcpy(p_ptr->died_from, "indecisiveness");
4152 				p_ptr->deathblow = 0;
4153 				p_ptr->death = TRUE;
4154 				/* End of story, next.. */
4155 				break;
4156 			}
4157 
4158 			/* Don't initiate earlier than at threshold level, it's a ceremony ^^ */
4159 			if (p_ptr->lev <= 19) break;
4160 
4161 			/* Modify skill tree */
4162 			if (p_ptr->r_killed[RI_CANDLEBEARER] != 0) {
4163 				//A demon appears!
4164 				msg_print(Ind, "\374\377p*** \377GYour corruption grows well within you. \377p***");
4165 				p_ptr->ptrait = TRAIT_CORRUPTED;
4166 			} else {
4167 				//An angel appears!
4168 				msg_print(Ind, "\374\377p*** \377sYou have been ordained to be order in presence of chaos. \377p***");
4169 				p_ptr->ptrait = TRAIT_ENLIGHTENED;
4170 			}
4171 
4172 			shape_Maia_skills(Ind);
4173 			calc_techniques(Ind);
4174 
4175 			p_ptr->redraw |= PR_SKILLS | PR_MISC;
4176 			p_ptr->update |= PU_SKILL_INFO | PU_SKILL_MOD;
4177 		}
4178 		break;
4179 #endif
4180 	}
4181 
4182 
4183 	/* those that depend on a class */
4184 	switch (p_ptr->pclass) {
4185 	case CLASS_ROGUE:
4186 #ifdef ENABLE_CLOAKING
4187 		if (old_lev < LEARN_CLOAKING_LEVEL && p_ptr->lev >= LEARN_CLOAKING_LEVEL) {
4188 			msg_print(Ind, "\374\377GYou learn how to cloak yourself to pass unnoticed (press '\377gSHIFT+v\377G').");
4189 			if (!p_ptr->warning_cloak) p_ptr->warning_cloak = 2;
4190 		}
4191 #endif
4192 		break;
4193 	case CLASS_RANGER:
4194 		if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn how to move through dense forests easily.");
4195 		if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn how to swim well, with heavy backpack even.");
4196 		break;
4197 	case CLASS_DRUID: /* Forms gained by Druids */
4198 		/* compare mimic_druid in defines.h */
4199 		if (old_lev < 5 && p_ptr->lev >= 5) {
4200 			msg_print(Ind, "\374\377GYou learn how to change into a Cave Bear (#160) and Panther (#198)");
4201 			msg_print(Ind, "\374\377G(Press '\377gm\377G' key and choose '\377guse innate power\377G' to polymorph.)");
4202 		}
4203 		if (old_lev < 10 && p_ptr->lev >= 10) {
4204 			msg_print(Ind, "\374\377GYou learn how to change into a Grizzly Bear (#191) and Yeti (#154)");
4205 			msg_print(Ind, "\374\377GYou learn how to walk among your brothers through deep forest.");
4206 		}
4207 		if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn how to change into a Griffon (#279) and Sasquatch (#343)");
4208 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn how to change into a Werebear (#414), Great Eagle (#335), Aranea (#963) and Great White Shark (#898)");
4209 		if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn how to change into a Wyvern (#334) and Multi-hued Hound (#513)");
4210 		if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to change into a 5-h-Hydra (#440), Minotaur (#641) and Giant Squid (#482)");
4211 		if (old_lev < 35 && p_ptr->lev >= 35) msg_print(Ind, "\374\377GYou learn how to change into a 7-h-Hydra (#614), Elder Aranea (#964) and Plasma Hound (#726)");
4212 		if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYou learn how to change into an 11-h-Hydra (#688), Giant Roc (#640) and Lesser Kraken (#740)");
4213 		if (old_lev < 45 && p_ptr->lev >= 45) msg_print(Ind, "\374\377GYou learn how to change into a Maulotaur (#723) and Winged Horror (#704)");// and Behemoth (#716)");
4214 		if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYou learn how to change into a Spectral tyrannosaur (#705), Jabberwock (#778) and Greater Kraken (775)");//Leviathan (#782)");
4215 		if (old_lev < 55 && p_ptr->lev >= 55) msg_print(Ind, "\374\377GYou learn how to change into a Horned Serpent (#1131)");
4216 		if (old_lev < 60 && p_ptr->lev >= 60) msg_print(Ind, "\374\377GYou learn how to change into a Firebird (#1127)");
4217 		break;
4218 	case CLASS_SHAMAN:
4219 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4220 		break;
4221 	case CLASS_MINDCRAFTER:
4222 		if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou learn to keep hold of your sanity!");
4223 		if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to keep strong hold of your sanity!");
4224 		break;
4225 	}
4226 
4227 	/* learn fighting techniques */
4228 	if (old_lev < mtech_lev[p_ptr->pclass][0] && p_ptr->lev >= mtech_lev[p_ptr->pclass][0])
4229 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Sprint'! (press '\377gm\377G')");
4230 	if (old_lev < mtech_lev[p_ptr->pclass][1] && p_ptr->lev >= mtech_lev[p_ptr->pclass][1])
4231 		msg_print(Ind, p_ptr->pclass == CLASS_MINDCRAFTER ?
4232 		    "\374\377GYou learn the fighting technique 'Taunt'! (press '\377gm\377G')" :
4233 		    "\374\377GYou learn the fighting technique 'Taunt'!");
4234 	if (old_lev < mtech_lev[p_ptr->pclass][3] && p_ptr->lev >= mtech_lev[p_ptr->pclass][3])
4235 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Distract'!");
4236 	if (old_lev < mtech_lev[p_ptr->pclass][7] && p_ptr->lev >= mtech_lev[p_ptr->pclass][7])
4237 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Flash bomb'!");
4238 	if (old_lev < mtech_lev[p_ptr->pclass][9] && p_ptr->lev >= mtech_lev[p_ptr->pclass][9])
4239 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Spin'!");
4240 #ifdef ENABLE_ASSASSINATE
4241 	if (old_lev < mtech_lev[p_ptr->pclass][10] && p_ptr->lev >= mtech_lev[p_ptr->pclass][10])
4242 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Assasinate'!");
4243 #endif
4244 	if (old_lev < mtech_lev[p_ptr->pclass][11] && p_ptr->lev >= mtech_lev[p_ptr->pclass][11])
4245 		msg_print(Ind, "\374\377GYou learn the fighting technique 'Berserk'!");
4246 	if (old_lev < mtech_lev[p_ptr->pclass][14] && p_ptr->lev >= mtech_lev[p_ptr->pclass][14]
4247 	    && p_ptr->total_winner)
4248 		msg_print(Ind, "\374\377GYou learn the royal fighting technique 'Shadow run'!");
4249 
4250 	/* update the client's 'm' menu for fighting techniques */
4251 	calc_techniques(Ind);
4252 	Send_skill_info(Ind, SKILL_TECHNIQUE, TRUE);
4253 
4254 
4255 #ifdef ENABLE_STANCES
4256 	/* increase SKILL_STANCE by +1 automatically (just for show :-p) if we actually have that skill */
4257 	if (get_skill(p_ptr, SKILL_STANCE) && p_ptr->lev <= 50) {
4258 		p_ptr->s_info[SKILL_STANCE].value = p_ptr->lev * 1000;
4259 		/* Update the client */
4260 		Send_skill_info(Ind, SKILL_STANCE, TRUE);
4261 		/* give message if we learn a new stance (compare cmd6.c! keep it synchronized */
4262 		msg_gained_abilities(Ind, (p_ptr-> lev - 1) * 10, SKILL_STANCE);
4263 	}
4264 #endif
4265 
4266 #if 0		/* Make fruit bat gain speed on levelling up, instead of starting out with full +10 speed bonus? */
4267 	if (p_ptr->fruit_bat == 1 && old_lev < p_ptr->lev) {
4268 		if (p_ptr->lev % 5 == 0 && p_ptr->lev <= 35) msg_print(Ind, "\374\377GYour flying abilities have improved, you have gained some speed.");
4269 	}
4270 #endif
4271 
4272 #ifdef KINGCAP_LEV
4273 	/* Added a check that (s)he's not already a king - mikaelh */
4274 //		if(p_ptr->lev == 50 && !p_ptr->total_winner) msg_print(Ind, "\374\377GYou can't gain more levels until you defeat Morgoth, Lord of Darkness!");
4275 	if (p_ptr->lev == 50 && !p_ptr->total_winner) msg_print(Ind, "\374\377G* To level up further, you must defeat Morgoth, Lord of Darkness! *");
4276 #endif
4277 
4278 	/* pvp mode cant go higher, but receives a reward maybe */
4279 	if (p_ptr->mode & MODE_PVP) {
4280 		if (get_skill(p_ptr, SKILL_MIMIC) &&
4281 		    p_ptr->pclass != CLASS_DRUID &&
4282 		    p_ptr->prace != RACE_VAMPIRE) {
4283 			msg_print(Ind, "\375\377GYou gain one free mimicry transformation of your choice!");
4284 			p_ptr->free_mimic = 1;
4285 		}
4286 		if (old_lev < MID_PVP_LEVEL && p_ptr->lev >= MID_PVP_LEVEL) {
4287 			msg_broadcast_format(Ind, "\374\377G* %s has raised in ranks greatly! *", p_ptr->name);
4288 			msg_print(Ind, "\375\377G* You have raised quite a bit in ranks of PvP characters!         *");
4289 			msg_print(Ind, "\375\377G*   For that, you just received a reward, and if you die you will *");
4290 			msg_print(Ind, "\375\377G*   also receive a deed on the next character you log in with.    *");
4291 	                give_reward(Ind, RESF_MID, "Gladiator's reward", 1, 0);
4292 		}
4293 		if (p_ptr->lev == MAX_PVP_LEVEL) {
4294 			msg_broadcast_format(Ind, "\374\377G* %s has reached the highest level available to PvP characters! *", p_ptr->name);
4295 			msg_print(Ind, "\375\377G* You have reached the highest level available to PvP characters! *");
4296 			msg_print(Ind, "\375\377G*   For that, you just received a reward, and if you die you will *");
4297 			msg_print(Ind, "\375\377G*   also receive a deed on the next character you log in with.    *");
4298 //				buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MAX);
4299 	                give_reward(Ind, RESF_HIGH, "Gladiator's reward", 1, 0);
4300 		}
4301 	}
4302 
4303 	/* Make a new copy of the skills - mikaelh */
4304 	memcpy(p_ptr->s_info_old, p_ptr->s_info, MAX_SKILLS * sizeof(skill_player));
4305 	p_ptr->skill_points_old = p_ptr->skill_points;
4306 
4307 	/* Reskilling is now possible */
4308 	p_ptr->reskill_possible = TRUE;
4309 
4310 	/* Re-check house permissions, to display doors in correct colour (level-based door access!) */
4311 	if (!p_ptr->wpos.wz) p_ptr->redraw |= PR_MAP;
4312 
4313 	/* Handle stuff */
4314 	handle_stuff(Ind);
4315 
4316 	/* Update the skill points info on the client */
4317 	Send_skill_info(Ind, 0, TRUE);
4318 }
4319 
4320 
4321 /*
4322  * Gain experience
4323  */
gain_exp(int Ind,s64b amount)4324 void gain_exp(int Ind, s64b amount) {
4325 	player_type *p_ptr = Players[Ind];//, *p_ptr2=NULL;
4326 //	int Ind2 = 0;
4327 
4328 	if (is_admin(p_ptr) && p_ptr->lev >= 99) return;
4329 
4330 	/* enforce dedicated Ironman Deep Dive Challenge character slot usage */
4331 	if (amount && (p_ptr->mode & MODE_DED_IDDC) && !in_irondeepdive(&p_ptr->wpos)) {
4332 #if 0 /* poof when gaining exp prematurely */
4333 		msg_print(Ind, "\377RYou failed to enter the Ironman Deep Dive Challenge!");
4334 		strcpy(p_ptr->died_from, "indetermination");
4335 		p_ptr->deathblow = 0;
4336                 p_ptr->death = TRUE;
4337                 return;
4338 #else /* just don't get exp */
4339 		return;
4340 #endif
4341 	}
4342 
4343 	if (p_ptr->IDDC_logscum) {
4344                 //(spammy) msg_print(Ind, "\377oThis floor has become stale, take a staircase to move on!");
4345                 return;
4346         }
4347 
4348 #ifdef IRON_TEAM_EXPERIENCE
4349 	int iron_team_members_here = 0, iron_team_limit = 0;
4350 #endif
4351 
4352 #ifdef ARCADE_SERVER
4353 return;
4354 #endif
4355 
4356 	if (amount <= 0) return;
4357 #ifdef ALT_EXPRATIO
4358 	/* New way to gain exp: Exp ratio works no longer for determining required exp
4359 	   to level up, but instead to determine how much exp you gain: */
4360 	amount = (amount * 100L) / ((s64b)p_ptr->expfact);
4361 	if (amount < 1) amount = 1;
4362 #endif
4363 
4364 	/* You cant gain xp on your land */
4365 	if (player_is_king(Ind)) return;
4366 
4367 
4368 #ifdef IRON_TEAM_EXPERIENCE
4369 	/* moved here from party_gain_exp() for implementing the 'sync'-exception */
4370 	/* Iron Teams only get exp if the whole team is on the same floor! - C. Blue */
4371 	if (p_ptr->party && parties[p_ptr->party].mode == PA_IRONTEAM) {
4372 		for (i = 1; i <= NumPlayers; i++) {
4373 			if (p_ptr->conn == NOT_CONNECTED) continue;
4374 
4375 			/* note: this line means that iron teams must not add
4376 			admins, or the members won't gain exp anymore */
4377 			if (is_admin(p_ptr)) continue;
4378 
4379 			/* player on the same dungeon level? */
4380 			if (!inarea(&p_ptr->wpos, wpos)) continue;
4381 
4382 			/* count party members on the same dlvl */
4383 			if (player_in_party(p_ptr->party, i)) iron_team_members_here++;
4384 		}
4385 
4386 		/* only gain exp if all members are here */
4387 		if (iron_team_members_here != parties[p_ptr->party].members) {
4388 			/* New: allow exception to somewhat 'sync' own exp w/ the exp of
4389 			iron team member having the most exp, to avoid falling back too much.
4390 			(most drastic example: death of everlasting char). - C. Blue */
4391 			if (p_ptr->exp >= parties[p_ptr->party].experience) return;
4392 			iron_team_limit = parties[p_ptr->party].experience;
4393 		}
4394 	}
4395 #endif
4396 
4397 
4398 	/* allow own kills to be gained */
4399 	if (p_ptr->ghost) amount = (amount * 2) / 4;
4400 
4401 #ifdef KINGCAP_LEV
4402 	/* You must defeat morgoth before being allowed level > 50
4403 	   otherwise stop 1 exp point before 51 */
4404  #ifndef ALT_EXPRATIO
4405 	if ((!p_ptr->total_winner) && (p_ptr->exp + amount + 1 >=
4406 	    ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)))) {
4407 		if (p_ptr->exp + 1 >=
4408 		    ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)))
4409 			return;
4410 		amount = ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->exp;
4411 		amount--;
4412 	}
4413  #else
4414 	if ((!p_ptr->total_winner) && (p_ptr->exp + amount + 1 >= ((s64b)player_exp[50 - 1]))) {
4415 		if (p_ptr->exp + 1 >= ((s64b)player_exp[50 - 1]))
4416 			return;
4417 		amount = ((s64b)player_exp[50 - 1]) - p_ptr->exp;
4418 		amount--;
4419 	}
4420  #endif
4421 #endif
4422 #ifdef KINGCAP_EXP
4423 	/* You must defeat morgoth before being allowed to gain more
4424 	than 21,240,000 exp which is level 50 for Draconian Ranger <- might be OUTDATED */
4425 	if ((!p_ptr->total_winner) && (p_ptr->exp + amount >= 21240000)) {
4426 		if (p_ptr->exp >= 21240000) return;
4427 		amount = 21240000 - p_ptr->exp;
4428 	}
4429 #endif
4430 
4431 	/* PvP-mode players have a level limit */
4432 	if (p_ptr->mode & MODE_PVP) {
4433 #ifndef ALT_EXPRATIO
4434 		if (p_ptr->exp + amount + 1 >= ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] *
4435 					    (s64b)p_ptr->expfact / 100L))) {
4436 			if (p_ptr->exp + 1 >= ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] *
4437 					    (s64b)p_ptr->expfact / 100L)))
4438 				return;
4439 			amount = ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->exp;
4440 			amount--;
4441 		}
4442 #else
4443 		if (p_ptr->exp + amount + 1 >= ((s64b)player_exp[MAX_PVP_LEVEL - 1])) {
4444 			if (p_ptr->exp + 1 >= ((s64b)player_exp[MAX_PVP_LEVEL - 1]))
4445 				return;
4446 			amount = ((s64b)player_exp[MAX_PVP_LEVEL - 1]) - p_ptr->exp;
4447 			amount--;
4448 		}
4449 #endif
4450 	}
4451 
4452 #ifdef IRON_TEAM_EXPERIENCE
4453 	/* new: allow players to 'sync' their exp to leading player in an iron team party */
4454 	if (iron_team_limit && (p_ptr->exp + amount > iron_team_limit))
4455 		amount = iron_team_limit - p_ptr->exp;
4456 #endif
4457 
4458 	/* Gain some experience */
4459 	p_ptr->exp += amount;
4460 
4461 	/* Slowly recover from experience drainage */
4462 	if (p_ptr->exp < p_ptr->max_exp) {
4463 #ifdef KINGCAP_LEV
4464 		/* You must defeat morgoth before beong allowed level > 50 */
4465  #ifndef ALT_EXPRATIO
4466 		if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) + 1 >= ((s64b)((s64b)player_exp[50 - 1] *
4467 		   (s64b)p_ptr->expfact / 100L)))) {
4468 			if (p_ptr->max_exp >= ((s64b)((s64b)player_exp[50 - 1] *
4469 			   (s64b)p_ptr->expfact / 100L)))
4470 				return;
4471 			amount = (((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->max_exp);
4472 			amount--;
4473 		}
4474  #else
4475 		if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) + 1 >= ((s64b)player_exp[50 - 1]))) {
4476 			if (p_ptr->max_exp >= ((s64b)player_exp[50 - 1]))
4477 				return;
4478 			amount = (((s64b)player_exp[50 - 1]) - p_ptr->max_exp);
4479 			amount--;
4480 		}
4481  #endif
4482 #endif
4483 #ifdef KINGCAP_EXP
4484 		if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) >= 21240000)) {
4485 			if (p_ptr->max_exp >= 21240000) return;
4486 			amount = (21240000 - p_ptr->max_exp);
4487 		}
4488 #endif
4489 
4490 #ifdef IRON_TEAM_EXPERIENCE
4491 		/* new: allow players to 'sync' their exp to leading player in an iron team party */
4492 		if (iron_team_limit && (p_ptr->max_exp + amount > iron_team_limit))
4493 			amount = iron_team_limit - p_ptr->max_exp;
4494 #endif
4495 
4496 		/* Gain max experience (10%) */
4497 		p_ptr->max_exp += amount / 10;
4498 	}
4499 
4500 	/* Check Experience */
4501 	check_experience(Ind);
4502 
4503 #ifdef IRON_TEAM_EXPERIENCE
4504 	/* possibly set new maximum for iron team */
4505 	if (p_ptr->party && parties[p_ptr->party].mode == PA_IRONTEAM &&
4506 	    p_ptr->max_exp > parties[p_ptr->party].experience)
4507 		parties[p_ptr->party].experience = p_ptr->max_exp;
4508 #endif
4509 }
4510 
4511 
4512 /*
4513  * Lose experience
4514  * (caused by GF_NETHER, GF_CHAOS, traps, exp-melee-hits, TY-curse)
4515  */
lose_exp(int Ind,s32b amount)4516 void lose_exp(int Ind, s32b amount) {
4517 	player_type *p_ptr = Players[Ind];
4518 
4519 	/* Amulet of Immortality */
4520 	if (p_ptr->admin_invuln) return;
4521 
4522 	if (safe_area(Ind)) return;
4523 
4524 	/* Amulet of Immortality */
4525 	if (p_ptr->admin_invuln) return;
4526 
4527 	/* Paranoia */
4528 	if (p_ptr->death) return;
4529 
4530 	/* Hack -- player is secured inside a store/house except in dungeons */
4531 	if (p_ptr->store_num != -1 && !p_ptr->wpos.wz && !bypass_invuln) return;
4532 
4533 #if 0
4534 	if (disturb) {
4535 		break_cloaking(Ind, 0);
4536 		stop_precision(Ind);
4537 	}
4538 #endif
4539 
4540 	if (p_ptr->lev == 99) {
4541 		//msg_print(Ind, "You are impervious to life force drain!");
4542 		return;
4543 	}
4544 
4545 #if 0 /* todo: get this right and all */
4546 	/* Mega-Hack -- Apply "invulnerability" */
4547 	if (p_ptr->invuln && (!bypass_invuln) && !p_ptr->invuln_applied) {
4548 		/* Hack: Just reduce exp loss flat */
4549 		amount = (amount + 1) / 2;
4550 	}
4551 #endif
4552 
4553 	/* Never drop below zero experience */
4554 	if (amount > p_ptr->exp) amount = p_ptr->exp - 1;
4555 	if (!amount) return;
4556 
4557 #if 1
4558 	if (((p_ptr->alert_afk_dam && p_ptr->afk)
4559  #ifdef ALERT_OFFPANEL_DAM
4560 	    || (p_ptr->alert_offpanel_dam && (p_ptr->panel_row_old != p_ptr->panel_row || p_ptr->panel_col_old != p_ptr->panel_col))
4561  #endif
4562 	    )
4563  #ifdef USE_SOUND_2010
4564 	    ) {
4565 		Send_warning_beep(Ind);
4566 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
4567  #else
4568 	    && p_ptr->paging == 0) {
4569 		p_ptr->paging = 1;
4570  #endif
4571 	}
4572 #endif
4573 
4574 #if 1
4575 	/* warn if taking (continuous) damage while inside a store! */
4576 	if (p_ptr->store_num != -1) {
4577  #ifdef USE_SOUND_2010
4578 		Send_warning_beep(Ind);
4579 		//sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
4580  #else
4581 		if (p_ptr->paging == 0) p_ptr->paging = 1;
4582  #endif
4583 		//all places using lose_exp() already give a message..
4584 		//msg_print(Ind, "\377RWarning - your experience is getting drained!");
4585 	}
4586 #endif
4587 
4588 	/* Lose some experience */
4589 	p_ptr->exp -= amount;
4590 
4591 	/* Check Experience */
4592 	check_experience(Ind);
4593 }
4594 
4595 
4596 /* helper function to boost a character to a specific level (for Dungeon Keeper event) */
4597 void gain_exp_to_level(int Ind, int level) {
4598 	u32b k = 0;
4599 	if (level <= 1) return;
4600 	k = player_exp[level - 2];
4601 	if (Players[Ind]->max_exp < k)
4602 		/* make up for rounding error (+99) */
4603 		gain_exp(Ind, ((k - Players[Ind]->max_exp) * Players[Ind]->expfact + 99) / 100);
4604 }
4605 
4606 
4607 
4608 /*
4609  * Hack -- Return the "automatic coin type" of a monster race
4610  * Used to allocate proper treasure when "Creeping coins" die
4611  *
4612  * XXX XXX XXX Note the use of actual "monster names"
4613  */
4614 static int get_coin_type(monster_race *r_ptr) {
4615 	cptr name = (r_name + r_ptr->name);
4616 
4617 	/* Analyze "coin" monsters */
4618 	if (r_ptr->d_char == '$') {
4619 		/* Look for textual clues */
4620 		if (strstr(name, " copper ")) return (1);
4621 		if (strstr(name, " silver ")) return (2);
4622 		if (strstr(name, " gold ")) return (10);
4623 		if (strstr(name, " mithril ")) return (16);
4624 		if (strstr(name, " adamantite ")) return (18);
4625 
4626 		/* Look for textual clues */
4627 		if (strstr(name, "Copper ")) return (1);
4628 		if (strstr(name, "Silver ")) return (2);
4629 		if (strstr(name, "Gold ")) return (10);
4630 		if (strstr(name, "Mithril ")) return (16);
4631 		if (strstr(name, "Adamantite ")) return (18);
4632 	}
4633 
4634 	/* Assume nothing */
4635 	return (0);
4636 }
4637 
4638 
4639 /*
4640  * Handle the "death" of a monster.
4641  *
4642  * Disperse treasures centered at the monster location based on the
4643  * various flags contained in the monster flags fields.
4644  *
4645  * Check for "Quest" completion when a quest monster is killed.
4646  *
4647  * Note that only the player can induce "monster_death()" on Uniques.
4648  * Thus (for now) all Quest monsters should be Uniques.
4649  *
4650  * Note that in a few, very rare, circumstances, killing Morgoth
4651  * may result in the Iron Crown of Morgoth crushing the Lead-Filled
4652  * Mace "Grond", since the Iron Crown is more important.
4653  */
4654 
4655 /* Display Zu-Aon kills in special colours:
4656  *  UxU is too flashy, lcl is possible, xcx maybe best (Nether Realm floor look preserved in msg ;) */
4657 #define ZU_AON_FLASHY_MSG
4658 
4659 void monster_death(int Ind, int m_idx) {
4660 	player_type *p_ptr = Players[Ind];
4661 	player_type *q_ptr = Players[Ind];
4662 
4663 	int	i, j, y, x, ny, nx;
4664 	int	tmp_luck = p_ptr->luck;
4665 
4666 //	int	dump_item = 0;
4667 //	int	dump_gold = 0;
4668 
4669 	int	number = 0;
4670 	int	total = 0;
4671 
4672 	char buf[160], m_name[MAX_CHARS], o_name[ONAME_LEN];
4673 	cptr titlebuf;
4674 
4675 	cave_type *c_ptr;
4676 
4677 	monster_type *m_ptr = &m_list[m_idx];
4678 	monster_race *r_ptr = race_inf(m_ptr);
4679 	bool is_Morgoth = (m_ptr->r_idx == RI_MORGOTH);
4680 	bool is_Sauron = (m_ptr->r_idx == RI_SAURON);
4681 	bool is_Pumpkin = (m_ptr->r_idx == RI_PUMPKIN1 || m_ptr->r_idx == RI_PUMPKIN2 || m_ptr->r_idx == RI_PUMPKIN3);
4682 	int credit_idx = r_ptr->dup_idx ? r_ptr->dup_idx : m_ptr->r_idx;
4683 //	bool visible = (p_ptr->mon_vis[m_idx] || (r_ptr->flags1 & RF1_UNIQUE));
4684 
4685 	bool good = (r_ptr->flags1 & RF1_DROP_GOOD) ? TRUE : FALSE;
4686 	bool great = (r_ptr->flags1 & RF1_DROP_GREAT) ? TRUE : FALSE;
4687 
4688 	bool do_gold = (!(r_ptr->flags1 & RF1_ONLY_ITEM));
4689 	bool do_item = (!(r_ptr->flags1 & RF1_ONLY_GOLD));
4690 
4691 	int force_coin = get_coin_type(r_ptr);
4692 	s16b local_quark = 0;
4693 	object_type forge;
4694 	object_type *qq_ptr;
4695 	struct worldpos *wpos;
4696 	cave_type **zcave;
4697 	int dlev, rlev, tol_lev;
4698 
4699 	int a_idx, chance, I_kind;
4700 	artifact_type *a_ptr;
4701 
4702 	bool henc_cheezed = FALSE, pvp = ((p_ptr->mode & MODE_PVP) != 0);
4703 	u32b resf_drops = make_resf(p_ptr), resf_chosen = resf_drops;
4704 
4705 
4706 	/* experimental: Zu-Aon drops only randarts */
4707 	if (m_ptr->r_idx == RI_ZU_AON || m_ptr->r_idx == RI_BAD_LUCK_BAT)
4708 		resf_drops |= (RESF_FORCERANDART | RESF_NOTRUEART);
4709 	/* Morgoth never drops true artifacts */
4710 	if (is_Morgoth) resf_drops |= RESF_NOTRUEART;
4711 
4712 	/* terminate mindcrafter charm effect */
4713 	if (m_ptr->charmedignore) {
4714 		Players[m_ptr->charmedignore]->mcharming--;
4715 		m_ptr->charmedignore = 0;
4716 	}
4717 
4718 #ifdef RPG_SERVER
4719 	/* Pet death. Update and inform the owner -the_sandman */
4720 	if (m_ptr->pet) {
4721 		for (i = NumPlayers; i > 0; i--) {
4722 			if (m_ptr->owner == Players[i]->id) {
4723 				msg_format(i, "\374\377R%s has killed your pet!", Players[Ind]->name);
4724 				msg_format(Ind, "\374\377RYou have killed %s's pet!", Players[i]->name);
4725 				Players[i]->has_pet = 0;
4726 				FREE(m_ptr->r_ptr, monster_race); //no drop, no exp.
4727 				return;
4728 			}
4729 		}
4730 	}
4731 #endif
4732 
4733 	if (cfg.henc_strictness && !p_ptr->total_winner &&
4734 	    /* p_ptr->lev more logical but harsh: */
4735 #if 1 /* player should always seek not too high-level party members compared to player's current real level? */
4736 	    m_ptr->henc - p_ptr->max_lev > MAX_PARTY_LEVEL_DIFF + 1)
4737 #else /* players may seek higher-level party members to team up with if he's died before? Weird combination so not recommended! */
4738 	    m_ptr->henc - p_ptr->max_plv > MAX_PARTY_LEVEL_DIFF + 1)
4739 #endif
4740 		henc_cheezed = TRUE;
4741 
4742 	/* Get the location */
4743 	y = m_ptr->fy;
4744 	x = m_ptr->fx;
4745 	wpos = &m_ptr->wpos;
4746 	if (!(zcave = getcave(wpos))) return;
4747 
4748 	if (ge_special_sector && /* training tower event running? and we are there? */
4749 	    wpos->wx == WPOS_ARENA_X && wpos->wy == WPOS_ARENA_Y &&
4750 	    wpos->wz == WPOS_ARENA_Z) {
4751 		monster_desc(0, m_name, m_idx, 0x00);
4752 		msg_broadcast_format(0, "\376\377S** %s has defeated %s! **", p_ptr->name, m_name);
4753 		s_printf("EVENT_RESULT: %s (%d) has defeated %s.\n", p_ptr->name, p_ptr->lev, m_name);
4754 	}
4755 
4756 	/* get monster name for damage deal description */
4757 	monster_desc(Ind, m_name, m_idx, 0x00);
4758 
4759 	process_hooks(HOOK_MONSTER_DEATH, "d", Ind);
4760 
4761 	if (season_halloween) {
4762 		/* let everyone know, so they are prepared.. >:) */
4763 		if ((m_ptr->r_idx == RI_PUMPKIN1 || m_ptr->r_idx == RI_PUMPKIN2 || m_ptr->r_idx == RI_PUMPKIN3)
4764 		    && !m_ptr->clone) {
4765 			msg_broadcast_format(0, "\374\377L**\377o%s has defeated a tasty halloween spirit!\377L**", p_ptr->name);
4766 			s_printf("HALLOWEEN: %s (%d/%d) has defeated %s.\n", p_ptr->name, p_ptr->max_plv, p_ptr->max_lev, m_name);
4767 			great_pumpkin_timer = 15 + rand_int(45);
4768 			//great_pumpkin_killer = p_ptr->id;
4769 			strcpy(great_pumpkin_killer, p_ptr->accountname);
4770 		}
4771 	} else if (season_xmas) {
4772 		if ((m_ptr->r_idx == RI_SANTA1 || m_ptr->r_idx == RI_SANTA2)
4773 		    && !m_ptr->clone) {
4774 			msg_broadcast_format(0, "\374\377L**\377oSanta dropped the presents near %s!\377L**", p_ptr->name);
4775 			s_printf("XMAS: %s (%d) has defeated %s.\n", p_ptr->name, p_ptr->max_plv, m_name);
4776 			santa_claus_timer = 60 + rand_int(120);
4777 		}
4778 	}
4779 
4780 
4781 
4782 	/*
4783 	 * Mega^3-hack: killing a 'Warrior of the Dawn' is likely to
4784 	 * spawn another in the fallen one's place!
4785 	 */
4786 	if (strstr((r_name + r_ptr->name),"the Dawn")) {
4787 		if (!(randint(20) == 13)) {
4788 			int wy = p_ptr->py, wx = p_ptr->px;
4789 			int attempts = 100;
4790 
4791 			do {
4792 				scatter(wpos, &wy, &wx,p_ptr->py,p_ptr->px, 20, 0);
4793 			} while (!(in_bounds(wy,wx) && cave_floor_bold(zcave, wy,wx)) && --attempts);
4794 
4795 			if (attempts > 0) {
4796 #if 0
4797                                 if (is_friend(m_ptr) > 0) {
4798 					if (summon_specific_friendly(wy, wx, 100, SUMMON_DAWN, FALSE)) {
4799 						if (player_can_see_bold(wy, wx))
4800 							msg_print ("A new warrior steps forth!");
4801 					}
4802 				}
4803 				else
4804 #endif
4805 				{
4806 					if (summon_specific(wpos, wy, wx, 100, m_ptr->clone + 20, SUMMON_DAWN, 1, 0)) {
4807 						if (player_can_see_bold(Ind, wy, wx))
4808 							msg_print (Ind, "A new warrior steps forth!");
4809 					}
4810 				}
4811 			}
4812 		}
4813 	}
4814 
4815 	/* One more ultra-hack: An Unmaker goes out with a big bang! */
4816 	else if (strstr((r_name + r_ptr->name),"Unmaker")) {
4817 		int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
4818 		(void)project(m_idx, 6, wpos, y, x, 150, GF_CHAOS, flg, "The Unmaker explodes for");
4819 	}
4820 
4821 	/* Pink horrors are replaced with 2 Blue horrors */
4822 	else if (strstr((r_name + r_ptr->name),"Pink horror")) {
4823 		for (i = 0; i < 2; i++) {
4824 			int wy = p_ptr->py, wx = p_ptr->px;
4825 			int attempts = 100;
4826 
4827 			do {
4828 				scatter(wpos, &wy, &wx, p_ptr->py, p_ptr->px, 3, 0);
4829 			} while (!(in_bounds(wy,wx) && cave_floor_bold(zcave, wy,wx)) && --attempts);
4830 
4831 			if (attempts > 0) {
4832 				summon_override_checks = SO_IDDC;
4833 				if (summon_specific(wpos, wy, wx, 100, 0, SUMMON_BLUE_HORROR, 1, 0)) { /* that's _not_ 2, lol */
4834 					if (player_can_see_bold(Ind, wy, wx))
4835 						msg_print (Ind, "A blue horror appears!");
4836 				}
4837 				summon_override_checks = SO_NONE;
4838 			}
4839 		}
4840 	}
4841 
4842 	/* Let monsters explode! */
4843 	for (i = 0; i < 4; i++) {
4844 		if (m_ptr->blow[i].method == RBM_EXPLODE) {
4845 			int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
4846 			int typ = GF_MISSILE;
4847 			int d_dice = m_ptr->blow[i].d_dice;
4848 			int d_side = m_ptr->blow[i].d_side;
4849 			int damage = damroll(d_dice, d_side);
4850 			int base_damage = r_ptr->blow[i].d_dice * r_ptr->blow[i].d_side; /* if monster didn't gain levels */
4851 
4852 			switch (m_ptr->blow[i].effect) {
4853 			case RBE_HURT:      typ = GF_MISSILE; break;
4854 			case RBE_POISON:    typ = GF_POIS; break;
4855 			case RBE_UN_BONUS:  typ = GF_DISENCHANT; break;
4856 			case RBE_UN_POWER:  typ = GF_MISSILE; break; /* ToDo: Apply the correct effects */
4857 			case RBE_EAT_GOLD:  typ = GF_MISSILE; break;
4858 			case RBE_EAT_ITEM:  typ = GF_MISSILE; break;
4859 			case RBE_EAT_FOOD:  typ = GF_MISSILE; break;
4860 			case RBE_EAT_LITE:  typ = GF_MISSILE; break;
4861 			case RBE_ACID:      typ = GF_ACID; break;
4862 			case RBE_ELEC:      typ = GF_ELEC; break;
4863 			case RBE_FIRE:      typ = GF_FIRE; break;
4864 			case RBE_COLD:      typ = GF_COLD; break;
4865 			case RBE_BLIND:     typ = GF_BLIND; break;
4866 			case RBE_LITE:      typ = GF_LITE; break;
4867 //			case RBE_HALLU:     typ = GF_CONFUSION; break;
4868 			case RBE_HALLU:     typ = GF_CHAOS; break;	/* CAUTION! */
4869 			case RBE_CONFUSE:   typ = GF_CONFUSION; break;
4870 			case RBE_TERRIFY:   typ = GF_MISSILE; break;
4871 			case RBE_PARALYZE:  typ = GF_MISSILE; break;
4872 			case RBE_LOSE_STR:  typ = GF_MISSILE; break;
4873 			case RBE_LOSE_DEX:  typ = GF_MISSILE; break;
4874 			case RBE_LOSE_CON:  typ = GF_MISSILE; break;
4875 			case RBE_LOSE_INT:  typ = GF_MISSILE; break;
4876 			case RBE_LOSE_WIS:  typ = GF_MISSILE; break;
4877 			case RBE_LOSE_CHR:  typ = GF_MISSILE; break;
4878 			case RBE_LOSE_ALL:  typ = GF_MISSILE; break;
4879 			case RBE_PARASITE:  typ = GF_MISSILE; break;
4880 			case RBE_SHATTER:   typ = GF_DETONATION; break;
4881 			case RBE_EXP_10:    typ = GF_MISSILE; break;
4882 			case RBE_EXP_20:    typ = GF_MISSILE; break;
4883 			case RBE_EXP_40:    typ = GF_MISSILE; break;
4884 			case RBE_EXP_80:    typ = GF_MISSILE; break;
4885 			case RBE_DISEASE:   typ = GF_POIS; break;
4886 			case RBE_TIME:      typ = GF_TIME; break;
4887 			case RBE_SANITY:    typ = GF_MISSILE; break;
4888 			}
4889 
4890 			snprintf(p_ptr->attacker, sizeof(p_ptr->attacker), "%s inflicts", m_name);
4891 			project(m_idx, 3, wpos, y, x, damage > base_damage ? base_damage : damage, typ, flg, p_ptr->attacker);
4892 			break;
4893 		}
4894 	}
4895 
4896 	/* Log-scumming in IDDC is like fighting clones */
4897 	if (p_ptr->IDDC_logscum) return;
4898 	/* enforce dedicated Ironman Deep Dive Challenge character slot usage */
4899 	if ((p_ptr->mode & MODE_DED_IDDC) && !in_irondeepdive(&p_ptr->wpos)
4900 	    && r_ptr->mexp) /* Allow kills in Bree */
4901 		return;
4902 	/* clones don't drop treasure or complete quests.. */
4903 	if (m_ptr->clone) {
4904 		/* Specialty - even for non-creditable Sauron:
4905 		   If Sauron is killed in Mt Doom, allow the player to recall! */
4906 		if (is_Sauron) {
4907 			dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
4908 			if (d_ptr->type == DI_MT_DOOM) {
4909 				dun_level *l_ptr = getfloor(&p_ptr->wpos);
4910 				l_ptr->flags1 |= LF1_IRON_RECALL;
4911 				floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
4912 			}
4913 		}
4914 
4915 		/* no credit/loot for clones */
4916 		return;
4917 	}
4918 	/* ..neither do cheezed kills */
4919 	if (henc_cheezed &&
4920 	    !is_Morgoth && /* make exception for Morgoth, so hi-lvl fallen kings can re-king */
4921 	    !is_Pumpkin) /* allow a mixed hunting group */
4922 		return;
4923 
4924 	/* Check whether a quest requested this monster dead */
4925 	if (p_ptr->quest_any_k_within_target) quest_check_goal_k(Ind, m_ptr);
4926 
4927 	dlev = getlevel(wpos);
4928 	rlev = r_ptr->level;
4929 
4930 	/* Determine how much we can drop */
4931 	if ((r_ptr->flags1 & RF1_DROP_60) && (rand_int(100) < 60)) number++;
4932 	if ((r_ptr->flags1 & RF1_DROP_90) && (rand_int(100) < 90)) number++;
4933 	if (r_ptr->flags0 & RF0_DROP_1) number++;
4934 	if (r_ptr->flags1 & RF1_DROP_1D2) number += damroll(1, 2);
4935 	if (r_ptr->flags1 & RF1_DROP_2D2) number += damroll(2, 2);
4936 	if (r_ptr->flags1 & RF1_DROP_3D2) number += damroll(3, 2);
4937 	if (r_ptr->flags1 & RF1_DROP_4D2) number += damroll(4, 2);
4938 
4939 	/* Hack -- inscribe items that a unique drops */
4940 	if (r_ptr->flags1 & RF1_UNIQUE) {
4941 		local_quark = quark_add(r_name + r_ptr->name);
4942 		unique_quark = local_quark;
4943 
4944 		/* make uniques drop a bit better than normal monsters */
4945 		tmp_luck += 20;
4946 		/* luck caps at 40 */
4947 		if (tmp_luck > 40) tmp_luck = 40;
4948 	}
4949 
4950 	/* Questors: Usually drop no items, except if specified */
4951 	if (m_ptr->questor) {
4952 		if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
4953 			if (!(q_info[m_ptr->quest].questor[m_ptr->questor_idx].drops & 0x1)) number = 0;
4954 		} else {
4955 			s_printf("QUESTOR_DEPRECATED (monster_dead)\n");
4956 			number = 0;
4957 		}
4958 	}
4959 
4960 	/* Drop some objects */
4961 	for (j = 0; j < number; j++) {
4962 		/* Try 20 times per item, increasing range */
4963 //		for (i = 0; i < 20; ++i)
4964 		{
4965 #if 0
4966 			int d = (i + 14) / 15;
4967 
4968 			/* Pick a "correct" location */
4969 			scatter(wpos, &ny, &nx, y, x, d, 0);
4970 			/* Must be "clean" floor grid */
4971 			if (!cave_clean_bold(zcave, ny, nx)) continue;
4972 
4973 			/* Access the grid */
4974 			c_ptr = &zcave[ny][nx];
4975 #endif	// 0
4976 
4977 			/* Hack -- handle creeping coins */
4978 			coin_type = force_coin;
4979 
4980 #ifdef TRADITIONAL_LOOT_LEVEL
4981 			/* Average dungeon and monster levels */
4982 			object_level = (dlev + rlev) / 2;
4983  #ifdef RANDOMIZED_LOOT_LEVEL
4984 			if (object_level < rlev) tol_lev = rlev - object_level;
4985 			else tol_lev = dlev - object_level;
4986 			if (tol_lev > 11) tol_lev = 13; /* need +12 levels of tolerance to allow depth-115 items to drop from level 80 monsters */
4987 			object_level += rand_int(tol_lev);
4988  #endif
4989 #else
4990 			/* Monster level is more important than floor level */
4991 			object_level = (dlev + rlev * 2) / 3;
4992  #ifdef RANDOMIZED_LOOT_LEVEL
4993 			if (object_level < rlev) tol_lev = rlev - object_level;
4994 			else tol_lev = dlev - object_level;
4995 			if (tol_lev > 21) tol_lev = 21; /* need +20 levels of tolerance to allow depth-115 items to drop from level 80 monsters */
4996 			object_level += rand_int(tol_lev);
4997  #endif
4998 #endif
4999 
5000 			/* No easy item hunting in towns.. */
5001 			if (wpos->wz == 0) object_level = rlev / 2;
5002 
5003 			/* Place Gold */
5004 			if (do_gold && (!do_item || (rand_int(100) < 50))) {
5005 				place_gold(wpos, y, x, 0);
5006 //				if (player_can_see_bold(Ind, ny, nx)) dump_gold++;
5007 			}
5008 
5009 			/* Place Object */
5010 			else {
5011 				place_object_restrictor = RESF_NONE;
5012 
5013 				/* hack to allow custom test l00t drop for admins: */
5014 				if (is_admin(p_ptr)) {
5015 					/* the hack works by using weapon's inscription! */
5016 					char *k_tval, *k_sval;
5017 					if (p_ptr->inventory[INVEN_WIELD].tval &&
5018 					    p_ptr->inventory[INVEN_WIELD].note &&
5019 					    (k_tval = strchr(quark_str(p_ptr->inventory[INVEN_WIELD].note), '%')) &&
5020 					    (k_sval = strchr(k_tval, ':'))
5021 					    ) {
5022 						resf_drops |= RESF_DEBUG_ITEM;
5023 						/* extract tval:sval */
5024 						/* abuse luck parameter for this */
5025 						tmp_luck = lookup_kind(atoi(k_tval + 1), atoi(k_sval + 1));
5026 						/* catch invalid items */
5027 						if (!tmp_luck) resf_drops &= ~RESF_DEBUG_ITEM;
5028 					}
5029 				}
5030 
5031 				/* generate an object and place it */
5032 				place_object(wpos, y, x, good, great, FALSE, resf_drops, r_ptr->drops, tmp_luck, ITEM_REMOVAL_NORMAL);
5033 
5034 //				if (player_can_see_bold(Ind, ny, nx)) dump_item++;
5035 			}
5036 
5037 			/* Reset the object level */
5038 			object_level = dlev;
5039 
5040 			/* Reset "coin" type */
5041 			coin_type = 0;
5042 		}
5043 	}
5044 
5045 	/* Forget it */
5046 	unique_quark = 0;
5047 
5048 	/* Take note of any dropped treasure */
5049 #if 0
5050 	/* XXX this doesn't work for now.. (not used anyway) */
5051 	if (visible && (dump_item || dump_gold)) {
5052 		/* Take notes on treasure */
5053 		lore_treasure(m_idx, dump_item, dump_gold);
5054 	}
5055 #endif
5056 
5057 	/* Get credit for unique monster kills */
5058 	if (r_ptr->flags1 & RF1_UNIQUE) {
5059 		/* Set unique monster to 'killed' for this player */
5060 		p_ptr->r_killed[m_ptr->r_idx] = 1;
5061 		Send_unique_monster(Ind, m_ptr->r_idx);
5062 		/* Set unique monster to 'helped with' for all other nearby players
5063 		   who haven't explicitely killed it yet - C. Blue */
5064 		for (i = 1; i <= NumPlayers; i++) {
5065 			if (i == Ind) continue;
5066 			if (is_admin(Players[i])) continue;
5067 			if (Players[i]->conn == NOT_CONNECTED) continue;
5068 			/* it's sufficient to just be on the same dungeon floor to get credit */
5069 			if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
5070 			/* must be in the same party though */
5071 			if (!Players[i]->party || p_ptr->party != Players[i]->party) continue;
5072 
5073 			/* Hack: '2' means 'helped' instead of 'killed' */
5074 			if (!Players[i]->r_killed[m_ptr->r_idx]) {
5075 				Players[i]->r_killed[m_ptr->r_idx] = 2;
5076 				Send_unique_monster(i, m_ptr->r_idx);
5077 			}
5078 		}
5079 	/* Get kill credit for non-uniques (important for mimics) */
5080 	//HACK: added test for m_ptr->r_idx to suppress bad msgs about 0 forms learned (exploders?)
5081 	} else if (credit_idx && p_ptr->r_killed[credit_idx] < 1000 && !m_ptr->questor) {
5082 		int before = p_ptr->r_killed[credit_idx];
5083 		i = get_skill_scale(p_ptr, SKILL_MIMIC, 100);
5084 
5085 		/* get +1 bonus credit in Ironman Deep Dive Challenge */
5086 		if (in_irondeepdive(wpos))
5087 #ifndef IDDC_MIMICRY_BOOST
5088 			p_ptr->r_killed[credit_idx]++;
5089 #else /* give a possibly greater boost than just +1 */
5090 			p_ptr->r_killed[credit_idx] += IDDC_MIMICRY_BOOST;
5091 #endif
5092 
5093 #ifdef RPG_SERVER
5094 		/* There is a 1 in (m_ptr->level - kill count)^2 chance of learning form straight away
5095 		 * to make it easier (at least statistically) getting forms in the iron server. Plus,
5096 		 * mimicked speed and hp are lowered already anyway.	- the_sandman */
5097 		if ( ( r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx] > 0 ) &&
5098 		     ( (randint((r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx]) *
5099 		     	     	(r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx])) == 1))) {
5100 			p_ptr->r_killed[credit_idx] = r_info[credit_idx].level;
5101 		} else { /* Badluck */
5102 			p_ptr->r_killed[credit_idx]++;
5103 
5104 			/* Shamans have a chance to learn E forms very quickly */
5105 			if (p_ptr->pclass == CLASS_SHAMAN && (mimic_shaman_E(credit_idx) || r_info[credit_idx].d_char == 'X'))
5106 				p_ptr->r_killed[credit_idx] += 2;
5107 		}
5108 #else
5109 		if (pvp) {
5110 			/* PvP mode chars learn forms very quickly! */
5111 			p_ptr->r_killed[credit_idx] += 3;
5112 		} else {
5113 			p_ptr->r_killed[credit_idx]++;
5114 
5115 			/* Shamans have a chance to learn E forms very quickly */
5116 			if (p_ptr->pclass == CLASS_SHAMAN && (mimic_shaman_E(credit_idx) || r_info[credit_idx].d_char == 'X'))
5117 				p_ptr->r_killed[credit_idx] += 2;
5118 		}
5119 #endif
5120 
5121 		if (p_ptr->r_killed[credit_idx] > 1000)
5122 			p_ptr->r_killed[credit_idx] = 1000;
5123 
5124 		if (i && i >= r_info[credit_idx].level &&
5125 		    (before == 0 || /* <- for level 0 townspeople */
5126 		     before < r_info[credit_idx].level) &&
5127 		    (p_ptr->r_killed[credit_idx] >= r_info[credit_idx].level ||
5128 		    /* for level 0 townspeople: */
5129 		    r_info[credit_idx].level == 0))
5130 		{
5131 			if (!((r_ptr->flags1 & RF1_UNIQUE) || (p_ptr->pclass == CLASS_DRUID) ||
5132 			    ((p_ptr->pclass == CLASS_SHAMAN) && !mimic_shaman(credit_idx)) ||
5133 			    (p_ptr->prace == RACE_VAMPIRE))) {
5134 				msg_format(Ind, "\374\377UYou have learned the form of %s! (%d)",
5135 				    r_info[credit_idx].name + r_name, credit_idx);
5136 				/* smooth transition from poly ring form to known form */
5137 				if (p_ptr->body_monster == credit_idx) p_ptr->tim_mimic = p_ptr->tim_mimic_what = 0;
5138 				if (!p_ptr->warning_mimic) {
5139 					p_ptr->warning_mimic = 1;
5140 					msg_print(Ind, "\374\377U(Press '\377ym\377U' key and choose '\377yuse innate power\377U' to polymorph.)");
5141 					s_printf("warning_mimic: %s\n", p_ptr->name);
5142 				}
5143 			}
5144 		}
5145 	}
5146 
5147 	/* Take note of the killer */
5148 	if ((r_ptr->flags1 & RF1_UNIQUE) && !pvp) {
5149 		int Ind2 = 0;
5150 		player_type *p_ptr2 = NULL;
5151 
5152 #ifdef MUCHO_RUMOURS
5153 		/*the_sandman prints a rumour */
5154 		/* print the same message other players get before it - mikaelh */
5155 		msg_print(Ind, "Suddenly a thought comes to your mind:");
5156 		fortune(Ind, TRUE);
5157 #endif
5158 
5159 		/* give credit to the killer by default */
5160 if (cfg.unikill_format) {
5161 	/* let's try with titles before the name :) -C. Blue */
5162 		titlebuf = get_ptitle(q_ptr, FALSE);
5163 
5164 		if (is_Morgoth)
5165 			snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s %s.\377v**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5166 #ifdef ZU_AON_FLASHY_MSG
5167 		else if (m_ptr->r_idx == RI_ZU_AON)
5168 			snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s %s.\377x**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5169 #endif
5170 		else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5171 			snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s %s.\377U**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5172 		else
5173 			snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s %s.\377b**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5174 } else {
5175 	/* for now disabled (works though) since we don't have telepath class
5176 	   at the moment, and party names would make the line grow too long if
5177 	   combined with title before the actual name :/ -C. Blue */
5178 		if (!Ind2) {
5179 			if (is_Morgoth)
5180 				snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s.\377v**", r_name_get(m_ptr), p_ptr->name);
5181 #ifdef ZU_AON_FLASHY_MSG
5182 			else if (m_ptr->r_idx == RI_ZU_AON)
5183 				snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s.\377x**", r_name_get(m_ptr), p_ptr->name);
5184 #endif
5185 			else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5186 				snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s.\377U**", r_name_get(m_ptr), p_ptr->name);
5187 			else
5188 				snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s.\377b**", r_name_get(m_ptr), p_ptr->name);
5189 		} else {
5190 			if (is_Morgoth)
5191 				snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by fusion %s-%s.\377v**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5192 #ifdef ZU_AON_FLASHY_MSG
5193 			else if (m_ptr->r_idx == RI_ZU_AON)
5194 				snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by fusion %s-%s.\377x**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5195 #endif
5196 			else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5197 				snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by fusion %s-%s.\377U**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5198 			else
5199 				snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by fusion %s-%s.\377b**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5200 		}
5201 
5202 		/* give credit to the party if there is a teammate on the
5203 		   level, and the level is not 0 (the town)  */
5204 		if (p_ptr->party) {
5205 			for (i = 1; i <= NumPlayers; i++) {
5206 				if ( (Players[i]->party == p_ptr->party) && (inarea(&Players[i]->wpos, &p_ptr->wpos)) && (i != Ind) && (p_ptr->wpos.wz) )
5207 				{
5208 					if (is_Morgoth)
5209 						snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s of %s.\377v**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5210 #ifdef ZU_AON_FLASHY_MSG
5211 					else if (m_ptr->r_idx == RI_ZU_AON)
5212 						snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s of %s.\377x**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5213 #endif
5214 					else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5215 						snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s of %s.\377U**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5216 					else
5217 						snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s of %s.\377b**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5218 					break;
5219 				}
5220 
5221 			}
5222 		}
5223 }
5224 
5225     if (!is_admin(p_ptr)) {
5226 #ifdef TOMENET_WORLDS
5227 		if (cfg.worldd_unideath)
5228 			world_msg(buf);
5229 		else if (cfg.worldd_pwin && is_Morgoth)
5230 			world_msg(buf);
5231 #endif
5232 		/* Tell every player */
5233 		msg_broadcast(-1, buf);
5234 		/* Log event */
5235 		s_printf("%s was slain by %s.\n", r_name_get(m_ptr), p_ptr->name);
5236 
5237 	}
5238     }
5239 
5240 	/* If the dungeon where Morgoth is killed is Ironman/Forcedown/No-Recall
5241 	   allow recalling on this particular floor, since player will lose all true arts.
5242 	   Note: If strict_etiquette is false, the player can actualy keep his arts!
5243 	   Originally for RPG_SERVER, but atm enabled for all. - C. Blue */
5244 	if (is_Morgoth
5245 #if 1 /* hm */
5246 	    && cfg.strict_etiquette
5247 #endif
5248 	    ) {
5249 		dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5250 		dun_level *l_ptr = getfloor(&p_ptr->wpos);
5251 		if ((((d_ptr->flags2 & DF2_IRON || d_ptr->flags1 & DF1_FORCE_DOWN)
5252 		    && d_ptr->maxdepth > ABS(p_ptr->wpos.wz)) ||
5253 		    (d_ptr->flags1 & DF1_NO_RECALL))
5254 		    && !(l_ptr->flags1 & LF1_IRON_RECALL)
5255 		    && !(d_ptr->flags2 & DF2_NO_EXIT_WOR)) {
5256 			/* Allow exceptional recalling.. */
5257 			l_ptr->flags1 |= LF1_IRON_RECALL;
5258 			/* ..and notify everyone on the level about it */
5259 			floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
5260 		}
5261 	}
5262 	else if (is_Sauron) {
5263 		dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5264 
5265 		/* If player killed Sauron, also mark the Shadow (formerly Necromancer) of Dol Guldur as killed!
5266 		   This is required since we now need a dungeon boss for Dol Guldur again =)
5267 		   So always kill the Shadow first, if you want his loot. - C. Blue */
5268 		p_ptr->r_killed[RI_DOL_GULDUR] = 1;
5269 
5270 		/* If Sauron is killed in Mt Doom, allow the player to recall! */
5271 		if (d_ptr->type == DI_MT_DOOM) {
5272 			dun_level *l_ptr = getfloor(&p_ptr->wpos);
5273 
5274 			l_ptr->flags1 |= LF1_IRON_RECALL;
5275 			floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
5276 		}
5277 
5278 		/* for The One Ring.. */
5279 		if (in_irondeepdive(wpos)) sauron_weakened_iddc = FALSE;
5280 		else sauron_weakened = FALSE;
5281 	}
5282 
5283 	/* Dungeon bosses often drop a dungeon-set true artifact (for now 1 in 3 chance) */
5284 	if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN)) {
5285 		dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5286 
5287 		msg_format(Ind, "\374\377UYou have conquered %s!", d_name + d_info[d_ptr->type].name);
5288 
5289 		if ((
5290 #ifdef IRONDEEPDIVE_MIXED_TYPES
5291 		    in_irondeepdive(wpos) ? (a_idx = d_info[iddc[ABS(wpos->wz)].type].final_artifact) :
5292 #endif
5293 		    (a_idx = d_info[d_ptr->type].final_artifact))
5294 		    /* hack: 0 rarity = always generate -- for Ring of Phasing! */
5295 
5296 		    && (
5297 #ifdef IRONDEEPDIVE_MIXED_TYPES
5298 		    in_irondeepdive(wpos) || //Let's reward those brave IDDC participants?
5299 #endif
5300 		    (!a_info[a_idx].rarity || !rand_int(3)))
5301 
5302 		    && !cfg.arts_disabled &&
5303 #ifdef RING_OF_PHASING_NO_TIMEOUT
5304 		    (
5305 #endif
5306 		    a_info[a_idx].cur_num == 0
5307 #ifdef RING_OF_PHASING_NO_TIMEOUT
5308 		    || a_idx == ART_PHASING)
5309 #endif
5310 		    ) {
5311 #ifdef RING_OF_PHASING_NO_TIMEOUT
5312 			/* remove current ring of phasing, so it can be dropped anew */
5313 			if (a_info[a_idx].cur_num) erase_artifact(a_idx);
5314 #endif
5315 			s_printf("preparing FINAL_ARTIFACT %d", a_idx);
5316 			a_ptr = &a_info[a_idx];
5317 			qq_ptr = &forge;
5318 			object_wipe(qq_ptr);
5319 			I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
5320 			/* Create the artifact */
5321 			invcopy(qq_ptr, I_kind);
5322 			qq_ptr->name1 = a_idx;
5323 
5324 			if (!(resf_chosen & RESF_NOTRUEART) ||
5325 			    ((resf_chosen & RESF_WINNER) && winner_artifact_p(qq_ptr))) {
5326 				/* Extract the fields */
5327 				qq_ptr->pval = a_ptr->pval;
5328 				qq_ptr->ac = a_ptr->ac;
5329 				qq_ptr->dd = a_ptr->dd;
5330 				qq_ptr->ds = a_ptr->ds;
5331 				qq_ptr->to_a = a_ptr->to_a;
5332 				qq_ptr->to_h = a_ptr->to_h;
5333 				qq_ptr->to_d = a_ptr->to_d;
5334 				qq_ptr->weight = a_ptr->weight;
5335 
5336 			    	object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5337 				s_printf(" '%s'", o_name);
5338 
5339 				handle_art_inum(a_idx);
5340 
5341 				/* Hack -- acquire "cursed" flag */
5342 				if (a_ptr->flags3 & (TR3_CURSED)) qq_ptr->ident |= (ID_CURSED);
5343 
5344 				/* Complete generation, especially level requirements check */
5345 				apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5346 
5347 				qq_ptr->note = local_quark;
5348 				qq_ptr->note_utag = strlen(quark_str(local_quark));
5349 
5350 				/* Little sanity hack for level requirements
5351 				   of the Ring of Phasing - would be 92 otherwise */
5352 				if (a_idx == ART_PHASING) {
5353 					qq_ptr->level = (60 + rand_int(6));
5354 					qq_ptr->marked2 = ITEM_REMOVAL_NEVER;
5355 				}
5356 
5357 				/* Drop the artifact from heaven */
5358 #ifdef PRE_OWN_DROP_CHOSEN
5359 				else { /* ring of phasing is never 0'ed */
5360 					qq_ptr->level = 0;
5361 					qq_ptr->owner = p_ptr->id;
5362 					qq_ptr->mode = p_ptr->mode;
5363 					determine_artifact_timeout(a_idx, wpos);
5364 				}
5365 #endif
5366 				drop_near(qq_ptr, -1, wpos, y, x);
5367 				s_printf("..dropped.\n");
5368 			} else  s_printf("..failed.\n");
5369 		} else if (
5370 #ifdef IRONDEEPDIVE_MIXED_TYPES
5371 		    in_irondeepdive(wpos) ? (I_kind = d_info[iddc[ABS(wpos->wz)].type].final_object) :
5372 #endif
5373 		    (I_kind = d_info[d_ptr->type].final_object)) {
5374 			s_printf("preparing FINAL_OBJECT %d", I_kind);
5375 			qq_ptr = &forge;
5376 			object_wipe(qq_ptr);
5377 			/* Create the object */
5378 			invcopy(qq_ptr, I_kind + 1); /* weirdness, why is it actually 1 too low? */
5379 
5380 			/* Complete generation, especially level requirements check */
5381 			apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5382 
5383 		    	object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5384 			s_printf(" '%s'", o_name);
5385 
5386 			qq_ptr->note = local_quark;
5387 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5388 
5389 			/* Drop the object from heaven */
5390 #ifdef PRE_OWN_DROP_CHOSEN
5391 			qq_ptr->level = 0;
5392 			qq_ptr->owner = p_ptr->id;
5393 			qq_ptr->mode = p_ptr->mode;
5394 			if (true_artifact_p(qq_ptr)) determine_artifact_timeout(qq_ptr->name1, wpos);
5395 #endif
5396 			drop_near(qq_ptr, -1, wpos, y, x);
5397 			s_printf("..dropped.\n");
5398 		}
5399 	}
5400 
5401 	if (r_ptr->flags1 & (RF1_DROP_CHOSEN)) {
5402 		/* Mega-Hack -- drop "winner" treasures */
5403 		if (is_Morgoth && !pvp) {
5404 			/* Hack -- an "object holder" */
5405 			object_type prize;
5406 
5407 			int num = 0;
5408 
5409 			/* Nothing left, game over... */
5410 			for (i = 1; i <= NumPlayers; i++) {
5411 				q_ptr = Players[i];
5412 				if (q_ptr->ghost) continue;
5413 				/* Make everyone in the game in the same party on the
5414 				 * same level greater than or equal to level 40 total
5415 				 * winners.
5416 				 */
5417 				if ((((p_ptr->party) && (q_ptr->party == p_ptr->party)) ||
5418 				    (q_ptr == p_ptr) ) && q_ptr->lev >= 40 && inarea(&p_ptr->wpos,&q_ptr->wpos))
5419 				{
5420 
5421 					/* Total winner */
5422 					q_ptr->total_winner = TRUE;
5423 					q_ptr->once_winner = TRUE;
5424 					s_printf("%s *** total_winner : %s (lev %d (%d,%d))\n", showtime(), q_ptr->name, q_ptr->lev, q_ptr->max_lev, q_ptr->max_plv);
5425 
5426 					s_printf("CHARACTER_WINNER: race=%s ; class=%s\n", race_info[q_ptr->prace].title, class_info[q_ptr->pclass].title);
5427 
5428 					/* Lose ironman champion status if this total_winner title was actually
5429 					   acquired after having already beaten the ironman deep dive challenge */
5430 					q_ptr->iron_winner = FALSE;
5431 
5432 					/* Redraw the "title" */
5433 					q_ptr->redraw |= (PR_TITLE);
5434 
5435 					/* Congratulations */
5436 					msg_print(i, "\377G*** CONGRATULATIONS ***");
5437 					if (q_ptr->mode & (MODE_HARD | MODE_NO_GHOST)) {
5438 						msg_format(i, "\374\377GYou have won the game and are henceforth titled '%s'!", (q_ptr->male) ? "Emperor" : "Empress");
5439 						msg_broadcast_format(i, "\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "Emperor" : "Empress", q_ptr->name);
5440 						if (!is_admin(q_ptr)) l_printf("%s \\{v%s (%d) has been crowned %s\n", showdate(), q_ptr->name, q_ptr->lev, q_ptr->male ? "emperor" : "empress");
5441 #ifdef TOMENET_WORLDS
5442 						if (cfg.worldd_pwin) world_msg(format("\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "Emperor" : "Empress", q_ptr->name));
5443 #endif
5444 					} else {
5445 						msg_format(i, "\374\377GYou have won the game and are henceforth titled '%s!'", (q_ptr->male) ? "King" : "Queen");
5446 						msg_broadcast_format(i, "\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "King" : "Queen", q_ptr->name);
5447 						if (!is_admin(q_ptr)) l_printf("%s \\{v%s (%d) has been crowned %s\n", showdate(), q_ptr->name, q_ptr->lev, q_ptr->male ? "king" : "queen");
5448 #ifdef TOMENET_WORLDS
5449 						if (cfg.worldd_pwin) world_msg(format("\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "King" : "Queen", q_ptr->name));
5450 #endif
5451 					}
5452 					msg_print(i, "\377G(You may retire (by committing suicide) when you are ready.)");
5453 
5454 					num++;
5455 
5456 					/* Set all his artifacts to double-speed timeout */
5457 					for (j = 0; j < INVEN_TOTAL; j++)
5458 						if (p_ptr->inventory[j].name1 &&
5459 						    p_ptr->inventory[j].name1 != ART_RANDART)
5460 							a_info[p_ptr->inventory[j].name1].winner = TRUE;
5461 
5462 					/* Set his retire_timer if neccecary */
5463 					if (cfg.retire_timer >= 0) {
5464 						q_ptr->retire_timer = cfg.retire_timer;
5465 						msg_format(i, "Otherwise you will retire after %s minutes of tenure.", cfg.retire_timer);
5466 					}
5467 
5468 					/* take char dump and screenshot from winning scene */
5469 					if (is_newer_than(&q_ptr->version, 4, 4, 2, 0, 0, 0)) Send_chardump(i, "-victory");
5470 
5471 #ifdef ENABLE_STANCES
5472 					/* increase SKILL_STANCE by +1 automatically (just for show :-p) if we actually have that skill */
5473 					if (get_skill(q_ptr, SKILL_STANCE) >= 45) {
5474 						/* give message if we learn a new stance (compare cmd6.c! keep it synchronized */
5475 						msg_print(i, "\374\377GYou learn how to enter Royal Rank combat stances.");
5476 						/* automatically upgrade currently taken stance power */
5477 						if (q_ptr->combat_stance) q_ptr->combat_stance_power = 3;
5478 					}
5479 #endif
5480 
5481 					if (get_skill(q_ptr, SKILL_MARTIAL_ARTS) >= 48) {
5482 	                            		msg_print(i, "\374\377GYou learn the Royal Titan's Fist technique.");
5483 				                msg_print(i, "\374\377GYou learn the Royal Phoenix Claw technique.");
5484 		                        }
5485 
5486 					if (q_ptr->lev >= 50 && q_ptr->pclass == CLASS_ROGUE) {
5487 						msg_print(i, "\374\377GYou learn the royal fighting technique 'Shadow Run'");
5488 						calc_techniques(i);
5489 						Send_skill_info(i, SKILL_TECHNIQUE, TRUE);
5490 					}
5491 				}
5492 			}
5493 
5494 			/* Paranoia (if a ghost killed Morgoth) ;) - C. Blue */
5495 		    if (num) {
5496 
5497 			/* Mega-Hack -- Prepare to make "Grond" */
5498 			invcopy(&prize, lookup_kind(TV_BLUNT, SV_GROND));
5499 			/* Mega-Hack -- Mark this item as "Grond" */
5500 			prize.name1 = ART_GROND;
5501 			/* Mega-Hack -- Actually create "Grond" */
5502 			apply_magic(wpos, &prize, -1, TRUE, TRUE, TRUE, FALSE, resf_chosen);
5503 
5504 			prize.number = num;
5505 			prize.level = 45;
5506 			prize.note = local_quark;
5507 			prize.note_utag = strlen(quark_str(local_quark));
5508 
5509 			/* Drop it in the dungeon */
5510 			if (wpos->wz) prize.marked2 = ITEM_REMOVAL_NEVER;
5511 			else prize.marked2 = ITEM_REMOVAL_DEATH_WILD;
5512 			drop_near(&prize, -1, wpos, y, x);
5513 
5514 			/* Mega-Hack -- Prepare to make "Morgoth" */
5515 			invcopy(&prize, lookup_kind(TV_CROWN, SV_MORGOTH));
5516 			/* Mega-Hack -- Mark this item as "Morgoth" */
5517 			prize.name1 = ART_MORGOTH;
5518 			/* Mega-Hack -- Actually create "Morgoth" */
5519 			apply_magic(wpos, &prize, -1, TRUE, TRUE, TRUE, FALSE, resf_chosen);
5520 
5521 			prize.number = num;
5522 			prize.level = 45;
5523 			prize.note = local_quark;
5524 			prize.note_utag = strlen(quark_str(local_quark));
5525 
5526 			/* Drop it in the dungeon */
5527 			if (wpos->wz) prize.marked2 = ITEM_REMOVAL_NEVER;
5528 			else prize.marked2 = ITEM_REMOVAL_DEATH_WILD;
5529 			drop_near(&prize, -1, wpos, y, x);
5530 
5531 
5532 			/* Special reward: 1 *great* acquirement item per player. */
5533 			i = object_level;
5534 			object_level = 127;
5535 			acquirement(wpos, y, x, num, TRUE, TRUE, RESF_WINNER | RESF_LIFE | RESF_NOTRUEART | RESF_EGOHI);
5536 			object_level = i;
5537 
5538 		    } /* Paranoia tag */
5539 
5540 			/* Hack -- instantly retire any new winners if neccecary */
5541 			if (cfg.retire_timer == 0) {
5542 				for (i = 1; i <= NumPlayers; i++) {
5543 					p_ptr = Players[i];
5544 					if (p_ptr->total_winner)
5545 						do_cmd_suicide(i);
5546 				}
5547 			}
5548 
5549 			FREE(m_ptr->r_ptr, monster_race);
5550 			return;
5551 
5552 		} else if (strstr((r_name + r_ptr->name),"Smeagol")) {
5553 			/* Get local object */
5554 			qq_ptr = &forge;
5555 
5556 			object_wipe(qq_ptr);
5557 
5558 			/* Mega-Hack -- Prepare to make a ring of invisibility */
5559 			/* Sorry, =inv is too nice.. */
5560 			//                        invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_INVIS));
5561 			invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_STEALTH));
5562 			qq_ptr->number = 1;
5563 			qq_ptr->note = local_quark;
5564 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5565 
5566 			apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5567 
5568 			qq_ptr->bpval = 5;
5569 			/* Drop it in the dungeon */
5570 			drop_near(qq_ptr, -1, wpos, y, x);
5571 
5572 	        /* finally made Robin Hood drop a Bow ;) */
5573     	        } else if (strstr((r_name + r_ptr->name),"Robin Hood, the Outlaw") && magik(50)) {
5574 			qq_ptr = &forge;
5575 			object_wipe(qq_ptr);
5576     		        invcopy(qq_ptr, lookup_kind(TV_BOW, SV_LONG_BOW));
5577 			qq_ptr->number = 1;
5578 			qq_ptr->note = local_quark;
5579 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5580 			apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, TRUE, TRUE, resf_drops);
5581 			drop_near(qq_ptr, -1, wpos, y, x);
5582 
5583 		} else if (r_ptr->flags7 & RF7_NAZGUL) {
5584 			/* Get local object */
5585 			qq_ptr = &forge;
5586 
5587 			object_wipe(qq_ptr);
5588 
5589 			/* Mega-Hack -- Prepare to make a Ring of Power */
5590 			invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_SPECIAL));
5591 			qq_ptr->number = 1;
5592 
5593 			qq_ptr->name1 = ART_RANDART;
5594 
5595 			/* Piece together a 32-bit random seed */
5596 			qq_ptr->name3 = rand_int(0xFFFF) << 16;
5597 			qq_ptr->name3 += rand_int(0xFFFF);
5598 
5599 			/* Check the tval is allowed */
5600 //			if (randart_make(qq_ptr) != NULL)
5601 
5602 			apply_magic(wpos, qq_ptr, -1, FALSE, TRUE, FALSE, FALSE, RESF_NONE);
5603 
5604 			/* Save the inscription */
5605 			/* (pfft, not so smart..) */
5606 			/*qq_ptr->note = quark_add(format("#of %s", r_name + r_ptr->name));*/
5607 			qq_ptr->bpval = m_ptr->r_idx;
5608 
5609 			/* Drop it in the dungeon */
5610 #ifdef PRE_OWN_DROP_CHOSEN
5611 			qq_ptr->level = 0;
5612 			qq_ptr->owner = p_ptr->id;
5613 			qq_ptr->mode = p_ptr->mode;
5614 #endif
5615 			drop_near(qq_ptr, -1, wpos, y, x);
5616 
5617 		/* Hack - the Dragonriders give some firestone */
5618 		} else if (r_ptr->flags3 & RF3_DRAGONRIDER) {
5619 			/* Get local object */
5620 			qq_ptr = &forge;
5621 
5622 			/* Prepare to make some Firestone */
5623 			if (magik(70)) invcopy(qq_ptr, lookup_kind(TV_FIRESTONE, SV_FIRESTONE));
5624 			else invcopy(qq_ptr, lookup_kind(TV_FIRESTONE, SV_FIRE_SMALL));
5625 			qq_ptr->number = (byte)rand_range(1,12);
5626 
5627 			/* Drop it in the dungeon */
5628 			drop_near(qq_ptr, -1, wpos, y, x);
5629 
5630 		/* PernAngband additions */
5631 		/* Mega^2-hack -- destroying the Stormbringer gives it us! */
5632 		} else if (strstr((r_name + r_ptr->name),"Stormbringer")) {
5633 			/* Get local object */
5634 			qq_ptr = &forge;
5635 
5636 			/* Prepare to make the Stormbringer */
5637 			invcopy(qq_ptr, lookup_kind(TV_SWORD, SV_BLADE_OF_CHAOS));
5638 
5639 			/* Megahack -- specify the ego */
5640 	    		qq_ptr->name2 = EGO_STORMBRINGER;
5641 
5642 			/* Piece together a 32-bit random seed */
5643 			qq_ptr->name3 = rand_int(0xFFFF) << 16;
5644 			qq_ptr->name3 += rand_int(0xFFFF);
5645 
5646 			apply_magic(wpos, qq_ptr, -1, FALSE, FALSE, FALSE, FALSE, RESF_NONE);
5647 			qq_ptr->level = 0;
5648 
5649 			qq_ptr->ident |= ID_CURSED;
5650 
5651 			/* hack for a good result */
5652 			qq_ptr->to_h = 17 + rand_int(14);
5653 			qq_ptr->to_d = 17 + rand_int(14);
5654 
5655 			/* Drop it in the dungeon */
5656 			drop_near(qq_ptr, -1, wpos, y, x);
5657 
5658 #if 0 /* currently no such book */
5659 	        /* Raal's Tomes of Destruction drop a Raal's Tome of Destruction */
5660 //	        else if ((strstr((r_name + r_ptr->name),"Raal's Tome of Destruction")) && (rand_int(100) < 20))
5661         	} else if ((strstr((r_name + r_ptr->name),"Raal's Tome of Destruction")) && (magik(1))) {
5662 			/* Get local object */
5663 			qq_ptr = &forge;
5664 
5665             		/* Prepare to make a Raal's Tome of Destruction */
5666 //                	invcopy(qq_ptr, lookup_kind(TV_MAGIC_BOOK, 8));
5667 			/* Make a Tome of the Hellflame (Udun) */
5668 	                invcopy(qq_ptr, lookup_kind(TV_BOOK, 11));
5669 
5670 			/* Drop it in the dungeon */
5671             		drop_near(qq_ptr, -1, wpos, y, x);
5672 #endif
5673 
5674 		} else if (m_ptr->r_idx == RI_LIVING_LIGHTNING) {
5675 			int tries = 100;
5676 			object_type forge_bak, forge_fallback;
5677 			qq_ptr = &forge;
5678 			/* possible loot:
5679 			    skydsm,elec rod,elec ring,elec/mana rune,mage staff,tome of wind
5680 			*/
5681 
5682 			while (tries--) {
5683 				object_wipe(qq_ptr);
5684 				invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_ELEC));
5685 				qq_ptr->number = 1;
5686 				qq_ptr->note = local_quark;
5687 				qq_ptr->note_utag = strlen(quark_str(local_quark));
5688 				apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART);
5689 				/* hack - ensure non-cursed item: */
5690 				if (qq_ptr->to_a > 0) break;
5691 			}
5692 #if 1
5693 			tries = 3000;
5694 			object_copy(&forge_bak, &forge);
5695 			object_copy(&forge_fallback, &forge);
5696 			while (qq_ptr->pval < 6 && tries--) {
5697 				object_copy(&forge, &forge_bak);
5698 				/* Piece together a 32-bit random seed */
5699 				qq_ptr->name3 = rand_int(0xFFFF) << 16;
5700 				qq_ptr->name3 += rand_int(0xFFFF);
5701 				randart_make(qq_ptr);
5702 				apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART);
5703 
5704 				/* no AGGR/AM items */
5705 				a_ptr = randart_make(qq_ptr);
5706 				if ((a_ptr->flags3 & (TR3_AGGRAVATE | TR3_NO_MAGIC))
5707 				    || artifact_power(a_ptr) < 90) {
5708 					/* hack: don't even use these for fallback */
5709 					qq_ptr->pval = 0;
5710 					continue;
5711 				}
5712 
5713 				if (qq_ptr->pval > forge_fallback.pval) object_copy(&forge_fallback, qq_ptr);
5714 			}
5715 			if (qq_ptr->pval < 6) object_copy(qq_ptr, &forge_fallback);
5716 #endif
5717 			qq_ptr->timeout = 0;
5718 			drop_near(qq_ptr, -1, wpos, y, x);
5719 
5720 			object_wipe(qq_ptr);
5721 			invcopy(qq_ptr, lookup_kind(TV_BOOK, 2));
5722 			qq_ptr->number = 1;
5723 			qq_ptr->note = local_quark;
5724 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5725 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5726 			drop_near(qq_ptr, -1, wpos, y, x);
5727 
5728 			object_wipe(qq_ptr);
5729 			invcopy(qq_ptr, lookup_kind(TV_RUNE, 5));
5730 			qq_ptr->number = 1;
5731 			qq_ptr->note = local_quark;
5732 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5733 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5734 			drop_near(qq_ptr, -1, wpos, y, x);
5735 
5736 			object_wipe(qq_ptr);
5737 			invcopy(qq_ptr, lookup_kind(TV_RUNE, 8));
5738 			qq_ptr->number = 1;
5739 			qq_ptr->note = local_quark;
5740 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5741 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5742 			drop_near(qq_ptr, -1, wpos, y, x);
5743 
5744 			object_wipe(qq_ptr);
5745 			invcopy(qq_ptr, lookup_kind(TV_ROD, SV_ROD_ELEC_BALL));
5746 			qq_ptr->number = 1;
5747 			qq_ptr->note = local_quark;
5748 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5749 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5750 			qq_ptr->name2 = EGO_RISTARI;
5751 			qq_ptr->name2b = 0;
5752 			drop_near(qq_ptr, -1, wpos, y, x);
5753 
5754 			object_wipe(qq_ptr);
5755 			invcopy(qq_ptr, lookup_kind(TV_DRAG_ARMOR, SV_DRAGON_SKY));
5756 			qq_ptr->number = 1;
5757 			qq_ptr->note = local_quark;
5758 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5759 			qq_ptr->name1 = ART_RANDART;
5760 			tries = 500;
5761 			while (tries) {
5762 				/* Piece together a 32-bit random seed */
5763 				qq_ptr->name3 = rand_int(0xFFFF) << 16;
5764 				qq_ptr->name3 += rand_int(0xFFFF);
5765 				apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART | RESF_LIFE);
5766 
5767 				a_ptr = randart_make(qq_ptr);
5768 				if (artifact_power(a_ptr) >= 105 + 5 && /* at least +1 new mod gained; and +extra bonus boost */
5769 				    qq_ptr->to_a > 0 && /* not cursed */
5770 				    !(a_ptr->flags3 & (TR3_AGGRAVATE | TR3_NO_MAGIC)))
5771 					break;
5772 				tries--;
5773 			}
5774 			if (!tries) msg_format(Ind, "RI_LIVING_LIGHTNING: Re-rolling out of tries!");
5775 
5776 			qq_ptr->timeout = 0;
5777 			drop_near(qq_ptr, -1, wpos, y, x);
5778 
5779 		} else if (m_ptr->r_idx == RI_HELLRAISER) {
5780 			/* Get local object */
5781 			qq_ptr = &forge;
5782 
5783 			object_wipe(qq_ptr);
5784 
5785 			/* Drop Scroll Of Artifact Creation along with loot */
5786 			invcopy(qq_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_ARTIFACT_CREATION));
5787 			qq_ptr->number = 1;
5788 			qq_ptr->note = local_quark;
5789 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5790 
5791 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5792 
5793 			/* Drop it in the dungeon */
5794 			drop_near(qq_ptr, -1, wpos, y, x);
5795 
5796 			/* Prepare a second reward */
5797 			object_wipe(qq_ptr);
5798 
5799 			/* Drop Potions Of Learning along with loot */
5800 #ifdef EXPAND_TV_POTION
5801 			invcopy(qq_ptr, lookup_kind(TV_POTION, SV_POTION_LEARNING));
5802 #else
5803 			invcopy(qq_ptr, lookup_kind(TV_POTION2, SV_POTION2_LEARNING));
5804 #endif
5805 			qq_ptr->number = 1;
5806 			qq_ptr->note = local_quark;
5807 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5808 
5809 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5810 
5811 			/* Drop it in the dungeon */
5812 #ifdef PRE_OWN_DROP_CHOSEN
5813 			qq_ptr->level = 0;
5814 			qq_ptr->owner = p_ptr->id;
5815 			qq_ptr->mode = p_ptr->mode;
5816 #endif
5817 			drop_near(qq_ptr, -1, wpos, y, x);
5818 
5819 		} else if (m_ptr->r_idx == RI_DOR) {
5820 			/* Get local object */
5821 			qq_ptr = &forge;
5822 
5823 #if 0
5824 			/* super-charged wands of rockets */
5825 			object_wipe(qq_ptr);
5826 			invcopy(qq_ptr, lookup_kind(TV_WAND, SV_WAND_ROCKETS));
5827 			qq_ptr->number = 2 + rand_int(2);
5828 			qq_ptr->note = local_quark;
5829 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5830 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5831 			qq_ptr->pval = qq_ptr->number * 5 + 3 + rand_int(4);
5832 			drop_near(qq_ptr, -1, wpos, y, x);
5833 #endif
5834 
5835 			/* a rod of havoc */
5836 			object_wipe(qq_ptr);
5837 			invcopy(qq_ptr, lookup_kind(TV_ROD, SV_ROD_HAVOC));
5838 			qq_ptr->number = 1;
5839 			qq_ptr->note = local_quark;
5840 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5841 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5842 			/* hack ego power */
5843 			qq_ptr->name2 = EGO_RISTARI;
5844 			qq_ptr->name2b = 0;
5845 			drop_near(qq_ptr, -1, wpos, y, x);
5846 
5847 		/* dungeon boss, but drops multiple items */
5848 		} else if (m_ptr->r_idx == RI_ZU_AON) {
5849 			dun_level *l_ptr = getfloor(&p_ptr->wpos);
5850 
5851 			l_ptr->flags2 |= LF2_COLLAPSING;
5852 			nether_realm_collapsing = TRUE;
5853 			nrc_x = m_ptr->fx;
5854 			nrc_y = m_ptr->fy;
5855 
5856 #if 1
5857 			for (i = 1; i <= NumPlayers; i++) {
5858 				if (inarea(&Players[i]->wpos, &p_ptr->wpos)
5859 				    && !is_admin(Players[i]))
5860 					l_printf("%s \\{U%s made it through the Nether Realm\n", showdate(), Players[i]->name);
5861 			}
5862 #endif
5863 
5864 			/* Get local object */
5865 			qq_ptr = &forge;
5866 			object_wipe(qq_ptr);
5867 			/* Drop Scroll Of Artifact Creation */
5868 			invcopy(qq_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_ARTIFACT_CREATION));
5869 			qq_ptr->number = 1;
5870 			qq_ptr->note = local_quark;
5871 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5872 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5873 			/* Drop it in the dungeon */
5874 			drop_near(qq_ptr, -1, wpos, y, x);
5875 
5876 			/* Prepare a second reward */
5877 			object_wipe(qq_ptr);
5878 			/* Drop Potions Of Learning along with loot */
5879 #ifdef EXPAND_TV_POTION
5880 			invcopy(qq_ptr, lookup_kind(TV_POTION, SV_POTION_LEARNING));
5881 #else
5882 			invcopy(qq_ptr, lookup_kind(TV_POTION2, SV_POTION2_LEARNING));
5883 #endif
5884 			qq_ptr->number = 1;
5885 			qq_ptr->note = local_quark;
5886 			qq_ptr->note_utag = strlen(quark_str(local_quark));
5887 			apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5888 			/* Drop it in the dungeon */
5889 #ifdef PRE_OWN_DROP_CHOSEN
5890 			qq_ptr->level = 0;
5891 			qq_ptr->owner = p_ptr->id;
5892 			qq_ptr->mode = p_ptr->mode;
5893 #endif
5894 			drop_near(qq_ptr, -1, wpos, y, x);
5895 
5896 		} else if (!pvp) {
5897 			a_idx = 0;
5898 			chance = 0;
5899 			I_kind = 0;
5900 
5901 			if (strstr((r_name + r_ptr->name)," Mardra, rider of the Gold Loranth")) {
5902 				a_idx = ART_MARDRA;
5903 				chance = 55;
5904 			} else if (strstr((r_name + r_ptr->name), "Saruman of Many Colours")) {
5905 				a_idx = ART_ELENDIL;
5906 				chance = 30;
5907 			} else if (strstr((r_name + r_ptr->name), "Hagen, son of Alberich")) { /* not in the game */
5908 				a_idx = ART_NIMLOTH;
5909 				chance = 66;
5910 			} else if (strstr((r_name + r_ptr->name), "Gothmog, the High Captain of Balrogs")) {
5911 				a_idx = ART_GOTHMOG;
5912 				chance = 80;
5913 			} else if (strstr((r_name + r_ptr->name), "Eol, the Dark Elf")) {
5914 				if (magik(25)) a_idx = ART_ANGUIREL;
5915 				else a_idx = ART_EOL;
5916 				chance = 65;
5917 			} else if (strstr((r_name + r_ptr->name), "Kronos, Lord of the Titans")) {
5918 				a_idx = ART_KRONOS;
5919 				chance = 80;
5920 			/* Wyrms have a chance of dropping The Amulet of Grom, the Wyrm Hunter: -C. Blue */
5921 			} else if ((r_ptr->flags3 & RF3_DRAGON)) {
5922 				a_idx = ART_AMUGROM;
5923 				chance = 101;
5924 
5925 				/* only powerful wyrms may have a chance of dropping it */
5926 				if ((m_ptr->maxhp < 6000) && rand_int(300)) a_idx = 0;/* strong wyrms at 6000+ */
5927 				else if ((m_ptr->maxhp >= 6000) && (m_ptr->maxhp < 10000) && rand_int(150)) a_idx = 0;
5928 				else if ((m_ptr->maxhp >= 10000) && rand_int(75)) a_idx = 0;/* gwop ^^ */
5929 			}
5930 
5931 #ifdef SEMI_PROMISED_ARTS_MODIFIER
5932 			if (chance < 100 / SEMI_PROMISED_ARTS_MODIFIER) /* never turn into zero */
5933 				chance = 1;
5934 			else if (chance < 101) /* 101 = always drops */
5935 				chance = chance * SEMI_PROMISED_ARTS_MODIFIER / 100;
5936 #endif
5937 
5938 //			if ((a_idx > 0) && ((randint(99)<chance) || (wizard)))
5939 			if ((a_idx > 0) && magik(chance) && !cfg.arts_disabled &&
5940 			    (a_info[a_idx].cur_num == 0)) {
5941 				a_ptr = &a_info[a_idx];
5942 				/* Get local object */
5943 				qq_ptr = &forge;
5944 				/* Wipe the object */
5945 				object_wipe(qq_ptr);
5946 				/* Acquire the "kind" index */
5947 				I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
5948 				/* Create the artifact */
5949 				invcopy(qq_ptr, I_kind);
5950 				/* Save the name */
5951 				qq_ptr->name1 = a_idx;
5952 
5953 				if (!(resf_chosen & RESF_NOTRUEART) ||
5954 				    ((resf_chosen & RESF_WINNER) && winner_artifact_p(qq_ptr))) {
5955 					/* Extract the fields */
5956 					qq_ptr->pval = a_ptr->pval;
5957 					qq_ptr->ac = a_ptr->ac;
5958 					qq_ptr->dd = a_ptr->dd;
5959 					qq_ptr->ds = a_ptr->ds;
5960 					qq_ptr->to_a = a_ptr->to_a;
5961 					qq_ptr->to_h = a_ptr->to_h;
5962 					qq_ptr->to_d = a_ptr->to_d;
5963 					qq_ptr->weight = a_ptr->weight;
5964 
5965 				    	object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5966 					s_printf("DROP_CHOSEN: '%s'\n", o_name);
5967 
5968 					if (local_quark) {
5969 						qq_ptr->note = local_quark;
5970 						qq_ptr->note_utag = strlen(quark_str(local_quark));
5971 					}
5972 
5973 //					random_artifact_resistance(qq_ptr);
5974 					handle_art_inum(a_idx);
5975 
5976 					/* Hack -- acquire "cursed" flag */
5977 					if (a_ptr->flags3 & (TR3_CURSED)) qq_ptr->ident |= (ID_CURSED);
5978 
5979 					/* Complete generation, especially level requirements check */
5980 					apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5981 
5982 					/* Little sanity hack for level requirements
5983 					   of the Ring of Phasing - would be 92 otherwise */
5984 					if (a_idx == ART_PHASING) {
5985 						qq_ptr->level = (60 + rand_int(6));
5986 						qq_ptr->marked2 = ITEM_REMOVAL_NEVER;
5987 					}
5988 
5989 					/* Drop the artifact from heaven */
5990 #ifdef PRE_OWN_DROP_CHOSEN
5991 					qq_ptr->level = 0;
5992 					qq_ptr->owner = p_ptr->id;
5993 					qq_ptr->mode = p_ptr->mode;
5994 					determine_artifact_timeout(a_idx, wpos);
5995 #endif
5996 					drop_near(qq_ptr, -1, wpos, y, x);
5997 				}
5998 			}
5999 		}
6000 	}
6001 
6002 #ifdef IDDC_EASY_SPEED_RINGS
6003  #if IDDC_EASY_SPEED_RINGS > 0
6004 	/* IDDC hacks: Easy speed ring obtaining */
6005 	if ((p_ptr->IDDC_flags & 0x3) &&
6006 	    //basically wyrms+ and some especially feared uniques
6007 	    (m_ptr->level >= 63 || (m_ptr->level >= 59 && (r_ptr->flags1 & RF1_UNIQUE))) &&
6008 	    (r_ptr->flags1 & (RF1_DROP_GOOD | RF1_DROP_GREAT)) &&
6009 	    //not TOO easy
6010   #if IDDC_EASY_SPEED_RINGS > 1
6011 	    !rand_int(10)) {
6012   #else
6013 	    !rand_int(15)) {
6014   #endif
6015 		s_printf("Player '%s' : IDDC_flags %d -> ", p_ptr->name, p_ptr->IDDC_flags);
6016 		p_ptr->IDDC_flags--;
6017 		s_printf("%d\n", p_ptr->IDDC_flags);
6018 
6019 		/* Get local object */
6020 		qq_ptr = &forge;
6021 		object_wipe(qq_ptr);
6022 
6023 		invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_SPEED));
6024 		qq_ptr->number = 1;
6025 		qq_ptr->note = local_quark;
6026 		qq_ptr->note_utag = strlen(quark_str(local_quark));
6027 		apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
6028 
6029 		qq_ptr->bpval = 7 + rand_int(4); //make it decent
6030 		qq_ptr->ident &= ~ID_CURSED; //paranoia
6031 
6032 		drop_near(qq_ptr, -1, wpos, y, x);
6033 	}
6034  #endif
6035 #endif
6036 
6037 	/* for when a quest giver turned non-invincible */
6038 	if (m_ptr->questor) {
6039 		if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
6040 			/* Drop a specific item? */
6041 			if (q_info[m_ptr->quest].questor[m_ptr->questor_idx].drops & 0x2)
6042 				questor_drop_specific(Ind, m_ptr->quest, m_ptr->questor_idx, wpos, x, y);
6043 			/* Quest progression/fail effect? */
6044 			questor_death(m_ptr->quest, m_ptr->questor_idx, wpos, 0);
6045 		} else {
6046 			s_printf("QUESTOR DEPRECATED (monster_dead2)\n");
6047 		}
6048 	}
6049 
6050 //        if((!force_coin)&&(randint(100)<50)) place_corpse(m_ptr);
6051 
6052 	/* Only process "Quest Monsters" */
6053 	if (!(r_ptr->flags1 & RF1_QUESTOR)) return;
6054 
6055 	/* Hack -- Mark quests as complete */
6056 	for (i = 0; i < MAX_XO_IDX; i++)
6057 	{
6058 		/* Hack -- note completed quests */
6059 		if (xo_list[i].level == r_ptr->level) xo_list[i].level = 0;
6060 
6061 		/* Count incomplete quests */
6062 		if (xo_list[i].level) total++;
6063 	}
6064 
6065 
6066 	/* Need some stairs */
6067 	if (total)
6068 	{
6069 		/* Stagger around */
6070 		while (!cave_valid_bold(zcave, y, x))
6071 		{
6072 			int d = 1;
6073 
6074 			/* Pick a location */
6075 			scatter(wpos, &ny, &nx, y, x, d, 0);
6076 
6077 			/* Stagger */
6078 			y = ny; x = nx;
6079 		}
6080 
6081 		/* Delete any old object XXX XXX XXX */
6082 		delete_object(wpos, y, x, TRUE);
6083 
6084 		/* Explain the stairway */
6085 		msg_print(Ind, "A magical stairway appears...");
6086 
6087 		/* Access the grid */
6088 		c_ptr = &zcave[y][x];
6089 
6090 		/* Create stairs down */
6091 		c_ptr->feat = FEAT_MORE;
6092 
6093 		/* Note the spot */
6094 		note_spot_depth(wpos, y, x);
6095 
6096 		/* Draw the spot */
6097 		everyone_lite_spot(wpos, y, x);
6098 
6099 		/* Remember to update everything */
6100 		p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS);
6101 	}
6102 
6103         FREE(m_ptr->r_ptr, monster_race);
6104 }
6105 
6106 /* FIXME: this function is known to be bypassable by nominally
6107  * 'party-owning'.
6108  */
6109 void kill_house_contents(house_type *h_ptr) {
6110 	struct worldpos *wpos = &h_ptr->wpos;
6111 	object_type *o_ptr;
6112 	int i;
6113 
6114 	/* hack: for PLAYER_STORES actually allocate the cave temporarily,
6115 	   just for delete_object()->delete_object_idx() to find any offered items and log their removal. */
6116 	bool must_alloc = (getcave(wpos) == NULL);
6117 	if (must_alloc) {
6118 		alloc_dungeon_level(wpos);
6119 		generate_cave(wpos, NULL);
6120 	}
6121 
6122 #ifdef USE_MANG_HOUSE
6123 	if (h_ptr->flags & HF_RECT) {
6124 		int sy, sx, ey, ex, x, y;
6125 		sy = h_ptr->y + 1;
6126 		sx = h_ptr->x + 1;
6127 		ey = h_ptr->y + h_ptr->coords.rect.height - 1;
6128 		ex = h_ptr->x + h_ptr->coords.rect.width - 1;
6129 		for (y = sy; y < ey; y++) {
6130 			for (x = sx; x < ex; x++)
6131 				delete_object(wpos, y, x, TRUE);
6132 		}
6133 
6134 		/* make sure no player gets stuck by being inside while it's sold - C. Blue */
6135 		for (i = 1; i <= NumPlayers; i++) {
6136 			if (inarea(&Players[i]->wpos, wpos) &&
6137 			    Players[i]->py >= sy && Players[i]->py <= ey &&
6138 			    Players[i]->px >= sx && Players[i]->px <= ex)
6139 				teleport_player_force(i, 1);
6140 		}
6141 	} else {
6142 		fill_house(h_ptr, FILL_CLEAR, NULL);
6143 		/* Polygonal house */
6144 
6145 		//todo: teleport any players inside out */
6146 	}
6147 #endif	// USE_MANG_HOUSE
6148 
6149 #ifndef USE_MANG_HOUSE_ONLY
6150 	for (i = 0; i < h_ptr->stock_num; i++) {
6151 		o_ptr = &h_ptr->stock[i];
6152 		if (o_ptr->k_idx && true_artifact_p(o_ptr))
6153 			handle_art_d(o_ptr->name1);
6154 		questitem_d(o_ptr, o_ptr->number);
6155 
6156 #ifdef PLAYER_STORES
6157 		/* Log removal of player store items */
6158 		if (o_ptr->note && strstr(quark_str(o_ptr->note), "@S")) {
6159 			char o_name[ONAME_LEN];//, p_name[NAME_LEN];
6160 			object_desc(0, o_name, o_ptr, TRUE, 3);
6161 			//s_printf("PLAYER_STORE_REMOVED: %s - %s (%d,%d,%d; %d,%d).\n",
6162 			s_printf("PLAYER_STORE_REMOVED: %s (%d,%d,%d; %d,%d).\n",
6163 			    //p_name, o_name, wpos->wx, wpos->wy, wpos->wz,
6164 			    o_name, wpos->wx, wpos->wy, wpos->wz,
6165 			    o_ptr->ix, o_ptr->iy);
6166 		}
6167 #endif
6168 
6169 		invwipe(o_ptr);
6170 	}
6171 	h_ptr->stock_num = 0;
6172 #endif	// USE_MANG_HOUSE_ONLY
6173 
6174 #ifdef HOUSE_PAINTING
6175 	/* Remove house paint */
6176 	h_ptr->colour = 0;
6177 	fill_house(h_ptr, FILL_UNPAINT, NULL);
6178 #endif
6179 
6180 	/* hack: reset size/price of extendable (trad) houses */
6181 	if ((h_ptr->flags & HF_TRAD)) {
6182 		int area = (h_ptr->coords.rect.width - 2) * (h_ptr->coords.rect.height - 2);
6183 		h_ptr->stock_size = (area >= STORE_INVEN_MAX) ? STORE_INVEN_MAX : area;
6184 
6185 		/* note: trad houses currently can't have sizes > 30 (compare wild.c),
6186 		   so it's sufficient to add term for medium houses + term for small houses,
6187 		   ignoring the term for large houses. */
6188 		h_ptr->dna->price = initial_house_price(h_ptr);
6189 	}
6190 
6191 	if (must_alloc) dealloc_dungeon_level(wpos);
6192 }
6193 
6194 void kill_houses(int id, byte type) {
6195 	int i;
6196 	for (i = 0; i < num_houses; i++) {
6197 		struct dna_type *dna = houses[i].dna;
6198 		if (dna->owner == id && dna->owner_type == type) {
6199 			dna->owner = 0L;
6200 			dna->creator = 0L;
6201 			dna->a_flags = ACF_NONE;
6202 			kill_house_contents(&houses[i]);
6203 		}
6204 	}
6205 }
6206 
6207 /* XXX maybe this function can delete the objects
6208  * to prevent 'house-owner char cheeze'	- Jir -
6209  */
6210 void kill_objs(int id){
6211 	int i;
6212 	object_type *o_ptr;
6213 	for (i = 0; i < o_max; i++) {
6214 		o_ptr = &o_list[i];
6215 		if (!o_ptr->k_idx) continue;
6216 		if (o_ptr->owner == id) {
6217 			o_ptr->owner = MAX_ID + 1;
6218 			/* o_ptr->mode = 0; <- makes everlasting items usable! bad! */
6219 		}
6220 	}
6221 }
6222 
6223 
6224 #define QUIT_BAN_NONE	0
6225 #define QUIT_BAN_ROLLER	1
6226 #define QUIT_BAN_ALL	2
6227 
6228 /* This function prevents DoS attack using suicide */
6229 /* ;) DoS... its just annoying. hehe */
6230 static void check_roller(int Ind) {
6231 	player_type *p_ptr = Players[Ind];
6232 	time_t now = time(&now);
6233 
6234 	/* This was necessary ;) */
6235 	if(is_admin(p_ptr)) return;
6236 
6237 	if (!cfg.quit_ban_mode) return;
6238 
6239 	if (cfg.quit_ban_mode == QUIT_BAN_ROLLER) {
6240 		/* (s)he should have played somewhat */
6241 		if (p_ptr->max_exp) return;
6242 
6243 		/* staying for more than 60 seconds? */
6244 		if (now - lookup_player_laston(p_ptr->id) > 60) return;
6245 
6246 		/* died to a townie?
6247 		if (p_ptr->ghost) return; */
6248 	}
6249 
6250 	/* ban her/him for 1 min */
6251 	add_banlist(p_ptr->accountname, NULL, p_ptr->hostname, 1, "Suicide spam");
6252 }
6253 
6254 
6255 static void check_killing_reward(int Ind) {
6256 	player_type *p_ptr = Players[Ind];
6257 
6258 	/* reward top gladiators */
6259 	if (p_ptr->kills >= 10) {
6260 		/* reset! */
6261 		//p_ptr->kills -= 10;
6262 		p_ptr->kills = 0;
6263 
6264 		msg_broadcast_format(Ind, "\374\377y** %s vanquished 10 opponents! **", p_ptr->name);
6265 		msg_print(Ind, "\375\377G* Another 10 aggressors have fallen by your hands! *");
6266 		msg_print(Ind, "\375\377G* You received a reward! *");
6267                 give_reward(Ind, RESF_MID, "Gladiator's reward", 1, 0);
6268 	}
6269 }
6270 
6271 /* deletes a ghost-dead player, cleans up his business, and disconnects him */
6272 static void erase_player(int Ind, int death_type, bool static_floor) {
6273 	player_type *p_ptr = Players[Ind];
6274 	char buf[1024];
6275 	int i;
6276 
6277 	kill_houses(p_ptr->id, OT_PLAYER);
6278 	rem_xorder(p_ptr->xorder_id);
6279 	kill_objs(p_ptr->id);
6280 	p_ptr->death = TRUE;
6281 
6282 #ifdef AUCTION_SYSTEM
6283 	auction_player_death(p_ptr->id);
6284 #endif
6285 
6286 	/* Remove him from his party/guild */
6287 	if (p_ptr->party) {
6288 		/* He leaves */
6289 		party_leave(Ind, FALSE);
6290 	}
6291 	if (p_ptr->guild) {
6292 		if ((guilds[p_ptr->guild].flags & GFLG_AUTO_READD)) {
6293 			acc_set_guild(p_ptr->accountname, p_ptr->guild);
6294 			acc_set_guild_dna(p_ptr->accountname, p_ptr->guild_dna);
6295 		}
6296 		if ((p_ptr->guild_flags & PGF_ADDER))
6297 			acc_set_flags(p_ptr->accountname, ACC_GUILD_ADDER, TRUE);
6298 		guild_leave(Ind, FALSE);
6299 	}
6300 
6301 	/* Ghosts dont static the lvl if under cfg_preserve_death_level ft. DEG */
6302 	if (static_floor && getlevel(&p_ptr->wpos) < cfg.preserve_death_level) {
6303 		struct worldpos old_wpos;
6304 		/*
6305 		 * HACK - Change the wpos temporarily so that new_players_on_depth
6306 		 * won't think that the player is on the level - mikaelh
6307 		 */
6308 		wpcopy(&old_wpos, &p_ptr->wpos);
6309 		p_ptr->wpos.wz++;
6310 		new_players_on_depth(&old_wpos, -1, TRUE);
6311 		p_ptr->wpos.wz--;
6312 	}
6313 
6314 	buffer_account_for_event_deed(p_ptr, death_type);
6315 
6316 	/* temporarily reserve his character name in case he want's to remake that character */
6317 	for (i = 0; i < MAX_RESERVED_NAMES; i++) {
6318 		if (reserved_name_character[i][0]) continue;
6319 
6320 		strcpy(reserved_name_character[i], p_ptr->name);
6321 		strcpy(reserved_name_account[i], p_ptr->accountname);
6322 		reserved_name_timeout[i] = 60 * 24; //minutes
6323 		break;
6324 	}
6325 	if (i == MAX_RESERVED_NAMES)
6326 		s_printf("Warning: Coudln't reserve character name '%s' for account '%s'!\n", p_ptr->name, p_ptr->accountname);
6327 
6328 	/* Remove him from the player name database */
6329 	delete_player_name(p_ptr->name);
6330 
6331 	/* Put him on the high score list */
6332 	if(!p_ptr->noscore && !(p_ptr->mode & (MODE_PVP | MODE_EVERLASTING)))
6333 		add_high_score(Ind);
6334 
6335 	/* Format string for death reason */
6336 	if (death_type == DEATH_QUIT) strcpy(buf, "Committed suicide");
6337 	else if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
6338 		snprintf(buf, sizeof(buf), "Killed by %s (%d pts)", p_ptr->really_died_from, total_points(Ind));
6339 	else snprintf(buf, sizeof(buf), "Killed by %s (%d pts)", p_ptr->died_from, total_points(Ind));
6340 
6341 	/* Get rid of him */
6342 	Destroy_connection(p_ptr->conn, buf);
6343 }
6344 
6345 static void inven_death_damage(int Ind, int verbose) {
6346 	player_type *p_ptr = Players[Ind];
6347 	object_type *o_ptr;
6348 	char o_name[ONAME_LEN];
6349 	int shuffle[INVEN_PACK];
6350 	int inventory_loss = 0;
6351 	int i, j, k;
6352 
6353 	for (i = 0; i < INVEN_PACK; i++) shuffle[i] = i;
6354 	intshuffle(shuffle, INVEN_PACK);
6355 
6356 	/* Destroy some items randomly */
6357 	for (i = 0; i < INVEN_PACK; i++) {
6358 		j = shuffle[i];
6359 		o_ptr = &p_ptr->inventory[j];
6360 		if (!o_ptr->k_idx) continue;
6361 
6362 		/* hack: don't discard his remaining gold - a penalty was already deducted from it */
6363 		if (o_ptr->tval == TV_GOLD) continue;
6364 		/* guild keys are supposedly indestructible, so whatever.. */
6365 		if (o_ptr->tval == TV_KEY && o_ptr->sval == SV_GUILD_KEY) continue;
6366 #ifdef DEATH_PACK_ITEM_NICE
6367 		/* don't be too nasty to magic device users */
6368 		if (is_magic_device(o_ptr->tval)) {
6369 			k = object_value_real(0, o_ptr);
6370 			if (k >= 2000 && rand_int(2)) continue;//basic bolt rods
6371 			if (k >= 30000 && rand_int(2)) continue;//anni wand (rocket,havoc)
6372 		}
6373 		/* ..and to rare book carriers */
6374 		if (o_ptr->tval == TV_BOOK &&
6375 		    (o_ptr->sval == SV_CUSTOM_TOME_2 || o_ptr->sval == SV_CUSTOM_TOME_3)
6376 		    && rand_int(2))
6377 			continue;
6378 #endif
6379 
6380 		if (magik(DEATH_PACK_ITEM_LOST)) {
6381 			object_desc(Ind, o_name, o_ptr, TRUE, 3);
6382 			s_printf("item_lost: %s (slot %d)\n", o_name, j);
6383 
6384 			if (verbose) {
6385 				/* Message */
6386 				msg_format(Ind, "\376\377oYour %s %s destroyed!", o_name,
6387 				                ((o_ptr->number > 1) ? "were" : "was"));
6388 			}
6389 
6390 			if (true_artifact_p(o_ptr)) {
6391 				/* set the artifact as unfound */
6392 				handle_art_d(o_ptr->name1);
6393 			}
6394 			questitem_d(o_ptr, o_ptr->number);
6395 
6396 			inven_item_increase(Ind, j, -(o_ptr->number));
6397 			inven_item_optimize(Ind, j);
6398 			inventory_loss++;
6399 
6400 			if (inventory_loss >= 4) {
6401 				break;
6402 			}
6403 		}
6404 	}
6405 }
6406 
6407 static void equip_death_damage(int Ind, int verbose) {
6408 	player_type *p_ptr = Players[Ind];
6409 	object_type *o_ptr;
6410 	char o_name[ONAME_LEN];
6411 	int shuffle[INVEN_TOTAL];
6412 	int equipment_loss = 0;
6413 	int i, j;
6414 
6415 	for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) shuffle[i] = i;
6416 	intshuffle(shuffle + INVEN_WIELD, INVEN_EQ);
6417 
6418 	/* Destroy some items randomly */
6419 	for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) {
6420 		j = shuffle[i];
6421 		o_ptr = &p_ptr->inventory[j];
6422 		if (!o_ptr->k_idx) continue;
6423 
6424 		if (magik(DEATH_EQ_ITEM_LOST)) {
6425 			object_desc(Ind, o_name, o_ptr, TRUE, 3);
6426 			s_printf("item_lost: %s (slot %d)\n", o_name, j);
6427 
6428 			if (verbose) {
6429 				/* Message */
6430 				msg_format(Ind, "\376\377oYour %s %s destroyed!", o_name,
6431 				                ((o_ptr->number > 1) ? "were" : "was"));
6432 			}
6433 
6434 			if (true_artifact_p(o_ptr)) {
6435 				/* set the artifact as unfound */
6436 				handle_art_d(o_ptr->name1);
6437 			}
6438 			questitem_d(o_ptr, o_ptr->number);
6439 
6440 			inven_item_increase(Ind, j, -(o_ptr->number));
6441 			inven_item_optimize(Ind, j);
6442 			equipment_loss++;
6443 
6444 			if (equipment_loss >= 1) {
6445 				break;
6446 			}
6447 		}
6448 	}
6449 }
6450 
6451 /*
6452  * Handle the death of a player and drop their stuff.
6453  */
6454 
6455  /*
6456   HACKED to handle fruit bat
6457   changed so players remain in the team when killed
6458   changed so when leader ghosts perish the team is disbanded
6459   -APD-
6460  */
6461 
6462 void player_death(int Ind) {
6463 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
6464 	int Ind2;
6465 	object_type *o_ptr;
6466 	monster_type *m_ptr;
6467 	dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
6468 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
6469 	char buf[1024], m_name_extra[MNAME_LEN], msg_layout = 'a';
6470 	int i, k, j, tries = 0;
6471 #if 0
6472 	int inventory_loss = 0, equipment_loss = 0;
6473 #endif
6474 //	int inven_sort_map[INVEN_TOTAL];
6475 	//wilderness_type *wild;
6476 	bool hell = TRUE, secure = FALSE, ge_secure = FALSE, pvp = ((p_ptr->mode & MODE_PVP) != 0), erase = FALSE, insanity = streq(p_ptr->died_from, "insanity");
6477 	cptr titlebuf;
6478 	int death_type = -1; /* keep track of the way (s)he died, for buffer_account_for_event_deed() */
6479 	bool world_broadcast = TRUE, just_fruitbat_transformation = (p_ptr->fruit_bat == -1);
6480 	bool was_total_winner = p_ptr->total_winner, retire = FALSE;
6481 	bool in_iddc = in_irondeepdive(&p_ptr->wpos);
6482 
6483 #ifdef SHOW_REALLY_DIED_FROM
6484 	if ((streq(p_ptr->died_from, "It") || p_ptr->image
6485  #ifdef SHOW_REALLY_DIED_FROM_INSANITY
6486 	    || insanity
6487  #endif
6488 	    ) && !(
6489  #ifndef SHOW_REALLY_DIED_FROM_INSANITY
6490 	    insanity ||
6491  #endif
6492 	    streq(p_ptr->died_from, "indecisiveness") ||
6493 	    streq(p_ptr->died_from, "indetermination"))
6494 	    && p_ptr->really_died_from[0]) //paranoia?
6495 		strcpy(p_ptr->died_from, p_ptr->really_died_from);
6496 #endif
6497 
6498 	/* character-intrinsic conditions violated -> unpreventable no-ghost death */
6499 	if (streq(p_ptr->died_from, "indecisiveness") ||
6500 	    streq(p_ptr->died_from, "indetermination"))
6501 		erase = TRUE;
6502 
6503 	/* Amulet of immortality prevents death */
6504 	if (!erase && p_ptr->admin_invuln) {
6505 		if (just_fruitbat_transformation) p_ptr->fruit_bat = 0;
6506 		return;
6507 	}
6508 
6509 	/* prepare player's title */
6510 	titlebuf = get_ptitle(p_ptr, FALSE);
6511 
6512 	break_cloaking(Ind, 0);
6513 	break_shadow_running(Ind);
6514 	stop_precision(Ind);
6515 	stop_shooting_till_kill(Ind);
6516 
6517 	if (just_fruitbat_transformation) {
6518 		p_ptr->death = FALSE;
6519 		p_ptr->update |= (PU_BONUS);
6520 		p_ptr->redraw |= (PR_HP | PR_GOLD | PR_BASIC | PR_DEPTH);
6521 		p_ptr->notice |= (PN_COMBINE | PN_REORDER);
6522 		p_ptr->window |= (PW_INVEN | PW_EQUIP);
6523 		p_ptr->fruit_bat = 2;
6524 		calc_hitpoints(Ind);
6525 
6526 		/* Tell the players */
6527 		snprintf(buf, sizeof(buf), "\374\377o%s was turned into a fruit bat by %s!", p_ptr->name, p_ptr->died_from);
6528 		/* handle the secret_dungeon_master option */
6529 		if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)) {
6530 #ifdef TOMENET_WORLDS
6531 			if (cfg.worldd_pdeath) world_msg(buf);
6532 #endif
6533 			msg_broadcast(Ind, buf);
6534 		}
6535 		return;
6536 	}
6537 
6538 #ifdef RPG_SERVER
6539 	if (p_ptr->wpos.wz != 0) {
6540 		for (i = m_top-1; i >= 0; i--) {
6541 			monster_type *m_ptr = &m_list[i];
6542 			if (m_ptr->owner == p_ptr->id && m_ptr->pet) {
6543 				m_ptr->pet = 0; //default behaviour!
6544 				m_ptr->owner = 0;
6545 				i = -1;
6546 			}
6547 		}
6548 	}
6549 #endif
6550 
6551 	/* very very rare case, but this can happen(eg. starvation) */
6552 	if (p_ptr->store_num != -1) {
6553 		handle_store_leave(Ind);
6554 		Send_store_kick(Ind);
6555 	}
6556 
6557 	if (d_ptr && (d_ptr->flags2 & DF2_NO_DEATH)) secure = TRUE;
6558 
6559 	if (in_iddc
6560 	    && !is_admin(p_ptr)) {
6561 		for (i = 0; i < IDDC_HIGHSCORE_SIZE; i++) {
6562 			if (deep_dive_level[i] >= ABS(p_ptr->wpos.wz) || deep_dive_level[i] == -1) {
6563 #ifdef IDDC_RESTRICT_ACC_CLASS /* only allow one entry of same account+class? : discard new entry */
6564 				if (!strcmp(deep_dive_account[i], p_ptr->accountname) &&
6565 				    deep_dive_class[i] == p_ptr->pclass) {
6566 					i = IDDC_HIGHSCORE_DISPLAYED;
6567 					break;
6568 				}
6569 #endif
6570 				continue;
6571 			}
6572 #ifdef IDDC_RESTRICT_ACC_CLASS /* only allow one entry of same account+class? : discard previous entry */
6573 			for (j = i; j < IDDC_HIGHSCORE_SIZE - 1; j++) {
6574 				if (!strcmp(deep_dive_account[j], p_ptr->accountname) &&
6575 				    deep_dive_class[i] == p_ptr->pclass) {
6576 					int k;
6577 
6578 					/* pull up all succeeding entries by 1  */
6579 					for (k = j; k < IDDC_HIGHSCORE_SIZE - 1; k++) {
6580 						deep_dive_level[k] = deep_dive_level[k + 1];
6581 						strcpy(deep_dive_name[k], deep_dive_name[k + 1]);
6582 						strcpy(deep_dive_char[k], deep_dive_char[k + 1]);
6583 						strcpy(deep_dive_account[k], deep_dive_account[k + 1]);
6584 						deep_dive_class[k] = deep_dive_class[k + 1];
6585 					}
6586 					break;
6587 				}
6588 			}
6589 #endif
6590 			/* push down all entries by 1, to make room for inserting new entry */
6591 			for (j = IDDC_HIGHSCORE_SIZE - 1; j > i; j--) {
6592 				deep_dive_level[j] = deep_dive_level[j - 1];
6593 				strcpy(deep_dive_name[j], deep_dive_name[j - 1]);
6594 				strcpy(deep_dive_char[j], deep_dive_char[j - 1]);
6595 				strcpy(deep_dive_account[j], deep_dive_account[j - 1]);
6596 				deep_dive_class[j] = deep_dive_class[j - 1];
6597 			}
6598 			deep_dive_level[i] = ABS(p_ptr->wpos.wz);
6599 			//strcpy(deep_dive_name[i], p_ptr->name);
6600 #ifdef IDDC_HISCORE_SHOWS_ICON
6601 			sprintf(deep_dive_name[i], "%s, %s %s (\\{%c%c\\{s/\\{%c%d\\{s),",
6602 			    p_ptr->name, get_prace(p_ptr), class_info[p_ptr->pclass].title, color_attr_to_char(p_ptr->cp_ptr->color), p_ptr->fruit_bat ? 'b' : '@',
6603 			    p_ptr->ghost ? 'r' : 's', p_ptr->max_plv);
6604 #else
6605 			sprintf(deep_dive_name[i], "%s, %s %s (\\{%c%d\\{s),",
6606 			    p_ptr->name, get_prace(p_ptr), class_info[p_ptr->pclass].title,
6607 			    p_ptr->ghost ? 'r' : 's', p_ptr->max_plv);
6608 #endif
6609 			strcpy(deep_dive_char[i], p_ptr->name);
6610 			strcpy(deep_dive_account[i], p_ptr->accountname);
6611 			deep_dive_class[i] = p_ptr->pclass;
6612 			break;
6613 		}
6614 
6615 		if (i < IDDC_HIGHSCORE_DISPLAYED) {
6616 			sprintf(buf, "\374\377a%s reached floor %d in the Ironman Deep Dive challenge, placing %d%s!",
6617 			    p_ptr->name, ABS(p_ptr->wpos.wz), i + 1, i == 0 ? "st" : (i == 1 ? "nd" : (i == 2 ? "rd" : "th")));
6618 			msg_broadcast_format(0, buf);
6619 #ifdef TOMENET_WORLDS
6620 			if (cfg.worldd_events) world_msg(buf);
6621 #endif
6622 		} else {
6623 			sprintf(buf, "\374\377a%s reached floor %d in the Ironman Deep Dive challenge!",
6624 			    p_ptr->name, ABS(p_ptr->wpos.wz));
6625 			msg_broadcast_format(0, buf);
6626 #ifdef TOMENET_WORLDS
6627 			if (cfg.worldd_events) world_msg(buf);
6628 #endif
6629 		}
6630 
6631 		if (ABS(p_ptr->wpos.wz) >= 30)
6632 			l_printf("%s \\{s%s (%d) reached floor %d in the Ironman Deep Dive challenge\n",
6633 			    showdate(), p_ptr->name, p_ptr->max_plv, ABS(p_ptr->wpos.wz));
6634 		else if (i < IDDC_HIGHSCORE_SIZE) { /* the score table is updated anyway, even if no l_printf() entry is created */
6635 			char path[MAX_PATH_LENGTH];
6636 			char path_rev[MAX_PATH_LENGTH];
6637 			path_build(path, MAX_PATH_LENGTH, ANGBAND_DIR_DATA, "legends.log");
6638 			path_build(path_rev, MAX_PATH_LENGTH, ANGBAND_DIR_DATA, "legends-rev.log");
6639 			reverse_lines(path, path_rev);
6640 		}
6641 	}
6642 
6643 	if (ge_special_sector &&
6644 	    (p_ptr->wpos.wx == WPOS_ARENA_X && p_ptr->wpos.wy == WPOS_ARENA_Y &&
6645 	    p_ptr->wpos.wz == WPOS_ARENA_Z)) {
6646 		secure = TRUE;
6647 		ge_secure = TRUE; /* extra security for global events */
6648 	}
6649 
6650 	if (pvp) {
6651 		secure = FALSE;
6652 		msg_layout = 'L';
6653 	}
6654 
6655 	/* Hack -- amulet of life saving */
6656 	if (p_ptr->alive && !erase && (secure ||
6657 	    (p_ptr->inventory[INVEN_NECK].k_idx &&
6658 	    p_ptr->inventory[INVEN_NECK].sval == SV_AMULET_LIFE_SAVING))) {
6659 		s_printf("%s (%d) was pseudo-killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->really_died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6660 
6661 		if (!secure) {
6662 			msg_print(Ind, "\377oYour amulet shatters into pieces!");
6663 			inven_item_increase(Ind, INVEN_NECK, -99);
6664 			//inven_item_describe(Ind, INVEN_NECK);
6665 			inven_item_optimize(Ind, INVEN_NECK);
6666 		}
6667 
6668 		/* Cure him from various maladies */
6669 //		p_ptr->black_breath = FALSE;
6670 		if (p_ptr->image) (void)set_image(Ind, 0);
6671 		if (p_ptr->blind) (void)set_blind(Ind, 0);
6672 		if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
6673 		if (p_ptr->confused) (void)set_confused(Ind, 0);
6674 		if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6675 		if (p_ptr->stun) (void)set_stun(Ind, 0);
6676 		if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6677 		/* if (p_ptr->food < PY_FOOD_ALERT) */
6678 		(void)set_food(Ind, PY_FOOD_FULL - 1);
6679 
6680 		/* Teleport him */
6681 		teleport_player(Ind, 200, TRUE);
6682 
6683 		/* Remove the death flag */
6684 		p_ptr->death = FALSE;
6685 //		ptr->ghost = 0;
6686 
6687 		/* Give him his hit points back */
6688 		p_ptr->chp = p_ptr->mhp;
6689 		p_ptr->chp_frac = 0;
6690 
6691 		if (secure) {
6692 			p_ptr->new_level_method = (p_ptr->wpos.wz > 0 ? LEVEL_RECALL_DOWN : LEVEL_RECALL_UP);
6693 			p_ptr->recall_pos.wx = p_ptr->wpos.wx;
6694 			p_ptr->recall_pos.wy = p_ptr->wpos.wy;
6695 			p_ptr->recall_pos.wz = 0;
6696 			if (ge_secure) {
6697 				k = 0;
6698 				/* reset the monster :D */
6699 			        for (i = 1; i < m_max; i++) {
6700 			                m_ptr = &m_list[i];
6701 					if (m_ptr->wpos.wx == p_ptr->wpos.wx && m_ptr->wpos.wy == p_ptr->wpos.wy && m_ptr->wpos.wz == p_ptr->wpos.wz) {
6702 						k = m_ptr->r_idx;
6703 						j = m_ptr->ego;
6704 						monster_desc(0, m_name_extra, i, 0x00);
6705 						m_name_extra[0] = toupper(m_name_extra[0]);
6706 						wipe_m_list(&p_ptr->wpos);
6707 						summon_override_checks = SO_ALL & ~SO_PROTECTED;
6708 #if 1 /* GE_ARENA_ALLOW_EGO */
6709 						while (!summon_detailed_one_somewhere(&p_ptr->wpos, k, j, FALSE, 101)
6710 						    && (++tries < 1000));
6711 #else
6712 						while (!summon_specific_race_somewhere(&p_ptr->wpos, k, 100, 1)
6713 						    && (++tries < 1000));
6714 #endif
6715 						summon_override_checks = SO_NONE;
6716 						break;
6717 					}
6718 				}
6719 				if (k) { /* usual */
6720 					msg_broadcast_format(0, "\376\377A** %s has defeated %s! **", m_name_extra, p_ptr->name);
6721 					s_printf("EVENT_RESULT: %s has defeated %s (%d) (%d damage).\n", m_name_extra, p_ptr->name, p_ptr->lev, p_ptr->deathblow);
6722 				} else { /* can happen if monster dies first, then player dies to monster DoT */
6723 					msg_broadcast_format(0, "\376\377A** %s didn't survive! **", p_ptr->name);
6724 					s_printf("EVENT_RESULT: %s (%d) was defeated (%d damage).\n", p_ptr->name, p_ptr->lev, p_ptr->deathblow);
6725 				}
6726 				recall_player(Ind, "\377oYou die.. at least it felt like you did..!");
6727 			}
6728 			else recall_player(Ind, "\377oYou almost died.. but your life was secured here!");
6729 
6730 			p_ptr->safe_sane = TRUE;
6731 			/* Apply small penalty for death */
6732 			if (!ge_secure) { /* except if we were in a special event that protects */
6733 #ifndef ARCADE_SERVER
6734 				p_ptr->au = p_ptr->au * 4 / 5;
6735 				p_ptr->max_exp = (p_ptr->max_exp * 4 + 1) / 5; /* never drop below 1! (Highlander Tournament exploit) */
6736 				p_ptr->exp = p_ptr->max_exp;
6737 #endif
6738 			} else {
6739 				if (p_ptr->csane <= 10) p_ptr->csane = 10; /* just something, paranoia */
6740 			}
6741 			check_experience(Ind);
6742 
6743 			/* update stats */
6744 			p_ptr->update |= PU_SANITY;
6745 			update_stuff(Ind);
6746 			p_ptr->safe_sane = FALSE;
6747 			/* Redraw */
6748 			p_ptr->redraw |= (PR_BASIC);
6749 			/* Update */
6750 			p_ptr->update |= (PU_BONUS);
6751 		} else {
6752 			/* Went mad? */
6753 			if (p_ptr->csane < 0) p_ptr->csane = 0;
6754 		}
6755 
6756 		/* Wow! You may return!! */
6757 		if (!ge_secure) p_ptr->soft_deaths++;
6758 		return;
6759 	}
6760 
6761 	if ((!(p_ptr->mode & MODE_NO_GHOST)) && !cfg.no_ghost && !pvp) {
6762 		if(!p_ptr->wpos.wz || !(d_ptr->flags2 & (DF2_HELL | DF2_IRON)))
6763 			hell = FALSE;
6764 	}
6765 
6766 	if ((Ind2 = get_esp_link(Ind, LINKF_PAIN, &p_ptr2))) {
6767 		strcpy(p_ptr2->died_from, p_ptr->died_from);
6768 		if (!p_ptr2->ghost)
6769 		{
6770 			strcpy(p_ptr2->died_from_list, p_ptr->died_from);
6771 			p_ptr2->died_from_depth = getlevel(&p_ptr2->wpos);
6772 			/* Hack to remember total winning */
6773                         if (p_ptr2->total_winner) strcat(p_ptr2->died_from_list, "\001");
6774 		}
6775 		/* new: 50-50 chance to die for linked mind */
6776 		bypass_invuln = TRUE;
6777 		if (p_ptr2->chp >= 30)
6778 			take_hit(Ind2, p_ptr2->chp - 20 + rand_int(42), p_ptr->died_from, 0);
6779 		else
6780 			take_hit(Ind2, p_ptr2->chp - 2 + rand_int(6), p_ptr->died_from, 0);
6781 		bypass_invuln = FALSE;
6782 	}
6783 
6784 	if (erase) hell = TRUE;
6785 
6786 	/* Morgoth's level might be NO_GHOST! */
6787 	if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_GHOST)) hell = TRUE;
6788 
6789 	/* For global events (Highlander Tournament) */
6790 	/* either instakill in sector 0,0... */
6791 	if (p_ptr->global_event_temp & PEVF_NOGHOST_00) hell = TRUE;
6792 	/* or instead teleport them to surface */
6793 	/* added wpos checks due to weirdness. -Molt */
6794 	if (p_ptr->wpos.wx != WPOS_SECTOR00_X && p_ptr->wpos.wy != WPOS_SECTOR00_Y && (p_ptr->global_event_temp & PEVF_SAFEDUN_00)) {
6795 		s_printf("Somethin weird with %s. GET is %d\n", p_ptr->name, p_ptr->global_event_temp);
6796 		msg_broadcast(0, "Uh oh, somethin's not right here.");
6797 	}
6798 	if ((p_ptr->global_event_temp & PEVF_SAFEDUN_00) && (p_ptr->csane >= 0) && p_ptr->wpos.wx == WPOS_SECTOR00_X && p_ptr->wpos.wy == WPOS_SECTOR00_Y && p_ptr->wpos.wz != 0) {
6799 		s_printf("DEBUG_TOURNEY: player %s revived.\n", p_ptr->name);
6800 		s_printf("%s (%d) was pseudo-killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->really_died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6801 
6802 		if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6803 		if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6804 		(void)set_food(Ind, PY_FOOD_FULL - 1);
6805 
6806 		if (!sector00downstairs) p_ptr->global_event_temp &= ~PEVF_SAFEDUN_00; /* no longer safe from death */
6807 		p_ptr->recall_pos.wx = 0;
6808 		p_ptr->recall_pos.wy = 0;
6809 		p_ptr->recall_pos.wz = 0;
6810 		p_ptr->global_event_temp |= PEVF_PASS_00; /* pass through sector00separation */
6811 		p_ptr->new_level_method = LEVEL_OUTSIDE_RAND;
6812 		recall_player(Ind, "");
6813 
6814 		/* Allow him to find the stairs quickly for re-entering highlander dungeon */
6815 		wiz_lite(Ind);
6816 
6817 		/* Teleport him */
6818 		teleport_player(Ind, 200, TRUE);
6819 		/* Remove the death flag */
6820 		p_ptr->death = FALSE;
6821 //		p_ptr->ghost = 0;
6822 		/* Give him his hit points back */
6823 		p_ptr->chp = p_ptr->mhp;
6824 		p_ptr->chp_frac = 0;
6825 
6826 		/* Redraw */
6827 		p_ptr->redraw |= (PR_BASIC);
6828 		/* Update */
6829 		p_ptr->update |= (PU_BONUS);
6830 
6831 		/* Inform him about his situation */
6832 		if (!sector00downstairs) msg_print(Ind, "\377oYou were defeated too early and have to sit out the remaining time!");
6833 		else msg_print(Ind, "\377oYou were defeated too early, find the staircase and re-enter the dungeon!");
6834 
6835 		p_ptr->soft_deaths++;
6836 		return;
6837 	}
6838 
6839 #ifdef ENABLE_INSTANT_RES
6840 	if (p_ptr->insta_res && !erase && p_ptr->alive) {
6841 		char instant_res_possible = TRUE;
6842 		int dlvl = getlevel(&p_ptr->wpos);
6843 		int instant_res_cost = dlvl * dlvl * 10 + 10;
6844 
6845 		/* Only everlasters */
6846 		if (!(p_ptr->mode & MODE_EVERLASTING))
6847 			instant_res_possible = FALSE;
6848 
6849 		/* If already a ghost, get destroyed */
6850 		if (p_ptr->ghost)
6851 			instant_res_possible = FALSE;
6852 
6853 		/* Insanity is a no-ghost death */
6854 		if (insanity)
6855 			instant_res_possible = FALSE;
6856 
6857 		/* Not on NO_GHOST levels */
6858 		if (hell)
6859 			instant_res_possible = FALSE;
6860 
6861 		/* Not on suicides */
6862 		if (!p_ptr->alive)
6863 			instant_res_possible = FALSE;
6864 
6865  #ifdef INSTANT_RES_EXCEPTION
6866 		/* Not in Nether Realm */
6867 		if (in_netherrealm(&p_ptr->wpos))
6868 			instant_res_possible = FALSE;
6869  #endif
6870 
6871 		/* Divine wrath is meant to kill people */
6872 		if (streq(p_ptr->died_from, "divine wrath"))
6873 			instant_res_possible = FALSE;
6874 
6875 		/* Check that the player has enough money */
6876 		if (instant_res_cost > p_ptr->au + p_ptr->balance) {
6877 			msg_print(Ind, "\376\377yYou do not have sufficient funds for instant-resurrection!");
6878 			instant_res_possible = FALSE;
6879 		}
6880 
6881 		if (instant_res_possible) {
6882 			int loss_factor, reduce;
6883  #ifndef FALLEN_WINNERSONLY
6884 			int i;
6885 			u32b dummy, f5;
6886  #endif
6887 
6888 			/* Log it */
6889 			s_printf("INSTA_RES: %s (%d) was defeated by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6890 			if (!strcmp(p_ptr->died_from, "It") || insanity || p_ptr->image)
6891 				s_printf("(%s was really defeated by %s.)\n", p_ptr->name, p_ptr->really_died_from);
6892 
6893  #ifdef USE_SOUND_2010
6894 			/* Play the death sound */
6895 			if (p_ptr->male) sound(Ind, "death_male", "death", SFX_TYPE_MISC, TRUE);
6896 			else sound(Ind, "death_female", "death", SFX_TYPE_MISC, TRUE);
6897  #else
6898 			sound(Ind, SOUND_DEATH);
6899  #endif
6900 
6901 			/* Message to other players */
6902 			if (cfg.unikill_format)
6903 				snprintf(buf, sizeof(buf), "\374\377D%s %s (%d) was defeated by %s.", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
6904 			else
6905 				snprintf(buf, sizeof(buf), "\374\377D%s (%d) was defeated by %s.", p_ptr->name, p_ptr->lev, p_ptr->died_from);
6906 
6907 			msg_broadcast(Ind, buf);
6908  #ifdef TOMENET_WORLDS
6909 			if (cfg.worldd_pdeath) world_msg(buf);
6910  #endif
6911 
6912 			/* Add to legends log if he was a winner or very high level */
6913 			if (!is_admin(p_ptr)) {
6914 				if (p_ptr->total_winner)
6915 					l_printf("%s \\{r%s royalty %s (%d) died and was instantly resurrected\n", showdate(), p_ptr->male ? "His" : "Her", p_ptr->name, p_ptr->lev);
6916 				else if (p_ptr->lev >= 50)
6917 					l_printf("%s \\{r%s (%d) died and was instantly resurrected\n", showdate(), p_ptr->name, p_ptr->lev);
6918 			}
6919 
6920 			/* Tell him what happened -- moved the messages up here so they get onto the chardump! */
6921 			msg_format(Ind, "\374\377RYou were defeated by %s, but the priests have saved you.", p_ptr->died_from);
6922 
6923 			/* new - death dump for insta-res too! */
6924 			Send_chardump(Ind, "-death");
6925 
6926 			/* Hm, this doesn't need to be on the char dump actually */
6927 			msg_format(Ind, "\377oThey have requested a fee of %d gold pieces.", instant_res_cost);
6928 
6929 			/* Cure him from various maladies */
6930 			if (p_ptr->image) (void)set_image(Ind, 0);
6931 			if (p_ptr->blind) (void)set_blind(Ind, 0);
6932 			if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
6933 			if (p_ptr->confused) (void)set_confused(Ind, 0);
6934 			if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6935 			if (p_ptr->stun) (void)set_stun(Ind, 0);
6936 			if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6937 			(void)set_food(Ind, PY_FOOD_FULL - 1);
6938 
6939 			if (p_ptr->black_breath) {
6940 				//msg_print(Ind, "The hold of the Black Breath on you is broken!");
6941                                 p_ptr->black_breath = FALSE;
6942 			}
6943 
6944 			/* Remove the death flag */
6945 			p_ptr->death = FALSE;
6946 
6947 			/* Give him his hit points back */
6948 			p_ptr->chp = p_ptr->mhp;
6949 			p_ptr->chp_frac = 0;
6950 
6951 			/* Lose inventory and equipment items as per normal death */
6952  #ifdef DEATH_PACK_ITEM_LOST
6953 			inven_death_damage(Ind, TRUE);
6954  #endif
6955  #ifdef DEATH_EQ_ITEM_LOST
6956 			equip_death_damage(Ind, TRUE);
6957  #endif
6958 
6959 			/* Extract the cost */
6960 			p_ptr->au -= instant_res_cost;
6961 			if (p_ptr->au < 0) {
6962 				p_ptr->balance += p_ptr->au;
6963 				p_ptr->au = 0;
6964 			}
6965 
6966 			/* Also lose some cash on death */
6967 			s_printf("gold_lost: carried %d, remaining ", p_ptr->au);
6968  #if 0 /* lose 0 below 50k, up to 50% up to 500k, 50% after that */
6969 			if (p_ptr->au <= 50000) ;
6970 			else if (p_ptr->au <= 500000) p_ptr->au = (((p_ptr->au) * 100) / (100 + ((p_ptr->au - 50000) / 4500)));
6971 			else p_ptr->au /= 2;
6972  #else /* lose 5..33% */
6973 			/* overflow handling */
6974 			if (p_ptr->au <= 20000000) p_ptr->au = (p_ptr->au * (rand_int(29) + 67)) / 100;
6975 			else p_ptr->au = (p_ptr->au / 100) * (rand_int(29) + 67);
6976  #endif
6977 			s_printf("%d.\n", p_ptr->au);
6978 
6979 			p_ptr->safe_sane = TRUE;
6980 
6981 			/* Lose some experience */
6982 			loss_factor = INSTANT_RES_XP_LOST;
6983 			if (get_skill(p_ptr, SKILL_HCURING) >= 50) loss_factor -= 5;
6984 
6985 			reduce = p_ptr->max_exp;
6986 			reduce = reduce > 99999 ?
6987 			reduce / 100 * loss_factor : reduce * loss_factor / 100;
6988 			p_ptr->max_exp -= reduce;
6989 
6990 			reduce = p_ptr->exp;
6991 			reduce = reduce > 99999 ?
6992 			reduce / 100 * loss_factor : reduce * loss_factor / 100;
6993 			p_ptr->exp -= reduce;
6994 
6995 			check_experience(Ind);
6996 
6997 			/* Remove massive crown of Morgoth and Grond */
6998 			if (p_ptr->inventory[INVEN_HEAD].k_idx && p_ptr->inventory[INVEN_HEAD].name1 == ART_MORGOTH) {
6999 				char o_name[ONAME_LEN];
7000 
7001 				o_ptr = &p_ptr->inventory[INVEN_HEAD];
7002 				object_desc(Ind, o_name, o_ptr, TRUE, 3);
7003 				msg_format(Ind, "\376\377oYour %s was destroyed!", o_name);
7004 				handle_art_d(o_ptr->name1);
7005 
7006 				inven_item_increase(Ind, INVEN_HEAD, -(o_ptr->number));
7007 				inven_item_optimize(Ind, INVEN_HEAD);
7008 			}
7009 			if (p_ptr->inventory[INVEN_WIELD].k_idx && p_ptr->inventory[INVEN_WIELD].name1 == ART_GROND) {
7010 				char o_name[ONAME_LEN];
7011 
7012 				o_ptr = &p_ptr->inventory[INVEN_WIELD];
7013 				object_desc(Ind, o_name, o_ptr, TRUE, 3);
7014 				msg_format(Ind, "\376\377oYour %s was destroyed!", o_name);
7015 				handle_art_d(o_ptr->name1);
7016 
7017 				inven_item_increase(Ind, INVEN_WIELD, -(o_ptr->number));
7018 				inven_item_optimize(Ind, INVEN_WIELD);
7019 			}
7020 
7021 			/* update stats */
7022 			p_ptr->update |= PU_SANITY;
7023 			update_stuff(Ind);
7024 			p_ptr->safe_sane = FALSE;
7025 
7026 			p_ptr->recall_pos.wx = p_ptr->town_x;
7027 			p_ptr->recall_pos.wy = p_ptr->town_y;
7028 			p_ptr->recall_pos.wz = 0;
7029 			p_ptr->new_level_method = LEVEL_TO_TEMPLE;
7030 			recall_player(Ind, "");
7031 
7032  #if 0
7033 			/* Unown land */
7034 			if (p_ptr->total_winner) {
7035   #ifdef NEW_DUNGEON
7036 /* FIXME */
7037 /*
7038 				msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7039 				wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7040 */
7041   #else
7042 				msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7043 				wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7044   #endif
7045 			}
7046  #endif
7047 
7048 			/* No longer a winner */
7049 			p_ptr->total_winner = FALSE;
7050 
7051 			/* Set all his artifacts back to normal-speed timeout */
7052 			if (was_total_winner && !cfg.fallenkings_etiquette) {
7053 				for (j = 0; j < INVEN_TOTAL; j++)
7054 					if (p_ptr->inventory[j].name1 &&
7055 					    p_ptr->inventory[j].name1 != ART_RANDART)
7056 						a_info[p_ptr->inventory[j].name1].winner = FALSE;
7057 			}
7058 
7059  #ifndef FALLEN_WINNERSONLY
7060 			/* Take off winner artifacts and winner-only items */
7061 			for (i = INVEN_WIELD; i <= INVEN_TOTAL; i++) {
7062 				o_ptr = &p_ptr->inventory[i];
7063 				object_flags(o_ptr, &dummy, &dummy, &dummy, &dummy, &f5, &dummy, &dummy);
7064 				if ((f5 & TR5_WINNERS_ONLY)) {
7065 					bypass_inscrption = TRUE;
7066 					inven_takeoff(Ind, i, 255, FALSE);
7067 				}
7068 			}
7069  #endif
7070 
7071 			/* Redraw */
7072 			p_ptr->redraw |= (PR_BASIC);
7073 			/* Update */
7074 			p_ptr->update |= (PU_BONUS);
7075 
7076 			p_ptr->deaths++;
7077 			return;
7078 		}
7079 	}
7080 #endif
7081 
7082 	/* Players of level cfg.nodrop [5] will die a no-ghost death.
7083 	   This should clarify the situation for newbies and avoid them
7084 	   getting confused and/or lacking their startup equipment.
7085 	   On the other hand, it's confusing to ghost-die when you know
7086 	   you chose everlasting +_+ */
7087 #if 0 /* disable newbies-lvl explanation msg (much below) iff this is on */
7088 	if (p_ptr->max_plv < cfg.newbies_cannot_drop) hell = TRUE;
7089 #endif
7090 
7091 #ifdef USE_SOUND_2010
7092 	/* don't play a sfx for mere suicide */
7093 	if (p_ptr->alive) {
7094 		if (p_ptr->male) sound(Ind, "death_male", "death", SFX_TYPE_MISC, TRUE);
7095 		else sound(Ind, "death_female", "death", SFX_TYPE_MISC, TRUE);
7096 	}
7097 #else
7098 	/* don't play a sfx for mere suicide */
7099 	if (p_ptr->alive) sound(Ind, SOUND_DEATH);
7100 #endif
7101 
7102 	/* Drop gold if player has any -------------------------------------- */
7103 	if (p_ptr->alive && p_ptr->au) {
7104 		/* Put the player's gold in the overflow slot */
7105 		invcopy(&p_ptr->inventory[INVEN_PACK], lookup_kind(TV_GOLD, 9));
7106 		/* Change the mode of the gold accordingly */
7107 		p_ptr->inventory[INVEN_PACK].mode = p_ptr->mode;
7108 		p_ptr->inventory[INVEN_PACK].owner = p_ptr->id; /* hack */
7109 
7110 		/* Drop no more than 32000 gold */
7111 //		if (p_ptr->au > 32000) p_ptr->au = 32000;
7112 		/* (actually, this if-clause is not necessary) */
7113 		s_printf("gold_lost: carried %d, remaining ", p_ptr->au);
7114 #if 0 /* lose 0 below 50k, up to 50% up to 500k, 50% after that */
7115 		if (p_ptr->au <= 50000) ;
7116 		else if (p_ptr->au <= 500000) p_ptr->au = (((p_ptr->au) * 100) / (100 + ((p_ptr->au - 50000) / 4500)));
7117 		else p_ptr->au /= 2;
7118 #else /* lose 5..33% */
7119 		p_ptr->au = (p_ptr->au * (rand_int(29) + 67)) / 100;
7120 #endif
7121 
7122 		if (p_ptr->max_plv >= cfg.newbies_cannot_drop) {
7123 			/* Set the amount */
7124 			p_ptr->inventory[INVEN_PACK].pval = p_ptr->au;
7125 			/* set fitting gold 'colour' */
7126 			p_ptr->inventory[INVEN_PACK].k_idx = gold_colour(p_ptr->au, FALSE, TRUE);
7127 			p_ptr->inventory[INVEN_PACK].xtra1 = 1;//mark as 'compact' in case it falls on top of a normal money pile
7128 			p_ptr->inventory[INVEN_PACK].sval = k_info[p_ptr->inventory[INVEN_PACK].k_idx].sval;
7129 			s_printf("%d.\n", p_ptr->au);
7130 		} else {
7131 			invwipe(&p_ptr->inventory[INVEN_PACK]);
7132 			s_printf("none.\n");
7133 		}
7134 
7135 		/* No more gold */
7136 		p_ptr->au = 0;
7137 	}
7138 
7139 	/* Drop/lose items -------------------------------------------------- */
7140 
7141 	/* Don't "lose" items on suicide (they all poof anyway, except for true arts possibly) */
7142 #ifdef DEATH_PACK_ITEM_LOST
7143 	if (p_ptr->alive) inven_death_damage(Ind, FALSE);
7144 #endif
7145 #ifdef DEATH_EQ_ITEM_LOST
7146 	if (p_ptr->alive) equip_death_damage(Ind, FALSE);
7147 #endif
7148 
7149 	/* Setup the sorter */
7150 	ang_sort_comp = ang_sort_comp_value;
7151 	ang_sort_swap = ang_sort_swap_value;
7152 	/* Remember original position before sorting */
7153 	for (i = 0; i < INVEN_TOTAL; i++) p_ptr->inventory[i].inven_order = i;
7154 	/* Sort the player's inventory according to value */
7155 	ang_sort(Ind, p_ptr->inventory, NULL, INVEN_TOTAL);
7156 
7157 	/* Starting with the most valuable, drop things one by one */
7158 	for (i = 0; i < INVEN_TOTAL; i++) {
7159 		bool away = FALSE;
7160 
7161 		o_ptr = &p_ptr->inventory[i];
7162 		/* Make sure we have an object */
7163 		if (o_ptr->k_idx == 0) continue;
7164 
7165 		if (o_ptr->questor) { /* questor items cannot be 'dropped', only destroyed! */
7166 			questitem_d(o_ptr, o_ptr->number);
7167 			continue;
7168 		}
7169 
7170 		/* Set all his artifacts back to normal-speed timeout */
7171 		if (was_total_winner && !cfg.fallenkings_etiquette &&
7172 		    p_ptr->inventory[i].name1 &&
7173 		    p_ptr->inventory[i].name1 != ART_RANDART)
7174 			a_info[p_ptr->inventory[i].name1].winner = FALSE;
7175 
7176 		/* If we committed suicide, only drop artifacts */
7177 //			if (!p_ptr->alive && !artifact_p(o_ptr)) continue;
7178 		if (!p_ptr->alive) {
7179 			if (!true_artifact_p(o_ptr)) continue;
7180 
7181 			/* hack -- total winners do not drop artifacts when they suicide */
7182 			//		if (!p_ptr->alive && p_ptr->total_winner && artifact_p(&p_ptr->inventory[i]))
7183 
7184 			/* Artifacts cannot be dropped after all */
7185 			/* Don't litter Valinor -- Ring of Phasing must be destroyed anyways */
7186 			if ((cfg.anti_arts_hoard) || in_valinor(&p_ptr->wpos)) {
7187 				/* set the artifact as unfound */
7188 				handle_art_d(o_ptr->name1);
7189 
7190 				/* Don't drop the artifact */
7191 				continue;
7192 			}
7193 		}
7194 
7195 		if (!is_admin(p_ptr) && !p_ptr->inval && (p_ptr->max_plv >= cfg.newbies_cannot_drop) &&
7196 		    /* Don't drop Morgoth's crown or Grond */
7197 		    !(o_ptr->name1 == ART_MORGOTH) && !(o_ptr->name1 == ART_GROND)
7198 #ifdef IDDC_NO_TRADE_CHEEZE
7199 		    && !(in_iddc && o_ptr->NR_tradable)
7200 #endif
7201 		    ) {
7202 #ifdef DEATH_ITEM_SCATTER
7203 			/* Apply penalty of death */
7204 			if (!artifact_p(o_ptr) && magik(DEATH_ITEM_SCATTER))
7205 				away = TRUE;
7206 			else
7207 #endif	/* DEATH_ITEM_SCATTER */
7208 			{
7209 				if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7210 				else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7211 				else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7212 
7213 				/* Drop this one */
7214 				away = drop_near(o_ptr, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px)
7215 					<= 0 ? TRUE : FALSE;
7216 			}
7217 
7218 			if (away) {
7219 				int o_idx = 0, x1, y1, try = 500;
7220 				cave_type **zcave;
7221 				if ((zcave = getcave(&p_ptr->wpos))) /* this should never.. */
7222 					while (o_idx <= 0 && try--) {
7223 						x1 = rand_int(p_ptr->cur_wid);
7224 						y1 = rand_int(p_ptr->cur_hgt);
7225 
7226 						if (!cave_clean_bold(zcave, y1, x1)) continue;
7227 						if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7228 						else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7229 						else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7230 						o_idx = drop_near(o_ptr, 0, &p_ptr->wpos, y1, x1);
7231 					}
7232 			}
7233 		} else {
7234 			/* set the artifact as unfound */
7235 			if (true_artifact_p(o_ptr)) handle_art_d(o_ptr->name1);
7236 			questitem_d(o_ptr, o_ptr->number);
7237 		}
7238 
7239 		/* No more item */
7240 		invwipe(o_ptr);
7241 	}
7242 
7243 	/* Get rid of him if he's a ghost or suffers a no-ghost death */
7244 	if ((p_ptr->ghost || (hell && p_ptr->alive)) ||
7245 	    insanity ||
7246 	    streq(p_ptr->died_from, "indecisiveness") ||
7247 	    streq(p_ptr->died_from, "indetermination") ||
7248 	    ((p_ptr->lives == 1 + 1) && cfg.lifes && p_ptr->alive &&
7249 	    !(p_ptr->mode & MODE_EVERLASTING))) {
7250 		/* Tell players */
7251 		if (insanity) {
7252 			/* Tell him */
7253 			msg_print(Ind, "\374\377RYou die.");
7254 			//msg_print(Ind, NULL);
7255 //todo: use 'died_from' (insanity-blinking-style):
7256 			msg_format(Ind, "\374\377%c**\377rYou have been destroyed by \377oI\377Gn\377bs\377Ba\377sn\377Ri\377vt\377yy\377r.\377%c**", msg_layout, msg_layout);
7257 
7258 s_printf("CHARACTER_TERMINATION: INSANITY race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7259 
7260 			if (cfg.unikill_format)
7261 			snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was destroyed by \377m%s\377r.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7262 			else
7263 			snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was destroyed by \377m%s\377r.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7264 			s_printf("%s (%d) was destroyed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7265 			if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7266 				s_printf("(%s was really destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7267 
7268 #if CHATTERBOX_LEVEL > 2
7269 			if (strstr(p_ptr->died_from, "Farmer Maggot's dog") && magik(50)) {
7270 				msg_broadcast(Ind, "Suddenly a thought comes to your mind:");
7271 				msg_broadcast(0, "Who let the dogs out?");
7272 			} else if (p_ptr->last_words) {
7273 				char death_message[80];
7274 
7275         			(void)get_rnd_line("death.txt", 0, death_message, 80);
7276 				msg_print(Ind, death_message);
7277 			}
7278 #endif	// CHATTERBOX_LEVEL
7279 
7280 			death_type = DEATH_INSANITY;
7281 			if (p_ptr->ghost) {
7282 				death_type = DEATH_GHOST;
7283 				Send_chardump(Ind, "-ghost");
7284 			} else Send_chardump(Ind, "-death");
7285 			Net_output1(Ind);
7286 		} else if (p_ptr->ghost) {
7287 			/* Tell him */
7288 			msg_format(Ind, "\374\377a**\377rYour ghost was destroyed by %s.\377a**", p_ptr->died_from);
7289 
7290 s_printf("CHARACTER_TERMINATION: GHOSTKILL race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7291 
7292 			if (cfg.unikill_format) {
7293 				if (p_ptr->name[strlen(p_ptr->name) - 1] == 's')
7294 					snprintf(buf, sizeof(buf), "\374\377a**\377r%s %s' (%d) ghost was destroyed by %s.\377a**", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7295 				else
7296 					snprintf(buf, sizeof(buf), "\374\377a**\377r%s %s's (%d) ghost was destroyed by %s.\377a**", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7297 			} else {
7298 				if (p_ptr->name[strlen(p_ptr->name) - 1] == 's')
7299 					snprintf(buf, sizeof(buf), "\374\377a**\377r%s' (%d) ghost was destroyed by %s.\377a**", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7300 				else
7301 					snprintf(buf, sizeof(buf), "\374\377a**\377r%s's (%d) ghost was destroyed by %s.\377a**", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7302 			}
7303 			s_printf("%s's (%d) ghost was destroyed by %s for %d damage on %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7304 			if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7305 				s_printf("(%s's ghost was really destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7306 
7307 #if CHATTERBOX_LEVEL > 2
7308 			if (p_ptr->last_words) {
7309 				char death_message[80];
7310 
7311         			(void)get_rnd_line("death.txt", 0, death_message, 80);
7312 				msg_print(Ind, death_message);
7313 			}
7314 #endif	// CHATTERBOX_LEVEL
7315 
7316 			death_type = DEATH_GHOST;
7317 		} else {
7318 			/* Tell him */
7319 			msg_print(Ind, "\374\377RYou die.");
7320 	//		msg_print(Ind, NULL);
7321 #ifdef MORGOTH_FUNKY_KILL_MSGS /* Might add some atmosphere? (lol) - C. Blue */
7322 			if (!strcmp(p_ptr->died_from, "Morgoth, Lord of Darkness")) {
7323 				char funky_msg[20];
7324 				switch (randint(5)) {
7325 				case 1:strcpy(funky_msg,"wasted");break;
7326 				case 2:strcpy(funky_msg,"crushed");break;
7327 				case 3:strcpy(funky_msg,"shredded");break;
7328 				case 4:strcpy(funky_msg,"torn up");break;
7329 				case 5:strcpy(funky_msg,"crushed");break; /* again :) */
7330 				}
7331 				msg_format(Ind, "\374\377%c**\377rYou have been %s by %s.\377%c**", msg_layout, funky_msg, p_ptr->died_from, msg_layout);
7332 				if (cfg.unikill_format) {
7333 					snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was %s by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, funky_msg, p_ptr->died_from, msg_layout);
7334 				} else {
7335 					snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was %s and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, funky_msg, p_ptr->died_from, msg_layout);
7336 				}
7337 			} else {
7338 #endif
7339 				if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7340 #ifdef ENABLE_MAIA
7341 				    || streq(p_ptr->died_from, "indecisiveness")
7342 #endif
7343 				    || streq(p_ptr->died_from, "indetermination")
7344 				    || insanity) {
7345 					msg_format(Ind, "\374\377%c**\377rYou have been killed by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7346 				} else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7347 					msg_format(Ind, "\374\377%c**\377rYou have been annihilated by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7348 				} else {
7349 					msg_format(Ind, "\374\377%c**\377rYou have been vaporized by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7350 				}
7351 
7352 				if (cfg.unikill_format) {
7353 					if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7354 #ifdef ENABLE_MAIA
7355 					    || streq(p_ptr->died_from, "indecisiveness")
7356 #endif
7357 					    || streq(p_ptr->died_from, "indetermination")
7358 					    || insanity)
7359 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was killed by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7360 					else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450)))
7361 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was annihilated by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7362 					else
7363 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was vaporized by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7364 				} else {
7365 					if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7366 #ifdef ENABLE_MAIA
7367 					    || streq(p_ptr->died_from, "indecisiveness")
7368 #endif
7369 					    || streq(p_ptr->died_from, "indetermination")
7370 					    || insanity)
7371 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was killed and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7372 					else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450)))
7373 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was annihilated and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7374 					else
7375 						snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was vaporized and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7376 				}
7377 #ifdef MORGOTH_FUNKY_KILL_MSGS
7378 			}
7379 #endif
7380 			s_printf("%s (%d) was killed and destroyed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7381 			if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7382 				s_printf("(%s was really killed and destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7383 
7384 s_printf("CHARACTER_TERMINATION: %s race=%s ; class=%s ; trait=%s ; %d deaths\n", pvp ? "PVP" : "NOGHOST", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7385 
7386 #if CHATTERBOX_LEVEL > 2
7387 			if (p_ptr->last_words) {
7388 				char death_message[80];
7389 				(void)get_rnd_line("death.txt", 0, death_message, 80);
7390 				msg_print(Ind, death_message);
7391 			}
7392 #endif	// CHATTERBOX_LEVEL
7393 			death_type = DEATH_PERMA;
7394 			Send_chardump(Ind, "-death");
7395 			Net_output1(Ind);
7396 		}
7397 #ifdef TOMENET_WORLDS
7398 		world_player(p_ptr->id, p_ptr->name, FALSE, TRUE);
7399 #endif
7400 
7401 #if (MAX_PING_RECVS_LOGGED > 0)
7402 		/* Print last ping reception times */
7403 		struct timeval now;
7404 		gettimeofday(&now, NULL);
7405 		s_printf("PINGS_RECEIVED:");
7406 		/* Starting from latest */
7407 		for (i = 0; i < MAX_PING_RECVS_LOGGED; i++) {
7408 			j = (p_ptr->pings_received_head - i + MAX_PING_RECVS_LOGGED) % MAX_PING_RECVS_LOGGED;
7409 			if (p_ptr->pings_received[j].tv_sec) {
7410 				s_printf(" %s", timediff(&p_ptr->pings_received[j], &now));
7411 			}
7412 		}
7413 		s_printf("\n");
7414 #endif
7415 
7416 		if (is_admin(p_ptr)) snprintf(buf, sizeof(buf), "\376\377D%s bids farewell to this plane.", p_ptr->name);
7417 
7418 		if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)){
7419 #ifdef TOMENET_WORLDS
7420 			if (cfg.worldd_pdeath) world_msg(buf);
7421 #endif
7422 			msg_broadcast(Ind, buf);
7423 		}
7424 
7425 		/* Reward the killer if it was a PvP-mode char */
7426 		if (pvp) {
7427 			int killer = name_lookup_quiet(Ind, p_ptr->really_died_from, FALSE, FALSE);
7428 
7429 			/* reward him again, making restarting easier */
7430 			if (p_ptr->max_plv == MID_PVP_LEVEL)
7431 				buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MID);
7432 			if (p_ptr->max_plv == MAX_PVP_LEVEL)
7433 				buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MAX);
7434 
7435 			if (killer) {
7436 				if (Players[killer]->max_plv > p_ptr->max_plv) Players[killer]->kills_lower++;
7437 				else if (Players[killer]->max_plv < p_ptr->max_plv) Players[killer]->kills_higher++;
7438 				else Players[killer]->kills_equal++;
7439 
7440 #if 0 /* only reward exp for killing same level or higher players */
7441 				if (Players[killer]->max_plv <= p_ptr->max_plv) {
7442 					/* note how expfact isn't multiplied, so a difference between the races remains :) */
7443 					gain_exp(killer, (player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * (1 + (p_ptr->max_plv - 5) / (Players[killer]->lev - 5)));
7444 				}
7445 #else /* reward exp for all player-kills, but less for killing lower level chars */
7446 				if (Players[killer]->max_plv <= p_ptr->max_plv) {
7447 					/* note how expfact isn't multiplied, so a difference between the races/classes remains, as usual */
7448 					gain_exp(killer, (player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * (1 + (p_ptr->max_plv - 5) / (Players[killer]->lev - 5)));
7449 				} else {
7450 					/* get less exp if player was lower than killer, dropping rapidly */
7451 					k = 2 + Players[killer]->lev - p_ptr->max_plv;//2+k; k*k+0; *12/
7452 					gain_exp(killer, ((player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * 10) / ((k * k) - 2));
7453 				}
7454 #endif
7455 
7456 				/* get victim's kills credited as own ones >:) */
7457 //wrong code: used for rewards	Players[killer]->kills += p_ptr->kills;
7458 #if 0 /* disabled since it doesn't make much sense */
7459 				Players[killer]->kills_lower += p_ptr->kills_lower;
7460 				Players[killer]->kills_equal += p_ptr->kills_equal;
7461 				Players[killer]->kills_higher += p_ptr->kills_higher;
7462 #endif
7463 				Players[killer]->kills++;
7464 				Players[killer]->kills_own++;
7465 
7466 				check_killing_reward(killer);
7467 			} else { /* killed by monster/trap? still reward nearby pvp players! */
7468 				int players_in_area = 0, avg_kills;
7469 				for (i = 1; i <= NumPlayers; i++) {
7470 					if (i == Ind) continue;
7471 					if (is_admin(Players[i])) continue;
7472 					if (Players[i]->conn == NOT_CONNECTED) continue;
7473 					if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
7474 					if (!(Players[i]->mode & MODE_PVP)) continue;
7475 					players_in_area++;
7476 				}
7477 				if (players_in_area) {
7478 					/* give everyone a 'share' of the kills */
7479 #if 0 /* round downwards */
7480 					avg_kills = p_ptr->kills / players_in_area;
7481 					/* at least give 1 kill if player had one */
7482 					if (!avg_kills && p_ptr->kills) avg_kills = 1;
7483 #else /* round upwards! generous */
7484 					avg_kills = (p_ptr->kills + players_in_area - 1) / players_in_area;
7485 #endif
7486 					/* get victim's kills credited as own ones >:) */
7487 					for (i = 1; i <= NumPlayers; i++) {
7488 						if (i == Ind) continue;
7489 						if (is_admin(Players[i])) continue;
7490 						if (Players[i]->conn == NOT_CONNECTED) continue;
7491 						if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
7492 						if (!(Players[i]->mode & MODE_PVP)) continue;
7493 #if 0 /* wrong code (rewards) */
7494 						Players[i]->kills += avg_kills;
7495 #else
7496 						if (avg_kills) Players[i]->kills++;
7497 #endif
7498 						check_killing_reward(i);
7499 					}
7500 				}
7501 			}
7502 		} else { /* wasn't a pvp-mode death */
7503 			/* copy/paste from above pvp section, just for info */
7504 			int killer = name_lookup_quiet(Ind, p_ptr->really_died_from, FALSE, FALSE);
7505 			if (killer) {
7506 				if (Players[killer]->max_plv > p_ptr->max_plv) Players[killer]->kills_lower++;
7507 				else if (Players[killer]->max_plv < p_ptr->max_plv) Players[killer]->kills_higher++;
7508 				else Players[killer]->kills_equal++;
7509 				//wrong code (rewards)	Players[killer]->kills += p_ptr->kills;
7510 #if 0 /* not much sense */
7511 				Players[killer]->kills_lower += p_ptr->kills_lower;
7512 				Players[killer]->kills_equal += p_ptr->kills_equal;
7513 				Players[killer]->kills_higher += p_ptr->kills_higher;
7514 #endif
7515 				Players[killer]->kills++;
7516 				Players[killer]->kills_own++;
7517 
7518 				/* no reward outside of PvP xD */
7519 			}
7520 		}
7521 
7522 		/* Add to legends log if he was at least 50 or died vs Morgoth */
7523 		if (!is_admin(p_ptr)) {
7524 			if (p_ptr->total_winner)
7525 				l_printf("%s \\{r%s royalty %s (%d) died\n", showdate(), p_ptr->male ? "His" : "Her", p_ptr->name, p_ptr->lev);
7526 			else if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_GHOST))
7527 				l_printf("%s \\{r%s (%d) died facing Morgoth\n", showdate(), p_ptr->name, p_ptr->lev);
7528 #ifndef RPG_SERVER
7529 			/* for non-ghost deaths, display somewhat "lower" levels (below 50) too */
7530 			else if (p_ptr->lev >= 40)
7531 				l_printf("%s \\{r%s (%d) died\n", showdate(), p_ptr->name, p_ptr->lev);
7532 #else /* for RPG_SERVER, also display more trivial deaths, so people know the player is up for startup-party again */
7533 			else if (p_ptr->lev >= 20)
7534 				l_printf("%s \\{r%s (%d) died\n", showdate(), p_ptr->name, p_ptr->lev);
7535 #endif
7536 		}
7537 
7538 		erase_player(Ind, death_type, TRUE);
7539 
7540 		/* Done */
7541 		return;
7542 	}
7543 
7544 	/* --- non-noghost-death: everlasting or more lives left --- */
7545 	/* Add to legends log if he was a winner */
7546 	if (p_ptr->total_winner && !is_admin(p_ptr) && p_ptr->alive)
7547 		l_printf("%s \\{r%s (%d) lost %s royal title by death\n", showdate(), p_ptr->name, p_ptr->lev, p_ptr->male ? "his" : "her");
7548 
7549 	/* Tell everyone he died */
7550 	if (p_ptr->alive) {
7551 		if (cfg.unikill_format) {
7552 			if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7553 #ifdef ENABLE_MAIA
7554 			    || streq(p_ptr->died_from, "indecisiveness")
7555 #endif
7556 			    || streq(p_ptr->died_from, "indetermination")
7557 			    || insanity) {
7558 				/* snprintf(buf, sizeof(buf), "\374\377r%s was killed by %s.", p_ptr->name, p_ptr->died_from); */
7559 				/* Add the player lvl to the death message. the_sandman */
7560 				snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was killed by %s", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7561 			}
7562 			else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7563 				/* snprintf(buf, sizeof(buf), "\377r%s was annihilated by %s.", p_ptr->name, p_ptr->died_from); */
7564 				snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was annihilated by %s", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7565 			}
7566 			else {
7567 				snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was vaporized by %s.", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7568 			}
7569 		} else {
7570 			if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7571 #ifdef ENABLE_MAIA
7572 			    || streq(p_ptr->died_from, "indecisiveness")
7573 #endif
7574 			    || streq(p_ptr->died_from, "indetermination")
7575 			    || insanity) {
7576 				/* snprintf(buf, sizeof(buf), "\374\377r%s was killed by %s.", p_ptr->name, p_ptr->died_from); */
7577 				/* Add the player lvl to the death message. the_sandman */
7578 				snprintf(buf, sizeof(buf), "\374\377r%s (%d) was killed by %s", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7579 			}
7580 			else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7581 				/* snprintf(buf, sizeof(buf), "\377r%s was annihilated by %s.", p_ptr->name, p_ptr->died_from); */
7582 				snprintf(buf, sizeof(buf), "\374\377r%s (%d) was annihilated by %s", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7583 			}
7584 			else {
7585 				snprintf(buf, sizeof(buf), "\374\377r%s (%d) was vaporized by %s.", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7586 			}
7587 		}
7588 		s_printf("%s (%d) was killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7589 		if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7590 			s_printf("(%s was really killed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7591 
7592 s_printf("CHARACTER_TERMINATION: NORMAL race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7593 	}
7594 	else if (p_ptr->iron_winner) {
7595 		if (p_ptr->total_winner) {
7596 			snprintf(buf, sizeof(buf), "\374\377vThe iron emperor %s has retired to a warm, sunny climate.", p_ptr->name);
7597 			if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired from the iron throne\n", showdate(), p_ptr->name, p_ptr->lev);
7598 		} else {
7599 			snprintf(buf, sizeof(buf), "\374\377sThe iron champion %s has retired to a warm, sunny climate.", p_ptr->name);
7600 			if (!is_admin(p_ptr)) l_printf("%s \\{s%s (%d) retired as an iron champion\n", showdate(), p_ptr->name, p_ptr->lev);
7601 		}
7602 		s_printf("%s (%d) committed suicide. (Retirement)\n", p_ptr->name, p_ptr->lev);
7603 		retire = TRUE;
7604 		death_type = DEATH_QUIT;
7605 s_printf("CHARACTER_TERMINATION: RETIREMENT race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7606         }
7607 	else if (!p_ptr->total_winner) {
7608 		/* assume newb_suicide option for world broadcasts */
7609 		if (p_ptr->max_plv == 1) world_broadcast = FALSE;
7610 
7611 		snprintf(buf, sizeof(buf), "\374\377D%s committed suicide.", p_ptr->name);
7612 		s_printf("%s (%d) committed suicide.\n", p_ptr->name, p_ptr->lev);
7613 		death_type = DEATH_QUIT;
7614 s_printf("CHARACTER_TERMINATION: SUICIDE race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7615 	} else {
7616 		if (in_valinor(&p_ptr->wpos)) {
7617 			snprintf(buf, sizeof(buf), "\374\377vThe unbeatable %s has retired to the shores of valinor.", p_ptr->name);
7618 			if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired to the shores of valinor\n", showdate(), p_ptr->name, p_ptr->lev);
7619 		} else {
7620 			snprintf(buf, sizeof(buf), "\374\377vThe unbeatable %s has retired to a warm, sunny climate.", p_ptr->name);
7621 			if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired to a warm, sunny climate\n", showdate(), p_ptr->name, p_ptr->lev);
7622 		}
7623 		s_printf("%s (%d) committed suicide. (Retirement)\n", p_ptr->name, p_ptr->lev);
7624 		retire = TRUE;
7625 		death_type = DEATH_QUIT;
7626 s_printf("CHARACTER_TERMINATION: RETIREMENT race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7627 	}
7628 
7629 	if (is_admin(p_ptr)) {
7630 		if (death_type == -1) snprintf(buf, sizeof(buf), "\376\377D%s enters a ghostly state.", p_ptr->name);
7631 		else snprintf(buf, sizeof(buf), "\376\377D%s bids farewell to this plane.", p_ptr->name);
7632 	}
7633 
7634 	/* Tell the players */
7635 	/* handle the secret_dungeon_master option */
7636 	if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)) {
7637 		/* handle newbie suicide option by manually doing 'msg_broadcast': */
7638 		if (death_type == DEATH_QUIT) {
7639 			/* Tell every player */
7640 			for (i = 1; i <= NumPlayers; i++) {
7641 				if (Players[i]->conn == NOT_CONNECTED) continue;
7642 				if (i == Ind) continue;
7643 				if (!Players[i]->newb_suicide && p_ptr->max_plv == 1)
7644 					msg_format(i, "%c%s", '\376', buf + 1);
7645 				else
7646 					msg_print(i, buf);
7647 			}
7648 		} else msg_broadcast(Ind, buf);
7649 
7650 #ifdef TOMENET_WORLDS
7651 		if (cfg.worldd_pdeath && world_broadcast) world_msg(buf);
7652 #endif
7653 	}
7654 
7655 #if 0
7656 	/* Unown land */
7657 	if (p_ptr->total_winner) {
7658 #ifdef NEW_DUNGEON
7659 /* FIXME */
7660 /*
7661 		msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7662 		wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7663 */
7664 #else
7665 		msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7666 		wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7667 #endif
7668 	}
7669 #endif
7670 
7671 	/* No longer a winner */
7672 	p_ptr->total_winner = FALSE;
7673 
7674 	/* Handle suicide */
7675 	if (!p_ptr->alive) {
7676 #ifdef TOMENET_WORLDS
7677 		world_player(p_ptr->id, p_ptr->name, FALSE, TRUE);
7678 #endif
7679 
7680 		/* prevent suicide spam, if set in cfg */
7681 		check_roller(Ind);
7682 
7683 		if (!p_ptr->ghost) {
7684 			if (retire) Send_chardump(Ind, "-retirement");
7685 			else Send_chardump(Ind, "-death");
7686 			Net_output1(Ind);
7687 		}
7688 
7689 		erase_player(Ind, death_type, FALSE);
7690 
7691 		/* Done */
7692 		return;
7693 	}
7694 
7695 	/* Tell him */
7696 	msg_print(Ind, "\374\377RYou die.");
7697 //	msg_print(Ind, NULL);
7698 #if CHATTERBOX_LEVEL > 2
7699 	if (p_ptr->last_words) {
7700 		char death_message[80];
7701 
7702 		(void)get_rnd_line("death.txt", 0, death_message, 80);
7703 		msg_print(Ind, death_message);
7704 	}
7705 #endif	// CHATTERBOX_LEVEL
7706 
7707 	/* Paranoia - ghosts getting destroyed are already caught above */
7708 	if (p_ptr->ghost) Send_chardump(Ind, "-ghost"); else
7709 	Send_chardump(Ind, "-death");
7710 
7711 	/* Polymorph back to player */
7712 	if (p_ptr->body_monster) do_mimic_change(Ind, 0, TRUE);
7713 
7714 	/* Cure him from various maladies */
7715 	p_ptr->black_breath = FALSE;
7716 	if (p_ptr->image) (void)set_image(Ind, 0);
7717 	if (p_ptr->blind) (void)set_blind(Ind, 0);
7718 	if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
7719 	if (p_ptr->confused) (void)set_confused(Ind, 0);
7720 	if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
7721 	if (p_ptr->stun) (void)set_stun(Ind, 0);
7722 	if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
7723 	/* if (p_ptr->food < PY_FOOD_FULL) */
7724 	(void)set_food(Ind, PY_FOOD_FULL - 1);
7725 
7726 	/* Don't have 'vegetable' ghosts running around after equipment was dropped */
7727 	p_ptr->safe_sane = TRUE;
7728 	p_ptr->update |= PU_SANITY;
7729 	update_stuff(Ind);
7730 	p_ptr->safe_sane = FALSE;
7731 
7732 	if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7733 #ifdef ENABLE_MAIA
7734 	    || streq(p_ptr->died_from, "indecisiveness")
7735 #endif
7736 	    || streq(p_ptr->died_from, "indetermination")
7737 	    || insanity) {
7738 		msg_format(Ind, "\374\377RYou have been killed by %s.", p_ptr->died_from);
7739 	}
7740 	else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7741 		msg_format(Ind, "\374\377RYou have been annihilated by %s.", p_ptr->died_from);
7742 	}
7743 	else {
7744 		msg_format(Ind, "\374\377RYou have been vaporized by %s.", p_ptr->died_from);
7745 	}
7746 
7747 #if (MAX_PING_RECVS_LOGGED > 0)
7748 	/* Print last ping reception times */
7749 	struct timeval now;
7750 	gettimeofday(&now, NULL);
7751 	s_printf("PING_RECEIVED:");
7752 	/* Starting from latest */
7753 	for (i = 0; i < MAX_PING_RECVS_LOGGED; i++) {
7754 		j = (p_ptr->pings_received_head - i + MAX_PING_RECVS_LOGGED) % MAX_PING_RECVS_LOGGED;
7755 		if (p_ptr->pings_received[j].tv_sec) {
7756 			s_printf(" %s", timediff(&p_ptr->pings_received[j], &now));
7757 		}
7758 	}
7759 	s_printf("\n");
7760 #endif
7761 
7762 	/* Turn him into a ghost */
7763 	p_ptr->ghost = 1;
7764 	/* Prevent accidental floating up/downwards depending on client option. - C. Blue */
7765 	if (p_ptr->safe_float) p_ptr->safe_float_turns = 5;
7766 
7767 	/* Hack -- drop bones :) */
7768 #ifdef ENABLE_MAIA
7769 	/* hackhack: Maiar don't have a real physical body ;) */
7770 	if (p_ptr->prace != RACE_MAIA)
7771 #endif
7772 	for (i = 0; i < 4; i++) {
7773 		object_type	forge;
7774 		o_ptr = &forge;
7775 
7776 		invcopy(o_ptr, lookup_kind(TV_SKELETON, i ? SV_BROKEN_BONE : SV_BROKEN_SKULL));
7777 		object_known(o_ptr);
7778 		object_aware(Ind, o_ptr);
7779 		o_ptr->owner = p_ptr->id;
7780 		o_ptr->mode = p_ptr->mode;
7781 		o_ptr->level = 0;
7782 		o_ptr->note = quark_add(format("# of %s", p_ptr->name));
7783 		/* o_ptr->note = quark_add(format("#of %s", p_ptr->name));
7784 		the_sandman: removed the auto-space-padding on {# inscs */
7785 
7786 		if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7787 		else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7788 		else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7789 		(void)drop_near(o_ptr, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px);
7790 	}
7791 
7792 	/* Give him his hit points back */
7793 	p_ptr->chp = p_ptr->mhp;
7794 	p_ptr->chp_frac = 0;
7795 
7796 	/* Teleport him */
7797 	/* XXX p_ptr->death allows teleportation even when NO_TELE etc. */
7798 	teleport_player(Ind, 200, TRUE);
7799 
7800 	/* Hack -- Give him/her the newbie death guide */
7801 //	if (p_ptr->max_plv < 20)	/* Now it's for everyone */
7802 	{
7803 		object_type	forge;
7804 		o_ptr = &forge;
7805 
7806 		invcopy(o_ptr, lookup_kind(TV_PARCHMENT, SV_PARCHMENT_DEATH));
7807 		object_known(o_ptr);
7808 		object_aware(Ind, o_ptr);
7809 		o_ptr->owner = p_ptr->id;
7810 		o_ptr->mode = p_ptr->mode;
7811 		o_ptr->level = 1;
7812 		(void)inven_carry(Ind, o_ptr);
7813 	}
7814 	/* Cancel any WOR spells */
7815 	p_ptr->word_recall = 0;
7816 
7817 	/* He is carrying nothing */
7818 	p_ptr->inven_cnt = 0;
7819 
7820 	p_ptr->deaths++;
7821 
7822 	/* Remove the death flag */
7823 	p_ptr->death = FALSE;
7824 
7825 	/* Update bonus */
7826 	p_ptr->update |= (PU_BONUS);
7827 
7828 	/* Redraw */
7829 	p_ptr->redraw |= (PR_HP | PR_GOLD | PR_BASIC | PR_DEPTH);
7830 
7831 	/* Notice */
7832 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
7833 
7834 	/* Windows */
7835 	p_ptr->window |= (PW_INVEN | PW_EQUIP);
7836 
7837 #if 1 /* Enable, iff newbies-level leading to perma-death is disabled above. */
7838 	if (p_ptr->max_plv < cfg.newbies_cannot_drop) {
7839 		msg_format(Ind, "\374\377oYou died below level %d, which means that your items didn't drop.", cfg.newbies_cannot_drop);
7840 		msg_print(Ind, "\374\377oTherefore, it's recommended to press '\377RQ\377o' to suicide and start over.");
7841 		if (p_ptr->wpos.wz < 0) msg_print(Ind, "\374\377oIf you don't like to do that, use '\377R<\377o' to float back to town,");
7842 		else if (p_ptr->wpos.wz > 0) msg_print(Ind, "\374\377oIf you don't like to do that, use '\377R>\377o' to float back to town,");
7843 		else if (in_bree(&p_ptr->wpos)) msg_print(Ind, "\374\377oIf you don't like to do that, of course you may just continue");
7844 		else msg_print(Ind, "\374\377oIf you don't like to do that, just continue by flying back to town");
7845 		msg_print(Ind, "\374\377oand enter the temple (\377g4\377o) to be revived and handed some money.");
7846 	} else
7847 #endif
7848 	if (!p_ptr->warning_death) {
7849 		/* normal warning - in dungeon */
7850 		if (p_ptr->wpos.wz) {
7851 			p_ptr->warning_death = 1;
7852 			msg_print(Ind, "\374\377yIf you leave this floor and nobody else stays on it, it will change and");
7853 			msg_print(Ind, "\374\377ytherefore all your items would be lost! You now have two choices:");
7854 			if (p_ptr->wpos.wz > 0)
7855 				msg_print(Ind, "\374\377ya) Float back to town with '\377o>\377y' key and revive yourself in the temple ('\377g4\377y').");
7856 			else
7857 				msg_print(Ind, "\374\377ya) Float back to town with '\377o<\377y' key and revive yourself in the temple ('\377g4\377y').");
7858 			msg_print(Ind, "\374\377yb) Stay here as a ghost and ask someone else to come and revive you.");
7859 		} else {
7860 		/* specialty - on worldmap */
7861 			if (in_bree(&p_ptr->wpos))
7862 				msg_print(Ind, "\374\377yRevive yourself by floating over to the temple ('\377g4\377y') and entering it.");
7863 			else {
7864 				msg_print(Ind, "\374\377yYou now have two choices:");
7865 				msg_print(Ind, "\374\377ya) Float back to town and revive yourself by entering the temple ('\377g4\377y').");
7866 				msg_print(Ind, "\374\377yb) Stay here as a ghost and ask someone else to come and revive you.");
7867 			}
7868 		}
7869 	}
7870 
7871 #if 0 /* currently disabled, because replaced by warning_death */
7872 	/* Possibly tell him what to do now */
7873 	if (p_ptr->warning_ghost == 0) {
7874 		p_ptr->warning_ghost = 1;
7875 		msg_print(Ind, "\375\377RHINT: You died! You can wait for someone to revive you or use \377o<\377R or \377o>");
7876 		msg_print(Ind, "\375\377R      keys to float back to town and revive yourself in the temple (the \377g4\377R).");
7877 		msg_print(Ind, "\375\377R      If you wish to start over, press \377oSHIFT+q\377R to erase this character.");
7878 		s_printf("warning_ghost: %s\n", p_ptr->name);
7879 	}
7880 #endif
7881 }
7882 
7883 /*
7884  * Resurrect a player
7885  */
7886 
7887  /* To prevent people from ressurecting too many times, I am modifying this to give
7888     everyone 1 "freebie", and then to have a p_ptr->level % chance of failing to
7889     ressurect and have your ghost be destroyed.
7890 
7891     -APD-
7892 
7893     hmm, haven't gotten aroudn to doing this yet...
7894 
7895     loss_reduction tells by how much % the GHOST_XP_LOST is reduced (C. Blue).
7896  */
7897 void resurrect_player(int Ind, int loss_factor) {
7898 	player_type *p_ptr = Players[Ind];
7899 	int reduce;
7900 
7901 	/* Hack -- the dungeon master can not resurrect */
7902 	if (p_ptr->admin_dm) return;	// TRUE;
7903 
7904 	/* Reset ghost flag */
7905 	p_ptr->ghost = 0;
7906 
7907 	disturb(Ind, 1, 0);
7908 
7909 	/* limits - hack: '0' means use default value */
7910 	if (!loss_factor) loss_factor = GHOST_XP_LOST;
7911 	/* paranoia */
7912 	else if (loss_factor < 0) loss_factor = GHOST_XP_LOST;
7913 	else if (loss_factor > 100) loss_factor = GHOST_XP_LOST;
7914 
7915 	/* Lose some experience */
7916 	if (get_skill(p_ptr, SKILL_HCURING) >= 50) loss_factor -= 5;
7917 	if (loss_factor < 30) loss_factor = 30;//hardcoded mess
7918 
7919 	reduce = p_ptr->max_exp;
7920 	reduce = reduce > 99999 ?
7921 	    reduce / 100 * loss_factor : reduce * loss_factor / 100;
7922 	p_ptr->max_exp -= reduce;
7923 
7924 	reduce = p_ptr->exp;
7925 	reduce = reduce > 99999 ?
7926 	    reduce / 100 * loss_factor : reduce * loss_factor / 100;
7927 	p_ptr->exp -= reduce;
7928 
7929 	p_ptr->safe_sane = TRUE;
7930 	check_experience(Ind);
7931 	p_ptr->update |= PU_SANITY;
7932 	update_stuff(Ind);
7933 	p_ptr->safe_sane = FALSE;
7934 
7935 	/* Message */
7936 	msg_print(Ind, "\376\377GYou feel life force return to your body!");
7937 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
7938 
7939 	/* (was in player_death: Take care of ghost suiciding before final resurrection (p_ptr->alive check, C. Blue)) */
7940 	/*if (p_ptr->alive && ((p_ptr->lives > 0+1) && cfg.lifes)) p_ptr->lives--;*/
7941 	/* Tell him his remaining lifes */
7942 	if (!(p_ptr->mode & MODE_EVERLASTING)
7943 	    && !(p_ptr->mode & MODE_PVP)) {
7944 		if (p_ptr->lives > 1+1) p_ptr->lives--;
7945 		if (cfg.lifes) {
7946 			if (p_ptr->lives == 1+1)
7947 				msg_print(Ind, "\376\377GYou have no more resurrections left!");
7948 			else
7949 				msg_format(Ind, "\376\377GYou have %d resurrections left.", p_ptr->lives-1-1);
7950 		}
7951 	}
7952 
7953 	/* Bonus service: Also restore drained exp (for newbies, especially) */
7954 	restore_level(Ind);
7955 
7956 	/* Redraw */
7957 	p_ptr->redraw |= (PR_BASIC);
7958 
7959 	/* Update */
7960 	p_ptr->update |= (PU_BONUS);
7961 
7962 	/* Inform him of instant resurrection option */
7963 	if (p_ptr->warning_instares == 0) {
7964 		p_ptr->warning_instares = 1;
7965 		msg_print(Ind, "\375\377yHINT: You can turn on \377oInstant Resurrection\377y in the temple by pressing '\377or\377y'.");
7966 		msg_print(Ind, "\375\377y      Make sure to read up on it in the \377oguide\377y to understand pros and cons!");
7967 		s_printf("warning_instares: %s\n", p_ptr->name);
7968 	}
7969 }
7970 
7971 void check_xorders(){
7972 	int i, j;
7973 	struct player_type *q_ptr;
7974 	for (i = 0; i < MAX_XORDERS; i++) {
7975 		if (xorders[i].active && xorders[i].id) {
7976 			if ((turn - xorders[i].turn) > MAX_XORDER_TURNS) {
7977 				for (j = 1; j <= NumPlayers; j++) {
7978 					q_ptr = Players[j];
7979 					if (q_ptr && q_ptr->xorder_id == xorders[i].id) {
7980 						msg_print(j, "\376\377oYou have failed your extermination order!");
7981 						q_ptr->xorder_id = 0;
7982 						q_ptr->xorder_num = 0;
7983 					}
7984 				}
7985 				xorders[i].active = 0;
7986 				xorders[i].id = 0;
7987 				xorders[i].type = 0;
7988 			}
7989 		}
7990 	}
7991 }
7992 
7993 void del_xorder(int id){
7994 	int i;
7995 	for (i = 0; i < MAX_XORDERS; i++) {
7996 		if (xorders[i].id == id) {
7997 			s_printf("Extermination order %d removed\n", id);
7998 			xorders[i].active = 0;
7999 			xorders[i].id = 0;
8000 			xorders[i].type = 0;
8001 		}
8002 	}
8003 }
8004 
8005 /* One player leave a quest (death, deletion) */
8006 void rem_xorder(u16b id){
8007 	int i;
8008 
8009 	s_printf("Player death. Extermination order id: %d\n", id);
8010 
8011 	if(!id) return;
8012 
8013 	for (i = 0; i < MAX_XORDERS; i++) {
8014 		if (xorders[i].id == id) {
8015 			break;
8016 		}
8017 	}
8018 	if (i == MAX_XORDERS) return;
8019 	s_printf("Extermination order found in slot %d\n",i);
8020 	if (xorders[i].active) {
8021 		xorders[i].active--;
8022 		s_printf("Remaining active: %d\n", xorders[i].active);
8023 		if (!xorders[i].active) {
8024 			process_hooks(HOOK_QUEST_FAIL, "d", id);
8025 			s_printf("delete call\n");
8026 			del_xorder(id);
8027 		}
8028 	}
8029 }
8030 
8031 void kill_xorder(int Ind) {
8032 	int i;
8033 	u16b id, pos = 9999;
8034 	player_type *p_ptr = Players[Ind], *q_ptr;
8035 	char temp[160];
8036 	bool great, verygreat = FALSE;
8037 	u32b resf;
8038 
8039 	id = p_ptr->xorder_id;
8040 	for (i = 0; i < MAX_XORDERS; i++) {
8041 		if (xorders[i].id == id) {
8042 			pos = i;
8043 			break;
8044 		}
8045 	}
8046 //	if (pos == -1) return;	/* it's UNsigned :) */
8047 	if (pos == 9999) return;
8048 
8049 	process_hooks(HOOK_QUEST_FINISH, "d", Ind);
8050 
8051 	if (xorders[i].flags & QUEST_RACE) {
8052 		snprintf(temp, 160, "\374\377y%s has carried out a%s %s extermination order!",
8053 		    p_ptr->name,
8054 		    is_a_vowel(*(r_name + r_info[xorders[pos].type].name)) ? "n" : "",
8055 		    r_name + r_info[xorders[pos].type].name);
8056 		msg_broadcast(Ind, temp);
8057 	}
8058 	if (xorders[i].flags & QUEST_GUILD) {
8059 		hash_entry *temphash;
8060 		snprintf(temp, 160, "\374\377y%s has carried out the %s extermination order!", p_ptr->name, r_name + r_info[xorders[pos].type].name);
8061 		if ((temphash = lookup_player(xorders[i].creator)) && temphash->guild) {
8062 			guild_msg(temphash->guild ,temp);
8063 			if (!p_ptr->guild) {
8064 				guild_msg_format(temphash->guild, "\374\377%c%s is now a guild member!", COLOUR_CHAT_GUILD, p_ptr->name);
8065 				guilds[temphash->guild].members++;
8066 				msg_format(Ind, "\374\377yYou've been added to '\377%c%s\377w'.", COLOUR_CHAT_GUILD, guilds[temphash->guild].name);
8067 				p_ptr->guild = temphash->guild;
8068 				p_ptr->guild_dna = guilds[p_ptr->guild].dna;
8069 				clockin(Ind, 3);	/* set in db */
8070 			}
8071 			else if (p_ptr->guild == temphash->guild) {
8072 				guild_msg_format(temphash->guild, "\374\377%c%s has carried out the extermination order!", COLOUR_CHAT_GUILD, p_ptr->name);
8073 			}
8074 		}
8075 	} else {
8076 		object_type forge, *o_ptr = &forge;
8077 		int avg;
8078 
8079 		msg_format(Ind, "\374\377yYou have carried out the %s extermination order!", r_name + r_info[xorders[pos].type].name);
8080 		s_printf("r_info quest: %s won the %s extermination order\n", p_ptr->name, r_name + r_info[xorders[pos].type].name);
8081 		strcpy(temp, r_name + r_info[xorders[pos].type].name);
8082 		strcat(temp, " extermination");
8083 		unique_quark = quark_add(temp);
8084 
8085 		/* grant verygreat rerolls for better value? */
8086 		avg = ((r_info[xorders[pos].type].level * 2) + (p_ptr->lev * 4)) / 2;
8087 		avg = avg > 100 ? 100 : avg;
8088 //		if (great && p_ptr->lev >= 25) verygreat = magik(r_info[xorders[pos].type].level - (5 - (p_ptr->lev / 5)));
8089 //		if (great) verygreat = magik(((r_info[xorders[pos].type].level * 2) + (p_ptr->lev * 4)) / 5);
8090 		avg /= 2; avg = 540 / (57 - avg) + 5; /* same as exp calculation ;) phew, Heureka.. (14..75) */
8091 
8092 		/* boost quest rewards for the iron price */
8093 #ifndef RPG_SERVER
8094 		if (in_irondeepdive(&p_ptr->wpos)) {
8095 #endif
8096 			great = TRUE;
8097 			verygreat = magik(avg);
8098 			resf = RESF_LOW2;
8099 #ifndef RPG_SERVER
8100 		} else {
8101 			great = magik(50 + p_ptr->lev * 2);
8102 			if (great) verygreat = magik(avg);
8103 			resf = RESF_LOW;
8104 		}
8105 #endif
8106 
8107 #if 0 /* needs more care, otherwise acquirement could even be BETTER than create_reward, depending on RESF.. */
8108 		create_reward(Ind, o_ptr, getlevel(&p_ptr->wpos), getlevel(&p_ptr->wpos), great, verygreat, resf, 3000);
8109 		if (!o_ptr->note) o_ptr->note = quark_add(temp);
8110 		o_ptr->note_utag = strlen(temp);
8111 		inven_carry(Ind, o_ptr);
8112 #else
8113 		acquirement_direct(o_ptr, &p_ptr->wpos, great, verygreat, resf);
8114 		//s_printf("object rewarded %d,%d,%d\n", o_ptr->tval, o_ptr->sval, o_ptr->k_idx);
8115 		inven_carry(Ind, o_ptr);
8116 #endif
8117 		unique_quark = 0;
8118 	}
8119 
8120 	for (i = 1; i <= NumPlayers; i++) {
8121 		q_ptr = Players[i];
8122 		if (q_ptr && q_ptr->xorder_id == id) {
8123 			q_ptr->xorder_id = 0;
8124 			q_ptr->xorder_num = 0;
8125 		}
8126 	}
8127 	del_xorder(id);
8128 }
8129 
8130 s16b questid = 1;
8131 
8132 bool add_xorder(int Ind, int target, u16b type, u16b num, u16b flags) {
8133 	int i, j;
8134 	bool added = FALSE;
8135 	player_type *p_ptr = Players[target], *q_ptr;
8136 	if (!p_ptr) return(FALSE);
8137 
8138 	process_hooks(HOOK_GEN_QUEST, "d", Ind);
8139 
8140 	for (i = 0; i < MAX_XORDERS; i++) {
8141 		if (!xorders[i].active) {
8142 			xorders[i].active = 0;
8143 			xorders[i].id = questid;
8144 			xorders[i].type = type;
8145 			xorders[i].flags = flags;
8146 			xorders[i].turn = turn;
8147 			added = TRUE;
8148 			break;
8149 		}
8150 	}
8151 	if (!added) {
8152 		msg_print(Ind, "Sorry, no more extermination orders are available at this time.");
8153 		return(FALSE);
8154 	}
8155 	added = 0;
8156 
8157 	/* give it only to the one original target player */
8158 	j = target;
8159 	q_ptr = Players[j];
8160 #ifndef RPG_SERVER
8161 	if (q_ptr->lev < 5 && !in_irondeepdive(&q_ptr->wpos)) return(FALSE); /* level 5 is minimum to do quests */
8162 #else
8163 	if (q_ptr->lev < 3) return(FALSE);
8164 #endif
8165 	q_ptr->xorder_id = questid;
8166 	q_ptr->xorder_num = num;
8167 	clockin(j, 4); /* register that player */
8168 	if ((flags & QUEST_GUILD))
8169 		msg_print(j, "\374\377oYou have been given an extermination order from your guild\377y!");
8170 	else
8171 		msg_print(j, "\376\377oYou have been given a extermination order\377y!");
8172 //	msg_format(j, "\377oFind and kill \377y%d \377g%s%s\377y!", num, r_name+r_info[type].name, flags&QUEST_GUILD?"":" \377obefore any other player");
8173 	msg_format(j, "\376\377oFind and kill \377y%d \377g%s\377o (level %d)!", num, r_name + r_info[type].name, r_info[type].level);
8174 	msg_format(Ind, "\376\377oThe remaining time to carry it out is \377y%d\377o minutes.", MAX_XORDER_TURNS / (cfg.fps * 60));
8175 	xorders[i].active++;
8176 
8177 	if (!xorders[i].active) {
8178 		del_xorder(questid);
8179 		return(FALSE);
8180 	}
8181 	s_printf("Added extermination order id %d (players %d), target %d (%s): %d x %s\n",
8182 	    xorders[i].id, xorders[i].active, target, p_ptr != NULL ? p_ptr->name : "NULL",
8183 	    num, r_name + r_info[type].name);
8184 	questid++;
8185 	if (questid == 0) questid = 1;
8186 	if (target != Ind) {
8187 		if (flags & QUEST_GUILD) {
8188 			guild_msg_format(Players[Ind]->guild, "\374\377%c%s has been given an extermination order!", COLOUR_CHAT_GUILD, p_ptr->name);
8189 		}
8190 		else msg_format(Ind, "Extermination order given to %s", p_ptr->name);
8191 		xorders[i].creator = Players[Ind]->id;
8192 	}
8193 	return(TRUE);
8194 }
8195 
8196 /* prepare some quest parameters for a standard kill quest */
8197 bool prepare_xorder(int Ind, int j, u16b flags, int *level, u16b *type, u16b *num){
8198 	int r = *type, i = *num, lev = *level, k = 0;
8199 
8200 	if (Players[j]->xorder_id) {
8201 		for (i = 0; i < MAX_XORDERS; i++) {
8202 			if (xorders[i].id == Players[j]->xorder_id) {
8203 				if (j == Ind)
8204 					msg_format(Ind, "\376\377oYour %sorder is to exterminate \377y%d \377g%s\377o (level %d).",
8205 					    (xorders[i].flags & QUEST_GUILD) ? "guild's " : "", Players[Ind]->xorder_num,
8206 					    r_name + r_info[xorders[i].type].name, r_info[xorders[i].type].level);
8207 					msg_format(Ind, "\376\377oThe remaining time to carry it out is \377y%d\377o minutes.", (MAX_XORDER_TURNS - (turn - xorders[i].turn)) / (cfg.fps * 60));
8208 				return FALSE;
8209 			}
8210 		}
8211 	}
8212 
8213 	/* don't start too early -C. Blue */
8214 #ifndef RPG_SERVER
8215 	if (Players[j]->lev < 5 && !in_irondeepdive(&Players[j]->wpos)) {
8216 		msg_print(Ind, "\377oYou need to be level 5 or higher to receive an extermination order!");
8217 #else /* for ironman there's no harm in allowing early quests */
8218 	if (Players[j]->lev < 3) {
8219 		msg_print(Ind, "\377oYou need to be level 3 or higher to receive an extermination order!");
8220 #endif
8221 		return FALSE;
8222 	}
8223 
8224 	/* plev 1..50 -> mlev 1..100 (!) */
8225 	if (lev <= 50) lev += (lev * lev) / 83;
8226 	else lev = 80 + rand_int(20);
8227 
8228 	get_mon_num_hook = xorder_aux;
8229 	get_mon_num_prep(0, NULL);
8230 	i = 2 + randint(5);
8231 
8232 	do {
8233 		r = get_mon_num(lev, lev - 10); //reduce OoD chance slightly
8234 
8235 		k++;
8236 		if (k > 100) lev--;
8237 	} while (((lev - 5) > r_info[r].level && lev >= 5) ||
8238 	    (r_info[r].flags1 & RF1_UNIQUE) ||
8239 	    (r_info[r].flags7 & RF7_MULTIPLY) ||
8240 	    !r_info[r].level); /* "no town quests" ;) */
8241 //	    r_info[r].level <= 2); /* no Training Tower quests */
8242 
8243 	/* easier in Ironman environments */
8244 #ifndef RPG_SERVER
8245 	if (in_irondeepdive(&Players[j]->wpos)) {
8246 #endif
8247 		if (lev < 40) {
8248 			if (r_info[r].flags1 & RF1_FRIENDS) i = i + 3 + randint(4);
8249 			/* very easy for very low level non-friends quests */
8250 			else if (lev < 20) i = (i + 1) / 2;
8251 		} else {
8252 			if (r_info[r].flags1 & RF1_FRIENDS) i = i + 9 + randint(5);
8253 			if (i > 6) i--;
8254 			if (i > 4) i--;
8255 		}
8256 #ifndef RPG_SERVER
8257 	/* pack monsters require a high number, so 2-3 packs must be located */
8258 	} else if (r_info[r].flags1 & RF1_FRIENDS) i = i + 11 + randint(7);
8259 #endif
8260 
8261 	/* Hack: If (non-)FRIENDS variant exists, use the first one (usually the non-FRIENDS one) */
8262 	if (r_info[r].dup_idx) r = r_info[r].dup_idx;
8263 
8264 	*level = lev; *type = r; *num = i;
8265 	return TRUE;
8266 }
8267 
8268 
8269 
8270 /*
8271  * Decreases monsters hit points, handling monster death.
8272  *
8273  * We return TRUE if the monster has been killed (and deleted).
8274  *
8275  * We announce monster death (using an optional "death message"
8276  * if given, and a otherwise a generic killed/destroyed message).
8277  *
8278  * Only "physical attacks" can induce the "You have slain" message.
8279  * Missile and Spell attacks will induce the "dies" message, or
8280  * various "specialized" messages.  Note that "You have destroyed"
8281  * and "is destroyed" are synonyms for "You have slain" and "dies".
8282  *
8283  * Hack -- unseen monsters yield "You have killed it." message.
8284  *
8285  * Added fear (DGK) and check whether to print fear messages -CWS
8286  *
8287  * Genericized name, sex, and capitilization -BEN-
8288  *
8289  * As always, the "ghost" processing is a total hack.
8290  *
8291  * Hack -- we "delay" fear messages by passing around a "fear" flag.
8292  *
8293  * XXX XXX XXX Consider decreasing monster experience over time, say,
8294  * by using "(m_exp * m_lev * (m_lev)) / (p_lev * (m_lev + n_killed))"
8295  * instead of simply "(m_exp * m_lev) / (p_lev)", to make the first
8296  * monster worth more than subsequent monsters.  This would also need
8297  * to induce changes in the monster recall code.
8298  */
8299 bool mon_take_hit(int Ind, int m_idx, int dam, bool *fear, cptr note) {
8300 	player_type *p_ptr = Players[Ind];
8301 
8302 	monster_type	*m_ptr = &m_list[m_idx];
8303 	monster_race    *r_ptr = race_inf(m_ptr);
8304 
8305 	s64b		new_exp, new_exp_frac;
8306 	s64b 		tmp_exp;
8307 	long skill_trauma = get_skill(p_ptr, SKILL_TRAUMATURGY) * SKILL_STEP;
8308 	long scale_trauma = 0;
8309 	bool old_tacit = suppress_message;
8310 
8311 //	int dun_level2 = getlevel(&p_ptr->wpos);
8312 	dungeon_type *dt_ptr2 = getdungeon(&p_ptr->wpos);
8313 #if 0
8314 	int dun_type2;
8315 	dungeon_info_type *d_ptr2 = NULL;
8316 	if (p_ptr->wpos.wz) {
8317 	        dun_type2 = dt_ptr2->type;
8318 	        d_ptr2 = &d_info[dun_type2];
8319 	}
8320 #endif
8321 
8322 	p_ptr->test_count++;
8323 	p_ptr->test_dam += dam;
8324 
8325 	/* break charmignore */
8326 	if (m_ptr->charmedignore) {
8327 		Players[m_ptr->charmedignore]->mcharming--;
8328 		m_ptr->charmedignore = 0;
8329 	}
8330 
8331 	/* Redraw (later) if needed */
8332 	update_health(m_idx);
8333 
8334 	/* Change monster's highest player encounter - mode 1+ : a player targetted this monster */
8335 	if (!in_bree(&m_ptr->wpos)) { /* not in Bree, because of Halloween :) */
8336 		if (m_ptr->henc < p_ptr->max_lev) m_ptr->henc = p_ptr->max_lev;
8337 		if (m_ptr->henc_top < (p_ptr->max_lev + p_ptr->max_plv) / 2) m_ptr->henc_top = (p_ptr->max_lev + p_ptr->max_plv) / 2;
8338 		if (m_ptr->henc < p_ptr->supp) m_ptr->henc = p_ptr->supp;
8339 		if (m_ptr->henc_top < (p_ptr->max_lev + p_ptr->supp_top) / 2) m_ptr->henc_top = (p_ptr->max_lev + p_ptr->supp_top) / 2;
8340 	}
8341 
8342 	/* Traumaturgy skill - C. Blue */
8343 	if (dam && skill_trauma &&
8344 /*	    los(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) && */
8345 /*	    projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE) && */
8346 	    target_able(Ind, m_idx) &&
8347 	    (!(r_ptr->flags3 & RF3_UNDEAD)) &&
8348 	    (!(r_ptr->flags3 & RF3_NONLIVING)) &&
8349 	    (!(strchr("AEgv", r_ptr->d_char))))
8350 	{
8351 		/* difficult to balance, due to the different damage effects of spells- might need some changes */
8352 		long gain = scale_trauma;
8353 		gain = (dam/20 > gain ? gain : dam/20);//50
8354 		if (gain > m_ptr->hp) gain = m_ptr->hp;
8355 		if (!gain && magik(dam * 5)) gain = 1; /* no perma-supply for level 1 mana bolts for now */
8356 
8357 		if (gain && (p_ptr->csp < p_ptr->msp)) {
8358 			msg_print(Ind, "You draw energy from the pain of your opponent.");
8359 			p_ptr->csp += gain;
8360 	                if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
8361 			p_ptr->redraw |= (PR_MANA);
8362 		}
8363 	}
8364 
8365 	/* Some monsters are immune to death */
8366 	if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
8367 
8368 	/* Wake it up */
8369 	m_ptr->csleep = 0;
8370 
8371 	/* for when a quest giver turned non-invincible */
8372 #if 0
8373 	if (m_ptr->questor) {
8374 		if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
8375 			if (q_info[m_ptr->quest].stage[q_info[m_ptr->quest].cur_stage].questor_hostility[m_ptr->questor_idx] &&
8376 			    m_ptr->hp - dam <= q_info[m_ptr->quest].stage[q_info[m_ptr->quest].cur_stage].questor_hostility[m_ptr->questor_idx]->hostile_revert_hp)
8377 				quest_questor_reverts(m_ptr->quest, m_ptr->questor_idx, &m_ptr->wpos);
8378 		} else {
8379 			s_printf("QUESTOR DEPRECATED (monster_dead3)\n");
8380 		}
8381 	}
8382 #else
8383 	if (m_ptr->questor && m_ptr->hp - dam <= m_ptr->limit_hp) {
8384 		if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx)
8385 			quest_questor_reverts(m_ptr->quest, m_ptr->questor_idx, &m_ptr->wpos);
8386 		else
8387 			s_printf("QUESTOR DEPRECATED (monster_dead3)\n");
8388 	}
8389 #endif
8390 
8391 	/* Hurt it */
8392 	m_ptr->hp -= dam;
8393 
8394 	/* record the data for use in C_BLUE_AI */
8395 	p_ptr->dam_turn[0] += (m_ptr->hp < dam) ? m_ptr->hp : dam;
8396 
8397 	/* It is dead now */
8398 	if (m_ptr->hp < 0) {
8399 #ifdef ARCADE_SERVER
8400 		cave_set_feat(&m_ptr->wpos, m_ptr->fy, m_ptr->fx, 172); /* drop "blood"? */
8401 		if(m_ptr->hp < -1000) {
8402 
8403 			object_type forge, *o_ptr;
8404 			o_ptr = &forge;
8405 
8406 			int i, head, arm, leg, part, ok;
8407 			head = arm = leg = part = 0;
8408 			for (i = 1; i < 5; i++) {
8409 			        ok = 0;
8410 				while(ok == 0) {
8411 					ok = 1;
8412 					part = randint(4);
8413 					if(part == 1 && head == 1)
8414 						ok = 0;
8415 					if(part == 2 && arm == 2)
8416 						ok = 0;
8417 					if(part == 4 && leg == 2)
8418 						ok = 0;
8419 				}
8420 				if(part == 1)
8421 					head++;
8422 				if(part == 2)
8423 					arm++;
8424 				if(part == 4)
8425 					leg++;
8426 				invcopy(o_ptr, lookup_kind(TV_SKELETON, part));
8427 				object_known(o_ptr);
8428 				o_ptr->owner = p_ptr->id;
8429 				o_ptr->mode = p_ptr->mode;
8430 				o_ptr->level = 1;
8431 				o_ptr->marked2 = ITEM_REMOVAL_NORMAL;
8432 				(void)drop_near(o_ptr, 0, &m_ptr->wpos, m_ptr->fy, m_ptr->fx);
8433 			}
8434 		}
8435 #endif
8436 
8437 		char m_name[MNAME_LEN];
8438 		dun_level *l_ptr = getfloor(&p_ptr->wpos);
8439 
8440 
8441 		/* prepare for experience calculation further down */
8442 		if (m_ptr->level == 0) tmp_exp = r_ptr->mexp;
8443 		else tmp_exp = r_ptr->mexp * m_ptr->level;
8444 
8445 		/* for when a quest giver turned non-invincible */
8446 		if (m_ptr->questor) {
8447 			if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
8448 				if (q_info[m_ptr->quest].questor[m_ptr->questor_idx].exp != -1)
8449 					tmp_exp = q_info[m_ptr->quest].questor[m_ptr->questor_idx].exp * m_ptr->level;
8450 			} else {
8451 				s_printf("QUESTOR DEPRECATED (monster_deatd2)\n");
8452 			}
8453 		}
8454 
8455 
8456 		/* for obtaining statistical IDDC information: */
8457 		if (l_ptr) l_ptr->monsters_killed++;
8458 
8459 		/* Hack -- remove possible suppress flag */
8460 		suppress_message = FALSE;
8461 
8462 		/* Extract monster name */
8463 		monster_desc(Ind, m_name, m_idx, 0);
8464 
8465 #ifdef USE_SOUND_2010
8466 #else
8467 		sound(Ind, SOUND_KILL);
8468 #endif
8469 
8470 		/* Death by Missile/Spell attack */
8471 		/* DEG modified spell damage messages. */
8472 		if (note) {
8473 			msg_format_near(Ind, "\377y%^s%s from \377g%d \377ydamage.", m_name, note, dam);
8474 			msg_format(Ind, "\377y%^s%s from \377g%d \377ydamage.", m_name, note, dam);
8475 		}
8476 
8477 		/* Death by physical attack -- invisible monster */
8478 		else if (!p_ptr->mon_vis[m_idx]) {
8479 			msg_format_near(Ind, "\377y%^s has been killed from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8480 			msg_format(Ind, "\377yYou have killed %s.", m_name);
8481 		}
8482 
8483 		/* Death by Physical attack -- non-living monster */
8484 		else if ((r_ptr->flags3 & RF3_DEMON) ||
8485 		         (r_ptr->flags3 & RF3_UNDEAD) ||
8486 		         (r_ptr->flags2 & RF2_STUPID) ||
8487 		         (strchr("Evg", r_ptr->d_char))) {
8488 			msg_format_near(Ind, "\377y%^s has been destroyed from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8489 			msg_format(Ind, "\377yYou have destroyed %s.", m_name);
8490 		}
8491 
8492 		/* Death by Physical attack -- living monster */
8493 		else {
8494 			msg_format_near(Ind, "\377y%^s has been slain from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8495 			msg_format(Ind, "\377yYou have slain %s.", m_name);
8496 		}
8497 
8498 		/* Check if it's cloned unique, ie "someone else's spawn" */
8499 		if ((r_ptr->flags1 & RF1_UNIQUE) && p_ptr->r_killed[m_ptr->r_idx] == 1)
8500 			m_ptr->clone = 90; /* still allow some experience to be gained */
8501 
8502 		/* Generate treasure and give kill credit */
8503 		monster_death(Ind, m_idx);
8504 
8505 
8506 		/* experience calculation: gain 2 decimal digits (for low-level exp'ing) */
8507 		tmp_exp *= 100;
8508 
8509 		/* Award players of disadvantageous situations */
8510 		if (l_ptr) {
8511 			int factor = 100;
8512 			if (l_ptr->flags1 & LF1_NO_MAGIC)     factor += 10;
8513 			if (l_ptr->flags1 & LF1_NO_MAP)       factor += 15;
8514 			if (l_ptr->flags1 & LF1_NO_MAGIC_MAP) factor += 10;
8515 			if (l_ptr->flags1 & LF1_NO_DESTROY)   factor += 5;
8516 			if (l_ptr->flags1 & LF1_NO_GENO)      factor += 5;
8517 
8518 			tmp_exp = (tmp_exp * factor) / 100;
8519 		}
8520 
8521 		if (p_ptr->wpos.wz) {
8522 			int factor = 100;
8523 			if (dt_ptr2->flags1 & DF1_NO_UP)		factor += 5;
8524 			if (dt_ptr2->flags2 & DF2_NO_RECALL_INTO)	factor += 5;
8525 			if (dt_ptr2->flags1 & DF1_NO_RECALL)		factor += 10;
8526 			if (dt_ptr2->flags1 & DF1_FORCE_DOWN)		factor += 10;
8527 			if (dt_ptr2->flags2 & DF2_IRON)			factor += 15;
8528 			if (dt_ptr2->flags2 & DF2_HELL)			factor += 10;
8529 			if (dt_ptr2->flags2 & DF2_NO_DEATH)		factor -= 50;
8530 
8531 			if (dt_ptr2->flags3 & DF3_EXP_5)		factor += 5;
8532 			if (dt_ptr2->flags3 & DF3_EXP_10)		factor += 10;
8533 			if (dt_ptr2->flags3 & DF3_EXP_20)		factor += 20;
8534 
8535 #ifdef DUNGEON_VISIT_BONUS
8536 			if (!(dt_ptr2->flags3 & DF3_NO_DUNGEON_BONUS))
8537 				switch (dungeon_bonus[dt_ptr2->id]) {
8538 				case 3: factor += 20; break;
8539 				case 2: factor += 13; break;
8540 				case 1: factor += 7; break;
8541 				}
8542 #endif
8543 
8544 			tmp_exp = (tmp_exp * factor) / 100;
8545 		}
8546 
8547 		if (p_ptr->wpos.wz != 0) {
8548 			/* Monsters in the Nether Realm give extra-high exp,
8549 			   +2% per floor! (C. Blue) */
8550 			if (dt_ptr2->type == DI_NETHER_REALM)
8551 				tmp_exp = ((((-p_ptr->wpos.wz) * 2) + 100) * tmp_exp) / 100;
8552 		}
8553 
8554 		/* factor in clone state */
8555 		tmp_exp = (tmp_exp * (100 - m_ptr->clone)) / 100;
8556 
8557 		/* Split experience if in a party */
8558 		if (p_ptr->party == 0 || p_ptr->ghost) {
8559 			/* Don't allow cheap support from super-high level characters */
8560 			if (cfg.henc_strictness && !p_ptr->total_winner &&
8561 			    /* p_ptr->lev more logical but harsh: */
8562 #if 1 /* player should always seek not too high-level party members compared to player's current real level? */
8563 			    m_ptr->henc - p_ptr->max_lev > MAX_PARTY_LEVEL_DIFF + 1)
8564 #else /* players may seek higher-level party members to team up with if he's died before? Weird combination so not recommended! */
8565 			    m_ptr->henc - p_ptr->max_plv > MAX_PARTY_LEVEL_DIFF + 1)
8566 #endif
8567 				tmp_exp = 0; /* zonk */
8568 
8569 			else {
8570 				/* Higher characters who farm monsters on low levels compared to
8571 				   their clvl will gain less exp. */
8572 				if (!in_irondeepdive(&p_ptr->wpos))
8573 					tmp_exp = det_exp_level(tmp_exp, p_ptr->lev, getlevel(&p_ptr->wpos));
8574 
8575 				/* Give some experience, undo 2 extra digits */
8576 				new_exp = tmp_exp / p_ptr->lev / 100;
8577 
8578 				/* Give fractional experience, undo 2 extra digits (*100L instead of *10000L) */
8579 				new_exp_frac = ((tmp_exp - new_exp * p_ptr->lev * 100)
8580 						* 100L) / p_ptr->lev + p_ptr->exp_frac;
8581 
8582 				/* Never get too much exp off a monster
8583 				   due to high level difference,
8584 				   make exception for low exp boosts like "holy jackal" */
8585 				if ((new_exp > r_ptr->mexp * 4) && (new_exp > 200)) {
8586 					new_exp = r_ptr->mexp * 4;
8587 					new_exp_frac = 0;
8588 				}
8589 
8590 				/* Keep track of experience */
8591 				if (new_exp_frac >= 10000L) {
8592 					new_exp++;
8593 					p_ptr->exp_frac = new_exp_frac - 10000L;
8594 				} else {
8595 					p_ptr->exp_frac = new_exp_frac;
8596 					p_ptr->redraw |= PR_EXP; //EXP_BAR_FINESCALE
8597 				}
8598 
8599 				/* Gain experience */
8600 				if (new_exp) {
8601 					if (!(p_ptr->mode & MODE_PVP)) gain_exp(Ind, new_exp);
8602 				} else if (!p_ptr->warning_fracexp && tmp_exp) {
8603 					msg_print(Ind, "\374\377ySome monsters give less than 1 experience point, but you still gain a bit!");
8604 					s_printf("warning_fracexp: %s\n", p_ptr->name);
8605 					p_ptr->warning_fracexp = 1;
8606 				}
8607 			}
8608 		} else {
8609 			/* Give experience to that party */
8610 			/* Seemingly it's severe to cloning, but maybe it's ok :) */
8611 //			if (!player_is_king(Ind) && !m_ptr->clone) party_gain_exp(Ind, p_ptr->party, tmp_exp);
8612 			/* Since players won't share exp if leveldiff > MAX_PARTY_LEVEL_DIFF (7)
8613 			   I see ne problem with kings sharing exp.
8614 			   Otherwise Nether Realm parties are punished.. */
8615 //			if (!player_is_king(Ind)) party_gain_exp(Ind, p_ptr->party, tmp_exp);
8616 			//add 2 extra digits to r_ptr->mexp too by multiplying by 100, to match tmp_exp shift
8617 			if (!(p_ptr->mode & MODE_PVP)) party_gain_exp(Ind, p_ptr->party, tmp_exp, r_ptr->mexp * 100, m_ptr->henc, m_ptr->henc_top);
8618 		}
8619 
8620 
8621 		/*
8622 		 * Necromancy skill regenerates you
8623 		 * Cannot drain an undead or nonliving monster
8624 		 */
8625 		if ((get_skill(p_ptr, SKILL_NECROMANCY)) &&
8626 			(!(r_ptr->flags3 & RF3_UNDEAD)) &&
8627 			(!(r_ptr->flags3 & RF3_NONLIVING)) &&
8628 			target_able(Ind, m_idx) && !p_ptr->ghost) /* Target must be in LoS */
8629 		{
8630 /*			int gain = (r_ptr->level *
8631 				get_skill_scale(p_ptr, SKILL_NECROMANCY, 100)) / 100 +
8632 				get_skill(p_ptr, SKILL_NECROMANCY); */
8633 			long gain, gain_sp, skill; /* let's make it more complicated - gain HP and SP now - C. Blue */
8634 
8635 			skill = get_skill_scale(p_ptr, SKILL_NECROMANCY, 50);
8636 			gain = get_skill_scale(p_ptr, SKILL_NECROMANCY, 100);
8637 
8638 			gain = (m_ptr->level > gain ? gain : m_ptr->level);
8639 			gain_sp = gain;
8640 
8641 			if (skill >= 15) gain = (2 + gain) * (2 + gain) * (2 + gain) / 327;
8642 			else gain = ((3 + skill) * (3 +  skill) - 9) / 21;
8643 
8644 			if (!gain) gain = 1; /* level 0 monsters (and super-low skill) give some energy too */
8645 
8646 #if 0 /* strange values I guess */
8647 			if (gain_sp >= 60) gain_sp = (gain_sp - 60) * 20 + 100;
8648 			else if (gain_sp >= 40) gain_sp = (gain_sp - 40) * 4 + 20;
8649 			else if (gain_sp >= 30) gain_sp = (gain_sp - 30) + 7;
8650 			else if (gain_sp >= 20) gain_sp = (gain_sp - 20) / 2 + 2;
8651 			else gain_sp /= 10;
8652 			if (!gain_sp && magik(25)) gain_sp = 1; /* level 0 monsters have chance to give energy too */
8653 #else
8654 			gain_sp = ((gain_sp + 1) * (gain_sp + 1)) / 50;
8655 			if (!gain_sp) gain_sp = 1; /* level 0 monsters give energy */
8656 #endif
8657 
8658 			if ((p_ptr->chp < p_ptr->mhp) || (p_ptr->csp < p_ptr->msp)) {
8659 				msg_print(Ind, "You absorb the energy of the dying soul.");
8660 				hp_player_quiet(Ind, gain, TRUE);
8661 				p_ptr->csp += gain_sp;
8662 				if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
8663 				p_ptr->redraw |= (PR_MANA);
8664 			}
8665 		}
8666 
8667 		/* RANGED ATTACKS ONLY vampire feeding! */
8668 		/* Vampires feed off the life force! (if any) */
8669 		// mimic forms for vampires/bats: 432, 520, 521, 623, 989
8670 		if (p_ptr->vamp_fed_midx == m_idx) p_ptr->vamp_fed_midx = 0;
8671 		else if (p_ptr->prace == RACE_VAMPIRE &&
8672 		    !((r_ptr->flags3 & RF3_UNDEAD) ||
8673 		    //(r_ptr->flags3 & RF3_DEMON) ||
8674 		    (r_ptr->flags3 & RF3_NONLIVING) ||
8675 		    (strchr("Egv", r_ptr->d_char)))
8676 		    /* not too far away? */
8677 		    && (ABS(m_ptr->fx - p_ptr->px) <= 1 && ABS(m_ptr->fy - p_ptr->py) <= 1)) {
8678 			int feed = m_ptr->maxhp + 100;
8679 			feed = (6 - (300 / feed)) * 100;//300..600
8680 			if (r_ptr->flags3 & RF3_DEMON) feed /= 2;
8681 			if (r_ptr->d_char == 'A') feed /= 3;
8682 			/* Never get gorged */
8683 			feed += p_ptr->food;
8684 			if (feed >= PY_FOOD_MAX) feed = PY_FOOD_MAX - 1;
8685 			set_food(Ind, feed);
8686 		}
8687 
8688 		/* Kill credit for quest */
8689 		if (!m_ptr->clone) {
8690 			int i, credit_idx = r_ptr->dup_idx ? r_ptr->dup_idx : m_ptr->r_idx;
8691 			for (i = 0; i < MAX_XORDERS; i++) {
8692 				if (p_ptr->xorder_id && xorders[i].id == p_ptr->xorder_id) {
8693 					if (credit_idx == xorders[i].type) {
8694 						p_ptr->xorder_num--;
8695 						if (p_ptr->xorder_num <= 0) { //there's a panic save bug after verygreat apply magic, q_n = -1 after
8696 							kill_xorder(Ind);
8697 						} else
8698 							msg_format(Ind, "%d more to go!", p_ptr->xorder_num);
8699 					}
8700 					break;
8701 				}
8702 			}
8703 		}
8704 
8705 #ifdef MONSTER_INVENTORY
8706 		monster_drop_carried_objects(m_ptr);
8707 #endif	// MONSTER_INVENTORY
8708 
8709 
8710 		/* When the player kills a Unique, it stays dead */
8711 		/* No more, this is handled byt p_ptr->r_killed -- DG */
8712 //		if (r_ptr->flags1 & RF1_UNIQUE) r_ptr->max_num = 0;
8713 //		p_ptr->r_killed[m_ptr->r_idx] = TRUE;
8714 
8715 		/* Recall even invisible uniques or winners */
8716 		if (p_ptr->mon_vis[m_idx] || (r_ptr->flags1 & RF1_UNIQUE)) {
8717 			/* Count kills in all lives */
8718 			if (!is_admin(p_ptr)) r_ptr->r_tkills++;
8719 
8720 			/* Hack -- Auto-recall */
8721 			recent_track(m_ptr->r_idx);
8722 		}
8723 
8724 		/* Delete the monster */
8725 		delete_monster_idx(m_idx, FALSE);
8726 
8727 		/* Not afraid */
8728 		(*fear) = FALSE;
8729 
8730 		suppress_message = old_tacit;
8731 
8732 		/* Monster is dead */
8733 		return (TRUE);
8734 	}
8735 
8736 
8737 #ifdef ALLOW_FEAR
8738 
8739 	/* Mega-Hack -- Pain cancels fear */
8740 	if (m_ptr->monfear && (dam > 0)) {
8741 		int tmp = randint(dam);
8742 
8743 		/* Cure a little fear */
8744 		if (tmp < m_ptr->monfear) {
8745 			/* Reduce fear */
8746 			m_ptr->monfear -= tmp;
8747 		}
8748 
8749 		/* Cure all the fear */
8750 		else {
8751 			/* Cure fear */
8752 			m_ptr->monfear = 0;
8753 
8754 			/* No more fear */
8755 			(*fear) = FALSE;
8756 		}
8757 	}
8758 
8759 	/* Sometimes a monster gets scared by damage */
8760 	else if (!m_ptr->monfear && !(r_ptr->flags3 & RF3_NO_FEAR)) {
8761 		int percentage;
8762 
8763 		/* prevent crash bug that happened in line 8237 (mon_take_hit),
8764 		   apparently maxhp can extremely rarely be 0 - C. Blue */
8765 		if (m_ptr->maxhp == 0) {
8766 			s_printf("DBG_MAXHP_1 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
8767 			return FALSE;
8768 		}
8769 
8770 		/* Percentage of fully healthy */
8771 		percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
8772 
8773 		/*
8774 		 * Run (sometimes) if at 10% or less of max hit points,
8775 		 * or (usually) when hit for half its current hit points
8776 		 */
8777 		if (((percentage <= 10) && (rand_int(10) < percentage)) ||
8778 		    ((dam >= m_ptr->hp) && (rand_int(100) < 80)))
8779 		{
8780 			/* Hack -- note fear */
8781 			(*fear) = TRUE;
8782 
8783 			/* XXX XXX XXX Hack -- Add some timed fear */
8784 			m_ptr->monfear = (randint(10) +
8785 			                  (((dam >= m_ptr->hp) && (percentage > 7)) ?
8786 			                   20 : ((11 - percentage) * 5)));
8787 			m_ptr->monfear_gone = 0;
8788 		}
8789 	}
8790 
8791 #endif
8792 
8793 	/* Not dead yet */
8794 	return (FALSE);
8795 }
8796 
8797 void monster_death_mon(int am_idx, int m_idx)
8798 {
8799 	int			i, j, y, x, ny, nx;
8800 	int			number = 0;
8801 	cave_type		*c_ptr;
8802 
8803 	monster_type	*m_ptr = &m_list[m_idx];
8804 	monster_race *r_ptr = race_inf(m_ptr);
8805 
8806 	bool good = (r_ptr->flags1 & RF1_DROP_GOOD) ? TRUE : FALSE;
8807 	bool great = (r_ptr->flags1 & RF1_DROP_GREAT) ? TRUE : FALSE;
8808 
8809 	bool do_gold = (!(r_ptr->flags1 & RF1_ONLY_ITEM));
8810 	bool do_item = (!(r_ptr->flags1 & RF1_ONLY_GOLD));
8811 
8812 	int force_coin = get_coin_type(r_ptr);
8813 	struct worldpos *wpos;
8814 	cave_type **zcave;
8815 
8816 	/* Get the location */
8817 	y = m_ptr->fy;
8818 	x = m_ptr->fx;
8819 	wpos = &m_ptr->wpos;
8820 	if (!(zcave = getcave(wpos))) return;
8821 
8822 	/* Determine how much we can drop */
8823 	if ((r_ptr->flags1 & RF1_DROP_60) && (rand_int(100) < 60)) number++;
8824 	if ((r_ptr->flags1 & RF1_DROP_90) && (rand_int(100) < 90)) number++;
8825 	if (r_ptr->flags0 & RF0_DROP_1) number++;
8826 	if (r_ptr->flags1 & RF1_DROP_1D2) number += damroll(1, 2);
8827 	if (r_ptr->flags1 & RF1_DROP_2D2) number += damroll(2, 2);
8828 	if (r_ptr->flags1 & RF1_DROP_3D2) number += damroll(3, 2);
8829 	if (r_ptr->flags1 & RF1_DROP_4D2) number += damroll(4, 2);
8830 
8831 	/* Drop some objects */
8832 	for (j = 0; j < number; j++) {
8833 		/* Try 20 times per item, increasing range */
8834 		for (i = 0; i < 20; ++i) {
8835 			int d = (i + 14) / 15;
8836 
8837 			/* Pick a "correct" location */
8838 			scatter(wpos, &ny, &nx, y, x, d, 0);
8839 
8840 			/* Must be "clean" floor grid */
8841 			if (!cave_clean_bold(zcave, ny, nx)) continue;
8842 
8843 			/* Access the grid */
8844 			c_ptr = &zcave[ny][nx];
8845 
8846 			/* Hack -- handle creeping coins */
8847 			coin_type = force_coin;
8848 
8849 			/* Average dungeon and monster levels */
8850 			object_level = (getlevel(wpos) + r_ptr->level) / 2;
8851 
8852 			/* No easy item hunting in towns.. */
8853 			if (wpos->wz == 0) object_level = r_ptr->level / 2;
8854 
8855 			/* Place Gold */
8856 			if (do_gold && (!do_item || (rand_int(100) < 50))) {
8857 				place_gold(wpos, ny, nx, 0);
8858 			}
8859 			/* Place Object */
8860 			else {
8861 				place_object_restrictor = RESF_NONE;
8862 				place_object(wpos, ny, nx, good, great, FALSE, RESF_LOW, default_obj_theme, 0, ITEM_REMOVAL_NORMAL);
8863 			}
8864 
8865 			/* Reset the object level */
8866 			object_level = getlevel(wpos);
8867 
8868 			/* Reset "coin" type */
8869 			coin_type = 0;
8870 
8871 			/* Notice */
8872 			note_spot_depth(wpos, ny, nx);
8873 
8874 			/* Display */
8875 			everyone_lite_spot(wpos, ny, nx);
8876 
8877 			/* Under a player */
8878 			if (c_ptr->m_idx < 0) {
8879 				msg_print(0 - c_ptr->m_idx, "You feel something roll beneath your feet.");
8880 			}
8881 
8882 			break;
8883 		}
8884 	}
8885 
8886 	FREE(m_ptr->r_ptr, monster_race);
8887 }
8888 
8889 bool mon_take_hit_mon(int am_idx, int m_idx, int dam, bool *fear, cptr note)
8890 {
8891 	monster_type *am_ptr = &m_list[am_idx];
8892 	monster_type	*m_ptr = &m_list[m_idx];
8893 	monster_race    *r_ptr = race_inf(m_ptr);
8894 	s64b		new_exp;
8895 
8896 	/* Redraw (later) if needed */
8897 	update_health(m_idx);
8898 
8899 	/* Wake it up */
8900 	m_ptr->csleep = 0;
8901 
8902 	/* Hurt it */
8903 	m_ptr->hp -= dam;
8904 
8905 	/* Cannot kill uniques */
8906 	if ((r_ptr->flags1 & RF1_UNIQUE) && (m_ptr->hp < 1)) m_ptr->hp = 1;
8907 
8908 	/* It is dead now */
8909 	if (m_ptr->hp < 0) {
8910 		/* Give some experience */
8911 //		new_exp = ((long)r_ptr->mexp * r_ptr->level) / am_ptr->level;
8912 		/* Division by zero occurs here when a pet attacks a townie (level 0) - mikaelh */
8913 		/* Only gain exp when target monster level > 0 */
8914 		if (am_ptr->level > 0) {
8915 			new_exp = ((long)r_ptr->mexp * m_ptr->level) / am_ptr->level;
8916 
8917 			/* Gain experience */
8918 			if((new_exp*(100-m_ptr->clone))/100)
8919 				/* disabled for golems for now, till attack-bug (9k damage) has been solved */
8920 				if (!m_ptr->special && !m_ptr->owner)
8921 					monster_gain_exp(am_idx, (new_exp*(100-m_ptr->clone))/100, TRUE);
8922 		}
8923 /*
8924 switch (m_ptr->r_idx - 1) {
8925 case SV_GOLEM_WOOD:
8926 case SV_GOLEM_COPPER:
8927 case SV_GOLEM_IRON:
8928 case SV_GOLEM_ALUM:
8929 case SV_GOLEM_SILVER:
8930 case SV_GOLEM_GOLD:
8931 case SV_GOLEM_MITHRIL:
8932 case SV_GOLEM_ADAM:
8933 } */
8934 
8935 		/* Generate treasure */
8936                 if (!m_ptr->clone) monster_death_mon(am_idx, m_idx);
8937 
8938 		/* Delete the monster */
8939 		delete_monster_idx(m_idx, TRUE);
8940 
8941 		/* Not afraid */
8942 		(*fear) = FALSE;
8943 
8944 		/* Monster is dead */
8945 		return (TRUE);
8946 	}
8947 
8948 
8949 #ifdef ALLOW_FEAR
8950 
8951 	/* Mega-Hack -- Pain cancels fear */
8952 	if (m_ptr->monfear && (dam > 0)) {
8953 		int tmp = randint(dam);
8954 
8955 		/* Cure a little fear */
8956 		if (tmp < m_ptr->monfear) {
8957 			/* Reduce fear */
8958 			m_ptr->monfear -= tmp;
8959 		}
8960 		/* Cure all the fear */
8961 		else {
8962 			/* Cure fear */
8963 			m_ptr->monfear = 0;
8964 
8965 			/* No more fear */
8966 			(*fear) = FALSE;
8967 		}
8968 	}
8969 
8970 	/* Sometimes a monster gets scared by damage */
8971 	else if (!m_ptr->monfear && !(r_ptr->flags3 & RF3_NO_FEAR)) {
8972 		int percentage;
8973 
8974 		/* prevent crash bug that happened in line 8237 (mon_take_hit),
8975 		   apparently maxhp can extremely rarely be 0 - C. Blue */
8976 		if (m_ptr->maxhp == 0) {
8977 			s_printf("DBG_MAXHP_2 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
8978 			return FALSE;
8979 		}
8980 
8981 		/* Percentage of fully healthy */
8982 		percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
8983 
8984 		/*
8985 		 * Run (sometimes) if at 10% or less of max hit points,
8986 		 * or (usually) when hit for half its current hit points
8987 		 */
8988 		if (((percentage <= 10) && (rand_int(10) < percentage)) ||
8989 		    ((dam >= m_ptr->hp) && (rand_int(100) < 80))) {
8990 			/* Hack -- note fear */
8991 			(*fear) = TRUE;
8992 
8993 			/* XXX XXX XXX Hack -- Add some timed fear */
8994 			m_ptr->monfear = (randint(10) +
8995 			    (((dam >= m_ptr->hp) && (percentage > 7)) ?
8996 			    20 : ((11 - percentage) * 5)));
8997 			m_ptr->monfear_gone = 0;
8998 		}
8999 	}
9000 
9001 #endif
9002 
9003 	/* Not dead yet */
9004 	return (FALSE);
9005 }
9006 
9007 /* Initialises the panel, when newly entering a level */
9008 void panel_calculate(Ind) {
9009 	player_type *p_ptr = Players[Ind];
9010 
9011         p_ptr->panel_row = ((p_ptr->py - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9012         if (p_ptr->panel_row > p_ptr->max_panel_rows) p_ptr->panel_row = p_ptr->max_panel_rows;
9013         else if (p_ptr->panel_row < 0) p_ptr->panel_row = 0;
9014 
9015         p_ptr->panel_col = ((p_ptr->px - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9016         if (p_ptr->panel_col > p_ptr->max_panel_cols) p_ptr->panel_col = p_ptr->max_panel_cols;
9017         else if (p_ptr->panel_col < 0) p_ptr->panel_col = 0;
9018 
9019 #ifdef ALERT_OFFPANEL_DAM
9020 	/* For alert-beeps on damage: Reset remembered panel */
9021 	p_ptr->panel_row_old = p_ptr->panel_row;
9022 	p_ptr->panel_col_old = p_ptr->panel_col;
9023 #endif
9024 
9025 	panel_bounds(Ind);
9026 
9027 	tradpanel_calculate(Ind);
9028 }
9029 /* for functions of fixed size of effect that therefore require the
9030    'traditional' panel dimensions, such as Magic Mapping: */
9031 void tradpanel_calculate(Ind) {
9032 	player_type *p_ptr = Players[Ind];
9033 
9034 	p_ptr->tradpanel_row = ((p_ptr->py - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9035 	if (p_ptr->tradpanel_row > p_ptr->max_tradpanel_rows) p_ptr->tradpanel_row = p_ptr->max_tradpanel_rows;
9036 	else if (p_ptr->tradpanel_row < 0) p_ptr->tradpanel_row = 0;
9037 
9038 	p_ptr->tradpanel_col = ((p_ptr->px - SCREEN_WID / 4) / (SCREEN_WID / 2));
9039 	if (p_ptr->tradpanel_col > p_ptr->max_tradpanel_cols) p_ptr->tradpanel_col = p_ptr->max_tradpanel_cols;
9040 	else if (p_ptr->tradpanel_col < 0) p_ptr->tradpanel_col = 0;
9041 
9042 #ifdef ALERT_OFFPANEL_DAM
9043 	/* For alert-beeps on damage: Reset remembered panel */
9044 	p_ptr->panel_row_old = p_ptr->panel_row;
9045 	p_ptr->panel_col_old = p_ptr->panel_col;
9046 #endif
9047 
9048 	tradpanel_bounds(Ind);
9049 }
9050 
9051 /*
9052  * Calculates current boundaries
9053  * Called below and from "do_cmd_locate()".
9054  */
9055 void panel_bounds(int Ind)
9056 {
9057 	player_type *p_ptr = Players[Ind];
9058 
9059 	p_ptr->panel_row_min = p_ptr->panel_row * (p_ptr->screen_hgt / 2);
9060 	p_ptr->panel_row_max = p_ptr->panel_row_min + p_ptr->screen_hgt - 1;
9061 	p_ptr->panel_row_prt = p_ptr->panel_row_min - SCREEN_PAD_TOP;
9062 	p_ptr->panel_col_min = p_ptr->panel_col * (p_ptr->screen_wid / 2);
9063 	p_ptr->panel_col_max = p_ptr->panel_col_min + p_ptr->screen_wid - 1;
9064 	p_ptr->panel_col_prt = p_ptr->panel_col_min - SCREEN_PAD_LEFT;
9065 }
9066 void tradpanel_bounds(int Ind)
9067 {
9068 	player_type *p_ptr = Players[Ind];
9069 
9070 	/* for stuff such as magic mapping that relies on traditional panel size */
9071 	p_ptr->tradpanel_row_min = p_ptr->tradpanel_row * (SCREEN_HGT / 2);
9072 	p_ptr->tradpanel_row_max = p_ptr->tradpanel_row_min + SCREEN_HGT - 1;
9073 	p_ptr->tradpanel_col_min = p_ptr->tradpanel_col * (SCREEN_WID / 2);
9074 	p_ptr->tradpanel_col_max = p_ptr->tradpanel_col_min + SCREEN_WID - 1;
9075 }
9076 
9077 
9078 
9079 /*
9080  * Given an row (y) and col (x), this routine detects when a move
9081  * off the screen has occurred and figures new borders. -RAK-
9082  *
9083  * "Update" forces a "full update" to take place.
9084  *
9085  * The map is reprinted if necessary, and "TRUE" is returned.
9086  */
9087 void verify_panel(int Ind)
9088 {
9089 	player_type *p_ptr = Players[Ind];
9090 
9091 	int y = p_ptr->py;
9092 	int x = p_ptr->px;
9093 
9094 	int prow = p_ptr->panel_row;
9095 	int pcol = p_ptr->panel_col;
9096 
9097 
9098 	/* Also update (virtual) traditional panel */
9099 	verify_tradpanel(Ind);
9100 
9101 
9102 	/* Scroll screen when 2 grids from top/bottom edge */
9103 	if ((y < p_ptr->panel_row_min + SCROLL_MARGIN_ROW) || (y > p_ptr->panel_row_max - SCROLL_MARGIN_ROW)) {
9104 		prow = ((y - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9105 		if (prow > p_ptr->max_panel_rows) prow = p_ptr->max_panel_rows;
9106 		else if (prow < 0) prow = 0;
9107 	}
9108 
9109 	/* Scroll screen when 4 grids from left/right edge */
9110 	if ((x < p_ptr->panel_col_min + SCROLL_MARGIN_COL) || (x > p_ptr->panel_col_max - SCROLL_MARGIN_COL)) {
9111 		pcol = ((x - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9112 		if (pcol > p_ptr->max_panel_cols) pcol = p_ptr->max_panel_cols;
9113 		else if (pcol < 0) pcol = 0;
9114 	}
9115 
9116 	/* Check for "no change" */
9117 	if ((prow == p_ptr->panel_row) && (pcol == p_ptr->panel_col)) return;
9118 
9119 	/* Hack -- optional disturb on "panel change" */
9120 	if (p_ptr->disturb_panel) disturb(Ind, 0, 0);
9121 
9122 	/* Save the new panel info */
9123 	p_ptr->panel_row = prow;
9124 	p_ptr->panel_col = pcol;
9125 
9126 	/* Recalculate the boundaries */
9127 	panel_bounds(Ind);
9128 
9129 #ifdef ALERT_OFFPANEL_DAM
9130 	/* For alert-beeps on damage: Reset remembered panel */
9131 	p_ptr->panel_row_old = p_ptr->panel_row;
9132 	p_ptr->panel_col_old = p_ptr->panel_col;
9133 #endif
9134 
9135 	/* client-side weather stuff */
9136 	p_ptr->panel_changed = TRUE;
9137 
9138 	/* Update stuff */
9139 	p_ptr->update |= (PU_MONSTERS);
9140 
9141 	/* Redraw map */
9142 	p_ptr->redraw |= (PR_MAP);
9143 
9144 	/* Window stuff */
9145 	p_ptr->window |= (PW_OVERHEAD);
9146 }
9147 void verify_tradpanel(int Ind)
9148 {
9149 	player_type *p_ptr = Players[Ind];
9150 
9151 	int y = p_ptr->py;
9152 	int x = p_ptr->px;
9153 
9154 	int prow = p_ptr->tradpanel_row;
9155 	int pcol = p_ptr->tradpanel_col;
9156 
9157 	/* Scroll screen when 2 grids from top/bottom edge */
9158 	if ((y < p_ptr->tradpanel_row_min + TRAD_SCROLL_MARGIN_ROW) || (y > p_ptr->tradpanel_row_max - TRAD_SCROLL_MARGIN_ROW)) {
9159 		prow = ((y - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9160 		if (prow > p_ptr->max_tradpanel_rows) prow = p_ptr->max_tradpanel_rows;
9161 		else if (prow < 0) prow = 0;
9162 	}
9163 
9164 	/* Scroll screen when 4 grids from left/right edge */
9165 	if ((x < p_ptr->tradpanel_col_min + TRAD_SCROLL_MARGIN_COL) || (x > p_ptr->tradpanel_col_max - TRAD_SCROLL_MARGIN_COL)) {
9166 		pcol = ((x - SCREEN_WID / 4) / (SCREEN_WID / 2));
9167 		if (pcol > p_ptr->max_tradpanel_cols) pcol = p_ptr->max_tradpanel_cols;
9168 		else if (pcol < 0) pcol = 0;
9169 	}
9170 
9171 	/* Check for "no change" */
9172 	if ((prow == p_ptr->tradpanel_row) && (pcol == p_ptr->tradpanel_col)) return;
9173 
9174 #if 0 /* only in 'real' verify_panel() */
9175 	/* Hack -- optional disturb on "panel change" */
9176 	if (p_ptr->disturb_panel) disturb(Ind, 0, 0);
9177 #endif
9178 
9179 	/* Save the new panel info */
9180 	p_ptr->tradpanel_row = prow;
9181 	p_ptr->tradpanel_col = pcol;
9182 
9183 	/* Recalculate the boundaries */
9184 	tradpanel_bounds(Ind);
9185 
9186 #if 0 /* only in 'real' verify_panel() */
9187 	/* client-side weather stuff */
9188 	p_ptr->panel_changed = TRUE;
9189 
9190 	/* Update stuff */
9191 	p_ptr->update |= (PU_MONSTERS);
9192 
9193 	/* Redraw map */
9194 	p_ptr->redraw |= (PR_MAP);
9195 
9196 	/* Window stuff */
9197 	p_ptr->window |= (PW_OVERHEAD);
9198 #endif
9199 }
9200 
9201 /* Test whether the player is currently looking at his local surroundings (default)
9202    as opposed to some far off panel (done by cmd_locate()).
9203    Purpose: Prevent detection magic from working on remote areas. */
9204 bool local_panel(int Ind) {
9205 	player_type *p_ptr = Players[Ind];
9206 
9207 	int y = p_ptr->py;
9208 	int x = p_ptr->px;
9209 
9210 	int prow = p_ptr->panel_row;
9211 	int pcol = p_ptr->panel_col;
9212 
9213 
9214 #if 0
9215 	/* Also check (virtual) traditional panel */
9216 	if (!local_tradpanel(Ind)) return FALSE;
9217 #endif
9218 
9219 
9220 	/* Scroll screen when 2 grids from top/bottom edge */
9221 	if ((y < p_ptr->panel_row_min + SCROLL_MARGIN_ROW) || (y > p_ptr->panel_row_max - SCROLL_MARGIN_ROW)) {
9222 		prow = ((y - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9223 		if (prow > p_ptr->max_panel_rows) prow = p_ptr->max_panel_rows;
9224 		else if (prow < 0) prow = 0;
9225 	}
9226 
9227 	/* Scroll screen when 4 grids from left/right edge */
9228 	if ((x < p_ptr->panel_col_min + SCROLL_MARGIN_COL) || (x > p_ptr->panel_col_max - SCROLL_MARGIN_COL)) {
9229 		pcol = ((x - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9230 		if (pcol > p_ptr->max_panel_cols) pcol = p_ptr->max_panel_cols;
9231 		else if (pcol < 0) pcol = 0;
9232 	}
9233 
9234 	/* Check for "no change" */
9235 	if ((prow == p_ptr->panel_row) && (pcol == p_ptr->panel_col)) return TRUE;
9236 	return FALSE;
9237 }
9238 #if 0
9239 bool local_tradpanel(int Ind) {
9240 	player_type *p_ptr = Players[Ind];
9241 
9242 	int y = p_ptr->py;
9243 	int x = p_ptr->px;
9244 
9245 	int prow = p_ptr->tradpanel_row;
9246 	int pcol = p_ptr->tradpanel_col;
9247 
9248 	/* Scroll screen when 2 grids from top/bottom edge */
9249 	if ((y < p_ptr->tradpanel_row_min + TRAD_SCROLL_MARGIN_ROW) || (y > p_ptr->tradpanel_row_max - TRAD_SCROLL_MARGIN_ROW)) {
9250 		prow = ((y - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9251 		if (prow > p_ptr->max_tradpanel_rows) prow = p_ptr->max_tradpanel_rows;
9252 		else if (prow < 0) prow = 0;
9253 	}
9254 
9255 	/* Scroll screen when 4 grids from left/right edge */
9256 	if ((x < p_ptr->tradpanel_col_min + TRAD_SCROLL_MARGIN_COL) || (x > p_ptr->tradpanel_col_max - TRAD_SCROLL_MARGIN_COL)) {
9257 		pcol = ((x - SCREEN_WID / 4) / (SCREEN_WID / 2));
9258 		if (pcol > p_ptr->max_tradpanel_cols) pcol = p_ptr->max_tradpanel_cols;
9259 		else if (pcol < 0) pcol = 0;
9260 	}
9261 
9262 	/* Check for "no change" */
9263 	if ((prow == p_ptr->tradpanel_row) && (pcol == p_ptr->tradpanel_col)) return TRUE;
9264 	return FALSE;
9265 }
9266 #endif
9267 
9268 
9269 /*
9270  * Monster health description
9271  */
9272 cptr look_mon_desc(int m_idx)
9273 {
9274 	monster_type *m_ptr = &m_list[m_idx];
9275 	monster_race *r_ptr = race_inf(m_ptr);
9276 
9277 	bool          living = TRUE;
9278 	int           perc;
9279 
9280 
9281 	/* Determine if the monster is "living" (vs "undead") */
9282 	if (r_ptr->flags3 & RF3_UNDEAD) living = FALSE;
9283 	if (r_ptr->flags3 & RF3_DEMON) living = FALSE;
9284 	if (strchr("Egv", r_ptr->d_char)) living = FALSE;
9285 
9286 
9287 	/* Healthy monsters */
9288 	if (m_ptr->hp >= m_ptr->maxhp) {
9289 		/* asleep even? */
9290 		if (m_ptr->csleep) return("asleep");
9291 		/* albeit stunned? */
9292 		if (m_ptr->stunned > 100) return("knocked out");
9293 		if (m_ptr->stunned > 50) return("heavily dazed");
9294 		if (m_ptr->stunned) return("dazed");
9295 		/* No damage (and no other effect either) */
9296 		return (living ? "unhurt" : "undamaged");
9297 	}
9298 
9299 
9300 	/* prevent crash bug that happened in line 8237 (mon_take_hit),
9301 	   apparently maxhp can extremely rarely be 0 - C. Blue */
9302 	if (m_ptr->maxhp == 0) {
9303 		s_printf("DBG_MAXHP_3 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
9304 		return "awake"; /* some excuse string ;) */
9305 	}
9306 
9307 	/* Calculate a health "percentage" */
9308 	perc = 100L * m_ptr->hp / m_ptr->maxhp;
9309 
9310 	if (perc >= 60)
9311 		return (living ? "somewhat wounded" : "somewhat damaged");
9312 
9313 	if (perc >= 25)
9314 		return (living ? "wounded" : "damaged");
9315 
9316 	if (perc >= 10)
9317 		return (living ? "badly wounded" : "badly damaged");
9318 
9319 	return (living ? "almost dead" : "almost destroyed");
9320 }
9321 
9322 
9323 
9324 /*
9325  * Angband sorting algorithm -- quick sort in place
9326  *
9327  * Note that the details of the data we are sorting is hidden,
9328  * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
9329  * function hooks to interact with the data, which is given as
9330  * two pointers, and which may have any user-defined form.
9331  */
9332 void ang_sort_aux(int Ind, vptr u, vptr v, int p, int q)
9333 {
9334 	int z, a, b;
9335 
9336 	/* Done sort */
9337 	if (p >= q) return;
9338 
9339 	/* Pivot */
9340 	z = p;
9341 
9342 	/* Begin */
9343 	a = p;
9344 	b = q;
9345 
9346 	/* Partition */
9347 	while (TRUE) {
9348 		/* Slide i2 */
9349 		while (!(*ang_sort_comp)(Ind, u, v, b, z)) b--;
9350 
9351 		/* Slide i1 */
9352 		while (!(*ang_sort_comp)(Ind, u, v, z, a)) a++;
9353 
9354 		/* Done partition */
9355 		if (a >= b) break;
9356 
9357 		/* Swap */
9358 		(*ang_sort_swap)(Ind, u, v, a, b);
9359 
9360 		/* Advance */
9361 		a++, b--;
9362 	}
9363 
9364 	/* Recurse left side */
9365 	ang_sort_aux(Ind, u, v, p, b);
9366 
9367 	/* Recurse right side */
9368 	ang_sort_aux(Ind, u, v, b+1, q);
9369 }
9370 
9371 void ang_sort_extra_aux(int Ind, vptr u, vptr v, vptr w, int p, int q)
9372 {
9373 	int z, a, b;
9374 
9375 	/* Done sort */
9376 	if (p >= q) return;
9377 
9378 	/* Pivot */
9379 	z = p;
9380 
9381 	/* Begin */
9382 	a = p;
9383 	b = q;
9384 
9385 	/* Partition */
9386 	while (TRUE) {
9387 		/* Slide i2 */
9388 		while (!(*ang_sort_extra_comp)(Ind, u, v, w, b, z)) b--;
9389 
9390 		/* Slide i1 */
9391 		while (!(*ang_sort_extra_comp)(Ind, u, v, w, z, a)) a++;
9392 
9393 		/* Done partition */
9394 		if (a >= b) break;
9395 
9396 		/* Swap */
9397 		(*ang_sort_extra_swap)(Ind, u, v, w, a, b);
9398 
9399 		/* Advance */
9400 		a++, b--;
9401 	}
9402 
9403 	/* Recurse left side */
9404 	ang_sort_extra_aux(Ind, u, v, w, p, b);
9405 
9406 	/* Recurse right side */
9407 	ang_sort_extra_aux(Ind, u, v, w, b+1, q);
9408 }
9409 
9410 
9411 /*
9412  * Angband sorting algorithm -- quick sort in place
9413  *
9414  * Note that the details of the data we are sorting is hidden,
9415  * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
9416  * function hooks to interact with the data, which is given as
9417  * two pointers, and which may have any user-defined form.
9418  */
9419 void ang_sort(int Ind, vptr u, vptr v, int n)
9420 {
9421 	/* Sort the array */
9422 	ang_sort_aux(Ind, u, v, 0, n-1);
9423 }
9424 
9425 /* Added this for further sorting the all monsters that are *closest* to
9426    the player by their sleep state: Target awake monsters first, before
9427    waking up sleeping ones. Suggested by Caine/Ifrit - C. Blue */
9428 void ang_sort_extra(int Ind, vptr u, vptr v, vptr w, int n)
9429 {
9430 	/* Sort the array */
9431 	ang_sort_extra_aux(Ind, u, v, w, 0, n-1);
9432 }
9433 
9434 /* returns our max times 100 divided by our current...*/
9435 static int player_wounded(s16b ind)
9436 {
9437 	player_type *p_ptr = Players[ind];
9438 	int wounded = (p_ptr->mhp * 100) / p_ptr->chp;
9439 
9440 	/* allow targetting healed up players that suffer from status ailments
9441 	   curable by Cure Wounds spell - C. Blue */
9442 	if (wounded == 100 &&
9443 	    (p_ptr->cut || p_ptr->blind || p_ptr->confused || p_ptr->stun))
9444 		wounded = 101;
9445 
9446 	return wounded;
9447 }
9448 
9449 /* this should probably be somewhere more logical, but I should probably be
9450 sleeping right now.....
9451 Selects the most wounded target.
9452 
9453 Hmm, I am sure there are faster sort algorithms out there... oh well, I don't
9454 think it really matters... this one goes out to you Mr. Munroe.
9455 -ADA-
9456 */
9457 
9458 static void wounded_player_target_sort(int Ind, vptr sx, vptr sy, vptr id, int n)
9459 {
9460 	int c,num;
9461 	s16b swp;
9462 	s16b * idx = (s16b *) id;
9463 	byte * x = (byte *) sx;
9464 	byte * y = (byte *) sy;
9465 	byte swpb;
9466 
9467 	/* num equals our max index */
9468 	num = n-1;
9469 
9470 	while (num > 0) {
9471 		for (c = 0; c < num; c++) {
9472 			if (player_wounded(idx[c+1]) > player_wounded(idx[c])) {
9473 				swp = idx[c];
9474 				idx[c] = idx[c+1];
9475 				idx[c+1] = swp;
9476 
9477 				swpb = x[c];
9478 				x[c] = x[c+1];
9479 				x[c+1] = swpb;
9480 
9481 				swpb = y[c];
9482 				y[c] = y[c+1];
9483 				y[c+1] = swpb;
9484 			}
9485 		}
9486 	num--;
9487 	}
9488 }
9489 
9490 
9491 
9492 /*
9493  * Sorting hook -- comp function -- by "distance to player"
9494  *
9495  * We use "u" and "v" to point to arrays of "x" and "y" positions,
9496  * and sort the arrays by double-distance to the player.
9497  */
9498 bool ang_sort_comp_distance(int Ind, vptr u, vptr v, int a, int b)
9499 {
9500 	player_type *p_ptr = Players[Ind];
9501 
9502 	byte *x = (byte*)(u);
9503 	byte *y = (byte*)(v);
9504 
9505 	int da, db, kx, ky;
9506 
9507 	/* Absolute distance components */
9508 	kx = x[a]; kx -= p_ptr->px; kx = ABS(kx);
9509 	ky = y[a]; ky -= p_ptr->py; ky = ABS(ky);
9510 
9511 	/* Approximate Double Distance to the first point */
9512 	da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9513 
9514 	/* Absolute distance components */
9515 	kx = x[b]; kx -= p_ptr->px; kx = ABS(kx);
9516 	ky = y[b]; ky -= p_ptr->py; ky = ABS(ky);
9517 
9518 	/* Approximate Double Distance to the first point */
9519 	db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9520 
9521 	/* Compare the distances */
9522 	return (da <= db);
9523 }
9524 
9525 
9526 /*
9527  * Sorting hook -- swap function -- by "distance to player"
9528  *
9529  * We use "u" and "v" to point to arrays of "x" and "y" positions,
9530  * and sort the arrays by distance to the player.
9531  */
9532 void ang_sort_swap_distance(int Ind, vptr u, vptr v, int a, int b)
9533 {
9534 	byte *x = (byte*)(u);
9535 	byte *y = (byte*)(v);
9536 
9537 	byte temp;
9538 
9539 	/* Swap "x" */
9540 	temp = x[a];
9541 	x[a] = x[b];
9542 	x[b] = temp;
9543 
9544 	/* Swap "y" */
9545 	temp = y[a];
9546 	y[a] = y[b];
9547 	y[b] = temp;
9548 }
9549 
9550 
9551 bool ang_sort_extra_comp_distance(int Ind, vptr u, vptr v, vptr w, int a, int b)
9552 {
9553 	player_type *p_ptr = Players[Ind];
9554 
9555 	byte *x = (byte*)(u);
9556 	byte *y = (byte*)(v);
9557 	byte *z = (byte*)(w);
9558 
9559 	int da, db, kx, ky;
9560 
9561 	/* Absolute distance components */
9562 	kx = x[a]; kx -= p_ptr->px; kx = ABS(kx);
9563 	ky = y[a]; ky -= p_ptr->py; ky = ABS(ky);
9564 
9565 	/* Approximate Double Distance to the first point */
9566 	da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9567 
9568 	/* Absolute distance components */
9569 	kx = x[b]; kx -= p_ptr->px; kx = ABS(kx);
9570 	ky = y[b]; ky -= p_ptr->py; ky = ABS(ky);
9571 
9572 	/* Approximate Double Distance to the first point */
9573 	db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9574 
9575 	/* Compare the distances -- if equal, prefer the target that is not asleep, default to 'a'. */
9576 	return ((da == db) ? (z[b] || !z[a]) : (da <= db));
9577 }
9578 
9579 void ang_sort_extra_swap_distance(int Ind, vptr u, vptr v, vptr w, int a, int b)
9580 {
9581 	byte *x = (byte*)(u);
9582 	byte *y = (byte*)(v);
9583 	byte *z = (byte*)(w);
9584 
9585 	byte temp;
9586 
9587 	/* Swap "x" */
9588 	temp = x[a];
9589 	x[a] = x[b];
9590 	x[b] = temp;
9591 
9592 	/* Swap "y" */
9593 	temp = y[a];
9594 	y[a] = y[b];
9595 	y[b] = temp;
9596 
9597 	/* Swap "z" */
9598 	temp = z[a];
9599 	z[a] = z[b];
9600 	z[b] = temp;
9601 }
9602 
9603 
9604 
9605 /*
9606  * Compare the values of two objects.
9607  *
9608  * Pointer "v" should not point to anything (it isn't used, anyway).
9609  */
9610 bool ang_sort_comp_value(int Ind, vptr u, vptr v, int a, int b)
9611 {
9612 	object_type *inven = (object_type *)u;
9613 	s64b va, vb;
9614 
9615 	if (inven[a].tval && inven[b].tval) {
9616 		va = object_value(Ind, &inven[a]);
9617 		vb = object_value(Ind, &inven[b]);
9618 
9619 		return (va >= vb);
9620 	}
9621 
9622 	if (inven[a].tval) return FALSE;
9623 	return TRUE;
9624 }
9625 
9626 
9627 void ang_sort_swap_value(int Ind, vptr u, vptr v, int a, int b)
9628 {
9629 	object_type *x = (object_type *)u;
9630 	object_type temp;
9631 
9632 	temp = x[a];
9633 	x[a] = x[b];
9634 	x[b] = temp;
9635 }
9636 
9637 
9638 /*
9639  * Sort a list of r_idx by level(depth).	- Jir -
9640  *
9641  * Pointer "v" should not point to anything (it isn't used, anyway).
9642  */
9643 bool ang_sort_comp_mon_lev(int Ind, vptr u, vptr v, int a, int b)
9644 {
9645 	s16b *r_idx = (s16b*)u;
9646 	s32b va, vb;
9647 	monster_race *ra_ptr = &r_info[r_idx[a]];
9648 	monster_race *rb_ptr = &r_info[r_idx[b]];
9649 
9650 	if (ra_ptr->name && rb_ptr->name) {
9651 		va = ra_ptr->level * 3000 + r_idx[a];
9652 		vb = rb_ptr->level * 3000 + r_idx[b];
9653 
9654 		return (va >= vb);
9655 	}
9656 
9657 	if (ra_ptr->name) return FALSE;
9658 	return TRUE;
9659 }
9660 
9661 
9662 /* namely. */
9663 void ang_sort_swap_s16b(int Ind, vptr u, vptr v, int a, int b)
9664 {
9665 	s16b *x = (s16b*)u;
9666 	s16b temp;
9667 
9668 	temp = x[a];
9669 	x[a] = x[b];
9670 	x[b] = temp;
9671 }
9672 
9673 /*
9674  * Sort a list of k_idx by tval and sval.	- Jir -
9675  *
9676  * Pointer "v" should not point to anything (it isn't used, anyway).
9677  */
9678 bool ang_sort_comp_tval(int Ind, vptr u, vptr v, int a, int b)
9679 {
9680 	s16b *k_idx = (s16b*)u;
9681 	s32b va, vb;
9682 	object_kind *ka_ptr = &k_info[k_idx[a]];
9683 	object_kind *kb_ptr = &k_info[k_idx[b]];
9684 
9685 	if (ka_ptr->tval && kb_ptr->tval) {
9686 		va = ka_ptr->tval * 256 + ka_ptr->sval;
9687 		vb = kb_ptr->tval * 256 + kb_ptr->sval;
9688 
9689 		return (va >= vb);
9690 	}
9691 
9692 	if (ka_ptr->tval) return FALSE;
9693 	return TRUE;
9694 }
9695 
9696 
9697 
9698 /*** Targetting Code ***/
9699 
9700 
9701 /*
9702  * Determine is a monster makes a reasonable target
9703  *
9704  * The concept of "targetting" was stolen from "Morgul" (?)
9705  *
9706  * The player can target any location, or any "target-able" monster.
9707  *
9708  * Currently, a monster is "target_able" if it is visible, and if
9709  * the player can hit it with a projection, and the player is not
9710  * hallucinating.  This allows use of "use closest target" macros.
9711  *
9712  * Future versions may restrict the ability to target "trappers"
9713  * and "mimics", but the semantics is a little bit weird.
9714  */
9715 /* Allow auto-retaliation to not get 'disabled' by a Sparrow next to the player?
9716    Also see EXPENSIVE_NO_TARGET_TEST. */
9717 //#define CHEAP_NO_TARGET_TEST
9718 bool target_able(int Ind, int m_idx)
9719 {
9720 	player_type *p_ptr = Players[Ind], *q_ptr;
9721 	monster_type *m_ptr;
9722 
9723 	if (!p_ptr) return FALSE;
9724 
9725 	/* Hack -- no targeting hallucinations */
9726 	if (p_ptr->image) return (FALSE);
9727 
9728 	/* Check for OK monster */
9729 	if (m_idx > 0) {
9730 		monster_race *r_ptr;
9731 
9732 		/* Acquire pointer */
9733 		m_ptr = &m_list[m_idx];
9734 		r_ptr = race_inf(m_ptr);
9735 
9736 		/* Monster must be visible */
9737 		if (!p_ptr->mon_vis[m_idx]) return (FALSE);
9738 
9739 		/* Monster must not be owned */
9740 		if (p_ptr->id == m_ptr->owner) return (FALSE);
9741 
9742 		/* Distance to target too great?
9743 		   Use distance() to form a 'natural' circle shaped radius instead of a square shaped radius,
9744 		   monsters do this too */
9745 		if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) > MAX_RANGE) return (FALSE);
9746 
9747 		/* Monster must be projectable */
9748 #ifdef PY_PROJ_WALL
9749 		if (!projectable_wall(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE)) return (FALSE);
9750 #else
9751 		if (!projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE)) return (FALSE);
9752 #endif
9753 
9754 		if(m_ptr->owner == p_ptr->id) return(FALSE);
9755 
9756 		/* XXX XXX XXX Hack -- Never target trappers */
9757 		/* if (CLEAR_ATTR && CLEAR_CHAR) return (FALSE); */
9758 
9759 		/* Cannot be targeted */
9760 #ifdef CHEAP_NO_TARGET_TEST
9761 		/* Allow targetting if it's next to player? */
9762 		if (!(ABS(p_ptr->px - m_ptr->fx) <= 1 && ABS(p_ptr->py - m_ptr->fy) <= 1))
9763 #endif
9764 		if (r_ptr->flags7 & RF7_NO_TARGET) return (FALSE);
9765 
9766 		/* Assume okay */
9767 		return (TRUE);
9768 	}
9769 
9770 	/* Check for OK player */
9771 	if (m_idx < 0) {
9772 		/* Don't target oneself */
9773 		if (Ind == 0 - m_idx) return(FALSE);
9774 
9775 		/* Acquire pointer */
9776 		q_ptr = Players[0 - m_idx];
9777 
9778 		if ((0 - m_idx) > NumPlayers) q_ptr = NULL;
9779 
9780 		/* Paranoia check -- require a valid player */
9781 		if (!q_ptr || q_ptr->conn == NOT_CONNECTED){
9782 			p_ptr->target_who = 0;
9783 			return (FALSE);
9784 		}
9785 
9786 		/* Players must be on same depth */
9787 		if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) return (FALSE);
9788 
9789 		/* Player must be visible */
9790 		if (!p_ptr->play_vis[-m_idx]) return (FALSE);
9791 
9792 		/* Player must be in FoV */
9793 		if (!player_can_see_bold(Ind, q_ptr->py, q_ptr->px)) return (FALSE);
9794 
9795 		/* Distance to target too great?
9796 		   Use distance() to form a 'natural' circle shaped radius instead of a square shaped radius,
9797 		   monsters do this too */
9798 		if (distance(p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px) > MAX_RANGE) return (FALSE);
9799 
9800 		/* Player must be projectable */
9801 #ifdef PY_PROJ_WALL
9802 		if (!projectable_wall(&p_ptr->wpos, p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px, MAX_RANGE)) return (FALSE);
9803 #else
9804 		if (!projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px, MAX_RANGE)) return (FALSE);
9805 #endif
9806 
9807 		/* Assume okay */
9808 		return (TRUE);
9809 	}
9810 
9811 	/* Assume no target */
9812 	return (FALSE);
9813 }
9814 
9815 
9816 
9817 
9818 /*
9819  * Update (if necessary) and verify (if possible) the target.
9820  *
9821  * We return TRUE if the target is "okay" and FALSE otherwise.
9822  */
9823 bool target_okay(int Ind)
9824 {
9825 	player_type *p_ptr = Players[Ind];
9826 
9827 	/* Accept stationary targets */
9828 //	if (p_ptr->target_who > MAX_M_IDX) return (TRUE);
9829 	if (p_ptr->target_who < 0 - MAX_PLAYERS) return (TRUE);
9830 
9831 	/* Check moving monsters */
9832 	if (p_ptr->target_who > 0) {
9833 		/* Accept reasonable targets */
9834 		if (target_able(Ind, p_ptr->target_who)) {
9835 			monster_type *m_ptr = &m_list[p_ptr->target_who];
9836 
9837 			/* Acquire monster location */
9838 			p_ptr->target_row = m_ptr->fy;
9839 			p_ptr->target_col = m_ptr->fx;
9840 
9841 			/* Good target */
9842 			return (TRUE);
9843 		}
9844 	}
9845 
9846 	/* Check moving players */
9847 	if (p_ptr->target_who < 0) {
9848 		/* Accept reasonable targets */
9849 		if (target_able(Ind, p_ptr->target_who)) {
9850 			player_type *q_ptr = Players[0 - p_ptr->target_who];
9851 
9852 			/* Acquire player location */
9853 			p_ptr->target_row = q_ptr->py;
9854 			p_ptr->target_col = q_ptr->px;
9855 
9856 			/* Good target */
9857 			return (TRUE);
9858 		}
9859 	}
9860 
9861 	/* Assume no target */
9862 	return (FALSE);
9863 }
9864 
9865 
9866 
9867 /*
9868  * Hack -- help "select" a location (see below)
9869  */
9870 s16b target_pick(int Ind, int y1, int x1, int dy, int dx)
9871 {
9872 	player_type *p_ptr = Players[Ind];
9873 	int i, v;
9874 	int x2, y2, x3, y3, x4, y4;
9875 	int b_i = -1, b_v = 9999;
9876 
9877 	/* Scan the locations */
9878 	for (i = 0; i < p_ptr->target_n; i++) {
9879 		/* Point 2 */
9880 		x2 = p_ptr->target_x[i];
9881 		y2 = p_ptr->target_y[i];
9882 
9883 		/* Directed distance */
9884 		x3 = (x2 - x1);
9885 		y3 = (y2 - y1);
9886 
9887 		/* Verify quadrant */
9888 		if (dx && (x3 * dx <= 0)) continue;
9889 		if (dy && (y3 * dy <= 0)) continue;
9890 
9891 		/* Absolute distance */
9892 		x4 = ABS(x3);
9893 		y4 = ABS(y3);
9894 
9895 		/* Verify quadrant */
9896 		if (dy && !dx && (x4 > y4)) continue;
9897 		if (dx && !dy && (y4 > x4)) continue;
9898 
9899 		/* Approximate Double Distance */
9900 		v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
9901 
9902 		/* XXX XXX XXX Penalize location */
9903 
9904 		/* Track best */
9905 		if ((b_i >= 0) && (v >= b_v)) continue;
9906 
9907 		/* Track best */
9908 		b_i = i; b_v = v;
9909 	}
9910 
9911 	/* Result */
9912 	return (b_i);
9913 }
9914 
9915 
9916 /*
9917  * Set a new target.  This code can be called from "get_aim_dir()"
9918  *
9919  * The target must be on the current panel.  Consider the use of
9920  * "panel_bounds()" to allow "off-panel" targets, perhaps by using
9921  * some form of "scrolling" the map around the cursor.  XXX XXX XXX
9922  *
9923  * That is, consider the possibility of "auto-scrolling" the screen
9924  * while the cursor moves around.  This may require changes in the
9925  * "update_mon()" code to allow "visibility" even if off panel.
9926  *
9927  * Hack -- targetting an "outer border grid" may be dangerous,
9928  * so this is not currently allowed.
9929  *
9930  * You can now use the direction keys to move among legal monsters,
9931  * just like the new "look" function allows the use of direction
9932  * keys to move amongst interesting locations.
9933  */
9934 static bool autotarget = FALSE;
9935 bool target_set(int Ind, int dir)
9936 {
9937 	player_type *p_ptr = Players[Ind], *q_ptr;
9938 	struct worldpos *wpos = &p_ptr->wpos;
9939 	int		i, m, idx;
9940 	int		y;
9941 	int		x;
9942 //	bool	flag = TRUE;
9943 	bool	flag = autotarget;
9944 	char	out_val[160];
9945 	cave_type		*c_ptr;
9946 	monster_type	*m_ptr;
9947 	cave_type **zcave;
9948 	if (!(zcave = getcave(wpos))) return(FALSE);
9949 
9950 
9951 	if (!dir) {
9952 		x = p_ptr->px;
9953 		y = p_ptr->py;
9954 
9955 		/* Go ahead and turn off target mode */
9956 		p_ptr->target_who = 0;
9957 
9958 		/* Turn off health tracking */
9959 		health_track(Ind, 0);
9960 
9961 
9962 		/* Reset "target" array */
9963 		p_ptr->target_n = 0;
9964 
9965 		/* Collect "target-able" monsters */
9966 		for (i = 1; i < m_max; i++) {
9967 			monster_type *m_ptr = &m_list[i];
9968 
9969 			/* Skip "dead" monsters */
9970 			if (!m_ptr->r_idx) continue;
9971 
9972 			/* Skip monsters not on this depth */
9973 			if (!inarea(&m_ptr->wpos, wpos)) continue;
9974 
9975 			/* Ignore "unreasonable" monsters */
9976 			if (!target_able(Ind, i)) continue;
9977 
9978 			/* Save this monster index */
9979 			p_ptr->target_x[p_ptr->target_n] = m_ptr->fx;
9980 			p_ptr->target_y[p_ptr->target_n] = m_ptr->fy;
9981 			p_ptr->target_state[p_ptr->target_n] = m_ptr->csleep ? 1 : 0;
9982 			p_ptr->target_n++;
9983 		}
9984 
9985 		/* Collect "target-able" players */
9986 		for (i = 1; i <= NumPlayers; i++) {
9987 			/* Acquire pointer */
9988 			q_ptr = Players[i];
9989 
9990 			/* Don't target yourself */
9991 			if (i == Ind) continue;
9992 
9993 			/* Skip unconnected players */
9994 			if (q_ptr->conn == NOT_CONNECTED) continue;
9995 
9996 			/* Ignore players we aren't hostile to */
9997 			if (!check_hostile(Ind, i)) {
9998 					continue;
9999 			}
10000 			/* Ignore "unreasonable" players */
10001 			if (!target_able(Ind, 0 - i)) continue;
10002 
10003 			/* Save the player index */
10004 			p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10005 			p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10006 			p_ptr->target_state[p_ptr->target_n] = q_ptr->afk ? 1 : 0; /* AFK players count as 'asleep' ;) */
10007 			p_ptr->target_n++;
10008 		}
10009 
10010 		/* Set the sort hooks */
10011 		ang_sort_extra_comp = ang_sort_extra_comp_distance;
10012 		ang_sort_extra_swap = ang_sort_extra_swap_distance;
10013 
10014 		/* Sort the positions */
10015 		ang_sort_extra(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_state, p_ptr->target_n);
10016 
10017 		/* Collect indices */
10018 		for (i = 0; i < p_ptr->target_n; i++) {
10019 			c_ptr = &zcave[p_ptr->target_y[i]][p_ptr->target_x[i]];
10020 			p_ptr->target_idx[i] = c_ptr->m_idx;
10021 		}
10022 
10023 		/* Start near the player */
10024 		m = 0;
10025 	} else if (dir >= 128) {
10026 		/* Initialize if needed */
10027 		if (dir == 128) {
10028 			p_ptr->target_col = p_ptr->px;
10029 			p_ptr->target_row = p_ptr->py;
10030 		} else {
10031 			y = p_ptr->target_row + ddy[dir - 128];
10032 			x = p_ptr->target_col + ddx[dir - 128];
10033 			if (!in_bounds(y, x)) return FALSE; /* paranoia (won't harm, but seems weird) */
10034 			p_ptr->target_row = y;
10035 			p_ptr->target_col = x;
10036 		}
10037 
10038 		/* Info */
10039 		strcpy(out_val, "[<dir>, t, q] ");
10040 
10041 		/* Tell the client */
10042 		Send_target_info(Ind, p_ptr->target_col - p_ptr->panel_col_prt, p_ptr->target_row - p_ptr->panel_row_prt, out_val);
10043 
10044 		/* Check for completion */
10045 		if (dir == 128 + 5) {
10046 			p_ptr->target_who = MAX_M_IDX + 1;
10047 			return TRUE;
10048 		}
10049 
10050 		/* Done */
10051 		return FALSE;
10052 	} else {
10053 		/* Start where we last left off */
10054 		m = p_ptr->look_index;
10055 
10056 		/* Reset the locations */
10057 		for (i = 0; i < p_ptr->target_n; i++) {
10058 			if (p_ptr->target_idx[i] > 0) {
10059 				m_ptr = &m_list[p_ptr->target_idx[i]];
10060 
10061 				p_ptr->target_y[i] = m_ptr->fy;
10062 				p_ptr->target_x[i] = m_ptr->fx;
10063 			} else if (p_ptr->target_idx[i] < 0) {
10064 				q_ptr = Players[0 - p_ptr->target_idx[i]];
10065 
10066 				p_ptr->target_y[i] = q_ptr->py;
10067 				p_ptr->target_x[i] = q_ptr->px;
10068 			}
10069 		}
10070 
10071 		/* Find a new monster */
10072 		i = target_pick(Ind, p_ptr->target_y[m], p_ptr->target_x[m], ddy[dir], ddx[dir]);
10073 
10074 		/* Use that monster */
10075 		if (i > 0) {
10076 			m = i;
10077 
10078 #if 0 /* enable when this targetting method is fixed: */
10079     /* Currently you cannot select any available target, even though you can look at it,
10080 	probably a problem in target_pick(). */
10081     /* Also make 'l'ooking at a monster target it, probably. (p_ptr->look_index vs p_ptr->target_who) */
10082 			if (p_ptr->target_idx[i] > 0) {
10083 				m_ptr = &m_list[p_ptr->target_idx[i]];
10084 				snprintf(out_val, sizeof(out_val), "%s%s (Lv %d, %s%s)",
10085 				    ((r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) && p_ptr->r_killed[m_ptr->r_idx] == 1) ? "\377D" : "",
10086 				    r_name_get(&m_list[p_ptr->target_idx[m]]),
10087 				    m_ptr->level, look_mon_desc(p_ptr->target_idx[m]),
10088 				    m_ptr->clone ? ", clone" : "");
10089 			} else if (p_ptr->target_idx[i] < 0) {
10090 				q_ptr = Players[0 - p_ptr->target_idx[i]];
10091 				if (q_ptr->body_monster) {
10092 		                        snprintf(out_val, sizeof(out_val), "%s the %s (%s)", q_ptr->name, r_name + r_info[q_ptr->body_monster].name, get_ptitle(q_ptr, FALSE));
10093 		                } else {
10094 		                        snprintf(out_val, sizeof(out_val), "%s the %s %s", q_ptr->name, get_prace(q_ptr), get_ptitle(q_ptr, FALSE));
10095 				}
10096 			}
10097 //			strcpy(out_val, "[<dir>, t, q] ");
10098 			Send_target_info(Ind, p_ptr->target_x[m] - p_ptr->panel_col_prt, p_ptr->target_y[m] - p_ptr->panel_row_prt, out_val);
10099 #endif
10100 		}
10101 	}
10102 
10103 	/* Target monsters */
10104 	if (flag && p_ptr->target_n && p_ptr->target_idx[m] > 0) {
10105 		y = p_ptr->target_y[m];
10106 		x = p_ptr->target_x[m];
10107 		idx = p_ptr->target_idx[m];
10108 
10109 		m_ptr = &m_list[idx];
10110 
10111 		/* Hack -- Track that monster race */
10112 		recent_track(m_ptr->r_idx);
10113 
10114 		/* Hack -- Track that monster */
10115 		health_track(Ind, idx);
10116 
10117 		/* Hack -- handle stuff */
10118 		handle_stuff(Ind);
10119 
10120 		/* Describe, prompt for recall */
10121 		snprintf(out_val, sizeof(out_val),
10122 		    "%s{%d} (%s) [<dir>, q, t] ",
10123 		    r_name_get(m_ptr),
10124 		    m_ptr->level,
10125 		    look_mon_desc(idx));
10126 
10127 		/* Tell the client about it */
10128 		Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10129 	} else if (flag && p_ptr->target_n && p_ptr->target_idx[m] < 0) {
10130 		y = p_ptr->target_y[m];
10131 		x = p_ptr->target_x[m];
10132 		idx = p_ptr->target_idx[m];
10133 
10134 		q_ptr = Players[0 - idx];
10135 
10136 		/* Hack -- Track that player */
10137 		health_track(Ind, idx);
10138 
10139 		/* Hack -- handle stuff */
10140 		handle_stuff(Ind);
10141 
10142 		/* Describe */
10143 		snprintf(out_val, sizeof(out_val), "%s [<dir>, q, t] ", q_ptr->name);
10144 
10145 		/* Tell the client about it */
10146 		Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10147 	}
10148 
10149 	/* Remember current index */
10150 	p_ptr->look_index = m;
10151 
10152 	/* Set target */
10153 	if (dir == 5 || autotarget) {
10154 		p_ptr->target_who = p_ptr->target_idx[m];
10155 		p_ptr->target_col = p_ptr->target_x[m];
10156 		p_ptr->target_row = p_ptr->target_y[m];
10157 
10158 		/* Track */
10159 		if (p_ptr->target_who) health_track(Ind, p_ptr->target_who);
10160 	}
10161 
10162 	/* Failure */
10163 	if (!p_ptr->target_who) return (FALSE);
10164 
10165 	/* Clear target info */
10166 	p_ptr->target_n = 0;
10167 
10168 	/* Success */
10169 	return (TRUE);
10170 }
10171 
10172 
10173 #if 0 /* not functional atm, replaced by target-closest strategy */
10174 
10175 /* targets the most wounded teammate. should be useful for stuff like
10176  * heal other and teleport macros. -ADA-
10177  *
10178  * Now this function can take 3rd arg which specifies which player to
10179  * set the target.
10180  * This part was written by Asclep(DEG); thx for his courtesy!
10181  * */
10182 
10183 bool target_set_friendly(int Ind, int dir, ...)
10184 {
10185 	va_list ap;
10186 	player_type *p_ptr = Players[Ind], *q_ptr;
10187 	struct worldpos *wpos = &p_ptr->wpos;
10188 	cave_type **zcave;
10189 	int		i, m, castplayer, idx;
10190 	int		y;
10191 	int		x;
10192 	char	out_val[160];
10193 	cave_type	*c_ptr;
10194 
10195 	if (!(zcave = getcave(wpos))) return(FALSE);
10196 
10197 		va_start(ap,dir);
10198 		castplayer = va_arg(ap,int);
10199 		va_end(ap);
10200 
10201 		x = p_ptr->px;
10202 		y = p_ptr->py;
10203 
10204 		/* Go ahead and turn off target mode */
10205 		p_ptr->target_who = 0;
10206 
10207 		/* Turn off health tracking */
10208 		health_track(Ind, 0);
10209 
10210 
10211 		/* Reset "target" array */
10212 		p_ptr->target_n = 0;
10213 
10214 //		if (!((castplayer > 0) && (castplayer < 20)))
10215 		if (!((0 < castplayer) && (castplayer <= NumPlayers))) {
10216 			/* Collect "target-able" players */
10217 			for (i = 1; i <= NumPlayers; i++) {
10218 				/* Acquire pointer */
10219 				q_ptr = Players[i];
10220 
10221 				/* Don't target yourself */
10222 				if (i == Ind) continue;
10223 
10224 				/* Skip unconnected players */
10225 				if (q_ptr->conn == NOT_CONNECTED) continue;
10226 
10227 				/* Ignore players we aren't friends with */
10228 				if (check_hostile(Ind, i)) continue;
10229 
10230 				/* if we are in party, only help members */
10231 				if (p_ptr->party && (!player_in_party(p_ptr->party, i))) continue;
10232 
10233 				/* Ignore "unreasonable" players */
10234 				if (!target_able(Ind, 0 - i)) continue;
10235 
10236 				/* Save the player index */
10237 				p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10238 				p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10239 				p_ptr->target_idx[p_ptr->target_n] = i;
10240 				p_ptr->target_n++;
10241 			}
10242 		} else {
10243 			/* Acquire pointer */
10244 			q_ptr = Players[castplayer];
10245 
10246 			/* Skip unconnected players */
10247 			if (q_ptr->conn == NOT_CONNECTED) return FALSE;
10248 
10249 			/* Ignore "unreasonable" players */
10250 			if (!target_able(Ind, 0 - castplayer)) return FALSE;
10251 
10252 			/* Save the player index */
10253 			p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10254 			p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10255 			p_ptr->target_idx[p_ptr->target_n] = castplayer;
10256 			p_ptr->target_n++;
10257 		}
10258 
10259 
10260 		/* Set the sort hooks */
10261 		ang_sort_comp = ang_sort_comp_distance;
10262 		ang_sort_swap = ang_sort_swap_distance;
10263 
10264 		/* Sort the positions */
10265 		wounded_player_target_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_idx, p_ptr->target_n);
10266 
10267 		m = 0;
10268 
10269 	/* too lazy to handle dirs right now */
10270 
10271 	/* handle player target.... */
10272 	if (p_ptr->target_n) {
10273 		y = p_ptr->target_y[m];
10274 		x = p_ptr->target_x[m];
10275 		idx = p_ptr->target_idx[m];
10276 
10277 		c_ptr = &zcave[y][x];
10278 
10279 		q_ptr = Players[idx];
10280 
10281 		/* Hack -- Track that player */
10282 		health_track(Ind, 0 - idx);
10283 
10284 		/* Hack -- handle stuff */
10285 		handle_stuff(Ind);
10286 
10287 		/* Describe */
10288 		snprintf(out_val, sizeof(out_val), "%s targetted.", q_ptr->name);
10289 
10290 		/* Tell the client about it */
10291 		Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10292 	}
10293 
10294 	/* Remember current index */
10295 	p_ptr->look_index = m;
10296 
10297 	p_ptr->target_who = 0 - p_ptr->target_idx[m];
10298 	p_ptr->target_col = p_ptr->target_x[m];
10299 	p_ptr->target_row = p_ptr->target_y[m];
10300 
10301 	/* Failure */
10302 	if (!p_ptr->target_who) return (FALSE);
10303 
10304 	/* Clear target info */
10305 	p_ptr->target_n = 0;
10306 
10307 	/* Success */
10308 	return (TRUE);
10309 }
10310 
10311 #else
10312 
10313 /* targets closest player */
10314 bool target_set_friendly(int Ind, int dir)
10315 {
10316 	player_type *p_ptr = Players[Ind], *q_ptr;
10317 	struct worldpos *wpos = &p_ptr->wpos;
10318 	cave_type **zcave;
10319 	int		i, m, idx;
10320 	int		y;
10321 	int		x;
10322 	char	out_val[160];
10323 
10324 	if (!(zcave = getcave(wpos))) return(FALSE);
10325 
10326 	x = p_ptr->px;
10327 	y = p_ptr->py;
10328 
10329 	/* Go ahead and turn off target mode */
10330 	p_ptr->target_who = 0;
10331 
10332 	/* Turn off health tracking */
10333 	health_track(Ind, 0);
10334 
10335 
10336 	/* Reset "target" array */
10337 	p_ptr->target_n = 0;
10338 
10339 	for (i = 1; i <= NumPlayers; i++) {
10340 		q_ptr = Players[i];
10341 
10342 		/* Don't target yourself */
10343 		if (i == Ind) continue;
10344 
10345 		/* Skip unconnected players */
10346 		if (q_ptr->conn == NOT_CONNECTED) continue;
10347 
10348 		/* Ignore players we aren't friends with */
10349 		if (check_hostile(Ind, i)) continue;
10350 
10351 		/* if we are in party, only help members */
10352 		if (p_ptr->party && (!player_in_party(p_ptr->party, i))) continue;
10353 
10354 		/* Ignore "unreasonable" players */
10355 		if (!target_able(Ind, 0 - i)) continue;
10356 
10357 		/* Save the player index */
10358 		p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10359 		p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10360 		p_ptr->target_idx[p_ptr->target_n] = i;
10361 		p_ptr->target_n++;
10362 	}
10363 
10364 #if 1
10365 	/* Sort the positions */
10366 	wounded_player_target_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_idx, p_ptr->target_n);
10367 #else //TODO
10368 	/* Set the sort hooks */
10369 	ang_sort_comp = ang_sort_comp_distance;
10370 	ang_sort_swap = ang_sort_swap_distance;
10371 
10372 	/* Sort the positions */
10373 	ang_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_n);
10374 #endif
10375 
10376 	m = 0;
10377 
10378 	/* handle player target.... */
10379 	if (p_ptr->target_n) {
10380 		y = p_ptr->target_y[m];
10381 		x = p_ptr->target_x[m];
10382 		idx = p_ptr->target_idx[m];
10383 
10384 		/* Hack -- Track that player */
10385 		health_track(Ind, 0 - idx);
10386 
10387 		/* Hack -- handle stuff */
10388 		handle_stuff(Ind);
10389 
10390 		/* Describe */
10391 		snprintf(out_val, sizeof(out_val), "%s targetted.", Players[idx]->name);
10392 
10393 		/* Tell the client about it */
10394 		Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10395 	}
10396 
10397 	/* Remember current index */
10398 	p_ptr->look_index = m;
10399 
10400 	p_ptr->target_who = 0 - p_ptr->target_idx[m];
10401 	p_ptr->target_col = p_ptr->target_x[m];
10402 	p_ptr->target_row = p_ptr->target_y[m];
10403 
10404 	/* Failure */
10405 	if (!p_ptr->target_who) return (FALSE);
10406 
10407 	/* Clear target info */
10408 	p_ptr->target_n = 0;
10409 
10410 	/* Success */
10411 	return (TRUE);
10412 }
10413 
10414 #endif
10415 
10416 
10417 
10418 /*
10419  * Get an "aiming direction" from the user.
10420  *
10421  * The "dir" is loaded with 1,2,3,4,6,7,8,9 for "actual direction", and
10422  * "0" for "current target", and "-1" for "entry aborted".
10423  *
10424  * Note that "Force Target", if set, will pre-empt user interaction,
10425  * if there is a usable target already set.
10426  *
10427  * Note that confusion over-rides any (explicit?) user choice.
10428  *
10429  * We just ask the client to send us a direction, unless we are confused --KLJ--
10430  */
10431 bool get_aim_dir(int Ind)
10432 {
10433 	int dir;
10434 	player_type *p_ptr = Players[Ind];
10435 
10436 	if (p_ptr->auto_target) {
10437 		autotarget = TRUE;
10438 		target_set(Ind, 0);
10439 		autotarget = FALSE;
10440 	}
10441 
10442 	/* Hack -- auto-target if requested */
10443 	if (p_ptr->use_old_target && target_okay(Ind)) {
10444 		dir = 5;
10445 
10446 		/* XXX XXX Pretend we read this direction from the network */
10447 		Handle_direction(Ind, dir);
10448 		return (TRUE);
10449 	}
10450 
10451 	Send_direction(Ind);
10452 
10453 	return (TRUE);
10454 }
10455 
10456 
10457 bool get_item(int Ind, signed char tester_hook) { //paranoia @ 'signed' char =-p
10458 	Send_item_request(Ind, tester_hook);
10459 
10460 	return (TRUE);
10461 }
10462 
10463 /*
10464  * Allows to travel both vertical/horizontal using Recall;
10465  * probably wilderness(horizontal) travel will be made by other means
10466  * in the future.
10467  *
10468  * Also, player_type doesn't contain the max.depth for each dungeon...
10469  * Currently, this function uses getlevel() to determine the max.depth
10470  * for each dungeon, but this should be replaced by actual depths
10471  * a player has ever been.	- Jir -
10472  */
10473 void set_recall_depth(player_type * p_ptr, object_type * o_ptr) {
10474 //	int recall_depth = 0;
10475 //	worldpos goal;
10476 
10477 	unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10478 
10479 	/* default to the players maximum depth */
10480 	p_ptr->recall_pos.wx = p_ptr->wpos.wx;
10481 	p_ptr->recall_pos.wy = p_ptr->wpos.wy;
10482 #ifdef SEPARATE_RECALL_DEPTHS
10483 	p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10484 			WILD_F_DOWN) ? 0 - get_recall_depth(&p_ptr->wpos, p_ptr) : get_recall_depth(&p_ptr->wpos, p_ptr);
10485 #else
10486 	p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10487 			WILD_F_DOWN) ? 0 - p_ptr->max_dlv : p_ptr->max_dlv;
10488 #endif
10489 
10490 #if 0
10491 	p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10492 			WILD_F_DOWN) ? 0 - p_ptr->max_dlv :
10493 			((wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_UP) ?
10494 			 p_ptr->max_dlv : 0);
10495 
10496 	goal.wx = p_ptr->wpos.wx;
10497 	goal.wy = p_ptr->wpos.wy;
10498 //	goal.wz = 0 - p_ptr->max_dlv;	// hack -- default to 'dungeon'
10499 #endif	// 0
10500 
10501 	/* check for a valid inscription */
10502 	if (inscription == NULL) return;
10503 
10504 	/* scan the inscription for @R */
10505 	while (*inscription != '\0') {
10506 		if (*inscription == '@') {
10507 			inscription++;
10508 
10509 			/* a valid @R has been located */
10510 			if (*inscription == 'R') {
10511 				inscription++;
10512 				/* @RW for World(Wilderness) travel */
10513 				/* It would be also amusing to limit the distance.. */
10514 				if ((*inscription == 'W') || (*inscription == 'X')) {
10515 					unsigned char * next;
10516 					inscription++;
10517 					p_ptr->recall_pos.wx = atoi((char *)inscription) % MAX_WILD_X;
10518 					p_ptr->recall_pos.wz = 0;
10519 					next = (unsigned char *)strchr((char *)inscription,',');
10520 					if (next) {
10521 						if (++next) p_ptr->recall_pos.wy = atoi((char*)next) % MAX_WILD_Y;
10522 					}
10523 				}
10524 				else if (*inscription == 'Y') {
10525 					inscription++;
10526 					p_ptr->recall_pos.wy = atoi((char*)inscription) % MAX_WILD_Y;
10527 					p_ptr->recall_pos.wz = 0;
10528 				}
10529 #if 1
10530 				/* @RT for inter-Town travels (not fully implemented yet) */
10531 				else if (*inscription == 'T') {
10532 					inscription++;
10533 					p_ptr->recall_pos.wx = p_ptr->town_x;
10534 					p_ptr->recall_pos.wy = p_ptr->town_y;
10535 					p_ptr->recall_pos.wz = 0;
10536 				}
10537 #endif
10538 				else {
10539 					int tmp = 0;
10540 					if (*inscription == 'Z') inscription++;
10541 
10542 					/* convert the inscription into a level index */
10543 					if ((tmp = atoi((char*)inscription) /
10544 							(p_ptr->depth_in_feet ? 50 : 1)))
10545 						p_ptr->recall_pos.wz = tmp;
10546 
10547 					/* catch user mistake: missing W in @RWx,y */
10548 					while (*inscription != '\0') {
10549 						if (*inscription == ',') {
10550 							p_ptr->recall_pos.wz = 0;
10551 							return;
10552 						}
10553 						inscription++;
10554 					}
10555 				}
10556 			}
10557 		}
10558 		inscription++;
10559 	}
10560 
10561 	/* sanity check or crash */
10562 	if (p_ptr->recall_pos.wx < 0) p_ptr->recall_pos.wx = 0;
10563 	if (p_ptr->recall_pos.wy < 0) p_ptr->recall_pos.wy = 0;
10564 }
10565 
10566 bool set_recall_timer(int Ind, int v) {
10567 	player_type *p_ptr = Players[Ind];
10568 	bool notice = FALSE;
10569 
10570 	/* don't accidentally recall players in Ironman Deep Dive Challenge
10571 	   by some effect (spell/Morgoth) */
10572 	if (!is_admin(p_ptr) &&
10573 	    in_irondeepdive(&p_ptr->wpos) && (p_ptr->mode & MODE_DED_IDDC) && !irondeepdive_bottom(&p_ptr->wpos)) {
10574 		msg_print(Ind, "\377oThere is some static discharge in the air around you, but nothing happens.");
10575 		return FALSE;
10576 	}
10577 
10578 	/* Hack -- Force good values */
10579 	v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
10580 
10581 	/* Open */
10582 	if (v) {
10583 		if (!p_ptr->word_recall) {
10584 			msg_print(Ind, "\377oThe air about you becomes charged...");
10585 			notice = TRUE;
10586 		}
10587 	}
10588 	/* Shut */
10589 	else {
10590 		if (p_ptr->word_recall) {
10591 			msg_print(Ind, "\377oA tension leaves the air around you...");
10592 			notice = TRUE;
10593 		}
10594 	}
10595 
10596 	/* Use the value */
10597 	p_ptr->word_recall = v;
10598 
10599 	/* Nothing to notice */
10600 	if (!notice) return (FALSE);
10601 
10602 	/* Disturb */
10603 	if (p_ptr->disturb_state) disturb(Ind, 0, 0);
10604 
10605 	/* Redraw the depth(colour) */
10606 	p_ptr->redraw |= (PR_DEPTH);
10607 
10608 	/* Handle stuff */
10609 	handle_stuff(Ind);
10610 
10611 	/* Result */
10612 	return (TRUE);
10613 }
10614 
10615 bool set_recall(int Ind, int v, object_type * o_ptr) {
10616 	player_type *p_ptr = Players[Ind];
10617 
10618 	/* don't accidentally recall players in Ironman Deep Dive Challenge
10619 	   by some effect (spell/Morgoth) */
10620 	if (!is_admin(p_ptr) &&
10621 	    in_irondeepdive(&p_ptr->wpos) && (p_ptr->mode & MODE_DED_IDDC) && !irondeepdive_bottom(&p_ptr->wpos)) {
10622 		msg_print(Ind, "\377oThere is some static discharge in the air around you, but nothing happens.");
10623 		return FALSE;
10624 	}
10625 
10626 	if (!p_ptr->word_recall) {
10627 		set_recall_depth(p_ptr, o_ptr);
10628 		return (set_recall_timer(Ind, v));
10629 	} else {
10630 		return (set_recall_timer(Ind, 0));
10631 	}
10632 
10633 }
10634 
10635 void telekinesis_aux(int Ind, int item) {
10636 	player_type *p_ptr = Players[Ind], *p2_ptr;
10637 	object_type *q_ptr, *o_ptr = p_ptr->current_telekinesis;
10638 	int Ind2;
10639 	char *inscription, *scan;
10640 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
10641 	int max_weight = p_ptr->current_telekinesis_mw;
10642 #endif
10643 
10644 	p_ptr->current_telekinesis = NULL;
10645 
10646 	/* Get the item (in the pack) */
10647 	if (item >= 0) {
10648 		q_ptr = &p_ptr->inventory[item];
10649 	} else { /* Get the item (on the floor) */
10650 		msg_print(Ind, "You must carry the object to teleport it.");
10651 		return;
10652 	}
10653 
10654 	Ind2 = get_player(Ind, o_ptr);
10655 	if (!Ind2) return;
10656 	p2_ptr = Players[Ind2];
10657 
10658 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
10659 	if (q_ptr->weight * q_ptr->number > max_weight) {
10660 		msg_format(Ind, "The item%s too heavy.", q_ptr->number > 1 ? "s are" : " is");
10661 		return;
10662 	}
10663 #endif
10664 
10665 	if (p2_ptr->ghost && !is_admin(p_ptr)) {
10666 		msg_print(Ind, "You cannot send items to ghosts!");
10667 		return;
10668 	}
10669 
10670 	if (compat_pmode(Ind, Ind2, FALSE) && !is_admin(p_ptr)) {
10671 		msg_format(Ind, "You cannot contact %s beings!", compat_pmode(Ind, Ind2, FALSE));
10672 		return;
10673 	}
10674 
10675 	/* prevent winners picking up true arts accidentally */
10676 	if (true_artifact_p(q_ptr) && !winner_artifact_p(q_ptr) &&
10677 	    p2_ptr->total_winner && cfg.kings_etiquette) {
10678 		msg_print(Ind, "Royalties may not own true artifacts!");
10679 		if (!is_admin(p2_ptr)) return;
10680 	}
10681 
10682 	/* the_sandman: item lvl restrictions are disabled in rpg */
10683 #ifndef RPG_SERVER
10684 	if ((q_ptr->owner) && (q_ptr->owner != p2_ptr->id) &&
10685 	    (q_ptr->level > p2_ptr->lev || q_ptr->level == 0)) {
10686 		if (cfg.anti_cheeze_telekinesis) {
10687 			msg_print(Ind, "The target isn't powerful enough yet to receive that item!");
10688 			if (!is_admin(p_ptr)) return;
10689 		}
10690 		if (true_artifact_p(q_ptr) && cfg.anti_arts_pickup)
10691 //                      if (artifact_p(q_ptr) && cfg.anti_arts_pickup)
10692 		{
10693 			msg_print(Ind, "The target isn't powerful enough yet to receive that artifact!");
10694 			if (!is_admin(p_ptr)) return;
10695 		}
10696 	}
10697 #endif
10698 	if ((k_info[q_ptr->k_idx].flags5 & TR5_WINNERS_ONLY) &&
10699 #ifdef FALLEN_WINNERSONLY
10700 	    !p_ptr->once_winner
10701 #else
10702 	    !p_ptr->total_winner
10703 #endif
10704 	    ) {
10705 		msg_print(Ind, "Only royalties are powerful enough to receive that item!");
10706 		if (!is_admin(p_ptr)) return;
10707 	}
10708 
10709 	if (cfg.anti_arts_send && artifact_p(q_ptr) && !is_admin(p_ptr)) {
10710 		msg_print(Ind, "The artifact resists telekinesis!");
10711 		return;
10712 	}
10713 
10714 	/* questor items cannot be 'dropped', only destroyed! */
10715 	if (q_ptr->questor) {
10716 		msg_print(Ind, "This item cannot be sent by telekinesis!");
10717 		return;
10718 	}
10719 
10720 	/* Add a check for full inventory of target player - mikaelh */
10721 	if (!inven_carry_okay(Ind2, q_ptr, 0x0)) {
10722 		msg_print(Ind, "Item doesn't fit into the target player's inventory.");
10723 		return;
10724 	}
10725 
10726 	/* Check that the target player isn't shopping - mikaelh */
10727 	if (p2_ptr->store_num != -1) {
10728 		msg_print(Ind, "Target player is currently shopping.");
10729 		return;
10730 	}
10731 
10732 	/* You cannot send artifact */
10733 	if ((cfg.anti_arts_hoard || p_ptr->total_winner) && true_artifact_p(q_ptr) && !is_admin(p_ptr)) {
10734 		msg_print(Ind, "You have an acute feeling of loss!");
10735 		handle_art_d(q_ptr->name1);
10736 	} else {
10737 		char o_name[ONAME_LEN];
10738 		/* If they're not within the same dungeon level,
10739 		   they cannot reach each other if
10740 		   one is in an IRON or NO_RECALL dungeon/tower */
10741 		if (!inarea(&p_ptr->wpos, &p2_ptr->wpos) && !is_admin(p_ptr)) {
10742 			dungeon_type *d_ptr;
10743 			d_ptr = getdungeon(&p_ptr->wpos);
10744 			if(d_ptr && ((d_ptr->flags2 & (DF2_IRON | DF2_NO_RECALL_INTO)) || (d_ptr->flags1 & DF1_NO_RECALL))){
10745 				msg_print(Ind, "You are unable to contact that player");
10746 				return;
10747 			}
10748 			d_ptr = getdungeon(&p2_ptr->wpos);
10749 			if(d_ptr && ((d_ptr->flags2 & (DF2_IRON | DF2_NO_RECALL_INTO)) || (d_ptr->flags1 & DF1_NO_RECALL))){
10750 				msg_print(Ind, "You are unable to contact that player");
10751 				return;
10752 			}
10753 		}
10754 
10755 		if (!(p2_ptr->esp_link_flags & LINKF_TELEKIN)) {
10756 			msg_print(Ind, "That player isn't concentrating on telekinesis at the moment.");
10757 			if (!is_admin(p_ptr)) return;
10758 		}
10759 
10760 		/* Log it - mikaelh */
10761 		object_desc_store(Ind, o_name, q_ptr, TRUE, 3);
10762 		s_printf("(Tele) Item transaction from %s(%d) to %s(%d):\n  %s\n", p_ptr->name, p_ptr->lev, Players[Ind2]->name, Players[Ind2]->lev, o_name);
10763 
10764 		if (true_artifact_p(q_ptr)) a_info[q_ptr->name1].carrier = p_ptr->id;
10765 
10766 		/* Highlander Tournament: Don't allow transactions before it begins */
10767 		if (!p2_ptr->max_exp) {
10768 			msg_print(Ind2, "You gain a tiny bit of experience from receiving an item via telekinesis.");
10769 			gain_exp(Ind2, 1);
10770 		}
10771 
10772 		/* Remove dangerous inscriptions - mikaelh */
10773 		if (q_ptr->note && p2_ptr->clear_inscr) {
10774 			scan = inscription = strdup(quark_str(q_ptr->note));
10775 
10776 			while (*scan != '\0') {
10777 				if (*scan == '@') {
10778 					/* Replace @ with space */
10779 					*scan = ' ';
10780 				}
10781 				scan++;
10782 			}
10783 
10784 			q_ptr->note = quark_add(inscription);
10785 			free(inscription);
10786 		}
10787 
10788 		/* Actually teleport the object to the player inventory */
10789 		can_use(Ind2, q_ptr); /* change owner */
10790 		inven_carry(Ind2, q_ptr);
10791 
10792 		/* Combine the pack */
10793 		p2_ptr->notice |= (PN_COMBINE);
10794 
10795 		/* Window stuff */
10796 		p2_ptr->window |= (PW_INVEN | PW_EQUIP);
10797 
10798 		msg_format(Ind2, "You are hit by a powerful magic wave from %s.", p_ptr->name);
10799 	}
10800 
10801 #ifdef USE_SOUND_2010
10802 	sound_item(Ind, q_ptr->tval, q_ptr->sval, "pickup_");
10803 #endif
10804 
10805 	/* Wipe it */
10806 	inven_item_increase(Ind, item, -99);
10807 	inven_item_describe(Ind, item);
10808 	inven_item_optimize(Ind, item);
10809 
10810 	/* Combine the pack */
10811 	p_ptr->notice |= (PN_COMBINE);
10812 
10813 	/* Window stuff */
10814 	p_ptr->window |= (PW_INVEN | PW_EQUIP);
10815 
10816 }
10817 
10818 int get_player(int Ind, object_type *o_ptr) {
10819 	bool ok = FALSE;
10820 	int Ind2 = 0;
10821 	unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10822 	char ins2[80];
10823 
10824 	/* check for a valid inscription */
10825 	if (inscription == NULL) {
10826 //		msg_print(Ind, "Nobody to use the power with.");
10827 		msg_print(Ind, "\377yNo target player specified.");
10828 		return 0;
10829 	}
10830 
10831 	/* scan the inscription for @P */
10832 	while ((*inscription != '\0') && !ok) {
10833 		if (*inscription == '@') {
10834 			inscription++;
10835 
10836 			/* a valid @P has been located */
10837 			if (*inscription == 'P') {
10838 				inscription++;
10839 
10840 				/* stop at '#' symbol, to allow more inscription
10841 				   variety without disturbing player name parsing */
10842 				strcpy(ins2, (cptr)inscription);
10843 				if (strchr(ins2, '#')) *(strchr(ins2, '#')) = '\0';
10844 
10845 //				Ind2 = find_player_name(inscription);
10846 //				Ind2 = name_lookup_loose(Ind, (cptr)inscription,< FALSE, FALSE);
10847 				Ind2 = name_lookup_loose(Ind, ins2, FALSE, FALSE);
10848 				if (Ind2) ok = TRUE;
10849 			}
10850 		}
10851 		inscription++;
10852 	}
10853 
10854 	if (!ok) {
10855 		msg_print(Ind, "\377yCouldn't find the target.");
10856 		return 0;
10857 	}
10858 
10859 	if (Ind == Ind2) {
10860 		msg_print(Ind, "\377yYou cannot do that on yourself.");
10861 		return 0;
10862 	}
10863 
10864 	return Ind2;
10865 }
10866 
10867 int get_monster(int Ind, object_type *o_ptr) {
10868         bool ok1 = TRUE, ok2 = TRUE;
10869 	int r_idx = 0;
10870 
10871 	unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10872 
10873        	/* check for a valid inscription */
10874 	if (inscription == NULL) {
10875 		msg_print(Ind, "No monster specified.");
10876 		return 0;
10877 	}
10878 
10879 	/* scan the inscription for @M */
10880 	while ((*inscription != '\0') && ok1 && ok2) {
10881 		if (*inscription == '@') {
10882 			inscription++;
10883 
10884 			/* a valid @M has been located */
10885 			if (*inscription == 'M') {
10886 				inscription++;
10887 
10888 				r_idx = atoi((cptr)inscription);
10889 				if (r_idx < 1 || r_idx > MAX_R_IDX - 1) ok1 = FALSE;
10890 				else if (!r_info[r_idx].name) ok1 = FALSE;
10891 				else if (!Players[Ind]->r_killed[r_idx]) ok2 = FALSE;
10892 			}
10893 		}
10894 		inscription++;
10895 	}
10896 
10897         if (!ok1) {
10898 		msg_print(Ind, "That monster does not exist.");
10899 		return 0;
10900 	}
10901 
10902 	if (!ok2) {
10903 		msg_print(Ind, "You haven't killed one of these monsters yet.");
10904 		return 0;
10905 	}
10906 
10907 	return r_idx;
10908 }
10909 
10910 void blood_bond(int Ind, object_type *o_ptr) {
10911         player_type *p_ptr = Players[Ind], *p2_ptr;
10912 //      bool ok = FALSE;
10913         int Ind2;
10914 	player_list_type *pl_ptr;
10915 	cave_type **zcave;
10916 	cave_type *c_ptr;
10917 
10918 	if (p_ptr->pvpexception == 3) {
10919 		msg_print(Ind, "Sorry, you're *not* allowed to attack other players.");
10920 		return; /* otherwise, blood bond will result in insta-death */
10921 	}
10922 
10923 	Ind2 = get_player(Ind, o_ptr);
10924 	if (!Ind2) {
10925 		msg_print(Ind, "\377oCouldn't blood bond because that player wasn't found.");
10926 		return;
10927 	}
10928 	p2_ptr = Players[Ind2];
10929 
10930 	/* not during pvp-only or something (Highlander Tournament) */
10931 	if (sector00separation &&
10932 	    ((p_ptr->wpos.wx == WPOS_SECTOR00_X && p_ptr->wpos.wy == WPOS_SECTOR00_Y) ||
10933 	    (p2_ptr->wpos.wx == WPOS_SECTOR00_X && p2_ptr->wpos.wy == WPOS_SECTOR00_Y))) {
10934 		msg_print(Ind, "You cannot blood bond right now.");
10935 		return;
10936 	}
10937 
10938 	if (check_blood_bond(Ind, Ind2)) {
10939 		msg_format(Ind, "You are already blood bonded with %s.", p2_ptr->name);
10940 		return;
10941 	}
10942 
10943 	/* To prevent an AFK player being teleported around: */
10944 	if (p2_ptr->afk) {
10945 		msg_print(Ind, "That player is currently AFK.");
10946 		return;
10947 	}
10948 
10949 	/* protect players in inns */
10950 	if ((zcave = getcave(&p2_ptr->wpos))) {
10951 		c_ptr = &zcave[p2_ptr->py][p2_ptr->px];
10952 		if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) {
10953 			msg_print(Ind, "That player currently dwells on protected grounds.");
10954 			return;
10955 		}
10956 	}
10957 
10958 	MAKE(pl_ptr, player_list_type);
10959 	pl_ptr->id = p2_ptr->id;
10960 	if (p_ptr->blood_bond) {
10961 		pl_ptr->next = p_ptr->blood_bond;
10962 	} else {
10963 		pl_ptr->next = NULL;
10964 	}
10965 	p_ptr->blood_bond = pl_ptr;
10966 
10967 	MAKE(pl_ptr, player_list_type);
10968 	pl_ptr->id = p_ptr->id;
10969 	if (p_ptr->blood_bond) {
10970 		pl_ptr->next = p2_ptr->blood_bond;
10971 	} else {
10972 		pl_ptr->next = NULL;
10973 	}
10974 	p2_ptr->blood_bond = pl_ptr;
10975 
10976 	s_printf("BLOOD_BOND: %s blood bonds with %s\n", p_ptr->name, p2_ptr->name);
10977 	msg_format(Ind, "\374\377cYou blood bond with %s.", p2_ptr->name);
10978 	msg_format(Ind2, "\374%s blood bonds with you.", p_ptr->name);
10979 	msg_broadcast_format(Ind, "\374\377c%s blood bonds with %s.", p_ptr->name, p2_ptr->name);
10980 
10981 	/* new: auto-hostile, circumventing town peace zone functionality: */
10982 	add_hostility(Ind, p2_ptr->name, TRUE);
10983 	add_hostility(Ind2, p_ptr->name, FALSE);
10984 
10985 	p_ptr->update |= PU_BONUS;
10986 	p2_ptr->update |= PU_BONUS;
10987 }
10988 
10989 bool check_blood_bond(int Ind, int Ind2)
10990 {
10991 	player_type *p_ptr, *p2_ptr;
10992 	player_list_type *pl_ptr;
10993 
10994 	p_ptr = Players[Ind];
10995 	p2_ptr = Players[Ind2];
10996 	if (!p2_ptr) return FALSE;
10997 
10998 	pl_ptr = p_ptr->blood_bond;
10999 	while (pl_ptr) {
11000 		if (pl_ptr->id == p2_ptr->id) return TRUE;
11001 		pl_ptr = pl_ptr->next;
11002 	}
11003 	return FALSE;
11004 }
11005 
11006 void remove_blood_bond(int Ind, int Ind2)
11007 {
11008 	player_type *p_ptr, *p2_ptr;
11009 	player_list_type *pl_ptr, *ppl_ptr;
11010 
11011 	p_ptr = Players[Ind];
11012 	p2_ptr = Players[Ind2];
11013 	if (!p2_ptr) return;
11014 
11015 	ppl_ptr = NULL;
11016 	pl_ptr = p_ptr->blood_bond;
11017 	while (pl_ptr)
11018 	{
11019 		if (pl_ptr->id == p2_ptr->id)
11020 		{
11021 			if (ppl_ptr)
11022 			{
11023 				ppl_ptr->next = pl_ptr->next;
11024 			}
11025 			else
11026 			{
11027 				/* First in the list */
11028 				p_ptr->blood_bond = pl_ptr->next;
11029 			}
11030 			KILL(pl_ptr, player_list_type);
11031 			return;
11032 		}
11033 		ppl_ptr = pl_ptr;
11034 		pl_ptr = pl_ptr->next;
11035 	}
11036 }
11037 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
11038 bool telekinesis(int Ind, object_type *o_ptr, int max_weight) {
11039 	player_type *p_ptr = Players[Ind];
11040 
11041 	get_item(Ind, ITH_MAX_WEIGHT + max_weight);
11042 
11043 	/* Clear any other pending actions */
11044 	clear_current(Ind);
11045 
11046 	p_ptr->current_telekinesis = o_ptr;
11047 	p_ptr->current_telekinesis_mw = max_weight;
11048 
11049 	return TRUE;
11050 }
11051 #endif
11052 
11053 /* this has finally earned its own function, to make it easy for restoration to do this also */
11054 bool do_scroll_life(int Ind)
11055 {
11056 	int x,y;
11057 
11058 	player_type * p_ptr = Players[Ind], *q_ptr;
11059 	cave_type * c_ptr;
11060 	cave_type **zcave;
11061 	zcave = getcave(&p_ptr->wpos);
11062 	if (!zcave) return(FALSE);
11063 
11064 	for (y = -1; y <= 1; y++) {
11065 		for (x = -1; x <= 1; x++) {
11066 	   		c_ptr = &zcave[p_ptr->py+y][p_ptr->px+x];
11067 	  		if (c_ptr->m_idx < 0) {
11068 				q_ptr = Players[0 - c_ptr->m_idx];
11069    				if (q_ptr->ghost) {
11070 					if (cave_floor_bold(zcave, p_ptr->py + y, p_ptr->px + x) &&
11071 					    !(c_ptr->info & CAVE_ICKY))
11072 					{
11073     						resurrect_player(0 - c_ptr->m_idx, 0);
11074 	/* if player is not in town and resurrected on *TRUE* death level
11075 	   then this is a GOOD action. Reward the player */
11076 						if (!istown(&p_ptr->wpos) && getlevel(&p_ptr->wpos) == q_ptr->died_from_depth) {
11077 							u16b dal = 1 + ((2 * q_ptr->lev) / p_ptr->lev);
11078 							if (p_ptr->align_good > dal)
11079 								p_ptr->align_good -= dal;
11080 							else p_ptr->align_good = 0;
11081 						}
11082 	   			        	return TRUE;
11083 					} else {
11084 						msg_print(Ind, "The scroll fails here!");
11085 					}
11086       				}
11087   			}
11088   		}
11089   	}
11090   	/* we did nore ressurect anyone */
11091   	return FALSE;
11092 }
11093 
11094 
11095 /* modified above function to instead restore XP... used in priest spell rememberence */
11096 bool do_restoreXP_other(int Ind)
11097 {
11098 	int x,y;
11099 
11100 	player_type * p_ptr = Players[Ind];
11101 	cave_type * c_ptr;
11102 	cave_type **zcave;
11103 	if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
11104 
11105 	for (y = -1; y <= 1; y++) {
11106 		for (x = -1; x <= 1; x++) {
11107 	   		c_ptr = &zcave[p_ptr->py+y][p_ptr->px+x];
11108 
11109 	  		if (c_ptr->m_idx < 0) {
11110    				if (Players[0 - c_ptr->m_idx]->exp < Players[0 - c_ptr->m_idx]->max_exp) {
11111     					restore_level(0 - c_ptr->m_idx);
11112    			        	return TRUE;
11113       				}
11114   			}
11115   		}
11116   	}
11117   	/* we did nore ressurect anyone */
11118   	return FALSE;
11119   }
11120 
11121 
11122 /* Hack -- since the framerate has been boosted by five times since version
11123  * 0.6.0 to make game movement more smooth, we return the old level speed
11124  * times five to keep the same movement rate.
11125  */
11126 
11127 void unstatic_level(struct worldpos *wpos){
11128 	int i;
11129 
11130 	for (i = 1; i <= NumPlayers; i++) {
11131 		if (Players[i]->conn == NOT_CONNECTED) continue;
11132 		if (Players[i]->st_anchor) {
11133 			Players[i]->st_anchor = 0;
11134 			msg_print(GetInd[Players[i]->id], "Your space/time anchor breaks");
11135 		}
11136 	}
11137 	for (i = 1; i <= NumPlayers; i++){
11138 		if (Players[i]->conn == NOT_CONNECTED) continue;
11139 		if (inarea(&Players[i]->wpos, wpos)) {
11140 			teleport_player_level(i, TRUE);
11141 		}
11142 	}
11143 	new_players_on_depth(wpos,0,FALSE);
11144 }
11145 
11146 /* these Dungeon Master commands should probably be added somewhere else, but I am
11147  * hacking them together here to start.
11148  */
11149 
11150 /* static or unstatic a level */
11151 bool master_level(int Ind, char * parms) {
11152 	int i;
11153 	/* get the player pointer */
11154 	player_type *p_ptr = Players[Ind];
11155 
11156 	if (!is_admin(p_ptr)) return FALSE;
11157 
11158 	switch (parms[0]) {
11159 		/* unstatic the level */
11160 		case 'u':
11161 		{
11162 			struct worldpos twpos;
11163 			wpcopy(&twpos,&p_ptr->wpos);
11164 			unstatic_level(&twpos);
11165        			/* additionally unstale it, simply by poofing it completely. - C. Blue */
11166        			if (getcave(&twpos)) dealloc_dungeon_level(&twpos);
11167        			msg_format(Ind, "The level %s has been unstaticed.", wpos_format(Ind, &twpos));
11168 			break;
11169 		}
11170 
11171 		/* static the level */
11172 		case 's':
11173 		{
11174 			/* Increase the number of players on the dungeon
11175 			 * masters level by one. */
11176 			new_players_on_depth(&p_ptr->wpos,1,TRUE);
11177 			msg_format(Ind, "The level %s has been staticed.", wpos_format(Ind, &p_ptr->wpos));
11178 			break;
11179 		}
11180 		/* add dungeon stairs here */
11181 		case 'D':
11182 		{
11183 			cave_type **zcave;
11184 			u32b f1 = 0x0, f2 = 0x0, f3 = 0x0;
11185 			if(!parms[1] || !parms[2] || p_ptr->wpos.wz) return FALSE;
11186 			if(istown(&p_ptr->wpos)){
11187 				msg_print(Ind,"Even you may not create dungeons in the town!");
11188 				return FALSE;
11189 			}
11190 			/* extract flags (note that 0x01 are reservd hacks to prevent zero byte) */
11191 			if (parms[4] & 0x02) f1 |= DF1_FORGET;
11192 			if (parms[4] & 0x04) f3 |= (DF3_HIDDENLIB | DF3_DEEPSUPPLY);
11193 			if (parms[4] & 0x08) f3 |= DF3_NO_SIMPLE_STORES;
11194 			if (parms[5] & 0x02) f2 |= DF2_RANDOM;
11195 			if (parms[5] & 0x04) f2 |= DF2_HELL;
11196 			if (parms[5] & 0x08) f2 |= DF2_NO_MAGIC_MAP;
11197 			if (parms[5] & 0x10) f2 |= DF2_IRON;
11198 			if (parms[5] & 0x20) f2 |= DF2_TOWNS_IRONRECALL;
11199 			if (parms[5] & 0x40) f2 |= DF2_TOWNS_RND;
11200 			if (parms[5] & 0x80) f2 |= DF2_TOWNS_FIX;
11201 			if (parms[6] & 0x04) f2 |= DF2_MISC_STORES;
11202 			if (parms[6] & 0x08) {
11203 				if (parms[6] & 0x10) f2 |= DF2_IRONRND1;
11204 				if (parms[6] & 0x20) f2 |= DF2_IRONRND2;
11205 				if (parms[6] & 0x40) f2 |= DF2_IRONRND3;
11206 				if (parms[6] & 0x80) f2 |= DF2_IRONRND4;
11207 			} else {
11208 				if (parms[6] & 0x10) f2 |= DF2_IRONFIX1;
11209 				if (parms[6] & 0x20) f2 |= DF2_IRONFIX2;
11210 				if (parms[6] & 0x40) f2 |= DF2_IRONFIX3;
11211 				if (parms[6] & 0x80) f2 |= DF2_IRONFIX4;
11212 			}
11213 			/* create tower or dungeon */
11214 			if(parms[3] == 't' && !(wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_UP)){
11215 				printf("tower: flags %x,%x\n", f1, f2);
11216 				if((zcave = getcave(&p_ptr->wpos))) {
11217 					zcave[p_ptr->py][p_ptr->px].feat = FEAT_LESS;
11218 					if (zcave[p_ptr->py][p_ptr->px].info & CAVE_JAIL) f3 |= DF3_JAIL_DUNGEON;
11219 				}
11220 				add_dungeon(&p_ptr->wpos, parms[1], parms[2], f1, f2, f3, TRUE, 0, parms[7], 0, 0);
11221 				new_level_down_y(&p_ptr->wpos, p_ptr->py);
11222 				new_level_down_x(&p_ptr->wpos, p_ptr->px);
11223 			}
11224 			if(parms[3] == 'd' && !(wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_DOWN)){
11225 				printf("dungeon: flags %x,%x\n", f1, f2);
11226 				if((zcave = getcave(&p_ptr->wpos))) {
11227 					zcave[p_ptr->py][p_ptr->px].feat = FEAT_MORE;
11228 					if (zcave[p_ptr->py][p_ptr->px].info & CAVE_JAIL) f3 |= DF3_JAIL_DUNGEON;
11229 				}
11230 				add_dungeon(&p_ptr->wpos, parms[1], parms[2], f1, f2, f3, FALSE, 0, parms[7], 0, 0);
11231 				new_level_up_y(&p_ptr->wpos, p_ptr->py);
11232 				new_level_up_x(&p_ptr->wpos, p_ptr->px);
11233 			}
11234 			break;
11235 		}
11236 		case 'R':
11237 		{
11238 			/* Remove dungeon (here) if it exists */
11239 			cave_type **zcave;
11240 			if(!(zcave = getcave(&p_ptr->wpos))) break;
11241 
11242 			/* either remove the dungeon we're currently in */
11243 			if (p_ptr->wpos.wz) {
11244 				if (p_ptr->wpos.wz < 0) {
11245 					p_ptr->recall_pos.wx = p_ptr->wpos.wx;
11246 					p_ptr->recall_pos.wy = p_ptr->wpos.wy;
11247 					p_ptr->recall_pos.wz = 0;
11248 					recall_player(Ind, "");
11249 					rem_dungeon(&p_ptr->wpos, FALSE);
11250 				} else {
11251 					p_ptr->recall_pos.wx = p_ptr->wpos.wx;
11252 					p_ptr->recall_pos.wy = p_ptr->wpos.wy;
11253 					p_ptr->recall_pos.wz = 0;
11254 					recall_player(Ind, "");
11255 					rem_dungeon(&p_ptr->wpos, TRUE);
11256 				}
11257 			} else { /* or the one whose entrance staircase we're standing on */
11258 				switch(zcave[p_ptr->py][p_ptr->px].feat){
11259 					case FEAT_MORE:
11260 						rem_dungeon(&p_ptr->wpos, FALSE);
11261 						zcave[p_ptr->py][p_ptr->px].feat = FEAT_GRASS;
11262 						break;
11263 					case FEAT_LESS:
11264 						rem_dungeon(&p_ptr->wpos, TRUE);
11265 						zcave[p_ptr->py][p_ptr->px].feat = FEAT_GRASS;
11266 						break;
11267 					default:
11268 						msg_print(Ind, "There is no dungeon here");
11269 				}
11270 			}
11271 			break;
11272 		}
11273 		case 'T':
11274 		{
11275 			struct worldpos twpos;
11276 			if(!parms[1] || p_ptr->wpos.wz) return FALSE;
11277 			if(istown(&p_ptr->wpos)){
11278 				msg_print(Ind, "There is already a town here!");
11279 				return FALSE;
11280 			}
11281 			wpcopy(&twpos,&p_ptr->wpos);
11282 
11283 			/* clean level first! */
11284 			wipe_m_list(&p_ptr->wpos);
11285 			wipe_o_list(&p_ptr->wpos);
11286 //			wipe_t_list(&p_ptr->wpos);
11287 
11288 			/* dont do this where there are houses! */
11289 			for (i = 0; i < num_houses; i++) {
11290 				if (inarea(&p_ptr->wpos, &houses[i].wpos)) {
11291 					houses[i].flags |= HF_DELETED;
11292 				}
11293 			}
11294 			addtown(p_ptr->wpos.wy, p_ptr->wpos.wx, parms[1], 0, TOWN_VANILLA);
11295 			unstatic_level(&twpos);
11296 			if(getcave(&twpos))
11297 				dealloc_dungeon_level(&twpos);
11298 
11299 			break;
11300 		}
11301 		/* default -- do nothing. */
11302 		default: break;
11303 	}
11304 	return TRUE;
11305 }
11306 
11307 /* static or unstatic a level (from chat-line command) */
11308 bool master_level_specific(int Ind, struct worldpos *wpos, char * parms)
11309 {
11310 	/* get the player pointer */
11311 	player_type *p_ptr = Players[Ind];
11312 
11313 //	if (strcmp(p_ptr->name, cfg_dungeon_master)) return FALSE;
11314 	if (!is_admin(p_ptr)) return FALSE;
11315 
11316 	switch (parms[0])
11317 	{
11318 		/* unstatic the level */
11319 		case 'u':
11320 		{
11321 			unstatic_level(wpos);
11322        			/* additionally unstale it, simply by poofing it completely. - C. Blue */
11323        			dealloc_dungeon_level(wpos);
11324 //     			msg_format(Ind, "The level (%d,%d) %dft has been unstaticed.", wpos->wx, wpos->wy, wpos->wz * 50);
11325        			msg_format(Ind, "The level %s has been unstaticed.", wpos_format(Ind, wpos));
11326 			break;
11327 		}
11328 
11329 		/* static the level */
11330 		case 's':
11331 		{
11332 			/* Increase the number of players on the dungeon
11333 			 * masters level by one. */
11334 			new_players_on_depth(&p_ptr->wpos,1,TRUE);
11335 			msg_print(Ind, "The level has been staticed.");
11336 			break;
11337 		}
11338 		/* default -- do nothing. */
11339 		default: break;
11340 	}
11341 	return TRUE;
11342 }
11343 
11344 
11345 /*
11346  *
11347  * Guild build access
11348  * Must be owner inside guild hall
11349  *
11350  */
11351 //static bool guild_build(int Ind){
11352 bool guild_build(int Ind){
11353 	player_type *p_ptr = Players[Ind];
11354 	int i;
11355 
11356 	for (i = 0; i < num_houses; i++) {
11357 		if (inarea(&houses[i].wpos, &p_ptr->wpos)) {
11358 			if (fill_house(&houses[i], FILL_PLAYER, p_ptr)) {
11359 				if (access_door(Ind, houses[i].dna, FALSE) || admin_p(Ind)) {
11360 					if (houses[i].dna->owner_type == OT_GUILD &&
11361 					    p_ptr->guild == houses[i].dna->owner &&
11362 					    guilds[p_ptr->guild].master == p_ptr->id) {
11363 						if (p_ptr->au > 1000) {
11364 							p_ptr->au -= 1000;
11365 							p_ptr->redraw |= PR_GOLD;
11366 							return(TRUE);
11367 						}
11368 					}
11369 				}
11370 				break;
11371 			}
11372 		}
11373 	}
11374 	return(FALSE);
11375 }
11376 
11377 /* Build walls and such.  This should probably be improved, I am just hacking
11378  * it together right now for Halloween. -APD
11379  */
11380 bool master_build(int Ind, char * parms)
11381 {
11382 	player_type * p_ptr = Players[Ind];
11383 	cave_type * c_ptr;
11384 	struct c_special *cs_ptr;
11385 	static unsigned char new_feat = FEAT_WALL_EXTRA;
11386 	cave_type **zcave;
11387 
11388 	if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
11389 
11390 	if (!is_admin(p_ptr) && (!player_is_king(Ind)) && (!guild_build(Ind))) return FALSE;
11391 
11392 	/* extract arguments, otherwise build a wall of type new_feat */
11393 	if (parms) {
11394 		/* Hack -- the first character specifies the type of wall */
11395 		new_feat = parms[0];
11396 		/* Hack -- toggle auto-build on/off */
11397 		switch (parms[1]) {
11398 			case 'T': p_ptr->master_move_hook = master_build; break;
11399 			case 'F': p_ptr->master_move_hook = NULL; return FALSE;
11400 			default : break;
11401 		}
11402 	}
11403 
11404 	c_ptr = &zcave[p_ptr->py][p_ptr->px];
11405 
11406 	/* Never destroy real house doors! Work on this later */
11407 	if ((cs_ptr = GetCS(c_ptr, CS_DNADOOR))) return(FALSE);
11408 
11409 	/* This part to be rewritten for stacked CS */
11410 	c_ptr->feat = new_feat;
11411 	if (c_ptr->feat == FEAT_HOME) {
11412 		struct c_special *cs_ptr;
11413 		/* new special door creation (with keys) */
11414 		struct key_type *key;
11415 		object_type newkey;
11416 		int id;
11417 		MAKE(key, struct key_type);
11418 		sscanf(&parms[2],"%d",&id);
11419 		key->id = id;
11420 		invcopy(&newkey, lookup_kind(TV_KEY, SV_HOUSE_KEY ));
11421 		newkey.pval = key->id;
11422 		newkey.marked2 = ITEM_REMOVAL_NEVER;
11423 		drop_near(&newkey, -1, &p_ptr->wpos, p_ptr->py, p_ptr->px);
11424 		cs_ptr = ReplaceCS(c_ptr, CS_KEYDOOR);
11425 		if (cs_ptr) cs_ptr->sc.ptr = key;
11426 		else KILL(key, struct key_type);
11427 		p_ptr->master_move_hook = NULL;	/*buggers up if not*/
11428 	}
11429 	if (c_ptr->feat == FEAT_SIGN) {
11430 		struct c_special *cs_ptr;
11431 		struct floor_insc *sign;
11432 		MAKE(sign, struct floor_insc);
11433 		strcpy(sign->text, &parms[2]);
11434 		cs_ptr = ReplaceCS(c_ptr, CS_INSCRIP);
11435 		if (cs_ptr) cs_ptr->sc.ptr = sign;
11436 		else KILL(sign, struct floor_insc);
11437 		p_ptr->master_move_hook = NULL;	/*buggers up if not*/
11438 	}
11439 
11440 	return TRUE;
11441 }
11442 
11443 static char master_specific_race_char = 'a';
11444 
11445 static bool master_summon_specific_aux(int r_idx)
11446 {
11447 	monster_race *r_ptr = &r_info[r_idx];
11448 
11449 	/* no uniques */
11450 	if (r_ptr->flags1 & RF1_UNIQUE) return FALSE;
11451 
11452 	/* if we look like what we are looking for */
11453 	if (r_ptr->d_char == master_specific_race_char) return TRUE;
11454 	return FALSE;
11455 }
11456 
11457 /* Auxillary function to master_summon, determine the exact type of monster
11458  * to summon from a more general description.
11459  */
11460 static u16b master_summon_aux_monster_type(int Ind, char monster_type, char * monster_parms)
11461 {
11462 	player_type *p_ptr = Players[Ind];
11463 	int tmp, lev;
11464 
11465 	/* handle each category of monster types */
11466 	switch (monster_type)
11467 	{
11468 		/* specific monster specified */
11469 		case 's':
11470 		{
11471 			/* allows specification by monster No. */
11472 			tmp = atoi(monster_parms);
11473 			if (tmp > 0) return tmp;
11474 
11475 			/* if the name was specified, summon this exact race */
11476 			if (strlen(monster_parms) > 1) return race_index(monster_parms);
11477 			/* otherwise, summon a monster that looks like us */
11478 			else
11479 			{
11480 				master_specific_race_char = monster_parms[0];
11481 				get_mon_num_hook = master_summon_specific_aux;
11482 				get_mon_num_prep(0, NULL);
11483 //				tmp = get_mon_num(rand_int(100) + 10);
11484 				lev = (monster_parms[0] == 't') ? 0 : rand_int(100) + 10;
11485 				tmp = get_mon_num(lev, lev);
11486 
11487 				/* restore monster generator */
11488 				get_mon_num_hook = dungeon_aux;
11489 
11490 				/* return our monster */
11491 				return tmp;
11492 			}
11493 		}
11494 		/* orc specified */
11495 		case 'o':
11496 		{
11497 			/* if not random, assume specific orc specified */
11498 			if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11499 			/* random orc */
11500 			else switch(rand_int(6))
11501 			{
11502 				case 0: return race_index("Snaga");
11503 				case 1: return race_index("Cave orc");
11504 				case 2: return race_index("Hill orc");
11505 				case 3: return race_index("Dark orc");
11506 				case 4: return race_index("Half-orc");
11507 				case 5: return race_index("Uruk");
11508 			}
11509 			break;
11510 		}
11511 		/* low undead specified */
11512 		case 'u':
11513 		{
11514 			/* if not random, assume specific high undead specified */
11515 			if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11516 			/* random low undead */
11517 			else switch(rand_int(11))
11518 			{
11519 				case 0: return race_index("Poltergeist");
11520 				case 1: return race_index("Green glutton ghost");
11521 				case 2: return race_index("Lost soul");
11522 				case 3: return race_index("Skeleton kobold");
11523 				case 4: return race_index("Skeleton orc");
11524 				case 5: return race_index("Skeleton human");
11525 				case 6: return race_index("Zombified orc");
11526 				case 7: return race_index("Zombified human");
11527 				case 8: return race_index("Mummified orc");
11528 				case 9: return race_index("Moaning spirit");
11529 				case 10: return race_index("Vampire bat");
11530 			}
11531 			break;
11532 		}
11533 
11534 		/* high undead specified */
11535 		case 'U':
11536 		{
11537 			/* if not random, assume specific high undead specified */
11538 			if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11539 			/* random low undead */
11540 			else switch(rand_int(13))
11541 			{
11542 				case 0: return race_index("Vampire");
11543 				case 1: return race_index("Giant skeleton troll");
11544 				case 2: return race_index("Lich");
11545 				case 3: return race_index("Master vampire");
11546 				case 4: return race_index("Dread");
11547 				case 5: return race_index("Nether wraith");
11548 				case 6: return race_index("Night mare");
11549 				case 7: return race_index("Vampire lord");
11550 				case 8: return race_index("Archpriest");
11551 				case 9: return race_index("Undead beholder");
11552 				case 10: return race_index("Dreadmaster");
11553 				case 11: return race_index("Nightwing");
11554 				case 12: return race_index("Nightcrawler");
11555 			}
11556 			break;
11557 		}
11558 
11559 		/* specific depth specified */
11560 		case 'd':
11561 		{
11562 			get_mon_num_hook = dungeon_aux;
11563 
11564 			/* Wilderness-specific hook */
11565 			if (!p_ptr->wpos.wz) set_mon_num_hook_wild(&p_ptr->wpos);
11566 
11567 			get_mon_num_prep(0, NULL);
11568 			return get_mon_num(monster_parms[0], monster_parms[0] - 20); //reduce OoD if we summon depth-specificly
11569 		}
11570 
11571 		default : break;
11572 	}
11573 
11574 	/* failure */
11575 	return 0;
11576 
11577 }
11578 
11579 /* Temporary debugging hack, to test the new excellents.
11580  */
11581 bool master_acquire(int Ind, char * parms)
11582 {
11583 	player_type * p_ptr = Players[Ind];
11584 
11585 	if (!is_admin(p_ptr)) return FALSE;
11586 	acquirement(&p_ptr->wpos, p_ptr->py, p_ptr->px, 1, TRUE, TRUE, make_resf(p_ptr));
11587 	return TRUE;
11588 }
11589 
11590 /* Monster summoning options. More documentation on this later. */
11591 bool master_summon(int Ind, char * parms)
11592 {
11593 	int c;
11594 	player_type * p_ptr = Players[Ind];
11595 
11596 	static char monster_type = 0;  /* What type of monster we are -- specific, random orc, etc */
11597 	static char monster_parms[80];
11598 	static char summon_type = 0; /* what kind to summon -- x right here, group at random location, etc */
11599 	static char summon_parms = 0; /* arguments to previous byte */
11600 	static u16b r_idx = 0; /* which monser to actually summon, from previous variables */
11601 	unsigned char size = 0;  /* how many monsters to actually summon */
11602 
11603 	if (!is_admin(p_ptr) && (!player_is_king(Ind))) return FALSE;
11604 
11605 	summon_override_checks = SO_ALL; /* set admin summoning flag for overriding all validity checks */
11606 
11607 	/* extract arguments.  If none are found, summon previous type. */
11608 	if (parms)
11609 	{
11610 		/* the first character specifies the type of monster */
11611 		summon_type = parms[0];
11612 		summon_parms = parms[1];
11613 		monster_type = parms[2];
11614 		/* Hack -- since monster_parms is a string, throw it on the end */
11615 		strcpy(monster_parms, &parms[3]);
11616 	}
11617 
11618 	switch (summon_type)
11619 	{
11620 		/* summon x here */
11621 		case 'x':
11622 		{
11623 			/* for each monster we are summoning */
11624 			for (c = 0; c < summon_parms; c++)
11625 			{
11626 				/* figure out who to summon */
11627 				r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11628 
11629 				/* summon the monster, if we have a valid one */
11630 				if (r_idx)
11631 					summon_specific_race(&p_ptr->wpos, p_ptr->py, p_ptr->px, r_idx, 0, 1);
11632 			}
11633 			break;
11634 		}
11635 
11636 		/* summon x at random locations */
11637 		case 'X':
11638 		{
11639 			for (c = 0; c < summon_parms; c++)
11640 			{
11641 				/* figure out who to summon */
11642 				r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11643 
11644 				/* summon the monster at a random location */
11645 				if (r_idx)
11646 					summon_specific_race_somewhere(&p_ptr->wpos,r_idx, 0, 1);
11647 			}
11648 			break;
11649 		}
11650 
11651 		/* summon group of random size here */
11652 		case 'g':
11653 		{
11654 			/* figure out how many to summon */
11655 			size = rand_int(rand_int(50)) + 2;
11656 
11657 			/* figure out who to summon */
11658 			r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11659 
11660 			/* summon the group here */
11661 			summon_specific_race(&p_ptr->wpos, p_ptr->py, p_ptr->px, r_idx, 0, size);
11662 			break;
11663 		}
11664 		/* summon group of random size at random location */
11665 		case 'G':
11666 		{
11667 			/* figure out how many to summon */
11668 			size = rand_int(rand_int(50)) + 2;
11669 
11670 			/* figure out who to summon */
11671 			r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11672 
11673 			/* someone the group at a random location */
11674 			summon_specific_race_somewhere(&p_ptr->wpos, r_idx, 0, size);
11675 			break;
11676 		}
11677 		/* summon mode on (use with discretion... lets not be TOO mean ;-) )*/
11678 		case 'T':
11679 		{
11680 			summon_type = 'x';
11681 			summon_parms = 1;
11682 
11683 			p_ptr->master_move_hook = master_summon;
11684 			break;
11685 		}
11686 
11687 		/* summon mode off */
11688 		case 'F':
11689 		{
11690 			p_ptr->master_move_hook = NULL;
11691 			break;
11692 		}
11693 	}
11694 
11695 	summon_override_checks = SO_NONE; /* clear all override flags */
11696 	return TRUE;
11697 }
11698 
11699 #define FIND_CLOSEST_JAIL
11700 bool imprison(int Ind, u16b time, char *reason) {
11701 	int id, i, j;
11702 #ifdef FIND_CLOSEST_JAIL
11703 	int dist = 999, tmp, picked = -1;
11704 #endif
11705 	struct dna_type *dna;
11706 	player_type *p_ptr = Players[Ind];
11707 	char string[160];
11708 	cave_type **zcave, **nzcave;
11709 	struct worldpos old_wpos;
11710 
11711 	if (!jails_enabled) {
11712 		p_ptr->tim_susp = 0;
11713 		s_printf("IMPRISON: %s DISABLED.\n", p_ptr->name);
11714 		return FALSE;
11715 	}
11716 
11717 	if (!(zcave = getcave(&p_ptr->wpos))) return (FALSE);
11718 
11719 	s_printf("IMPRISON: %s ", p_ptr->name);
11720 
11721 	if (!p_ptr || !(id = lookup_player_id("Jailer"))) {
11722 		s_printf("JAILER\n");
11723 		return (FALSE);
11724 	}
11725 
11726 	if (p_ptr->wpos.wz) {
11727 		p_ptr->tim_susp += time;
11728 		s_printf("TIM_SUSP.\n");
11729 		return (TRUE);
11730 	}
11731 
11732 #ifdef JAIL_TOWN_AREA /* only imprison when within town area? */
11733 	if (!istownarea(&p_ptr->wpos, MAX_TOWNAREA)) {
11734 		p_ptr->tim_susp += time;
11735 		s_printf("NO_TOWN.\n");
11736 		return (TRUE);
11737 	}
11738 #endif
11739 
11740 	if (p_ptr->tim_jail) {
11741 		p_ptr->tim_jail += time;
11742 		s_printf("TIM_JAIL.\n");
11743 		return (TRUE);
11744 	}
11745 
11746 	/* get appropriate prison house */
11747 	for (i = 0; i < num_houses; i++) {
11748 		if (!(houses[i].flags & HF_JAIL)) continue;
11749 		if ((houses[i].flags & HF_DELETED)) continue;
11750 		dna = houses[i].dna;
11751 		if (dna->owner == id && dna->owner_type == OT_PLAYER) {
11752 #ifndef FIND_CLOSEST_JAIL /* get first prison we find? */
11753 			break;
11754 #else /* get closest prison we find? */
11755 			tmp = distance(houses[i].wpos.wy, houses[i].wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wx);
11756 			if (tmp < dist) {
11757 				dist = tmp;
11758 				picked = i;
11759 			}
11760 #endif
11761 		}
11762 	}
11763 #ifndef FIND_CLOSEST_JAIL
11764 	if (i == num_houses) {
11765 		p_ptr->tim_susp = 0;
11766 		s_printf("FAILED.\n");
11767 		return (FALSE);
11768 	}
11769 #else
11770 	if (picked == -1) {
11771 		p_ptr->tim_susp = 0;
11772 		s_printf("FAILED.\n");
11773 		return (FALSE);
11774 	}
11775 	i = picked;
11776 #endif
11777 
11778 	/* lazy, single prison system */
11779 	/* hopefully no overcrowding! */
11780 	if (!(nzcave = getcave(&houses[i].wpos))){
11781 		alloc_dungeon_level(&houses[i].wpos);
11782 		generate_cave(&houses[i].wpos, p_ptr);
11783 
11784 #if 1
11785 		/* generate some vermin randomly, for flavour */
11786 		nzcave = getcave(&houses[i].wpos);
11787 		if (rand_int(2)) for (j = randint(2); j; j--) {
11788 			int x, y;
11789 			//abuse 'id'
11790 			id = 10;
11791 			while (id--) {
11792 				if (rand_int(2)) x = houses[i].x - 15 + rand_int(13);
11793 				else x = houses[i].x + 15 - rand_int(13);
11794 				if (rand_int(2)) y = houses[i].y - 15 + rand_int(13);
11795 				else y = houses[i].y + 15 - rand_int(13);
11796 
11797 				if (!in_bounds(y, x)) continue;
11798 				if (!(nzcave[y][x].info & CAVE_STCK)) continue;
11799 
11800 				break;
11801 			}
11802 			if (id) place_monster_one(&houses[i].wpos,
11803 			    y, x,
11804 			    1, 0, 0, rand_int(2) ? TRUE : FALSE, 0, 0);
11805 		}
11806 #endif
11807 	}
11808 
11809 	store_exit(Ind);
11810 
11811 	zcave[p_ptr->py][p_ptr->px].m_idx = 0;
11812 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
11813 	forget_lite(Ind);
11814 	forget_view(Ind);
11815 	wpcopy(&old_wpos, &p_ptr->wpos);
11816 	wpcopy(&p_ptr->wpos, &houses[i].wpos);
11817 	new_players_on_depth(&old_wpos, -1, TRUE);
11818 
11819 	p_ptr->py = houses[i].y;
11820 	p_ptr->px = houses[i].x;
11821 
11822 	/* that messes it up */
11823 	/* nzcave[p_ptr->py][p_ptr->px].m_idx = (0-Ind); */
11824 	new_players_on_depth(&p_ptr->wpos, 1, TRUE);
11825 
11826 	p_ptr->new_level_flag = TRUE;
11827 	p_ptr->new_level_method = LEVEL_HOUSE;
11828 
11829 #ifdef JAILER_KILLS_WOR
11830 	/* eat his WoR scrolls as suggested? */
11831 	id = FALSE; //abuse 'id' and 'i'
11832 	i = TRUE;
11833 	for (j = 0; j < INVEN_WIELD; j++) {
11834 		object_type *j_ptr;
11835 		if (!p_ptr->inventory[j].k_idx) continue;
11836 		j_ptr = &p_ptr->inventory[j];
11837 		if ((j_ptr->tval == TV_SCROLL) && (j_ptr->sval == SV_SCROLL_WORD_OF_RECALL)) {
11838 			if (id) i = FALSE;
11839 			if (j_ptr->number > 1) i = FALSE;
11840 			inven_item_increase(Ind, j, -j_ptr->number);
11841 			inven_item_optimize(Ind, j);
11842 			combine_pack(Ind);
11843 			reorder_pack(Ind);
11844 			id = TRUE;
11845 		}
11846 	}
11847 	if (id) msg_format(Ind, "\376\377oThe jailer confiscates your word-of-recall scroll%s.", i ? "" : "s");
11848 #endif
11849 
11850 	everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
11851 	snprintf(string, sizeof(string), "\374\377o%s was jailed for %s.", p_ptr->name, reason);
11852 	msg_broadcast(Ind, string);
11853 	msg_format(Ind, "\374\377oYou have been jailed for %s.", reason);
11854 	p_ptr->tim_jail = time + p_ptr->tim_susp;
11855 	p_ptr->tim_susp = 0;
11856 
11857 	s_printf("DONE.\n");
11858 	return (TRUE);
11859 }
11860 
11861 static void player_edit(char *name){
11862 
11863 }
11864 
11865 bool master_player(int Ind, char *parms){
11866 	player_type *p_ptr = Players[Ind];
11867 	player_type *q_ptr;
11868 	int Ind2 = 0;
11869 	int i;
11870 	struct account *d_acc;
11871 	int *id_list, n;
11872 	char buf[MSG_LEN];
11873 
11874 	if (!is_admin(p_ptr)) {
11875 		msg_print(Ind,"You need to be the dungeon master to use this command.");
11876 		return FALSE;
11877 	}
11878 	switch (parms[0]) {
11879 		case 'E':	/* offline editor */
11880 			for (i = 1; i <= NumPlayers; i++){
11881 				if (!strcmp(Players[i]->name, &parms[1])){
11882 					msg_format(Ind,"%s is currently playing",&parms[1]);
11883 					return(FALSE);
11884 				}
11885 			}
11886 			player_edit(&parms[1]);
11887 
11888 			break;
11889 		case 'A':	/* acquirement */
11890 			Ind2 = name_lookup(Ind, &parms[1], FALSE, FALSE);
11891 			if(Ind2)
11892 			{
11893 				player_type *p_ptr2 = Players[Ind2];
11894 				acquirement(&p_ptr2->wpos, p_ptr2->py, p_ptr2->px, 1, TRUE, TRUE, make_resf(p_ptr2));
11895 				msg_format(Ind, "%s is granted an item.", p_ptr2->name);
11896 				msg_print(Ind2, "You feel a divine favor!");
11897 				return(FALSE);
11898 			}
11899 //			msg_print(Ind, "That player is not in the game.");
11900 			break;
11901 		case 'k':	/* admin wrath (preceed name with '!' for no-ghost kill */
11902 			i = 1;
11903 			if (parms[1] == '!') i = 2;
11904 			Ind2 = name_lookup(Ind, &parms[i], FALSE, FALSE);
11905 			if (Ind2) {
11906 				q_ptr = Players[Ind2];
11907 				msg_print(Ind2, "\377rYou are hit by a bolt from the blue!");
11908 				strcpy(q_ptr->died_from,"divine wrath");
11909 				if (i == 2) q_ptr->global_event_temp |= PEVF_NOGHOST_00; //hack: no-ghost death
11910 				q_ptr->deathblow = 0;
11911 				player_death(Ind2);
11912 				return(TRUE);
11913 			}
11914 //			msg_print(Ind, "That player is not in the game.");
11915 
11916 			break;
11917 		case 'S':	/* Static a regular */
11918 			stat_player(&parms[1], TRUE);
11919 			break;
11920 		case 'U':	/* Unstatic him */
11921 			stat_player(&parms[1], FALSE);
11922 			break;
11923 		case 't':	/* DM telekinesis */
11924 			/* I needed this before - it is useful */
11925 			/* Unfortunately the current telekinesis */
11926 			/* is not compatible with it, and I do not */
11927 			/* want to combine it while there is a */
11928 			/* potential bug. */
11929 			break;
11930 		case 'B':
11931 			/* This could be fun - be wise dungeon master */
11932 			sprintf(buf, "\375\377r[\377%c%s\377r]\377%c %s", 'b', p_ptr->name, COLOUR_CHAT, &parms[1]); /* admin colour 'b' */
11933 			censor_length = 0;
11934 			msg_broadcast_format(0, buf);
11935 #ifdef TOMENET_WORLDS
11936 			if (cfg.worldd_broadcast) world_chat(0, buf);
11937 #endif
11938 			break;
11939 		case 'r':	/* FULL ACCOUNT SCAN + RM */
11940 			/* Delete a player from the database/savefile */
11941 			d_acc = GetAccount(&parms[1], NULL, FALSE);
11942 			if (d_acc != (struct account*)NULL) {
11943 				char name[80];
11944 				n = player_id_list(&id_list, d_acc->id);
11945 				for(i = 0; i < n; i++) {
11946 					strcpy(name, lookup_player_name(id_list[i]));
11947 					msg_format(Ind, "\377oDeleting %s", name);
11948 					delete_player_id(id_list[i]);
11949 					sf_delete(name);
11950 				}
11951 				if (n) C_KILL(id_list, n, int);
11952 				d_acc->flags |= ACC_DELD;
11953 				/* stamp in the deleted account */
11954 				WriteAccount(d_acc, FALSE);
11955 				KILL(d_acc, struct account);
11956 			}
11957 			else
11958 				msg_print(Ind, "\377rCould not find account");
11959 			break;
11960 	}
11961 	return(FALSE);
11962 }
11963 
11964 static vault_type *get_vault(char *name)
11965 {
11966 	int i;
11967 
11968 	for (i = 0; i < MAX_V_IDX; i++) {
11969 		if (strstr(v_name + v_info[i].name, name))
11970 			return &v_info[i];
11971 	}
11972 
11973 	return NULL;
11974 }
11975 
11976 /* Generate something */
11977 bool master_generate(int Ind, char * parms)
11978 {
11979 	/* get the player pointer */
11980 	player_type *p_ptr = Players[Ind];
11981 
11982 	if (!is_admin(p_ptr)) return FALSE;
11983 
11984 	switch (parms[0])
11985 	{
11986 		/* generate a vault */
11987 		case 'v':
11988 		{
11989 			vault_type *v_ptr = NULL;
11990 
11991 			switch(parms[1])
11992 			{
11993 				case '#':
11994 					v_ptr = &v_info[parms[2] + 127];
11995 					break;
11996 				case 'n':
11997 					v_ptr = get_vault(&parms[2]);
11998 			}
11999 
12000 			if(!v_ptr || !v_ptr->wid) return FALSE;
12001 
12002 //			build_vault(&p_ptr->wpos, p_ptr->py, p_ptr->px, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
12003 			build_vault(&p_ptr->wpos, p_ptr->py, p_ptr->px, v_ptr, p_ptr);
12004 
12005 			break;
12006 		}
12007 	}
12008 	return TRUE;
12009 }
12010 
12011 #if 0 /* some new esp link stuff - mikaelh */
12012 bool establish_esp_link(int Ind, int Ind2, byte type, u16b flags, u16b end)
12013 {
12014 	player_type *p_ptr, *p2_ptr;
12015 	esp_link_type *esp_ptr;
12016 
12017 	p_ptr = Players[Ind];
12018 	p2_ptr = Players[Ind2];
12019 	if (!p2_ptr) return;
12020 
12021 	esp_ptr = check_esp_link(Ind, Ind2);
12022 	if (esp_ptr) {
12023 		if (esp_ptr->type == type) {
12024 			/* compatible ESP link already exists, add flags */
12025 			esp_ptr->flags |= flags;
12026 			esp_ptr->end = end;
12027 		}
12028 		else return FALSE;
12029 	}
12030 	else {
12031 		MAKE(esp_ptr, esp_link_type);
12032 
12033 		esp_ptr->id = p2_ptr->id;
12034 		esp_ptr->type = type;
12035 		esp_ptr->flags = flags;
12036 		esp_ptr->end = end;
12037 
12038 		if (!(esp_ptr->flags & LINKF_HIDDEN))
12039 		{
12040 			msg_format(Ind, "\377oYou establish a mind link with %s.", p2_ptr->name);
12041 			msg_format(Ind, "\377o%s has established a mind link with you.", p_ptr->name);
12042 		}
12043 
12044 		esp_ptr->next = p_ptr->esp_link;
12045 		p_ptr->esp_link = esp_ptr;
12046 	}
12047 
12048 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12049 	p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12050 	p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12051 	p2_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12052 	p2_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12053 	p2_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12054 
12055 	return TRUE;
12056 }
12057 
12058 void break_esp_link(int Ind, int Ind2)
12059 {
12060 	player_type *p_ptr, *p2_ptr;
12061 	esp_link_type *esp_ptr, *pest_link;
12062 
12063 	p_ptr = Players[Ind];
12064 	p2_ptr = Players[Ind2];
12065 	if (!p2_ptr) return;
12066 
12067 	pesp_ptr = NULL;
12068 	esp_ptr = p_ptr->esp_link;
12069 	while (esp_ptr)
12070 	{
12071 		if (esp_ptr->id == p2_ptr->id)
12072 		{
12073 			if (!(esp_ptr->flags & LINKF_HIDDEN)) {
12074 				msg_format(Ind, "\377RYou break the mind link with %s.", p2_ptr->name);
12075 				msg_format(Ind2, "\377R%s breaks the mind link with you.", p_ptr->name);
12076 			}
12077 
12078 			if (pesp_ptr)
12079 			{
12080 				pest_ptr->next = esp_ptr->next;
12081 			}
12082 			else
12083 			{
12084 				p_ptr->esp_link = esp_ptr->next;
12085 			}
12086 			KILL(esp_ptr, esp_link_type);
12087 
12088 			p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12089 			p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12090 			p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12091 			p2_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12092 			p2_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12093 			p2_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12094 		}
12095 		pesp_ptr = esp_ptr;
12096 		esp_ptr = esp_ptr->next;
12097 	}
12098 }
12099 
12100 esp_link_type *check_esp_link(ind Ind, int Ind2)
12101 {
12102 	player_type *p_ptr, *p2_ptr;
12103 	esp_link_type *esp_ptr;
12104 
12105 	p_ptr = Players[Ind];
12106 	p2_ptr = Players[Ind2];
12107 	if (!p2_ptr) return NULL;
12108 
12109 	esp_ptr = p_ptr->esp_link;
12110 	while (esp_ptr)
12111 	{
12112 		if (esp_ptr->id == p2_ptr->id) return esp_ptr;
12113 		esp_ptr = esp_ptr->next;
12114 	}
12115 	return NULL;
12116 }
12117 
12118 bool check_esp_link_type(int Ind, int Ind2, u16b flags)
12119 {
12120 	esp_link_type* esp_ptr;
12121 	esp_ptr = check_esp_link(Ind, Ind2);
12122 
12123 	if (esp_ptr && esp_ptr->flags & flags) return TRUE;
12124 	else return FALSE;
12125 }
12126 #endif
12127 
12128 void toggle_aura(int Ind, int aura) {
12129 	char buf[80];
12130 	Players[Ind]->aura[aura] = !Players[Ind]->aura[aura];
12131 	strcpy(buf, "\377sYour ");
12132 	switch (aura) { /* up to MAX_AURAS */
12133 	case 0: strcat(buf, "aura of fear"); break;
12134 	case 1: strcat(buf, "shivering aura"); break;
12135 	case 2: strcat(buf, "aura of death"); break;
12136 	}
12137 	strcat(buf, " is now ");
12138 	if (Players[Ind]->aura[aura]) strcat(buf, "unleashed"); else strcat(buf, "suppressed");
12139 	strcat(buf, "!");
12140 	msg_print(Ind, buf);
12141 }
12142 
12143 void check_aura(int Ind, int aura) {
12144 	char buf[80];
12145 	strcpy(buf, "\377sYour ");
12146 	switch (aura) { /* up to MAX_AURAS */
12147 	case 0: strcat(buf, "aura of fear"); break;
12148 	case 1: strcat(buf, "shivering aura"); break;
12149 	case 2: strcat(buf, "aura of death"); break;
12150 	}
12151 	strcat(buf, " is currently ");
12152 	if (Players[Ind]->aura[aura]) strcat(buf, "unleashed"); else strcat(buf, "suppressed");
12153 	strcat(buf, ".");
12154 	msg_print(Ind, buf);
12155 }
12156 
12157 /* determine minimum dungeon level required for a player of a particular
12158    character level to obtain optimum experience. */
12159 int det_req_level(int plev) {
12160 	if (plev < 20) return (0);
12161         else if (plev < 30) return (375 / (45 - plev));
12162         else if (plev < 50) return (650 / (56 - plev));
12163         else if (plev < 65) return (plev * 2);
12164         else if (plev < 75) return ((plev - 65) * 4 + 130);
12165         else return ((plev - 75) + 170);
12166 }
12167 /* calculate actual experience gain based on det_req_level */
12168 s64b det_exp_level(s64b exp, int plev, int dlev) {
12169 	int req_dlvl = det_req_level(plev);
12170 
12171 	if (dlev < req_dlvl - 5) return 0; /* actually give zero exp for 'grey' levels? */
12172 	if (dlev < req_dlvl) return ((exp * 2) / (2 + req_dlvl - dlev)); /* give reduced exp for 'yellow' levels */
12173 	return (exp); /* normal exp */
12174 }
12175