1 /* $Id$ */
2 /* File: spells2.c */
3 
4 /* Purpose: Spell code (part 2) */
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 #include "angband.h"
16 
17 /*
18  * A warlock could easily beat the game by scumming & genociding vaults;
19  * Here're some codes against this method.		- Jir -
20  *
21  * Note also that some vaults/quests will be genocide-resistant.
22  */
23 /*
24  * (Mass) Genocide spell being way too powerful, the caster's HP is halved
25  * if this option is set.
26  */
27 #define SEVERE_GENO
28 /*
29  * Geno won't work if inside a vault(icky).
30  * Strongly recommended.
31  */
32 #define NO_GENO_ON_ICKY
33 /*
34  * Each monster has (level) in RESIST_GENO chance of surviving this.
35  */
36 #define RESIST_GENO 250
37 
38 /*
39  * 'Trap detection' is way too powerful traps and 'searching' ability
40  * are almost meanless; if this flag is defined, the spell can only
41  * detect some of the traps depending on the player level.
42  */
43 //#define TRAP_DETECTION_FAILURE /* appearently unused */
44 
45 /* for PVP mode diminishing healing calc - C. Blue */
46 //#define PVP_DIMINISHING_HEALING_CAP(p) (3 * ((p)->mhp + (p)->lev * 6)) /* unfair for non-mimics */
47 #define PVP_DIMINISHING_HEALING_CAP(p) (((p)->lev + 5) * ((p)->lev + 5)) /* 10: 225, 20: 625, 30: 1225 */
48 
49 /* Give 'absence' messages for detection magic?
50    This would need magic devices causing these to get identified, since we
51    can read what they supposedly do. */
52 //#define DETECT_ABSENCE
53 
54 /* Helper function to educe spell damage by 50% while in wraithform.
55  *  Some spells must be excempt, because their 'dam'
56  * actually stores their functionality. - C. Blue
57  */
proj_dam_wraith(int typ,int * dam)58 static void proj_dam_wraith(int typ, int *dam) {
59 
60 	switch (typ) {
61 	case GF_RECALL_PLAYER: /* <- dam is timeout! */
62 	case GF_RESTORE_PLAYER:
63 	case GF_CURE_PLAYER:
64 	case GF_CURING:
65 		return;
66 	case GF_HEAL_PLAYER:
67 		*dam = (*dam & 0x3C00) + (*dam & 0x03FF) / 2;
68 		return;
69 	case GF_OLD_DRAIN:
70 		/* - sorry, 9999 is the priest spell hack :P */
71 		if (*dam == 9999) return;
72 	default:
73 		*dam /= 2;
74 	}
75 }
76 
77 #ifdef ENABLE_MAIA
78 /*
79  * For angelic beings, this spell will gather any party
80  * members on the same level to him/herself. This also
81  * tele_to's all monsters in LOS.
82  * For demonic beings, do a dispel on LOS.
83  */
divine_vengeance(int Ind,int power)84 void divine_vengeance(int Ind, int power) {
85 	player_type *p_ptr = Players[Ind];
86 	bool summon = !istownarea(&p_ptr->wpos, MAX_TOWNAREA);
87 
88 	if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
89 		int i;
90 		/* players TELE_TO */
91 		if (p_ptr->party == 0) {
92 			msg_print(Ind, "You can only teleport to party members.");
93 		} else {
94 			fire_ball(Ind, GF_KILL_GLYPH, 0, 0, 2, "");
95 			for (i = 1; i <= NumPlayers; i++) {
96 				/* Skip self */
97 				if (i == Ind) continue;
98 
99 				player_type *q_ptr = Players[i];
100 
101 				/* Skip disconnected players */
102 				if (q_ptr->conn == NOT_CONNECTED) continue;
103 
104 				/* Skip players not on this depth */
105 				if (!inarea(&q_ptr->wpos, &p_ptr->wpos)) continue;
106 
107 				/* Skip DM if not DM himself */
108 				if (q_ptr->admin_dm && !p_ptr->admin_dm) continue;
109 
110 				/* Skip players who haven't opened their mind */
111 				if (!(q_ptr->esp_link_flags & LINKF_OPEN)) continue;
112 
113 				/* Skip players not in the same party */
114 				if (q_ptr->party == 0 || p_ptr->party == 0) continue;
115 				if (p_ptr->party != q_ptr->party) continue;
116 
117 				/* Have a present from the nether world for each player you teleport! */
118 				if (summon) summon_specific(&p_ptr->wpos, p_ptr->py, p_ptr->px, getlevel(&p_ptr->wpos), 100, SUMMON_MONSTER, 0, cfg.clone_summoning);
119 
120 				teleport_player_to(i, p_ptr->py, p_ptr->px);
121 			}
122 		}
123 		/* monsters TELE_TO */
124 		project_los(Ind, GF_TELE_TO, 0, " commands return");
125 	} else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
126 		dispel_monsters(Ind, power);
127 	//	project_los(Ind, GF_DISP_ALL, power, " commands leave");
128 	}
129 }
130 
131 /* A: fury
132  * D: +hp (does not stack with +LIFE)
133  */
divine_empowerment(int Ind,int level)134 void divine_empowerment(int Ind, int level) {
135 	player_type *p_ptr = Players[Ind];
136 	if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
137 		set_fury(Ind, 20 + level / 10);
138 	} else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
139 		int bonus = 0;
140 		if (level >= 55) {
141 			bonus = 3;
142 		} else if (level >= 52) {
143 			bonus = 2;
144 		} else if (level >= 40) {
145 			bonus = 1;
146 		}
147 		(void)do_divine_hp(Ind, (level * 3) / 2, bonus);
148 	}
149 	return;
150 }
151 
152 /* A: aoe slow, time/mana res
153  * D: +crit
154  */
divine_intensify(int Ind,int level)155 void divine_intensify(int Ind, int level) {
156 	player_type *p_ptr = Players[Ind];
157 	if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
158 		//aoe divine_xtra_res_time
159 		project_los(Ind, GF_OLD_SLOW, level * 3, "");
160 		(void)do_divine_xtra_res_time(Ind, (level * 3) / 2);
161 		return;
162 	} else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
163 		int bonus = 2 + ((level - 45) / 5) * 2;
164 		(void)do_divine_crit(Ind, (level * 3) / 2, bonus);
165 	}
166 }
167 
py_create_gateway(int Ind)168 int py_create_gateway(int Ind) {
169 	player_type *p_ptr = Players[Ind];
170 	struct worldpos *wpos = &(p_ptr->wpos);
171 	cave_type **zcave;
172 	struct dun_level *l_ptr = getfloor(wpos);
173 
174 	if (!wpos->wz || !(zcave = getcave(wpos)) || !cave_clean_bold(zcave, p_ptr->py, p_ptr->px)) {
175 		msg_format(Ind, "\377wThis spell has no effect here.");
176 		return 0;
177 	}
178 
179 	if ((l_ptr->flags1 & LF1_CUSTOM_GATEWAY)) {
180 		msg_print(Ind, "\377yThe presence of another active gateway spell is disturbing your attempt.");
181 		return 0;
182 	}
183 
184 	if (p_ptr->voidx && p_ptr->voidy) {
185 		if (place_between_targetted(wpos, p_ptr->py, p_ptr->px, p_ptr->voidy, p_ptr->voidx)) {
186 			//TODO: jumpgate limit? Using level flag for this here:
187 			l_ptr->flags1 |= LF1_CUSTOM_GATEWAY;
188 
189 			//When successfull, we clear state, so we can create more.
190 			p_ptr->voidx = 0;
191 			p_ptr->voidy = 0;
192 
193 			p_ptr->redraw |= (PR_MAP);
194 			msg_format(Ind, "\377vYou successfully create a gateway between the two points!");
195 			msg_format_near(Ind, "\377v%s has successfully created a gateway!", p_ptr->name);
196 		}
197 		/* completed the spell successfully */
198 		return 2;
199 	}
200 
201 	// Let's not have this in towns/houses; OK everywhere else
202 	if (!allow_terraforming(wpos, FEAT_TREE)) return 0;
203 
204 	msg_format(Ind, "\377vYou set your mind to create a gateway here.");
205 
206 	p_ptr->voidx = p_ptr->px;
207 	p_ptr->voidy = p_ptr->py;
208 
209 	place_between_dummy(wpos, p_ptr->py, p_ptr->px);
210 	return 1;
211 }
212 /* A: instant wor for every party member on level. INCLUDING town recalls?
213  *    /rec 32 32 -> will attempt to teleport party members to Bree.
214  * further note: hm, this could fatally disturb idle party members. also dangerous if all party teleports into a D pit!!. make this only active if player (and therefore interested party members) are not in town.
215  * D: void jumpgate creation
216  */
divine_gateway(int Ind)217 void divine_gateway(int Ind) {
218 	player_type *p_ptr = Players[Ind];
219 	if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
220 
221 		//XXX call set_recall ?
222 		if (istown(&p_ptr->wpos) || !p_ptr->wpos.wz) {
223 			msg_format(Ind, "\377wThis spell has no effect here.");
224 			return;
225 		}
226 
227 		// Send some audio feedback
228 		Send_beep(Ind);
229 
230 		set_recall_timer(Ind, 1);
231 
232 		int i;
233 		for (i = 1; i <= NumPlayers; i++) {
234                         if (i == Ind) continue;
235                         if (Players[i]->conn == NOT_CONNECTED) continue;
236 
237                         /* on the same dungeon floor */
238                         if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
239 
240                         /* must be in the same party */
241                         if (!Players[i]->party || p_ptr->party != Players[i]->party) continue;
242 
243 			set_recall_timer(i, 1);
244 		}
245 	} else if (p_ptr->ptrait == TRAIT_CORRUPTED)
246 		(void)py_create_gateway(Ind);
247 }
248 
249 #else /*lol, shared .pkg*/
divine_vengeance(int Ind,int power)250 void divine_vengeance(int Ind, int power) {
251 	return;
252 }
divine_empowerment(int Ind,int power)253 void divine_empowerment(int Ind, int power) {
254 	return;
255 }
divine_intensify(int Ind,int power)256 void divine_intensify(int Ind, int power) {
257 	return;
258 }
divine_gateway(int Ind)259 void divine_gateway(int Ind) {
260 	return;
261 }
262 #endif
263 
264 
265 /* for mindcrafters: teleport to friendly player with open mind - C. Blue */
do_autokinesis_to(int Ind,int dis)266 void do_autokinesis_to(int Ind, int dis) {
267 	player_type *p_ptr = Players[Ind], *q_ptr;
268 	int i;
269 
270 	if (p_ptr->party == 0) {
271 		msg_print(Ind, "You can only teleport to party members.");
272 		return;
273 	}
274 
275 	for (i = 1; i <= NumPlayers; i++) {
276 		/* Skip self */
277 		if (i == Ind) continue;
278 		q_ptr = Players[i];
279 		/* Skip disconnected players */
280 		if (q_ptr->conn == NOT_CONNECTED) continue;
281 		/* Skip DM if not DM himself */
282 		if (q_ptr->admin_dm && !p_ptr->admin_dm) continue;
283 		/* Skip ghosts */
284 		if (q_ptr->ghost && !q_ptr->admin_dm) continue;
285 		/* Skip players not on this depth */
286 		if (!inarea(&q_ptr->wpos, &p_ptr->wpos)) continue;
287 		/* Skip players not in the same party */
288 		if (q_ptr->party == 0 || p_ptr->party != q_ptr->party) continue;
289 		/* Skip players who haven't opened their mind */
290 		if (!(q_ptr->esp_link_flags & LINKF_OPEN)) continue;
291 		/* Skip targets too far away */
292 		if (distance(p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px) > dis) continue;
293 
294 		/* success */
295 		msg_print(Ind, "You reach an allied mind!");
296 		teleport_player_to(Ind, q_ptr->py, q_ptr->px);
297 		return;
298 	}
299 
300 	/* fail */
301 	msg_print(Ind, "You couldn't make out any destination within your mental reach.");
302 }
303 
304 /*
305  * Grow trees
306  */
grow_trees(int Ind,int rad)307 void grow_trees(int Ind, int rad)
308 {
309 	player_type *p_ptr = Players[Ind];
310 	int a, i, j;
311 
312 	if (!allow_terraforming(&p_ptr->wpos, FEAT_TREE)) return;
313 
314 #ifdef USE_SOUND_2010
315         sound(Ind, "grow_trees", NULL, SFX_TYPE_COMMAND, FALSE);
316 #endif
317 
318 	for (a = 0; a < rad * rad + 11; a++) {
319                 cave_type **zcave = getcave(&p_ptr->wpos);
320 
321 		i = (rand_int((rad * 2) + 1) - rad + rand_int((rad * 2) + 1) - rad) / 2;
322 		j = (rand_int((rad * 2) + 1) - rad + rand_int((rad * 2) + 1) - rad) / 2;
323 
324 		if (!in_bounds2(&p_ptr->wpos, p_ptr->py + j, p_ptr->px + i)) continue;
325 		if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
326 
327 		if (cave_naked_bold(zcave, p_ptr->py + j, p_ptr->px + i) &&
328 		    (zcave[p_ptr->py + j][p_ptr->px + i].feat != FEAT_HOME_OPEN)) /* HACK - not on open house door - mikaelh */
329 		{
330 			cave_set_feat_live(&p_ptr->wpos, p_ptr->py + j, p_ptr->px + i, magik(50)?FEAT_TREE:FEAT_BUSH);
331 		}
332 	}
333 }
334 
335 /*
336  * Garden of the Gods handler :-)
337  * Basically go through each wall tile in dungeon. For each one, there is a chance% of it
338  * getting turned into a tree. - the_sandman
339  */
create_garden(int Ind,int chance)340 bool create_garden(int Ind, int chance) {
341 	int y, x;
342 	player_type *p_ptr;	//Who(and where)?
343         cave_type *c_ptr;
344 	p_ptr = Players[Ind];
345 
346         struct c_special *cs_ptr;       /* for special key doors */
347 	struct worldpos *wpos = &(p_ptr->wpos);
348 
349         cave_type **zcave;
350         if(!(zcave = getcave(wpos))) return (FALSE);
351 
352 	if (!allow_terraforming(wpos, FEAT_TREE)) return(FALSE);
353 
354 	for (y = 0; y < MAX_HGT; y++) {
355 		for (x = 0; x < MAX_WID; x++) {
356 			if (!in_bounds(y, x)) continue;
357 
358 			c_ptr = &zcave[y][x];
359 
360 			/*
361 			 * Never transform vaults (altough it would create some potentially
362 			 * nasty effects >;) Imagine all those Z seeping out to get you...
363 			 */
364 			if (c_ptr->info & CAVE_ICKY) continue;
365 
366 			if((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
367 
368 			if (cave_valid_bold(zcave, y, x) && ( /* <- destroyable, no art on grid, not FF1_PERMANENT */
369 //				(c_ptr->feat == FEAT_QUARTZ) ||
370 //				(c_ptr->feat == FEAT_MAGMA) ||
371 //				(c_ptr->feat == FEAT_QUARTZ_H) ||
372 //				(c_ptr->feat == FEAT_QUARTZ_K) ||
373 //				(c_ptr->feat == FEAT_MAGMA_K) ||
374 //				(c_ptr->feat == FEAT_SAND_WALL) ||
375 //				(c_ptr->feat == FEAT_SAND_WALL_H) ||
376 //				(c_ptr->feat == FEAT_SAND_WALL_K) ||
377 //				(c_ptr->feat == FEAT_ICE_WALL) ||
378 //				(c_ptr->feat == FEAT_GLASS_WALL) ||
379 //				(c_ptr->feat == FEAT_ILLUS_WALL) ||
380 				(c_ptr->feat == FEAT_WALL_EXTRA) || /* granite walls: */
381 				(c_ptr->feat == FEAT_WALL_INNER) ||
382 				(c_ptr->feat == FEAT_WALL_OUTER) ||
383 				(c_ptr->feat == FEAT_WALL_SOLID))
384 //				&& !cave_floor_bold(zcave, y, x) /* don't convert empty floor! */
385 //				&& !(f_info[c_ptr->feat].flags1 & FF1_PERMANENT)
386 			    )
387             		{
388 				if (randint(100) < chance) {
389 					/* Delete the object (if any) */
390 					delete_object(wpos, y, x, TRUE);
391 					cave_set_feat_live(&p_ptr->wpos, y, x, magik(50)?FEAT_TREE:FEAT_BUSH);
392 					//c_ptr->feat = feat;
393 				}
394 			}
395 		} //width
396 	} //height
397 
398 	/* Message */
399 	msg_print(Ind, "You see raw power escaping from the rocks!");
400 	msg_print_near(Ind, "You see raw power escaping from the rocks!");
401 	return (TRUE);
402 }//garden
403 
404 /*
405  * this will now add to both melee and ranged toHit instead at a rate of
406  * spell_lvl/2
407  * Yep. More druidry. - the_sandman
408  */
do_focus_shot(int Ind,int v,int p)409 bool do_focus_shot(int Ind, int v, int p) {
410     player_type *p_ptr = Players[Ind];
411     bool notice = FALSE;
412 
413     /* Hack -- Force good values */
414     v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
415 
416     /* Open */
417     if (v)
418     {
419             if (!p_ptr->focus_time)
420             {
421                     msg_format_near(Ind, "%s's arm movements turn blurry!", p_ptr->name);
422                     msg_print(Ind, "Your arms feel... dexterous!");
423                     notice = TRUE;
424             }
425             p_ptr->focus_time = v;
426             p_ptr->focus_val = p;
427             calc_boni(Ind);
428     }
429 
430     /* Shut */
431     else
432     {
433             if (p_ptr->focus_time)
434             {
435                     msg_format_near(Ind, "You can see %s's arms again.", p_ptr->name);
436                     msg_print(Ind, "Your feel your arms turn into lead.");
437                     notice = TRUE;
438                     p_ptr->focus_time = 0;
439             }
440             p_ptr->focus_val = 0;
441     }
442 
443 #if 0
444 //Buggy with another set_fast
445 	/* Decrease speed */
446 	if (p_ptr->focus_time != 0) set_fast(Ind, v, -(p/5));
447 #endif
448 
449     /* Nothing to notice */
450     if (!notice) return (FALSE);
451 
452     /* Disturb */
453     if (p_ptr->disturb_state) disturb(Ind, 0, 0);
454 
455     /* Recalculate bonuses */
456     p_ptr->update |= (PU_BONUS);
457 
458     /* Handle stuff */
459     handle_stuff(Ind);
460 
461     /* Result */
462     return (TRUE);
463 }//focus shot
464 
465 /*
466  * Extra stats! By how much depends on the player's level.
467  * At the moment it is +1 for every 7.
468  * Druidry. - the_sandman
469  */
do_xtra_stats(int Ind,int v,int p)470 bool do_xtra_stats(int Ind, int v, int p) {
471         player_type *p_ptr = Players[Ind];
472         bool notice = (FALSE);
473 
474         /* Hack -- Force good values */
475         v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
476 
477         /* Open */
478         if (v) {
479                 if (!p_ptr->xtrastat || p_ptr->statval < p) {
480                         msg_format_near(Ind, "%s seems to be more powerful!", p_ptr->name);
481                         msg_print(Ind, "You feel... powerful!");
482 
483 			p_ptr->xstr = 0;
484 			p_ptr->xint = 0;
485 			p_ptr->xdex = 0;
486 			p_ptr->xcon = 0;
487 
488 			p_ptr->statval = p;
489 			p = (p / 10) + 2;
490 			switch (p_ptr->statval / 5) {
491 				default: p_ptr->xint = p;
492 				case 3:
493 				case 2: p_ptr->xcon = p;
494 				case 1: p_ptr->xdex = p;
495 				case 0: p_ptr->xstr = p;
496 			}
497 
498                         notice = TRUE;
499                 }
500         }
501 
502         /* Shut */
503         else {	//v = 0;
504                 if (p_ptr->xtrastat) {
505                         msg_format_near(Ind, "%s returns to %s normal self.", p_ptr->name, (p_ptr->male? "his" : "her"));
506                         msg_print(Ind, "You somehow feel weak.");
507 
508 			p_ptr->xtrastat = 0;
509 			p_ptr->statval = 0;
510 
511                         notice = TRUE;
512                 }
513         }
514 
515         p_ptr->xtrastat = v;
516 
517         /* Nothing to notice */
518         if (!notice) return (FALSE);
519 
520         /* Disturb */
521         if (p_ptr->disturb_state) disturb(Ind, 0, 0);
522 
523         /* Recalculate bonuses */
524         p_ptr->update |= (PU_BONUS);
525 
526         /* Handle stuff */
527         handle_stuff(Ind);
528 
529         /* Result */
530         return (TRUE);
531 }//xtra stats
532 
533 /*
534  * The last spell to be added for tonight!
535  * "Banish" animals... Killing them, really. - the_sandman
536  */
do_banish_animals(int Ind,int chance)537 bool do_banish_animals(int Ind, int chance) {
538 	int i, j = 0, c;
539 	player_type *p_ptr;
540 	p_ptr = Players[Ind];
541 	cave_type **zcave;
542 	dun_level *l_ptr;
543 	struct worldpos *wpos = &p_ptr->wpos;
544 
545 	if (Ind < 0 || chance <= 0) return (FALSE);
546 	if (!(zcave = getcave(wpos))) return(FALSE);
547 	if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
548 
549 	for (i = 1; i < m_max; i++) {
550 		monster_type *m_ptr = &m_list[i];
551 		monster_race *r_ptr = race_inf(m_ptr);
552 		if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
553 		if (!(r_ptr->flags3 & RF3_ANIMAL)) continue;
554 		if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
555 		//if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
556 		if (!inarea(&m_ptr->wpos, wpos)) continue;
557 
558 		/* Taken from genocide_aux(): Not valid inside a vault */
559 		if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
560 
561 		c = chance - r_ptr->level;
562 		if (c <= 0) continue;
563 		if (c > rand_int(100)) {
564 			//off with you!
565 			delete_monster_idx(i, TRUE);
566 			j++;
567 		}
568 	}
569 	if (j < 5) {
570 		msg_print(Ind, "\337gA few here long for their gardens.");
571 		msg_format_near(Ind, "\337g%s tries hard but alas can only convert a few animals.", p_ptr->name);
572 	} else if (j < 10) {
573 		msg_print(Ind, "\337gA handful here longs for their gardens.");
574 		msg_format_near(Ind, "\337g%s tries hard but alas can only convert a handful of animals.", p_ptr->name);
575 	} else if (j < 20) {
576 		msg_print(Ind, "\337gA pack here abandoned evil to retire in their gardens.");
577 		msg_format_near(Ind, "\337g%s tries hard and you notice animals going away.", p_ptr->name);
578 	} else if (j < 50) {
579 		msg_print(Ind, "\337gIt's a near-miracle!");
580 		msg_format_near(Ind, "\337g%s banishes animals with conviction.", p_ptr->name);
581 	} else {
582 		msg_print(Ind, "\337gThe Day of Returning is here!.");
583 		/* lol */
584 		msg_format_near(Ind, "\337gYou see %s's tears of joy at the number of returning animals.", p_ptr->name);
585 	}
586 	return (TRUE);
587 }
588 
589 /* For Dawn activation - C. Blue
590    (note: highest non-unique undead is Black Reaver: level 74) */
do_banish_undead(int Ind,int chance)591 bool do_banish_undead(int Ind, int chance) {
592 	int i, j = 0, c;
593 	player_type *p_ptr;
594 	p_ptr = Players[Ind];
595 	cave_type **zcave;
596 	dun_level *l_ptr;
597 	struct worldpos *wpos = &p_ptr->wpos;
598 
599 	if (Ind < 0 || chance <= 0) return (FALSE);
600 	if (!(zcave = getcave(wpos))) return(FALSE);
601 	if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
602 
603 	for (i = 1; i < m_max; i++) {
604 		monster_type *m_ptr = &m_list[i];
605 		monster_race *r_ptr = race_inf(m_ptr);
606 		if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
607 		if (!(r_ptr->flags3 & RF3_UNDEAD)) continue;
608 		if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
609 		//if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
610 		if (!inarea(&m_ptr->wpos, wpos)) continue;
611 
612 		/* Taken from genocide_aux(): Not valid inside a vault */
613 		if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
614 
615 		c = chance - r_ptr->level;
616 		if (c <= 0) continue;
617 		if (c > rand_int(100)) {
618 			//off with you!
619 			delete_monster_idx(i, TRUE);
620 			j++;
621 		}
622 	}
623 	/* (no time for tears of joy dealing with undead) */
624 	return (TRUE);
625 }
626 
627 /* For Mardra activation - C. Blue
628    (note: highest non-unique D is GWoP: level 85) */
do_banish_dragons(int Ind,int chance)629 bool do_banish_dragons(int Ind, int chance) {
630 	int i, j = 0, c;
631 	player_type *p_ptr;
632 	p_ptr = Players[Ind];
633 	cave_type **zcave;
634 	dun_level *l_ptr;
635 	struct worldpos *wpos = &p_ptr->wpos;
636 
637 	if (Ind < 0 || chance <= 0) return (FALSE);
638 	if (!(zcave = getcave(wpos))) return(FALSE);
639 	if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
640 
641 	for (i = 1; i < m_max; i++) {
642 		monster_type *m_ptr = &m_list[i];
643 		monster_race *r_ptr = race_inf(m_ptr);
644 		if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
645 		if (!(r_ptr->flags3 & RF3_DRAGON)) continue;
646 		if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
647 		//if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
648 		if (!inarea(&m_ptr->wpos, wpos)) continue;
649 
650 		/* Taken from genocide_aux(): Not valid inside a vault */
651 		if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
652 
653 		c = chance - r_ptr->level;
654 		if (c <= 0) continue;
655 		if (c > rand_int(100)) {
656 			//off with you!
657 			delete_monster_idx(i, TRUE);
658 			j++;
659 		}
660 	}
661 	/* (no time for tears of joy dealing with undead) */
662 	return (TRUE);
663 }
664 
665 /*
666  * Increase players hit points, notice effects, and tell the player about it.
667  */
hp_player(int Ind,int num)668 bool hp_player(int Ind, int num) {
669 	player_type *p_ptr = Players[Ind];
670 
671 	// The "number" that the character is displayed as before healing
672 	int old_num, new_num;
673 	long eff_num; /* actual amount of HP gain */
674 	long e = PVP_DIMINISHING_HEALING_CAP(p_ptr);
675 
676 	if (p_ptr->no_heal) return FALSE;
677 
678 	p_ptr->test_heal += num;
679 
680 	// The "number" that the character is displayed as before healing
681 	old_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
682 	if (old_num >= 7) old_num = 10;
683 
684 	/* player can't be healed while burning in the holy fire of martyrium */
685 	if (p_ptr->martyr && !bypass_invuln) return(FALSE);
686 
687 	/* Hell mode is .. hard */
688 	if ((p_ptr->mode & MODE_HARD) && (num > 3)) num = num * 3 / 4;
689 
690 	eff_num = (p_ptr->mhp - p_ptr->chp < num) ? (p_ptr->mhp - p_ptr->chp) : num;
691 
692 	/* PVP mode uses diminishing healing - C. Blue */
693 	if (p_ptr->mode & MODE_PVP) {
694 		eff_num = eff_num * (p_ptr->heal_effect < e ? 100 :
695 				    ((e * 100) / ((p_ptr->heal_effect - (e * 2) / 3) * 3)));
696 		eff_num /= 100;
697 	}
698 
699 	if (!eff_num) return(FALSE);
700 
701 	if (p_ptr->chp < p_ptr->mhp) {
702 		/* data collection for PVP mode: weaken continous healing over time to prevent silliness (who stacks more pots) - C. Blue */
703 		p_ptr->heal_effect += eff_num;
704 
705 		/* data collection for C_BLUE_AI: add up healing happening during current turn */
706 		p_ptr->heal_turn[0] += eff_num;
707 
708 		/* refill HP, note that we can't use eff_num here due to chp_frac check */
709 		num = eff_num;
710 		p_ptr->chp += num;
711 		if (p_ptr->chp > p_ptr->mhp) {
712 			p_ptr->chp = p_ptr->mhp;
713 			p_ptr->chp_frac = 0;
714 		}
715 
716 		/* Update health bars */
717 		update_health(0 - Ind);
718 
719 		/* Redraw */
720 		p_ptr->redraw |= (PR_HP);
721 
722 		/* Figure out of if the player's "number" has changed */
723 		new_num = (p_ptr->chp * 95) / (p_ptr->mhp * 10);
724 		if (new_num >= 7) new_num = 10;
725 
726 		/* If so then refresh everyone's view of this player */
727 		if (new_num != old_num)
728 			everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
729 
730 		/* Window stuff */
731 		p_ptr->window |= (PW_PLAYER);
732 
733 		num = num / 5;
734 		if (num < 3) {
735 			if (num == 0) {
736 				msg_print(Ind, "You feel a little better.");
737 			} else {
738 				msg_print(Ind, "You feel better.");
739 			}
740 		} else {
741 			if (num < 7) {
742 				msg_print(Ind, "You feel much better.");
743 			} else {
744 				msg_print(Ind, "You feel very good.");
745 			}
746 		}
747 
748 		return (TRUE);
749 	}
750 
751 	return (FALSE);
752 }
753 
754 /*
755  * Increase players hit points, notice effects, and don't tell the player it.
756  * 'autoeffect' stands for non-'intended' healing, that applies automatically,
757  * such as necromancy, vampiric items, standard body regeneration;
758  * set 'autoeffect' to TRUE if you want to do forced healing without any
759  * implications.
760  */
hp_player_quiet(int Ind,int num,bool autoeffect)761 bool hp_player_quiet(int Ind, int num, bool autoeffect) {
762 	player_type *p_ptr = Players[Ind];
763 
764 	// The "number" that the character is displayed as before healing
765 	int old_num, new_num;
766 	long eff_num; /* actual amount of HP gain */
767 	long e = PVP_DIMINISHING_HEALING_CAP(p_ptr);
768 
769 	if (p_ptr->no_heal && !autoeffect) return FALSE;
770 
771 	p_ptr->test_heal += num;
772 
773 	old_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
774 	if (old_num >= 7) old_num = 10;
775 
776 	/* player can't be healed while burning in the holy fire of martyrium */
777 	if (p_ptr->martyr && !bypass_invuln) return(FALSE);
778 
779 	/* Hell mode is .. hard */
780 	if ((p_ptr->mode & MODE_HARD) && (num > 3)) num = num * 3 / 4;
781 
782 	eff_num = (p_ptr->mhp - p_ptr->chp < num) ? (p_ptr->mhp - p_ptr->chp) : num;
783 
784 	/* PVP mode uses diminishing healing - C. Blue */
785 	if (!autoeffect && (p_ptr->mode & MODE_PVP)) {
786 		eff_num = eff_num * (p_ptr->heal_effect < e ? 100 :
787 				    ((e * 100) / ((p_ptr->heal_effect - (e * 2) / 3) * 3)));
788 		eff_num /= 100;
789 	}
790 
791 	if (!eff_num) return(FALSE);
792 
793 	if (p_ptr->chp < p_ptr->mhp) {
794 		if (!autoeffect) {
795 			/* data collection for PVP mode: weaken continous healing over time to prevent silliness (who stacks more pots) - C. Blue */
796 			p_ptr->heal_effect += eff_num;
797 		}
798 		/* data collection for C_BLUE_AI: add up healing happening during current turn */
799 		p_ptr->heal_turn[0] += eff_num;
800 
801 		/* refill HP, note that we can't use eff_num here due to chp_frac check */
802 		num = eff_num;
803 		p_ptr->chp += num;
804 		if (p_ptr->chp > p_ptr->mhp) {
805 			p_ptr->chp = p_ptr->mhp;
806 			p_ptr->chp_frac = 0;
807 		}
808 
809 		/* Update health bars */
810 		update_health(0 - Ind);
811 
812 		/* Redraw */
813 		p_ptr->redraw |= (PR_HP);
814 
815 		/* Figure out of if the player's "number" has changed */
816 		new_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
817 		if (new_num >= 7) new_num = 10;
818 
819 		/* If so then refresh everyone's view of this player */
820 		if (new_num != old_num)
821 			everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
822 
823 		/* Window stuff */
824 		p_ptr->window |= (PW_PLAYER);
825 
826 		return (TRUE);
827 	}
828 
829 	return (FALSE);
830 }
831 
832 
flash_bomb(int Ind)833 void flash_bomb(int Ind)
834 {
835 	player_type *p_ptr = Players[Ind];
836 	msg_print(Ind, "You throw down a blinding flash bomb!");
837 	msg_format_near(Ind, "%s throws a blinding flash bomb!", p_ptr->name);
838 
839 #ifdef USE_SOUND_2010
840 	sound(Ind, "flash_bomb", NULL, SFX_TYPE_COMMAND, TRUE);
841 #endif
842 
843 //	project_los(Ind, GF_BLIND, (p_ptr->lev / 10) + 4, "");
844 	project_los(Ind, GF_BLIND, (p_ptr->lev / 10) + 8, "");
845 }
846 
847 
848 /*
849  * Leave a "glyph of warding" which prevents monster movement
850  */
warding_glyph(int Ind)851 void warding_glyph(int Ind)
852 {
853 	player_type *p_ptr = Players[Ind];
854 
855 	cave_type **zcave;
856 	if (!(zcave = getcave(&p_ptr->wpos))) return;
857 
858 	if (!allow_terraforming(&p_ptr->wpos, FEAT_GLYPH) && !is_admin(p_ptr)) return;
859 
860 	cave_set_feat_live(&p_ptr->wpos, p_ptr->py, p_ptr->px, FEAT_GLYPH);
861 }
862 
863 
864 /*
865  * Array of stat "descriptions"
866  */
867 static cptr desc_stat_pos[] =
868 {
869 	"strong",
870 	"smart",
871 	"wise",
872 	"dextrous",
873 	"healthy",
874 	"cute"
875 };
876 
877 #if 0	// second set for future use
878 {
879 	"mighty",
880 	"intelligent",
881 	"sagacious",
882 	"agile",
883 	"sturdy",
884 	"charming"
885 }
886 #endif	// 0
887 
888 
889 /*
890  * Array of stat "descriptions"
891  */
892 static cptr desc_stat_neg[] =
893 {
894 	"weak",
895 	"stupid",
896 	"naive",
897 	"clumsy",
898 	"sickly",
899 	"ugly"
900 };
901 
902 static cptr desc_stat_neg2[] =
903 {
904 	"strong",
905 	"bright",
906 	"wise",
907 	"agile",
908 	"hale",
909 	"beautiful"
910 };
911 
912 #if 0
913 {
914 	"feeble",
915 	"dull",
916 	"foolish",
917 	"awkward",
918 	"fragile",
919 	"indecent"
920 },
921 #endif	// 0
922 
923 
924 /*
925  * Lose a "point"
926  */
do_dec_stat(int Ind,int stat,int mode)927 bool do_dec_stat(int Ind, int stat, int mode)
928 {
929 	player_type *p_ptr = Players[Ind];
930 
931 	bool sust = FALSE;
932 
933 	/* Access the "sustain" */
934 	switch (stat)
935 	{
936 		case A_STR: if (p_ptr->sustain_str) sust = TRUE; break;
937 		case A_INT: if (p_ptr->sustain_int) sust = TRUE; break;
938 		case A_WIS: if (p_ptr->sustain_wis) sust = TRUE; break;
939 		case A_DEX: if (p_ptr->sustain_dex) sust = TRUE; break;
940 		case A_CON: if (p_ptr->sustain_con) sust = TRUE; break;
941 		case A_CHR: if (p_ptr->sustain_chr) sust = TRUE; break;
942 	}
943 
944 	/* Sustain */
945 	if (sust || safe_area(Ind))
946 	{
947 		/* Message */
948 		msg_format(Ind, "You feel %s for a moment, but the feeling passes.",
949 		           desc_stat_neg[stat]);
950 
951 		/* Notice effect */
952 		return (TRUE);
953 	}
954 
955 	/* Attempt to reduce the stat */
956 	if (dec_stat(Ind, stat, 10, mode))
957 	{
958 		/* Message */
959 		msg_format(Ind, "You feel very %s.", desc_stat_neg[stat]);
960 
961 		/* Notice effect */
962 		return (TRUE);
963 	}
964 
965 	/* Nothing obvious */
966 	return (FALSE);
967 }
968 
969 
970 /*
971  * Lose a "point" by a TIME attack (or Black Breath)
972  */
do_dec_stat_time(int Ind,int stat,int mode,int sust_chance,int reduction_mode,bool msg)973 bool do_dec_stat_time(int Ind, int stat, int mode, int sust_chance, int reduction_mode, bool msg)
974 {
975 	player_type *p_ptr = Players[Ind];
976 
977 	bool sust = FALSE;
978 
979 	/* Access the "sustain" */
980 	switch (stat)
981 	{
982 		case A_STR: if (p_ptr->sustain_str) sust = TRUE; break;
983 		case A_INT: if (p_ptr->sustain_int) sust = TRUE; break;
984 		case A_WIS: if (p_ptr->sustain_wis) sust = TRUE; break;
985 		case A_DEX: if (p_ptr->sustain_dex) sust = TRUE; break;
986 		case A_CON: if (p_ptr->sustain_con) sust = TRUE; break;
987 		case A_CHR: if (p_ptr->sustain_chr) sust = TRUE; break;
988 	}
989 
990 	if (p_ptr->stat_cur[stat] <= 3) return(FALSE);
991 
992 	/* Sustain */
993 	if ((sust && magik(sust_chance)) || safe_area(Ind)) {
994 		/* Message */
995 		msg_format(Ind, "You don't feel as %s as you used to be, but the feeling passes",
996 		           desc_stat_neg2[stat]);
997 
998 		/* Notice effect */
999 		return (TRUE);
1000 	}
1001 
1002 	/* Message */
1003 	if (msg) msg_format(Ind, "You're not as %s as you used to be.", desc_stat_neg2[stat]);
1004 
1005 	/* Attempt to reduce the stat */
1006 	switch (reduction_mode) {
1007 	case 0:
1008 		if (dec_stat(Ind, stat, 10, mode))
1009 		{
1010 			/* Notice effect */
1011 			return (TRUE);
1012 		}
1013 		break;
1014 	case 1:
1015 		p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 3) / 4;
1016 		break;
1017 	case 2:
1018 		p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 6) / 7;
1019 		break;
1020 	case 3:
1021 		p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 7) / 8;
1022 		break;
1023 	}
1024 	if (p_ptr->stat_cur[stat] < 3) p_ptr->stat_cur[stat] = 3;
1025 
1026 	if (mode == STAT_DEC_PERMANENT) p_ptr->stat_max[stat] = p_ptr->stat_cur[stat];
1027 
1028 	p_ptr->update |= (PU_BONUS | PU_MANA | PU_HP | PU_SANITY);
1029 
1030 	/* Nothing obvious */
1031 	return (TRUE);
1032 }
1033 
1034 
1035 /*
1036  * Restore lost "points" in a stat
1037  */
do_res_stat(int Ind,int stat)1038 bool do_res_stat(int Ind, int stat)
1039 {
1040 	/* Attempt to increase */
1041 	if (res_stat(Ind, stat))
1042 	{
1043 		/* Message */
1044 		msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1045 
1046 		/* Notice */
1047 		return (TRUE);
1048 	}
1049 
1050 	/* Nothing obvious */
1051 	return (FALSE);
1052 }
1053 
1054 /*
1055  * Restore temporary-lost "points" in a stat
1056  */
do_res_stat_temp(int Ind,int stat)1057 bool do_res_stat_temp(int Ind, int stat)
1058 {
1059 	player_type *p_ptr = Players[Ind];
1060 
1061 	/* Restore if needed */
1062 	if (p_ptr->stat_cur[stat] != p_ptr->stat_max[stat])
1063 	{
1064 		/* Restore */
1065 		p_ptr->stat_cur[stat] += p_ptr->stat_los[stat];
1066 
1067 		if (p_ptr->stat_cur[stat] > p_ptr->stat_max[stat])
1068 			p_ptr->stat_cur[stat] = p_ptr->stat_max[stat];
1069 
1070 		p_ptr->stat_los[stat] = 0;
1071 		p_ptr->stat_cnt[stat] = 0;
1072 
1073 		/* Recalculate bonuses */
1074 		p_ptr->update |= (PU_BONUS);
1075 
1076 		/* Message */
1077 		msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1078 		/* Success */
1079 		return (TRUE);
1080 	}
1081 
1082 	/* Nothing to restore */
1083 	return (FALSE);
1084 }
1085 
1086 /*
1087  * Gain a "point" in a stat
1088  */
do_inc_stat(int Ind,int stat)1089 bool do_inc_stat(int Ind, int stat)
1090 {
1091 	bool res;
1092 
1093 	/* Restore strength */
1094 	res = res_stat(Ind, stat);
1095 
1096 	/* Attempt to increase */
1097 	if (inc_stat(Ind, stat))
1098 	{
1099 		/* Message */
1100 		msg_format(Ind, "Wow!  You feel very %s!", desc_stat_pos[stat]);
1101 
1102 		/* Notice */
1103 		return (TRUE);
1104 	}
1105 
1106 	/* Restoration worked */
1107 	if (res)
1108 	{
1109 		/* Message */
1110 		msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1111 
1112 		/* Notice */
1113 		return (TRUE);
1114 	}
1115 
1116 	/* Nothing obvious */
1117 	return (FALSE);
1118 }
1119 
1120 
1121 
1122 /*
1123  * Identify everything being carried.
1124  * Done by a potion of "self knowledge".
1125  */
identify_pack(int Ind)1126 void identify_pack(int Ind) {
1127 	player_type *p_ptr = Players[Ind];
1128 
1129 	int                 i;
1130 	object_type        *o_ptr;
1131 	bool inven_unchanged[INVEN_TOTAL];
1132 
1133 	/* Simply identify and know every item */
1134 	for (i = 0; i < INVEN_TOTAL; i++) {
1135 		inven_unchanged[i] = TRUE;
1136 		o_ptr = &p_ptr->inventory[i];
1137 
1138 		if (o_ptr->k_idx) {
1139 			if (object_known_p(Ind, o_ptr) && object_aware_p(Ind, o_ptr)) continue;
1140 
1141 			object_aware(Ind, o_ptr);
1142 			object_known(o_ptr);
1143 			inven_unchanged[i] = FALSE;
1144 		}
1145 	}
1146 
1147 	/* Recalculate bonuses */
1148 	p_ptr->update |= (PU_BONUS);
1149 
1150 	/* Combine / Reorder the pack (later) */
1151 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
1152 
1153 	/* Window stuff */
1154 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
1155 
1156 	/* Handle stuff */
1157 	handle_stuff(Ind);
1158 
1159 #if 0 /* moved to client-side, clean! */
1160 	/* hack: trigger client-side auto-inscriptions for convenience,
1161 	   if it isn't due anyway.  */
1162 	if (!p_ptr->inventory_changes) Send_inventory_revision(Ind);
1163 #endif
1164 	/* well, instead: */
1165 	for (i = 0; i < INVEN_TOTAL; i++) {
1166 		if (inven_unchanged[i]) continue;
1167 		Send_apply_auto_insc(Ind, i);
1168 	}
1169 }
1170 
1171 
1172 
1173 
1174 
1175 
1176 /*
1177  * Used by the "enchant" function (chance of failure)
1178  */
1179 static int enchant_table[16] =
1180 {
1181 	0, 10,  50, 100, 200,
1182 	300, 400, 500, 700, 875,
1183 	960, 980, 990, 996, 999,
1184 	1000
1185 };
1186 
1187 /*
1188  * Lock a door. Currently range of one only.. Maybe a beam
1189  * would be better?
1190  */
wizard_lock(int Ind,int dir)1191 void wizard_lock(int Ind, int dir){
1192 	player_type *p_ptr;
1193 	cave_type **zcave, *c_ptr;
1194 	int dy, dx;
1195 
1196 	p_ptr = Players[Ind];
1197 	if (!p_ptr) return;
1198 	zcave = getcave(&p_ptr->wpos);
1199 	if (!zcave) return;
1200 
1201 	/* anti-cheeze: exp'ing with doors */
1202 	if (!p_ptr->wpos.wz) return;
1203 
1204 	dx = p_ptr->px + ddx[dir];
1205 	dy = p_ptr->py + ddy[dir];
1206 
1207 	c_ptr = &zcave[dy][dx];
1208 	if (c_ptr->feat >= FEAT_DOOR_HEAD && c_ptr->feat < (FEAT_DOOR_HEAD + 7)) {
1209 		if (c_ptr->feat == FEAT_DOOR_HEAD) {
1210 			msg_print(Ind, "The door locks!");
1211 			c_ptr->info |= CAVE_MAGELOCK;
1212 		} else msg_print(Ind, "The door appears stronger!");
1213 		c_ptr->feat++;
1214 	} else if (c_ptr->feat != (FEAT_DOOR_HEAD + 7))
1215 		msg_print(Ind, "You see no lockable door there");
1216 	else
1217 		msg_print(Ind, "The door is locked fast already!");
1218 }
1219 
1220 /*
1221  * Removes curses from items in inventory
1222  *
1223  * Note that Items which are "Perma-Cursed" (The One Ring,
1224  * The Crown of Morgoth) can NEVER be uncursed.
1225  *
1226  * Note that if "all" is FALSE, then Items which are
1227  * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
1228  * will not be uncursed.
1229  */
1230 /*
1231  * 0x01 - all
1232  * 0x02 - limit to one item (added for projectable spell)
1233  */
remove_curse_aux(int Ind,int all,int pInd)1234 int remove_curse_aux(int Ind, int all, int pInd) {
1235 	player_type *p_ptr = Players[Ind];
1236 	object_type *o_ptr;
1237 #ifdef NEW_REMOVE_CURSE
1238 	char o_name[ONAME_LEN];
1239 #endif
1240 
1241 	int i, j, cnt = 0;
1242 	u32b f1, f2, f3, f4, f5, f6, esp;
1243 
1244 #ifdef NEW_REMOVE_CURSE
1245 	if (pInd) msg_format(Ind, "%s recites some holy words..", Players[pInd]->name);
1246 #endif
1247 
1248 	for (j = 0; j < INVEN_TOTAL; j++) {
1249 		i = (j + INVEN_WIELD) % INVEN_TOTAL;
1250 		o_ptr = &p_ptr->inventory[i];
1251 
1252 		/* Uncursed already */
1253 		if (!cursed_p(o_ptr)) continue;
1254 
1255 		/* Extract the flags */
1256 		object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1257 
1258 		/* Heavily Cursed Items need a special spell */
1259 		if (!(all & 0x01) && (f3 & TR3_HEAVY_CURSE)) continue;
1260 
1261 		/* Perma-Cursed Items can NEVER be uncursed */
1262 		if ((f3 & TR3_PERMA_CURSE) && !is_admin(p_ptr)) continue;
1263 
1264 #ifdef NEW_REMOVE_CURSE
1265 		/* Allow rc to fail sometimes */
1266 		if ((!(all & 0x01) || (f3 & TR3_HEAVY_CURSE)) && magik(o_ptr->level)) {
1267 			object_desc(Ind, o_name, o_ptr, FALSE, 3);
1268 			msg_format(Ind, "Your %s shimmer%s purple for a moment..", o_name, o_ptr->number == 1 ? "s" : "");
1269 			continue;
1270 		}
1271 
1272 		object_desc(Ind, o_name, o_ptr, FALSE, 3);
1273 		msg_format(Ind, "Your %s flash%s blue!", o_name, o_ptr->number == 1 ? "es" : "");
1274 #endif
1275 
1276 		/* Uncurse it */
1277 		o_ptr->ident &= ~ID_CURSED;
1278 
1279 		/* Hack -- Assume felt */
1280 		o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
1281 
1282 		/* Take note */
1283 		note_toggle_cursed(o_ptr, FALSE);
1284 
1285 		/* Recalculate the bonuses */
1286 		p_ptr->update |= (PU_BONUS);
1287 
1288 		/* Window stuff */
1289 		p_ptr->window |= (PW_INVEN | PW_EQUIP);
1290 
1291 		/* Count the uncursings */
1292 		cnt++;
1293 
1294 		/* Not everything at once. */
1295 #ifdef NEW_REMOVE_CURSE
1296 		if ((all & 0x02) ||
1297 #else
1298 		if (
1299 #endif
1300 		    (!(all & 0x01) && magik(50)))
1301 			break;
1302 	}
1303 
1304 	/* Return "something uncursed" */
1305 	return (cnt);
1306 }
1307 
1308 
1309 /* well, erm... */
1310 /*
1311  * Remove most curses
1312  */
remove_curse(int Ind)1313 bool remove_curse(int Ind) {
1314 #ifndef NEW_REMOVE_CURSE
1315 	return (remove_curse_aux(Ind, 0x0, 0));
1316 #else
1317 	/* assume we're called _only_ as the projectable holy school spell */
1318 	int i, p, r = 0;
1319 	cave_type **zcave;
1320 	player_type *p_ptr = Players[Ind];
1321 
1322 	/* remove our own curse(s) first - can't remove other player's curses while we're not cleansed ;) */
1323 	i = remove_curse_aux(Ind, 0x0, 0);
1324 	if (i) return i;
1325 
1326 	/* remove someone else's curse */
1327 	if ((zcave = getcave(&p_ptr->wpos))) {
1328 		/* check grids around the player, first one we find possibly gets a curse fixed */
1329 		for (i = 7; i >= 0; i--) {
1330 			if ((p = zcave[p_ptr->py + ddy_ddd[i]][p_ptr->px + ddx_ddd[i]].m_idx >= 0)) continue;
1331 			r = remove_curse_aux(-p, 0x0 + 0x2, Ind);
1332 			break;
1333 		}
1334 	}
1335 
1336 	/* remove our own curse(s) */
1337 	return r;
1338 #endif
1339 }
1340 
1341 /*
1342  * Remove all curses
1343  */
remove_all_curse(int Ind)1344 bool remove_all_curse(int Ind) {
1345 #ifndef NEW_REMOVE_CURSE
1346 	return (remove_curse_aux(Ind, 0x1, 0));
1347 #else
1348 	/* assume we're called _only_ as the projectable holy school spell */
1349 	int i, p, r = 0;
1350 	cave_type **zcave;
1351 	player_type *p_ptr = Players[Ind];
1352 
1353 	/* remove our own curse(s) first - can't remove other player's curses while we're not cleansed ;) */
1354 	i = remove_curse_aux(Ind, 0x1, 0);
1355 	if (i) return i;
1356 
1357 	/* remove someone else's curse */
1358 	if ((zcave = getcave(&p_ptr->wpos))) {
1359 		/* check grids around the player, first one we find possibly gets a curse fixed */
1360 		for (i = 7; i >= 0; i--) {
1361 			if ((p = zcave[p_ptr->py + ddy_ddd[i]][p_ptr->px + ddx_ddd[i]].m_idx >= 0)) continue;
1362 			r = remove_curse_aux(-p, 0x1 + 0x2, Ind);
1363 			break;
1364 		}
1365 	}
1366 	return r;
1367 #endif
1368 }
1369 
1370 /*
1371  * Restores any drained experience
1372  */
restore_level(int Ind)1373 bool restore_level(int Ind)
1374 {
1375 	player_type *p_ptr = Players[Ind];
1376 
1377 	/* Restore experience */
1378 	if (p_ptr->exp < p_ptr->max_exp) {
1379 		/* Message */
1380 		msg_print(Ind, "You feel your life energies returning.");
1381 
1382 		/* Restore the experience */
1383 		p_ptr->exp = p_ptr->max_exp;
1384 
1385 		/* Check the experience */
1386 		check_experience(Ind);
1387 
1388 		/* Did something */
1389 		return (TRUE);
1390 	}
1391 
1392 	/* No effect */
1393 	return (FALSE);
1394 }
1395 
1396 
1397 /*
1398  * self-knowledge... idea from nethack.  Useful for determining powers and
1399  * resistences of items.  It saves the screen, clears it, then starts listing
1400  * attributes, a screenful at a time.  (There are a LOT of attributes to
1401  * list.  It will probably take 2 or 3 screens for a powerful character whose
1402  * using several artifacts...) -CFT
1403  *
1404  * It is now a lot more efficient. -BEN-
1405  *
1406  * See also "identify_fully()".
1407  *
1408  * XXX XXX XXX Use the "show_file()" method, perhaps.
1409  */
self_knowledge(int Ind)1410 void self_knowledge(int Ind) {
1411 	player_type *p_ptr = Players[Ind];
1412 	int		k;
1413 	u32b	f1 = 0L, f2 = 0L, f3 = 0L, f4 = 0L, f5 = 0L, f6 = 0L;	//, esp = 0L;
1414 	object_type	*o_ptr;
1415 //	cptr	*info = p_ptr->info;
1416 	bool	life = FALSE;
1417 	FILE *fff;
1418 #if 0
1419 	char file_name[MAX_PATH_LENGTH];
1420 
1421 	/* Temporary file */
1422 	if (path_temp(file_name, MAX_PATH_LENGTH)) return;
1423 	strcpy(p_ptr->infofile, file_name);
1424 #endif	// 0
1425 	/* Open a new file */
1426 	fff = my_fopen(p_ptr->infofile, "wb");
1427 	/* Current file viewing */
1428 	strcpy(p_ptr->cur_file, p_ptr->infofile);
1429 
1430 	/* Output color byte */
1431 //	fprintf(fff, "%c", 'w');
1432 
1433 	/* Let the player scroll through the info */
1434 	p_ptr->special_file_type = TRUE;
1435 
1436 	/* Acquire item flags from equipment */
1437 	for (k = INVEN_WIELD; k < INVEN_TOTAL; k++) {
1438 		u32b t1, t2, t3, t4, t5, t6, tesp;
1439 		o_ptr = &p_ptr->inventory[k];
1440 		/* Skip empty items */
1441 		if (!o_ptr->k_idx) continue;
1442 		/* Extract the flags */
1443 		object_flags(o_ptr, &t1, &t2, &t3, &t4, &t5, &t6, &tesp);
1444 
1445 		/* Extract flags */
1446 		f1 |= t1;
1447 		f2 |= t2;
1448 		f3 |= t3;
1449 		f4 |= t4;
1450 		f5 |= t5;
1451 		f6 |= t6;
1452 
1453 		/* Mega Hack^3 -- check the amulet of life saving */
1454 		if (o_ptr->tval == TV_AMULET &&
1455 			o_ptr->sval == SV_AMULET_LIFE_SAVING)
1456 			life = TRUE;
1457 	}
1458 
1459 	/* Mega Hack^3 -- describe the amulet of life saving */
1460 	if (life) fprintf(fff, "Your life will be saved from perilous scene once.\n");
1461 
1462 #if 0
1463 	k = 100 - p_ptr->csane * 100 / p_ptr->msane;
1464 	if (k < 100) {
1465 //		sprintf(info[i++], "%d%% of your mind is under your control.", k);
1466 		fprintf(fff, "%d%% of your mind is under your control.\n", k);
1467 	}
1468 #else
1469 	/* Insanity warning (better message needed!) */
1470 	if (p_ptr->csane < p_ptr->msane / 8) {
1471 		fprintf(fff, "You are next to mad.\n");
1472 	} else if (p_ptr->csane < p_ptr->msane / 4) {
1473 		fprintf(fff, "Your mind is filled with insane thoughts.\n");
1474 	} else if (p_ptr->csane < p_ptr->msane / 2) {
1475 		fprintf(fff, "You have a seed of insanity in your mind.\n");
1476 	}
1477 #endif
1478 
1479 	if (p_ptr->blind) fprintf(fff, "You cannot see.\n");
1480 	if (p_ptr->confused) fprintf(fff, "You are confused.\n");
1481 	if (p_ptr->afraid) fprintf(fff, "You are terrified.\n");
1482 	if (p_ptr->cut) fprintf(fff, "\377rYou are bleeding.\n");
1483 	if (p_ptr->stun) fprintf(fff, "\377oYou are stunned.\n");
1484 	if (p_ptr->poisoned) fprintf(fff, "\377GYou are poisoned.\n");
1485 	if (p_ptr->image) fprintf(fff, "You are hallucinating.\n");
1486 
1487 	if (p_ptr->aggravate) fprintf(fff, "You aggravate monsters.\n");
1488 	if (p_ptr->teleport) fprintf(fff, "Your position is very uncertain.\n");
1489 
1490 	if (p_ptr->blessed) fprintf(fff, "You feel rightous.\n");
1491 	if (p_ptr->hero) fprintf(fff, "You feel heroic.\n");
1492 	if (p_ptr->shero) fprintf(fff, "You are in a battle rage.\n");
1493 	if (p_ptr->fury) fprintf(fff, "You are in a wild fury.\n");
1494 	if (p_ptr->berserk) fprintf(fff, "You are going berserk.\n");
1495 	if (p_ptr->protevil) fprintf(fff, "You are protected from evil.\n");
1496 #if 0
1497 	if (p_ptr->protgood) fprintf(fff, "You are protected from good.\n");
1498 #endif	// 0
1499 	if (p_ptr->shield) fprintf(fff, "You are protected by a mystic shield.\n");
1500 	if (p_ptr->invuln) fprintf(fff, "You are temporarily invulnerable.\n");
1501 	if (p_ptr->confusing) fprintf(fff, "Your hands are glowing dull red.\n");
1502 	if (p_ptr->stunning) fprintf(fff, "Your hands are very heavy.\n");
1503 	if (p_ptr->searching) fprintf(fff, "You are looking around very carefully.\n");
1504 #if 0
1505 	if (p_ptr->new_spells) fprintf(fff, "You can learn some more spells.\n");
1506 #endif
1507 	if (p_ptr->word_recall) fprintf(fff, "You will soon be recalled.\n");
1508 	if (p_ptr->see_infra) fprintf(fff, "Your eyes are sensitive to infrared light.\n");
1509 	if (p_ptr->invis) fprintf(fff, "You are invisible.\n");
1510 #if 0 /* really not required to tell the player this stuff, it'd be just spam */
1511 	if (p_ptr->cloaked) fprintf(fff, "You are cloaked.\n");
1512 	if (p_ptr->shadow_running) fprintf(fff, "You are shadow_running.\n");
1513 #endif
1514 	if (p_ptr->see_inv) fprintf(fff, "You can see invisible creatures.\n");
1515 	if (p_ptr->feather_fall) fprintf(fff, "You land gently.\n");
1516 #if 1
1517 	if (p_ptr->climb) fprintf(fff, "You can climb high mountains.\n");
1518 	if (p_ptr->levitate) fprintf(fff, "You can levitate.\n");
1519 	if (p_ptr->can_swim) fprintf(fff, "You can swim easily.\n");
1520 #endif	// 0
1521 	if (p_ptr->free_act) fprintf(fff, "You have free action.\n");
1522 	if (p_ptr->regenerate) fprintf(fff, "You regenerate quickly.\n");
1523 	if (p_ptr->resist_time) fprintf(fff, "You are resistant to time.\n");
1524 	if (p_ptr->resist_mana) fprintf(fff, "You are resistant to magical energy.\n");
1525 	if (p_ptr->immune_water) fprintf(fff, "You are completely protected from unleashed water.\n");
1526 	else if (p_ptr->resist_water) fprintf(fff, "You are resistant to unleashed water.\n");
1527 	if (p_ptr->regen_mana) fprintf(fff, "You accumulate mana quickly.\n");
1528 
1529 	if (p_ptr->prace == RACE_MAIA && p_ptr->ptrait) fprintf(fff, "You have no need for worldly food.\n");
1530 	else if (get_skill(p_ptr, SKILL_HSUPPORT) >= 40) fprintf(fff, "You have no need for worldly food.\n");
1531 	else if (p_ptr->ghost) fprintf(fff, "You have no need for worldly food.\n");
1532 	else if (p_ptr->prace == RACE_VAMPIRE && p_ptr->total_winner) fprintf(fff, "Your appetite is small.\n");
1533 	else if (p_ptr->slow_digest) fprintf(fff, "Your appetite is small.\n");
1534 
1535 	if (p_ptr->telepathy) {
1536 //		fprintf(fff, "You have ESP.\n");
1537 		if (p_ptr->telepathy & ESP_ALL) fprintf(fff, "You have ESP.\n");
1538 		else {
1539 			if (p_ptr->telepathy & ESP_ORC) fprintf(fff, "You can sense the presence of orcs.\n");
1540 			if (p_ptr->telepathy & ESP_TROLL) fprintf(fff, "You can sense the presence of trolls.\n");
1541 			if (p_ptr->telepathy & ESP_DRAGON) fprintf(fff, "You can sense the presence of dragons.\n");
1542 			if (p_ptr->telepathy & ESP_SPIDER) fprintf(fff, "You can sense the presence of spiders.\n");
1543 			if (p_ptr->telepathy & ESP_GIANT) fprintf(fff, "You can sense the presence of giants.\n");
1544 			if (p_ptr->telepathy & ESP_DEMON) fprintf(fff, "You can sense the presence of demons.\n");
1545 			if (p_ptr->telepathy & ESP_UNDEAD) fprintf(fff, "You can sense presence of undead.\n");
1546 			if (p_ptr->telepathy & ESP_EVIL) fprintf(fff, "You can sense the presence of evil beings.\n");
1547 			if (p_ptr->telepathy & ESP_ANIMAL) fprintf(fff, "You can sense the presence of animals.\n");
1548 			if (p_ptr->telepathy & ESP_DRAGONRIDER) fprintf(fff, "You can sense the presence of dragonriders.\n");
1549 			if (p_ptr->telepathy & ESP_GOOD) fprintf(fff, "You can sense the presence of good beings.\n");
1550 			if (p_ptr->telepathy & ESP_NONLIVING) fprintf(fff, "You can sense the presence of non-living things.\n");
1551 			if (p_ptr->telepathy & ESP_UNIQUE) fprintf(fff, "You can sense the presence of unique beings.\n");
1552 		}
1553 	}
1554 	if (p_ptr->antimagic)	// older (percent)
1555 	{
1556 //		fprintf(fff, "You are surrounded by an anti-magic field.\n");
1557 		if (p_ptr->antimagic >= ANTIMAGIC_CAP) /* AM cap */
1558 			fprintf(fff, "You are surrounded by a complete anti-magic field.\n");
1559 		else if (p_ptr->antimagic >= ANTIMAGIC_CAP - 10)
1560 			fprintf(fff, "You are surrounded by a mighty anti-magic field.\n");
1561 		else if (p_ptr->antimagic >= ANTIMAGIC_CAP - 20)
1562 			fprintf(fff, "You are surrounded by a strong anti-magic field.\n");
1563 		else if (p_ptr->antimagic >= 50)
1564 			fprintf(fff, "You are surrounded by an anti-magic field.\n");
1565 		else if (p_ptr->antimagic >= 30)
1566 			fprintf(fff, "You are surrounded by a weaker anti-magic field.\n");
1567 		else fprintf(fff, "You are surrounded by a feeble anti-magic field.\n");
1568 
1569 	}
1570 #if 1
1571         if (p_ptr->anti_magic)	// newer (saving-throw boost)
1572                 fprintf(fff, "You are surrounded by an anti-magic shell.\n");
1573 #endif	// 0
1574 	if (p_ptr->hold_life) fprintf(fff, "You have a firm hold on your life force.\n");
1575 #if 1	// somewhat hacky
1576 	if (p_ptr->lite) fprintf(fff, "You are carrying a permanent light.\n");
1577 #endif	// 0
1578 	if (p_ptr->auto_id) fprintf(fff, "You can sense magic.\n");
1579 #if 1
1580 	if (p_ptr->reflect) fprintf(fff, "You reflect arrows and bolts.\n");
1581 	if (p_ptr->no_cut) fprintf(fff, "You cannot be cut.\n");
1582 
1583 	if (p_ptr->reduce_insanity > 0) {
1584 		fprintf(fff, "Your mind is somewhat resistant against insanity.\n");
1585 	}
1586 	if (p_ptr->suscep_fire) fprintf(fff, "You are susceptible to fire.\n");
1587 	if (p_ptr->suscep_cold) fprintf(fff, "You are susceptible to cold.\n");
1588 	if (p_ptr->suscep_acid) fprintf(fff, "You are susceptible to acid.\n");
1589 	if (p_ptr->suscep_elec) fprintf(fff, "You are susceptible to electricity.\n");
1590 	if (p_ptr->suscep_pois) fprintf(fff, "You are susceptible to poison.\n");
1591 	if (p_ptr->suscep_lite) fprintf(fff, "You are susceptible to light.\n");
1592 	if (p_ptr->suscep_good) fprintf(fff, "You are susceptible to evil-vanquishing effects.\n");
1593 	if (p_ptr->suscep_evil) fprintf(fff, "You are susceptible to good-vanquishing effects.\n");
1594 	if (p_ptr->suscep_life) fprintf(fff, "You are susceptible to undead-vanquishing effects.\n");
1595 
1596 	if (p_ptr->sh_fire) fprintf(fff, "You are surrounded with a fiery aura.\n");
1597 	if (p_ptr->sh_elec) fprintf(fff, "You are surrounded with electricity.\n");
1598 	if (p_ptr->sh_cold) fprintf(fff, "You are surrounded with a freezing aura.\n");
1599 
1600 	if (p_ptr->resist_continuum) fprintf(fff, "The space-time continuum cannot be disrupted near you.\n");
1601 	if (p_ptr->anti_tele) fprintf(fff, "You are surrounded by an anti-teleportation field.\n");
1602 	if (p_ptr->res_tele) fprintf(fff, "You resist incoming teleportation effects.\n");
1603 #endif	// 0
1604 
1605 	if (p_ptr->immune_acid) fprintf(fff, "You are completely immune to acid.\n");
1606 	else if ((p_ptr->resist_acid) && (p_ptr->oppose_acid))
1607 		fprintf(fff, "You resist acid exceptionally well.\n");
1608 	else if ((p_ptr->resist_acid) || (p_ptr->oppose_acid))
1609 		fprintf(fff, "You are resistant to acid.\n");
1610 
1611 	if (p_ptr->immune_elec) fprintf(fff, "You are completely immune to lightning.\n");
1612 	else if ((p_ptr->resist_elec) && (p_ptr->oppose_elec))
1613 		fprintf(fff, "You resist lightning exceptionally well.\n");
1614 	else if ((p_ptr->resist_elec) || (p_ptr->oppose_elec))
1615 		fprintf(fff, "You are resistant to lightning.\n");
1616 
1617 	if (p_ptr->immune_fire) fprintf(fff, "You are completely immune to fire.\n");
1618 	else if ((p_ptr->resist_fire) && (p_ptr->oppose_fire))
1619 		fprintf(fff, "You resist fire exceptionally well.\n");
1620 	else if ((p_ptr->resist_fire) || (p_ptr->oppose_fire))
1621 		fprintf(fff, "You are resistant to fire.\n");
1622 
1623 	if (p_ptr->immune_cold) fprintf(fff, "You are completely immune to cold.\n");
1624 	else if ((p_ptr->resist_cold) && (p_ptr->oppose_cold))
1625 		fprintf(fff, "You resist cold exceptionally well.\n");
1626 	else if ((p_ptr->resist_cold) || (p_ptr->oppose_cold))
1627 		fprintf(fff, "You are resistant to cold.\n");
1628 
1629 	if (p_ptr->immune_poison) fprintf(fff, "You are completely immune to poison.\n");
1630 	else if ((p_ptr->resist_pois) && (p_ptr->oppose_pois))
1631 		fprintf(fff, "You resist poison exceptionally well.\n");
1632 	else if ((p_ptr->resist_pois) || (p_ptr->oppose_pois))
1633 		fprintf(fff, "You are resistant to poison.\n");
1634 
1635 	if (p_ptr->resist_lite) fprintf(fff, "You are resistant to bright light.\n");
1636 	if (p_ptr->resist_dark) fprintf(fff, "You are resistant to darkness.\n");
1637 	if (p_ptr->resist_conf) fprintf(fff, "You are resistant to confusion.\n");
1638 	if (p_ptr->resist_sound) fprintf(fff, "You are resistant to sonic attacks.\n");
1639 	if (p_ptr->resist_disen) fprintf(fff, "You are resistant to disenchantment.\n");
1640 	if (p_ptr->resist_chaos) fprintf(fff, "You are resistant to chaos.\n");
1641 	if (p_ptr->resist_shard) fprintf(fff, "You are resistant to blasts of shards.\n");
1642 	if (p_ptr->resist_nexus) fprintf(fff, "You are resistant to nexus attacks.\n");
1643 	if (p_ptr->immune_neth) fprintf(fff, "You are immune to nether forces.\n");
1644 	else if (p_ptr->resist_neth) fprintf(fff, "You are resistant to nether forces.\n");
1645 	if (p_ptr->resist_fear) fprintf(fff, "You are completely fearless.\n");
1646 	if (p_ptr->resist_blind) fprintf(fff, "Your eyes are resistant to blindness.\n");
1647 
1648 	if (p_ptr->sustain_str) fprintf(fff, "Your strength is sustained.\n");
1649 	if (p_ptr->sustain_int) fprintf(fff, "Your intelligence is sustained.\n");
1650 	if (p_ptr->sustain_wis) fprintf(fff, "Your wisdom is sustained.\n");
1651 	if (p_ptr->sustain_con) fprintf(fff, "Your constitution is sustained.\n");
1652 	if (p_ptr->sustain_dex) fprintf(fff, "Your dexterity is sustained.\n");
1653 	if (p_ptr->sustain_chr) fprintf(fff, "Your charisma is sustained.\n");
1654 	if (p_ptr->black_breath || p_ptr->black_breath_tmp)
1655 		fprintf(fff, "You suffer from Black Breath.\n");
1656 
1657 	if (f1 & TR1_STR) fprintf(fff, "Your strength is affected by your equipment.\n");
1658 	if (f1 & TR1_INT) fprintf(fff, "Your intelligence is affected by your equipment.\n");
1659 	if (f1 & TR1_WIS) fprintf(fff, "Your wisdom is affected by your equipment.\n");
1660 	if (f1 & TR1_DEX) fprintf(fff, "Your dexterity is affected by your equipment.\n");
1661 	if (f1 & TR1_CON) fprintf(fff, "Your constitution is affected by your equipment.\n");
1662 	if (f1 & TR1_CHR) fprintf(fff, "Your charisma is affected by your equipment.\n");
1663 
1664 	if (f1 & TR1_STEALTH) fprintf(fff, "Your stealth is affected by your equipment.\n");
1665 	if (f1 & TR1_SEARCH) fprintf(fff, "Your searching ability is affected by your equipment.\n");
1666 	if (f5 & TR5_DISARM) fprintf(fff, "Your disarming ability is affected by your equipment.\n");
1667 	if (f1 & TR1_INFRA) fprintf(fff, "Your infravision is affected by your equipment.\n");
1668 	if (f1 & TR1_TUNNEL) fprintf(fff, "Your digging ability is affected by your equipment.\n");
1669 	if (f1 & TR1_SPEED) fprintf(fff, "Your speed is affected by your equipment.\n");
1670 	if (f1 & TR1_BLOWS) fprintf(fff, "Your attack speed is affected by your equipment.\n");
1671 	if (f5 & TR5_CRIT) fprintf(fff, "Your ability to score critical hits is affected by your equipment.\n");
1672 
1673 	if (p_ptr->luck == 40)
1674 		fprintf(fff, "You are ultimatively lucky!\n");
1675 	else if (p_ptr->luck >= 30)
1676 		fprintf(fff, "You are lucky very frequently!\n");
1677 	else if (p_ptr->luck >= 20)
1678 		fprintf(fff, "You are lucky often.\n");
1679 	else if (p_ptr->luck >= 10)
1680 		fprintf(fff, "You are lucky here and there.\n");
1681 	else if (p_ptr->luck > 0)
1682 		fprintf(fff, "You are lucky sometimes.\n");
1683 
1684 	/* Analyze the weapon */
1685 	if (p_ptr->inventory[INVEN_WIELD].k_idx ||
1686 	    (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) /* dual-wield */
1687 	{
1688 		/* Indicate Blessing */
1689 		if (f3 & TR3_BLESSED) fprintf(fff, "Your weapon has been blessed by the gods.\n");
1690 		if (f5 & TR5_CHAOTIC) fprintf(fff, "Your weapon is branded with the Sign of Chaos.\n");
1691 		/* Hack */
1692 		if (f5 & TR5_IMPACT) fprintf(fff, "The impact of your weapon can cause earthquakes.\n");
1693 		if (f5 & TR5_VORPAL) fprintf(fff, "Your weapon is very sharp.\n");
1694 		if (f1 & TR1_VAMPIRIC) fprintf(fff, "Your weapon drains life from your foes.\n");
1695 
1696 		/* Special "Attack Bonuses" */
1697 		if (f1 & TR1_BRAND_ACID) fprintf(fff, "Your weapon melts your foes.\n");
1698 		if (f1 & TR1_BRAND_ELEC) fprintf(fff, "Your weapon shocks your foes.\n");
1699 		if (f1 & TR1_BRAND_FIRE) fprintf(fff, "Your weapon burns your foes.\n");
1700 		if (f1 & TR1_BRAND_COLD) fprintf(fff, "Your weapon freezes your foes.\n");
1701 		if (f1 & TR1_BRAND_POIS) fprintf(fff, "Your weapon poisons your foes.\n");
1702 
1703 		/* Special "slay" flags */
1704 		if (f1 & TR1_SLAY_ORC) fprintf(fff, "Your weapon is especially deadly against orcs.\n");
1705 		if (f1 & TR1_SLAY_TROLL) fprintf(fff, "Your weapon is especially deadly against trolls.\n");
1706 		if (f1 & TR1_SLAY_GIANT) fprintf(fff, "Your weapon is especially deadly against giants.\n");
1707 		if (f1 & TR1_SLAY_ANIMAL) fprintf(fff, "Your weapon strikes at animals with extra force.\n");
1708 		if (f1 & TR1_KILL_UNDEAD) fprintf(fff, "Your weapon is a great bane of undead.\n");
1709 		else if (f1 & TR1_SLAY_UNDEAD) fprintf(fff, "Your weapon strikes at undead with holy wrath.\n");
1710 		if (f1 & TR1_KILL_DEMON) fprintf(fff, "Your weapon is a great bane of demons.\n");
1711 		else if (f1 & TR1_SLAY_DEMON) fprintf(fff, "Your weapon strikes at demons with holy wrath.\n");
1712 		if (f1 & TR1_KILL_DRAGON) fprintf(fff, "Your weapon is a great bane of dragons.\n");
1713 		else if (f1 & TR1_SLAY_DRAGON) fprintf(fff, "Your weapon is especially deadly against dragons.\n");
1714 		if (f1 & TR1_SLAY_EVIL) fprintf(fff, "Your weapon strikes at evil with extra force.\n");
1715 	}
1716 //	info[i] = NULL;
1717 
1718 	/* Close the file */
1719 	my_fclose(fff);
1720 
1721 	/* Let the client know to expect some info */
1722 	strcpy(p_ptr->cur_file_title, "Knowledge of Yourself");
1723 	Send_special_other(Ind);
1724 }
1725 
1726 
1727 /*
1728  * Forget everything
1729  */
lose_all_info(int Ind)1730 bool lose_all_info(int Ind) {
1731 	player_type *p_ptr = Players[Ind];
1732 	int i;
1733 	char note2[80], noteid[10];
1734 
1735 	if (safe_area(Ind)) return TRUE;
1736 	if (p_ptr->auto_id) return FALSE;
1737 
1738 	/* Forget info about objects */
1739 	for (i = 0; i < INVEN_TOTAL; i++) {
1740 		object_type *o_ptr = &p_ptr->inventory[i];
1741 
1742 		/* Skip non-items */
1743 		if (!o_ptr->k_idx) continue;
1744 
1745 		/* Allow "protection" by the MENTAL flag */
1746 		if (o_ptr->ident & ID_MENTAL) continue;
1747 
1748 		/* Remove "default inscriptions" */
1749 		if (o_ptr->note && (o_ptr->ident & ID_SENSE)) {
1750 #if 0
1751 			/* Access the inscription */
1752 			cptr q = quark_str(o_ptr->note);
1753 
1754 			/* Hack -- Remove auto-inscriptions */
1755 			if ((streq(q, "cursed")) ||
1756 			    //"uncursed"?
1757 			    (streq(q, "broken")) ||
1758 			    (streq(q, "good")) ||
1759 			    (streq(q, "average")) ||
1760 			    (streq(q, "excellent")) ||
1761 			    (streq(q, "worthless")) ||
1762 			    (streq(q, "special")) ||
1763 			    (streq(q, "terrible"))) {
1764 				/* Forget the inscription */
1765 				o_ptr->note = 0;
1766 			}
1767 #else
1768 			note_crop_pseudoid(note2, noteid, quark_str(o_ptr->note));
1769 			if (!note2[0]) o_ptr->note = o_ptr->note_utag = 0;//utag is paranoia
1770 			else o_ptr->note = quark_add(note2);
1771 #endif
1772 		}
1773 
1774 		/* Hack -- Clear the "empty" flag */
1775 		o_ptr->ident &= ~ID_EMPTY;
1776 
1777 		/* Hack -- Clear the "known" flag */
1778 		o_ptr->ident &= ~ID_KNOWN;
1779 
1780 		/* Hack -- Clear the "felt" flag */
1781 		o_ptr->ident &= ~(ID_SENSE | ID_SENSE_HEAVY);
1782 	}
1783 
1784 	/* Recalculate bonuses */
1785 	p_ptr->update |= (PU_BONUS);
1786 
1787 	/* Combine / Reorder the pack (later) */
1788 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
1789 
1790 	/* Window stuff */
1791 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
1792 
1793 	/* Mega-Hack -- Forget the map */
1794 	wiz_dark(Ind);
1795 
1796 	/* It worked */
1797 	return (TRUE);
1798 }
1799 
1800 
1801 /*
1802  * Detect any treasure on the current panel		-RAK-
1803  *
1804  * We do not yet create any "hidden gold" features XXX XXX XXX
1805  */
1806 /*
1807  * TODO:
1808  * 1. allow to display gold carried by monsters
1809  * 2. make this a ranged spell
1810  */
detect_treasure(int Ind,int rad)1811 bool detect_treasure(int Ind, int rad) {
1812 	player_type *p_ptr = Players[Ind];
1813 	struct worldpos *wpos = &p_ptr->wpos;
1814 	dun_level *l_ptr;
1815 	int		py = p_ptr->py, px = p_ptr->px;
1816 
1817 	int		y, x;
1818 	bool	detect = FALSE;
1819 
1820 	cave_type	*c_ptr;
1821 	byte		*w_ptr;
1822 	object_type	*o_ptr;
1823 	cave_type **zcave;
1824 
1825 	/* anti-exploit */
1826 	if (!local_panel(Ind)) return FALSE;
1827 
1828 	if (!(zcave = getcave(wpos))) return(FALSE);
1829 	l_ptr = getfloor(wpos);
1830 
1831 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
1832 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
1833 
1834 	/* Scan the current panel */
1835 //	for (y = p_ptr->panel_row_min; y <= p_ptr->panel_row_max; y++)
1836 	for (y = py - rad; y <= py + rad; y++) {
1837 //		for (x = p_ptr->panel_col_min; x <= p_ptr->panel_col_max; x++)
1838 		for (x = px - rad; x <= px + rad; x++) {
1839 			/* Reject locations outside of dungeon */
1840 			if (!in_bounds4(l_ptr, y, x)) continue;
1841 
1842 			/* Reject those out of radius */
1843 			if (distance(py, px, y, x) > rad) continue;
1844 
1845 			c_ptr = &zcave[y][x];
1846 			w_ptr = &p_ptr->cave_flag[y][x];
1847 
1848 			o_ptr = &o_list[c_ptr->o_idx];
1849 
1850 			/* Magma/Quartz + Known Gold */
1851 			if ((c_ptr->feat == FEAT_MAGMA_K) ||
1852 			    (c_ptr->feat == FEAT_QUARTZ_K) ||
1853 			    (c_ptr->feat == FEAT_SANDWALL_K))
1854 			{
1855 				/* Notice detected gold */
1856 				if (!(*w_ptr & CAVE_MARK)) {
1857 					/* Detect */
1858 					detect = TRUE;
1859 
1860 					/* Hack -- memorize the feature */
1861 					*w_ptr |= CAVE_MARK;
1862 
1863 					/* Redraw */
1864 					lite_spot(Ind, y, x);
1865 				}
1866 			}
1867 
1868 			/* Notice embedded gold */
1869 			if ((c_ptr->feat == FEAT_MAGMA_H) ||
1870 			    (c_ptr->feat == FEAT_QUARTZ_H) ||
1871 			    (c_ptr->feat == FEAT_SANDWALL_H))
1872 			{
1873 				/* Expose the gold */
1874 				c_ptr->feat += 0x02;
1875 
1876 				/* Detect */
1877 				detect = TRUE;
1878 
1879 				/* Hack -- memorize the item */
1880 				*w_ptr |= CAVE_MARK;
1881 
1882 				/* Redraw */
1883 				lite_spot(Ind, y, x);
1884 			}
1885 
1886 			/* Notice gold */
1887 			if (o_ptr->tval == TV_GOLD) {
1888 				/* Notice new items */
1889 				if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
1890 					/* Detect */
1891 					detect = TRUE;
1892 
1893 					/* Hack -- memorize the item */
1894 					p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
1895 
1896 					/* Redraw */
1897 					lite_spot(Ind, y, x);
1898 				}
1899 			}
1900 		}
1901 	}
1902 
1903 	return (detect);
1904 }
1905 /* detect treasures level-wide, for DIGGING skill */
floor_detect_treasure(int Ind)1906 bool floor_detect_treasure(int Ind) {
1907 	player_type *p_ptr = Players[Ind];
1908 	struct worldpos *wpos = &p_ptr->wpos;
1909 	dun_level *l_ptr;
1910 	int y, x;
1911 	bool detect = FALSE;
1912 	cave_type *c_ptr;
1913 	byte *w_ptr;
1914 	object_type *o_ptr;
1915 	cave_type **zcave;
1916 
1917 	if (!(zcave = getcave(wpos))) return(FALSE);
1918 	if (!(l_ptr = getfloor(wpos))) return(FALSE); /* doesn't work on surface levels (wpos.wz == 0) */
1919 
1920 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
1921 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
1922 
1923 	/* Scan the whole level */
1924 	for (y = 0; y < l_ptr->hgt; y++) {
1925 		for (x = 0; x < l_ptr->wid; x++) {
1926 			/* Reject locations outside of dungeon */
1927 			if (!in_bounds4(l_ptr, y, x)) continue;
1928 
1929 			c_ptr = &zcave[y][x];
1930 			w_ptr = &p_ptr->cave_flag[y][x];
1931 			o_ptr = &o_list[c_ptr->o_idx];
1932 
1933 			/* Magma/Quartz + Known Gold */
1934 			if ((c_ptr->feat == FEAT_MAGMA_K) ||
1935 			    (c_ptr->feat == FEAT_QUARTZ_K) ||
1936 			    (c_ptr->feat == FEAT_SANDWALL_K)) {
1937 				/* Notice detected gold */
1938 				if (!(*w_ptr & CAVE_MARK)) {
1939 					/* Detect */
1940 					detect = TRUE;
1941 					/* Hack -- memorize the feature */
1942 					*w_ptr |= CAVE_MARK;
1943 					/* Redraw */
1944 					lite_spot(Ind, y, x);
1945 				}
1946 			}
1947 
1948 			/* Notice embedded gold */
1949 			if ((c_ptr->feat == FEAT_MAGMA_H) ||
1950 			    (c_ptr->feat == FEAT_QUARTZ_H) ||
1951 			    (c_ptr->feat == FEAT_SANDWALL_H)) {
1952 				/* Expose the gold */
1953 				c_ptr->feat += 0x02;
1954 				/* Detect */
1955 				detect = TRUE;
1956 				/* Hack -- memorize the item */
1957 				*w_ptr |= CAVE_MARK;
1958 				/* Redraw */
1959 				lite_spot(Ind, y, x);
1960 			}
1961 
1962 			/* Notice gold */
1963 			if (o_ptr->tval == TV_GOLD) {
1964 				/* Notice new items */
1965 				if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
1966 					/* Detect */
1967 					detect = TRUE;
1968 					/* Hack -- memorize the item */
1969 					p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
1970 					/* Redraw */
1971 					lite_spot(Ind, y, x);
1972 				}
1973 			}
1974 		}
1975 	}
1976 	return (detect);
1977 }
1978 
1979 
1980 
1981 /*
1982  * Detect magic items.
1983  *
1984  * This will light up all spaces with "magic" items, including artifacts,
1985  * ego-items, potions, scrolls, books, rods, wands, staves, amulets, rings,
1986  * and "enchanted" items of the "good" variety.
1987  *
1988  * It can probably be argued that this function is now too powerful.
1989  */
detect_magic(int Ind,int rad)1990 bool detect_magic(int Ind, int rad) {
1991 	player_type *p_ptr = Players[Ind];
1992 
1993 	struct worldpos *wpos = &p_ptr->wpos;
1994 	dun_level *l_ptr;
1995 //	int py = p_ptr->py, px = p_ptr->px;
1996 
1997 	int	i, j, tv;
1998 	bool	detect = FALSE;
1999 
2000 	cave_type	*c_ptr;
2001 	object_type	*o_ptr;
2002 
2003 	cave_type **zcave;
2004 
2005 	/* anti-exploit */
2006 	if (!local_panel(Ind)) return FALSE;
2007 
2008 	if (!(zcave = getcave(wpos))) return(FALSE);
2009 	l_ptr = getfloor(wpos);
2010 
2011 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2012 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2013 
2014 	/* Scan the current panel */
2015 //	for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2016 	for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2017 //		for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2018 		for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2019 			/* Reject locations outside of dungeon */
2020 			if (!in_bounds4(l_ptr, i, j)) continue;
2021 
2022 			/* Reject those out of radius */
2023 			if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2024 
2025 			/* Access the grid and object */
2026 			c_ptr = &zcave[i][j];
2027 			o_ptr = &o_list[c_ptr->o_idx];
2028 
2029 			/* Nothing there */
2030 			if (!(c_ptr->o_idx)) continue;
2031 
2032 			/* Examine the tval */
2033 			tv = o_ptr->tval;
2034 
2035 			/* Artifacts, misc magic items, or enchanted wearables */
2036 			if (artifact_p(o_ptr) || ego_item_p(o_ptr) ||
2037 			    (tv == TV_AMULET) || (tv == TV_RING) ||
2038 			    is_magic_device(tv) ||
2039 			    (tv == TV_SCROLL) || (tv == TV_POTION) ||
2040 			    ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
2041 			{
2042 				/* Note new items */
2043 				if (!(p_ptr->obj_vis[c_ptr->o_idx]))
2044 				{
2045 					/* Detect */
2046 					detect = TRUE;
2047 
2048 					/* Memorize the item */
2049 					p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
2050 
2051 					/* Redraw */
2052 					lite_spot(Ind, i, j);
2053 				}
2054 			}
2055 		}
2056 	}
2057 
2058 	/* Return result */
2059 	return (detect);
2060 }
2061 
2062 
2063 
2064 
2065 /*
2066  * A "generic" detect monsters routine, tagged to flags3
2067  */
2068 //bool detect_monsters_xxx(u32b match_flag, int rad)
detect_monsters_xxx(int Ind,u32b match_flag)2069 bool detect_monsters_xxx(int Ind, u32b match_flag) {
2070 	player_type *p_ptr = Players[Ind];
2071 	int  i, y, x;
2072 	bool flag = FALSE;
2073 	cptr desc_monsters = "weird monsters";
2074 
2075 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
2076 
2077 	/* anti-exploit */
2078 	if (!local_panel(Ind)) return FALSE;
2079 
2080 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2081 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2082 
2083 	/* Clear previously detected stuff */
2084 	clear_ovl(Ind);
2085 
2086 	/* Scan monsters */
2087 	for (i = 1; i < m_max; i++) {
2088 		monster_type *m_ptr = &m_list[i];
2089 		monster_race *r_ptr = race_inf(m_ptr);
2090 
2091 		/* Skip dead monsters */
2092 		if (!m_ptr->r_idx) continue;
2093 
2094 		/* Skip visible monsters */
2095 		if (p_ptr->mon_vis[i]) continue;
2096 
2097 		/* Skip monsters not on this depth */
2098 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2099 
2100 		/* Location */
2101 		y = m_ptr->fy;
2102 		x = m_ptr->fx;
2103 
2104 		/* Only detect nearby monsters */
2105 		// if (m_ptr->cdis > rad) continue;
2106 
2107 		/* Detect evil monsters */
2108 		if (!panel_contains(y, x)) continue;
2109 
2110 		/* Detect evil monsters */
2111 		if (r_ptr->flags3 & (match_flag)) {
2112 			byte a;
2113 			char c;
2114 
2115 			/* Hack - Temporarily visible */
2116 			p_ptr->mon_vis[i] = TRUE;
2117 
2118 			/* Get the look of the monster */
2119 			map_info(Ind, y, x, &a, &c);
2120 
2121 			/* No longer visible */
2122 			p_ptr->mon_vis[i] = FALSE;
2123 
2124 			/* Draw the monster on the screen */
2125 			draw_spot_ovl(Ind, y, x, a, c);
2126 
2127 			flag = TRUE;
2128 		}
2129 	}
2130 
2131 	switch (match_flag) {
2132 		case RF3_EVIL:
2133 			desc_monsters = "evil";
2134 			break;
2135 		case RF3_DEMON:
2136 			desc_monsters = "demons";
2137 			break;
2138 		case RF3_UNDEAD:
2139 			desc_monsters = "the undead";
2140 			break;
2141 		case RF3_GOOD:
2142 			desc_monsters = "good";
2143 			break;
2144 		case RF3_ORC:
2145 			desc_monsters = "orcs";
2146 			break;
2147 			/* TODO: ...you know :) */
2148 	}
2149 
2150 	/* Describe */
2151 	if (flag) {
2152 		/* Describe result */
2153 		msg_format(Ind, "You sense the presence of %s!", desc_monsters);
2154 		//msg_print(NULL);
2155 
2156 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2157 		/* Wait */
2158 		Send_pause(Ind);
2159 
2160 		/* Mega-Hack -- Fix the monsters */
2161 		update_monsters(FALSE);
2162 #endif
2163 	} else {
2164 #ifdef DETECT_ABSENCE
2165 		/* Describe result */
2166 		msg_format(Ind, "You sense the absence of %s.", desc_monsters);
2167 #endif
2168 	}
2169 
2170 	/* Result */
2171 	return (flag);
2172 }
2173 
2174 
2175 
2176 /*
2177  * Locates and displays all invisible creatures on current panel -RAK-
2178  */
detect_invisible(int Ind)2179 bool detect_invisible(int Ind) {
2180 	player_type *p_ptr = Players[Ind];
2181 
2182 	int		i;
2183 	bool	flag = FALSE;
2184 
2185 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
2186 
2187 	/* anti-exploit */
2188 	if (!local_panel(Ind)) return FALSE;
2189 
2190 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2191 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2192 
2193 	/* Clear previously detected stuff */
2194 	clear_ovl(Ind);
2195 
2196 	/* Detect all invisible monsters */
2197 	for (i = 1; i < m_max; i++) {
2198 		monster_type *m_ptr = &m_list[i];
2199                 monster_race *r_ptr = race_inf(m_ptr);
2200 
2201 		int fy = m_ptr->fy;
2202 		int fx = m_ptr->fx;
2203 
2204 		/* Paranoia -- Skip dead monsters */
2205 		if (!m_ptr->r_idx) continue;
2206 
2207 		/* Skip visible monsters */
2208 		if (p_ptr->mon_vis[i]) continue;
2209 
2210 		/* Skip monsters not on this depth */
2211 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2212 
2213 		/* Detect all invisible monsters */
2214 		if (panel_contains(fy, fx) && (r_ptr->flags2 & RF2_INVISIBLE)) {
2215 			byte a;
2216 			char c;
2217 
2218 #ifdef OLD_MONSTER_LORE
2219 			/* Take note that they are invisible */
2220 			r_ptr->r_flags2 |= RF2_INVISIBLE;
2221 #endif
2222 
2223 			/* Hack - Temporarily visible */
2224 			p_ptr->mon_vis[i] = TRUE;
2225 
2226 			/* Get the look of the monster */
2227 			map_info(Ind, fy, fx, &a, &c);
2228 
2229 			/* No longer visible */
2230 			p_ptr->mon_vis[i] = FALSE;
2231 
2232 			/* Draw the monster on the screen */
2233 			draw_spot_ovl(Ind, fy, fx, a, c);
2234 
2235 			flag = TRUE;
2236 		}
2237 	}
2238 
2239 	/* Detect all invisible players */
2240 	for (i = 1; i <= NumPlayers; i++) {
2241 		player_type *q_ptr = Players[i];
2242 
2243 		int py = q_ptr->py;
2244 		int px = q_ptr->px;
2245 
2246 		/* Skip disconnected players */
2247 		if (q_ptr->conn == NOT_CONNECTED) continue;
2248 
2249 		/* Skip oneself */
2250 		if (i == Ind) continue;
2251 
2252 		/* Skip visible players */
2253 		if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) continue;
2254 
2255 		/* Skip the dungeon master */
2256 		if (q_ptr->admin_dm && !player_sees_dm(Ind)) continue;
2257 
2258 		/* Detect all invisible players but not the dungeon master */
2259 		if (panel_contains(py, px) && q_ptr->ghost)  {
2260 			byte a;
2261 			char c;
2262 
2263 			/* Hack - Temporarily visible */
2264 			p_ptr->play_vis[i] = TRUE;
2265 
2266 			/* Get the look of the player */
2267 			map_info(Ind, py, px, &a, &c);
2268 
2269 			/* No longer visible */
2270 			p_ptr->mon_vis[i] = FALSE;
2271 
2272 			/* Draw the player on the screen */
2273 			draw_spot_ovl(Ind, py, px, a, c);
2274 
2275 			flag = TRUE;
2276 		}
2277 	}
2278 
2279 	/* Describe result, and clean up */
2280 	if (flag) {
2281 		/* Describe, and wait for acknowledgement */
2282 		msg_print(Ind, "You sense the presence of invisible creatures!");
2283 		msg_print(Ind, NULL);
2284 
2285 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2286 		/* Wait */
2287 		Send_pause(Ind);
2288 
2289 		/* Mega-Hack -- Fix the monsters and players */
2290 		update_monsters(FALSE);
2291 		update_players();
2292 #endif
2293 	} else {
2294 #ifdef DETECT_ABSENCE
2295 		msg_print(Ind, "You sense the absence of invisible creatures.");
2296 		msg_print(Ind, NULL);
2297 #endif
2298 	}
2299 
2300 	/* Result */
2301 	return (flag);
2302 }
2303 
2304 
2305 
2306 /*
2307  * Display evil creatures on current panel		-RAK-
2308  */
2309 #if 0
2310 bool detect_evil(int Ind) {
2311 	player_type *p_ptr = Players[Ind];
2312 
2313 	int		i;
2314 	bool	flag = FALSE;
2315 
2316 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
2317 
2318 	/* anti-exploit */
2319 	if (!local_panel(Ind)) return FALSE;
2320 
2321 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2322 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2323 
2324 	/* Clear previously detected stuff */
2325 	clear_ovl(Ind);
2326 
2327 	/* Display all the evil monsters */
2328 	for (i = 1; i < m_max; i++) {
2329 		monster_type *m_ptr = &m_list[i];
2330                 monster_race *r_ptr = race_inf(m_ptr);
2331 
2332 		int fy = m_ptr->fy;
2333 		int fx = m_ptr->fx;
2334 
2335 		/* Paranoia -- Skip dead monsters */
2336 		if (!m_ptr->r_idx) continue;
2337 
2338 		/* Skip visible monsters */
2339 		if (p_ptr->mon_vis[i]) continue;
2340 
2341 		/* Skip monsters not on this depth */
2342 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2343 
2344 		/* Detect evil monsters */
2345 		if (panel_contains(fy, fx) && (r_ptr->flags3 & RF3_EVIL)) {
2346 			byte a;
2347 			char c;
2348 
2349 			/* Hack - Temporarily visible */
2350 			p_ptr->mon_vis[i] = TRUE;
2351 
2352 			/* Get the look of the monster */
2353 			map_info(Ind, fy, fx, &a, &c);
2354 
2355 			/* No longer visible */
2356 			p_ptr->mon_vis[i] = FALSE;
2357 
2358 			/* Draw the monster on the screen */
2359 			draw_spot_ovl(Ind, fy, fx, a, c);
2360 
2361 			flag = TRUE;
2362 		}
2363 	}
2364 
2365 	/* Note effects and clean up */
2366 	if (flag) {
2367 		/* Describe, and wait for acknowledgement */
2368 		msg_print(Ind, "You sense the presence of evil!");
2369 		msg_print(Ind, NULL);
2370 
2371 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2372 		/* Wait */
2373 		Send_pause(Ind);
2374 
2375 		/* Mega-Hack -- Fix the monsters */
2376 		update_monsters(FALSE);
2377 #endif
2378 	}
2379     else {
2380 #ifdef DETECT_ABSENCE
2381 	msg_print(Ind, "You sense the absence of evil.");
2382 	msg_print(Ind, NULL);
2383 #endif
2384     }
2385 
2386 	/* Result */
2387 	return (flag);
2388 }
2389 #else
detect_evil(int Ind)2390 bool detect_evil(int Ind) {
2391 	return(detect_monsters_xxx(Ind, RF3_EVIL));
2392 }
2393 #endif	// 0
2394 
2395 
2396 
2397 /*
2398  * Display all non-invisible monsters/players on the current panel
2399  */
detect_creatures(int Ind)2400 bool detect_creatures(int Ind) {
2401 	player_type *p_ptr = Players[Ind];
2402 
2403 	int	i;
2404 	bool	flag = FALSE;
2405 
2406 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
2407 
2408 	/* anti-exploit */
2409 	if (!local_panel(Ind)) return FALSE;
2410 
2411 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2412 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2413 
2414 	/* Clear previously detected stuff */
2415 	clear_ovl(Ind);
2416 
2417 	/* Detect non-invisible monsters */
2418 	for (i = 1; i < m_max; i++) {
2419 		monster_type *m_ptr = &m_list[i];
2420 		monster_race *r_ptr = race_inf(m_ptr);
2421 
2422 		int fy = m_ptr->fy;
2423 		int fx = m_ptr->fx;
2424 
2425 		/* Paranoia -- Skip dead monsters */
2426 		if (!m_ptr->r_idx) continue;
2427 
2428 		/* Skip visible monsters */
2429 		if (p_ptr->mon_vis[i]) continue;
2430 
2431 		/* Skip monsters not on this depth */
2432 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2433 
2434 		/* Detect all non-invisible monsters */
2435 		if (panel_contains(fy, fx) && (!(r_ptr->flags2 & RF2_INVISIBLE))) {
2436 			byte a;
2437 			char c;
2438 
2439 			/* Hack - Temporarily visible */
2440 			p_ptr->mon_vis[i] = TRUE;
2441 
2442 			/* Get the look of the monster */
2443 			map_info(Ind, fy, fx, &a, &c);
2444 
2445 			/* No longer visible */
2446 			p_ptr->mon_vis[i] = FALSE;
2447 
2448 			/* Draw the monster on the screen */
2449 			draw_spot_ovl(Ind, fy, fx, a, c);
2450 
2451 			flag = TRUE;
2452 		}
2453 	}
2454 
2455 	/* Detect non-invisible players */
2456 	for (i = 1; i <= NumPlayers; i++) {
2457 		player_type *q_ptr = Players[i];
2458 
2459 		int py = q_ptr->py;
2460 		int px = q_ptr->px;
2461 
2462 		/* Skip disconnected players */
2463 		if (q_ptr->conn == NOT_CONNECTED) continue;
2464 
2465 		/* Never detect the dungeon master! */
2466 		if (q_ptr->admin_dm && !player_sees_dm(Ind)) continue;
2467 
2468 		/* Skip visible players */
2469 		if (p_ptr->play_vis[i]) continue;
2470 
2471 		/* Skip players not on this depth */
2472 		if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) continue;
2473 
2474 		/* Skip ourself */
2475 		if (i == Ind) continue;
2476 
2477 		/* Detect all non-invisible players */
2478 		if (panel_contains(py, px) && !q_ptr->ghost) {
2479 			byte a;
2480 			char c;
2481 
2482 			/* Hack - Temporarily visible */
2483 			p_ptr->play_vis[i] = TRUE;
2484 
2485 			/* Get the look of the player */
2486 			map_info(Ind, py, px, &a, &c);
2487 
2488 			/* No longer visible */
2489 			p_ptr->play_vis[i] = FALSE;
2490 
2491 			/* Draw the player on the screen */
2492 			draw_spot_ovl(Ind, py, px, a, c);
2493 
2494 			flag = TRUE;
2495 		}
2496 	}
2497 
2498 	/* Describe and clean up */
2499 	if (flag) {
2500 		/* Describe, and wait for acknowledgement */
2501 		msg_print(Ind, "You sense the presence of creatures!");
2502 		msg_print(Ind, NULL);
2503 
2504 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2505 		/* Wait */
2506 		Send_pause(Ind);
2507 
2508 		/* Mega-Hack -- Fix the monsters and players */
2509 		update_monsters(FALSE);
2510 		update_players();
2511 #endif
2512 	} else {
2513 #ifdef DETECT_ABSENCE
2514 		msg_print(Ind, "You sense the absence of creatures.");
2515 		msg_print(Ind, NULL);
2516 #endif
2517 	}
2518 
2519 	/* Result */
2520 	return (flag);
2521 }
2522 
2523 /*
2524  * Display all monsters on the current panel
2525  */
detect_monsters_forced(int Ind)2526 void detect_monsters_forced(int Ind) {
2527 	player_type *p_ptr = Players[Ind];
2528 	int	i;
2529 
2530 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
2531 
2532 	/* anti-exploit */
2533 	if (!local_panel(Ind)) return;
2534 
2535 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return;
2536 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return;
2537 
2538 	/* Clear previously detected stuff */
2539 	clear_ovl(Ind);
2540 
2541 	for (i = 1; i < m_max; i++) {
2542 		monster_type *m_ptr = &m_list[i];
2543 //		monster_race *r_ptr = race_inf(m_ptr);
2544 
2545 		int fy = m_ptr->fy;
2546 		int fx = m_ptr->fx;
2547 
2548 		byte a;
2549 		char c;
2550 
2551 		/* Paranoia -- Skip dead monsters */
2552 		if (!m_ptr->r_idx) continue;
2553 
2554 		/* Skip visible monsters */
2555 		if (p_ptr->mon_vis[i]) continue;
2556 
2557 		/* Skip monsters not on this depth */
2558 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2559 
2560 		/* Hack - Temporarily visible */
2561 		p_ptr->mon_vis[i] = TRUE;
2562 
2563 		/* Get the look of the monster */
2564 		map_info(Ind, fy, fx, &a, &c);
2565 
2566 		/* No longer visible */
2567 		p_ptr->mon_vis[i] = FALSE;
2568 
2569 		/* Draw the monster on the screen */
2570 		draw_spot_ovl(Ind, fy, fx, a, c);
2571 	}
2572 }
2573 
2574 
2575 /*
2576  * Detect everything
2577  */
detection(int Ind,int rad)2578 bool detection(int Ind, int rad) {
2579 	bool	detect = FALSE;
2580 
2581 	/* Detect the easy things */
2582 	if (detect_treasure(Ind, rad)) detect = TRUE;
2583 	if (detect_object(Ind, rad)) detect = TRUE;
2584 	if (detect_trap(Ind, rad)) detect = TRUE;
2585 	if (detect_sdoor(Ind, rad)) detect = TRUE;
2586 	if (detect_creatures(Ind)) detect = TRUE;	/* not radius-ed for now */
2587 
2588 	/* Result */
2589 	return (detect);
2590 }
2591 
2592 #if 1
2593 /*
2594  * Detect bounty, a rogue's skill
2595  */
detect_bounty(int Ind,int rad)2596 bool detect_bounty(int Ind, int rad) {
2597 	player_type *p_ptr = Players[Ind];
2598 
2599 	// 10 ... 60 % of auto-detecting "stuff"
2600 	int chance = (p_ptr->lev) + 10;
2601 
2602 	struct worldpos *wpos = &p_ptr->wpos;
2603 	dun_level *l_ptr;
2604 
2605 	int i, j, t_idx = 0;
2606 
2607 	bool	detect = FALSE;
2608 	bool	detect_trap = FALSE;
2609 
2610 	cave_type  *c_ptr;
2611 	byte *w_ptr;
2612 	cave_type **zcave;
2613 	struct c_special *cs_ptr;
2614 
2615 	object_type	*o_ptr;
2616 
2617 	/* anti-exploit */
2618 	if (!local_panel(Ind)) return FALSE;
2619 
2620 	if (!(zcave = getcave(wpos))) return(FALSE);
2621 
2622 	l_ptr = getfloor(wpos);
2623 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2624 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2625 
2626 
2627 	/* Scan the current panel */
2628 	for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2629 		for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2630 			/* Reject locations outside of dungeon */
2631 			if (!in_bounds4(l_ptr, i, j)) continue;
2632 
2633 			/* Reject those out of radius */
2634 			if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2635 
2636 			/* Access the grid */
2637 			c_ptr = &zcave[i][j];
2638 			w_ptr = &p_ptr->cave_flag[i][j];
2639 
2640 			o_ptr = &o_list[c_ptr->o_idx];
2641 
2642 			detect_trap = FALSE;
2643 
2644 			/* Detect traps on chests */
2645 			if ((c_ptr->o_idx) && (o_ptr->tval == TV_CHEST)
2646 			    && p_ptr->obj_vis[c_ptr->o_idx] && (o_ptr->pval)
2647 			    && !object_known_p(Ind, o_ptr) && magik(chance)) {
2648 				/* Message =-p */
2649 				msg_print(Ind, "You have discovered a trap on the chest!");
2650 				/* Know the trap */
2651 				object_known(o_ptr);
2652 				/* Notice it */
2653 //				disturb(Ind, 0, 0);
2654 				detect = TRUE;
2655 			}
2656 
2657 			/* Detect invisible traps */
2658 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS)) && magik(chance)) {
2659 				t_idx = cs_ptr->sc.trap.t_idx;
2660 
2661 				if (!cs_ptr->sc.trap.found) {
2662 					/* Pick a trap */
2663 					pick_trap(wpos, i, j);
2664 				}
2665 
2666 				/* Hack -- memorize it */
2667 				*w_ptr |= CAVE_MARK;
2668 
2669 				/* Obvious */
2670 				detect = TRUE;
2671 				detect_trap = TRUE;
2672 			}
2673 
2674 			/* Detect secret doors */
2675 			if (c_ptr->feat == FEAT_SECRET && magik(chance)) {
2676 				struct c_special *cs_ptr;
2677 
2678 				/* Clear mimic feature */
2679 				if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
2680 					cs_erase(c_ptr, cs_ptr);
2681 
2682 				/* Find the door XXX XXX XXX */
2683 				c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
2684 
2685 				/* Memorize the door */
2686 				*w_ptr |= CAVE_MARK;
2687 
2688 				/* Obvious */
2689 				detect = TRUE;
2690 			}
2691 
2692 			// You feel a gust of air from nearby ...
2693 			if (((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_MORE) ||
2694 			    (c_ptr->feat == FEAT_WAY_LESS) || (c_ptr->feat == FEAT_WAY_MORE))
2695 				&& magik(chance)) {
2696 
2697 				/* Memorize the stairs */
2698 				*w_ptr |= CAVE_MARK;
2699 
2700 				/* Obvious */
2701 				detect = TRUE;
2702 			}
2703 
2704 			// You hear a jingle of coins nearby ...
2705 			if (c_ptr->feat == FEAT_SHOP && magik(chance)) {
2706 				/* Memorize the stairs */
2707 				*w_ptr |= CAVE_MARK;
2708 
2709 				/* Obvious */
2710 				detect = TRUE;
2711 			}
2712 			if (detect) lite_spot(Ind, i, j);
2713 			if (detect_trap) {
2714 				if (c_ptr->o_idx && !c_ptr->m_idx) {
2715 					byte a = get_trap_color(Ind, t_idx, c_ptr->feat);
2716 
2717 					/* Hack - Always show traps under items when detecting - mikaelh */
2718 					draw_spot_ovl(Ind, i, j, a, '^');
2719 				} else {
2720 					/* Normal redraw */
2721 					lite_spot(Ind, i, j);
2722 				}
2723 			}
2724 		}
2725 	}
2726 	return (detect);
2727 }
2728 #endif
2729 
2730 /*
2731  * Detect all objects on the current panel		-RAK-
2732  */
detect_object(int Ind,int rad)2733 bool detect_object(int Ind, int rad) {
2734 	player_type *p_ptr = Players[Ind];
2735 
2736 	struct worldpos *wpos = &p_ptr->wpos;
2737 	dun_level *l_ptr;
2738 	//int py = p_ptr->py, px = p_ptr->px;
2739 
2740 	int	i, j;
2741 	bool	detect = FALSE;
2742 
2743 	cave_type	*c_ptr;
2744 	object_type	*o_ptr;
2745 	cave_type **zcave;
2746 
2747 
2748 	/* anti-exploit */
2749 	if (!local_panel(Ind)) return FALSE;
2750 
2751 	if (!(zcave = getcave(wpos))) return(FALSE);
2752 	l_ptr = getfloor(wpos);
2753 
2754 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2755 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2756 
2757 	/* Scan the current panel */
2758 //	for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2759 	for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2760 //		for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2761 		for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2762 			/* Reject locations outside of dungeon */
2763 			if (!in_bounds4(l_ptr, i, j)) continue;
2764 
2765 			/* Reject those out of radius */
2766 			if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2767 
2768 			c_ptr = &zcave[i][j];
2769 
2770 			o_ptr = &o_list[c_ptr->o_idx];
2771 
2772 			/* Nothing here */
2773 			if (!(c_ptr->o_idx)) continue;
2774 
2775 			/* Do not detect "gold" */
2776 			if (o_ptr->tval == TV_GOLD) continue;
2777 
2778 			/* Note new objects */
2779 			if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
2780 				/* Detect */
2781 				detect = TRUE;
2782 
2783 				/* Hack -- memorize it */
2784 				p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
2785 
2786 				/* Redraw */
2787 				lite_spot(Ind, i, j);
2788 			}
2789 		}
2790 	}
2791 
2792 	return (detect);
2793 }
2794 
2795 
2796 /*
2797  * Locates and displays traps on current panel
2798  */
2799 //bool detect_trap(int Ind)
detect_trap(int Ind,int rad)2800 bool detect_trap(int Ind, int rad) {
2801 	player_type *p_ptr = Players[Ind];
2802 
2803 	struct worldpos *wpos = &p_ptr->wpos;
2804 	dun_level *l_ptr;
2805 //	int	py = p_ptr->py, px = p_ptr->px;
2806 
2807 	int	i, j, t_idx;
2808 	bool	detect = FALSE;
2809 
2810 	cave_type  *c_ptr;
2811 	byte *w_ptr;
2812 	cave_type **zcave;
2813 	struct c_special *cs_ptr;
2814 
2815 	object_type	*o_ptr;
2816 
2817 
2818 	/* anti-exploit */
2819 	if (!local_panel(Ind)) return FALSE;
2820 
2821 	if (!(zcave = getcave(wpos))) return(FALSE);
2822 	l_ptr = getfloor(wpos);
2823 
2824 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2825 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2826 
2827 	/* Clear previously detected stuff */
2828 	clear_ovl(Ind);
2829 
2830 	/* Scan the current panel */
2831 //	for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2832 	for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2833 //		for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2834 		for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2835 			/* Reject locations outside of dungeon */
2836 			if (!in_bounds4(l_ptr, i, j)) continue;
2837 
2838 			/* Reject those out of radius */
2839 			if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2840 
2841 			/* Access the grid */
2842 			c_ptr = &zcave[i][j];
2843 			w_ptr = &p_ptr->cave_flag[i][j];
2844 
2845 			/* Hack - traps on undetected doors cannot be found */
2846 /*			if (c_ptr->feat == FEAT_DOOR_TAIL + 1) continue;	--hmm why not */
2847 
2848 			/* Detect traps on chests */
2849                         o_ptr = &o_list[c_ptr->o_idx];
2850                         if ((c_ptr->o_idx) && (o_ptr->tval == TV_CHEST) && (o_ptr->pval) && (!object_known_p(Ind, o_ptr))) {
2851 				object_known(o_ptr);
2852 
2853 				/* New trap detected */
2854 				detect = TRUE;
2855 			}
2856 
2857 			/* Detect invisible traps */
2858 			//			if (c_ptr->feat == FEAT_INVIS)
2859 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
2860 				t_idx = cs_ptr->sc.trap.t_idx;
2861 
2862 				if (!cs_ptr->sc.trap.found) {
2863 					/* Pick a trap */
2864 					pick_trap(wpos, i, j);
2865 
2866 					/* New trap detected */
2867 					detect = TRUE;
2868 				}
2869 
2870 				/* Hack -- memorize it */
2871 				*w_ptr |= CAVE_MARK;
2872 
2873 				/* Redraw */
2874 				lite_spot(Ind, i, j);
2875 
2876 				if (c_ptr->o_idx && !c_ptr->m_idx) {
2877 					byte a = get_trap_color(Ind, t_idx, c_ptr->feat);
2878 
2879 					/* Hack - Always show traps under items when detecting - mikaelh */
2880 					draw_spot_ovl(Ind, i, j, a, '^');
2881 				} else {
2882 					/* Normal redraw */
2883 					lite_spot(Ind, i, j);
2884 				}
2885 
2886 #if 0
2887 				/* Already seen traps */
2888 				else if (c_ptr->feat >= FEAT_TRAP_HEAD && c_ptr->feat <= FEAT_TRAP_TAIL) {
2889 					/* Memorize it */
2890 					*w_ptr |= CAVE_MARK;
2891 
2892 					/* Redraw */
2893 					lite_spot(Ind, i, j);
2894 
2895 					/* Obvious */
2896 					detect = TRUE;
2897 				}
2898 #endif	// 0
2899 			}
2900 		}
2901 	}
2902 
2903 	if (detect) {
2904 		msg_print(Ind, "You have detected new traps.");
2905 	} else {
2906 #ifdef DETECT_ABSENCE
2907 		msg_print(Ind, "You have detected no new traps.");
2908 #endif
2909 	}
2910 
2911 	return (detect);
2912 }
2913 
2914 
2915 
2916 /*
2917  * Locates and displays all stairs and secret doors on current panel -RAK-
2918  */
detect_sdoor(int Ind,int rad)2919 bool detect_sdoor(int Ind, int rad) {
2920 	player_type *p_ptr = Players[Ind];
2921 
2922 	struct worldpos *wpos = &p_ptr->wpos;
2923 	dun_level *l_ptr;
2924 	//int py = p_ptr->py, px = p_ptr->px;
2925 
2926 	int		i, j;
2927 	bool	detect = FALSE;
2928 
2929 	cave_type *c_ptr;
2930 	byte *w_ptr;
2931 	cave_type **zcave;
2932 
2933 	/* anti-exploit */
2934 	if (!local_panel(Ind)) return FALSE;
2935 
2936 	if (!(zcave = getcave(wpos))) return(FALSE);
2937 	l_ptr = getfloor(wpos);
2938 
2939 	if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2940 	if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2941 
2942 	/* Scan the panel */
2943 //	for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2944 	for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2945 //		for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2946 		for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2947 			/* Reject locations outside of dungeon */
2948 			if (!in_bounds4(l_ptr, i, j)) continue;
2949 
2950 			/* Reject those out of radius */
2951 			if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2952 
2953 			/* Access the grid and object */
2954 			c_ptr = &zcave[i][j];
2955 			w_ptr = &p_ptr->cave_flag[i][j];
2956 
2957 			/* Hack -- detect secret doors */
2958 			if (c_ptr->feat == FEAT_SECRET) {
2959 				struct c_special *cs_ptr;
2960 
2961 				/* Clear mimic feature */
2962 				if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
2963 					cs_erase(c_ptr, cs_ptr);
2964 
2965 				/* Find the door XXX XXX XXX */
2966 				c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
2967 
2968 				/* Memorize the door */
2969 				*w_ptr |= CAVE_MARK;
2970 
2971 				/* Redraw */
2972 				lite_spot(Ind, i, j);
2973 
2974 				/* Obvious */
2975 				detect = TRUE;
2976 			}
2977 
2978 			/* Ignore known grids */
2979 			if (*w_ptr & CAVE_MARK) continue;
2980 
2981 			/* Hack -- detect stairs */
2982 			if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_MORE) ||
2983 			    (c_ptr->feat == FEAT_WAY_LESS) || (c_ptr->feat == FEAT_WAY_MORE))
2984 			{
2985 				/* Memorize the stairs */
2986 				*w_ptr |= CAVE_MARK;
2987 
2988 				/* Redraw */
2989 				lite_spot(Ind, i, j);
2990 
2991 				/* Obvious */
2992 				detect = TRUE;
2993 			}
2994 
2995 			/* Hack -- detect dungeon shops */
2996 			if (c_ptr->feat == FEAT_SHOP) {
2997 				/* Memorize the stairs */
2998 				*w_ptr |= CAVE_MARK;
2999 
3000 				/* Redraw */
3001 				lite_spot(Ind, i, j);
3002 
3003 				/* Obvious */
3004 				detect = TRUE;
3005 			}
3006 		}
3007 	}
3008 
3009 	return (detect);
3010 }
3011 
3012 
3013 /*
3014  * Create stairs at the player location
3015  */
stair_creation(int Ind)3016 void stair_creation(int Ind) {
3017 	player_type *p_ptr = Players[Ind];
3018 
3019 	/* Access the grid */
3020 	cave_type *c_ptr;
3021 
3022 	struct worldpos *wpos = &p_ptr->wpos;
3023 	cave_type **zcave;
3024 	if (!(zcave = getcave(wpos))) return;
3025 
3026 	/* Access the player grid */
3027 	c_ptr = &zcave[p_ptr->py][p_ptr->px];
3028 
3029 	/* XXX XXX XXX */
3030 	if (!cave_valid_bold(zcave, p_ptr->py, p_ptr->px)) {
3031 		msg_print(Ind, "The object resists the spell.");
3032 		return;
3033 	}
3034 
3035 	/* Hack -- Delete old contents */
3036 	delete_object(wpos, p_ptr->py, p_ptr->px, TRUE);
3037 
3038 	/* Create a staircase */
3039 	if (!can_go_down(wpos, 0x1) && !can_go_up(wpos, 0x1)) {
3040 		/* special..? */
3041 	} else if (can_go_down(wpos, 0x1) && !can_go_up(wpos, 0x1)) {
3042 		c_ptr->feat = FEAT_MORE;
3043 	} else if(can_go_up(wpos, 0x1) && !can_go_down(wpos, 0x1)) {
3044 		c_ptr->feat = FEAT_LESS;
3045 	} else if (rand_int(100) < 50) {
3046 		c_ptr->feat = FEAT_MORE;
3047 	} else {
3048 		c_ptr->feat = FEAT_LESS;
3049 	}
3050 
3051 	/* Notice */
3052 	note_spot(Ind, p_ptr->py, p_ptr->px);
3053 
3054 	/* Redraw */
3055 	everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
3056 }
3057 
3058 
3059 
3060 
3061 /*
3062  * Hook to specify "weapon"
3063  */
item_tester_hook_weapon(object_type * o_ptr)3064 static bool item_tester_hook_weapon(object_type *o_ptr) {
3065 	switch (o_ptr->tval) {
3066 	/* and now new.. :) */
3067 	case TV_TRAPKIT:
3068 		if (!is_firearm_trapkit(o_ptr->sval)) return FALSE;
3069 	case TV_SWORD:
3070 	case TV_BLUNT:
3071 	case TV_POLEARM:
3072 	case TV_DIGGING:
3073 	case TV_BOW:
3074 	case TV_BOLT:
3075 	case TV_ARROW:
3076 	case TV_SHOT:
3077 	case TV_MSTAFF:
3078 	case TV_BOOMERANG:
3079 	case TV_AXE:
3080 		return (TRUE);
3081 	}
3082 
3083 	return (FALSE);
3084 }
3085 
3086 
3087 /*
3088  * Hook to specify "armour"
3089  */
item_tester_hook_armour(object_type * o_ptr)3090 static bool item_tester_hook_armour(object_type *o_ptr) {
3091 	switch (o_ptr->tval) {
3092 	case TV_DRAG_ARMOR:
3093 	case TV_HARD_ARMOR:
3094 	case TV_SOFT_ARMOR:
3095 	case TV_SHIELD:
3096 	case TV_CLOAK:
3097 	case TV_CROWN:
3098 	case TV_HELM:
3099 	case TV_BOOTS:
3100 	case TV_GLOVES:
3101 	/* and now new.. :) */
3102 	//nope, not enchantable -- case TV_TRAPKIT:
3103 		return (TRUE);
3104 	}
3105 
3106 	return (FALSE);
3107 }
3108 
3109 
3110 
3111 /*
3112  * Enchants a plus onto an item.                        -RAK-
3113  *
3114  * Revamped!  Now takes item pointer, number of times to try enchanting,
3115  * and a flag of what to try enchanting.  Artifacts resist enchantment
3116  * some of the time, and successful enchantment to at least +0 might
3117  * break a curse on the item.  -CFT
3118  *
3119  * Note that an item can technically be enchanted all the way to +15 if
3120  * you wait a very, very, long time.  Going from +9 to +10 only works
3121  * about 5% of the time, and from +10 to +11 only about 1% of the time.
3122  *
3123  * Note that this function can now be used on "piles" of items, and
3124  * the larger the pile, the lower the chance of success.
3125  */
enchant(int Ind,object_type * o_ptr,int n,int eflag)3126 bool enchant(int Ind, object_type *o_ptr, int n, int eflag) {
3127 	player_type *p_ptr = Players[Ind];
3128 	int i, chance, prob;
3129 	bool res = FALSE;
3130 	bool a = like_artifact_p(o_ptr);
3131 	u32b f1, f2, f3, f4, f5, f6, esp;
3132 	bool did_tohit = FALSE, did_todam = FALSE, did_toac = FALSE;
3133 
3134 	/* Extract the flags */
3135 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
3136 
3137 	/* Unenchantable items always fail */
3138 	if (!is_enchantable(o_ptr)) return FALSE;
3139 	if (f5 & TR5_NO_ENCHANT) return (FALSE);
3140 	/* Artifacts cannot be enchanted. */
3141 	if (a) return (FALSE);
3142 
3143 	/* Large piles resist enchantment */
3144 	prob = o_ptr->number * 100;
3145 
3146 	/* Missiles are easy to enchant */
3147 	if (is_ammo(o_ptr->tval)) {
3148 		prob = prob / 20;
3149 	}
3150 
3151 	/* Try "n" times */
3152 	for (i = 0; i < n; i++) {
3153 		/* Hack -- Roll for pile resistance */
3154 		if (rand_int(prob) >= 100) continue;
3155 
3156 		/* Enchant to hit, but not that easily multiple times over 9 */
3157 		if ((eflag & ENCH_TOHIT) && (magik(30) || !(did_tohit && o_ptr->to_h > 9)))
3158 		{
3159 			if (o_ptr->to_h < 0) chance = 0;
3160 			else if (o_ptr->to_h > 14) chance = 1000;
3161 			else {
3162 				chance = enchant_table[o_ptr->to_h];
3163 				/* *Enchant Weapon* scrolls are better! */
3164 				if (n > 1) chance = ((chance * 1) / 3);
3165 			}
3166 
3167 			if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
3168 			{
3169 				o_ptr->to_h++;
3170 				res = TRUE;
3171 				did_tohit = TRUE;
3172 
3173 				/* only when you get it above -1 -CFT */
3174 				if (cursed_p(o_ptr) &&
3175 				    (!(f3 & TR3_PERMA_CURSE)) &&
3176 //				    (o_ptr->to_h >= 0) && (rand_int(100) < 25))
3177 				    (rand_int(100) < 10 + 10 * o_ptr->to_h))
3178 				{
3179 					msg_print(Ind, "The curse is broken!");
3180 					o_ptr->ident &= ~ID_CURSED;
3181 					o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3182 					note_toggle_cursed(o_ptr, FALSE);
3183 				}
3184 			}
3185 		}
3186 
3187 		/* Enchant to damage, but not that easily multiple times over 9 */
3188 		if ((eflag & ENCH_TODAM) && (magik(30) || !(did_todam && o_ptr->to_d > 9))) {
3189 			if (o_ptr->to_d < 0) chance = 0;
3190 			else if (o_ptr->to_d > 14) chance = 1000;
3191 			else {
3192 				chance = enchant_table[o_ptr->to_d];
3193 				/* *Enchant Weapon* scrolls are better! */
3194 				if (n > 1) chance = ((chance * 1) / 3);
3195 			}
3196 
3197 			if ((randint(1000) > chance) && (!a || (rand_int(100) < 50))) {
3198 				o_ptr->to_d++;
3199 				res = TRUE;
3200 				did_todam = TRUE;
3201 
3202 				/* only when you get it above -1 -CFT */
3203 				if (cursed_p(o_ptr) &&
3204 				    (!(f3 & TR3_PERMA_CURSE)) &&
3205 //				    (o_ptr->to_d >= 0) && (rand_int(100) < 25))
3206 				    (rand_int(100) < 10 + 10 * o_ptr->to_d))
3207 				{
3208 					msg_print(Ind, "The curse is broken!");
3209 					o_ptr->ident &= ~ID_CURSED;
3210 					o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3211 					note_toggle_cursed(o_ptr, FALSE);
3212 				}
3213 			}
3214 		}
3215 
3216 		/* Enchant to armor class, but not that easily multiple times over 9 */
3217 		if ((eflag & ENCH_TOAC) && (magik(30) || !(did_toac && o_ptr->to_a > 9))) {
3218 			if (o_ptr->to_a < 0) chance = 0;
3219 			else if (o_ptr->to_a > 14) chance = 1000;
3220 			else {
3221 				chance = enchant_table[o_ptr->to_a];
3222 				/* *Enchant Armour* scrolls are better! */
3223 				if (n > 1) chance = ((chance * 1) / 3);
3224 			}
3225 
3226 			if ((randint(1000) > chance) && (!a || (rand_int(100) < 50))) {
3227 				o_ptr->to_a++;
3228 				res = TRUE;
3229 				did_toac = TRUE;
3230 
3231 				/* only when you get it above -1 -CFT */
3232 				if (cursed_p(o_ptr) &&
3233 				    (!(f3 & TR3_PERMA_CURSE)) &&
3234 				    (o_ptr->to_a >= 0) && (rand_int(100) < 25)) {
3235 					msg_print(Ind, "The curse is broken!");
3236 					o_ptr->ident &= ~ID_CURSED;
3237 					o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3238 					note_toggle_cursed(o_ptr, FALSE);
3239 				}
3240 			}
3241 		}
3242 	}
3243 
3244 	/* Failure */
3245 	if (!res) return (FALSE);
3246 
3247 	/* Recalculate bonuses */
3248 	p_ptr->update |= (PU_BONUS);
3249 
3250 	/* Combine / Reorder the pack (later) */
3251 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3252 
3253 	/* Window stuff */
3254 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3255 
3256 	/* Resend plusses */
3257 	p_ptr->redraw |= (PR_PLUSSES);
3258 
3259 	/* Success */
3260 	return (TRUE);
3261 }
3262 
create_artifact(int Ind,bool nolife)3263 bool create_artifact(int Ind, bool nolife) {
3264 	player_type *p_ptr = Players[Ind];
3265 
3266 	/* just in case */
3267 	s_printf("(%s) Player %s initiates Artifact Creation (nolife=%d).\n", showtime(), p_ptr->name, nolife);
3268 
3269 	clear_current(Ind);
3270 
3271 	p_ptr->current_artifact = TRUE;
3272 	p_ptr->current_artifact_nolife = nolife;
3273 	get_item(Ind, ITH_NONE);
3274 
3275 	return TRUE;
3276 }
3277 
create_artifact_aux(int Ind,int item)3278 bool create_artifact_aux(int Ind, int item) {
3279 	player_type *p_ptr = Players[Ind];
3280 	object_type *o_ptr;
3281 	artifact_type *a_ptr;
3282 	int tries = 0;
3283 	char o_name[ONAME_LEN];
3284 	s32b old_owner;/* anti-cheeze :) */
3285 	u32b resf = make_resf(p_ptr);
3286 
3287 	/* Get the item (in the pack) */
3288 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
3289 	/* Get the item (on the floor) */
3290 	else o_ptr = &o_list[0 - item];
3291 
3292 	old_owner = o_ptr->owner;
3293 
3294 	/* Description */
3295 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
3296 	s_printf("ART_CREATION by player %s: %s\n", p_ptr->name, o_name);
3297 
3298 	if (((o_ptr->tval == TV_SOFT_ARMOR && o_ptr->sval == SV_SHIRT) ||
3299 	    (o_ptr->tval == TV_SPECIAL)) /* <- must be checked here, not in randart_make() due to seals, see randart_make(). */
3300 	     && !is_admin(p_ptr)) {
3301 		msg_print(Ind, "\376\377yThe item appears unchanged!");
3302 		return FALSE;
3303 	}
3304 	if (o_ptr->name1) {
3305 		msg_print(Ind, "\376\377yThe creation fails due to the powerful magic of the target object!");
3306 		return FALSE;
3307 	}
3308 	if (o_ptr->name2 || o_ptr->name2b) {
3309 		msg_print(Ind, "\376\377yThe creation fails due to the strong magic of the target object!");
3310 		return FALSE;
3311 		o_ptr->name2 = 0;
3312 		o_ptr->name2b = 0;
3313 		msg_print(Ind, "The strong magic of that object dissolves!");
3314 	}
3315 	if (o_ptr->number > 1) {
3316 /*		msg_print(Ind, "The creation fails because the magic is split to multiple targets!");
3317 		return FALSE;*/
3318 		o_ptr->number = 1;
3319 		msg_print(Ind, "The stack of objects magically dissolves, leaving only a single item!");
3320 	}
3321 
3322 	/* Describe */
3323 	msg_format(Ind, "%s %s glow%s *brightly*!",
3324 	    ((item >= 0) ? "Your" : "The"), o_name,
3325 	    ((o_ptr->number > 1) ? "" : "s"));
3326 
3327 	o_ptr->name1 = ART_RANDART;
3328 
3329 /* NOTE: MAKE SURE THE FOLLOWING CODE IS CONSISTENT WITH make_artifact() IN object2.c! */
3330 
3331 	/* Randart loop. Try until an allowed randart was made */
3332 	while (tries < 10) {
3333 		tries++;
3334 
3335 		/* Piece together a 32-bit random seed */
3336 		o_ptr->name3 = rand_int(0xFFFF) << 16;
3337 		o_ptr->name3 += rand_int(0xFFFF);
3338 
3339 		/* Check the tval is allowed */
3340 		if (randart_make(o_ptr) == NULL) {
3341 			/* If not, wipe seed. No randart today */
3342 			o_ptr->name1 = 0;
3343 			o_ptr->name3 = 0L;
3344 
3345 			msg_print(Ind, "The item appears unchanged!");
3346 			return FALSE;
3347 		}
3348 
3349 		/* If the resulting randart is allowed, leave the loop */
3350 		a_ptr = randart_make(o_ptr);
3351 		if (((resf & RESF_LIFE) && !p_ptr->current_artifact_nolife) || !(a_ptr->flags1 & TR1_LIFE)) break;
3352 	}
3353 
3354 	/* apply magic (which resets owner) and manually restore ownership again afterwards;
3355 	   apply_magic() is used to set level requirements, and copy the a_ptr to o_ptr. */
3356 	apply_magic(&p_ptr->wpos, o_ptr, 50, FALSE, FALSE, FALSE, FALSE, RESF_NONE);
3357 	o_ptr->owner = old_owner;
3358 
3359 	/* Hack - lose discount on item, looks bad/silly */
3360 	o_ptr->discount = 0;
3361 	o_ptr->note = 0;
3362 
3363 	/* Recalculate bonuses */
3364 	p_ptr->update |= (PU_BONUS);
3365 
3366 	/* Combine / Reorder the pack (later) */
3367 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3368 
3369 	/* Window stuff */
3370 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3371 
3372 	/* Art creation finished */
3373 	p_ptr->current_artifact = FALSE;
3374 	p_ptr->current_artifact_nolife = FALSE;
3375 
3376 	/* Log it (security) */
3377 	/* Description */
3378 	object_desc(Ind, o_name, o_ptr, FALSE, 3);
3379 	s_printf("ART_CREATION succeeded: %s\n", o_name);
3380 
3381 	/* Did we use up an item? (minus 1 art scroll) */
3382 	if (p_ptr->using_up_item >= 0) {
3383 		inven_item_describe(Ind, p_ptr->using_up_item);
3384 		inven_item_optimize(Ind, p_ptr->using_up_item);
3385 		p_ptr->using_up_item = -1;
3386 	}
3387 
3388 	return TRUE;
3389 }
3390 
curse_spell(int Ind)3391 bool curse_spell(int Ind) {	// could be void
3392 	player_type *p_ptr = Players[Ind];
3393 	clear_current(Ind);
3394 	get_item(Ind, ITH_NONE);
3395 	p_ptr->current_curse = TRUE;	/* This is awful. I intend to change it */
3396 	return TRUE;
3397 }
3398 
curse_spell_aux(int Ind,int item)3399 bool curse_spell_aux(int Ind, int item)
3400 {
3401 	player_type *p_ptr = Players[Ind];
3402 	object_type *o_ptr = &p_ptr->inventory[item];
3403 	char o_name[ONAME_LEN];
3404 
3405 	p_ptr->current_curse = FALSE;
3406 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
3407 
3408 
3409 	if (artifact_p(o_ptr) && (randint(10) < 8)) {
3410 		msg_print(Ind,"The artifact resists your attempts.");
3411 		return(FALSE);
3412 	}
3413 
3414 	if (item_tester_hook_weapon(o_ptr)) {
3415 		o_ptr->to_h = 0 - (randint(10) + 1);
3416 		o_ptr->to_d = 0 - (randint(10) + 1);
3417 	} else if (item_tester_hook_armour(o_ptr)) {
3418 		o_ptr->to_a = 0 - (randint(10) + 1);
3419 	} else {
3420 		switch (o_ptr->tval) {
3421 			case TV_RING:
3422 			default:
3423 				msg_print(Ind,"You cannot curse that item!");
3424 				return(FALSE);
3425 		}
3426 	}
3427 
3428 	msg_format(Ind,"\376\377yA terrible black aura surrounds your %s",
3429 	    o_name, o_ptr->number > 1 ? "" : "s");
3430 	/* except it doesnt actually get cursed properly yet. */
3431 	o_ptr->name1 = 0;
3432 	o_ptr->name3 = 0;
3433 	o_ptr->ident |= ID_CURSED;
3434 	o_ptr->ident &= ~(ID_KNOWN | ID_SENSE);	/* without this, the spell is pointless */
3435 
3436 	if (o_ptr->name2) o_ptr->pval = 0 - (randint(10) + 1);	/* nasty */
3437 
3438 	/* Did we use up an item? */
3439 	if (p_ptr->using_up_item >= 0) {
3440 		inven_item_describe(Ind, p_ptr->using_up_item);
3441 		inven_item_optimize(Ind, p_ptr->using_up_item);
3442 		p_ptr->using_up_item = -1;
3443 	}
3444 
3445 	/* Recalculate the bonuses - if stupid enough to curse worn item ;) */
3446 	p_ptr->update |= (PU_BONUS);
3447 
3448 	/* Window stuff */
3449 	p_ptr->window |= (PW_INVEN | PW_EQUIP);
3450 
3451 	return(TRUE);
3452 }
3453 
enchant_spell(int Ind,int num_hit,int num_dam,int num_ac,int flags)3454 bool enchant_spell(int Ind, int num_hit, int num_dam, int num_ac, int flags) {
3455 	player_type *p_ptr = Players[Ind];
3456 
3457 #ifndef NEW_SHIELDS_NO_AC
3458 	get_item(Ind, num_ac ? ITH_ENCH_AC : ITH_ENCH_WEAP);
3459 #else
3460 	get_item(Ind, num_ac ? ITH_ENCH_AC_NO_SHIELD : ITH_ENCH_WEAP);
3461 #endif
3462 
3463 	/* Clear any other pending actions - mikaelh */
3464 	clear_current(Ind);
3465 
3466 	p_ptr->current_enchant_h = num_hit;
3467 	p_ptr->current_enchant_d = num_dam;
3468 	p_ptr->current_enchant_a = num_ac;
3469 	p_ptr->current_enchant_flag = flags;
3470 
3471 	return (TRUE);
3472 }
3473 
3474 /*
3475  * Enchant an item (in the inventory or on the floor)
3476  * Note that "num_ac" requires armour, else weapon
3477  * Returns TRUE if attempted, FALSE if cancelled
3478  */
3479 /*
3480  * //deprecated//For now, 'flags' is the chance of the item getting 'discounted'
3481  * in the process.
3482  */
enchant_spell_aux(int Ind,int item,int num_hit,int num_dam,int num_ac,int flags)3483 bool enchant_spell_aux(int Ind, int item, int num_hit, int num_dam, int num_ac, int flags) {
3484 	player_type *p_ptr = Players[Ind];
3485 	bool okay = FALSE;
3486 	object_type *o_ptr;
3487 	char o_name[ONAME_LEN];
3488 
3489 	/* Assume enchant weapon */
3490 	item_tester_hook = item_tester_hook_weapon;
3491 
3492 	/* Enchant armor if requested */
3493  	if (num_ac) item_tester_hook = item_tester_hook_armour;
3494 
3495 	/* Get the item (in the pack) */
3496 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
3497 	/* Get the item (on the floor) */
3498 	else o_ptr = &o_list[0 - item];
3499 
3500 
3501 	if (!item_tester_hook(o_ptr) || !is_enchantable(o_ptr)) {
3502 		msg_print(Ind, "Sorry, you cannot enchant that item.");
3503 #ifndef NEW_SHIELDS_NO_AC
3504 		get_item(Ind, num_ac ? ITH_ENCH_AC : ITH_ENCH_WEAP);
3505 #else
3506 		get_item(Ind, num_ac ? ITH_ENCH_AC_NO_SHIELD : ITH_ENCH_WEAP);
3507 #endif
3508 		return (FALSE);
3509 	}
3510 
3511 	/* Description */
3512 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
3513 
3514 	/* Describe */
3515 	msg_format(Ind, "%s %s glow%s brightly!",
3516 	    ((item >= 0) ? "Your" : "The"), o_name,
3517 	    ((o_ptr->number > 1) ? "" : "s"));
3518 
3519 	/* Enchant */
3520 	if (enchant(Ind, o_ptr, num_hit, ENCH_TOHIT)) okay = TRUE;
3521 	if (enchant(Ind, o_ptr, num_dam, ENCH_TODAM)) okay = TRUE;
3522 	if (enchant(Ind, o_ptr, num_ac, ENCH_TOAC)) okay = TRUE;
3523 
3524 	/* Artifacts cannot be enchanted. */
3525 	//if (artifact_p(o_ptr)) msg_format(Ind,"Your %s %s unaffected.",o_name,((o_ptr->number != 1) ? "are" : "is"));
3526 
3527 	/* Failure */
3528 	if (!okay) {
3529 		/* Message */
3530 		msg_print(Ind, "The enchantment failed.");
3531 	}
3532 
3533 #if 0
3534 	/* Anti-cheeze */
3535 	if (okay && !artifact_p(o_ptr) && !ego_item_p(o_ptr) && magik(flags)) {
3536 		int discount = (100 - o_ptr->discount) / 2;
3537 		if (discount > 0) {
3538 			o_ptr->discount += discount;
3539 
3540 			/* Message */
3541 			msg_format(Ind, "It spoiled the appearence of %s %s somewhat!",
3542 			    ((item >= 0) ? "your" : "the"), o_name);
3543 		}
3544 	}
3545 #else
3546         /* Anti-cheeze: Prevent stealers from making infinite money in IDDC towns.
3547            It doesn't matter that much in other places, since there are usually
3548            better/equal ways to make money.
3549            For items probably >= 12k it doesn't matter anymore though. */
3550         if (okay && (flags & ENCH_STOLEN) &&
3551     	    object_value_real(0, o_ptr) < 15000 && o_ptr->discount != 100 &&
3552     	    isdungeontown(&p_ptr->wpos) && in_irondeepdive(&p_ptr->wpos)) {
3553 		msg_format(Ind, "The stolen enchantment scroll spoiled the appearence of %s %s!",
3554 		    ((item >= 0) ? "your" : "the"), o_name);
3555                 o_ptr->discount = 100;
3556                 if (!o_ptr->note) o_ptr->note = quark_add("devalued");
3557         }
3558 #endif
3559 
3560 	/* Did we use up an item? */
3561 	if (p_ptr->using_up_item >= 0) {
3562 		inven_item_describe(Ind, p_ptr->using_up_item);
3563 		inven_item_optimize(Ind, p_ptr->using_up_item);
3564 		p_ptr->using_up_item = -1;
3565 	}
3566 
3567 	p_ptr->current_enchant_h = -1;
3568 	p_ptr->current_enchant_d = -1;
3569 	p_ptr->current_enchant_a = -1;
3570 	p_ptr->current_enchant_flag = -1;
3571 
3572 	/* Window stuff */
3573 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3574 
3575 	/* Something happened */
3576 	return (TRUE);
3577 }
3578 
3579 
ident_spell(int Ind)3580 bool ident_spell(int Ind) {
3581 	player_type *p_ptr = Players[Ind];
3582 
3583 #ifdef ENABLE_XID_SPELL
3584 	/* special hack for !X on ID spells */
3585 	if (p_ptr->current_item < -1) {
3586 		clear_current(Ind);
3587  #ifndef XID_SPELL_AFTER_PICKUP
3588 		ident_spell_aux(Ind, p_ptr->current_item + 1);
3589  #else
3590 		ident_spell_aux(Ind, -p_ptr->current_item - 1);
3591  #endif
3592 		return TRUE;
3593 	}
3594 #endif
3595 
3596 	get_item(Ind, ITH_NONE);
3597 
3598 	/* Clear any other pending actions - mikaelh */
3599 	clear_current(Ind);
3600 
3601 	p_ptr->current_identify = 1;
3602 
3603 	return TRUE;
3604 }
3605 
3606 /*
3607  * Identify an object in the inventory (or on the floor)
3608  * This routine does *not* automatically combine objects.
3609  * Returns TRUE if something was identified, else FALSE.
3610  */
ident_spell_aux(int Ind,int item)3611 bool ident_spell_aux(int Ind, int item) {
3612 	player_type *p_ptr = Players[Ind];
3613 	object_type *o_ptr;
3614 	char o_name[ONAME_LEN];
3615 
3616 #ifdef ENABLE_XID_SPELL
3617 	/* clean up special hack for !X on ID spells */
3618 	p_ptr->current_item = -1;
3619 #endif
3620 
3621 	/* Get the item (in the pack) */
3622 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
3623 	/* Get the item (on the floor) */
3624 	else o_ptr = &o_list[0 - item];
3625 
3626 
3627 	/* Identify it fully */
3628 	object_aware(Ind, o_ptr);
3629 	object_known(o_ptr);
3630 
3631 	/* Recalculate bonuses */
3632 	p_ptr->update |= (PU_BONUS);
3633 
3634 	/* redraw to-hit/to-dam */
3635 	p_ptr->redraw |= (PR_PLUSSES);
3636 
3637 	/* Combine / Reorder the pack (later) */
3638 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3639 
3640 	/* Window stuff */
3641 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3642 
3643 	/* Description */
3644 	object_desc(Ind, o_name, o_ptr, TRUE, 3);
3645 
3646 	/* Describe */
3647 	if (item >= INVEN_WIELD) {
3648 		msg_format(Ind, "%^s: %s (%c).",
3649 		   describe_use(Ind, item), o_name, index_to_label(item));
3650 	} else if (item >= 0) {
3651 		msg_format(Ind, "In your pack: %s (%c).",
3652 		    o_name, index_to_label(item));
3653 	} else {
3654 		msg_format(Ind, "On the ground: %s.",
3655 		    o_name);
3656 	}
3657 
3658 	/* Did we use up an item? */
3659 	if (p_ptr->using_up_item >= 0) {
3660 //		inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not when IDing */
3661 		inven_item_optimize(Ind, p_ptr->using_up_item);
3662 		p_ptr->using_up_item = -1;
3663 	}
3664 
3665 	p_ptr->current_identify = 0;
3666 
3667 	if (item >= 0) p_ptr->inventory[item].auto_insc = TRUE;
3668 
3669 	/* Something happened */
3670 	return (TRUE);
3671 }
3672 
3673 
identify_fully(int Ind)3674 bool identify_fully(int Ind) {
3675 	player_type *p_ptr = Players[Ind];
3676 
3677 #ifdef ENABLE_XID_SPELL
3678 	/* special hack for !X on ID spells */
3679 	if (p_ptr->current_item < -1) {
3680 		clear_current(Ind);
3681  #ifndef XID_SPELL_AFTER_PICKUP
3682 		identify_fully_item(Ind, p_ptr->current_item + 1);
3683  #else
3684 		identify_fully_item(Ind, -p_ptr->current_item - 1);
3685  #endif
3686 		return TRUE;
3687 	}
3688 #endif
3689 
3690 	get_item(Ind, ITH_NONE);
3691 
3692 	/* Clear any other pending actions - mikaelh */
3693 	clear_current(Ind);
3694 
3695 	p_ptr->current_star_identify = 1;
3696 
3697 	return TRUE;
3698 }
3699 
3700 
3701 /*
3702  * Fully "identify" an object in the inventory	-BEN-
3703  * This routine returns TRUE if an item was identified.
3704  */
identify_fully_item(int Ind,int item)3705 bool identify_fully_item(int Ind, int item) {
3706 	player_type *p_ptr = Players[Ind];
3707 	object_type *o_ptr;
3708 	char o_name[ONAME_LEN];
3709 
3710 #ifdef ENABLE_XID_SPELL
3711 	/* clean up special hack for !X on ID spells */
3712 	p_ptr->current_item = -1;
3713 #endif
3714 
3715 	/* Get the item (in the pack) */
3716 	if (item >= 0)
3717 		o_ptr = &p_ptr->inventory[item];
3718 	/* Get the item (on the floor) */
3719 	else
3720 		o_ptr = &o_list[0 - item];
3721 
3722 
3723 	/* Identify it fully */
3724 	object_aware(Ind, o_ptr);
3725 	object_known(o_ptr);
3726 
3727 	/* Mark the item as fully known */
3728 	o_ptr->ident |= (ID_MENTAL);
3729 
3730 	/* Recalculate bonuses */
3731 	p_ptr->update |= (PU_BONUS);
3732 
3733 	/* Combine / Reorder the pack (later) */
3734 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3735 
3736 	/* Window stuff */
3737 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3738 
3739 	/* Handle stuff */
3740 	handle_stuff(Ind);
3741 
3742 	/* Description */
3743 	object_desc(Ind, o_name, o_ptr, TRUE, 3);
3744 
3745 	/* Describe */
3746 	if (item >= INVEN_WIELD)
3747 		msg_format(Ind, "%^s: %s (%c).",
3748 		           describe_use(Ind, item), o_name, index_to_label(item));
3749 	else if (item >= 0)
3750 		msg_format(Ind, "In your pack: %s (%c).",
3751 		           o_name, index_to_label(item));
3752 	else
3753 		msg_format(Ind, "On the ground: %s.",
3754 		           o_name);
3755 
3756 	/* Describe it fully */
3757 	(void)identify_fully_aux(Ind, o_ptr, FALSE);
3758 
3759 	/* Did we use up an item? */
3760 	if (p_ptr->using_up_item >= 0) {
3761 //		inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3762 		inven_item_optimize(Ind, p_ptr->using_up_item);
3763 		p_ptr->using_up_item = -1;
3764 
3765 		p_ptr->window |= PW_INVEN;
3766 	}
3767 
3768 	/* We no longer have a *identify* in progress */
3769 	p_ptr->current_star_identify = 0;
3770 
3771 	/* extra: in case the item wasn't normally identified yet but right away *id*ed, apply this too.. */
3772 	if (item >= 0) p_ptr->inventory[item].auto_insc = TRUE;
3773 
3774 	/* Success */
3775 	return (TRUE);
3776 }
3777 
3778 /* silent version of identify_fully_item() that doesn't display anything - C. Blue */
identify_fully_item_quiet(int Ind,int item)3779 bool identify_fully_item_quiet(int Ind, int item) {
3780 	player_type *p_ptr = Players[Ind];
3781 	object_type *o_ptr;
3782 
3783 	/* Get the item (in the pack) */
3784 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
3785 	/* Get the item (on the floor) */
3786 	else o_ptr = &o_list[0 - item];
3787 
3788 	/* Identify it fully */
3789 	object_aware(Ind, o_ptr);
3790 	object_known(o_ptr);
3791 
3792 	/* Mark the item as fully known */
3793 	o_ptr->ident |= (ID_MENTAL);
3794 	/* Recalculate bonuses */
3795 	p_ptr->update |= (PU_BONUS);
3796 	/* Combine / Reorder the pack (later) */
3797 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3798 	/* Window stuff */
3799 	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3800 
3801 	/* Did we use up an item? */
3802 	if (p_ptr->using_up_item >= 0) {
3803 //		inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3804 		inven_item_optimize(Ind, p_ptr->using_up_item);
3805 		p_ptr->using_up_item = -1;
3806 
3807 		p_ptr->window |= PW_INVEN;
3808 	}
3809 
3810 	/* Handle stuff */
3811 	handle_stuff(Ind);
3812 
3813 	/* We no longer have a *identify* in progress */
3814 	p_ptr->current_star_identify = 0;
3815 
3816 	/* Success */
3817 	return (TRUE);
3818 }
3819 
3820 /* variant of identify_fully_item_quiet that doesn't use player inventory,
3821    added for !X on Iron Helm of Knowledge, which probably doesn't make much
3822    sense though - C. Blue */
identify_fully_object_quiet(int Ind,object_type * o_ptr)3823 bool identify_fully_object_quiet(int Ind, object_type *o_ptr) {
3824 	player_type *p_ptr = Players[Ind];
3825 
3826 	/* Identify it fully */
3827 	object_aware(Ind, o_ptr);
3828 	object_known(o_ptr);
3829 
3830 	/* Mark the item as fully known */
3831 	o_ptr->ident |= (ID_MENTAL);
3832 
3833 	/* Did we use up an item? */
3834 	if (p_ptr->using_up_item >= 0) {
3835 //		inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3836 		inven_item_optimize(Ind, p_ptr->using_up_item);
3837 		p_ptr->using_up_item = -1;
3838 
3839 		p_ptr->window |= PW_INVEN;
3840 	}
3841 
3842 	/* Handle stuff */
3843 	handle_stuff(Ind);
3844 
3845 	/* We no longer have a *identify* in progress */
3846 	p_ptr->current_star_identify = 0;
3847 
3848 	/* Success */
3849 	return (TRUE);
3850 }
3851 
3852 /*
3853  * Hook for "get_item()".  Determine if something is rechargable.
3854  */
3855 //static bool item_tester_hook_recharge(object_type *o_ptr)
item_tester_hook_recharge(object_type * o_ptr)3856 bool item_tester_hook_recharge(object_type *o_ptr) {
3857 	u32b f1, f2, f3, f4, f5, f6, esp;
3858 
3859 	/* Extract the flags */
3860 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
3861 
3862 	/* Some objects cannot be recharged */
3863 	if (f4 & TR4_NO_RECHARGE) return (FALSE);
3864 
3865 	/* Recharge staffs/wands/rods */
3866 	if (is_magic_device(o_ptr->tval)) return (TRUE);
3867 
3868 	/* Nope */
3869 	return (FALSE);
3870 }
3871 
3872 
recharge(int Ind,int num)3873 bool recharge(int Ind, int num) {
3874 	player_type *p_ptr = Players[Ind];
3875 
3876 	get_item(Ind, ITH_RECHARGE);
3877 
3878 	/* Clear any other pending actions - mikaelh */
3879 	clear_current(Ind);
3880 
3881 	p_ptr->current_recharge = num;
3882 
3883 	return TRUE;
3884 }
3885 
3886 
3887 /*
3888  * Recharge a wand/staff/rod from the pack or on the floor.
3889  *
3890  * Mage -- Recharge I --> recharge(5)
3891  * Mage -- Recharge II --> recharge(40)
3892  * Mage -- Recharge III --> recharge(100)
3893  *
3894  * Priest -- Recharge --> recharge(15)
3895  *
3896  * Scroll of recharging --> recharge(60)
3897  *
3898  * recharge(20) = 1/6 failure for empty 10th level wand
3899  * recharge(60) = 1/10 failure for empty 10th level wand
3900  *
3901  * It is harder to recharge high level, and highly charged wands.
3902  *
3903  * XXX XXX XXX Beware of "sliding index errors".
3904  *
3905  * Should probably not "destroy" over-charged items, unless we
3906  * "replace" them by, say, a broken stick or some such.  The only
3907  * reason this is okay is because "scrolls of recharging" appear
3908  * BEFORE all staffs/wands/rods in the inventory.  Note that the
3909  * new "auto_sort_pack" option would correctly handle replacing
3910  * the "broken" wand with any other item (i.e. a broken stick).
3911  *
3912  * XXX XXX XXX Perhaps we should auto-unstack recharging stacks.
3913  */
recharge_aux(int Ind,int item,int pow)3914 bool recharge_aux(int Ind, int item, int pow) {
3915 	player_type *p_ptr = Players[Ind];
3916 	int                 i, t, lev, dr;
3917 	object_type		*o_ptr;
3918 
3919 
3920 	/* Only accept legal items */
3921 	item_tester_hook = item_tester_hook_recharge;
3922 
3923 	/* Get the item (in the pack) */
3924 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
3925 	/* Get the item (on the floor) */
3926 	else o_ptr = &o_list[0 - item];
3927 
3928 	if (!item_tester_hook(o_ptr)) {
3929 		msg_print(Ind, "You cannot recharge that item.");
3930 		get_item(Ind, ITH_RECHARGE);
3931 		return (FALSE);
3932 	}
3933 
3934 	/* Extract the object "level" */
3935 	lev = k_info[o_ptr->k_idx].level;
3936 
3937 	/* Recharge a rod */
3938 	if (o_ptr->tval == TV_ROD) {
3939 		/* Extract a recharge power */
3940 		i = (100 - lev + pow) / 5;
3941 
3942 		/* Paranoia -- prevent crashes */
3943 		if (i < 1) i = 1;
3944 
3945 		/* Back-fire */
3946 		if (rand_int(i) == 0) {
3947 			/* Hack -- backfire */
3948 			//msg_print(Ind, "The recharge backfires, draining the rod further!");
3949 			msg_print(Ind, "There is a static discharge.");
3950 
3951 			/* Hack -- decharge the rod */
3952 			if (o_ptr->pval < 10000) o_ptr->pval = (o_ptr->pval + 100) * 2;
3953 		}
3954 
3955 		/* Recharge */
3956 		else {
3957 			/* Rechange amount */
3958 			t = (pow * damroll(2, 4));
3959 
3960 			/* Recharge by that amount */
3961 			if (o_ptr->pval > t) o_ptr->pval -= t;
3962 			/* Fully recharged */
3963 			else o_ptr->pval = 0;
3964 		}
3965 	}
3966 
3967 	/* Recharge wand/staff */
3968 	else {
3969 		/* Recharge power */
3970 		i = (pow + 100 - lev - (10 * o_ptr->pval)) / 15;
3971 
3972 		/* Paranoia -- prevent crashes */
3973 		if (i < 1) i = 1;
3974 
3975 		/* Back-fire XXX XXX XXX */
3976 		if (rand_int(i) == 0) {
3977 			/* a chance to just discharge it instead of destroying it */
3978 			if (!rand_int(2)) {
3979 				msg_print(Ind, "There is a static discharge.");
3980 				o_ptr->pval = 0;
3981 				o_ptr->ident |= ID_EMPTY;
3982 			} else {
3983 				/* Dangerous Hack -- Destroy the item */
3984 				msg_print(Ind, "There is a bright flash of light.");
3985 
3986 				/* Reduce and describe inventory */
3987 				if (item >= 0) {
3988 					inven_item_increase(Ind, item, -999);
3989 					inven_item_describe(Ind, item);
3990 					inven_item_optimize(Ind, item);
3991 				}
3992 				/* Reduce and describe floor item */
3993 				else {
3994 					floor_item_increase(0 - item, -999);
3995 					floor_item_describe(0 - item);
3996 					floor_item_optimize(0 - item);
3997 				}
3998 			}
3999 		}
4000 
4001 		/* Hack: No controlled mass-summoning in ironman deep dive challenge */
4002 		else if (in_irondeepdive(&p_ptr->wpos) &&
4003 		    ((o_ptr->tval == TV_STAFF && o_ptr->sval == SV_STAFF_SUMMONING) ||
4004 		    (o_ptr->tval == TV_WAND && o_ptr->sval == SV_WAND_POLYMORPH))) {
4005 			msg_print(Ind, "There is a static discharge.");
4006 			o_ptr->pval = 0;
4007 			o_ptr->ident |= ID_EMPTY;
4008 		}
4009 
4010 		/* Recharge */
4011 		else {
4012 			/* Extract a "power" */
4013 			t = (pow / (lev + 2)) + 1;
4014 
4015 			/* Hack -- ego */
4016 			if (o_ptr->name2 == EGO_PLENTY) t <<= 1;
4017 
4018 #if 0 /* old way */
4019                        /* Recharge based on the power */
4020                        if (t > 0) o_ptr->pval += 2 + randint(t);
4021 #else /* new way: correct wand stacking, added stack size dr */
4022 			/* Wands stack, so recharging must multiply the power.
4023 			   Add small 'laziness' diminishing returns malus. */
4024 			if (o_ptr->tval == TV_WAND) {
4025 				/* Recharge based on the power */
4026 				//if (t > 0) o_ptr->pval += (2 * o_ptr->number) + rand_int(t * o_ptr->number);
4027 
4028 				/* allow dr to factor in more: */
4029 				//Diminishing returns start at number=10: ' * (1050 / (10 + 1000 / (o_ptr->number + 4)) - 4) '
4030 				//Diminishing returns start at number=3~: ' * (450 / (10 + 400 / (o_ptr->number + 3)) - 3) '
4031 				dr = 4500 / (10 + 400 / (o_ptr->number + 3)) - 30;
4032 				if (t > 0) o_ptr->pval += (3 * dr) / 10 + rand_int(t * dr) / 10;
4033 			} else {
4034 				/* Recharge based on the power */
4035 				//if (t > 0) o_ptr->pval += 2 + randint(t);
4036 
4037 				/* allow dr to factor in more: */
4038 				dr = 4500 / (10 + 400 / (o_ptr->number + 3)) - 30;
4039 				if (t > 0) o_ptr->pval += 1 + (rand_int((t + 2) * dr) / o_ptr->number) / 10;
4040 			}
4041 #endif
4042 
4043 			/* Hack -- we no longer "know" the item */
4044 			o_ptr->ident &= ~ID_KNOWN;
4045 
4046 			/* Hack -- we no longer think the item is empty */
4047 			o_ptr->ident &= ~ID_EMPTY;
4048 		}
4049 	}
4050 
4051 	/* Did we use up an item? */
4052 	if (p_ptr->using_up_item >= 0) {
4053 		inven_item_describe(Ind, p_ptr->using_up_item);
4054 		inven_item_optimize(Ind, p_ptr->using_up_item);
4055 		p_ptr->using_up_item = -1;
4056 	}
4057 
4058 	/* Combine / Reorder the pack (later) */
4059 	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
4060 
4061 	/* Window stuff */
4062 	p_ptr->window |= (PW_INVEN | PW_EQUIP);
4063 
4064 	/* We no longer have a recharge in progress */
4065 	p_ptr->current_recharge = 0;
4066 
4067 	/* Something was done */
4068 	return (TRUE);
4069 }
4070 
4071 
4072 
4073 
4074 
4075 
4076 
4077 
4078 /*
4079  * Apply a "project()" directly to all viewable monsters
4080  */
project_los(int Ind,int typ,int dam,char * attacker)4081 bool project_los(int Ind, int typ, int dam, char *attacker) {
4082 	player_type *p_ptr = Players[Ind];
4083 	struct worldpos *wpos = &p_ptr->wpos;
4084 	int		i, x, y;
4085 	int		flg = PROJECT_NORF | PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE;
4086 	bool		obvious = FALSE;
4087 	char		pattacker[80];
4088 
4089 	if (Ind) snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
4090 	else snprintf(pattacker, 80, "Something%s", attacker);
4091 
4092 	/* Affect all (nearby) monsters */
4093 	for (i = 1; i < m_max; i++) {
4094 		monster_type *m_ptr = &m_list[i];
4095 
4096 		/* Paranoia -- Skip dead monsters */
4097 		if (!m_ptr->r_idx) continue;
4098 
4099 		/* Skip monsters not on this depth */
4100 		if(!inarea(wpos, &m_ptr->wpos)) continue;
4101 
4102 		/* Location */
4103 		y = m_ptr->fy;
4104 		x = m_ptr->fx;
4105 
4106 		/* Require line of sight */
4107 		if (!player_has_los_bold(Ind, y, x)) continue;
4108 
4109 		/* Don't exceed max range (which may be < sight range)! */
4110 		if (distance(p_ptr->py, p_ptr->px, y, x) > MAX_RANGE) continue;
4111 		/* Maybe also check for BLOCK_LOS/BLOCK_CONTACT grids? (glass walls..) */
4112 		if (!projectable_wall(wpos, p_ptr->py, p_ptr->px, y, x, MAX_RANGE)) continue;
4113 
4114 		/* Jump directly to the target monster */
4115 		if (project(0 - Ind, 0, wpos, y, x, dam, typ, flg, pattacker)) obvious = TRUE;
4116 	}
4117 
4118 #if 1	//this would require to differ between project_los calls that are meant
4119 	//to work on players and those that are meant to work on monsters only
4120 	//like GF_OLD_SPEED, GF_OLD_HEAL, etc. If this is done, an attacker string
4121 	//should be added as well, however.
4122 
4123 	/* Affect all (nearby) non-partied players */
4124 	for (i = 1; i < NumPlayers + 1; i++) {
4125                 /* If he's not playing, skip him */
4126                 if (Players[i]->conn == NOT_CONNECTED)
4127                         continue;
4128 
4129                 /* If he's not here, skip him */
4130                 if (!inarea(wpos, &Players[i]->wpos))
4131                         continue;
4132 
4133                 /* Ignore players we aren't hostile to */
4134 //                if (!check_hostile(Ind, i)) continue;
4135 
4136 	        /* if we are in the same party, don't affect target player */
4137 	        if (p_ptr->party && (player_in_party(p_ptr->party, i)))
4138 			continue;
4139 
4140 		/* Location */
4141 		y = Players[i]->py;
4142 		x = Players[i]->px;
4143 
4144 		/* Require line of sight */
4145 		if (!player_has_los_bold(Ind, y, x)) continue;
4146 
4147 		/* Jump directly to the target player */
4148 		if (project(0 - Ind, 0, wpos, y, x, dam, typ, flg, pattacker)) obvious = TRUE;
4149 	}
4150 #endif
4151 
4152 	/* Result */
4153 	return (obvious);
4154 }
4155 
4156 
4157 /* Speed monsters */
speed_monsters(int Ind)4158 bool speed_monsters(int Ind) {
4159 	player_type *p_ptr = Players[Ind];
4160 	return (project_los(Ind, GF_OLD_SPEED, p_ptr->lev, ""));
4161 }
4162 /* Slow monsters */
slow_monsters(int Ind,int pow)4163 bool slow_monsters(int Ind, int pow) {
4164 	return (project_los(Ind, GF_OLD_SLOW, pow, ""));
4165 }
4166 /* Sleep monsters */
sleep_monsters(int Ind,int pow)4167 bool sleep_monsters(int Ind, int pow) {
4168 	return (project_los(Ind, GF_OLD_SLEEP, pow, ""));
4169 }
4170 /* Fear monsters */
fear_monsters(int Ind,int pow)4171 bool fear_monsters(int Ind, int pow) {
4172 	return (project_los(Ind, GF_TURN_ALL, pow, ""));
4173 }
4174 /* Stun monsters */
stun_monsters(int Ind,int pow)4175 bool stun_monsters(int Ind, int pow) {
4176 	return (project_los(Ind, GF_STUN, pow, ""));
4177 }
4178 
4179 
4180 /* Banish evil monsters */
away_evil(int Ind,int dist)4181 bool away_evil(int Ind, int dist) {
4182 	return (project_los(Ind, GF_AWAY_EVIL, dist, " banishes all evil"));
4183 }
4184 
4185 
4186 /* Turn undead */
turn_undead(int Ind)4187 bool turn_undead(int Ind) {
4188 	player_type *p_ptr = Players[Ind];
4189 	return (project_los(Ind, GF_TURN_UNDEAD, p_ptr->lev, " calls against all undead"));
4190 }
4191 /* Turn everyone */
turn_monsters(int Ind,int dam)4192 bool turn_monsters(int Ind, int dam) {
4193 	return (project_los(Ind, GF_TURN_ALL, dam, " calls against all monsters"));
4194 }
4195 
4196 
4197 /* Dispel undead monsters */
dispel_undead(int Ind,int dam)4198 bool dispel_undead(int Ind, int dam) {
4199 	return (project_los(Ind, GF_DISP_UNDEAD, dam, " banishes all undead"));
4200 }
4201 /* Dispel evil monsters */
dispel_evil(int Ind,int dam)4202 bool dispel_evil(int Ind, int dam) {
4203 	return (project_los(Ind, GF_DISP_EVIL, dam, " banishes all evil"));
4204 }
4205 /* Dispel demons */
dispel_demons(int Ind,int dam)4206 bool dispel_demons(int Ind, int dam) {
4207 	return (project_los(Ind, GF_DISP_DEMON, dam, " banishes all demons"));
4208 }
4209 /* Dispel all monsters */
dispel_monsters(int Ind,int dam)4210 bool dispel_monsters(int Ind, int dam) {
4211 	return (project_los(Ind, GF_DISP_ALL, dam, " banishes all monsters"));
4212 }
4213 
4214 
4215 /*
4216  * Wake up all monsters, and speed up "los" monsters.
4217  */
aggravate_monsters(int Ind,int who)4218 void aggravate_monsters(int Ind, int who) {
4219 	player_type *p_ptr = Players[Ind];
4220 	monster_type * m_ptr;
4221 	monster_race *r_ptr;
4222 
4223 	int i;
4224 
4225 	bool sleep = FALSE;
4226 	bool speed = FALSE;
4227 
4228 	/* Aggravate everyone nearby */
4229 	for (i = 1; i < m_max; i++) {
4230 		m_ptr = &m_list[i];
4231 		r_ptr = race_inf(m_ptr);
4232 
4233 		/* Paranoia -- Skip dead monsters */
4234 		if (!m_ptr->r_idx) continue;
4235 
4236 		/* Skip monsters not on this depth */
4237 		if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4238 
4239 		/* Skip aggravating monster (or player) */
4240 		if (i == who) continue;
4241 
4242 		/* Wake up nearby sleeping monsters */
4243 		if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4244 #if 0
4245 		if (m_ptr->cdis < MAX_SIGHT * 2)
4246 #endif
4247 		{
4248 			/* Wake up */
4249 			if (m_ptr->csleep) {
4250 				/* Wake up */
4251 				m_ptr->csleep = 0;
4252 				sleep = TRUE;
4253 			}
4254 		}
4255 
4256 		/* Don't speed up undead/nonliving monsters */
4257 		if ((r_ptr->flags3 & RF3_NONLIVING) || (r_ptr->flags2 & RF2_EMPTY_MIND)) continue;
4258 
4259 		/* Speed up monsters in line of sight */
4260 		if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4261 			/* Speed up (instantly) to racial base + 10 */
4262                         if (m_ptr->mspeed < m_ptr->speed + 10) {
4263 				/* Speed up */
4264                                 m_ptr->mspeed = m_ptr->speed + 10;
4265 				speed = TRUE;
4266 			}
4267 		}
4268 	}
4269 
4270 	/* Messages */
4271 	/* the_sandman: added _near so other players can hear too */
4272 	if (speed) {
4273 		msg_print(Ind, "You feel a sudden stirring nearby!");
4274 		msg_print_near(Ind, "You feel a sudden stirring nearby!");
4275 	} else if (sleep) {
4276 		msg_print(Ind, "You hear a sudden stirring in the distance!");
4277 		msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4278 	}
4279 }
4280 
4281 /*
4282  * Wake up all monsters
4283  */
wakeup_monsters(int Ind,int who)4284 void wakeup_monsters(int Ind, int who) {
4285 	player_type *p_ptr = Players[Ind];
4286 	int i;
4287 	bool sleep = FALSE;
4288 
4289 	/* Aggravate everyone nearby */
4290 	for (i = 1; i < m_max; i++) {
4291 		monster_type	*m_ptr = &m_list[i];
4292 
4293 		/* Paranoia -- Skip dead monsters */
4294 		if (!m_ptr->r_idx) continue;
4295 
4296 		/* Skip monsters not on this depth */
4297 		if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4298 
4299 		/* Skip aggravating monster (or player) */
4300 		if (i == who) continue;
4301 
4302 		/* Wake up nearby sleeping monsters */
4303 		if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4304 #if 0
4305 		if (m_ptr->cdis < MAX_SIGHT * 2)
4306 #endif
4307 		{
4308 			/* Wake up */
4309 			if (m_ptr->csleep) {
4310 				/* Wake up */
4311 				m_ptr->csleep = 0;
4312 				sleep = TRUE;
4313 			}
4314 		}
4315 	}
4316 
4317 	/* Messages */
4318 	/* the_sandman: added _near so other players can hear too */
4319 	if (sleep) {
4320 		msg_print(Ind, "You hear a sudden stirring in the distance!");
4321 		msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4322 	}
4323 }
4324 
wakeup_monsters_somewhat(int Ind,int who)4325 void wakeup_monsters_somewhat(int Ind, int who) {
4326 	player_type *p_ptr = Players[Ind];
4327 	int i;
4328 	bool sleep = FALSE;
4329 
4330 	/* Aggravate everyone nearby */
4331 	for (i = 1; i < m_max; i++) {
4332 		monster_type *m_ptr = &m_list[i];
4333 
4334 		/* Paranoia -- Skip dead monsters */
4335 		if (!m_ptr->r_idx) continue;
4336 
4337 		/* Skip monsters not on this depth */
4338 		if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4339 
4340 		/* Skip aggravating monster (or player) */
4341 		if (i == who) continue;
4342 
4343 		/* Wake up nearby sleeping monsters */
4344 		if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4345 #if 0
4346 		if (m_ptr->cdis < MAX_SIGHT * 2)
4347 #endif
4348 		{
4349 			/* Disturb sleep somewhat */
4350 			if (m_ptr->csleep) {
4351 				m_ptr->csleep = (m_ptr->csleep * 3) / 5;
4352 				m_ptr->csleep -= 10 + rand_int(6); //10
4353 				if (m_ptr->csleep <= 0) {
4354 					m_ptr->csleep = 0;
4355 					sleep = TRUE;
4356 				}
4357 			}
4358 		}
4359 	}
4360 
4361 #if 1 /* better style, not to display a msg maybe? */
4362 	/* Messages */
4363 	/* the_sandman: added _near so other players can hear too */
4364 	if (sleep) {
4365 		msg_print(Ind, "You hear a sudden stirring in the distance!");
4366 		msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4367 	}
4368 #endif
4369 }
4370 
distract_monsters(int Ind)4371 void distract_monsters(int Ind) {
4372 	player_type *p_ptr = Players[Ind];
4373 	monster_type	*m_ptr;
4374 	monster_race *r_ptr;
4375 
4376 	int i;
4377 	bool tauntable;
4378 
4379         msg_print(Ind, "You make yourself look less threatening than your team mates.");
4380         msg_format_near(Ind, "%s pretends you're more threatening than him.", p_ptr->name);
4381 	break_cloaking(Ind, 0);
4382 	break_shadow_running(Ind);
4383 	stop_precision(Ind);
4384 	stop_shooting_till_kill(Ind);
4385 
4386 	for (i = 1; i < m_max; i++) {
4387 		m_ptr = &m_list[i];
4388 		r_ptr = race_inf(m_ptr);
4389 
4390 		/* Paranoia -- Skip dead monsters */
4391 		if (!m_ptr->r_idx) continue;
4392 		if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4393 
4394 		if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON)) ||
4395             	    (strchr("hHkptn", r_ptr->d_char))) tauntable = TRUE;
4396 		else tauntable = FALSE;
4397 
4398 		if (r_ptr->level >= 98) tauntable = FALSE; /* end-game specialties are exempt */
4399 		if (r_ptr->flags1 & RF1_UNIQUE) {
4400 #if 0 /* still distractable, hence if 0'ed */
4401 			if (r_ptr->flags2 & RF2_POWERFUL) {
4402 				if (magik(75)) tauntable = FALSE; /* powerful unique monsters prefer to stay alive */
4403 			} else
4404 #endif
4405 				{
4406 				if (magik(50)) tauntable = FALSE; /* unique monsters resist more often */
4407 			}
4408 		}
4409 		else if (magik(25)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4410 //		else if (magik(r_ptr->level / 3)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4411 
4412 #if 0 /*actually, being POWERFUL doesn't really protect.. */
4413 		if (r_ptr->flags2 & RF2_POWERFUL) tauntable = FALSE;
4414 #endif
4415 #if 0 /* shamans -_- and not only that, way too many monsters are SMART, so commented out for now */
4416 		if (r_ptr->flags2 & RF2_SMART) tauntable = FALSE; /* smart monsters don't fall for taunts */
4417 #endif
4418 		if (r_ptr->flags3 & RF3_NONLIVING) tauntable = FALSE; /* nonliving monsters can't perceive taunts */
4419 		if (r_ptr->flags2 & RF2_EMPTY_MIND) tauntable = FALSE; /* empty-minded monsters can't perceive taunts */
4420 		if ((r_ptr->flags2 & RF2_WEIRD_MIND) && magik(50)) tauntable = FALSE; /* weird-minded monsters are hard to predict */
4421 		/* RF2_CAN_SPEAK ?? */
4422 
4423 		if (!tauntable) continue;
4424 
4425 		/* monster stands right next to this player? */
4426 		if (ABS(m_ptr->fy - p_ptr->py) <= 1 && ABS(m_ptr->fx - p_ptr->px) <= 1 &&
4427 		    m_ptr->last_target_melee == Ind) {
4428 			/* set another (adjacent) player as target */
4429 			m_ptr->switch_target = Ind;
4430 		}
4431 	}
4432 }
4433 
4434 /* attempts to make certain types of AI_ANNOY monsters approach the player for a while */
taunt_monsters(int Ind)4435 void taunt_monsters(int Ind)
4436 {
4437 	player_type *p_ptr = Players[Ind];
4438 	monster_type	*m_ptr;
4439 	monster_race *r_ptr;
4440 
4441 	int i;
4442 	bool sleep = FALSE, tauntable;
4443 
4444         msg_print(Ind, "You call out a taunt!");
4445         msg_format_near(Ind, "%s calls out a taunt!", p_ptr->name);
4446 	break_cloaking(Ind, 0);
4447 	stop_precision(Ind);
4448 
4449 	for (i = 1; i < m_max; i++) {
4450 		m_ptr = &m_list[i];
4451 		r_ptr = race_inf(m_ptr);
4452 
4453 		/* Paranoia -- Skip dead monsters */
4454 		if (!m_ptr->r_idx) continue;
4455 		if(!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4456 
4457 		if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON)) ||
4458             	    (strchr("hHkptn", r_ptr->d_char))) tauntable = TRUE;
4459 		else tauntable = FALSE;
4460 
4461 		if (r_ptr->level >= 98) tauntable = FALSE; /* end-game specialties are exempt */
4462 		if (r_ptr->flags1 & RF1_UNIQUE) {
4463 			if (r_ptr->flags2 & RF2_POWERFUL) {
4464 				if (magik(75)) tauntable = FALSE; /* powerful unique monsters prefer to stay alive */
4465 			} else {
4466 				if (magik(50)) tauntable = FALSE; /* unique monsters resist more often */
4467 			}
4468 		}
4469 		else if (magik(20)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4470 //		else if (magik(r_ptr->level / 3)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4471 
4472 #if 0 /*actually, being POWERFUL doesn't really protect.. */
4473 		if (r_ptr->flags2 & RF2_POWERFUL) tauntable = FALSE;
4474 #endif
4475 #if 0 /* shamans -_- and not only that, way too many monsters are SMART, so commented out for now */
4476 		if (r_ptr->flags2 & RF2_SMART) tauntable = FALSE; /* smart monsters don't fall for taunts */
4477 #endif
4478 		if (r_ptr->flags3 & RF3_NONLIVING) tauntable = FALSE; /* nonliving monsters can't perceive taunts */
4479 		if (r_ptr->flags2 & RF2_EMPTY_MIND) tauntable = FALSE; /* empty-minded monsters can't perceive taunts */
4480 		if ((r_ptr->flags2 & RF2_WEIRD_MIND) && magik(50)) tauntable = FALSE; /* weird-minded monsters are hard to predict */
4481 		/* RF2_CAN_SPEAK ?? */
4482 
4483 		/* some egos aren't tauntable possibly */
4484 		switch(m_ptr->ego) {
4485 		case 10: case 13: case 23: /* archers */
4486 		case 9: case 30: /* mages */
4487 			tauntable = FALSE;
4488 			break;
4489 		default: ;
4490 		}
4491 
4492 		/* some monsters (hard-coded ;() aren't tauntable */
4493 		switch(m_ptr->r_idx) {
4494 		case 46: case 93: case 240: case 449: case 638: case 738: /* p mages */
4495 		case 178: case 281: case 375: case 657: /* h mages */
4496 		case 539: /* h archers */
4497 			tauntable = FALSE;
4498 			break;
4499 		default: ;
4500 		}
4501 
4502 		if (!tauntable) continue;
4503 
4504 		if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4505 #if 0
4506 			/* wake up */
4507 			if (m_ptr->csleep) {
4508 				m_ptr->csleep = 0;
4509 				sleep = TRUE;
4510 			}
4511 #endif
4512 
4513 			/* taunt */
4514 			m_ptr->monfear = 0;
4515 			m_ptr->taunted = 7; /* number of monster moves staying taunted */
4516 			//was 5
4517 		}
4518 
4519 		/* monster stands right next to this player? */
4520 		if (ABS(m_ptr->fy - p_ptr->py) <= 1 && ABS(m_ptr->fx - p_ptr->px) <= 1)
4521 			m_ptr->last_target_melee = Ind;
4522 	}
4523 
4524 	if (sleep) {
4525 		msg_print(Ind, "You hear a sudden stirring in the distance!");
4526 		msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4527 	}
4528 }
4529 
4530 /* Need it for detonation pots in potion_smash_effect - C. Blue */
aggravate_monsters_floorpos(worldpos * wpos,int x,int y)4531 void aggravate_monsters_floorpos(worldpos *wpos, int x, int y) {
4532 	int i;
4533 
4534 	/* Aggravate everyone nearby */
4535 	for (i = 1; i < m_max; i++) {
4536 		monster_type	*m_ptr = &m_list[i];
4537 
4538 		/* Paranoia -- Skip dead monsters */
4539 		if (!m_ptr->r_idx) continue;
4540 
4541 		/* Skip monsters not on this depth */
4542 		if (!inarea(wpos, &m_ptr->wpos)) continue;
4543 
4544 		/* Wake up nearby sleeping monsters */
4545 		if (distance(y, x, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4546 #if 0
4547 		if (m_ptr->cdis < MAX_SIGHT * 2)
4548 #endif
4549 		{
4550 			/* Wake up */
4551 			if (m_ptr->csleep) {
4552 				/* Wake up */
4553 				m_ptr->csleep = 0;
4554 			}
4555 		}
4556 	}
4557 }
4558 
4559 
4560 /*
4561  * Wake up minions (escorts/friends). May be used by a pack monster or unique.
4562  * As soon as a monster is hit by a player or has a LOS to him. - C. Blue
4563  */
wake_minions(int Ind,int who)4564 void wake_minions(int Ind, int who) {
4565 	player_type *p_ptr = Players[Ind];
4566 
4567 	monster_type	*mw_ptr = &m_list[who], *m_ptr = NULL;
4568 	monster_race    *rw_ptr = race_inf(m_ptr), *r_ptr = NULL;
4569 	char		mw_name[MNAME_LEN];
4570 
4571 	int i;
4572 
4573 	bool sleep = FALSE;
4574 //	bool speed = FALSE;
4575 
4576 
4577 	monster_desc(Ind, mw_name, who, 0x00);
4578 
4579 	/* Aggravate everyone nearby */
4580 	for (i = 1; i < m_max; i++) {
4581 		m_ptr = &m_list[i];
4582 		r_ptr = race_inf(m_ptr);
4583 
4584 		/* Paranoia -- Skip dead monsters */
4585 		if (!m_ptr->r_idx) continue;
4586 
4587 		/* Skip monsters not on this depth */
4588 		if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4589 
4590 		/* Skip aggravating monster (or player) */
4591 		if (i == who) continue;
4592 
4593 		/* wake_minions used by a FRIENDS monster? */
4594 		if (rw_ptr->flags1 & (RF1_FRIEND | RF1_FRIENDS)) {
4595 			/* Skip monsters who aren't its friends */
4596 			if (m_ptr->r_idx != mw_ptr->r_idx) continue;
4597 		}
4598 
4599 		/* wake_minions used by a UNIQUE monster? */
4600 		if (rw_ptr->flags1 & RF1_UNIQUE) {
4601 			/* Skip monsters who don't belong to its escort */
4602 
4603 			/* Paranoia -- Skip identical monsters */
4604 			if (m_ptr->r_idx == mw_ptr->r_idx) continue;
4605 			/* Require similar "race" */
4606 			if (r_ptr->d_char != rw_ptr->d_char) continue;
4607 			/* Skip more advanced monsters */
4608 			if (r_ptr->level > rw_ptr->level) continue;
4609 			/* Skip unique monsters */
4610 			if (r_ptr->flags1 & RF1_UNIQUE) continue;
4611 			/* Skip non-escorting monsters */
4612 //			if (m_ptr->escorting != who) continue;
4613 		}
4614 
4615 		/* wake_minions used by an escorting monster? */
4616 #if 0	/* m_ptr->escorting = m_idx not yet implemented */
4617 		if (mw_ptr->escorting) {
4618 			/* Wake up his leader, which always is unique */
4619 			if (m_ptr->r_idx != mw_ptr->escorting) continue;
4620 			/* Leader wakes the pack */
4621 			wake_minions(Ind, i);
4622 		}
4623 #endif
4624 
4625 		/* Wake up nearby sleeping monsters */
4626 		if (distance(mw_ptr->fy, mw_ptr->fx, m_ptr->fy, m_ptr->fx) > rw_ptr->aaf) continue;
4627 #if 0
4628 		if (m_ptr->cdis < MAX_SIGHT * 2)
4629 #endif
4630 		{
4631 			/* Wake up */
4632 			if (m_ptr->csleep) {
4633 				/* Wake up */
4634 				m_ptr->csleep = 0;
4635 				sleep = TRUE;
4636 			}
4637 		}
4638 #if 0
4639 		/* Speed up monsters in line of sight */
4640 		if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4641 			/* Speed up (instantly) to racial base + 10 */
4642                         if (m_ptr->mspeed < m_ptr->speed + 10) {
4643 				/* Speed up */
4644                                 m_ptr->mspeed = m_ptr->speed + 10;
4645 				speed = TRUE;
4646 			}
4647 		}
4648 #endif
4649 	}
4650 
4651 	/* Messages */
4652 	if (!sleep) return;
4653 //	if (speed) msg_print(Ind, "You feel a sudden stirring nearby!");
4654 //	else if (sleep) msg_print(Ind, "You hear a sudden stirring in the distance!");
4655 	if ((r_ptr->flags2 & RF2_EMPTY_MIND) || (r_ptr->flags3 & RF3_NONLIVING)) ;
4656 	else if (r_ptr->flags3 & RF3_DRAGON) msg_format(Ind, "%s roars loudly!", mw_name);
4657 	else if (r_ptr->flags3 & RF3_UNDEAD) msg_format(Ind, "%s moans loudly!", mw_name);
4658 	else if (r_ptr->flags3 & RF3_ANIMAL) msg_format(Ind, "%s makes an alerting sound!", mw_name);
4659 	else if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON | RF3_DRAGONRIDER)) ||
4660 	    (strchr("AhHJkpPty", r_ptr->d_char))) {
4661 		msg_format(Ind, "%s shouts a command!", mw_name);
4662 		msg_format_near(Ind, "%s shouts a command!", mw_name);
4663 	}
4664 }
4665 
4666 
4667 /*
4668  * If Ind <=0, no one takes the damage.	- Jir -OA
4669  */
genocide_aux(int Ind,worldpos * wpos,char typ)4670 bool genocide_aux(int Ind, worldpos *wpos, char typ) {
4671 	player_type *p_ptr = Players[Ind];
4672 	int		i;
4673 	bool	result = FALSE;
4674 	int tmp;	// , d = 999;
4675 
4676 	dun_level		*l_ptr = getfloor(wpos);
4677 	cave_type **zcave;
4678 
4679 	if (!(zcave = getcave(wpos))) return(FALSE);
4680 	if(l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
4681 
4682 	bypass_invuln = TRUE;
4683 
4684 	/* Delete the monsters of that "type" */
4685 	for (i = 1; i < m_max; i++) {
4686 		monster_type	*m_ptr = &m_list[i];
4687 		monster_race    *r_ptr = race_inf(m_ptr);
4688 
4689 		/* Paranoia -- Skip dead monsters */
4690 		if (!m_ptr->r_idx) continue;
4691 
4692 		/* Hack -- Skip Unique Monsters */
4693 		if (r_ptr->flags1 & RF1_UNIQUE) continue;
4694 
4695 		/* Skip "wrong" monsters */
4696 		if (r_ptr->d_char != typ) continue;
4697 
4698 		/* Skip monsters not on this depth */
4699 		if(!inarea(wpos, &m_ptr->wpos)) continue;
4700 
4701 		/* Skip those immune */
4702 		if (r_ptr->flags9 & RF9_IM_TELE) continue;
4703 
4704 		/* Roll for resistance */
4705 		tmp = r_ptr->level;
4706 #ifdef RESIST_GENO
4707 		if (randint(RESIST_GENO) < tmp) continue;
4708 #endif	// RESIST_GENO
4709 
4710 #ifdef NO_GENO_ON_ICKY
4711 		/* Not valid inside a vault */
4712 		if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
4713 #endif	// NO_GENO_ON_ICKY
4714 
4715 		/* Delete the monster */
4716 		delete_monster_idx(i, TRUE);
4717 
4718 		/* Take damage */
4719 		if (Ind > 0)
4720 		{
4721 			if (!p_ptr->admin_dm)
4722 				take_hit(Ind, randint(4 + (tmp >> 3)), "the strain of casting Genocide", 0);
4723 
4724 			/* Redraw */
4725 			p_ptr->redraw |= (PR_HP);
4726 
4727 			/* Window stuff */
4728 			/* p_ptr->window |= (PW_PLAYER); */
4729 
4730 			/* Handle */
4731 			handle_stuff(Ind);
4732 
4733 			/* Delay */
4734 //			Send_flush(Ind); /* I don't think a delay is really necessary - mikaelh */
4735 		}
4736 
4737 		/* Take note */
4738 		result = TRUE;
4739 	}
4740 
4741 	if (Ind > 0) {
4742 #ifdef SEVERE_GENO
4743 		if (!p_ptr->death && result && !p_ptr->admin_dm)
4744 			take_hit(Ind, p_ptr->chp >> 1, "the strain of casting Genocide", 0);
4745 
4746 		/* Redraw */
4747 		p_ptr->redraw |= (PR_HP);
4748 #endif	// SEVERE_GENO
4749 
4750 		/* Window stuff */
4751 		p_ptr->window |= (PW_PLAYER);
4752 
4753 		/* Handle */
4754 		handle_stuff(Ind);
4755 	}
4756 
4757 	bypass_invuln = FALSE;
4758 
4759 	return (result);
4760 }
4761 
4762 /*
4763  * Delete all non-unique monsters of a given "type" from the level
4764  *
4765  * This is different from normal Angband now -- the closest non-unique
4766  * monster is chosen as the designed character to genocide.
4767  */
genocide(int Ind)4768 bool genocide(int Ind) {
4769 	player_type *p_ptr = Players[Ind];
4770 	int	i;
4771 	char	typ = -1;
4772 	int	d = 999, tmp;
4773 
4774 	worldpos *wpos = &p_ptr->wpos;
4775 	dun_level *l_ptr = getfloor(wpos);
4776 	cave_type **zcave;
4777 
4778 	if (!(zcave = getcave(wpos))) return(FALSE);
4779 	if(l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);	// double check..
4780 
4781 	/* Search all monsters and find the closest */
4782 	for (i = 1; i < m_max; i++) {
4783 		monster_type *m_ptr = &m_list[i];
4784                 monster_race *r_ptr = race_inf(m_ptr);
4785 
4786 		/* Paranoia -- Skip dead monsters */
4787 		if (!m_ptr->r_idx) continue;
4788 
4789 		/* Hack -- Skip Unique Monsters */
4790 		if (r_ptr->flags1 & RF1_UNIQUE) continue;
4791 
4792 		/* Skip monsters not on this depth */
4793 		if(!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4794 
4795 		/* Check distance */
4796 		if ((tmp = distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx)) < d) {
4797 			/* Set closest distance */
4798 			d = tmp;
4799 
4800 			/* Set char */
4801 			typ = r_ptr->d_char;
4802 		}
4803 	}
4804 
4805 	/* Check to make sure we found a monster */
4806 	if (d == 999) return FALSE;
4807 
4808 	return (genocide_aux(Ind, wpos, typ));
4809 }
4810 
4811 
4812 /*
4813  * Delete all nearby (non-unique) monsters
4814  * Either Ind must be a player's index for use by a player,
4815  * or Ind must be -m_idx for use by a monster trap.
4816  */
obliteration(int who)4817 bool obliteration(int who) {
4818 	player_type *p_ptr;
4819 	int i, tmp, rad, x, y;
4820 	bool result = FALSE;
4821 
4822 	worldpos *wpos;
4823 	dun_level *l_ptr;
4824 	cave_type **zcave;
4825 
4826 	/* monster hit a monster trap? */
4827 	if (who < 0) {
4828 		rad = 1;
4829 		p_ptr = NULL;
4830 		wpos = &m_list[-who].wpos;
4831 		x = m_list[-who].fx;
4832 		y = m_list[-who].fy;
4833 	}
4834 	/* player cast it */
4835 	else {
4836 		rad = MAX_SIGHT;
4837 		p_ptr = Players[who];
4838 		wpos = &p_ptr->wpos;
4839 		x = p_ptr->px;
4840 		y = p_ptr->py;
4841 	}
4842 
4843 	if (!(zcave = getcave(wpos))) return(FALSE);
4844 	l_ptr = getfloor(wpos);
4845 	if (l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
4846 
4847 	bypass_invuln = TRUE;
4848 
4849 	/* Delete the (nearby) monsters */
4850 	for (i = 1; i < m_max; i++) {
4851 		monster_type *m_ptr = &m_list[i];
4852                 monster_race *r_ptr = race_inf(m_ptr);
4853 
4854 		/* Paranoia -- Skip dead monsters */
4855 		if (!m_ptr->r_idx) continue;
4856 
4857 		/* Skip monsters not on this depth */
4858 		if (!inarea(wpos, &m_ptr->wpos)) continue;
4859 
4860 		/* Hack -- Skip unique monsters */
4861 		if (r_ptr->flags1 & RF1_UNIQUE) continue;
4862 
4863 		/* Skip distant monsters */
4864 		if (distance(y, x, m_ptr->fy, m_ptr->fx) > rad)
4865 #if 0
4866 		if (m_ptr->cdis > MAX_SIGHT)
4867 #endif
4868 			continue;
4869 
4870 		/* Skip those immune */
4871 		if (r_ptr->flags9 & RF9_IM_TELE) continue;
4872 
4873 		/* Roll for resistance */
4874 		tmp = r_ptr->level;
4875 #ifdef RESIST_GENO
4876 		if (randint(RESIST_GENO) < tmp) continue;
4877 #endif	// RESIST_GENO
4878 
4879 #ifdef NO_GENO_ON_ICKY
4880 		/* Not valid inside a vault */
4881 		if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY && p_ptr && !p_ptr->admin_dm)
4882 			continue;
4883 #endif	// NO_GENO_ON_ICKY
4884 
4885 		/* Delete the monster */
4886 		delete_monster_idx(i, TRUE);
4887 
4888 		/* Hack -- visual feedback */
4889 		/* does not effect the dungeon master, because it disturbs his movement
4890 		 */
4891 		if (p_ptr && !p_ptr->admin_dm) {
4892 			take_hit(who, randint(3 + (tmp >> 3)), "the strain of casting Genocide", 0);
4893 
4894 			/* Redraw */
4895 			p_ptr->redraw |= (PR_HP);
4896 
4897 			/* Window stuff */
4898 			/* p_ptr->window |= (PW_PLAYER); */
4899 
4900 			/* Handle */
4901 			handle_stuff(who);
4902 
4903 			/* Delay */
4904 			//Send_flush(who); /* I don't think a delay is really necessary - mikaelh */
4905 		}
4906 
4907 		/* Note effect */
4908 		result = TRUE;
4909 	}
4910 
4911 	if (p_ptr) {
4912 #ifdef SEVERE_GENO
4913 		if (!p_ptr->death && result && !p_ptr->admin_dm) {
4914 			take_hit(who, p_ptr->chp >> 1, "the strain of casting Genocide", 0);
4915 
4916 			/* Redraw */
4917 			p_ptr->redraw |= (PR_HP);
4918 		}
4919 #endif
4920 
4921 		/* Window stuff */
4922 		p_ptr->window |= (PW_PLAYER);
4923 
4924 		/* Handle */
4925 		handle_stuff(who);
4926 	}
4927 
4928 	bypass_invuln = FALSE;
4929 
4930 	return (result);
4931 }
4932 
4933 
4934 
4935 /*
4936  * Probe nearby monsters
4937  */
probing(int Ind)4938 bool probing(int Ind) {
4939 	monster_type *m_ptr;
4940 	monster_race *r_ptr;
4941 	int            i;
4942 	player_type *p_ptr = Players[Ind];
4943 	struct worldpos *wpos = &p_ptr->wpos;
4944 	bool	probe = FALSE;
4945 
4946 	/* Probe all (nearby) monsters */
4947 	for (i = 1; i < m_max; i++) {
4948 		m_ptr = &m_list[i];
4949 		r_ptr = race_inf(m_ptr);
4950 
4951 		/* Paranoia -- Skip dead monsters */
4952 		if (!m_ptr->r_idx) continue;
4953 
4954 		/* Skip monsters not on this depth */
4955 		if (!inarea(&m_ptr->wpos, wpos)) continue;
4956 
4957 		/* Require line of sight */
4958 		if (!player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) continue;
4959 
4960 		/* Probe visible monsters */
4961 		if (p_ptr->mon_vis[i]) {
4962 			char m_name[MNAME_LEN];
4963 			char buf[80];
4964 			int j;
4965 
4966 			/* Start the message */
4967 			if (!probe) msg_print(Ind, "Probing...");
4968 
4969 			/* Get "the monster" or "something" */
4970 			monster_desc(Ind, m_name, i, 0x04);
4971 			sprintf(buf, "blows");
4972 
4973 			for (j = 0; j < 4; j++)
4974 				if (m_ptr->blow[j].d_dice) strcat(buf, format(" %dd%d", m_ptr->blow[j].d_dice, m_ptr->blow[j].d_side));
4975 
4976 			/* Describe the monster */
4977 			if (r_ptr->flags7 & RF7_NO_DEATH)
4978 				msg_format(Ind, "%^s (%d) has unknown hp, %d ac, %d speed.", m_name, m_ptr->level, m_ptr->ac, m_ptr->mspeed - 110);
4979 			else
4980 				msg_format(Ind, "%^s (%d) has %d hp, %d ac, %d speed.", m_name, m_ptr->level, m_ptr->hp, m_ptr->ac, m_ptr->mspeed - 110);
4981 			/* include m_idx for admins */
4982 			if (is_admin(p_ptr)) msg_format(Ind, "%^s (Lv%d,%d) %s.", m_name, m_ptr->level, i, buf);
4983 			else msg_format(Ind, "%^s (Lv%d) %s.", m_name, m_ptr->level, buf);
4984 
4985 			/* Learn all of the non-spell, non-treasure flags */
4986 			lore_do_probe(i);
4987 
4988 			/* Probe worked */
4989 			probe = TRUE;
4990 		}
4991 	}
4992 
4993 	/* Done */
4994 	if (probe) msg_print(Ind, "That's all.");
4995 
4996 	/* Result */
4997 	return (probe);
4998 }
4999 
5000 
5001 
5002 /*
5003  * The spell of destruction
5004  *
5005  * This spell "deletes" monsters (instead of "killing" them).
5006  *
5007  * Later we may use one function for both "destruction" and
5008  * "earthquake" by using the "full" to select "destruction".
5009  */
destroy_area(struct worldpos * wpos,int y1,int x1,int r,bool full,byte feat,int stun)5010 void destroy_area(struct worldpos *wpos, int y1, int x1, int r, bool full, byte feat, int stun) {
5011 	int y, x, k, t, Ind;
5012 	player_type *p_ptr;
5013 	cave_type *c_ptr;
5014 	/*bool flag = FALSE;*/
5015 
5016 	dun_level *l_ptr = getfloor(wpos);
5017 	struct c_special *cs_ptr;       /* for special key doors */
5018 	cave_type **zcave;
5019 
5020 	if (!(zcave = getcave(wpos))) return;
5021 	if(l_ptr && l_ptr->flags1 & LF1_NO_DESTROY) return;
5022 
5023 	/* among others, make sure town areas aren't affected.. */
5024 	if (!allow_terraforming(wpos, FEAT_WALL_EXTRA)) return;
5025 
5026 	/* XXX XXX */
5027 	full = full ? full : 0;
5028 
5029 	/* Set to default */
5030 	feat = feat ? feat : FEAT_FLOOR;
5031 
5032 	/* Can't trigger within Vault? - note: this prevents exploit as well as death-_trap_ at once :) */
5033 	if (zcave[y1][x1].info & CAVE_ICKY) return;
5034 
5035 	/* Big area of affect */
5036 	for (y = (y1 - r); y <= (y1 + r); y++) {
5037 		for (x = (x1 - r); x <= (x1 + r); x++) {
5038 			/* Skip illegal grids */
5039 			if (!in_bounds(y, x)) continue;
5040 
5041 			/* Extract the distance */
5042 			k = distance(y1, x1, y, x);
5043 
5044 			/* Stay in the circle of death */
5045 			if (k > r) continue;
5046 
5047 			/* Access the grid */
5048 			c_ptr = &zcave[y][x];
5049 
5050 			/* Vault is protected */
5051 			if (c_ptr->info & CAVE_ICKY) continue;
5052 
5053 			/* Special key doors are protected -C. Blue */
5054 			if ((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
5055 
5056 			/* Lose room and nest */
5057 			/* Hack -- don't do this to houses/rooms outside the dungeon,
5058 			 * this will protect hosues outside town.
5059 			 */
5060 			if(wpos->wz) {
5061 				/* Lose room and nest */
5062 				c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT);
5063 			}
5064 
5065 			/* Lose light and knowledge */
5066 			c_ptr->info &= ~(CAVE_GLOW);
5067 			everyone_forget_spot(wpos, y, x);
5068 
5069 			/* Hack -- Notice player affect */
5070 			if (c_ptr->m_idx < 0) {
5071 				Ind = 0 - c_ptr->m_idx;
5072 				p_ptr = Players[Ind];
5073 
5074 				/* Message */
5075 				msg_print(Ind, "\377oThere is a searing blast of light and a terrible shockwave!");
5076 #ifdef USE_SOUND_2010
5077 				sound(Ind, "destruction", NULL, SFX_TYPE_MISC, FALSE);
5078 #endif
5079 
5080 				/* Blind the player */
5081 				if (!p_ptr->resist_blind && !p_ptr->resist_lite) {
5082 					/* Become blind */
5083 					(void)set_blind(Ind, p_ptr->blind + 20 + randint(10));
5084 				}
5085 				(void)set_stun(Ind, stun); /* ~20s in NR, depends tho */
5086 
5087 				/* Mega-Hack -- Forget the view and lite */
5088 				p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
5089 
5090 				/* Update stuff */
5091 				p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
5092 
5093 				/* Update the monsters */
5094 				p_ptr->update |= (PU_MONSTERS);
5095 
5096 				/* Redraw map */
5097 				p_ptr->redraw |= (PR_MAP);
5098 
5099 				/* Window stuff */
5100 				p_ptr->window |= (PW_OVERHEAD);
5101 
5102 				/* Do not hurt this grid */
5103 				continue;
5104 			}
5105 
5106 			/* Hack -- Skip the epicenter */
5107 			if ((y == y1) && (x == x1)) continue;
5108 
5109 			/* Delete the monster (if any) */
5110                         if (c_ptr->m_idx > 0) {
5111                                 monster_race *r_ptr = race_inf(&m_list[c_ptr->m_idx]);
5112                                 if (!(r_ptr->flags9 & RF9_IM_TELE)) delete_monster(wpos, y, x, TRUE);
5113                                 else continue;
5114                         }
5115 
5116 			/* Destroy "valid" grids */
5117 //			if ((cave_valid_bold(zcave, y, x)) && !(c_ptr->info&CAVE_ICKY))
5118 			if (cave_valid_bold(zcave, y, x)) {
5119 				struct c_special *cs_ptr;
5120 				/* Delete the object (if any) */
5121 				delete_object(wpos, y, x, TRUE);
5122 
5123 				/* Wall (or floor) type */
5124 				t = rand_int(200);
5125 
5126 				if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
5127 					/* Destroy the trap */
5128 					if (t < 100) cs_erase(c_ptr, cs_ptr);
5129 					else cs_ptr->sc.trap.found = FALSE;
5130 
5131 					/* Redraw */
5132 //					everyone_lite_spot(wpos, y, x);
5133 				}
5134 
5135 				/* Granite */
5136 				if (t < 20) {
5137 					/* Create granite wall */
5138 					cave_set_feat_live(wpos, y, x, FEAT_WALL_EXTRA);
5139 				}
5140 
5141 				/* Quartz */
5142 				else if (t < 70) {
5143 					/* Create quartz vein */
5144 					cave_set_feat_live(wpos, y, x, FEAT_QUARTZ);
5145 				}
5146 
5147 				/* Magma */
5148 				else if (t < 100) {
5149 					/* Create magma vein */
5150 					cave_set_feat_live(wpos, y, x, FEAT_MAGMA);
5151 				}
5152 
5153 				/* Floor */
5154 				else {
5155 					/* Create floor or whatever specified */
5156 					cave_set_feat_live(wpos, y, x, feat);
5157 				}
5158 			}
5159 		}
5160 	}
5161 	for (k = 1; k <= NumPlayers; k++) {
5162 		if (inarea(wpos, &Players[k]->wpos) &&
5163 		    Players[k]->stun < stun) {
5164 			msg_print(k, "\377oYou are hit by a terrible shockwave!");
5165 			(void)set_stun(k, stun - (distance(Players[k]->py, Players[k]->px, y1, x1) - r) / 3);
5166 		}
5167 	}
5168 }
5169 
5170 
5171 /*
5172  * Induce an "earthquake" of the given radius at the given location.
5173  *
5174  * This will turn some walls into floors and some floors into walls.
5175  *
5176  * The player will take damage and "jump" into a safe grid if possible,
5177  * otherwise, he will "tunnel" through the rubble instantaneously.
5178  *
5179  * Monsters will take damage, and "jump" into a safe grid if possible,
5180  * otherwise they will be "buried" in the rubble, disappearing from
5181  * the level in the same way that they do when genocided.
5182  *
5183  * Note that thus the player and monsters (except eaters of walls and
5184  * passers through walls) will never occupy the same grid as a wall.
5185  * Note that as of now (2.7.8) no monster may occupy a "wall" grid, even
5186  * for a single turn, unless that monster can pass_walls or kill_walls.
5187  * This has allowed massive simplification of the "monster" code.
5188  */
earthquake(struct worldpos * wpos,int cy,int cx,int r)5189 void earthquake(struct worldpos *wpos, int cy, int cx, int r) {
5190 	int		i, t, y, x, yy, xx, dy, dx, oy, ox;
5191 	int		damage = 0;
5192 	int		sn = 0, sy = 0, sx = 0;
5193 	int Ind;
5194 	player_type *p_ptr;
5195 	/*bool	hurt = FALSE;*/
5196 	cave_type	*c_ptr;
5197 	bool	map[32][32];
5198 	dun_level *l_ptr = getfloor(wpos);
5199 	struct c_special *cs_ptr;	/* for special key doors */
5200 	cave_type **zcave;
5201 
5202 	if (!(zcave = getcave(wpos))) return;
5203 	if(l_ptr && (l_ptr->flags1 & LF1_NO_DESTROY) && !override_LF1_NO_DESTROY) return;
5204 	override_LF1_NO_DESTROY = FALSE;
5205 
5206 	/* among others, make sure town areas aren't affected.. */
5207 	if (!allow_terraforming(wpos, FEAT_WALL_EXTRA)) return;
5208 
5209 	/* Paranoia -- Dnforce maximum range */
5210 	if (r > 12) r = 12;
5211 
5212 	/* Clear the "maximal blast" area */
5213 	for (y = 0; y < 32; y++) {
5214 		for (x = 0; x < 32; x++) {
5215 			map[y][x] = FALSE;
5216 		}
5217 	}
5218 
5219 	/* No one has taken any damage from this earthquake yet - mikaelh */
5220 	for (Ind = 1; Ind <= NumPlayers; Ind++)
5221 		Players[Ind]->total_damage = 0;
5222 
5223 	/* Check around the epicenter */
5224 	for (dy = -r; dy <= r; dy++) {
5225 		for (dx = -r; dx <= r; dx++) {
5226 			/* Extract the location */
5227 			yy = cy + dy;
5228 			xx = cx + dx;
5229 
5230 			/* Skip illegal grids */
5231 			if (!in_bounds(yy, xx)) continue;
5232 
5233 			/* Skip distant grids */
5234 			if (distance(cy, cx, yy, xx) > r) continue;
5235 
5236 			/* Access the grid */
5237 			c_ptr = &zcave[yy][xx];
5238 
5239 			/* Hack -- ICKY spaces are protected outside of the dungeon */
5240 			if ((!wpos->wz) && (c_ptr->info & CAVE_ICKY)) continue;
5241 
5242 			/* Special key doors are protected -C. Blue */
5243 			if ((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
5244 
5245 #if 0 /* noticed this at 10.jan 2009, if'0ed it, and added below else branch,
5246 	since it allows teleportation within vaults!  - C. Blue */
5247 /* note: this miiiight be ok for non-no_tele vaults, or if no_tele is also removed, and if
5248    additionally the vault wasn't build from perma-walls, so the walls actually got quaked away too;
5249    for that, also check 'cave_valid_bold' check used to actually destroy grids (further below). */
5250 
5251 			/* Lose room and vault and nest */
5252 			c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT | CAVE_ICKY | CAVE_STCK);
5253 
5254 #else /* keep preventing teleport from targetting a space inside the (quaked) vault */
5255 			/* Lose room and nest */
5256 			c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT);
5257 
5258  #if 0 /* addition mentioned above, but maybe bad idea? */
5259 			if (!(c_ptr->info & (CAVE_ICKY_PERMA | CAVE_STCK))) c_ptr->info &= ~CAVE_ICKY;
5260  #endif
5261 #endif
5262 
5263 			/* Lose light */
5264 			c_ptr->info &= ~(CAVE_GLOW);
5265 
5266 			/* This can be really annoying and frustrating - mikaelh */
5267 //			everyone_forget_spot(wpos, y, x);
5268 			everyone_lite_spot(wpos, y, x);
5269 
5270 #ifdef USE_SOUND_2010
5271 			if (c_ptr->m_idx < 0) sound(-c_ptr->m_idx, "earthquake", NULL, SFX_TYPE_NO_OVERLAP, FALSE);
5272 #endif
5273 
5274 			/* Skip the epicenter */
5275 			if ((!dx && !dy) && r) continue;
5276 
5277 			/* Skip most grids */
5278 			if (rand_int(100) < 85) continue;
5279 
5280 			/* Damage this grid */
5281 			map[16 + yy - cy][16 + xx - cx] = TRUE;
5282 
5283 			/* Hack -- Take note of player damage */
5284 			if (c_ptr->m_idx < 0) {
5285 				Ind = 0 - c_ptr->m_idx;
5286 				p_ptr = Players[Ind];
5287 				store_exit(Ind);
5288 
5289 				sn = 0;
5290 
5291 				/* Check around the player */
5292 				for (i = 0; i < 8; i++) {
5293 					/* Access the location */
5294 					y = p_ptr->py + ddy[i];
5295 					x = p_ptr->px + ddx[i];
5296 
5297 					/* Skip non-empty grids */
5298 					if (!cave_empty_bold(zcave, y, x)) continue;
5299 
5300 					/* Important -- Skip "quake" grids */
5301 					if (map[16+y-cy][16+x-cx]) continue;
5302 
5303 					/* Count "safe" grids */
5304 					sn++;
5305 
5306 					/* Randomize choice */
5307 					if (rand_int(sn) > 0) continue;
5308 
5309 					/* Save the safe location */
5310 					sy = y; sx = x;
5311 				}
5312 
5313 				/* Random message */
5314 				switch (randint(3)) {
5315 				case 1:
5316 					msg_print(Ind, "The cave ceiling collapses!");
5317 					break;
5318 				case 2:
5319 					msg_print(Ind, "The cave floor twists in an unnatural way!");
5320 					break;
5321 				default:
5322 					msg_print(Ind, "The cave quakes! You are pummeled with debris!");
5323 					break;
5324 				}
5325 
5326 				/* Hurt the player a lot */
5327 				if (!sn) {
5328 					/* Message and damage */
5329 					damage = 300;
5330 					if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5331 					/* Cap the damage - mikaelh */
5332 					if (damage + p_ptr->total_damage > 300) {
5333 						damage = 300 - p_ptr->total_damage;
5334 					}
5335 					if (damage) msg_format(Ind, "You are severely crushed for \377o%d\377w damage!", damage);
5336 
5337 					/* Stun only once - mikaelh */
5338 					if (p_ptr->total_damage == 0) {
5339 						(void)set_stun(Ind, p_ptr->stun + randint(40));
5340 					}
5341 				}
5342 
5343 				/* Destroy the grid, and push the player to safety */
5344 				else {
5345 					/* Calculate results */
5346 					switch (randint(3) - (magik((p_ptr->dodge_level * 3) / 4) ? 1 : 0) - (p_ptr->shadow_running ? 1 : 0)) {
5347 						case -1:
5348 						case 0:
5349 						case 1:
5350 							damage = 0;
5351 							msg_format(Ind, "\377%cYou nimbly dodge the blast and take no damage!", COLOUR_DODGE_GOOD);
5352 							break;
5353 						case 2:
5354 							damage = damroll(10, 4);
5355 							if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5356 							/* Cap the damage - mikaelh */
5357 							if (damage + p_ptr->total_damage > 300)
5358 								damage = 300 - p_ptr->total_damage;
5359 							if (damage)
5360 								msg_format(Ind, "You are bashed by rubble for \377o%d\377w damage!", damage);
5361 
5362 							/* Stun only once - mikaelh */
5363 							if (p_ptr->total_damage == 0) {
5364 								(void)set_stun(Ind, p_ptr->stun + randint(33));
5365 							}
5366 							break;
5367 						case 3:
5368 							damage = damroll(30, 4);
5369 							if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5370 							/* Cap the damage - mikaelh */
5371 							if (damage + p_ptr->total_damage > 300)
5372 								damage = 300 - p_ptr->total_damage;
5373 							if (damage)
5374 								msg_format(Ind, "You are crushed between the floor and ceiling for \377o%d\377w damage!", damage);
5375 
5376 							/* Stun only once - mikaelh */
5377 							if (p_ptr->total_damage == 0)
5378 								(void)set_stun(Ind, p_ptr->stun + randint(33));
5379 							break;
5380 					}
5381 
5382 					/* Save the old location */
5383 					oy = p_ptr->py;
5384 					ox = p_ptr->px;
5385 
5386 					/* Move the player to the safe location */
5387 					p_ptr->py = sy;
5388 					p_ptr->px = sx;
5389 
5390 					/* Update the cave player indices */
5391 					zcave[oy][ox].m_idx = 0;
5392 					zcave[sy][sx].m_idx = 0 - Ind;
5393 					cave_midx_debug(wpos, sy, sx, -Ind);
5394 
5395 					/* Redraw the old spot */
5396 					everyone_lite_spot(wpos, oy, ox);
5397 
5398 					/* Redraw the new spot */
5399 					everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
5400 
5401 					/* Check for new panel */
5402 					verify_panel(Ind);
5403 				}
5404 
5405 				/* Important -- no wall on player */
5406 				map[16 + p_ptr->py - cy][16 + p_ptr->px - cx] = FALSE;
5407 
5408 				/* Take some damage */
5409 				if (damage) {
5410 					take_hit(Ind, damage, "an earthquake", 0);
5411 
5412 					/* Add it tot the total damage taken - mikaelh */
5413 					p_ptr->total_damage += damage;
5414 				}
5415 
5416 				/* Mega-Hack -- Forget the view and lite */
5417 				p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
5418 
5419 				/* Update stuff */
5420 				p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
5421 
5422 				/* Update the monsters */
5423 				p_ptr->update |= (PU_DISTANCE);
5424 
5425 				/* Update the health bar */
5426 				p_ptr->redraw |= (PR_HEALTH);
5427 
5428 				/* Redraw map */
5429 				p_ptr->redraw |= (PR_MAP);
5430 
5431 				/* Window stuff */
5432 				p_ptr->window |= (PW_OVERHEAD);
5433 			}
5434 		}
5435 	}
5436 
5437 
5438 	/* Examine the quaked region */
5439 	for (dy = -r; dy <= r; dy++) {
5440 		for (dx = -r; dx <= r; dx++) {
5441 			/* Extract the location */
5442 			yy = cy + dy;
5443 			xx = cx + dx;
5444 
5445 			/* Skip unaffected grids */
5446 			if (!map[16 + yy - cy][16 + xx - cx]) continue;
5447 
5448 			/* Access the grid */
5449 			c_ptr = &zcave[yy][xx];
5450 
5451 			/* Process monsters */
5452 			if (c_ptr->m_idx > 0) {
5453 				monster_type *m_ptr = &m_list[c_ptr->m_idx];
5454                                 monster_race *r_ptr = race_inf(m_ptr);
5455 
5456 				/* Most monsters cannot co-exist with rock */
5457 				if (!(r_ptr->flags2 & RF2_KILL_WALL) &&
5458 				    !(r_ptr->flags2 & RF2_PASS_WALL)) {
5459 					/* Assume not safe */
5460 					sn = 0;
5461 
5462 					/* Monster can move to escape the wall */
5463 					if (!(r_ptr->flags1 & RF1_NEVER_MOVE)) {
5464 						/* Look for safety */
5465 						for (i = 0; i < 8; i++) {
5466 							/* Access the grid */
5467 							y = yy + ddy[i];
5468 							x = xx + ddx[i];
5469 
5470 							/* Skip non-empty grids */
5471 							if (!cave_empty_bold(zcave, y, x)) continue;
5472 
5473 							/* Hack -- no safety on glyph of warding */
5474 							if (zcave[y][x].feat == FEAT_GLYPH) continue;
5475 							if (zcave[y][x].feat == FEAT_RUNE) continue;
5476 
5477 							/* Important -- Skip "quake" grids */
5478 							if (map[16 + y - cy][16 + x - cx]) continue;
5479 
5480 							/* Count "safe" grids */
5481 							sn++;
5482 
5483 							/* Randomize choice */
5484 							if (rand_int(sn) > 0) continue;
5485 
5486 							/* Save the safe grid */
5487 							sy = y; sx = x;
5488 						}
5489 					}
5490 
5491 					/* Describe the monster */
5492 					/*monster_desc(Ind, m_name, c_ptr->m_idx, 0);*/
5493 
5494 					/* Scream in pain */
5495 					/*msg_format("%^s wails out in pain!", m_name);*/
5496 
5497 					/* Take damage from the quake */
5498 					damage = (sn ? damroll(4, 8) : 200);
5499 
5500 					/* Monster is certainly awake */
5501 					m_ptr->csleep = 0;
5502 
5503 					/* Apply damage directly */
5504 					m_ptr->hp -= damage;
5505 
5506 					/* Delete (not kill) "dead" monsters */
5507 					if (m_ptr->hp < 0) {
5508 						/* Message */
5509 						/*msg_format("%^s is embedded in the rock!", m_name);*/
5510 
5511 						/* Delete the monster */
5512 						delete_monster(wpos, yy, xx, TRUE);
5513 
5514 						/* No longer safe */
5515 						sn = 0;
5516 					}
5517 
5518 					/* Hack -- Escape from the rock */
5519 					if (sn) {
5520 						int m_idx = zcave[yy][xx].m_idx;
5521 
5522 						/* Update the new location */
5523 						zcave[sy][sx].m_idx = m_idx;
5524 
5525 						/* Update the old location */
5526 						zcave[yy][xx].m_idx = 0;
5527 
5528 						/* Move the monster */
5529 						m_ptr->fy = sy;
5530 						m_ptr->fx = sx;
5531 
5532 						/* Update the monster (new location) */
5533 						update_mon(m_idx, TRUE);
5534 
5535 						/* Redraw the new grid */
5536 						everyone_lite_spot(wpos, yy, xx);
5537 
5538 						/* Redraw the new grid */
5539 						everyone_lite_spot(wpos, sy, sx);
5540 					}
5541 				}
5542 			}
5543 		}
5544 	}
5545 
5546 
5547 	/* Examine the quaked region */
5548 	for (dy = -r; dy <= r; dy++) {
5549 		for (dx = -r; dx <= r; dx++) {
5550 			/* Extract the location */
5551 			yy = cy + dy;
5552 			xx = cx + dx;
5553 
5554 			/* Skip unaffected grids */
5555 			if (!map[16+yy-cy][16+xx-cx]) continue;
5556 
5557 			/* Access the cave grid */
5558 			c_ptr = &zcave[yy][xx];
5559 
5560 			/* Paranoia -- never affect player */
5561 			if (c_ptr->m_idx < 0) continue;
5562 
5563 			/* Destroy location (if valid) */
5564 			if (cave_valid_bold(zcave, yy, xx)) {
5565 				bool floor = cave_floor_bold(zcave, yy, xx);
5566 
5567 				/* Delete any object that is still there */
5568 				delete_object(wpos, yy, xx, TRUE);
5569 
5570 				/* Wall (or floor) type */
5571 				t = (floor ? rand_int(100) : 200);
5572 
5573 				/* Granite */
5574 				if (t < 20)
5575 					/* Create granite wall */
5576 					cave_set_feat_live(wpos, yy, xx, FEAT_WALL_EXTRA);
5577 
5578 				/* Quartz */
5579 				else if (t < 70)
5580 					/* Create quartz vein */
5581 					cave_set_feat_live(wpos, yy, xx, FEAT_QUARTZ);
5582 
5583 				/* Magma */
5584 				else if (t < 100)
5585 					/* Create magma vein */
5586 					cave_set_feat_live(wpos, yy, xx, FEAT_MAGMA);
5587 
5588 				/* Floor */
5589 				else
5590 					/* Create floor */
5591 //uses static array set in generate.c, fix!	place_floor_live(wpos, yy, xx);
5592 					cave_set_feat_live(wpos, yy, xx, FEAT_FLOOR);
5593 			}
5594 		}
5595 	}
5596 }
5597 
5598 /* Wipe everything */
wipe_spell(struct worldpos * wpos,int cy,int cx,int r)5599 void wipe_spell(struct worldpos *wpos, int cy, int cx, int r) {
5600 	int		yy, xx, dy, dx;
5601 	cave_type	*c_ptr;
5602 
5603 	cave_type **zcave;
5604 	if(!(zcave = getcave(wpos))) return;
5605 	/* Don't hurt town or surrounding areas */
5606 	if(istownarea(wpos, MAX_TOWNAREA)) return;
5607 
5608 	/* Paranoia -- Dnforce maximum range */
5609 	if (r > 12) r = 12;
5610 
5611 	/* Check around the epicenter */
5612 	for (dy = -r; dy <= r; dy++) {
5613 		for (dx = -r; dx <= r; dx++) {
5614 			/* Extract the location */
5615 			yy = cy + dy;
5616 			xx = cx + dx;
5617 
5618 			/* Skip illegal grids */
5619 			if (!in_bounds(yy, xx)) continue;
5620 
5621 			/* Skip distant grids */
5622 			if (distance(cy, cx, yy, xx) > r) continue;
5623 
5624 			/* Access the grid */
5625 			c_ptr = &zcave[yy][xx];
5626 
5627 			/* Hack -- ICKY spaces are protected outside of the dungeon */
5628 			if (c_ptr->info & CAVE_ICKY) continue;
5629 
5630 			/* Lose room and vault */
5631 			c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_NEST_PIT | CAVE_STCK | CAVE_ICKY_PERMA);
5632 
5633 			/* Turn into basic floor */
5634 			cave_set_feat(wpos, yy, xx, FEAT_FLOOR);
5635 
5636 			/* Delete monsters */
5637 			if (c_ptr->m_idx > 0) {
5638 				monster_race *r_ptr = race_inf(&m_list[c_ptr->m_idx]);
5639 				if (!(r_ptr->flags9 & RF9_IM_TELE)) delete_monster(wpos, yy, xx, TRUE);
5640 				else continue;
5641 			}
5642 
5643 			/* Delete objects */
5644 			delete_object(wpos, yy, xx, TRUE);
5645 
5646 			everyone_lite_spot(wpos, yy, xx);
5647 		}
5648 	}
5649 }
5650 
5651 
5652 /*
5653  * This routine clears the entire "temp" set.
5654  *
5655  * This routine will Perma-Lite all "temp" grids.
5656  *
5657  * This routine is used (only) by "lite_room()"
5658  *
5659  * Dark grids are illuminated.
5660  *
5661  * Also, process all affected monsters.
5662  *
5663  * SMART monsters always wake up when illuminated
5664  * NORMAL monsters wake up 1/4 the time when illuminated
5665  * STUPID monsters wake up 1/10 the time when illuminated
5666  */
cave_temp_room_lite(int Ind)5667 static void cave_temp_room_lite(int Ind)
5668 {
5669 	player_type *p_ptr = Players[Ind];
5670 	int i;
5671 	struct worldpos *wpos = &p_ptr->wpos;
5672 	cave_type **zcave;
5673 	if (!(zcave = getcave(wpos))) return;
5674 
5675 	/* Clear them all */
5676 	for (i = 0; i < p_ptr->temp_n; i++)
5677 	{
5678 		int y = p_ptr->temp_y[i];
5679 		int x = p_ptr->temp_x[i];
5680 
5681 		cave_type *c_ptr = &zcave[y][x];
5682 
5683 		/* No longer in the array */
5684 		c_ptr->info &= ~CAVE_TEMP;
5685 
5686 		/* Update only non-CAVE_GLOW grids */
5687 		/* if (c_ptr->info & CAVE_GLOW) continue; */
5688 
5689 		/* Perma-Lite */
5690 		c_ptr->info |= CAVE_GLOW;
5691 
5692 		/* Process affected monsters */
5693 		if (c_ptr->m_idx > 0)
5694 		{
5695 			int chance = 25;
5696 
5697 			monster_type	*m_ptr = &m_list[c_ptr->m_idx];
5698 
5699                         monster_race    *r_ptr = race_inf(m_ptr);
5700 
5701 			/* Update the monster */
5702 			update_mon(c_ptr->m_idx, FALSE);
5703 
5704 			/* Stupid monsters rarely wake up */
5705 			if (r_ptr->flags2 & RF2_STUPID) chance = 10;
5706 
5707 			/* Smart monsters always wake up */
5708 			if (r_ptr->flags2 & RF2_SMART) chance = 100;
5709 
5710 			/* Sometimes monsters wake up */
5711 			if (m_ptr->csleep && (rand_int(100) < chance))
5712 			{
5713 				/* Wake up! */
5714 				m_ptr->csleep = 0;
5715 
5716 				/* Notice the "waking up" */
5717 				if (p_ptr->mon_vis[c_ptr->m_idx])
5718 				{
5719 					char m_name[MNAME_LEN];
5720 
5721 					/* Acquire the monster name */
5722 					monster_desc(Ind, m_name, c_ptr->m_idx, 0);
5723 
5724 					/* Dump a message */
5725 					msg_format(Ind, "%^s wakes up.", m_name);
5726 				}
5727 			}
5728 		}
5729 
5730 		/* Note */
5731 		note_spot_depth(wpos, y, x);
5732 
5733 		/* Redraw */
5734 		everyone_lite_spot(wpos, y, x);
5735 	}
5736 
5737 	/* None left */
5738 	p_ptr->temp_n = 0;
5739 }
5740 
5741 
5742 
5743 /*
5744  * This routine clears the entire "temp" set.
5745  *
5746  * This routine will "darken" all "temp" grids.
5747  *
5748  * In addition, some of these grids will be "unmarked".
5749  *
5750  * This routine is used (only) by "unlite_room()"
5751  *
5752  * Also, process all affected monsters
5753  */
cave_temp_room_unlite(int Ind)5754 static void cave_temp_room_unlite(int Ind)
5755 {
5756 	player_type *p_ptr = Players[Ind];
5757 	int i;
5758 	struct worldpos *wpos = &p_ptr->wpos;
5759 	cave_type **zcave;
5760 	if (!(zcave = getcave(wpos))) return;
5761 
5762 	/* Clear them all */
5763 	for (i = 0; i < p_ptr->temp_n; i++)
5764 	{
5765 		int y = p_ptr->temp_y[i];
5766 		int x = p_ptr->temp_x[i];
5767 
5768 		cave_type *c_ptr = &zcave[y][x];
5769 
5770 		/* No longer in the array */
5771 		c_ptr->info &= ~CAVE_TEMP;
5772 
5773 		/* Darken the grid */
5774 		c_ptr->info &= ~CAVE_GLOW;
5775 
5776 		/* Hack -- Forget "boring" grids */
5777 //		if (c_ptr->feat <= FEAT_INVIS)
5778 		if (cave_plain_floor_grid(c_ptr))
5779 		{
5780 			/* Forget the grid */
5781 			p_ptr->cave_flag[y][x] &= ~CAVE_MARK;
5782 
5783 			/* Notice */
5784 			note_spot_depth(wpos, y, x);
5785 		}
5786 
5787 		/* Process affected monsters */
5788 		if (c_ptr->m_idx > 0)
5789 		{
5790 			/* Update the monster */
5791 			update_mon(c_ptr->m_idx, FALSE);
5792 		}
5793 
5794 		/* Redraw */
5795 		everyone_lite_spot(wpos, y, x);
5796 	}
5797 
5798 	/* None left */
5799 	p_ptr->temp_n = 0;
5800 }
5801 
5802 
5803 
5804 
5805 /*
5806  * Aux function -- see below
5807  */
cave_temp_room_aux(int Ind,struct worldpos * wpos,int y,int x)5808 static void cave_temp_room_aux(int Ind, struct worldpos *wpos, int y, int x)
5809 {
5810 	player_type *p_ptr = Players[Ind];
5811 
5812 	cave_type *c_ptr;
5813 	cave_type **zcave;
5814 	if (!(zcave = getcave(wpos))) return;
5815 	c_ptr = &zcave[y][x];
5816 
5817 	/* Avoid infinite recursion */
5818 	if (c_ptr->info & CAVE_TEMP) return;
5819 
5820 	/* Do not "leave" the current room */
5821 	if (!(c_ptr->info & CAVE_ROOM)) return;
5822 
5823 	/* Paranoia -- verify space */
5824 	if (p_ptr->temp_n == TEMP_MAX) return;
5825 
5826 	/* Mark the grid as "seen" */
5827 	c_ptr->info |= CAVE_TEMP;
5828 
5829 	/* Add it to the "seen" set */
5830 	p_ptr->temp_y[p_ptr->temp_n] = y;
5831 	p_ptr->temp_x[p_ptr->temp_n] = x;
5832 	p_ptr->temp_n++;
5833 }
5834 
5835 
5836 
5837 
5838 /*
5839  * Illuminate any room containing the given location.
5840  */
lite_room(int Ind,struct worldpos * wpos,int y1,int x1)5841 void lite_room(int Ind, struct worldpos *wpos, int y1, int x1)
5842 {
5843 	player_type *p_ptr = Players[Ind];
5844 
5845 	int i, x, y;
5846 
5847 	cave_type **zcave;
5848 	if (!(zcave = getcave(wpos))) return;
5849 
5850 	/* Add the initial grid */
5851 	cave_temp_room_aux(Ind, wpos, y1, x1);
5852 
5853 	/* While grids are in the queue, add their neighbors */
5854 	for (i = 0; i < p_ptr->temp_n; i++)
5855 	{
5856 		x = p_ptr->temp_x[i], y = p_ptr->temp_y[i];
5857 
5858 		/* Walls get lit, but stop light */
5859 		if (!cave_floor_bold(zcave, y, x)) continue;
5860 
5861 		/* Spread adjacent */
5862 		cave_temp_room_aux(Ind, wpos, y + 1, x);
5863 		cave_temp_room_aux(Ind, wpos, y - 1, x);
5864 		cave_temp_room_aux(Ind, wpos, y, x + 1);
5865 		cave_temp_room_aux(Ind, wpos, y, x - 1);
5866 
5867 		/* Spread diagonal */
5868 		cave_temp_room_aux(Ind, wpos, y + 1, x + 1);
5869 		cave_temp_room_aux(Ind, wpos, y - 1, x - 1);
5870 		cave_temp_room_aux(Ind, wpos, y - 1, x + 1);
5871 		cave_temp_room_aux(Ind, wpos, y + 1, x - 1);
5872 	}
5873 
5874 	/* Now, lite them all up at once */
5875 	cave_temp_room_lite(Ind);
5876 }
5877 
5878 
5879 /*
5880  * Darken all rooms containing the given location
5881  */
unlite_room(int Ind,struct worldpos * wpos,int y1,int x1)5882 void unlite_room(int Ind, struct worldpos *wpos, int y1, int x1)
5883 {
5884 	player_type *p_ptr = Players[Ind];
5885 
5886 	int i, x, y;
5887 
5888 	cave_type **zcave;
5889 	if (!(zcave = getcave(wpos))) return;
5890 
5891 	/* Add the initial grid */
5892 	cave_temp_room_aux(Ind, wpos, y1, x1);
5893 
5894 	/* Spread, breadth first */
5895 	for (i = 0; i < p_ptr->temp_n; i++)
5896 	{
5897 		x = p_ptr->temp_x[i], y = p_ptr->temp_y[i];
5898 
5899 		/* Walls get dark, but stop darkness */
5900 		if (!cave_floor_bold(zcave, y, x)) continue;
5901 
5902 		/* Spread adjacent */
5903 		cave_temp_room_aux(Ind, wpos, y + 1, x);
5904 		cave_temp_room_aux(Ind, wpos, y - 1, x);
5905 		cave_temp_room_aux(Ind, wpos, y, x + 1);
5906 		cave_temp_room_aux(Ind, wpos, y, x - 1);
5907 
5908 		/* Spread diagonal */
5909 		cave_temp_room_aux(Ind, wpos, y + 1, x + 1);
5910 		cave_temp_room_aux(Ind, wpos, y - 1, x - 1);
5911 		cave_temp_room_aux(Ind, wpos, y - 1, x + 1);
5912 		cave_temp_room_aux(Ind, wpos, y + 1, x - 1);
5913 	}
5914 
5915 	/* Now, darken them all at once */
5916 	cave_temp_room_unlite(Ind);
5917 }
5918 
5919 
5920 
5921 /*
5922  * Hack -- call light around the player
5923  * Affect all monsters in the projection radius
5924  */
lite_area(int Ind,int dam,int rad)5925 bool lite_area(int Ind, int dam, int rad) {
5926 	player_type *p_ptr = Players[Ind];
5927 
5928 	int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_KILL | PROJECT_NODO | PROJECT_NODF;
5929 
5930 	/* WRAITHFORM reduces damage/effect! */
5931 	if (p_ptr->tim_wraith) proj_dam_wraith(GF_LITE_WEAK, &dam);
5932 
5933 	/* Hack -- Message */
5934 	if (!p_ptr->blind)
5935 		msg_print(Ind, "You are surrounded by a white light.");
5936 
5937 	/* Hook into the "project()" function */
5938 	(void)project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, dam, GF_LITE_WEAK, flg, "");
5939 
5940 	/* Lite up the room */
5941 	lite_room(Ind, &p_ptr->wpos, p_ptr->py, p_ptr->px);
5942 
5943 	/* Assume seen */
5944 	return (TRUE);
5945 }
5946 
5947 
5948 /*
5949  * Hack -- call darkness around the player
5950  * Affect all monsters in the projection radius
5951  */
unlite_area(int Ind,int dam,int rad)5952 bool unlite_area(int Ind, int dam, int rad)
5953 {
5954 	player_type *p_ptr = Players[Ind];
5955 
5956 	int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_KILL | PROJECT_NODO | PROJECT_NODF;
5957 
5958 	/* WRAITHFORM reduces damage/effect! */
5959 	if (p_ptr->tim_wraith) proj_dam_wraith(GF_DARK_WEAK, &dam);
5960 
5961 	/* Hack -- Message */
5962 	if (!p_ptr->blind)
5963 	{
5964 		msg_print(Ind, "Darkness surrounds you.");
5965 	}
5966 
5967 	/* Hook into the "project()" function */
5968 	(void)project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, dam, GF_DARK_WEAK, flg, "");
5969 
5970 	/* Lite up the room */
5971 	unlite_room(Ind, &p_ptr->wpos, p_ptr->py, p_ptr->px);
5972 
5973 	/* Assume seen */
5974 	return (TRUE);
5975 }
5976 
5977 
5978 
5979 /*
5980  * Cast a ball spell
5981  * Stop if we hit a monster, act as a "ball"
5982  * Allow "target" mode to pass over monsters
5983  * Affect grids, objects, and monsters
5984  */
fire_ball(int Ind,int typ,int dir,int dam,int rad,char * attacker)5985 bool fire_ball(int Ind, int typ, int dir, int dam, int rad, char *attacker)
5986 {
5987 	player_type *p_ptr = Players[Ind];
5988 	char pattacker[80];
5989 	int tx, ty;
5990 
5991 	int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_NODO;
5992 
5993 	/* WRAITHFORM reduces damage/effect */
5994 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
5995 
5996 	/* Use the given direction */
5997 	tx = p_ptr->px + 99 * ddx[dir];
5998 	ty = p_ptr->py + 99 * ddy[dir];
5999 
6000 	/* Hack -- Use an actual "target" */
6001 	if ((dir == 5) && target_okay(Ind)) {
6002 		flg &= ~PROJECT_STOP;
6003 		tx = p_ptr->target_col;
6004 		ty = p_ptr->target_row;
6005 	}
6006 #if 1
6007 #ifdef USE_SOUND_2010
6008 	if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6009 	else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6010 	else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6011 	else {
6012 		/* The 'cast_ball' sound is only for attack spells */
6013 		if ((typ != GF_HEAL_PLAYER) && (typ != GF_AWAY_ALL) &&
6014 		    (typ != GF_WRAITH_PLAYER) && (typ != GF_SPEED_PLAYER) &&
6015 		    (typ != GF_SHIELD_PLAYER) && (typ != GF_RECALL_PLAYER) &&
6016 		    (typ != GF_BLESS_PLAYER) && (typ != GF_REMFEAR_PLAYER) &&
6017 		    (typ != GF_REMCONF_PLAYER) && (typ != GF_REMIMAGE_PLAYER) &&
6018 		    (typ != GF_SATHUNGER_PLAYER) && (typ != GF_RESFIRE_PLAYER) &&
6019 		    (typ != GF_RESCOLD_PLAYER) && (typ != GF_CUREPOISON_PLAYER) &&
6020 		    (typ != GF_SEEINVIS_PLAYER) && (typ != GF_SEEMAP_PLAYER) &&
6021 		    (typ != GF_CURECUT_PLAYER) && (typ != GF_CURESTUN_PLAYER) &&
6022 		    (typ != GF_DETECTCREATURE_PLAYER) && (typ != GF_DETECTDOOR_PLAYER) &&
6023 		    (typ != GF_DETECTTRAP_PLAYER) && (typ != GF_TELEPORTLVL_PLAYER) &&
6024 		    (typ != GF_RESPOIS_PLAYER) && (typ != GF_RESELEC_PLAYER) &&
6025 		    (typ != GF_RESACID_PLAYER) && (typ != GF_HPINCREASE_PLAYER) &&
6026 		    (typ != GF_HERO_PLAYER) && (typ != GF_SHERO_PLAYER) &&
6027 		    (typ != GF_TELEPORT_PLAYER) && (typ != GF_ZEAL_PLAYER) &&
6028 		    (typ != GF_RESTORE_PLAYER) && (typ != GF_REMCURSE_PLAYER) &&
6029 		    (typ != GF_CURE_PLAYER) && (typ != GF_RESURRECT_PLAYER) &&
6030 		    (typ != GF_SANITY_PLAYER) && (typ != GF_SOULCURE_PLAYER) &&
6031 		    (typ != GF_OLD_HEAL) && (typ != GF_OLD_SPEED) && (typ != GF_PUSH) &&
6032 		    (typ != GF_HEALINGCLOUD) && /* Also not a hostile spell */
6033 		    (typ != GF_MINDBOOST_PLAYER) && (typ != GF_IDENTIFY) &&
6034 		    (typ != GF_SLOWPOISON_PLAYER) && (typ != GF_CURING) &&
6035 		    (typ != GF_OLD_POLY)) /* Non-hostile players may polymorph each other */
6036 			if (p_ptr->sfx_magicattack) sound(Ind, "cast_ball", NULL, SFX_TYPE_COMMAND, TRUE);
6037 	}
6038 #endif
6039 #endif
6040 	/* Analyze the "dir" and the "target".  Hurt items on floor. */
6041 	snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6042 
6043 	/* affect self + players + monsters AND give credit on kill */
6044 	flg = mod_ball_spell_flags(typ, flg);
6045 	return (project(0 - Ind, rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6046 }
6047 
6048 /*
6049  * Cast a full ball spell
6050  * Stop if we hit a monster, act as a "ball"
6051  * Allow "target" mode to pass over monsters
6052  * Affect grids, objects, and monsters
6053  */
fire_full_ball(int Ind,int typ,int dir,int dam,int rad,char * attacker)6054 bool fire_full_ball(int Ind, int typ, int dir, int dam, int rad, char *attacker) {
6055 	player_type *p_ptr = Players[Ind];
6056 	char pattacker[80];
6057 	int tx, ty;
6058 
6059 	int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_FULL | PROJECT_NODO;
6060 
6061 
6062 	/* WRAITHFORM reduces damage/effect! */
6063 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6064 
6065 	/* Use the given direction */
6066 	tx = p_ptr->px + 99 * ddx[dir];
6067 	ty = p_ptr->py + 99 * ddy[dir];
6068 
6069 	/* Hack -- Use an actual "target" */
6070 	if ((dir == 5) && target_okay(Ind)) {
6071 		flg &= ~(PROJECT_STOP);
6072 		tx = p_ptr->target_col;
6073 		ty = p_ptr->target_row;
6074 	}
6075 #if 1
6076 #ifdef USE_SOUND_2010
6077 	if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6078 	else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6079 	else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6080 	else {
6081 		/* The 'cast_ball' sound is only for attack spells */
6082 		if ((typ != GF_HEAL_PLAYER) && (typ != GF_AWAY_ALL) &&
6083 		    (typ != GF_WRAITH_PLAYER) && (typ != GF_SPEED_PLAYER) &&
6084 		    (typ != GF_SHIELD_PLAYER) && (typ != GF_RECALL_PLAYER) &&
6085 		    (typ != GF_BLESS_PLAYER) && (typ != GF_REMFEAR_PLAYER) &&
6086 		    (typ != GF_REMCONF_PLAYER) && (typ != GF_REMIMAGE_PLAYER) &&
6087 		    (typ != GF_SATHUNGER_PLAYER) && (typ != GF_RESFIRE_PLAYER) &&
6088 		    (typ != GF_RESCOLD_PLAYER) && (typ != GF_CUREPOISON_PLAYER) &&
6089 		    (typ != GF_SEEINVIS_PLAYER) && (typ != GF_SEEMAP_PLAYER) &&
6090 		    (typ != GF_CURECUT_PLAYER) && (typ != GF_CURESTUN_PLAYER) &&
6091 		    (typ != GF_DETECTCREATURE_PLAYER) && (typ != GF_DETECTDOOR_PLAYER) &&
6092 		    (typ != GF_DETECTTRAP_PLAYER) && (typ != GF_TELEPORTLVL_PLAYER) &&
6093 		    (typ != GF_RESPOIS_PLAYER) && (typ != GF_RESELEC_PLAYER) &&
6094 		    (typ != GF_RESACID_PLAYER) && (typ != GF_HPINCREASE_PLAYER) &&
6095 		    (typ != GF_HERO_PLAYER) && (typ != GF_SHERO_PLAYER) &&
6096 		    (typ != GF_TELEPORT_PLAYER) && (typ != GF_ZEAL_PLAYER) &&
6097 		    (typ != GF_RESTORE_PLAYER) && (typ != GF_REMCURSE_PLAYER) &&
6098 		    (typ != GF_CURE_PLAYER) && (typ != GF_RESURRECT_PLAYER) &&
6099 		    (typ != GF_SANITY_PLAYER) && (typ != GF_SOULCURE_PLAYER) &&
6100 		    (typ != GF_OLD_HEAL) && (typ != GF_OLD_SPEED) && (typ != GF_PUSH) &&
6101 		    (typ != GF_HEALINGCLOUD) && /* Also not a hostile spell */
6102 		    (typ != GF_MINDBOOST_PLAYER) && (typ != GF_IDENTIFY) &&
6103 		    (typ != GF_SLOWPOISON_PLAYER) && (typ != GF_CURING) &&
6104 		    (typ != GF_OLD_POLY)) /* Non-hostile players may polymorph each other */
6105 			if (p_ptr->sfx_magicattack) sound(Ind, "cast_ball", NULL, SFX_TYPE_COMMAND, TRUE);
6106 	}
6107 #endif
6108 #endif
6109        /* Analyze the "dir" and the "target".  Hurt items on floor. */
6110        snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6111 
6112        /* affect self + players + monsters AND give credit on kill */
6113        flg = mod_ball_spell_flags(typ, flg);
6114        return (project(0 - Ind, rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6115 }
6116 
6117 /*
6118  * Cast a cloud spell
6119  * Stop if we hit a monster, act as a "ball"
6120  * Allow "target" mode to pass over monsters
6121  * Affect grids, objects, and monsters
6122  */
fire_cloud(int Ind,int typ,int dir,int dam,int rad,int time,int interval,char * attacker)6123 bool fire_cloud(int Ind, int typ, int dir, int dam, int rad, int time, int interval, char *attacker) {
6124 	player_type *p_ptr = Players[Ind];
6125 	int tx, ty;
6126 
6127 	int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY | PROJECT_NODF | PROJECT_NODO;
6128 
6129 	char pattacker[80];
6130 
6131 	/* WRAITHFORM reduces damage/effect! */
6132 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6133 
6134 	/* Use the given direction */
6135 	tx = p_ptr->px + 99 * ddx[dir];
6136 	ty = p_ptr->py + 99 * ddy[dir];
6137 
6138 	/* Hack -- Use an actual "target" */
6139 	if ((dir == 5) && target_okay(Ind))
6140 	{
6141 		flg &= ~(PROJECT_STOP);
6142 		tx = p_ptr->target_col;
6143 		ty = p_ptr->target_row;
6144 	}
6145 	project_interval = interval;
6146 	project_time = time;
6147 
6148 	if (snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker) < 0) return (FALSE);
6149 
6150 	/* Analyze the "dir" and the "target".  Hurt items on floor. */
6151 
6152 #ifdef USE_SOUND_2010
6153 	/* paranoia, aka this won't exist as "clouds".. */
6154 	if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6155 	else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6156 	else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6157 	/* only this one needed really */
6158 	else if (p_ptr->sfx_magicattack) sound(Ind, "cast_cloud", NULL, SFX_TYPE_COMMAND, FALSE);
6159 #endif
6160 
6161 	flg = mod_ball_spell_flags(typ, flg);
6162 	return (project(0 - Ind, (rad > 16) ? 16 : rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6163 }
6164 
6165 /*
6166  * Cast a wave spell
6167  * Stop if we hit a monster, act as a "ball"
6168  * Allow "target" mode to pass over monsters
6169  * Affect grids, objects, and monsters
6170  */
fire_wave(int Ind,int typ,int dir,int dam,int rad,int time,int interval,s32b eff,char * attacker)6171 bool fire_wave(int Ind, int typ, int dir, int dam, int rad, int time, int interval, s32b eff, char *attacker)
6172 {
6173 	char pattacker[80];
6174 
6175 	project_time_effect = eff;
6176         snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6177 	return (fire_cloud(Ind, typ, dir, dam, rad, time, interval, pattacker));
6178 }
6179 
6180 /*
6181  * Singing in the rain :-o
6182  */
cast_raindrop(worldpos * wpos,int x)6183 bool cast_raindrop(worldpos *wpos, int x) {
6184 	char pattacker[80];
6185         strcpy(pattacker, "");
6186         int pseudo_y_start;
6187 
6188 	int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6189 
6190 	project_time_effect = EFF_RAINING;
6191 	project_interval = 3;
6192 	/* let more drops appear at top line, simulating that they were
6193 	   created 'above' the screen, so we don't get quite empty top lines */
6194 	pseudo_y_start = rand_int(66 - 1 + 20) - 20;
6195 	project_time = pseudo_y_start < 0 ? 20 + pseudo_y_start : 20;
6196 	if (pseudo_y_start < 0) pseudo_y_start = 0;
6197 	return (project(PROJECTOR_EFFECT, 0, wpos, pseudo_y_start, x, 0, GF_RAINDROP, flg, pattacker));
6198 
6199 //	project_time = 20;//1 + randint(66 - 3);
6200 //	return (project(PROJECTOR_EFFECT, 0, wpos, 1 + randint(66 - 3), x, 0, GF_RAINDROP, flg, pattacker));
6201 }
6202 
6203 /*
6204  * Let it snow, let it snow, let it snow... (WINTER_SEASON)
6205  * 'interval' is movement speed
6206  */
cast_snowflake(worldpos * wpos,int x,int interval)6207 bool cast_snowflake(worldpos *wpos, int x, int interval) {
6208 	char pattacker[80];
6209         strcpy(pattacker, "");
6210 
6211 	int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6212 
6213 	project_time_effect = EFF_SNOWING;
6214 	project_interval = interval;
6215 	project_time = 100; /* just any value long enough to traverse the screen */
6216 
6217 	return (project(PROJECTOR_EFFECT, 0, wpos, 0, x, 0, GF_SNOWFLAKE, flg, pattacker));
6218 }
6219 
6220 /*
6221  * Fireworks! (NEW_YEARS_EVE)
6222  */
cast_fireworks(worldpos * wpos,int x,int y)6223 bool cast_fireworks(worldpos *wpos, int x, int y) {
6224 	char pattacker[80];
6225         strcpy(pattacker, "");
6226 
6227 	int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6228 
6229 	int typ = rand_int(7 * 3); /* colour & style */
6230 
6231 	if (typ < 7) project_time_effect = EFF_FIREWORKS1;
6232 	else if (typ < 7 * 2) {
6233 		project_time_effect = EFF_FIREWORKS2;
6234 		typ -= 7;
6235 	} else {
6236 		project_time_effect = EFF_FIREWORKS3;
6237 		typ -= 7 * 2;
6238 	}
6239 
6240 	switch(typ) {
6241 	case 0: typ = GF_FW_FIRE; break;
6242 	case 1: typ = GF_FW_ELEC; break;
6243 	case 2: typ = GF_FW_POIS; break;
6244 	case 3: typ = GF_FW_LITE; break;
6245 	case 4: typ = GF_FW_SHDI; break;
6246 	case 5: typ = GF_FW_SHDM; break;
6247 	case 6: typ = GF_FW_MULT; break;
6248 	}
6249 
6250 #if 0
6251 	project_interval = 4;
6252 	project_time = 5 + 5; /* X units to rise into the air, X units to explode */
6253 #else
6254 	/* Adjustments - mikaelh */
6255 	project_interval = 5;
6256 	project_time = 8 + 8; /* X units to rise into the air, X units to explode */
6257 	//if (project_time_effect == EFF_FIREWORKS3) project_time += 2 + 2;
6258 #endif
6259 
6260 	return (project(PROJECTOR_EFFECT, 0, wpos, y, x, 0, typ, flg, pattacker)); /* typ -> colour */
6261 }
6262 
cast_lightning(worldpos * wpos,int x,int y)6263 bool cast_lightning(worldpos *wpos, int x, int y) {
6264 	char pattacker[80];
6265 	int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6266 	int typ = rand_int(3 * 2); /* style / mirrored direction? */
6267 
6268         strcpy(pattacker, "");
6269 
6270 	if (typ < 2) {
6271 		project_time_effect = EFF_LIGHTNING1;
6272 		project_time = 14;
6273 	} else if (typ < 2 * 2) {
6274 		project_time_effect = EFF_LIGHTNING2;
6275 		project_time = 8;
6276 		typ -= 2;
6277 	} else {
6278 		project_time_effect = EFF_LIGHTNING3;
6279 		project_time = 10;
6280 		typ -= 2 * 2;
6281 	}
6282 
6283 	project_interval = 1;
6284 	project_time += 10; /* afterglow */
6285 
6286 #ifdef USE_SOUND_2010
6287 	sound_floor_vol(wpos, "thunder", NULL, SFX_TYPE_AMBIENT, 100);
6288 #endif
6289 
6290 	return (project(PROJECTOR_EFFECT, 0, wpos, y, x, typ, GF_SHOW_LIGHTNING, flg, pattacker));
6291 }
6292 
6293 
6294 /*
6295  * Player swaps position with whatever in (lty, ltx)
6296  * usually used for 'Void Jumpgate'		- Jir -
6297  */
6298 /*
6299  * Fixed monster swapping bug which caused many
6300  * unfair deaths and weirdness.
6301  * (evileye)
6302  */
swap_position(int Ind,int lty,int ltx)6303 bool swap_position(int Ind, int lty, int ltx){
6304 	player_type *p_ptr;
6305 	worldpos *wpos;
6306 	int tx, ty;
6307 	cave_type *c_ptr;
6308 	cave_type **zcave;
6309 #ifdef ENABLE_SELF_FLASHING
6310 	bool panel;
6311 #endif
6312 
6313 	p_ptr = Players[Ind];
6314 	if (!p_ptr) return FALSE;
6315 
6316 	wpos = &p_ptr->wpos;
6317 	if (!(zcave = getcave(wpos))) return FALSE;
6318 
6319 	store_exit(Ind);
6320 
6321 	c_ptr = &zcave[lty][ltx];
6322 
6323 	/* Keep track of the old location */
6324 	tx = p_ptr->px;
6325 	ty = p_ptr->py;
6326 
6327 	/* Move the player */
6328 	p_ptr->px = ltx;
6329 	p_ptr->py = lty;
6330 
6331 	if (!c_ptr->m_idx) {
6332 		/* Free space */
6333 		/* Update the old location */
6334 		zcave[ty][tx].m_idx = 0;
6335 		c_ptr->m_idx = 0 - Ind;
6336 		cave_midx_debug(wpos, lty, ltx, -Ind);
6337 
6338 		/* Redraw/remember old location */
6339 		note_spot_depth(wpos, ty, tx);
6340 		everyone_lite_spot(wpos, ty, tx);
6341 
6342 		/* Redraw new grid */
6343 		everyone_lite_spot(wpos, lty, ltx);
6344 	} else if (c_ptr->m_idx > 0) {
6345 		/* Monster */
6346 		monster_type *m_ptr = &m_list[c_ptr->m_idx];
6347 		zcave[ty][tx].m_idx = c_ptr->m_idx;
6348 
6349 		/* Move the monster */
6350 		m_ptr->fy = ty;
6351 		m_ptr->fx = tx;
6352 
6353 		/* Update the new location */
6354 		c_ptr->m_idx = 0 - Ind;
6355 		cave_midx_debug(wpos, lty, ltx, -Ind);
6356 
6357 		/* Update monster (new location) */
6358 		update_mon(zcave[ty][tx].m_idx, TRUE);
6359 
6360 		/* Redraw/remember old location */
6361 		note_spot_depth(wpos, ty, tx);
6362 		everyone_lite_spot(wpos, ty, tx);
6363 
6364 		/* Redraw new grid */
6365 		everyone_lite_spot(wpos, lty, ltx);
6366 	} else {//if (c_ptr->m_idx < 0) {
6367 		/* Other player */
6368 		int Ind2 = 0 - c_ptr->m_idx;
6369 		player_type *q_ptr = NULL;
6370 		if (Ind2) q_ptr = Players[Ind2];
6371 
6372 		/* Shift them if they are real */
6373 		if (q_ptr) {
6374 			store_exit(Ind2);
6375 
6376 			q_ptr->py = ty;
6377 			q_ptr->px = tx;
6378 			#ifdef ARCADE_SERVER
6379 			if (p_ptr->game == 3) {
6380 			p_ptr->arc_c = q_ptr->arc_c = 1;
6381 			p_ptr->arc_d = Ind2; }
6382 			#endif
6383 		}
6384 
6385 		p_ptr->px = ltx;
6386 		p_ptr->py = lty;
6387 
6388 		/* Update old player location */
6389 		c_ptr->m_idx = 0 - Ind;
6390 		cave_midx_debug(wpos, lty, ltx, -Ind);
6391 		zcave[ty][tx].m_idx = 0 - Ind2;
6392 		cave_midx_debug(wpos, ty, tx, -Ind2);
6393 
6394 		/* Redraw/remember old location */
6395 		note_spot_depth(wpos, ty, tx);
6396 		everyone_lite_spot(wpos, ty, tx);
6397 
6398 		/* Redraw new grid */
6399 		everyone_lite_spot(wpos, lty, ltx);
6400 
6401 		if (Ind2) verify_panel(Ind2);
6402 		if (q_ptr) {
6403 			/* Update stuff */
6404 			q_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_DISTANCE);
6405 
6406 			/* Update Window */
6407 			q_ptr->window |= (PW_OVERHEAD);
6408 
6409 			/* Handle stuff */
6410 			if (!q_ptr->death) handle_stuff(Ind);
6411 		}
6412 	}
6413 
6414 	/* Check for new panel (redraw map) */
6415 #ifdef ENABLE_SELF_FLASHING
6416 	panel = !local_panel(Ind);
6417 #endif
6418 	verify_panel(Ind);
6419 
6420 	/* Update stuff */
6421 	p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_DISTANCE);
6422 
6423 	/* Update Window */
6424 	p_ptr->window |= (PW_OVERHEAD);
6425 
6426 	/* Handle stuff */
6427 	if (!p_ptr->death) handle_stuff(Ind);
6428 
6429 	return panel;
6430 }
6431 
6432 
6433 /*
6434  * Hack -- apply a "projection()" in a direction (or at the target)
6435  */
project_hook(int Ind,int typ,int dir,int dam,int flg,char * attacker)6436 bool project_hook(int Ind, int typ, int dir, int dam, int flg, char *attacker)
6437 {
6438 	player_type *p_ptr = Players[Ind];
6439 	int tx, ty;
6440 
6441 	/* WRAITHFORM reduces damage/effect! */
6442 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6443 
6444 	/* Pass through the target if needed */
6445 	flg |= (PROJECT_THRU);
6446 
6447 	/* Use the given direction */
6448 	tx = p_ptr->px + ddx[dir];
6449 	ty = p_ptr->py + ddy[dir];
6450 
6451 	/* Hack -- Use an actual "target" */
6452 	if ((dir == 5) && target_okay(Ind)) {
6453 //		cave_type **zcave = getcave(&p_ptr->wpos);
6454 
6455 		tx = p_ptr->target_col;
6456 		ty = p_ptr->target_row;
6457 
6458 #if 0 /* oops, nonsense >_< this only concerns PROJECT_GRID/PROJECT_ITEM flags of course.. */
6459 		/* Allow targetting the item/floor of a specific grid with a bolt spell
6460 		   ..if no monster on it! Assume that the floor won't get hit if the monster
6461 		     instead gets hit, basically. Makes sense for bolt spells and prevents
6462 		     too much loot destruction. */
6463 		if (!(flg & PROJECT_BEAM) &&
6464 		    zcave && /* paranoia */
6465 		    zcave[ty][tx].m_idx == 0)
6466 			flg &= ~PROJECT_THRU;
6467 #else
6468 		if (!(flg & PROJECT_BEAM)) flg &= ~PROJECT_THRU;
6469 #endif
6470 	}
6471 
6472 	/* Analyze the "dir" and the "target", do NOT explode */
6473 	return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6474 }
6475 
6476 
6477 /*
6478  * Cast a bolt spell
6479  * Stop if we hit a monster, as a "bolt"
6480  * Affect monsters (not grids or objects)
6481  */
fire_bolt(int Ind,int typ,int dir,int dam,char * attacker)6482 bool fire_bolt(int Ind, int typ, int dir, int dam, char *attacker)
6483 {
6484 	char pattacker[80];
6485 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID | PROJECT_EVSG;
6486 	snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6487 
6488 #ifdef USE_SOUND_2010
6489 	if (Players[Ind]->sfx_magicattack) sound(Ind, "cast_bolt", NULL, SFX_TYPE_COMMAND, FALSE);
6490 #endif
6491 
6492 	return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6493 }
6494 
6495 /*
6496  * Cast a beam spell
6497  * Pass through monsters, as a "beam"
6498  * Affect monsters (not grids or objects)
6499  */
fire_beam(int Ind,int typ,int dir,int dam,char * attacker)6500 bool fire_beam(int Ind, int typ, int dir, int dam, char *attacker)
6501 {
6502         char pattacker[80];
6503 		//int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID;
6504 		//Actually, since beams affect the whole tile, don't deflect or reflect them (we don't have proper code for changing beam path anyway) - Kurzel
6505         int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6506 		snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6507 
6508 #ifdef USE_SOUND_2010
6509 	if (Players[Ind]->sfx_magicattack) sound(Ind, "cast_beam", NULL, SFX_TYPE_COMMAND, FALSE);
6510 #endif
6511 
6512 	return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6513 }
6514 
6515 /*
6516  * Cast a cloud spell
6517  * Stop if we hit a monster, act as a "ball"
6518  * Allow "target" mode to pass over monsters
6519  * Affect grids, objects, and monsters
6520  */
fire_wall(int Ind,int typ,int dir,int dam,int time,int interval,char * attacker)6521 bool fire_wall(int Ind, int typ, int dir, int dam, int time, int interval, char *attacker)
6522 {
6523 	player_type *p_ptr = Players[Ind];
6524 	int tx, ty;
6525 
6526 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY | PROJECT_THRU | PROJECT_NODF | PROJECT_NODO;
6527 
6528 	/* WRAITHFORM reduces damage/effect! */
6529 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6530 
6531 	/* Use the given direction */
6532 	tx = p_ptr->px + ddx[dir];
6533 	ty = p_ptr->py + ddy[dir];
6534 
6535 	/* Hack -- Use an actual "target" */
6536 	if ((dir == 5) && target_okay(Ind)) {
6537 		tx = p_ptr->target_col;
6538 		ty = p_ptr->target_row;
6539 	}
6540 	project_time_effect = EFF_WALL;
6541 	project_interval = interval;
6542 	project_time = time;
6543 
6544 #ifdef USE_SOUND_2010
6545 	sound(Ind, "cast_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6546 #endif
6547 
6548 	/* Analyze the "dir" and the "target", do NOT explode */
6549 	return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6550 }
6551 
6552 /*
6553  * Cast a bolt spell, or rarely, a beam spell
6554  */
fire_bolt_or_beam(int Ind,int prob,int typ,int dir,int dam,char * attacker)6555 bool fire_bolt_or_beam(int Ind, int prob, int typ, int dir, int dam, char *attacker)
6556 {
6557 	if (rand_int(100) < prob)
6558 		return (fire_beam(Ind, typ, dir, dam, attacker));
6559 	else
6560 		return (fire_bolt(Ind, typ, dir, dam, attacker));
6561 }
6562 
6563 /* Target bolt-like, but able to pass 'over' untargetted enemies to hit target grid,
6564    ie it manifests directly at the target location (like a ball of radius 0).
6565    Added for new mindcrafter spells; sort of a fake PROJECT_JUMP. - C. Blue */
fire_grid_bolt(int Ind,int typ,int dir,int dam,char * attacker)6566 bool fire_grid_bolt(int Ind, int typ, int dir, int dam, char *attacker) {
6567 	player_type *p_ptr = Players[Ind];
6568 	char pattacker[80];
6569 	int tx, ty;
6570 
6571 	int flg = PROJECT_NORF | PROJECT_HIDE | PROJECT_STOP | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID | PROJECT_EVSG | PROJECT_NODF | PROJECT_NODO;
6572 
6573 	/* WRAITHFORM reduces damage/effect! */
6574 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6575 
6576 	/* Use the given direction */
6577 	tx = p_ptr->px + 99 * ddx[dir];
6578 	ty = p_ptr->py + 99 * ddy[dir];
6579 
6580 	/* Hack -- Use an actual "target" */
6581 	if ((dir == 5) && target_okay(Ind)) {
6582 		flg &= ~PROJECT_STOP;
6583 		tx = p_ptr->target_col;
6584 		ty = p_ptr->target_row;
6585 	}
6586 
6587 #ifdef USE_SOUND_2010
6588 	if (p_ptr->sfx_magicattack) sound(Ind, "cast_bolt", NULL, SFX_TYPE_COMMAND, FALSE);
6589 #endif
6590 
6591 	/* Analyze the "dir" and the "target".  Hurt items on floor. */
6592 	snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6593 
6594 	if (typ == GF_HEAL_PLAYER) flg |= PROJECT_PLAY; //mod_ball_spell_flags(typ, flg);
6595 	return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6596 }
6597 
6598 /* Added for new mindcrafter spells.
6599    The '_grid_' part here means that the beam also hits the floor grids,
6600    ie feat/terrain/item! Added for mindcrafter disarming. - C. Blue */
fire_grid_beam(int Ind,int typ,int dir,int dam,char * attacker)6601 bool fire_grid_beam(int Ind, int typ, int dir, int dam, char *attacker) {
6602 	player_type *p_ptr = Players[Ind];
6603 	char pattacker[80];
6604 
6605 	// (project_grid is required for disarm beam! same for project_item, for chests!)
6606 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6607 //	flg |= PROJECT_STOP | PROJECT_HIDE;
6608 
6609 	/* Analyze the "dir" and the "target".  Hurt items on floor. */
6610 	snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6611 
6612 #ifdef USE_SOUND_2010
6613 	if (p_ptr->sfx_magicattack) sound(Ind, "cast_beam", NULL, SFX_TYPE_COMMAND, FALSE);
6614 #endif
6615 
6616 #if 0 /* why needed for beam? */
6617 	/* Use the given direction */
6618 	int tx = p_ptr->px + 99 * ddx[dir], ty = p_ptr->py + 99 * ddy[dir];
6619 
6620 	/* WRAITHFORM reduces damage/effect! */
6621 	if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6622 
6623 	/* Hack -- Use an actual "target" */
6624 	if ((dir == 5) && target_okay(Ind)) {
6625 		flg &= ~PROJECT_STOP;
6626 		tx = p_ptr->target_col;
6627 		ty = p_ptr->target_row;
6628 	}
6629 
6630 	return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6631 #else
6632 	return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6633 #endif
6634 
6635 }
6636 
6637 
6638 /*
6639  * Some of the old functions
6640  */
6641 /* TODO: the result should be affected by skills (and not plev) */
6642 
lite_line(int Ind,int dir,int dam)6643 bool lite_line(int Ind, int dir, int dam)
6644 {
6645 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL | PROJECT_NODF | PROJECT_NODO;
6646 	return (project_hook(Ind, GF_LITE_WEAK, dir, dam, flg, ""));
6647 }
6648 
drain_life(int Ind,int dir,int dam)6649 bool drain_life(int Ind, int dir, int dam)
6650 {
6651 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6652 	return(project_hook(Ind, GF_OLD_DRAIN, dir, dam, flg, ""));
6653 }
6654 
annihilate(int Ind,int dir,int dam)6655 bool annihilate(int Ind, int dir, int dam)
6656 {
6657 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6658 	return(project_hook(Ind, GF_ANNIHILATION, dir, dam, flg, ""));
6659 }
6660 
wall_to_mud(int Ind,int dir)6661 bool wall_to_mud(int Ind, int dir)
6662 {
6663 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_NODF | PROJECT_NODO;
6664 	return (project_hook(Ind, GF_KILL_WALL, dir, 20 + randint(30), flg, ""));
6665 }
6666 
destroy_door(int Ind,int dir)6667 bool destroy_door(int Ind, int dir)
6668 {
6669 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6670 	return (project_hook(Ind, GF_KILL_DOOR, dir, 0, flg, ""));
6671 }
6672 
disarm_trap(int Ind,int dir)6673 bool disarm_trap(int Ind, int dir)
6674 {
6675 	int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6676 	return (project_hook(Ind, GF_KILL_TRAP, dir, 0, flg, ""));
6677 }
6678 
heal_monster(int Ind,int dir)6679 bool heal_monster(int Ind, int dir)
6680 {
6681 	int flg = PROJECT_STOP | PROJECT_KILL;
6682 	snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker), "%s heals you for", Players[Ind]->name);
6683 	return (project_hook(Ind, GF_OLD_HEAL, dir, damroll(4, 6), flg, Players[Ind]->attacker));
6684 }
6685 
speed_monster(int Ind,int dir)6686 bool speed_monster(int Ind, int dir)
6687 {
6688 	player_type *p_ptr = Players[Ind];
6689 
6690 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6691 	return (project_hook(Ind, GF_OLD_SPEED, dir, p_ptr->lev, flg, ""));
6692 }
6693 
slow_monster(int Ind,int dir,int pow)6694 bool slow_monster(int Ind, int dir, int pow)
6695 {
6696 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6697 	return (project_hook(Ind, GF_OLD_SLOW, dir, pow, flg, ""));
6698 }
6699 
sleep_monster(int Ind,int dir,int pow)6700 bool sleep_monster(int Ind, int dir, int pow)
6701 {
6702 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6703 	return (project_hook(Ind, GF_OLD_SLEEP, dir, pow, flg, ""));
6704 }
6705 
confuse_monster(int Ind,int dir,int pow)6706 bool confuse_monster(int Ind, int dir, int pow)
6707 {
6708 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6709 	return (project_hook(Ind, GF_OLD_CONF, dir, pow, flg, ""));
6710 }
6711 
poly_monster(int Ind,int dir)6712 bool poly_monster(int Ind, int dir)
6713 {
6714 	player_type *p_ptr = Players[Ind];
6715 
6716 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_SELF | PROJECT_PLAY | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6717 	return (project_hook(Ind, GF_OLD_POLY, dir, p_ptr->lev, flg, ""));
6718 }
6719 
clone_monster(int Ind,int dir)6720 bool clone_monster(int Ind, int dir)
6721 {
6722 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6723 	return (project_hook(Ind, GF_OLD_CLONE, dir, 0, flg, ""));
6724 }
6725 
fear_monster(int Ind,int dir,int pow)6726 bool fear_monster(int Ind, int dir, int pow)
6727 {
6728 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6729 	return (project_hook(Ind, GF_TURN_ALL, dir, pow, flg, ""));
6730 }
6731 
teleport_monster(int Ind,int dir)6732 bool teleport_monster(int Ind, int dir)
6733 {
6734 	int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6735 	return (project_hook(Ind, GF_AWAY_ALL, dir, MAX_SIGHT * 5, flg, ""));
6736 }
6737 
cure_light_wounds_proj(int Ind,int dir)6738 bool cure_light_wounds_proj(int Ind, int dir)
6739 {
6740 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6741 	snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker), "%s heals you for", Players[Ind]->name);
6742 	return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(2, 10), flg, Players[Ind]->attacker));
6743 }
6744 
cure_serious_wounds_proj(int Ind,int dir)6745 bool cure_serious_wounds_proj(int Ind, int dir)
6746 {
6747 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6748 	snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6749 	return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(4, 10), flg, Players[Ind]->attacker));
6750 }
6751 
cure_critical_wounds_proj(int Ind,int dir)6752 bool cure_critical_wounds_proj(int Ind, int dir)
6753 {
6754 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6755 	snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6756 	return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(6, 10), flg, Players[Ind]->attacker));
6757 }
6758 
heal_other_proj(int Ind,int dir)6759 bool heal_other_proj(int Ind, int dir)
6760 {
6761 	int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6762 	snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6763 	return (project_hook(Ind, GF_HEAL_PLAYER, dir, 100, flg, Players[Ind]->attacker));
6764 }
6765 
6766 
6767 
6768 /*
6769  * Hooks -- affect adjacent grids (radius 1 ball attack)
6770  */
6771 
door_creation(int Ind)6772 bool door_creation(int Ind)
6773 {
6774 	player_type *p_ptr = Players[Ind];
6775 
6776 	int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6777 	return (project(0 - Ind, 1, &p_ptr->wpos, p_ptr->py, p_ptr->px, 0, GF_MAKE_DOOR, flg, ""));
6778 }
6779 
trap_creation(int Ind,int mod,int rad)6780 bool trap_creation(int Ind, int mod, int rad)
6781 {
6782 	player_type *p_ptr = Players[Ind];
6783 
6784 	int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6785 	return (project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, mod, GF_MAKE_TRAP, flg, ""));
6786 }
6787 
destroy_doors_touch(int Ind,int rad)6788 bool destroy_doors_touch(int Ind, int rad)
6789 {
6790 	player_type *p_ptr = Players[Ind];
6791 
6792 	int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6793 	return (project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, 0, GF_KILL_DOOR, flg, ""));
6794 }
6795 
sleep_monsters_touch(int Ind)6796 bool sleep_monsters_touch(int Ind)
6797 {
6798 	player_type *p_ptr = Players[Ind];
6799 
6800 	int flg = PROJECT_NORF | PROJECT_KILL | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6801 	return (project(0 - Ind, 1, &p_ptr->wpos, p_ptr->py, p_ptr->px, p_ptr->lev, GF_OLD_SLEEP, flg, ""));
6802 }
6803 
6804 /* Scan magical powers for the golem */
scan_golem_flags(object_type * o_ptr,monster_race * r_ptr)6805 static void scan_golem_flags(object_type *o_ptr, monster_race *r_ptr)
6806 {
6807 	u32b f1, f2, f3, f4, f5, f6, esp;
6808 
6809 	/* Extract the flags */
6810 	object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
6811 
6812 	if (f1 & TR1_LIFE) r_ptr->hdice += o_ptr->pval;
6813 	if (f1 & TR1_SPEED) r_ptr->speed += o_ptr->pval * 2 / 3;
6814 	if (f1 & TR1_TUNNEL) r_ptr->flags2 |= RF2_KILL_WALL;
6815 	if (f2 & TR2_RES_FIRE) r_ptr->flags3 |= RF3_IM_FIRE;
6816 	if (f2 & TR2_RES_ACID) r_ptr->flags3 |= RF3_IM_ACID;
6817 	if (f2 & TR2_RES_NETHER) r_ptr->flags3 |= RF3_RES_NETH;
6818 	if (f2 & TR2_RES_NEXUS) r_ptr->flags3 |= RF3_RES_NEXU;
6819 	if (f2 & TR2_RES_DISEN) r_ptr->flags3 |= RF3_RES_DISE;
6820 
6821 	/* Allow use of runes - some are redundant (for completeness) */
6822 	if (o_ptr->tval == TV_RUNE) switch(o_ptr->sval) {
6823 	case SV_R_LITE: r_ptr->flags9 |= RF9_RES_LITE; break;
6824 	case SV_R_DARK: r_ptr->flags9 |= RF9_RES_DARK; break;
6825 	case SV_R_NEXU: r_ptr->flags3 |= RF3_RES_NEXU; break;
6826 	case SV_R_NETH: r_ptr->flags3 |= RF3_RES_NETH; break;
6827 	case SV_R_CHAO: r_ptr->flags9 |= RF9_RES_CHAOS; break;
6828 	case SV_R_MANA: r_ptr->flags9 |= RF9_RES_MANA; break;
6829 
6830 	case SV_R_CONF: r_ptr->flags3 |= RF3_NO_CONF; break;
6831 //	case SV_R_INER: r_ptr->flags4 |= RF4_BR_INER; break; //Inertia has no resist; alt: RF3_NO_TELE!
6832 	case SV_R_ELEC: r_ptr->flags3 |= RF3_IM_ELEC; break;
6833 	case SV_R_FIRE: r_ptr->flags3 |= RF3_IM_FIRE; break;
6834 	case SV_R_WATE: r_ptr->flags3 |= RF3_RES_WATE; break;
6835 //	case SV_R_GRAV: r_ptr->flags4 |= RF4_BR_GRAV; break; //Gravity has no resist (for mobs)!
6836 	case SV_R_COLD: r_ptr->flags3 |= RF3_IM_COLD; break;
6837 	case SV_R_ACID: r_ptr->flags3 |= RF3_IM_ACID; break;
6838 	case SV_R_POIS: r_ptr->flags3 |= RF3_IM_POIS; break;
6839 	case SV_R_TIME: r_ptr->flags9 |= RF9_RES_TIME; break;
6840 	case SV_R_SOUN: r_ptr->flags9 |= RF9_RES_SOUND; break;
6841 	case SV_R_SHAR: r_ptr->flags9 |= RF9_RES_SHARDS; break;
6842 	case SV_R_DISE: r_ptr->flags3 |= RF3_RES_DISE; break;
6843 //	case SV_R_FORC: r_ptr->flags4 |= RF4_BR_WALL; break; //Force has no resist (for mobs); alt: RF3_NO_SLEEP!
6844 	case SV_R_PLAS: r_ptr->flags3 |= RF3_RES_PLAS; break;
6845 
6846 	default: break;
6847 	}
6848 }
6849 
6850 /* multi builder stuff - move when complete */
6851 struct builder {
6852 	int player;
6853 	int lx, ly, dx, dy, minx, miny, maxx, maxy;
6854 	int sx, sy;
6855 	int odir;
6856 	int moves;
6857 	int cvert;
6858 	struct worldpos wpos;
6859 	bool nofloor;
6860 	bool jail;
6861 	struct dna_type *dna;
6862 	char *vert;
6863 	struct c_special *cs;
6864 	struct builder *next;
6865 };
6866 
6867 #define MAX_BUILDERS 4	/* Just so the builders can go on strike */
6868 /* end of move stuff */
6869 
poly_build(int Ind,char * args)6870 static bool poly_build(int Ind, char *args) {
6871 	static struct builder *builders = NULL;
6872 	static int num_build = 0;
6873 
6874 	player_type *p_ptr = Players[Ind];
6875 	struct builder *curr = builders;
6876 	int x, y;
6877 	int dir = 0;
6878 	cave_type **zcave;
6879 	if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
6880 	while (curr) {
6881 		struct builder *prev = NULL;
6882 		bool kill = FALSE;
6883 		if (curr->player == p_ptr->id) break;
6884 		if (!lookup_player_name(curr->player)) {	/* disconnect or free builders */
6885 			if (prev)
6886 				prev->next = curr->next;
6887 			else
6888 				builders = curr->next;
6889 			kill = TRUE;
6890 		}
6891 		prev = curr;
6892 		curr = curr->next;
6893 		if (kill) {
6894 			KILL(prev, struct builder);
6895 		}
6896 	}
6897 
6898 	if (!curr) {			/* new builder */
6899 #ifdef MAX_BUILDERS
6900 		if (num_build == MAX_BUILDERS){
6901 			msg_print(Ind,"The builders are on strike!");
6902 			return FALSE;
6903 		}
6904 #endif
6905 		MAKE(curr, struct builder);
6906 		curr->next = builders;	/* insert is fastest */
6907 		curr->player = p_ptr->id;	/* set him up */
6908 		C_MAKE(curr->vert, MAXCOORD, char);
6909 		MAKE(curr->dna, struct dna_type);
6910 		curr->dna->creator = p_ptr->dna;
6911 		curr->dna->owner = p_ptr->id;
6912 		curr->dna->owner_type = OT_PLAYER;
6913 		curr->dna->a_flags = ACF_NONE;
6914 		curr->dna->min_level = ACF_NONE;
6915 		curr->dna->price = 5;	/* so work out */
6916 		curr->odir = 0;
6917 		curr->cvert = 0;
6918 		curr->nofloor = (args[0] == 'N');
6919 		curr->jail = (args[1] == 'Y');
6920 		curr->sx = p_ptr->px;
6921 		curr->sy = p_ptr->py;
6922 		curr->minx = curr->maxx = curr->sx;
6923 		curr->miny = curr->maxy = curr->sy;
6924 		curr->dx = curr->lx = curr->sx;
6925 		curr->dy = curr->ly = curr->sy;
6926 		curr->moves = 25;	/* always new */
6927 		wpcopy(&curr->wpos, &p_ptr->wpos);
6928 //		if (zcave[curr->sy][curr->sx].feat == FEAT_PERM_EXTRA){
6929 		if (zcave[curr->sy][curr->sx].feat == FEAT_WALL_HOUSE){
6930 #if 0	/* not necessary? - evileye */
6931 			zcave[curr->sy][curr->sx].special.sc.ptr = NULL;
6932 #endif
6933 			msg_print(Ind, "Your foundations were laid insecurely");
6934 			KILL(curr->dna, struct dna_type);
6935 			C_KILL(curr->vert, MAXCOORD, char);
6936 			p_ptr->master_move_hook = NULL;
6937 			KILL(curr, struct builder);	/* Sack the builders! */
6938 			return FALSE;
6939 		}
6940 		zcave[curr->sy][curr->sx].feat = FEAT_HOME_OPEN;
6941 		/* CS_DNADOOR seems to be added twice (wild_add_uhouse)..
6942 		 * please correct it, Evileye?	- Jir -
6943 		 */
6944 #if 0
6945 		if ((curr->cs = AddCS(&zcave[curr->sy][curr->sx], CS_DNADOOR))) {
6946 			curr->cs->sc.ptr = curr->dna;
6947 		}
6948 #endif
6949 		builders = curr;
6950 		return TRUE;
6951 	}
6952 
6953 	if (args) {
6954 		curr->moves += 25;
6955 		return TRUE;
6956 	}
6957 	x = p_ptr->px;
6958 	y = p_ptr->py;
6959 	curr->minx = MIN(x, curr->minx);
6960 	curr->maxx = MAX(x, curr->maxx);
6961 	curr->miny = MIN(y, curr->miny);
6962 	curr->maxy = MAX(y, curr->maxy);
6963 	if (x != curr->dx) {
6964 		if (x > curr->dx) dir = 1;
6965 		else dir = 2;
6966 	}
6967 	if (y != curr->dy) {
6968 		if (dir) {
6969 			curr->moves = 0;
6970 			/* diagonal! house building failed */
6971 		}
6972 		if(y > curr->dy) dir |= 4;
6973 		else dir |= 8;
6974 	}
6975 	if (curr->odir != dir) {
6976 		if (curr->odir) {		/* first move not new vertex */
6977 			curr->vert[curr->cvert++] = curr->dx-curr->lx;
6978 			curr->vert[curr->cvert++] = curr->dy-curr->ly;
6979 		}
6980 		curr->lx = curr->dx;
6981 		curr->ly = curr->dy;
6982 		curr->odir = dir;		/* change direction, add vertex */
6983 	}
6984 	curr->dx = x;
6985 	curr->dy = y;
6986 
6987 	if (p_ptr->px == curr->sx && p_ptr->py == curr->sy && curr->moves) {	/* check for close */
6988 		curr->vert[curr->cvert++] = curr->dx-curr->lx;			/* last vertex */
6989 		curr->vert[curr->cvert++] = curr->dy-curr->ly;
6990 		if (curr->cvert == 10 || curr->cvert == 8) {
6991 			/* rectangle! */
6992 			houses[num_houses].flags = HF_RECT;
6993 			houses[num_houses].x = curr->minx;
6994 			houses[num_houses].y = curr->miny;
6995 			houses[num_houses].coords.rect.width = curr->maxx + 1 - curr->minx;
6996 			houses[num_houses].coords.rect.height = curr->maxy + 1 - curr->miny;
6997 #if 0 /* hm, isn't this buggy? should just be same as for HF_NONE? */
6998 			houses[num_houses].dx = curr->sx-curr->minx;
6999 			houses[num_houses].dy = curr->sy-curr->miny;
7000 #else
7001 			houses[num_houses].dx = curr->sx;
7002 			houses[num_houses].dy = curr->sy;
7003 #endif
7004 			C_KILL(curr->vert, MAXCOORD, char);
7005 		} else {
7006 			houses[num_houses].flags = HF_NONE;	/* polygonal */
7007 			houses[num_houses].x = curr->sx;
7008 			houses[num_houses].y = curr->sy;
7009 			houses[num_houses].coords.poly = curr->vert;
7010 			/* was missing: actually remember the door position! (for pick_house() to work) */
7011 			houses[num_houses].dx = curr->sx;
7012 			houses[num_houses].dy = curr->sy;
7013 		}
7014 		if (curr->nofloor) houses[num_houses].flags |= HF_NOFLOOR;
7015 		if (curr->jail) houses[num_houses].flags |= HF_JAIL;
7016 /* Moat testing */
7017 #if 0
7018 		houses[num_houses].flags |= HF_MOAT;
7019 #endif
7020 /* Do not commit! */
7021 		wpcopy(&houses[num_houses].wpos, &p_ptr->wpos);
7022 		houses[num_houses].dna = curr->dna;
7023 		if (curr->cvert >= 8 && fill_house(&houses[num_houses], FILL_MAKEHOUSE, NULL)){
7024 			int area = (curr->maxx-curr->minx) * (curr->maxy-curr->miny);
7025 			houses[num_houses].flags |= HF_SELFBUILT;
7026 			curr->dna->price = area * area * 400; //initial_house_price(&houses[num_houses])
7027 			wild_add_uhouse(&houses[num_houses]);
7028 			msg_print(Ind,"You have completed your house");
7029 			num_houses++;
7030 		} else {
7031 			msg_print(Ind,"Your house was built unsoundly");
7032 			if(curr->vert) C_KILL(curr->vert, MAXCOORD, char);
7033 			KILL(curr->dna, struct dna_type);
7034 		}
7035 		curr->player = 0;		/* send the builders home */
7036 		p_ptr->master_move_hook = NULL;
7037 		p_ptr->update |= PU_VIEW;
7038 		return TRUE;
7039 	}
7040 	/* no going off depth, and no spoiling moats */
7041 	if (inarea(&curr->wpos, &p_ptr->wpos) && !(zcave[curr->dy][curr->dx].info&CAVE_ICKY && zcave[curr->dy][curr->dx].feat == FEAT_DEEP_WATER)) {
7042 		zcave[curr->dy][curr->dx].feat = FEAT_WALL_EXTRA;
7043 //		zcave[curr->dy][curr->dx].feat = FEAT_WALL_HOUSE;
7044 		if (curr->cvert < MAXCOORD && (--curr->moves) > 0) return TRUE;
7045 		p_ptr->update |= PU_VIEW;
7046 	}
7047 	msg_print(Ind,"Your house building attempt has failed");
7048 	cs_erase(&zcave[curr->sy][curr->sx], curr->cs);
7049 	KILL(curr->dna, struct dna_type);
7050 	C_KILL(curr->vert, MAXCOORD, char);
7051 	curr->player = 0;		/* send the builders home */
7052 	p_ptr->master_move_hook = NULL;
7053 	return FALSE;
7054 }
7055 
house_creation(int Ind,bool floor,bool jail)7056 void house_creation(int Ind, bool floor, bool jail)
7057 {
7058 	player_type *p_ptr = Players[Ind];
7059 	struct worldpos *wpos = &p_ptr->wpos;
7060 	char buildargs[3];
7061 
7062 	/* set master_move_hook : a bit like a setuid really ;) */
7063 	printf("floor: %d jail: %d\n",floor,jail);
7064 
7065 	/* No building in town */
7066 	if (wpos->wz) {
7067 		msg_print(Ind, "\376\377yYou must build on the world surface.");
7068 		return;
7069 	}
7070 	if (istownarea(wpos, MAX_TOWNAREA)) {
7071 		msg_print(Ind, "\376\377yYou cannot build within a town area.");
7072 		if (!is_admin(p_ptr)) return;
7073 	}
7074 	if (house_alloc - num_houses < 32) {
7075 		GROW(houses, house_alloc, house_alloc + 512, house_type);
7076 		house_alloc += 512;
7077 	}
7078 	p_ptr->master_move_hook = poly_build;
7079 
7080 	buildargs[0] = (floor ? 'Y' : 'N');
7081 	buildargs[1] = (jail ? 'Y' : 'N');
7082 	buildargs[2] = '\0';
7083 
7084 	poly_build(Ind, (char*)&buildargs);	/* Its a (char*) ;( */
7085 }
7086 
7087 /* (Note: Apparently currently only used by Moltor's second_handler().) */
place_foe(int owner_id,struct worldpos * wpos,int y,int x,int r_idx)7088 extern bool place_foe(int owner_id, struct worldpos *wpos, int y, int x, int r_idx) {
7089 	int                     i, Ind, j;
7090 	cave_type               *c_ptr;
7091 
7092 	monster_type    *m_ptr;
7093 	monster_race    *r_ptr = &r_info[r_idx];
7094 
7095 	char buf[80];
7096 
7097 	cave_type **zcave;
7098 	if (!(zcave = getcave(wpos))) return (0);
7099 	/* Verify location */
7100 	if (!in_bounds(y, x)) return (0);
7101 	/* Require empty space */
7102 	if (!cave_empty_bold(zcave, y, x)) return (0);
7103 
7104 	/* Paranoia */
7105 	if (!r_idx) return (0);
7106 
7107 	/* Paranoia */
7108 	if (!r_ptr->name) return (0);
7109 
7110 	/* Update r_ptr due to possible r_idx changes */
7111 	r_ptr = &r_info[r_idx];
7112 
7113 	if ((r_ptr->flags1 & RF1_UNIQUE)) return (0);
7114 
7115 	c_ptr = &zcave[y][x];
7116 
7117 	/* Make a new monster */
7118 	c_ptr->m_idx = m_pop();
7119 
7120 	/* Mega-Hack -- catch "failure" */
7121 	if (!c_ptr->m_idx) return (0);
7122 
7123 	/* Get a new monster record */
7124 	m_ptr = &m_list[c_ptr->m_idx];
7125 
7126 	/* Save the race */
7127 	m_ptr->r_idx = r_idx;
7128 
7129 	/* Place the monster at the location */
7130 	m_ptr->fy = y;
7131 	m_ptr->fx = x;
7132 	wpcopy(&m_ptr->wpos, wpos);
7133 
7134 	m_ptr->special = m_ptr->questor = 0;
7135 
7136 	/* Hack -- Count the monsters on the level */
7137 	r_ptr->cur_num++;
7138 
7139 
7140 	/* Hack -- count the number of "reproducers" */
7141 	if (r_ptr->flags7 & RF7_MULTIPLY) num_repro++;
7142 
7143 
7144 	/* Assign maximal hitpoints */
7145 	if (r_ptr->flags1 & RF1_FORCE_MAXHP)
7146 		m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7147 	else
7148 		m_ptr->maxhp = damroll(r_ptr->hdice, r_ptr->hside);
7149 
7150 	/* And start out fully healthy */
7151 	m_ptr->hp = m_ptr->maxhp;
7152 
7153 	/* Extract the monster base speed */
7154 	m_ptr->speed = r_ptr->speed;
7155 	/* set cur speed to base speed */
7156 	m_ptr->mspeed = m_ptr->speed;
7157 
7158 	/* Extract base ac and  other things */
7159 	m_ptr->ac = r_ptr->ac;
7160 
7161 	for (j = 0; j < 4; j++) {
7162 		m_ptr->blow[j].effect = r_ptr->blow[j].effect;
7163 		m_ptr->blow[j].method = r_ptr->blow[j].method;
7164 		m_ptr->blow[j].d_dice = r_ptr->blow[j].d_dice;
7165 		m_ptr->blow[j].d_side = r_ptr->blow[j].d_side;
7166 	}
7167 	m_ptr->level = r_ptr->level;
7168 	m_ptr->exp = MONSTER_EXP(m_ptr->level);
7169 	m_ptr->owner = 0;
7170 
7171 	/* Hack -- small racial variety */
7172 	if (!(r_ptr->flags1 & RF1_UNIQUE)) {
7173 		/* Allow some small variation per monster */
7174 		i = extract_energy[m_ptr->speed] / 100;
7175 		if (i) {
7176 			j = rand_spread(0, i);
7177 			m_ptr->mspeed += j;
7178 
7179 			if (m_ptr->mspeed < j) m_ptr->mspeed = 255;
7180 		}
7181 	}
7182 
7183 
7184 	/* Give a random starting energy */
7185 	m_ptr->energy = rand_int(1000);
7186 
7187 	/* Hack -- Reduce risk of "instant death by breath weapons" */
7188 	if (r_ptr->flags1 & RF1_FORCE_SLEEP) {
7189 		/* Start out with minimal energy */
7190 		m_ptr->energy = rand_int(100);
7191 	}
7192 
7193 	/* Starts 'flickered out'? */
7194 	if ((r_ptr->flags2 & RF2_WEIRD_MIND) && rand_int(10)) m_ptr->no_esp_phase = TRUE;
7195 
7196 	/* No "damage" yet */
7197 	m_ptr->stunned = 0;
7198 	m_ptr->confused = 0;
7199 	m_ptr->monfear = 0;
7200 
7201 	/* No knowledge */
7202 	m_ptr->cdis = 0;
7203 
7204 	/* clone value */
7205 
7206         m_ptr->owner = 0;
7207         m_ptr->pet = 0;
7208 
7209 	for (Ind = 1; Ind < NumPlayers + 1; Ind++) {
7210 		if (Players[Ind]->conn == NOT_CONNECTED)
7211 			continue;
7212 
7213 		Players[Ind]->mon_los[c_ptr->m_idx] = 0;
7214 		Players[Ind]->mon_vis[c_ptr->m_idx] = 0;
7215 	}
7216 
7217 	if (getlevel(wpos) > (m_ptr->level + 7)) {
7218 		m_ptr->exp = MONSTER_EXP(m_ptr->level + ((getlevel(wpos) - (m_ptr->level + 7)) / 3));
7219 		monster_check_experience(c_ptr->m_idx, TRUE);
7220 	}
7221 
7222 	strcpy(buf, (r_name + r_ptr->name));
7223 
7224 	/* Update the monster */
7225 	update_mon(c_ptr->m_idx, TRUE);
7226 
7227 
7228 	/* Assume no sleeping */
7229 	m_ptr->csleep = 0;
7230 
7231 	/* STR */
7232 	for (j = 0; j < 4; j++) {
7233 		m_ptr->blow[j].org_d_dice = r_ptr->blow[j].d_dice;
7234 		m_ptr->blow[j].org_d_side = r_ptr->blow[j].d_side;
7235 	}
7236 	/* DEX */
7237 	m_ptr->org_ac = m_ptr->ac;
7238 	/* CON */
7239 	m_ptr->org_maxhp = m_ptr->maxhp;
7240 
7241 #ifdef MONSTER_ASTAR
7242 	if (r_ptr->flags0 & RF0_ASTAR) {
7243 		/* search for an available A* table to use */
7244 		for (j = 0; j < ASTAR_MAX_INSTANCES; j++) {
7245 			/* found an available instance? */
7246 			if (astar_info_open[j].m_idx == -1) {
7247 				astar_info_open[j].m_idx = c_ptr->m_idx;
7248 				astar_info_open[j].nodes = 0; /* init: start with empty set of nodes */
7249 				astar_info_closed[j].nodes = 0; /* init: start with empty set of nodes */
7250 				m_ptr->astar_idx = j;
7251 				break;
7252 			}
7253 		}
7254 		/* no instance available? Mark us (-1) to use normal movement instead */
7255 		if (j == ASTAR_MAX_INSTANCES) m_ptr->astar_idx = -1;
7256 	}
7257 #endif
7258 
7259 	return (TRUE);
7260 }
7261 #ifdef RPG_SERVER
place_pet(int owner_id,struct worldpos * wpos,int y,int x,int r_idx)7262 bool place_pet(int owner_id, struct worldpos *wpos, int y, int x, int r_idx) {
7263 	int                     Ind, j;
7264 	cave_type               *c_ptr;
7265 
7266 	monster_type    *m_ptr;
7267 	monster_race    *r_ptr = &r_info[r_idx];
7268 
7269 	char buf[80];
7270 
7271 	cave_type **zcave;
7272 	if (!(zcave = getcave(wpos))) return (0);
7273 
7274 
7275 	/* Verify location */
7276 	if (!in_bounds(y, x)) return (0);
7277 	/* Require empty space */
7278 	if (!cave_empty_bold(zcave, y, x)) return (0);
7279 	/* Hack -- no creation on glyph of warding */
7280 	if (zcave[y][x].feat == FEAT_GLYPH) return (0);
7281 	if (zcave[y][x].feat == FEAT_RUNE) return (0);
7282 
7283 	/* Paranoia */
7284 	if (!r_idx) return (0);
7285 
7286 	/* Paranoia */
7287 	if (!r_ptr->name) return (0);
7288 
7289 	/* Update r_ptr due to possible r_idx changes */
7290 	r_ptr = &r_info[r_idx];
7291 
7292 	/* No uniques, obviously */
7293 	if (r_ptr->flags1 & RF1_UNIQUE) return (0);
7294 
7295 	/* No breeders */
7296 	if (r_ptr->flags7 & RF7_MULTIPLY) return (0);
7297 
7298 	c_ptr = &zcave[y][x];
7299 
7300 	/* Make a new monster */
7301 	c_ptr->m_idx = m_pop();
7302 
7303 	/* Mega-Hack -- catch "failure" */
7304 	if (!c_ptr->m_idx) return (0);
7305 
7306 	/* Get a new monster record */
7307 	m_ptr = &m_list[c_ptr->m_idx];
7308 
7309 	/* Save the race */
7310 	m_ptr->r_idx = r_idx;
7311 
7312 	/* Place the monster at the location */
7313 	m_ptr->fy = y;
7314 	m_ptr->fx = x;
7315 	wpcopy(&m_ptr->wpos, wpos);
7316 
7317 	m_ptr->special = m_ptr->questor = 0;
7318 
7319 	/* Hack -- Count the monsters on the level */
7320 	r_ptr->cur_num++;
7321 
7322 	/* Assign maximal hitpoints */
7323 	if (r_ptr->flags1 & RF1_FORCE_MAXHP)
7324 		m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7325 	else
7326 		m_ptr->maxhp = damroll(r_ptr->hdice, r_ptr->hside);
7327 
7328 	/* And start out fully healthy */
7329 	m_ptr->hp = m_ptr->maxhp;
7330 
7331 	/* Extract the monster base speed */
7332 	m_ptr->speed = r_ptr->speed;
7333 	/* set cur speed to base speed */
7334 	m_ptr->mspeed = m_ptr->speed;
7335 
7336 	/* Extract base ac and  other things */
7337 	m_ptr->ac = r_ptr->ac;
7338 
7339 	for (j = 0; j < 4; j++) {
7340 		m_ptr->blow[j].effect = r_ptr->blow[j].effect;
7341 		m_ptr->blow[j].method = r_ptr->blow[j].method;
7342 		m_ptr->blow[j].d_dice = r_ptr->blow[j].d_dice;
7343 		m_ptr->blow[j].d_side = r_ptr->blow[j].d_side;
7344 	}
7345 	m_ptr->level = r_ptr->level;
7346 	m_ptr->exp = MONSTER_EXP(m_ptr->level);
7347 	m_ptr->owner = 0;
7348 
7349 	/* Give a random starting energy */
7350 	m_ptr->energy = rand_int(100);
7351 
7352 	/* No "damage" yet */
7353 	m_ptr->stunned = 0;
7354 	m_ptr->confused = 0;
7355 	m_ptr->monfear = 0;
7356 
7357 	/* No knowledge */
7358 	m_ptr->cdis = 0;
7359 
7360 	/* special pet value */
7361         m_ptr->owner = Players[owner_id]->id;
7362         m_ptr->pet = 1;
7363 
7364 	for (Ind = 1; Ind < NumPlayers + 1; Ind++) {
7365 		if (Players[Ind]->conn == NOT_CONNECTED)
7366 			continue;
7367 
7368 		Players[Ind]->mon_los[c_ptr->m_idx] = 0;
7369 		Players[Ind]->mon_vis[c_ptr->m_idx] = 0;
7370 	}
7371 
7372 	if (getlevel(wpos) >= (m_ptr->level + 8)) {
7373 		m_ptr->exp = MONSTER_EXP(m_ptr->level + ((getlevel(wpos) - m_ptr->level - 5) / 3));
7374 		monster_check_experience(c_ptr->m_idx, TRUE);
7375 	}
7376 
7377 	strcpy(buf, (r_name + r_ptr->name));
7378 
7379 	/* Update the monster */
7380 	update_mon(c_ptr->m_idx, TRUE);
7381 
7382 	/* Assume no sleeping */
7383 	m_ptr->csleep = 0;
7384 
7385 	/* STR */
7386 	for (j = 0; j < 4; j++) {
7387 		m_ptr->blow[j].org_d_dice = r_ptr->blow[j].d_dice;
7388 		m_ptr->blow[j].org_d_side = r_ptr->blow[j].d_side;
7389 	}
7390 	/* DEX */
7391 	m_ptr->org_ac = m_ptr->ac;
7392 	/* CON */
7393 	m_ptr->org_maxhp = m_ptr->maxhp;
7394 
7395 	return (TRUE);
7396 }
7397 
7398 /* Create a servant ! */
pet_creation(int Ind)7399 char pet_creation(int Ind)
7400 { //put the sanity tests here and call place_pet
7401 	int id = 955; //green dr for now
7402 	/* bleh, green dr is too powerful, lets do spiders. i'm fond of spiders. */
7403 	int lev = Players[Ind]->lev;
7404 	if (lev < 5) id = (randint(2)>1 ? 60 /*cave S*/ : 62 /*wild cat*/);
7405 	else if (lev < 10) id = 127; //wood S
7406 	else if (lev < 15) id = 277; //mirkwood S
7407 	else if (lev < 20) id = 963; //aranea
7408 	else id = 964; //elder aranea
7409 
7410 	if (!Players[Ind]->has_pet) {
7411 		place_pet(Ind,
7412 		   &(Players[Ind]->wpos), Players[Ind]->py, Players[Ind]->px+1,  /* E of player */
7413 		   id);
7414 		Players[Ind]->has_pet = 1;
7415 		return 1;
7416 	}
7417 	return 0;
7418 }
7419 #endif
7420 
7421 /* Create a mindless servant ! */
golem_creation(int Ind,int max)7422 void golem_creation(int Ind, int max) {
7423 	player_type *p_ptr = Players[Ind];
7424 	monster_race *r_ptr;
7425 	monster_type *m_ptr;
7426 	int i;
7427 	int golem_type = -1;
7428 	int golem_arms[4], golem_m_arms = 0;
7429 	int golem_legs[30], golem_m_legs = 0;
7430 	s16b golem_flags = 0;
7431 	cave_type *c_ptr;
7432 	int x, y, k, g_cnt = 0;
7433 	bool okay = FALSE;
7434 	cave_type **zcave;
7435 	if (!(zcave = getcave(&p_ptr->wpos))) return;
7436 
7437 	/* Process the monsters */
7438 	for (k = m_top - 1; k >= 0; k--) {
7439 		/* Access the index */
7440 		i = m_fast[k];
7441 
7442 		/* Access the monster */
7443 		m_ptr = &m_list[i];
7444 
7445 		/* Excise "dead" monsters */
7446 		if (!m_ptr->r_idx) continue;
7447 
7448 		if (m_ptr->owner != p_ptr->id) continue;
7449 
7450 		if (!i) continue;
7451 
7452 		g_cnt++;
7453 	}
7454 
7455 	if (g_cnt >= max) {
7456 		msg_print(Ind, "You cannot create more golems.");
7457 		return;
7458 	}
7459 
7460 	for (x = p_ptr->px - 1; x <= p_ptr->px; x++)
7461 		for (y = p_ptr->py - 1; y <= p_ptr->py; y++) {
7462 			/* Verify location */
7463 			if (!in_bounds(y, x)) continue;
7464 			/* Require empty space */
7465 			if (!cave_empty_bold(zcave, y, x)) continue;
7466 
7467 			/* Hack -- no creation on glyph of warding */
7468 			if (zcave[y][x].feat == FEAT_GLYPH) continue;
7469 			if (zcave[y][x].feat == FEAT_RUNE) continue;
7470 
7471 			if ((p_ptr->px == x) && (p_ptr->py == y)) continue;
7472 
7473 			okay = TRUE;
7474 			break;
7475 		}
7476 
7477 	if (!okay) {
7478 		msg_print(Ind, "You don't have sufficient space to create a golem.");
7479 		return;
7480 	}
7481 
7482 
7483 	/* Access the location */
7484 	c_ptr = &zcave[y][x];
7485 
7486 	/* Make a new monster */
7487 	c_ptr->m_idx = m_pop();
7488 
7489 	/* Mega-Hack -- catch "failure" */
7490 	if (!c_ptr->m_idx) return;
7491 
7492 	/* Grab and allocate */
7493 	m_ptr = &m_list[c_ptr->m_idx];
7494 	MAKE(m_ptr->r_ptr, monster_race);
7495 	m_ptr->special = TRUE;
7496 	m_ptr->questor = FALSE;
7497 	m_ptr->fx = x;
7498 	m_ptr->fy = y;
7499 
7500 	r_ptr = m_ptr->r_ptr;
7501 
7502 	r_ptr->flags1 = 0;
7503 	r_ptr->flags2 = 0;
7504 	r_ptr->flags3 = 0;
7505 	r_ptr->flags4 = 0;
7506 	r_ptr->flags5 = 0;
7507 	r_ptr->flags6 = 0;
7508 	r_ptr->flags7 = 0;
7509 	r_ptr->flags8 = 0;
7510 	r_ptr->flags9 = 0;
7511 	r_ptr->flags0 = 0;
7512 
7513 	msg_print(Ind, "Some of your items begins to consume in roaring flames.");
7514 
7515 	/* Find items used for "golemification" */
7516 	for (i = 0; i < INVEN_WIELD; i++) {
7517 		object_type *o_ptr = &p_ptr->inventory[i];
7518 
7519 		if (o_ptr->tval == TV_GOLEM) {
7520 			if (o_ptr->sval <= SV_GOLEM_ADAM) {
7521 				golem_type = o_ptr->sval;
7522 				inven_item_increase(Ind, i, -1);
7523 				inven_item_optimize(Ind, i);
7524 				i--;
7525 				continue;
7526 			}
7527 			if (o_ptr->sval == SV_GOLEM_ARM) {
7528 				while (o_ptr->number) {
7529 					if (golem_m_arms == 4) break;
7530 					golem_arms[golem_m_arms++] = o_ptr->pval;
7531 					inven_item_increase(Ind, i, -1);
7532 				}
7533 				inven_item_optimize(Ind, i);
7534 				i--;
7535 				continue;
7536 			}
7537 			if (o_ptr->sval == SV_GOLEM_LEG) {
7538 				while (o_ptr->number) {
7539 					if (golem_m_legs == 30) break;
7540 					golem_legs[golem_m_legs++] = o_ptr->pval;
7541 					inven_item_increase(Ind, i, -1);
7542 				}
7543 				inven_item_optimize(Ind, i);
7544 				i--;
7545 				continue;
7546 			}
7547 			else golem_flags |= 1 << (o_ptr->sval - 200);
7548 		}
7549 		/* Combine / Reorder the pack (later) */
7550 		p_ptr->notice |= (PN_COMBINE | PN_REORDER);
7551 
7552 		/* Window stuff */
7553 		p_ptr->window |= (PW_INVEN | PW_EQUIP);
7554 	}
7555 
7556 	/* Ahah FAIL !!! */
7557 	if ((golem_type == -1) || (golem_m_legs < 2)) {
7558 		msg_print(Ind, "The spell fails! You lose all your material.");
7559 		delete_monster_idx(c_ptr->m_idx, TRUE);
7560 		return;
7561 	}
7562 
7563 	r_ptr->text = 0;
7564 	r_ptr->name = 0;
7565 	r_ptr->sleep = 0;
7566 	r_ptr->aaf = 20;
7567 	r_ptr->speed = 110;
7568 	for (i = 0; i < golem_m_legs; i++)
7569 		r_ptr->speed += golem_legs[i];
7570 	r_ptr->mexp = 1;
7571 
7572 	r_ptr->d_attr = TERM_YELLOW;
7573 	r_ptr->d_char = 'g';
7574 	r_ptr->x_attr = TERM_YELLOW;
7575 	r_ptr->x_char = 'g';
7576 
7577 	r_ptr->freq_innate = 0;
7578 	r_ptr->freq_spell = 0;
7579 	r_ptr->flags1 |= RF1_FORCE_MAXHP;
7580 	r_ptr->flags2 |= RF2_STUPID | RF2_EMPTY_MIND | RF2_REGENERATE | RF2_POWERFUL | RF2_BASH_DOOR | RF2_MOVE_BODY;
7581 	r_ptr->flags3 |= RF3_HURT_ROCK | RF3_IM_COLD | RF3_IM_ELEC | RF3_IM_POIS | RF3_NO_FEAR | RF3_NO_CONF | RF3_NO_SLEEP;
7582 	r_ptr->flags9 |= RF9_IM_TELE;
7583 
7584 	switch (golem_type) {
7585 		case SV_GOLEM_WOOD:
7586 			r_ptr->hdice = 10;
7587 			r_ptr->hside = 10;
7588 			r_ptr->ac = 20;
7589 			break;
7590 		case SV_GOLEM_COPPER:
7591 			r_ptr->hdice = 10;
7592 			r_ptr->hside = 20;
7593 			r_ptr->ac = 40;
7594 			break;
7595 		case SV_GOLEM_IRON:
7596 			r_ptr->hdice = 10;
7597 			r_ptr->hside = 40;
7598 			r_ptr->ac = 70;
7599 			break;
7600 		case SV_GOLEM_ALUM:
7601 			r_ptr->hdice = 10;
7602 			r_ptr->hside = 60;
7603 			r_ptr->ac = 90;
7604 			break;
7605 		case SV_GOLEM_SILVER:
7606 			r_ptr->hdice = 10;
7607 			r_ptr->hside = 70;
7608 			r_ptr->ac = 100;
7609 			break;
7610 		case SV_GOLEM_GOLD:
7611 			r_ptr->hdice = 10;
7612 			r_ptr->hside = 80;
7613 			r_ptr->ac = 130;
7614 			break;
7615 		case SV_GOLEM_MITHRIL:
7616 			r_ptr->hdice = 10;
7617 			r_ptr->hside = 100;
7618 			r_ptr->ac = 160;
7619 			break;
7620 		case SV_GOLEM_ADAM:
7621 			r_ptr->hdice = 10;
7622 			r_ptr->hside = 150;
7623 			r_ptr->ac = 210;
7624 			break;
7625 			//		default:
7626 	}
7627 	r_ptr->extra = golem_flags;
7628 	//#if 0
7629 	/* Find items used for "golemification" */
7630 	for (i = 0; i < INVEN_WIELD; i++) {
7631 		object_type *o_ptr = &p_ptr->inventory[i];
7632 		unsigned char *inscription = (unsigned char *) quark_str(o_ptr->note);
7633 
7634 		/* Additionnal items ? */
7635 		if (inscription != NULL) {
7636 			/* scan the inscription for @G */
7637 			while ((*inscription != '\0')) {
7638 				if (*inscription == '@') {
7639 					inscription++;
7640 
7641 					/* a valid @G has been located */
7642 					if (*inscription == 'G') {
7643 						inscription++;
7644 
7645 						scan_golem_flags(o_ptr, r_ptr);
7646 						/* scan_golem_flags uses only one item */
7647 						inven_item_increase(Ind,i,-1);
7648 						inven_item_optimize(Ind,i);
7649 						i--;
7650 						continue;
7651 					}
7652 				}
7653 				inscription++;
7654 			}
7655 		}
7656 	}
7657 	//#endif
7658 	/* extract base speed */
7659 	m_ptr->speed = r_ptr->speed;
7660 	/* set cur speed to base speed */
7661 	m_ptr->mspeed = m_ptr->speed;
7662 	m_ptr->ac = r_ptr->ac;
7663 	m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7664 	m_ptr->hp = maxroll(r_ptr->hdice, r_ptr->hside);
7665 	m_ptr->clone = 100;
7666 
7667 	for (i = 0; i < golem_m_arms; i++) {
7668 		m_ptr->blow[i].method = r_ptr->blow[i].method = RBM_HIT;
7669 		m_ptr->blow[i].effect = r_ptr->blow[i].effect = RBE_HURT;
7670 		m_ptr->blow[i].d_dice = r_ptr->blow[i].d_dice = (golem_type + 1) * 3;
7671 		m_ptr->blow[i].d_side = r_ptr->blow[i].d_side = 3 + golem_arms[i];
7672 	}
7673 
7674 	m_ptr->owner = p_ptr->id;
7675 	m_ptr->r_idx = 1 + golem_type;
7676 
7677 	m_ptr->level = p_ptr->lev;
7678 	m_ptr->exp = MONSTER_EXP(m_ptr->level);
7679 
7680 	/* Assume no sleeping */
7681 	m_ptr->csleep = 0;
7682 	wpcopy(&m_ptr->wpos, &p_ptr->wpos);
7683 
7684 	/* No "damage" yet */
7685 	m_ptr->stunned = 0;
7686 	m_ptr->confused = 0;
7687 	m_ptr->monfear = 0;
7688 
7689 	/* No knowledge */
7690 	m_ptr->cdis = 0;
7691 	m_ptr->mind = GOLEM_NONE;
7692 
7693 	/* prevent other players from killing it on accident */
7694 	r_ptr->flags8 |= RF8_NO_AUTORET | RF8_GENO_PERSIST | RF8_GENO_NO_THIN;
7695 	r_ptr->flags7 |= RF7_NO_TARGET;
7696 
7697 	/* Update the monster */
7698 	update_mon(c_ptr->m_idx, TRUE);
7699 }
7700 
7701 /* pernAngband Additions	- Jir - */
call_chaos(int Ind,int dir,int extra_damage)7702 void call_chaos(int Ind, int dir, int extra_damage) {
7703 	player_type *p_ptr = Players[Ind];
7704 	int Chaos_type, dummy;
7705 	int plev = p_ptr->lev;
7706 	bool line_chaos = FALSE;
7707 
7708 	/* determine damage type */
7709 #if 0 /* traditional */
7710 	int hurt_types[29] = { // 30
7711 		GF_ELEC,      GF_POIS,    GF_ACID,    GF_COLD,
7712 		GF_FIRE,      GF_MISSILE, GF_ARROW,   GF_PLASMA,
7713 //		GF_HOLY_FIRE,
7714 		GF_WATER,     GF_LITE,    GF_DARK,
7715 		GF_FORCE,     GF_INERTIA, GF_MANA,    GF_METEOR,
7716 		GF_ICE,       GF_CHAOS,   GF_NETHER,  GF_DISENCHANT,
7717 		GF_SHARDS,    GF_SOUND,   GF_NEXUS,   GF_CONFUSION,
7718 		GF_TIME,      GF_GRAVITY, GF_ROCKET,  GF_NUKE,
7719 		GF_DISINTEGRATE,
7720 		GF_HELL_FIRE,
7721 	};
7722 	Chaos_type = hurt_types[rand_int(29)];
7723 #endif
7724 #if 0 /* redux (blend out 'weaker' types that monsters may be immune to etc) */
7725 	int hurt_types[17] = {
7726 		/* not that much of chaos */
7727 		GF_MISSILE,	GF_SHARDS,	GF_INERTIA,	GF_SOUND,	GF_GRAVITY,
7728 		/* pretty chaossy */
7729 		GF_NEXUS,	GF_TIME,	GF_FORCE,	GF_MANA,
7730 		/* truly chaos */
7731 		GF_CHAOS,	GF_NUKE,	GF_METEOR,	GF_ROCKET,
7732 		GF_INFERNO,	GF_PLASMA,	GF_HELL_FIRE,	GF_DISINTEGRATE,
7733 	};
7734 	Chaos_type = hurt_types[rand_int(17)];
7735 #endif
7736 #if 1 /* redux^2 (only use damage types that deserve to be called chaos (hah)) */
7737 	int hurt_types[12] = {
7738 		/* pretty chaossy */
7739 		GF_NEXUS,	GF_TIME,	GF_FORCE,	GF_MANA,
7740 		/* truly chaos */
7741 		GF_CHAOS,	GF_NUKE,	GF_METEOR,	GF_ROCKET,
7742 		GF_INFERNO,	GF_PLASMA,	GF_HELL_FIRE,	GF_DISINTEGRATE,
7743 	};
7744 	Chaos_type = hurt_types[rand_int(12)];
7745 #endif
7746 
7747 	/* determine shape */
7748 	if (randint(4) == 1) line_chaos = TRUE;
7749 
7750 #if 0
7751 	/* Probably a meaningless line, a remnant from earlier code */
7752 	while (Chaos_type > GF_GRAVITY && Chaos_type < GF_ROCKET);
7753 #endif
7754 
7755 	if (randint(6) == 1) {
7756 		for (dummy = 1; dummy < 10; dummy++) {
7757 			if (dummy - 5) {
7758 				if (line_chaos) {
7759 //					fire_beam(Ind, Chaos_type, dummy, 1500 + extra_damage, p_ptr->attacker);
7760 					fire_beam(Ind, Chaos_type, dummy, 675 + extra_damage, p_ptr->attacker);
7761 				} else {
7762 //					fire_ball(Ind, Chaos_type, dummy, 1500 + extra_damage, 2, p_ptr->attacker);
7763 					fire_ball(Ind, Chaos_type, dummy, 675 + extra_damage, 2, p_ptr->attacker);
7764 				}
7765 			}
7766 		}
7767 	}
7768 	else if (randint(3) == 1) {
7769 //		fire_ball(Ind, Chaos_type, 0, 1500 + extra_damage, 8, p_ptr->attacker);
7770 		fire_ball(Ind, Chaos_type, 0, 675 + extra_damage, 8, p_ptr->attacker);
7771 	} else {
7772 //		if (!get_aim_dir(Ind) return;
7773 		if (line_chaos) {
7774 //			fire_beam(Ind, Chaos_type, dir, 1500 + extra_damage, p_ptr->attacker);
7775 			fire_beam(Ind, Chaos_type, dir, 675 + extra_damage, p_ptr->attacker);
7776 		} else {
7777 //			fire_ball(Ind, Chaos_type, dir, 1500 + extra_damage, 3 + (plev/35), p_ptr->attacker);
7778 			fire_ball(Ind, Chaos_type, dir, 675 + extra_damage, 3 + (plev/35), p_ptr->attacker);
7779 		}
7780 	}
7781 }
7782 
summon_cyber(int Ind,int s_clone,int clone_summoning)7783 bool summon_cyber(int Ind, int s_clone, int clone_summoning) {
7784 	player_type *p_ptr = Players[Ind];
7785 	int i;
7786 	int max_cyber = (getlevel(&p_ptr->wpos)/ 50) + randint(6);
7787 	bool ok = FALSE;
7788 
7789 	for (i = 0; i < max_cyber; i++)
7790 		ok = ok || summon_specific(&p_ptr->wpos, p_ptr->py, p_ptr->px, 100, s_clone, SUMMON_HI_DEMON, 1, clone_summoning);
7791 	return ok;
7792 }
7793 
7794 /* Heal insanity. */
heal_insanity(int Ind,int val)7795 bool heal_insanity(int Ind, int val)
7796 {
7797 	player_type *p_ptr = Players[Ind];
7798 
7799 	if (p_ptr->csane < p_ptr->msane) {
7800 		p_ptr->csane += val;
7801 
7802 		if (p_ptr->csane >= p_ptr->msane) {
7803 			p_ptr->csane = p_ptr->msane;
7804 			p_ptr->csane_frac = 0;
7805 		}
7806 
7807 		p_ptr->update |= PU_SANITY;
7808 		p_ptr->redraw |= PR_SANITY;
7809 		p_ptr->window |= (PW_PLAYER);
7810 
7811 		if (val < (p_ptr->msane/8)) {
7812 			msg_print(Ind, "You feel a little saner.");
7813 		} else if (val < (p_ptr->msane/4)) {
7814 			msg_print(Ind, "You feel saner.");
7815 		} else if (val < (p_ptr->msane/2)) {
7816 			msg_print(Ind, "You feel much saner.");
7817 		} else {
7818 			msg_print(Ind, "You feel very sane.");
7819 		}
7820 
7821 		return TRUE;
7822 	}
7823 
7824 	return FALSE;
7825 }
7826 
do_vermin_control(int Ind)7827 bool do_vermin_control(int Ind) {
7828         dun_level *l_ptr = getfloor(&Players[Ind]->wpos);
7829         if (l_ptr && !(l_ptr->flags1 & LF1_NO_MULTIPLY)) {
7830                 l_ptr->flags1 |= LF1_NO_MULTIPLY;
7831                 msg_print(Ind, "You feel less itchy.");
7832                 return TRUE;
7833         }
7834         return FALSE;
7835 }
7836 
rune_combine(int Ind)7837 void rune_combine(int Ind) {
7838 	player_type *p_ptr = Players[Ind];
7839 
7840 	clear_current(Ind);
7841 
7842 	p_ptr->current_rune = TRUE;
7843 	get_item(Ind, ITH_RUNE);
7844 
7845 	return;
7846 }
7847 
rune_combine_aux(int Ind,int item)7848 void rune_combine_aux(int Ind, int item) {
7849 	player_type *p_ptr = Players[Ind];
7850 
7851 	if (item == p_ptr->current_activation) return; //don't combine the same rune
7852 
7853 	/* Recall the first rune */
7854 	object_type *o_ptr = &p_ptr->inventory[p_ptr->current_activation];
7855 
7856 	/* Store the combining flag */
7857 	s16b e_flags = r_elements[o_ptr->sval].flag;
7858 
7859 	/* Remember the original info */
7860 	byte sval = o_ptr->sval;
7861 	s32b owner = o_ptr->owner;
7862 	byte mode = o_ptr->mode;
7863 	s16b level = o_ptr->level;
7864 	byte discount = o_ptr->discount;
7865 	byte number = o_ptr->number;
7866 	s16b note = o_ptr->note; //keep the incription of the initial rune
7867 
7868 	/* Recall the second rune */
7869 	o_ptr = &p_ptr->inventory[item];
7870 
7871 	/* Sanity */
7872 	if ((o_ptr->sval == sval) //same rune type
7873 	|| (o_ptr->tval != TV_RUNE) //not a rune (obselete)
7874 	|| (o_ptr->sval >= RCRAFT_MAX_ELEMENTS) //not a basic rune (obselete)
7875 	|| (!(o_ptr->level) && !(o_ptr->owner == p_ptr->id))) { //not owned
7876 		msg_format(Ind, "You cannot combine these runes!");
7877 		return;
7878 	}
7879 
7880 	/* Store the combining flag */
7881 	e_flags |= r_elements[o_ptr->sval].flag;
7882 
7883 	/* Lookup resulting rune -- (flags_to_projection) */
7884 	byte i;
7885 	for (i = 0; i < RCRAFT_MAX_PROJECTIONS; i++) {
7886 		if (e_flags == r_projections[i].flags)
7887 			break;
7888 	}
7889 
7890 	/* Store combined item values -- use worst case! */
7891 	level = (o_ptr->level > level) ? o_ptr->level : level;
7892 	discount = (o_ptr->discount > discount) ? o_ptr->discount : discount;
7893 	number = (o_ptr->number < number) ? o_ptr->number : number;
7894 
7895 	/* Destroy the rune stacks in the pack */
7896 	msg_format(Ind, "There is a coupling of magic.");
7897 	inven_item_increase(Ind, p_ptr->current_activation, -number);
7898 	inven_item_increase(Ind, item, -number);
7899 	if (p_ptr->current_activation > item) { //higher value (lower in inventory) first; to preserve indexes
7900 		inven_item_optimize(Ind, p_ptr->current_activation);
7901 		inven_item_optimize(Ind, item);
7902 	} else {
7903 		inven_item_optimize(Ind, item);
7904 		inven_item_optimize(Ind, p_ptr->current_activation);
7905 	}
7906 
7907 	/* Make new stack */
7908 	object_type *q_ptr, forge;
7909 
7910 	/* Default rune template */
7911 	q_ptr = &forge;
7912 	object_wipe(q_ptr);
7913 	invcopy(q_ptr, lookup_kind(TV_RUNE, i));
7914 
7915 	/* Recall original parameters */
7916 	q_ptr->owner = owner;
7917 	q_ptr->mode = mode;
7918 	q_ptr->level = level;
7919 	q_ptr->discount = discount;
7920 	q_ptr->number = number;
7921 	q_ptr->note = note;
7922 
7923 	/* Create the rune stack */
7924 	inven_carry(Ind, q_ptr);
7925 
7926 }
7927 
7928 /* see create_custom_tome_aux() below */
tome_creation(int Ind)7929 void tome_creation(int Ind) {
7930 	player_type *p_ptr = Players[Ind];
7931 
7932 	clear_current(Ind);
7933 
7934 	p_ptr->current_tome_creation = TRUE;
7935 	get_item(Ind, ITH_CUSTOM_TOME);
7936 
7937 	return;
7938 }
7939 
7940 /* add a spell scroll to the player's custom-made tome - C. Blue
7941    Note: pval must be incremented by 1, because first spell
7942    (MANATHRUST) starts at 0, but we use 0 for <not used>
7943    because xtra1..9 are of type 'byte' so we can't use -1. */
tome_creation_aux(int Ind,int item)7944 void tome_creation_aux(int Ind, int item) {
7945 	player_type	*p_ptr = Players[Ind];
7946 	bool		okay = TRUE;
7947 	object_type	*o_ptr, *o2_ptr;
7948 	char		o_name[ONAME_LEN];
7949 	byte		*xtra;
7950 
7951 	/* Get the item (in the pack) */
7952 	if (item >= 0) o_ptr = &p_ptr->inventory[item];
7953 	/* Get the item (on the floor) */
7954 	else o_ptr = &o_list[0 - item];
7955 	/* Get the item (in the pack) */
7956 	if (p_ptr->using_up_item >= 0) o2_ptr = &p_ptr->inventory[p_ptr->using_up_item];
7957 	/* Get the item (on the floor) */
7958 	else o2_ptr = &o_list[0 - p_ptr->using_up_item];
7959 
7960 	/* severe error: custom book no longer there */
7961 	if (o_ptr->tval != TV_BOOK || !is_custom_tome(o_ptr->sval)) {
7962 		/* completely start from scratch (have to re-'activate') */
7963 		msg_print(Ind, "A book's inventory location was changed, please retry!");
7964 		clear_current(Ind); /* <- not required actually */
7965 		return;
7966 	}
7967 
7968 #if 1 /* done in do_cmd_activate already. double-check */
7969 	/* free space left? */
7970 	/* k_info-pval dependant */
7971 	switch (o_ptr->bpval) {
7972 	case 0: okay = FALSE; break;
7973 	case 1: if (o_ptr->xtra1) okay = FALSE; break;
7974 	case 2: if (o_ptr->xtra2) okay = FALSE; break;
7975 	case 3: if (o_ptr->xtra3) okay = FALSE; break;
7976 	case 4: if (o_ptr->xtra4) okay = FALSE; break;
7977 	case 5: if (o_ptr->xtra5) okay = FALSE; break;
7978 	case 6: if (o_ptr->xtra6) okay = FALSE; break;
7979 	case 7: if (o_ptr->xtra7) okay = FALSE; break;
7980 	case 8: if (o_ptr->xtra8) okay = FALSE; break;
7981 	default: if (o_ptr->xtra9) okay = FALSE; break;
7982 	}
7983 	if (!okay) {
7984 		/* completely start from scratch (have to re-'activate') */
7985 		msg_print(Ind, "That book has no blank pages left!");
7986 		clear_current(Ind); /* <- not required actually */
7987 		return;
7988 	}
7989 #endif
7990 
7991 	if (o2_ptr->tval != TV_BOOK || o2_ptr->sval != SV_SPELLBOOK)
7992 	{
7993 		msg_print(Ind, "You can only transcribe a spell scroll!");
7994 		/* restore silyl hack.. */
7995 		p_ptr->using_up_item = item;
7996 		/* try again */
7997 		get_item(Ind, ITH_CUSTOM_TOME);
7998 		return;
7999 	}
8000 
8001 /* for DISCRETE_SPELL_SYSTEM: DSS_EXPANDED_SCROLLS */
8002 //TODO: call Send_spell_request(Ind, item); here if client is not outdated (DSS_EXPANDED_SCROLLS)
8003 
8004 	/* need to actually be able to cast the spell in order to transcribe it! */
8005 	if (exec_lua(Ind, format("return get_level(%d, %d, 50, -50)", Ind, o2_ptr->pval)) < 1) {
8006 		msg_print(Ind, "Your knowledge of that spell is insufficient!");
8007 		/* restore silyl hack.. */
8008 		p_ptr->using_up_item = item;
8009 		/* try again */
8010 		get_item(Ind, ITH_CUSTOM_TOME);
8011 		return;
8012 	}
8013 
8014 	/* check for duplicate entry -> prevent it */
8015 	if (o_ptr->xtra1 == o2_ptr->pval + 1 ||
8016 	    o_ptr->xtra2 == o2_ptr->pval + 1 ||
8017 	    o_ptr->xtra3 == o2_ptr->pval + 1 ||
8018 	    o_ptr->xtra4 == o2_ptr->pval + 1 ||
8019 	    o_ptr->xtra5 == o2_ptr->pval + 1 ||
8020 	    o_ptr->xtra6 == o2_ptr->pval + 1 ||
8021 	    o_ptr->xtra7 == o2_ptr->pval + 1 ||
8022 	    o_ptr->xtra8 == o2_ptr->pval + 1 ||
8023 	    o_ptr->xtra9 == o2_ptr->pval + 1) {
8024 		msg_print(Ind, "The book already contains that spell!");
8025 		/* restore silyl hack.. */
8026 		p_ptr->using_up_item = item;
8027 		/* try again */
8028 		get_item(Ind, ITH_CUSTOM_TOME);
8029 		return;
8030 	}
8031 
8032 	/* - Success finally - */
8033 
8034 	/* Find the next free slot */
8035 	if (!o_ptr->xtra1) xtra = &o_ptr->xtra1;
8036 	else if (!o_ptr->xtra2) xtra = &o_ptr->xtra2;
8037 	else if (!o_ptr->xtra3) xtra = &o_ptr->xtra3;
8038 	else if (!o_ptr->xtra4) xtra = &o_ptr->xtra4;
8039 	else if (!o_ptr->xtra5) xtra = &o_ptr->xtra5;
8040 	else if (!o_ptr->xtra6) xtra = &o_ptr->xtra6;
8041 	else if (!o_ptr->xtra7) xtra = &o_ptr->xtra7;
8042 	else if (!o_ptr->xtra8) xtra = &o_ptr->xtra8;
8043 	else xtra = &o_ptr->xtra9;
8044 
8045 	/* transcribe (add it)! */
8046 	*xtra = o2_ptr->pval + 1;
8047 
8048 	/* Description */
8049 	object_desc(Ind, o_name, o_ptr, FALSE, 0);
8050 	/* Describe */
8051 	msg_format(Ind, "%s %s glow%s brightly!",
8052 	           ((item >= 0) ? "Your" : "The"), o_name,
8053 	           ((o_ptr->number > 1) ? "" : "s"));
8054 
8055 	/* Did we use up an item? */
8056 	if (p_ptr->using_up_item >= 0)
8057 	{
8058 		inven_item_increase(Ind, p_ptr->using_up_item, -1);
8059 		inven_item_describe(Ind, p_ptr->using_up_item);
8060 		inven_item_optimize(Ind, p_ptr->using_up_item);
8061 		p_ptr->using_up_item = -1;
8062 	}
8063 
8064 	/* unstack if our custom book was originally in a pile */
8065         if ((item >= 0) && (o_ptr->number > 1))
8066         {
8067                 /* Make a fake item */
8068                 object_type tmp_obj;
8069                 tmp_obj = *o_ptr;
8070                 tmp_obj.number = 1;
8071 
8072 		/* Restore remaining 'untouched' stack of books */
8073 		*xtra = 0;
8074 
8075                 /* Message */
8076                 msg_print(Ind, "You unstack your book.");
8077 
8078                 /* Unstack the used item */
8079                 o_ptr->number--;
8080                 p_ptr->total_weight -= tmp_obj.weight;
8081                 item = inven_carry(Ind, &tmp_obj);
8082         }
8083 
8084 	/* Window stuff */
8085 	p_ptr->window |= (PW_INVEN);
8086 	p_ptr->notice |= (PN_REORDER);
8087 
8088 	/* Something happened */
8089 	return;
8090 }
8091 
do_mstopcharm(int Ind)8092 void do_mstopcharm(int Ind) {
8093 	player_type *p_ptr = Players[Ind];
8094 	monster_type *m_ptr;
8095 	int m;
8096 
8097 	if (p_ptr->mcharming == 0) return; /* optimization */
8098 
8099 	p_ptr->mcharming = 0;
8100 
8101 	for (m = m_top - 1; m >= 0; m--) {
8102 		m_ptr = &m_list[m_fast[m]];
8103 //		r_ptr = race_inf(m_ptr);
8104 		if (m_ptr->charmedignore && m_ptr->charmedignore == Ind)
8105 			m_ptr->charmedignore = 0;
8106 	}
8107 }
8108 
test_charmedignore(int Ind,int Ind_charmer,monster_race * r_ptr)8109 bool test_charmedignore(int Ind, int Ind_charmer, monster_race *r_ptr) {
8110 	player_type *q_ptr = Players[Ind_charmer];
8111 	int chance = 1, cost = 1;
8112 
8113 	/* non team-mates are not affected (and would cost extra mana) */
8114 	if (Ind != Ind_charmer &&
8115 	    (!player_in_party(q_ptr->party, Ind)))
8116 		return FALSE;
8117 
8118 	/* some monsters show resistance spikes */
8119 	if ((r_ptr->flags2 & RF2_SMART) ||
8120 	    (r_ptr->flags3 & RF3_NO_CONF) ||
8121 	    (r_ptr->flags1 & RF1_UNIQUE) ||
8122 	    (r_ptr->flags2 & RF2_POWERFUL)) {
8123 		chance++;
8124 		cost++;
8125 	}
8126 
8127 	/* especially costly? */
8128 	if (r_ptr->level > (q_ptr->lev * 7) / 5)
8129 		cost++;
8130 
8131 	/* spell continuously burns mana! */
8132 	if (turn % (cfg.fps / 10) == 0) {
8133 		if (q_ptr->csp < 1) {
8134 			do_mstopcharm(Ind_charmer);
8135 			return FALSE;
8136 		}
8137 		q_ptr->csp -= 1;
8138 		q_ptr->redraw |= PR_MANA;
8139 	}
8140 
8141 	/* the charm-caster himself is pretty safe */
8142 	if (Ind == Ind_charmer && magik(100 - chance))
8143 		return TRUE;
8144 	/* in same party?= slightly reduced effect >:) */
8145 	if (magik(99 - 2 * chance))
8146 		return TRUE;
8147 
8148 	return FALSE;
8149 }
8150 
8151 /* Add certain flags to a ball/breath/cloud projection depending on the damage type. */
mod_ball_spell_flags(int typ,u32b flags)8152 u32b mod_ball_spell_flags(int typ, u32b flags) {
8153 	switch (typ) {
8154 	/* stuff that also acts on the casting player himself */
8155 	case GF_HEAL_PLAYER:
8156 	case GF_HEALINGCLOUD:
8157 		return (flags | PROJECT_PLAY);
8158 	/* 'environmentally instant' stuff */
8159 	case GF_SOUND:
8160 	case GF_CONFUSION:
8161 	case GF_INERTIA:
8162 	case GF_TIME:
8163 	case GF_GRAVITY:
8164 	case GF_STUN:
8165 	case GF_PSI:
8166 	case GF_UNBREATH:
8167 	case GF_THUNDER:
8168 	case GF_ANNIHILATION:
8169 		return (flags | PROJECT_LODF);
8170 	/* very powerful 'force' stuff */
8171 	case GF_FORCE:
8172 	case GF_METEOR:
8173 	case GF_INFERNO:
8174 	case GF_DETONATION:
8175 	case GF_ROCKET:
8176 	case GF_WAVE:
8177 		return (flags | PROJECT_LODF);
8178 	}
8179 	return flags;
8180 }
8181