1 /* $Id$ */
2 /* File: cave.c */
3 
4 /* Purpose: low level dungeon routines -BEN- */
5 
6 #define SERVER
7 
8 #include "angband.h"
9 
10 /*
11  * monsters with 'RF1_ATTR_MULTI' uses colour according to their
12  * breath if it is on. (possible bottleneck, tho)
13  */
14 #define MULTI_HUED_PROPER
15 
16 /* View_shade_floor really shades all floor types, not just FEAT_FLOOR.
17    For this, the floor feats must have SPECIAL_LITE flag (or LAMP_LITE).
18    This usually doesn't look as cool as you might expect. - C. Blue
19    Note: This overrides NO_SHADE flag. */
20 //#define SHADE_ALL_FLOOR
21 
22 /* Don't shade self-illuminated grids that are out of view, if they are on the
23    world surface and it's night time.
24    Primary idea: Shop entrance areas don't get partially shaded with slate tone
25    when player circles around them. It looked a little bit odd maybe. */
26 #define DONT_SHADE_GLOW_AT_NIGHT
27 
28 /*
29  * Scans for cave_type array pointer.
30  * Returns cave array relative to the dimensions
31  * specified in the arguments. Returns NULL for
32  * a failure.
33  */
getcave(struct worldpos * wpos)34 cave_type **getcave(struct worldpos *wpos)
35 {
36 	struct wilderness_type *wild;
37 	wild = &wild_info[wpos->wy][wpos->wx];
38 	if (wpos->wx > MAX_WILD_X || wpos->wx < 0 || wpos->wy > MAX_WILD_Y || wpos->wy < 0) return(NULL);
39 	if (wpos->wz == 0) {
40 		return(wild->cave);
41 	} else {
42 		if (wpos->wz > 0) {
43 			if (wild->tower && wpos->wz <= wild->tower->maxdepth) {
44 				return(wild->tower->level[wpos->wz-1].cave);
45 			}
46 		}
47 		else if (wild->dungeon && wpos->wz >= -wild->dungeon->maxdepth)
48 			return(wild->dungeon->level[ABS(wpos->wz)-1].cave);
49 	}
50 	return ((cave_type **)NULL);
51 }
52 
53 /* an afterthought - it is often needed without up/down info */
getdungeon(struct worldpos * wpos)54 struct dungeon_type *getdungeon(struct worldpos *wpos)
55 {
56 	struct wilderness_type *wild;
57 	wild = &wild_info[wpos->wy][wpos->wx];
58 	if (wpos->wz == 0) return NULL;
59 	else {
60 		if ((wpos->wz > 0) && !wild->tower) return NULL;
61 		if ((wpos->wz < 0) && !wild->dungeon) return NULL;
62 		return(wpos->wz > 0 ? wild->tower : wild->dungeon);
63 	}
64 }
65 
66 /* another afterthought - it is often needed without up/down info */
getfloor(struct worldpos * wpos)67 struct dun_level *getfloor(struct worldpos *wpos)
68 {
69 	struct wilderness_type *wild;
70 	wild = &wild_info[wpos->wy][wpos->wx];
71 	if (wpos->wz == 0) {
72 /*		return(wild); */
73 		return(NULL);
74 	} else {
75 		if (wpos->wz > 0)
76 			return(&wild->tower->level[wpos->wz - 1]);
77 		else
78 			return(&wild->dungeon->level[ABS(wpos->wz) - 1]);
79 	}
80 }
81 
new_level_up_x(struct worldpos * wpos,int pos)82 void new_level_up_x(struct worldpos *wpos, int pos)
83 {
84 	struct wilderness_type *wild;
85 	wild = &wild_info[wpos->wy][wpos->wx];
86 	if (wpos->wz == 0) wild->up_x = pos;
87 	else if (wpos->wz > 0)
88 		wild->tower->level[wpos->wz - 1].up_x = pos;
89 	else
90 		wild->dungeon->level[ABS(wpos->wz) - 1].up_x = pos;
91 }
new_level_up_y(struct worldpos * wpos,int pos)92 void new_level_up_y(struct worldpos *wpos, int pos)
93 {
94 	struct wilderness_type *wild;
95 	wild = &wild_info[wpos->wy][wpos->wx];
96 	if (wpos->wz == 0) wild->up_y = pos;
97 	else if (wpos->wz > 0)
98 		wild->tower->level[wpos->wz - 1].up_y = pos;
99 	else
100 		wild->dungeon->level[ABS(wpos->wz) - 1].up_y = pos;
101 }
new_level_down_x(struct worldpos * wpos,int pos)102 void new_level_down_x(struct worldpos *wpos, int pos)
103 {
104 	struct wilderness_type *wild;
105 	wild = &wild_info[wpos->wy][wpos->wx];
106 	if (wpos->wz == 0) wild->dn_x = pos;
107 	else if (wpos->wz > 0)
108 		wild->tower->level[wpos->wz - 1].dn_x = pos;
109 	else
110 		wild->dungeon->level[ABS(wpos->wz) - 1].dn_x = pos;
111 }
new_level_down_y(struct worldpos * wpos,int pos)112 void new_level_down_y(struct worldpos *wpos, int pos)
113 {
114 	struct wilderness_type *wild;
115 	wild = &wild_info[wpos->wy][wpos->wx];
116 	if (wpos->wz == 0) wild->dn_y = pos;
117 	else if (wpos->wz > 0)
118 		wild->tower->level[wpos->wz - 1].dn_y = pos;
119 	else
120 		wild->dungeon->level[ABS(wpos->wz) - 1].dn_y = pos;
121 }
new_level_rand_x(struct worldpos * wpos,int pos)122 void new_level_rand_x(struct worldpos *wpos, int pos)
123 {
124 	struct wilderness_type *wild;
125 	wild = &wild_info[wpos->wy][wpos->wx];
126 	if (wpos->wz == 0) wild->rn_x = pos;
127 	else if (wpos->wz > 0)
128 		wild->tower->level[wpos->wz - 1].rn_x = pos;
129 	else
130 		wild->dungeon->level[ABS(wpos->wz) - 1].rn_x = pos;
131 }
new_level_rand_y(struct worldpos * wpos,int pos)132 void new_level_rand_y(struct worldpos *wpos, int pos)
133 {
134 	struct wilderness_type *wild;
135 	wild = &wild_info[wpos->wy][wpos->wx];
136 	if (wpos->wz == 0) wild->rn_y = pos;
137 	else if (wpos->wz > 0)
138 		wild->tower->level[wpos->wz - 1].rn_y = pos;
139 	else
140 		wild->dungeon->level[ABS(wpos->wz) - 1].rn_y = pos;
141 }
142 
level_up_x(struct worldpos * wpos)143 byte level_up_x(struct worldpos *wpos)
144 {
145 	struct wilderness_type *wild;
146 	wild = &wild_info[wpos->wy][wpos->wx];
147 	if (wpos->wz == 0) return (wild->up_x);
148 	return (wpos->wz > 0? wild->tower->level[wpos->wz - 1].up_x : wild->dungeon->level[ABS(wpos->wz) - 1].up_x);
149 }
level_up_y(struct worldpos * wpos)150 byte level_up_y(struct worldpos *wpos)
151 {
152 	struct wilderness_type *wild;
153 	wild = &wild_info[wpos->wy][wpos->wx];
154 	if (wpos->wz == 0) return (wild->up_y);
155 	return (wpos->wz > 0 ? wild->tower->level[wpos->wz - 1].up_y : wild->dungeon->level[ABS(wpos->wz) - 1].up_y);
156 }
level_down_x(struct worldpos * wpos)157 byte level_down_x(struct worldpos *wpos)
158 {
159 	struct wilderness_type *wild;
160 	wild = &wild_info[wpos->wy][wpos->wx];
161 	if (wpos->wz == 0) return (wild->dn_x);
162 	return(wpos->wz > 0 ? wild->tower->level[wpos->wz - 1].dn_x : wild->dungeon->level[ABS(wpos->wz) - 1].dn_x);
163 }
level_down_y(struct worldpos * wpos)164 byte level_down_y(struct worldpos *wpos)
165 {
166 	struct wilderness_type *wild;
167 	wild = &wild_info[wpos->wy][wpos->wx];
168 	if (wpos->wz == 0) return (wild->dn_y);
169 	return (wpos->wz > 0 ? wild->tower->level[wpos->wz - 1].dn_y : wild->dungeon->level[ABS(wpos->wz) - 1].dn_y);
170 }
level_rand_x(struct worldpos * wpos)171 byte level_rand_x(struct worldpos *wpos)
172 {
173 	struct wilderness_type *wild;
174 	wild = &wild_info[wpos->wy][wpos->wx];
175 	if (wpos->wz == 0) return(wild->rn_x);
176 	return (wpos->wz > 0 ? wild->tower->level[wpos->wz - 1].rn_x : wild->dungeon->level[ABS(wpos->wz) - 1].rn_x);
177 }
level_rand_y(struct worldpos * wpos)178 byte level_rand_y(struct worldpos *wpos)
179 {
180 	struct wilderness_type *wild;
181 	wild = &wild_info[wpos->wy][wpos->wx];
182 	if (wpos->wz == 0) return (wild->rn_y);
183 	return (wpos->wz > 0 ? wild->tower->level[wpos->wz - 1].rn_y : wild->dungeon->level[ABS(wpos->wz) - 1].rn_y);
184 }
185 
get_staircase_colour(dungeon_type * d_ptr,byte * c)186 static int get_staircase_colour(dungeon_type *d_ptr, byte *c) {
187 	/* (experimental testing stuff) */
188 	if (d_ptr->flags3 & (DF3_NO_TELE | DF3_NO_ESP | DF3_LIMIT_ESP | DF3_NO_SUMMON)) {
189 		*c = TERM_L_UMBER;
190 		return 0;
191 	}
192 
193 	/* override colour from easiest to worst */
194 	/* joker overrides the king ;) */
195 	if (d_ptr->flags2 & DF2_NO_DEATH) {
196 		*c = TERM_GREEN;
197 		return -1;
198 	}
199 
200 	if (d_ptr->flags2 & DF2_NO_EXIT_WOR) {
201 		if ((d_ptr->flags2 & DF2_IRON) || (d_ptr->flags1 & (DF1_FORCE_DOWN | DF1_NO_UP))) {
202 			*c = TERM_DARKNESS;
203 			return 7;
204 		}
205 	}
206 	if ((d_ptr->flags2 & DF2_NO_EXIT_STAIR)
207 	    && (d_ptr->flags2 & DF2_NO_EXIT_PROB)
208 	    && (d_ptr->flags2 & DF2_NO_EXIT_FLOAT)
209 	    && (d_ptr->flags2 & DF2_NO_EXIT_WOR)) {
210 		*c = TERM_DARKNESS;
211 		return 7;
212 	}
213 
214 	if (d_ptr->flags2 & DF2_IRON) {
215 		*c = TERM_L_DARK;
216 		return 6;
217 	}
218 	if (d_ptr->flags2 & DF2_HELL) {
219 		*c = TERM_FIRE;
220 		return 5;
221 	}
222 	if (d_ptr->flags1 & DF1_FORCE_DOWN) {
223 		*c = TERM_L_RED;
224 		return 4;
225 	}
226 	if (d_ptr->flags1 & DF1_NO_RECALL) {
227 		*c = TERM_RED;
228 		return 3;
229 	}
230 	if (d_ptr->flags1 & DF1_NO_UP) {
231 		*c = TERM_ORANGE;
232 		return 2;
233 	}
234 	if (d_ptr->flags2 & DF2_NO_RECALL_INTO) {
235 		*c = TERM_YELLOW;
236 		return 1;
237 	}
238 
239 	/* normal */
240 	*c = TERM_WHITE;
241 	return 0;
242 }
243 
244 /* For staircase-placement.
245    Mode: 1 stairs, (doesn't make sense? 2 wor,) (handled in cmd2.c, can't handle here actually: 4 probtravel, 8 ghostfloating) */
can_go_up(struct worldpos * wpos,byte mode)246 bool can_go_up(struct worldpos *wpos, byte mode)
247 {
248         struct wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
249 
250         struct dungeon_type *d_ptr = wild->tower;
251 	if (wpos->wz < 0) d_ptr = wild->dungeon;
252 
253 #if 0 /* fixed (old /update-dun killed flags2) */
254 	/* paranoia, but caused panic: in wilderness_gen() cmd_up({0,0,0},0x1) would return 1
255 	   resulting in bad up/down values for staircase generation when it attempts to locate
256 	   a staircase leading into pvp-arena and put some feats around it (at coords 0,0 ...).
257 	   Apparently, WILD_F_UP is set here, too. And even w_ptr->tower was also valid.
258 	   todo: fix this. -C. Blue */
259 	if (wpos->wz == 0 && wpos->wx == WPOS_PVPARENA_X && wpos->wy == WPOS_PVPARENA_Y &&
260 	    WPOS_PVPARENA_Z > 0) return (FALSE);
261 #endif
262 
263 	/* Check for empty staircase without any connected dungeon/tower! */
264 	if (!d_ptr) return((wild->flags&WILD_F_UP)?TRUE:FALSE); /* you MAY create 'empty' staircase */
265 
266 	if (mode & 0x1) {
267 		if (!wpos->wz && (d_ptr->flags2 & DF2_NO_ENTRY_STAIR)) return(FALSE);
268 		if (wpos->wz == -1 && (d_ptr->flags2 & DF2_NO_EXIT_STAIR)) return(FALSE);
269 		if (wpos->wz && (d_ptr->flags2 & DF2_NO_STAIRS_UP)) return(FALSE);
270 	}
271 
272 	if (wpos->wz<0) {
273 		if ((d_ptr->flags1 & (DF1_NO_UP | DF1_FORCE_DOWN)) ||
274 		    (d_ptr->flags2 & DF2_IRON))
275 			return(FALSE);
276 		return(TRUE);
277 	}
278 
279 	if (wpos->wz>0) return(wpos->wz < wild->tower->maxdepth);
280 
281 	return((wild->flags&WILD_F_UP)?TRUE:FALSE);
282 }
283 /* For staircase-placement and sinking/pit traps.
284    Mode: 1 stairs, (doesn't make sense? 2 wor,) (handled in cmd2.c, can't handle here actually: 4 probtravel, 8 ghostfloating) */
can_go_down(struct worldpos * wpos,byte mode)285 bool can_go_down(struct worldpos *wpos, byte mode)
286 {
287         struct wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
288 
289         struct dungeon_type *d_ptr = wild->dungeon;
290         if (wpos->wz > 0) d_ptr = wild->tower;
291 
292 #if 0 /* fixed (old /update-dun killed flags2) */
293 	/* paranoia, but caused panic: in wilderness_gen() cmd_up({0,0,0},0x1) would return 1
294 	   resulting in bad up/down values for staircase generation when it attempts to locate
295 	   a staircase leading into pvp-arena and put some feats around it (at coords 0,0 ...).
296 	   Apparently, WILD_F_UP is set here, too. And even w_ptr->tower was also valid.
297 	   todo: fix this. -C. Blue */
298 	if (wpos->wz == 0 && wpos->wx == WPOS_PVPARENA_X && wpos->wy == WPOS_PVPARENA_Y &&
299 	    WPOS_PVPARENA_Z < 0) return (FALSE);
300 #endif
301 
302 	/* Check for empty staircase without any connected dungeon/tower! */
303 	if (!d_ptr) return((wild->flags&WILD_F_DOWN)?TRUE:FALSE); /* you MAY create 'empty' staircase */
304 
305 	if (mode & 0x1) {
306 		if (!wpos->wz && (d_ptr->flags2 & DF2_NO_ENTRY_STAIR)) return(FALSE);
307 		if (wpos->wz == 1 && (d_ptr->flags2 & DF2_NO_EXIT_STAIR)) return(FALSE);
308 		if (wpos->wz && (d_ptr->flags2 & DF2_NO_STAIRS_DOWN)) return(FALSE);
309 	}
310 
311 	if (wpos->wz>0) {
312 		if ((d_ptr->flags1 & (DF1_NO_UP | DF1_FORCE_DOWN)) ||
313 		    (d_ptr->flags2 & DF2_IRON)) return(FALSE);
314 		return(TRUE);
315 	}
316 
317 	if (wpos->wz<0) return(ABS(wpos->wz) < wild->dungeon->maxdepth);
318 
319 	return((wild->flags&WILD_F_DOWN)?TRUE:FALSE);
320 }
321 /* ignore all dungeon/floor flags */
can_go_up_simple(struct worldpos * wpos)322 bool can_go_up_simple(struct worldpos *wpos)
323 {
324         struct wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
325 	if (wpos->wz < 0) return(TRUE);
326 	if (wpos->wz > 0) return(wpos->wz < wild->tower->maxdepth);
327 	return ((wild->flags & WILD_F_UP) ? TRUE : FALSE);
328 }
329 /* ignore all dungeon/floor flags */
can_go_down_simple(struct worldpos * wpos)330 bool can_go_down_simple(struct worldpos *wpos)
331 {
332         struct wilderness_type *wild = &wild_info[wpos->wy][wpos->wx];
333 	if (wpos->wz > 0) return(TRUE);
334 	if (wpos->wz < 0) return(ABS(wpos->wz) < wild->dungeon->maxdepth);
335 	return ((wild->flags & WILD_F_DOWN) ? TRUE : FALSE);
336 }
337 
wpcopy(struct worldpos * dest,struct worldpos * src)338 void wpcopy(struct worldpos *dest, struct worldpos *src)
339 {
340 	dest->wx = src->wx;
341 	dest->wy = src->wy;
342 	dest->wz = src->wz;
343 }
344 
update_uniques_killed(struct worldpos * wpos)345 static void update_uniques_killed(struct worldpos *wpos)
346 {
347 	int i, j;
348 	player_type *p_ptr;
349 	dun_level *l_ptr;
350 
351 	/* Update the list of uniques that have been killed by all players on the level */
352 	l_ptr = getfloor(wpos);
353 
354 	if (l_ptr && l_ptr->uniques_killed) {
355 		int admins = 0, players = 0;
356 
357 		for (i = 1; i <= NumPlayers; i++) {
358 			p_ptr = Players[i];
359 
360 			/* Skip disconnected players */
361 			if (p_ptr->conn == NOT_CONNECTED)
362 				continue;
363 
364 			/* Player on this depth? */
365 			if (!inarea(&p_ptr->wpos, wpos))
366 				continue;
367 
368 			/* Count the admins and non-admins */
369 			if (admin_p(i)) admins++;
370 			else players++;
371 		}
372 
373 		if (admins || players) {
374 			for (j = 1; j < MAX_R_IDX; j++) {
375 				monster_race *r_ptr = &r_info[j];
376 
377 				if (r_ptr->flags1 & RF1_UNIQUE) {
378 					/* Assume that the unique has been killed unless a player has killed it */
379 					l_ptr->uniques_killed[j] = TRUE;
380 
381 					for (i = 1; i <= NumPlayers; i++) {
382 						p_ptr = Players[i];
383 
384 						/* Skip disconnected players */
385 						if (p_ptr->conn == NOT_CONNECTED)
386 							continue;
387 
388 						/* Player on this depth? */
389 						if (!inarea(&p_ptr->wpos, wpos))
390 							continue;
391 
392 						/* Ignore admins if players are on the level */
393 						if (players && admin_p(i))
394 							continue;
395 
396 						/* Check that every player has killed the unique */
397 						l_ptr->uniques_killed[j] = l_ptr->uniques_killed[j] && p_ptr->r_killed[j] == 1;
398 					}
399 				}
400 			}
401 		} else {
402 			/* No players around, no restrictions */
403 			C_WIPE(l_ptr->uniques_killed, MAX_R_IDX, char);
404 		}
405 	}
406 }
407 
new_players_on_depth(struct worldpos * wpos,int value,bool inc)408 void new_players_on_depth(struct worldpos *wpos, int value, bool inc) {
409 	struct wilderness_type *w_ptr;
410 	time_t now;
411 
412 	int henc = 0, henc_top = 0, i;
413 	player_type *p_ptr;
414 	monster_type *m_ptr;
415 
416 	object_type *o_ptr;
417 	char o_name[ONAME_LEN];
418 
419 	cave_type **zcave;
420 	bool flag = FALSE;
421 	if ((zcave = getcave(wpos))) flag = TRUE;
422 
423 	now = time(&now);
424 
425 	w_ptr = &wild_info[wpos->wy][wpos->wx];
426 #if DEBUG_LEVEL > 2
427 		s_printf("new_players_on_depth.. %s  now:%d value:%d inc:%s\n", wpos_format(0, wpos), now, value, inc?"TRUE":"FALSE");
428 #endif
429 	if (in_valinor(wpos)) {
430 		for (i = 1; i <= NumPlayers; i++) {
431 			p_ptr = Players[i];
432 			if (p_ptr->conn == NOT_CONNECTED) continue;
433 			if (admin_p(i)) continue;
434 			if (inarea(&p_ptr->wpos, wpos)) s_printf("%s VALINOR: Player %s is here.\n", showtime(), p_ptr->name);
435 		}
436 	}
437 
438         /* Page all dungeon masters to notify them of a Nether Realm breach >:) - C. Blue */
439 	if (value > 0) {
440 		if (watch_nr && in_netherrealm(wpos)) {
441 			for (i = 1; i <= NumPlayers; i++) {
442 				if (Players[i]->conn == NOT_CONNECTED) continue;
443 				if (Players[i]->admin_dm && !Players[i]->afk) Players[i]->paging = 2;
444 			}
445 		} else if (watch_cp && wpos->wz && getdungeon(wpos)->type == DI_CLOUD_PLANES) {
446 			for (i = 1; i <= NumPlayers; i++) {
447 				if (Players[i]->conn == NOT_CONNECTED) continue;
448 				if (Players[i]->admin_dm && !Players[i]->afk) Players[i]->paging = 2;
449 			}
450 		}
451 	}
452 
453 	if (wpos->wz) {
454 		struct dungeon_type *d_ptr;
455 		struct dun_level *l_ptr;
456 		if (wpos->wz > 0)
457 			d_ptr = wild_info[wpos->wy][wpos->wx].tower;
458 		else
459 			d_ptr = wild_info[wpos->wy][wpos->wx].dungeon;
460 
461 
462 		l_ptr = &d_ptr->level[ABS(wpos->wz) - 1];
463 
464 		l_ptr->ondepth = (inc ? l_ptr->ondepth + value : value);
465 		if (l_ptr->ondepth < 0) l_ptr->ondepth = 0;
466 
467 		if (!l_ptr->ondepth) l_ptr->lastused = 0;
468 		if (value > 0) l_ptr->lastused = now;
469 	} else {
470 		w_ptr->ondepth = (inc ? w_ptr->ondepth + value : value);
471 		if (w_ptr->ondepth < 0) w_ptr->ondepth = 0;
472 		if (!w_ptr->ondepth) w_ptr->lastused = 0;
473 		if (value > 0) w_ptr->lastused = now;
474 		/* remove 'deposited' true artefacts if last player leaves a level,
475 		   and if true artefacts aren't allowed to be stored (in houses for example) */
476 		if (!w_ptr->ondepth && cfg.anti_arts_wild) {
477 			for (i = 0; i < o_max; i++) {
478 				o_ptr = &o_list[i];
479 				if (o_ptr->k_idx && inarea(&o_ptr->wpos, wpos) &&
480 				    undepositable_artifact_p(o_ptr)) {
481 					object_desc(0, o_name, o_ptr, FALSE, 0);
482 					s_printf("WILD_ART: %s of %s erased at (%d, %d, %d)\n",
483 					    o_name, lookup_player_name(o_ptr->owner), o_ptr->wpos.wx, o_ptr->wpos.wy, o_ptr->wpos.wz);
484 					handle_art_d(o_ptr->name1);
485 					if (flag && in_bounds_array(o_ptr->iy, o_ptr->ix))
486 						zcave[o_ptr->iy][o_ptr->ix].o_idx = 0;
487 					WIPE(o_ptr, object_type);
488 				}
489 			}
490 		}
491 	}
492 
493 	update_uniques_killed(wpos);
494 
495 	/* Perform henc_strictness anti-cheeze - mode 4 : monster is on the same dungeon level as a player */
496 	/* If a player enters a new level */
497 	if ((value <= 0) || (cfg.henc_strictness < 4)) return;
498 	if (in_bree(wpos)) return; /* not in Bree, because of Halloween :) */
499 
500 	/* Who is the highest player around? */
501 	for (i = 1; i <= NumPlayers; i++) {
502 		p_ptr = Players[i];
503 
504 		/* skip disconnected players */
505 		if (p_ptr->conn == NOT_CONNECTED)
506 			continue;
507 
508 		/* skip admins */
509 		if (admin_p(i)) continue;
510 
511 		/* player on this depth? */
512 		if (!inarea(&p_ptr->wpos, wpos)) continue;
513 
514 		if (henc < p_ptr->max_lev) henc = p_ptr->max_lev;
515 		if (henc_top < (p_ptr->max_lev + p_ptr->max_plv) / 2) henc_top = (p_ptr->max_lev + p_ptr->max_plv) / 2;
516 		if (henc < p_ptr->supp) henc = p_ptr->supp;
517 		if (henc_top < (p_ptr->max_lev + p_ptr->supp_top) / 2) henc_top = (p_ptr->max_lev + p_ptr->supp_top) / 2;
518 	}
519 
520 	/* Process the monsters, check against the highest player around */
521 	for (i = m_top - 1; i >= 0; i--) {
522 		/* Access the monster */
523 		m_ptr = &m_list[m_fast[i]];
524 
525 		/* On this level? Test its highest encounter so far */
526 		if (!inarea(&m_ptr->wpos, wpos)) continue;
527 
528 		if (m_ptr->henc < henc) m_ptr->henc = henc;
529 		if (m_ptr->henc_top < henc_top) m_ptr->henc_top = henc_top;
530 	}
531 }
532 
533 
check_Pumpkin(void)534 void check_Pumpkin(void) {
535 	int k, i, m_idx;
536 	struct worldpos *wpos;
537 	char msg[80];
538 	player_type *p_ptr;
539 	monster_type *m_ptr;
540 
541 	/* only during Halloween! */
542 	if (!season_halloween) return;
543 
544 	/* Process the monsters */
545 	for (k = m_top - 1; k >= 0; k--) {
546 		/* Access the index */
547 		m_idx = m_fast[k];
548 		/* Access the monster */
549 		m_ptr = &m_list[m_idx];
550 		/* Excise "dead" monsters */
551 		if (!m_ptr->r_idx) {
552 		        /* Excise the monster */
553 			m_fast[k] = m_fast[--m_top];
554 		        /* Skip */
555 		        continue;
556 		}
557 
558 		/* Players of too high level cannot participate in killing attemps (anti-cheeze) */
559 		/* search for Great Pumpkins */
560 		if (m_ptr->r_idx == RI_PUMPKIN1 || m_ptr->r_idx == RI_PUMPKIN2 || m_ptr->r_idx == RI_PUMPKIN3) {
561 			wpos = &m_ptr->wpos;
562 
563 			/* Exception for IDDC - just allow */
564 			if (in_irondeepdive(wpos)) continue;
565 
566 			for (i = 1; i <= NumPlayers; i++) {
567 				p_ptr = Players[i];
568 				if (is_admin(p_ptr)) continue;
569 				if (inarea(&p_ptr->wpos, wpos) &&
570 #if 0
571  #ifndef RPG_SERVER
572 				    (p_ptr->max_lev > 30))
573  #else
574 				    (p_ptr->max_lev > 40))
575  #endif
576 #else
577  #ifndef RPG_SERVER
578 				    (p_ptr->max_lev > 35))
579  #else
580 				    (p_ptr->max_lev > 40))
581  #endif
582 #endif
583 				{
584 					sprintf(msg, "\377oA ghostly force drives you out of this dungeon!");
585 					/* log */
586 #ifndef RPG_SERVER
587 					s_printf("HALLOWEEN: Recalled>35: %s\n", p_ptr->name);
588 #else
589 					s_printf("HALLOWEEN: Recalled>40: %s\n", p_ptr->name);
590 #endif
591 					/* get him out of here */
592 					p_ptr->new_level_method = (p_ptr->wpos.wz > 0 ? LEVEL_RECALL_DOWN : LEVEL_RECALL_UP);
593 					p_ptr->recall_pos.wx = p_ptr->wpos.wx;
594 					p_ptr->recall_pos.wy = p_ptr->wpos.wy;
595 					p_ptr->recall_pos.wz = 0;
596 //					p_ptr->word_recall =- 666;/*HACK: avoid recall_player loops! */
597 					recall_player(i, msg);
598 				}
599 			}
600 		}
601 	}
602 }
603 
604 /* This lets Morgoth become stronger, weaker or teleport himself away if
605  * a King/Queen joins his level or if a player enters it who hasn't killed
606  * Sauron, the Sorceror yet - C. Blue
607  */
check_Morgoth(int Ind)608 void check_Morgoth(int Ind)
609 {
610 	int k, i, x, y, num_on_depth = 0, m_idx;
611 	s32b tmphp;
612 	struct worldpos *wpos;
613 	char msg[80];
614 	player_type *p_ptr;
615 	monster_type *m_ptr;
616 
617 
618 	if (season_halloween) check_Pumpkin();
619 
620 
621 	/* Let Morgoth, Lord of Darkness gain additional power
622 	for each player who joins the depth */
623 
624 	/* Process the monsters */
625 	for (k = m_top - 1; k >= 0; k--) {
626 		/* Access the index */
627 		m_idx = m_fast[k];
628 		/* Access the monster */
629 		m_ptr = &m_list[m_idx];
630 		/* Excise "dead" monsters */
631 		if (!m_ptr->r_idx) {
632 		        /* Excise the monster */
633 	    		m_fast[k] = m_fast[--m_top];
634 		        /* Skip */
635 		        continue;
636 		}
637 
638 		/* search for Morgy */
639 		if (m_ptr->r_idx != RI_MORGOTH) continue;
640 		wpos = &m_ptr->wpos;
641 
642 		/* check if players are on his depth */
643 		num_on_depth = 0;
644 		for (i = 1; i <= NumPlayers; i++) {
645 			/* skip disconnected players */
646 			if (Players[i]->conn == NOT_CONNECTED) continue;
647 			/* skip admins */
648 			if (admin_p(i)) continue;
649 			/* player on this depth? */
650 			p_ptr = Players[i];
651 			if (inarea(&p_ptr->wpos, wpos)) num_on_depth++;
652 		}
653 
654 		/* if the last player leaves, don't reduce Morgy's power */
655 		if (num_on_depth == 0) continue;
656 
657 		/* Page all dungeon masters to notify them of a possible Morgoth-fight >:) - C. Blue */
658 		if (watch_morgoth
659 		    /* new: only page if a player actually entered Morgoth's level */
660 		    && Ind && inarea(&Players[Ind]->wpos, wpos))
661 			for (i = 1; i <= NumPlayers; i++) {
662 				if (Players[i]->conn == NOT_CONNECTED) continue;
663 				if (Players[i]->admin_dm && !(Players[i]->afk && !streq(Players[i]->afk_msg, "watch"))) Players[i]->paging = 4;
664 			}
665 
666 		/* save coordinates to redraw the spot after deletion later */
667 		x = m_ptr->fx;
668 		y = m_ptr->fy;
669 
670 		/* If a King/Queen or a Sauron-missing player enters Morgy's level:
671 		   if there was an allowed player already on the level, the bad player
672 		   will be insta-recalled to town. Otherwise, Morgy will be removed.
673 		   Invalid player alone with Morgy?: Yes->Remove Morgy, No->recall */
674 		for (i = 1; i <= NumPlayers; i++) {
675 			if (Players[i]->conn == NOT_CONNECTED) continue;
676 			p_ptr = Players[i];
677 			if (is_admin(p_ptr)) continue;
678 
679 			if (inarea(&p_ptr->wpos, wpos) &&
680 			    ((p_ptr->mode & MODE_PVP) || p_ptr->total_winner || (p_ptr->r_killed[RI_SAURON] != 1)))
681 			{
682 				/* Replace Morgoth with Sauron if Sauron is missing,
683 				   the other two cases have no repercussions for now -- just allow - C. Blue */
684 				if (in_irondeepdive(&p_ptr->wpos)) {
685 					if (p_ptr->r_killed[RI_SAURON] != 1) {
686 						dun_level *l_ptr = getfloor(wpos);
687 
688 						/* remove morgy here */
689 						delete_monster_idx(k, TRUE); /* careful, 'wpos' is now zero'ed */
690 						l_ptr->flags1 &= ~LF1_NO_GHOST;
691 
692 						/* notifications */
693 						sprintf(msg, "\377sMorgoth, Lord of Darkness summons Sauron, the Sorceror, and teleports out!");
694 						for (i = 1; i <= NumPlayers; i++) {
695 							if (Players[i]->conn == NOT_CONNECTED) continue;
696 							/* Player on Morgy depth? */
697 							if (inarea(&Players[i]->wpos, &p_ptr->wpos)) {
698 								msg_print(i, msg);
699 								handle_music(i); /* :-o */
700 							}
701 						}
702 						s_printf("Morgoth left level (inserting Sauron) due to %s\n", p_ptr->name);
703 
704 						/* place Sauron so players can kill him first */
705 						summon_override_checks = SO_ALL; /* (SO_IDDC?) */
706 						place_monster_one(&p_ptr->wpos, y, x, RI_SAURON, FALSE, FALSE, FALSE, 0, 0);
707 						summon_override_checks = SO_NONE;
708 
709 	                        	    	/* Notice */
710 	    		        	        note_spot_depth(&p_ptr->wpos, y, x);
711 			                        /* Display */
712 		                                everyone_lite_spot(&p_ptr->wpos, y, x);
713 					}
714 					/* the rest is allowed..
715 					   -PvP chars can't enter IDDC anyway
716 					   -and kings may just help their team mates for now, maybe cool */
717 				}
718 
719 				/* Teleport player in question out, tell the others on this depth */
720 				else if (num_on_depth > 1) {
721 					/* tell a message to the player */
722 					if (p_ptr->total_winner) {
723 						sprintf(msg, "\377sA hellish force drives you out of this dungeon!");
724 						/* log */
725 						s_printf("Morgoth recalled winner %s\n", p_ptr->name);
726 					} else if (p_ptr->mode & MODE_PVP) {
727 						sprintf(msg, "\377sA hellish force drives you out of this dungeon!");
728 						/* log */
729 						s_printf("Morgoth recalled MODE_PVP %s\n", p_ptr->name);
730 					} else {
731 						sprintf(msg, "\377sYou hear Sauron's laughter as his spell drives you out of the dungeon!");
732 						/* log */
733 						s_printf("Morgoth recalled Sauron-misser %s\n", p_ptr->name);
734 					}
735 
736 					/* get him out of here */
737 					p_ptr->new_level_method = (p_ptr->wpos.wz > 0 ? LEVEL_RECALL_DOWN : LEVEL_RECALL_UP);
738 					p_ptr->recall_pos.wx = p_ptr->wpos.wx;
739 					p_ptr->recall_pos.wy = p_ptr->wpos.wy;
740 					p_ptr->recall_pos.wz = 0;
741 					recall_player(i, msg);
742 
743 				/* Teleport Morgoth out, since no other players are affected */
744 				} else {
745 					sprintf(msg, "\377sMorgoth, Lord of Darkness teleports to a different dungeon floor!");
746 					for (i = 1; i <= NumPlayers; i++) {
747 						if (Players[i]->conn == NOT_CONNECTED) continue;
748 						/* Player on Morgy depth? */
749 						if (inarea(&Players[i]->wpos, wpos))
750 							msg_print(i, msg);
751 					}
752 
753 					/* log */
754 					s_printf("Morgoth left level due to %s\n", p_ptr->name);
755 					/* remove morgy here */
756 					delete_monster_idx(k, TRUE);
757 
758 					/* place replacement monster (clone): Death Orb (Star-Spawn, GB, GWoP) */
759 					summon_override_checks = SO_ALL; /* needed? */
760 //					place_monster_one(&p_ptr->wpos, y, x, 975, FALSE, FALSE, FALSE, 100, 4 + cfg.clone_summoning);//DOrb (kills items)
761 					place_monster_one(&p_ptr->wpos, y, x, 847, FALSE, FALSE, FALSE, 100, 4 + cfg.clone_summoning);//GWoP (best maybe)
762 					summon_override_checks = SO_NONE;
763 
764 	                                /* Notice */
765 	    		                note_spot_depth(&p_ptr->wpos, y, x);
766 		                        /* Display */
767 	                                everyone_lite_spot(&p_ptr->wpos, y, x);
768 				}
769 				return;
770 			}
771 		}
772 
773 		tmphp = (m_ptr->org_maxhp * (2 * (num_on_depth - 1) + 3)) / 3; /* 2/3 HP boost for each additional player */
774 		/* More players here than Morgy has power for? */
775 		if (m_ptr->maxhp < tmphp) {
776 			m_ptr->maxhp = tmphp;
777 			m_ptr->mspeed += 6;
778 			m_ptr->speed += 6; /* also adjust base speed, only important for aggr-haste */
779 			/* Anti-cheeze: Fully heal!
780 			   Otherwise 2 players could bring him down and the 3rd one
781 			   just joins for the last 'few' HP.. */
782 			m_ptr->hp = m_ptr->maxhp;
783 
784 			/* log */
785 			s_printf("Morgoth grows stronger\n");
786 			/* Tell everyone related to Morgy's depth */
787 			msg_print_near_monster(m_idx, "becomes stronger!");
788 			return;
789 		}
790 		/* Less players here than Morgy has power for? */
791     		else if (m_ptr->maxhp > tmphp) {
792 			/* anti-cheeze */
793 			if (m_ptr->hp == m_ptr->maxhp) {
794 				m_ptr->hp -= (tmphp - m_ptr->maxhp);
795 			}
796 			m_ptr->maxhp = tmphp;
797 			if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
798 			m_ptr->mspeed -= 6;
799 			m_ptr->speed -= 6; /* also adjust base speed, only important for aggr-haste */
800 
801 			/* log */
802 			s_printf("Morgoth weakens\n");
803 			/* Tell everyone related to Morgy's depth */
804 			msg_print_near_monster(m_idx, "becomes weaker!");
805 			return;
806 		}
807 	}
808 }
809 
players_on_depth(struct worldpos * wpos)810 int players_on_depth(struct worldpos *wpos)
811 {
812 	if (wpos->wx>MAX_WILD_X || wpos->wx<0 || wpos->wy>MAX_WILD_Y || wpos->wy<0) return(0);
813 	if (wpos->wz == 0)
814 		return(wild_info[wpos->wy][wpos->wx].ondepth);
815 	else {
816 		struct dungeon_type *d_ptr;
817 		if (wpos->wz > 0)
818 			d_ptr = wild_info[wpos->wy][wpos->wx].tower;
819 		else
820 			d_ptr = wild_info[wpos->wy][wpos->wx].dungeon;
821 
822 		return(d_ptr->level[ABS(wpos->wz) - 1].ondepth);
823 	}
824 }
825 
826 /* Don't determine wilderness level just from town radius, but also from the
827    level of that town? */
828 #define WILD_LEVEL_DEPENDS_ON_TOWN
829 /* Determine wilderness level (for monster generation) */
getlevel(struct worldpos * wpos)830 int getlevel(struct worldpos *wpos) {
831 	wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
832 
833 	if (wpos->wz == 0) {
834 		/* ground level */
835 #ifdef WILD_LEVEL_DEPENDS_ON_TOWN
836 		return (w_ptr->radius + w_ptr->town_lev / 3);
837 #else
838 		return (w_ptr->radius);
839 #endif
840 	} else {
841 		struct dungeon_type *d_ptr;
842 		int base;
843 
844 		if (wpos->wz > 0) d_ptr = w_ptr->tower;
845 		else d_ptr = w_ptr->dungeon;
846 		base = d_ptr->baselevel + ABS(wpos->wz) - 1;
847 		return (base);
848 	}
849 }
850 
851 /* Simple finder routine. Scan list of c_special, return match */
852 /* NOTE only ONE of each type !!! */
GetCS(cave_type * c_ptr,unsigned char type)853 struct c_special *GetCS(cave_type *c_ptr, unsigned char type) {
854 	struct c_special *trav;
855 
856 	if (!c_ptr->special) return(NULL);
857 	trav = c_ptr->special;
858 	while (trav) {
859 		if (trav->type == type) return(trav);
860 		trav = trav->next;
861 	}
862 	return(NULL);				/* returns ** to the structs. always dealloc */
863 }
864 
865 /* check for duplication, and also set the type	- Jir - */
AddCS(cave_type * c_ptr,byte type)866 struct c_special *AddCS(cave_type *c_ptr, byte type) {
867 	struct c_special *cs_ptr;
868 	if (GetCS(c_ptr, type)) {
869 		return(NULL);	/* already exists! */
870 	}
871 	MAKE(cs_ptr, struct c_special);
872 	if (!cs_ptr) return(NULL);
873 	cs_ptr->next = c_ptr->special;
874 	c_ptr->special = cs_ptr;
875 	cs_ptr->type = type;
876 	return(cs_ptr);
877 }
878 
879 /* like AddCS, but override already-existing one */
ReplaceCS(cave_type * c_ptr,byte type)880 c_special *ReplaceCS(cave_type *c_ptr, byte type)
881 {
882 	struct c_special *cs_ptr;
883 	if (!(cs_ptr = GetCS(c_ptr, type)))
884 	{
885 		MAKE(cs_ptr, struct c_special);
886 		if (!cs_ptr) return(NULL);
887 		cs_ptr->next = c_ptr->special;
888 		c_ptr->special = cs_ptr;
889 	}
890 	cs_ptr->type = type;
891 	return(cs_ptr);
892 }
893 
894 /* Free all memory related to c_ptr->special - mikaelh */
895 /* Note: doesn't clear the c_ptr->special pointer */
FreeCS(cave_type * c_ptr)896 void FreeCS(cave_type *c_ptr)
897 {
898 	struct c_special *trav, *prev;
899 
900 	prev = trav = c_ptr->special;
901 
902 	while (trav)
903 	{
904 		prev = trav;
905 		trav = trav->next;
906 		FREE(prev, struct c_special);
907 	}
908 }
909 
910 
911 
912 /*
913  * Approximate Distance between two points.
914  *
915  * When either the X or Y component dwarfs the other component,
916  * this function is almost perfect, and otherwise, it tends to
917  * over-estimate about one grid per fifteen grids of distance.
918  *
919  * Algorithm: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2
920  */
921 /*
922  * For radius-affecting things, consider using tdx[], tdy[], tdi[] instead,
923  * which contain pre-calculated results of this function.		- Jir -
924  * (Please see prepare_distance() )
925  */
distance(int y1,int x1,int y2,int x2)926 int distance(int y1, int x1, int y2, int x2)
927 {
928 	int dy, dx, d;
929 
930 	/* Find the absolute y/x distance components */
931 	dy = (y1 > y2) ? (y1 - y2) : (y2 - y1);
932 	dx = (x1 > x2) ? (x1 - x2) : (x2 - x1);
933 
934 	/* Hack -- approximate the distance */
935 	d = (dy > dx) ? (dy + (dx>>1)) : (dx + (dy>>1));
936 
937 	/* Return the distance */
938 	return (d);
939 }
940 
941 /*
942  * Returns TRUE if a grid is considered to be a wall for the purpose
943  * of magic mapping / clairvoyance
944  */
is_wall(cave_type * c_ptr)945 static bool is_wall(cave_type *c_ptr)
946 {
947 	int feat;
948 
949 	feat = c_ptr->feat;
950 
951 	/* Paranoia */
952 	if (feat > MAX_F_IDX) return FALSE;
953 
954 	/* Vanilla floors and doors aren't considered to be walls */
955 	if (feat < FEAT_SECRET) return FALSE;
956 
957 	/* Exception #1: a glass wall is a wall but doesn't prevent LOS */
958 	if (feat == FEAT_GLASS_WALL) return FALSE;
959 
960 	/* Exception #2: an illusion wall is not a wall but obstructs view */
961 	if (feat == FEAT_ILLUS_WALL) return TRUE;
962 
963 	/* Exception #3: Ivy (formerly: a small tree) is a floor but obstructs view */
964 	if (feat == FEAT_IVY) return TRUE;
965 
966 	/* Normal cases: use the WALL flag in f_info.txt */
967 	return (f_info[feat].flags1 & FF1_WALL) ? TRUE : FALSE;
968 }
969 
970 
971 /*
972  * A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,
973  * 4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.
974  *
975  * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).
976  *
977  * The LOS begins at the center of the tile (x1,y1) and ends at the center of
978  * the tile (x2,y2).  If los() is to return TRUE, all of the tiles this line
979  * passes through must be floor tiles, except for (x1,y1) and (x2,y2).
980  *
981  * We assume that the "mathematical corner" of a non-floor tile does not
982  * block line of sight.
983  *
984  * Because this function uses (short) ints for all calculations, overflow may
985  * occur if dx and dy exceed 90.
986  *
987  * Once all the degenerate cases are eliminated, the values "qx", "qy", and
988  * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that
989  * we can use integer arithmetic.
990  *
991  * We travel from start to finish along the longer axis, starting at the border
992  * between the first and second tiles, where the y offset = .5 * slope, taking
993  * into account the scale factor.  See below.
994  *
995  * Also note that this function and the "move towards target" code do NOT
996  * share the same properties.  Thus, you can see someone, target them, and
997  * then fire a bolt at them, but the bolt may hit a wall, not them.  However,
998  * by clever choice of target locations, you can sometimes throw a "curve".
999  *
1000  * Note that "line of sight" is not "reflexive" in all cases.
1001  *
1002  * Use the "projectable()" routine to test "spell/missile line of sight".
1003  *
1004  * Use the "update_view()" function to determine player line-of-sight.
1005  */
1006 #ifdef DOUBLE_LOS_SAFETY
1007 static bool los_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2);
los(struct worldpos * wpos,int y1,int x1,int y2,int x2)1008 bool los(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1009 	return (los_DLS(wpos, y1, x1, y2, x2) || los_DLS(wpos, y2, x2, y1, x1));
1010 }
los_DLS(struct worldpos * wpos,int y1,int x1,int y2,int x2)1011 static bool los_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1012 #else
1013 bool los(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1014 #endif
1015 	/* Delta */
1016 	int dx, dy;
1017 
1018 	/* Absolute */
1019 	int ax, ay;
1020 
1021 	/* Signs */
1022 	int sx, sy;
1023 
1024 	/* Fractions */
1025 	int qx, qy;
1026 
1027 	/* Scanners */
1028 	int tx, ty;
1029 
1030 	/* Scale factors */
1031 	int f1, f2;
1032 
1033 	/* Slope, or 1/Slope, of LOS */
1034 	int m;
1035 
1036 	cave_type **zcave;
1037 	if (!(zcave = getcave(wpos))) return FALSE;
1038 
1039 	/* Extract the offset */
1040 	dy = y2 - y1;
1041 	dx = x2 - x1;
1042 
1043 	/* Extract the absolute offset */
1044 	ay = ABS(dy);
1045 	ax = ABS(dx);
1046 
1047 
1048 	/* Handle adjacent (or identical) grids */
1049 	if ((ax < 2) && (ay < 2)) return (TRUE);
1050 
1051 
1052 	/* Paranoia -- require "safe" origin */
1053 	/* if (!in_bounds(y1, x1)) return (FALSE); */
1054 
1055 
1056 	/* Directly South/North */
1057 	if (!dx)
1058 	{
1059 		/* South -- check for walls */
1060 		if (dy > 0)
1061 		{
1062 			for (ty = y1 + 1; ty < y2; ty++)
1063 			{
1064 				if (!cave_los(zcave, ty, x1)) return (FALSE);
1065 			}
1066 		}
1067 
1068 		/* North -- check for walls */
1069 		else
1070 		{
1071 			for (ty = y1 - 1; ty > y2; ty--)
1072 			{
1073 				if (!cave_los(zcave, ty, x1)) return (FALSE);
1074 			}
1075 		}
1076 
1077 		/* Assume los */
1078 		return (TRUE);
1079 	}
1080 
1081 	/* Directly East/West */
1082 	if (!dy)
1083 	{
1084 		/* East -- check for walls */
1085 		if (dx > 0)
1086 		{
1087 			for (tx = x1 + 1; tx < x2; tx++)
1088 			{
1089 				if (!cave_los(zcave, y1, tx)) return (FALSE);
1090 			}
1091 		}
1092 
1093 		/* West -- check for walls */
1094 		else
1095 		{
1096 			for (tx = x1 - 1; tx > x2; tx--)
1097 			{
1098 				if (!cave_los(zcave, y1, tx)) return (FALSE);
1099 			}
1100 		}
1101 
1102 		/* Assume los */
1103 		return (TRUE);
1104 	}
1105 
1106 
1107 	/* Extract some signs */
1108 	sx = (dx < 0) ? -1 : 1;
1109 	sy = (dy < 0) ? -1 : 1;
1110 
1111 
1112 	/* Vertical "knights" */
1113 	if (ax == 1)
1114 	{
1115 		if (ay == 2)
1116 		{
1117 			if (cave_los(zcave, y1 + sy, x1)) return (TRUE);
1118 		}
1119 	}
1120 
1121 	/* Horizontal "knights" */
1122 	else if (ay == 1)
1123 	{
1124 		if (ax == 2)
1125 		{
1126 			if (cave_los(zcave, y1, x1 + sx)) return (TRUE);
1127 		}
1128 	}
1129 
1130 
1131 	/* Calculate scale factor div 2 */
1132 	f2 = (ax * ay);
1133 
1134 	/* Calculate scale factor */
1135 	f1 = f2 << 1;
1136 
1137 
1138 	/* Travel horizontally */
1139 	if (ax >= ay)
1140 	{
1141 		/* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
1142 		qy = ay * ay;
1143 		m = qy << 1;
1144 
1145 		tx = x1 + sx;
1146 
1147 		/* Consider the special case where slope == 1. */
1148 		if (qy == f2)
1149 		{
1150 			ty = y1 + sy;
1151 			qy -= f1;
1152 		}
1153 		else
1154 		{
1155 			ty = y1;
1156 		}
1157 
1158 		/* Note (below) the case (qy == f2), where */
1159 		/* the LOS exactly meets the corner of a tile. */
1160 		while (x2 - tx)
1161 		{
1162 			if (!cave_los(zcave, ty, tx)) return (FALSE);
1163 
1164 			qy += m;
1165 
1166 			if (qy < f2)
1167 			{
1168 				tx += sx;
1169 			}
1170 			else if (qy > f2)
1171 			{
1172 				ty += sy;
1173 				if (!cave_los(zcave, ty, tx)) return (FALSE);
1174 				qy -= f1;
1175 				tx += sx;
1176 			}
1177 			else
1178 			{
1179 				ty += sy;
1180 				qy -= f1;
1181 				tx += sx;
1182 			}
1183 		}
1184 	}
1185 
1186 	/* Travel vertically */
1187 	else
1188 	{
1189 		/* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
1190 		qx = ax * ax;
1191 		m = qx << 1;
1192 
1193 		ty = y1 + sy;
1194 
1195 		if (qx == f2)
1196 		{
1197 			tx = x1 + sx;
1198 			qx -= f1;
1199 		}
1200 		else
1201 		{
1202 			tx = x1;
1203 		}
1204 
1205 		/* Note (below) the case (qx == f2), where */
1206 		/* the LOS exactly meets the corner of a tile. */
1207 		while (y2 - ty)
1208 		{
1209 			if (!cave_los(zcave, ty, tx)) return (FALSE);
1210 
1211 			qx += m;
1212 
1213 			if (qx < f2)
1214 			{
1215 				ty += sy;
1216 			}
1217 			else if (qx > f2)
1218 			{
1219 				tx += sx;
1220 				if (!cave_los(zcave, ty, tx)) return (FALSE);
1221 				qx -= f1;
1222 				ty += sy;
1223 			}
1224 			else
1225 			{
1226 				tx += sx;
1227 				qx -= f1;
1228 				ty += sy;
1229 			}
1230 		}
1231 	}
1232 
1233 	/* Assume los */
1234 	return (TRUE);
1235 }
1236 
1237 /* Same as los, just ignores non-perma-wall grids - for monster targetting - C. Blue */
1238 #ifdef DOUBLE_LOS_SAFETY
1239 static bool los_wall_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2);
1240 bool los_wall(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1241 	return (los_wall_DLS(wpos, y1, x1, y2, x2) || los_wall_DLS(wpos, y2, x2, y1, x1));
1242 }
1243 static bool los_wall_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1244 #else
1245 bool los_wall(struct worldpos *wpos, int y1, int x1, int y2, int x2) {
1246 #endif
1247 	/* Delta */
1248 	int dx, dy;
1249 
1250 	/* Absolute */
1251 	int ax, ay;
1252 
1253 	/* Signs */
1254 	int sx, sy;
1255 
1256 	/* Fractions */
1257 	int qx, qy;
1258 
1259 	/* Scanners */
1260 	int tx, ty;
1261 
1262 	/* Scale factors */
1263 	int f1, f2;
1264 
1265 	/* Slope, or 1/Slope, of LOS */
1266 	int m;
1267 
1268 	cave_type **zcave;
1269 	if (!(zcave = getcave(wpos))) return FALSE;
1270 
1271 	/* Extract the offset */
1272 	dy = y2 - y1;
1273 	dx = x2 - x1;
1274 
1275 	/* Extract the absolute offset */
1276 	ay = ABS(dy);
1277 	ax = ABS(dx);
1278 
1279 
1280 	/* Handle adjacent (or identical) grids */
1281 	if ((ax < 2) && (ay < 2)) return (TRUE);
1282 
1283 
1284 	/* Paranoia -- require "safe" origin */
1285 	/* if (!in_bounds(y1, x1)) return (FALSE); */
1286 
1287 
1288 	/* Directly South/North */
1289 	if (!dx)
1290 	{
1291 		/* South -- check for walls */
1292 		if (dy > 0)
1293 		{
1294 			for (ty = y1 + 1; ty < y2; ty++)
1295 			{
1296 				if (!cave_los_wall(zcave, ty, x1)) return (FALSE);
1297 			}
1298 		}
1299 
1300 		/* North -- check for walls */
1301 		else
1302 		{
1303 			for (ty = y1 - 1; ty > y2; ty--)
1304 			{
1305 				if (!cave_los_wall(zcave, ty, x1)) return (FALSE);
1306 			}
1307 		}
1308 
1309 		/* Assume los */
1310 		return (TRUE);
1311 	}
1312 
1313 	/* Directly East/West */
1314 	if (!dy)
1315 	{
1316 		/* East -- check for walls */
1317 		if (dx > 0)
1318 		{
1319 			for (tx = x1 + 1; tx < x2; tx++)
1320 			{
1321 				if (!cave_los_wall(zcave, y1, tx)) return (FALSE);
1322 			}
1323 		}
1324 
1325 		/* West -- check for walls */
1326 		else
1327 		{
1328 			for (tx = x1 - 1; tx > x2; tx--)
1329 			{
1330 				if (!cave_los_wall(zcave, y1, tx)) return (FALSE);
1331 			}
1332 		}
1333 
1334 		/* Assume los */
1335 		return (TRUE);
1336 	}
1337 
1338 
1339 	/* Extract some signs */
1340 	sx = (dx < 0) ? -1 : 1;
1341 	sy = (dy < 0) ? -1 : 1;
1342 
1343 
1344 	/* Vertical "knights" */
1345 	if (ax == 1)
1346 	{
1347 		if (ay == 2)
1348 		{
1349 			if (cave_los_wall(zcave, y1 + sy, x1)) return (TRUE);
1350 		}
1351 	}
1352 
1353 	/* Horizontal "knights" */
1354 	else if (ay == 1)
1355 	{
1356 		if (ax == 2)
1357 		{
1358 			if (cave_los_wall(zcave, y1, x1 + sx)) return (TRUE);
1359 		}
1360 	}
1361 
1362 
1363 	/* Calculate scale factor div 2 */
1364 	f2 = (ax * ay);
1365 
1366 	/* Calculate scale factor */
1367 	f1 = f2 << 1;
1368 
1369 
1370 	/* Travel horizontally */
1371 	if (ax >= ay)
1372 	{
1373 		/* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
1374 		qy = ay * ay;
1375 		m = qy << 1;
1376 
1377 		tx = x1 + sx;
1378 
1379 		/* Consider the special case where slope == 1. */
1380 		if (qy == f2)
1381 		{
1382 			ty = y1 + sy;
1383 			qy -= f1;
1384 		}
1385 		else
1386 		{
1387 			ty = y1;
1388 		}
1389 
1390 		/* Note (below) the case (qy == f2), where */
1391 		/* the LOS exactly meets the corner of a tile. */
1392 		while (x2 - tx)
1393 		{
1394 			if (!cave_los_wall(zcave, ty, tx)) return (FALSE);
1395 
1396 			qy += m;
1397 
1398 			if (qy < f2)
1399 			{
1400 				tx += sx;
1401 			}
1402 			else if (qy > f2)
1403 			{
1404 				ty += sy;
1405 				if (!cave_los_wall(zcave, ty, tx)) return (FALSE);
1406 				qy -= f1;
1407 				tx += sx;
1408 			}
1409 			else
1410 			{
1411 				ty += sy;
1412 				qy -= f1;
1413 				tx += sx;
1414 			}
1415 		}
1416 	}
1417 
1418 	/* Travel vertically */
1419 	else
1420 	{
1421 		/* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
1422 		qx = ax * ax;
1423 		m = qx << 1;
1424 
1425 		ty = y1 + sy;
1426 
1427 		if (qx == f2)
1428 		{
1429 			tx = x1 + sx;
1430 			qx -= f1;
1431 		}
1432 		else
1433 		{
1434 			tx = x1;
1435 		}
1436 
1437 		/* Note (below) the case (qx == f2), where */
1438 		/* the LOS exactly meets the corner of a tile. */
1439 		while (y2 - ty)
1440 		{
1441 			if (!cave_los_wall(zcave, ty, tx)) return (FALSE);
1442 
1443 			qx += m;
1444 
1445 			if (qx < f2)
1446 			{
1447 				ty += sy;
1448 			}
1449 			else if (qx > f2)
1450 			{
1451 				tx += sx;
1452 				if (!cave_los_wall(zcave, ty, tx)) return (FALSE);
1453 				qx -= f1;
1454 				ty += sy;
1455 			}
1456 			else
1457 			{
1458 				tx += sx;
1459 				qx -= f1;
1460 				ty += sy;
1461 			}
1462 		}
1463 	}
1464 
1465 	/* Assume los */
1466 	return (TRUE);
1467 }
1468 
1469 
1470 
1471 
1472 
1473 /*
1474  * Can the player "see" the given grid in detail?
1475  *
1476  * He must have vision, illumination, and line of sight.
1477  *
1478  * Note -- "CAVE_LITE" is only set if the "torch" has "los()".
1479  * So, given "CAVE_LITE", we know that the grid is "fully visible".
1480  *
1481  * Note that "CAVE_GLOW" makes little sense for a wall, since it would mean
1482  * that a wall is visible from any direction.  That would be odd.  Except
1483  * under wizard light, which might make sense.  Thus, for walls, we require
1484  * not only that they be "CAVE_GLOW", but also, that they be adjacent to a
1485  * grid which is not only "CAVE_GLOW", but which is a non-wall, and which is
1486  * in line of sight of the player.
1487  *
1488  * This extra check is expensive, but it provides a more "correct" semantics.
1489  *
1490  * Note that we should not run this check on walls which are "outer walls" of
1491  * the dungeon, or we will induce a memory fault, but actually verifying all
1492  * of the locations would be extremely expensive.
1493  *
1494  * Thus, to speed up the function, we assume that all "perma-walls" which are
1495  * "CAVE_GLOW" are "illuminated" from all sides.  This is correct for all cases
1496  * except "vaults" and the "buildings" in town.  But the town is a hack anyway,
1497  * and the player has more important things on his mind when he is attacking a
1498  * monster vault.  It is annoying, but an extremely important optimization.
1499  *
1500  * Note that "glowing walls" are only considered to be "illuminated" if the
1501  * grid which is next to the wall in the direction of the player is also a
1502  * "glowing" grid.  This prevents the player from being able to "see" the
1503  * walls of illuminated rooms from a corridor outside the room.
1504  */
1505 bool player_can_see_bold(int Ind, int y, int x)
1506 {
1507 	player_type *p_ptr = Players[Ind];
1508 	int xx, yy;
1509 
1510 	cave_type *c_ptr;
1511 	byte *w_ptr;
1512 	cave_type **zcave;
1513 	struct worldpos *wpos;
1514 	wpos = &p_ptr->wpos;
1515 
1516 	/* Blind players see nothing */
1517 	if (p_ptr->blind) return (FALSE);
1518 
1519 	/* temp bug fix - evileye */
1520 	if (!(zcave = getcave(wpos))) return FALSE;
1521 	c_ptr = &zcave[y][x];
1522 	w_ptr = &p_ptr->cave_flag[y][x];
1523 
1524 	/* Note that "torch-lite" yields "illumination" */
1525 	if ((c_ptr->info & CAVE_LITE) && (*w_ptr & CAVE_VIEW))
1526 		return (TRUE);
1527 
1528 	/* Require line of sight to the grid */
1529 	if (!player_has_los_bold(Ind, y, x)) return (FALSE);
1530 
1531 	/* Require "perma-lite" of the grid */
1532 	if (!(c_ptr->info & CAVE_GLOW)) return (FALSE);
1533 
1534 	/* Floors are simple */
1535 	if (cave_floor_bold(zcave, y, x)) return (TRUE);
1536 
1537 	/* Hack -- move towards player */
1538 	yy = (y < p_ptr->py) ? (y + 1) : (y > p_ptr->py) ? (y - 1) : y;
1539 	xx = (x < p_ptr->px) ? (x + 1) : (x > p_ptr->px) ? (x - 1) : x;
1540 
1541 	/* Check for "local" illumination */
1542 	if (zcave[yy][xx].info & CAVE_GLOW) {
1543 		/* Assume the wall is really illuminated */
1544 		return (TRUE);
1545 	}
1546 
1547 	/* Assume not visible */
1548 	return (FALSE);
1549 }
1550 
1551 
1552 
1553 /*
1554  * Returns true if the player's grid is dark
1555  */
1556 bool no_lite(int Ind)
1557 {
1558 	player_type *p_ptr = Players[Ind];
1559 	if (p_ptr->admin_dm) return(FALSE);
1560 	return (!player_can_see_bold(Ind, p_ptr->py, p_ptr->px));
1561 }
1562 
1563 
1564 /*
1565  * Determine if a given location may be "destroyed"
1566  *
1567  * Used by destruction spells, and for placing stairs, etc.
1568  */
1569 /* Borrowed from ToME, with some extra checks */
1570 bool cave_valid_bold(cave_type **zcave, int y, int x)
1571 {
1572 	cave_type *c_ptr = &zcave[y][x];
1573 
1574 	s16b this_o_idx, next_o_idx = 0;
1575 
1576 	u32b f1, f2, f3, f4, f5, f6, esp;
1577 
1578 	/* Forbid perma-grids */
1579 /*	if (cave_perma_grid(c_ptr)) return (FALSE); */
1580 	if (cave_perma_bold(zcave, y, x)) return (FALSE);
1581 
1582 	/* Check objects */
1583 	for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1584 	{
1585 		object_type *o_ptr;
1586 
1587 		/* Acquire object */
1588 		o_ptr = &o_list[this_o_idx];
1589 
1590 		/* Acquire next object */
1591 		next_o_idx = o_ptr->next_o_idx;
1592 
1593 		/* Forbid artifact grids */
1594 		if (true_artifact_p(o_ptr))
1595 		{
1596 			object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1597 			if (f4 & TR4_SPECIAL_GENE) return (FALSE);
1598 		}
1599 	}
1600 
1601 	/* Accept */
1602 	return (TRUE);
1603 }
1604 
1605 
1606 
1607 
1608 
1609 
1610 
1611 
1612 /*
1613  * Hack -- Legal monster codes
1614  */
1615 static cptr image_monster_hack = \
1616 "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1617 
1618 /*
1619  * Mega-Hack -- Hallucinatory monster
1620  */
1621 static void image_monster(byte *ap, char *cp)
1622 {
1623 	int n = strlen(image_monster_hack);
1624 
1625 	/* Random symbol from set above */
1626 	(*cp) = (image_monster_hack[rand_int(n)]);
1627 
1628 	/* Random color */
1629 	(*ap) = randint(15);
1630 }
1631 
1632 
1633 /*
1634  * Hack -- Legal object codes
1635  */
1636 static cptr image_object_hack = \
1637 "?/|\\\"!$()_-=[]{},~";
1638 
1639 /*
1640  * Mega-Hack -- Hallucinatory object
1641  */
1642 static void image_object(byte *ap, char *cp)
1643 {
1644 	int n = strlen(image_object_hack);
1645 
1646 	/* Random symbol from set above */
1647 	(*cp) = (image_object_hack[rand_int(n)]);
1648 
1649 	/* Random color */
1650 	(*ap) = randint(15);
1651 }
1652 
1653 /*
1654  * Mega-Hack -- Mimic outlook
1655  * (Pleaes bear with us till really implemented..)
1656  */
1657 static void mimic_object(byte *ap, char *cp, int seed)
1658 {
1659 	int n = strlen(image_object_hack);
1660 
1661 	/* Random symbol from set above */
1662 	(*cp) = (image_object_hack[seed % n]);
1663 
1664 	/* Random color */
1665 	(*ap) = seed % 15 + 1;
1666 }
1667 
1668 
1669 /*
1670  * Hack -- Random hallucination
1671  */
1672 static void image_random(byte *ap, char *cp)
1673 {
1674 	/* Normally, assume monsters */
1675 	if (rand_int(100) < 75)
1676 	{
1677 		image_monster(ap, cp);
1678 	}
1679 
1680 	/* Otherwise, assume objects */
1681 	else
1682 	{
1683 		image_object(ap, cp);
1684 	}
1685 }
1686 
1687 #ifndef CLIENT_SHIMMER
1688 /*
1689  * Some eye-candies from PernAngband :)		- Jir -
1690  */
1691 char get_shimmer_color()
1692 {
1693 	switch (randint(7))
1694 	{
1695 		case 1:
1696 			return TERM_RED;
1697 		case 2:
1698 			return TERM_L_RED;
1699 		case 3:
1700 			return TERM_WHITE;
1701 		case 4:
1702 			return TERM_L_GREEN;
1703 		case 5:
1704 			return TERM_BLUE;
1705 		case 6:
1706 			return TERM_L_DARK;
1707 		case 7:
1708 			return TERM_GREEN;
1709 	}
1710 	return (TERM_VIOLET);
1711 }
1712 #endif
1713 
1714 /*
1715  * Table of breath colors.  Must match listings in a single set of
1716  * monster spell flags.
1717  *
1718  * The value "255" is special.  Monsters with that kind of breath
1719  * may be any color.
1720  */
1721 #if 0 /* old */
1722 static byte breath_to_attr[32][2] =
1723 {
1724 	{  0,  0 },
1725 	{  0,  0 },
1726 	{  0,  0 },
1727 	{  0,  0 },
1728 	{  0,  0 },
1729 	{  0,  0 },
1730 	{  0,  0 },
1731 	{  0,  0 },
1732 	{  TERM_SLATE, TERM_L_DARK },		/* RF4_BRTH_ACID */
1733 	{  TERM_BLUE,  TERM_L_BLUE },		/* RF4_BRTH_ELEC */
1734 	{  TERM_RED,  TERM_L_RED },		/* RF4_BRTH_FIRE */
1735 	{  TERM_WHITE,  TERM_L_WHITE },		/* RF4_BRTH_COLD */
1736 	{  TERM_GREEN,  TERM_L_GREEN },		/* RF4_BRTH_POIS */
1737 	{  TERM_L_GREEN,  TERM_GREEN },		/* RF4_BRTH_NETHR */
1738 	{  TERM_YELLOW,  TERM_ORANGE },		/* RF4_BRTH_LITE */
1739 	{  TERM_L_DARK,  TERM_SLATE },		/* RF4_BRTH_DARK */
1740 	{  TERM_L_UMBER,  TERM_UMBER },		/* RF4_BRTH_CONFU */
1741 	{  TERM_YELLOW,  TERM_L_UMBER },	/* RF4_BRTH_SOUND */
1742         {  255,  255 },   /* (any color) */	/* RF4_BRTH_CHAOS */
1743 	{  TERM_VIOLET,  TERM_VIOLET },		/* RF4_BRTH_DISEN */
1744 	{  TERM_L_RED,  TERM_VIOLET },		/* RF4_BRTH_NEXUS */
1745 	{  TERM_L_BLUE,  TERM_L_BLUE },		/* RF4_BRTH_TIME */
1746 	{  TERM_L_WHITE,  TERM_SLATE },		/* RF4_BRTH_INER */
1747 	{  TERM_L_WHITE,  TERM_SLATE },		/* RF4_BRTH_GRAV */
1748 	{  TERM_UMBER,  TERM_L_UMBER },		/* RF4_BRTH_SHARD */
1749 	{  TERM_ORANGE,  TERM_RED },		/* RF4_BRTH_PLAS */
1750 	{  TERM_UMBER,  TERM_L_UMBER },		/* RF4_BRTH_FORCE */
1751 	{  TERM_L_BLUE,  TERM_WHITE },		/* RF4_BRTH_MANA */
1752 	{  TERM_WHITE,  TERM_L_RED },		/* RF4_BRTH_DISINT */
1753 	{  TERM_GREEN,  TERM_L_GREEN },		/* RF4_BRTH_NUKE */
1754 	{  0,  0 },     /*  */
1755 	{  0,  0 },     /*  */
1756 };
1757 #else
1758 /* new table that uses animated TERM_ colour codes - C. Blue */
1759 static byte breath_to_attr[32][2] =
1760 {
1761 	{  0, 0},
1762 	{  0, 0},
1763 	{  0, 0},
1764 	{  0, 0},
1765 	{  0, 0},
1766 	{  0, 0},
1767 	{  0, 0},
1768 	{  0, 0},
1769 	{  TERM_ACID },				/* RF4_BRTH_ACID */
1770 	{  TERM_ELEC },				/* RF4_BRTH_ELEC */
1771 	{  TERM_FIRE },				/* RF4_BRTH_FIRE */
1772 	{  TERM_COLD },				/* RF4_BRTH_COLD */
1773 	{  TERM_POIS },				/* RF4_BRTH_POIS */
1774 	{  TERM_L_GREEN,  TERM_L_DARK },	/* RF4_BRTH_NETHR */
1775 	{  TERM_LITE, 0 },			/* RF4_BRTH_LITE */
1776 	{  TERM_DARKNESS, 0 },			/* RF4_BRTH_DARK */
1777 	{  TERM_CONF, 0 },			/* RF4_BRTH_CONFU */
1778 	{  TERM_SOUN, 0 },			/* RF4_BRTH_SOUND */
1779 	{  255,  255 },   /* (any color) */	/* RF4_BRTH_CHAOS */
1780 	{  TERM_ORANGE,  TERM_BLUE },		/* RF4_BRTH_DISEN */
1781 	{  TERM_L_RED,  TERM_VIOLET },		/* RF4_BRTH_NEXUS */
1782 	{  TERM_L_BLUE,  TERM_L_GREEN },	/* RF4_BRTH_TIME */
1783 	{  TERM_L_WHITE, TERM_SLATE },		/* RF4_BRTH_INER */
1784 	{  TERM_L_UMBER,  TERM_UMBER },		/* RF4_BRTH_GRAV */
1785 	{  TERM_SHAR, 0 },			/* RF4_BRTH_SHARD */
1786 	{  TERM_L_RED, TERM_RED },		/* RF4_BRTH_PLAS */
1787 	{  TERM_L_WHITE, TERM_ORANGE },		/* RF4_BRTH_FORCE */
1788 	{  TERM_VIOLET, TERM_L_BLUE },		/* RF4_BRTH_MANA */
1789 	{  TERM_L_DARK, TERM_ORANGE },		/* RF4_BRTH_DISINT */
1790 	{  TERM_GREEN, TERM_RED },		/* RF4_BRTH_NUKE */
1791 	{  0,  0 },     /*  */
1792 	{  0,  0 },     /*  */
1793 };
1794 #endif
1795 /*
1796  * Multi-hued monsters shimmer acording to their breaths.
1797  *
1798  * If a monster has only one kind of breath, it uses both colors
1799  * associated with that breath.  Otherwise, it just uses the first
1800  * color for any of its breaths.
1801  *
1802  * If a monster does not breath anything, it can be any color.
1803  */
1804 static byte multi_hued_attr(monster_race *r_ptr)
1805 {
1806 	byte allowed_attrs[15];
1807 	int stored_colors = 0;
1808 
1809 	byte a;
1810 
1811 	int i, j;
1812 	int breaths = 0;
1813 	int first_color = 0;
1814 	int second_color = 0;
1815 
1816 	/* Monsters with no ranged attacks can be any color */
1817 #ifdef CLIENT_SHIMMER
1818 	if (!r_ptr->freq_innate) return (TERM_HALF);
1819 #else
1820 	if (!r_ptr->freq_innate) return (get_shimmer_color());
1821 #endif
1822 
1823 	/* Check breaths */
1824 	for (i = 0; i < 32; i++) {
1825 		bool stored = FALSE;
1826 
1827 		/* Don't have that breath */
1828 		if (!(r_ptr->flags4 & (1L << i))) continue;
1829 
1830 		/* Get the first color of this breath */
1831 		first_color = breath_to_attr[i][0];
1832 
1833 		/* Breath has no color associated with it */
1834 		if (first_color == 0) continue;
1835 
1836 		/* Monster can be of any color */
1837 #ifdef CLIENT_SHIMMER
1838 		if (first_color == 255) return (TERM_MULTI);
1839 #else
1840 		if (first_color == 255) return (randint(15));
1841 #endif
1842 
1843 
1844 		/* Increment the number of breaths */
1845 		breaths++;
1846 
1847 		/* Monsters with lots of breaths may be any color. */
1848 #ifdef CLIENT_SHIMMER
1849 		if (breaths == 6) return (TERM_MULTI);
1850 #else
1851 		if (breaths == 6) return (randint(15));
1852 #endif
1853 
1854 
1855 		/* Always store the first color */
1856 		for (j = 0; j < stored_colors; j++) {
1857 			/* Already stored */
1858 			if (allowed_attrs[j] == first_color) stored = TRUE;
1859 		}
1860 		if (!stored) {
1861 			allowed_attrs[stored_colors] = first_color;
1862 			stored_colors++;
1863 		}
1864 
1865 		/*
1866 		 * Remember (but do not immediately store) the second color
1867 		 * of the first breath.
1868 		 */
1869 		if (breaths == 1) {
1870 			second_color = breath_to_attr[i][1];
1871 			/* make sure breath colour gets more showtime than base colour - C. Blue */
1872 			if (!second_color) second_color = first_color;
1873 		}
1874 	}
1875 
1876 	/* Monsters with no breaths may be of any color. */
1877 #ifdef CLIENT_SHIMMER
1878 	if (breaths == 0 || breaths == 5) {
1879 		return (TERM_HALF);
1880 	}
1881 #else
1882 	if (breaths == 0) return (get_shimmer_color());
1883 #endif
1884 
1885 	/* If monster has one breath, store the second color too. */
1886 	if (breaths == 1) {
1887 		/* only 1 breath, and one of these? -> discard its r_info
1888 		   base colour completely if ATTR_BASE isn't set: */
1889 		if (!(r_ptr->flags7 & RF7_ATTR_BASE)) {
1890 			switch(r_ptr->flags4 & 0x3fffff00) {
1891 			case RF4_BR_ACID:
1892 				return(TERM_ACID);
1893 			case RF4_BR_COLD:
1894 				return(TERM_COLD);
1895 			case RF4_BR_FIRE:
1896 				return(TERM_FIRE);
1897 			case RF4_BR_ELEC:
1898 				return(TERM_ELEC);
1899 			case RF4_BR_POIS:
1900 				return(TERM_POIS);
1901 			case RF4_BR_CONF:
1902 				return(TERM_CONF);
1903 			case RF4_BR_SOUN:
1904 				return(TERM_SOUN);
1905 			case RF4_BR_SHAR:
1906 				return(TERM_SHAR);
1907 			case RF4_BR_LITE:
1908 				return(TERM_LITE);
1909 			default:
1910 				/* This is annoying - mikaelh */
1911 //				printf("fla: %x\n", r_ptr->flags4 & 0x3fffff00);
1912 				break;
1913 			}
1914 		}
1915 		allowed_attrs[stored_colors] = second_color;
1916 		stored_colors++;
1917 	}
1918 
1919 	/*
1920 	 * Hack -- Always has the base colour
1921 	 * (otherwise, Dragonriders are all red)
1922 	 */
1923 #if 0
1924 	if (!m_ptr->special && !m_ptr->questor && p_ptr->use_r_gfx) a = p_ptr->r_attr[m_ptr->r_idx];
1925 	else a = r_ptr->d_attr;
1926 #endif	/* 0 */
1927 	a = r_ptr->d_attr;
1928 
1929 	allowed_attrs[stored_colors] = a;
1930 	stored_colors++;
1931 
1932 	/* Pick a color at random */
1933 	return (allowed_attrs[rand_int(stored_colors)]);
1934 }
1935 
1936 /* Despite of its name, this gets both, attr and char, for a monster race.. */
1937 static void get_monster_color(int Ind, monster_type *m_ptr, monster_race *r_ptr, cave_type *c_ptr, byte *ap, char *cp)
1938 {
1939 	player_type *p_ptr = Players[Ind];
1940 	byte a;
1941 	char c;
1942 	//monster_race *r_ptr = race_inf(m_ptr);
1943 
1944 	/* Possibly GFX corrupts with egos;
1945 	 * in that case use m_ptr->r_ptr instead.	- Jir -
1946 	 */
1947 	/* Desired attr */
1948 	/* a = r_ptr->x_attr; */
1949 	if (m_ptr && !m_ptr->special && !m_ptr->questor && p_ptr->use_r_gfx) a = p_ptr->r_attr[m_ptr->r_idx];
1950 	else a = r_ptr->d_attr;
1951 	/*                        else a = m_ptr->r_ptr->d_attr; */
1952 
1953 	/* Desired char */
1954 	/* c = r_ptr->x_char; */
1955 	if (m_ptr && !m_ptr->special && !m_ptr->questor && p_ptr->use_r_gfx) c = p_ptr->r_char[m_ptr->r_idx];
1956 	else c = r_ptr->d_char;
1957 	/*                        else c = m_ptr->r_ptr->d_char; */
1958 
1959 	/* Hack -- mimics */
1960 	if (r_ptr->flags9 & RF9_MIMIC) {
1961 		mimic_object(&a, &c, c_ptr->m_idx);
1962 	}
1963 
1964 	/* Ignore weird codes */
1965 	if (avoid_other) {
1966 		/* Use char */
1967 		(*cp) = c;
1968 
1969 		/* Use attr */
1970 		(*ap) = a;
1971 	}
1972 
1973 	/* Special attr/char codes */
1974 	else if ((a & 0x80) && (c & 0x80)) {
1975 		/* Use char */
1976 		(*cp) = c;
1977 
1978 		/* Use attr */
1979 		(*ap) = a;
1980 	}
1981 
1982 #ifdef M_EGO_NEW_FLICKER
1983 	/* Hack -- Unique/Ego 'glitters' sometimes */
1984 	else if ((((r_ptr->flags1 & RF1_UNIQUE) && magik(30)) ||
1985 	    (m_ptr && m_ptr->ego &&
1986 	    ((re_info[m_ptr->ego].d_attr != MEGO_CHAR_ANY) ?
1987 	    magik(85) : magik(5)))
1988 	    ) &&
1989 	    (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR)) &&
1990 	     !(r_ptr->flags2 & (RF2_SHAPECHANGER))))
1991 	{
1992 		(*cp) = c;
1993 
1994 		if (r_ptr->flags1 & RF1_UNIQUE) {
1995 			/* Multi-hued attr */
1996 			if (r_ptr->flags2 & (RF2_ATTR_ANY))
1997 				(*ap) = TERM_MULTI;
1998 			else
1999 				(*ap) = TERM_HALF;
2000 		} else { /* m_ptr->ego is set: */
2001 			if (re_info[m_ptr->ego].d_attr != MEGO_CHAR_ANY) {
2002 				/* ego colour differs from race colour? */
2003 				if (a != re_info[m_ptr->ego].d_attr) {
2004 					/* flicker in ego colour */
2005 					(*ap) = re_info[m_ptr->ego].d_attr;
2006 				} else if (magik(20)) {
2007 					/* flash randomly, rarely */
2008 					(*ap) = TERM_HALF;
2009 				} else {
2010 					(*ap) = a;
2011 				}
2012 			} else { /* no ego colour? rarely flash (similar to old way) */
2013 				/* ego has no colour - flicker in random colour */
2014 				(*ap) = TERM_HALF;
2015 			}
2016 		}
2017 	}
2018 #else
2019 	/* Hack -- Unique/Ego 'glitters' sometimes */
2020 	else if ((((r_ptr->flags1 & RF1_UNIQUE) && magik(30)) ||
2021 		(m_ptr && m_ptr->ego && magik(5)) ) &&
2022 		(!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR)) &&
2023 		 !(r_ptr->flags2 & (RF2_SHAPECHANGER))))
2024 	{
2025 		(*cp) = c;
2026 
2027 		/* Multi-hued attr */
2028 		if (r_ptr->flags2 & (RF2_ATTR_ANY))
2029 			(*ap) = TERM_MULTI;
2030 		else
2031 			(*ap) = TERM_HALF;
2032 	}
2033 #endif
2034 	/* Multi-hued monster */
2035 	else if (r_ptr->flags1 & RF1_ATTR_MULTI) {
2036 		/* Is it a shapechanger? */
2037 		if (r_ptr->flags2 & RF2_SHAPECHANGER) {
2038 			(*cp) = (randint((r_ptr->flags7 & RF7_VORTEX) ? 1 : 25) == 1?
2039 				 image_object_hack[randint(strlen(image_object_hack))]:
2040 				 image_monster_hack[randint(strlen(image_monster_hack))]);
2041 		} else
2042 			(*cp) = c;
2043 
2044 		/* Multi-hued attr */
2045 		if (r_ptr->flags2 & (RF2_ATTR_ANY))
2046 			(*ap) = randint(15);
2047 #ifdef MULTI_HUED_PROPER
2048 		else (*ap) = multi_hued_attr(r_ptr);
2049 #else
2050  #ifdef CLIENT_SHIMMER
2051 		else (*ap) = TERM_HALF;
2052  #else
2053 		else (*ap) = get_shimmer_color();
2054  #endif
2055 #endif	/* MULTI_HUED_PROPER */
2056 #if 0
2057 		/* Normal char */
2058 		(*cp) = c;
2059 
2060 		/* Multi-hued attr */
2061 		(*ap) = randint(15);
2062 #endif	/* 0 */
2063 	}
2064 	/* Special ATTR_BNW flag: Monster just flickers black and white,
2065 	   possibly also its base colour if ATTR_BASE is set either.
2066 	   Added this 'hack flag' to display silly Pandas - C. Blue */
2067 	else if (r_ptr->flags7 & RF7_ATTR_BNW) {
2068 		(*cp) = c;
2069 #ifdef SLOW_ATTR_BNW /* handle server-side -> slower speed flickering */
2070 		if ((r_ptr->flags7 & RF7_ATTR_BASE) && !rand_int(3)) {
2071 			/* Use base attr */
2072 			(*ap) = a;
2073 		} else {
2074 			(*ap) = rand_int(2) ? TERM_L_DARK : TERM_WHITE;
2075 		}
2076 #else /* handle client-side -> the usual fast flickering, same as dungeon wizards */
2077  #ifdef EXTENDED_TERM_COLOURS
2078 		if (is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0))
2079 			(*ap) = TERM_OLD_BNW + ((r_ptr->flags7 & RF7_ATTR_BASE) ? a : 0x0);
2080 		else
2081  #endif
2082 			(*ap) = TERM_BNW + ((r_ptr->flags7 & RF7_ATTR_BASE) ? a : 0x0);
2083 #endif
2084 	}
2085 	/* Normal monster (not "clear" in any way) */
2086 	else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) {
2087 		/* Use char */
2088 		(*cp) = c;
2089 
2090 		/* Is it a non-colourchanging shapechanger? */
2091 		if (r_ptr->flags2 & RF2_SHAPECHANGER) {
2092 			(*cp) = (randint((r_ptr->flags7 & RF7_VORTEX) ? 1 : 25) == 1?
2093 				 image_object_hack[randint(strlen(image_object_hack))]:
2094 				 image_monster_hack[randint(strlen(image_monster_hack))]);
2095 		}
2096 
2097 		/* Use attr */
2098 		(*ap) = a;
2099 	}
2100 
2101 	/* Hack -- Bizarre grid under monster */
2102 	else if ((*ap & 0x80) || (*cp & 0x80)) {
2103 		/* Use char */
2104 		(*cp) = c;
2105 
2106 		/* Use attr */
2107 		(*ap) = a;
2108 	}
2109 
2110 	/* Normal */
2111 	else {
2112 		/* Normal (non-clear char) monster */
2113 		if (!(r_ptr->flags1 & RF1_CHAR_CLEAR)) {
2114 			/* Normal char */
2115 			(*cp) = c;
2116 
2117 			/* Is it a non-colourchanging shapechanger? */
2118 			if (r_ptr->flags2 & RF2_SHAPECHANGER) {
2119 				(*cp) = (randint((r_ptr->flags7 & RF7_VORTEX) ? 1 : 25) == 1?
2120 					 image_object_hack[randint(strlen(image_object_hack))]:
2121 					 image_monster_hack[randint(strlen(image_monster_hack))]);
2122 			}
2123 
2124 		}
2125 
2126 		/* Normal (non-clear attr) monster */
2127 		else if (!(r_ptr->flags1 & RF1_ATTR_CLEAR)) {
2128 			/* Normal attr */
2129 			(*ap) = a;
2130 		}
2131 	}
2132 
2133 	/* Hack -- hallucination */
2134 	if (p_ptr->image) {
2135 		/* Hallucinatory monster */
2136 		image_monster(ap, cp);
2137 	}
2138 }
2139 
2140 /*
2141  * Return the correct "color" of another player
2142  */
2143 static byte player_color(int Ind)
2144 {
2145 	player_type *p_ptr = Players[Ind];
2146 //	monster_race *r_ptr = &r_info[p_ptr->body_monster];
2147 	byte pcolor = p_ptr->pclass;
2148 	char dummy;
2149 	cave_type **zcave = getcave(&p_ptr->wpos);
2150 	cave_type *c_ptr;
2151 	pcolor = p_ptr->cp_ptr->color;
2152 
2153 	/* Check that zcave isn't NULL - mikaelh */
2154 	if (!zcave) {
2155 		s_printf("DEBUG: zcave was NULL in player_color\n");
2156 		return TERM_L_DARK;
2157 	}
2158 
2159 	c_ptr = &zcave[p_ptr->py][p_ptr->px];
2160 
2161 	/* Ghosts are black */
2162 	if (p_ptr->ghost) {
2163 		if (p_ptr->admin_wiz)
2164 #ifdef EXTENDED_TERM_COLOURS
2165 			return TERM_L_DARK + (is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0) ? TERM_OLD_BNW : TERM_BNW);
2166 #else
2167 			return TERM_L_DARK + TERM_BNW;
2168 #endif
2169 		return TERM_L_DARK;
2170 	}
2171 
2172 	/* Black Breath carriers emit malignant aura sometimes.. */
2173 	if (p_ptr->black_breath && magik(50)) return TERM_L_DARK;
2174 
2175 	/* Covered by a mummy wrapping? */
2176 	if (TOOL_EQUIPPED(p_ptr) == SV_TOOL_WRAPPING) pcolor = TERM_L_DARK;
2177 	if (p_ptr->cloaked == 1) pcolor = TERM_L_DARK; /* ignore cloak_neutralized for now */
2178 
2179 	/* Mimicing a monster */
2180 	/* TODO: handle 'ATTR_MULTI', 'ATTR_CLEAR' */
2181 	/* the_sandman: an attempt to actually diplay the mhd flickers on mimicking player using DS spell */
2182 	if (p_ptr->body_monster)
2183 		get_monster_color(Ind, NULL, &r_info[p_ptr->body_monster], c_ptr, &pcolor, &dummy);
2184 
2185 	/* Wearing a costume */
2186 	if ((p_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p_ptr->inventory[INVEN_BODY].sval == SV_COSTUME))
2187 		get_monster_color(Ind, NULL, &r_info[p_ptr->inventory[INVEN_BODY].bpval], c_ptr, &pcolor, &dummy);
2188 
2189 	/* See vampires burn in the sun sometimes.. */
2190 	if (p_ptr->sun_burn && magik(33)) return TERM_FIRE;
2191 
2192 	/* Mana Shield and GOI also flicker */
2193 	/* NOTE: For the player looking at himself, this is done in lite_spot(),
2194 	         which is called from set_tim_manashield().  */
2195 #ifdef EXTENDED_TERM_COLOURS
2196 	if (!is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0)) {
2197 		if (p_ptr->tim_manashield > 15) return TERM_SHIELDM;
2198 		else if (p_ptr->tim_manashield) return TERM_NEXU;
2199 	} else
2200 #endif
2201 	if (p_ptr->tim_manashield > 15) return TERM_SHIELDM;
2202 
2203 #ifdef EXTENDED_TERM_COLOURS
2204 	if (!is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0)) {
2205 		if (p_ptr->invuln > 5) return TERM_SHIELDI;
2206 		else if (p_ptr->invuln && p_ptr->invuln_dur >= 5) return TERM_NUKE;
2207 	} else
2208 #endif
2209 	if (p_ptr->invuln > 5) return TERM_SHIELDI;
2210 
2211 	/* Holy Martyr or shadow running */
2212 	/* Admin wizards sometimes flicker black & white (TERM_BNW) */
2213 	if (p_ptr->shadow_running || p_ptr->martyr || p_ptr->admin_wiz)
2214 #ifdef EXTENDED_TERM_COLOURS
2215 		pcolor += is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0) ? TERM_OLD_BNW : TERM_BNW;
2216 #else
2217 		pcolor += TERM_BNW;
2218 #endif
2219 
2220 	/* Team colours have highest priority */
2221 	if (p_ptr->team) {
2222 		/* may have multiteam */
2223 		switch(p_ptr->team) {
2224 			case 1:
2225 				pcolor = TERM_L_RED; //the_sandman: changed it to light red
2226 						     //since red == istari.
2227 				break;
2228 			case 2:
2229 				pcolor = TERM_L_BLUE;
2230 				break;
2231 			case 3:
2232 				pcolor = TERM_YELLOW;
2233 				break;
2234 			case 4:
2235 				pcolor = TERM_UMBER;
2236 				break;
2237 			default:
2238 				break;
2239 		}
2240 		if ((has_ball(p_ptr) != -1) && magik(50)) pcolor = TERM_ORANGE; /* game ball carrier has orange flickering - mikaelh */
2241 	}
2242 
2243 	/* Color is based off of class */
2244 	return pcolor;
2245 }
2246 
2247 byte get_trap_color(int Ind, int t_idx, int feat)
2248 {
2249 	player_type *p_ptr = Players[Ind];
2250 	byte a;
2251 
2252 	/* Get attr */
2253 	a = t_info[t_idx].color;
2254 
2255 	/* Get a new color with a strange formula :) */
2256 	if (t_info[t_idx].flags & FTRAP_CHANGE)
2257 	{
2258 		u32b tmp;
2259 
2260 		/* tmp = dlev + dungeon_type + c_ptr->feat; */
2261 		tmp = p_ptr->wpos.wx + p_ptr->wpos.wy + p_ptr->wpos.wz + feat;
2262 
2263 		/* a = tmp % 16; */
2264 		/* mega-hack: use trap-like colours only */
2265 		a = tmp % 6 + 1;
2266 	}
2267 
2268 	/* Hack -- always l.blue if underwater */
2269 	if (feat == FEAT_DEEP_WATER || feat == FEAT_SHAL_WATER)
2270 		a = TERM_L_BLUE;
2271 
2272 	return a;
2273 }
2274 
2275 byte get_monster_trap_color(int Ind, int o_idx, int feat) {
2276 	byte a;
2277 	object_type *kit_o_ptr;
2278 //	object_type *load_o_ptr;
2279 
2280 	/* Get the trap objects */
2281 	kit_o_ptr = &o_list[o_idx];
2282 //	load_o_ptr = &o_list[kit_o_ptr->next_o_idx];
2283 
2284 	/* Get attr */
2285 	a = k_info[kit_o_ptr->k_idx].d_attr;
2286 
2287 	/* Hack -- always l.blue if underwater */
2288 	if (feat == FEAT_DEEP_WATER || feat == FEAT_SHAL_WATER)
2289 		a = TERM_L_BLUE;
2290 
2291 	return a;
2292 }
2293 
2294 byte get_rune_color(int Ind, int typ) {
2295 	byte a = spell_color(r_projections[typ].gf_type);
2296 	return a;
2297 }
2298 
2299 /*
2300  * Manipulate map grid colours, for example outside on world surface,
2301  * depending on clima or daytime!  - C. Blue
2302  */
2303 static int manipulate_cave_colour_season(cave_type *c_ptr, worldpos *wpos, int x, int y, int colour) {
2304 	bool old_rand = Rand_quick;
2305 	u32b tmp_seed = Rand_value; /* save RNG */
2306 	wilderness_type *w_ptr = &wild_info[wpos->wy][wpos->wx];
2307 
2308 	/* World surface manipulation only */
2309 	if (wpos->wz) return colour;
2310 
2311 	/* To use always the same feats for this everytime the player
2312 	   enters a worldmap sector, we seed the RNG with that particular
2313 	   worldmap coords. */
2314 	Rand_quick = TRUE;
2315 	/* My attempt to create something chaotic - mikaelh */
2316 	Rand_value = (3623 * wpos->wy + 29753) * (2843 * wpos->wx + 48869) +
2317 		(1741 * y + 22109) * y * x + (x + 96779) * x + 42;
2318 
2319 	/* Seasons */
2320 	switch (season) {
2321 	case SEASON_WINTER:
2322 		/* Replace green trees and grass by white =-} - using live information of original finnish winter */
2323 		if (w_ptr->type != WILD_VOLCANO && (w_ptr->type != WILD_DESERT || c_ptr->feat == FEAT_GRASS)) {
2324 			/* Sometimes display a feat still as green, sometimes brown. */
2325 			switch (c_ptr->feat) {
2326 			case FEAT_DIRT:
2327 				switch (Rand_div(7)) {
2328 				case 0: case 1: case 2: case 3: case 4:
2329 					colour = TERM_L_WHITE; break;
2330 				case 5: if (c_ptr->info & CAVE_LITE) colour = TERM_L_UMBER;
2331 					else colour = TERM_UMBER;
2332 					break;
2333 				case 6: colour = TERM_SLATE; break;
2334 				}
2335 				break;
2336 #if 0 /* maybe keep disabled, for stone2mud effects on world surface - doesn't matter much though? */
2337 			case FEAT_MUD:
2338 				switch (Rand_div(7)) {
2339 				case 0: case 1: case 2: case 3:
2340 					colour = TERM_L_WHITE; break;
2341 				case 4: case 5: case 6: if (c_ptr->info & CAVE_LITE) colour = TERM_L_UMBER;
2342 					else colour = TERM_UMBER;
2343 					break;
2344 				}
2345 				break;
2346 #endif
2347 			case FEAT_GRASS:
2348 				switch (Rand_div(7)) {
2349 				case 0: case 1: case 2: case 3: case 4:
2350 					colour = TERM_L_WHITE; break;
2351 				case 5: case 6:
2352 					if (c_ptr->info & CAVE_LITE) colour = TERM_L_UMBER;
2353 					else colour = TERM_UMBER;
2354 					break;
2355 //				case 7:	colour = TERM_GREEN; break;
2356 				}
2357 				break;
2358 			case FEAT_TREE:
2359 			case FEAT_BUSH:
2360 				if (Rand_div(50)) colour = TERM_WHITE;
2361 				else if (Rand_div(3)) colour = TERM_UMBER;
2362 				else colour = TERM_GREEN;
2363 				break;
2364 			case FEAT_IVY:
2365 				if (Rand_div(50)) colour = TERM_WHITE;
2366 				else if (Rand_div(3)) colour = TERM_UMBER;
2367 				else colour = TERM_GREEN;
2368 				break;
2369 			case FEAT_MOUNTAIN:
2370 				if (Rand_div(4)) colour = TERM_WHITE;
2371 				break;
2372 			}
2373 		}
2374 		break;
2375 	case SEASON_SPRING:
2376 		/* More saplings and all green goodness in spring time, yay */
2377 		if (w_ptr->type != WILD_DESERT || c_ptr->feat == FEAT_GRASS) {
2378 			switch (c_ptr->feat) {
2379 			case FEAT_GRASS:
2380 				switch (Rand_div(7)) {
2381 				case 0: case 1: case 2: case 3: case 4:
2382 					colour = TERM_L_GREEN; break;
2383 				case 5:	if (c_ptr->info & CAVE_LITE) colour = TERM_L_UMBER;
2384 					else colour = TERM_UMBER;
2385 					break;
2386 				case 6: colour = TERM_GREEN; break;
2387 				}
2388 				break;
2389 			case FEAT_TREE:
2390 			case FEAT_BUSH:
2391 				if (Rand_div(300)) colour = TERM_L_GREEN;
2392 				else if (Rand_div(3)) colour = TERM_L_UMBER;
2393 				else colour = TERM_UMBER;
2394 				break;
2395 			case FEAT_IVY:
2396 				if (Rand_div(500)) colour = TERM_GREEN;
2397 				else if (Rand_div(3)) colour = TERM_GREEN;
2398 				else colour = TERM_UMBER;
2399 				break;
2400 			}
2401 		}
2402 		break;
2403 	case SEASON_SUMMER:
2404 		/* Mostly grown trees, some bushes, all saturated green, some light green and yellow/light umber */
2405 		if (w_ptr->type != WILD_DESERT || c_ptr->feat == FEAT_GRASS) {
2406 			switch (c_ptr->feat) {
2407 			case FEAT_GRASS:
2408 				switch (Rand_div(6)) {
2409 				case 0:
2410 					colour = TERM_L_GREEN; break;
2411 				case 1: case 2:
2412 					if (c_ptr->info & CAVE_LITE) colour = TERM_YELLOW;
2413 					else colour = TERM_L_UMBER;
2414 							break;
2415 				case 3: case 4:
2416 					colour = TERM_GREEN; break;
2417 				case 5:
2418 					colour = TERM_YELLOW; break;
2419 				}
2420 				break;
2421 			case FEAT_TREE:
2422 			case FEAT_BUSH:
2423 				if (Rand_div(4)) colour = TERM_GREEN;
2424 				else if (Rand_div(10)) colour = TERM_L_GREEN;
2425 				else colour = TERM_L_UMBER;
2426 				break;
2427 			case FEAT_IVY:
2428 				if (Rand_div(3)) colour = TERM_GREEN;
2429 				else if (Rand_div(3)) colour = TERM_L_UMBER;
2430 				else colour = TERM_UMBER;
2431 				break;
2432 			}
2433 		}
2434 		break;
2435 	case SEASON_AUTUMN:
2436 		/* Rarely saplings, very colourful trees, turning to other tones than green */
2437 		if (w_ptr->type != WILD_DESERT || c_ptr->feat == FEAT_GRASS) {
2438 			switch (c_ptr->feat) {
2439 			case FEAT_GRASS:
2440 				switch (Rand_div(7)) {
2441 				case 0: case 1: case 2:
2442 					colour = TERM_GREEN; break;
2443 				case 3: case 4:
2444 					if (c_ptr->info & CAVE_LITE) colour = TERM_L_UMBER;
2445 					else colour = TERM_UMBER;
2446 					break;
2447 				case 5: case 6:
2448 					colour = TERM_YELLOW; break;
2449 				}
2450 				break;
2451 			case FEAT_TREE:
2452 			case FEAT_BUSH:
2453 				if (Rand_div(50))
2454 				switch (Rand_div(10)) {
2455 				case 0: case 1: colour = TERM_GREEN; break;
2456 				case 2: case 3: case 4: colour = TERM_YELLOW; break;
2457 				case 5: case 6: case 7: colour = TERM_L_UMBER; break;
2458 				case 8: case 9: colour = TERM_UMBER; break;
2459 				}
2460 				else colour = TERM_RED;
2461 				break;
2462 			case FEAT_IVY:
2463 				if (Rand_div(3)) colour = TERM_GREEN;
2464 				else if (Rand_div(3)) colour = TERM_L_UMBER;
2465 				else colour = TERM_UMBER;
2466 				break;
2467 			}
2468 		}
2469 		break;
2470 	}
2471 
2472 	Rand_quick = old_rand; /* resume complex rng - mikaelh */
2473 	Rand_value = tmp_seed; /* restore RNG */
2474 	return colour;
2475 }
2476 static int manipulate_cave_colour_daytime(cave_type *c_ptr, worldpos *wpos, int x, int y, int colour) {
2477 	/* World surface manipulation only */
2478 	if (wpos->wz) return colour;
2479 
2480 	/* Darkness on the world surface at night. Darken all colours. */
2481 	if (night_surface &&
2482 	    (!(c_ptr->info & (CAVE_GLOW | CAVE_LITE)) ||
2483 	    (f_info[c_ptr->feat].flags2 & FF2_NIGHT_DARK))) {
2484 		switch (colour) {
2485 		case TERM_DARK: return TERM_DARK;
2486 		case TERM_WHITE: return TERM_SLATE;
2487 		case TERM_SLATE: return TERM_L_DARK;
2488 		case TERM_ORANGE: return TERM_UMBER;
2489 		case TERM_RED: return TERM_RED;
2490 		case TERM_GREEN: return TERM_GREEN;
2491 		case TERM_BLUE: return TERM_BLUE;
2492 		case TERM_UMBER: return TERM_UMBER;
2493 		case TERM_L_DARK: return TERM_L_DARK;
2494 		case TERM_L_WHITE: return TERM_SLATE;
2495 		case TERM_VIOLET: return TERM_VIOLET;
2496 		case TERM_YELLOW: return TERM_L_UMBER;
2497 		case TERM_L_RED: return TERM_RED;
2498 		case TERM_L_GREEN: return TERM_GREEN;
2499 		case TERM_L_BLUE: return TERM_BLUE;
2500 		case TERM_L_UMBER: return TERM_UMBER;
2501 		}
2502 	}
2503 
2504 	return colour;
2505 }
2506 static int manipulate_cave_colour(cave_type *c_ptr, worldpos *wpos, int x, int y, int colour) {
2507 	colour = manipulate_cave_colour_season(c_ptr, wpos, x,  y,  colour);
2508 	return manipulate_cave_colour_daytime(c_ptr, wpos, x,  y,  colour);
2509 }
2510 #ifdef SHADE_ALL_FLOOR
2511 static int manipulate_cave_colour_shade(cave_type *c_ptr, worldpos *wpos, int x, int y, int colour) {
2512 	switch (colour) {
2513 	case TERM_DARK: return TERM_DARK;
2514 	case TERM_WHITE: return TERM_SLATE;
2515 	case TERM_SLATE: return TERM_L_DARK;
2516 	case TERM_ORANGE: return TERM_UMBER;
2517 	case TERM_RED: return TERM_RED;
2518 	case TERM_GREEN: return TERM_GREEN;
2519 	case TERM_BLUE: return TERM_BLUE;
2520 	case TERM_UMBER: return TERM_UMBER;
2521 	case TERM_L_DARK: return TERM_L_DARK;
2522 	case TERM_L_WHITE: return TERM_SLATE;
2523 	case TERM_VIOLET: return TERM_VIOLET;
2524 	case TERM_YELLOW: return TERM_L_UMBER;
2525 	case TERM_L_RED: return TERM_RED;
2526 	case TERM_L_GREEN: return TERM_GREEN;
2527 	case TERM_L_BLUE: return TERM_BLUE;
2528 	case TERM_L_UMBER: return TERM_UMBER;
2529 	}
2530 	return colour;
2531 }
2532 #endif
2533 
2534 
2535 /*
2536  * Extract the attr/char to display at the given (legal) map location
2537  *
2538  * Basically, we "paint" the chosen attr/char in several passes, starting
2539  * with any known "terrain features" (defaulting to darkness), then adding
2540  * any known "objects", and finally, adding any known "monsters".  This
2541  * is not the fastest method but since most of the calls to this function
2542  * are made for grids with no monsters or objects, it is fast enough.
2543  *
2544  * Note that this function, if used on the grid containing the "player",
2545  * will return the attr/char of the grid underneath the player, and not
2546  * the actual player attr/char itself, allowing a lot of optimization
2547  * in various "display" functions.
2548  *
2549  * Note that the "zero" entry in the feature/object/monster arrays are
2550  * used to provide "special" attr/char codes, with "monster zero" being
2551  * used for the player attr/char, "object zero" being used for the "stack"
2552  * attr/char, and "feature zero" being used for the "nothing" attr/char,
2553  * though this function makes use of only "feature zero".
2554  *
2555  * Note that monsters can have some "special" flags, including "ATTR_MULTI",
2556  * which means their color changes, and "ATTR_CLEAR", which means they take
2557  * the color of whatever is under them, and "CHAR_CLEAR", which means that
2558  * they take the symbol of whatever is under them.  Technically, the flag
2559  * "CHAR_MULTI" is supposed to indicate that a monster looks strange when
2560  * examined, but this flag is currently ignored.  All of these flags are
2561  * ignored if the "avoid_other" option is set, since checking for these
2562  * conditions is expensive and annoying on some systems.
2563  *
2564  * Currently, we do nothing with multi-hued objects.  We should probably
2565  * just add a flag to wearable object, or even to all objects, now that
2566  * everyone can use the same flags.  Then the "SHIMMER_OBJECT" code can
2567  * be used to request occasional "redraw" of those objects. It will be
2568  * very hard to associate flags with the "flavored" objects, so maybe
2569  * they will never be "multi-hued".
2570  *
2571  * Note the effects of hallucination.  Objects always appear as random
2572  * "objects", monsters as random "monsters", and normal grids occasionally
2573  * appear as random "monsters" or "objects", but note that these random
2574  * "monsters" and "objects" are really just "colored ascii symbols".
2575  *
2576  * Note that "floors" and "invisible traps" (and "zero" features) are
2577  * drawn as "floors" using a special check for optimization purposes,
2578  * and these are the only features which get drawn using the special
2579  * lighting effects activated by "floor_lighting".
2580  *
2581  * Note the use of the "mimic" field in the "terrain feature" processing,
2582  * which allows any feature to "pretend" to be another feature.  This is
2583  * used to "hide" secret doors, and to make all "doors" appear the same,
2584  * and all "walls" appear the same, and "hidden" treasure stay hidden.
2585  * It is possible to use this field to make a feature "look" like a floor,
2586  * but the "special lighting effects" for floors will not be used.
2587  *
2588  * Note the use of the new "terrain feature" information.  Note that the
2589  * assumption that all interesting "objects" and "terrain features" are
2590  * memorized allows extremely optimized processing below.  Note the use
2591  * of separate flags on objects to mark them as memorized allows a grid
2592  * to have memorized "terrain" without granting knowledge of any object
2593  * which may appear in that grid.
2594  *
2595  * Note the efficient code used to determine if a "floor" grid is
2596  * "memorized" or "viewable" by the player, where the test for the
2597  * grid being "viewable" is based on the facts that (1) the grid
2598  * must be "lit" (torch-lit or perma-lit), (2) the grid must be in
2599  * line of sight, and (3) the player must not be blind, and uses the
2600  * assumption that all torch-lit grids are in line of sight.
2601  *
2602  * Note that floors (and invisible traps) are the only grids which are
2603  * not memorized when seen, so only these grids need to check to see if
2604  * the grid is "viewable" to the player (if it is not memorized).  Since
2605  * most non-memorized grids are in fact walls, this induces *massive*
2606  * efficiency, at the cost of *forcing* the memorization of non-floor
2607  * grids when they are first seen.  Note that "invisible traps" are
2608  * always treated exactly like "floors", which prevents "cheating".
2609  *
2610  * Note the "special lighting effects" which can be activated for floor
2611  * grids using the "floor_lighting" option (for "white" floor grids),
2612  * causing certain grids to be displayed using special colors.  If the
2613  * player is "blind", we will use "dark gray", else if the grid is lit
2614  * by the torch, and the "view_lamp_lite" option is set, we will use
2615  * "yellow", else if the grid is "dark", we will use "dark gray", else
2616  * if the grid is not "viewable", and the "view_shade_floor" option is
2617  * set, and the we will use "slate" (gray).  We will use "white" for all
2618  * other cases, in particular, for illuminated viewable floor grids.
2619  *
2620  * Note the "special lighting effects" which can be activated for wall
2621  * grids using the "wall_lighting" option (for "white" wall grids),
2622  * causing certain grids to be displayed using special colors.  If the
2623  * player is "blind", we will use "dark gray", else if the grid is lit
2624  * by the torch, and the "view_lamp_lite" option is set, we will use
2625  * "yellow", else if the "view_shade_floor" option is set, and the grid
2626  * is not "viewable", or is "dark", or is glowing, but not when viewed
2627  * from the player's current location, we will use "slate" (gray).  We
2628  * will use "white" for all other cases, in particular, for correctly
2629  * illuminated viewable wall grids.
2630  *
2631  * Note that, when "wall_lighting" is set, we use an inline version
2632  * of the "player_can_see_bold()" function to check the "viewability" of
2633  * grids when the "view_shade_floor" option is set, and we do NOT use
2634  * any special colors for "dark" wall grids, since this would allow the
2635  * player to notice the walls of illuminated rooms from a hallway that
2636  * happened to run beside the room.  The alternative, by the way, would
2637  * be to prevent the generation of hallways next to rooms, but this
2638  * would still allow problems when digging towards a room.
2639  *
2640  * Note that bizarre things must be done when the "attr" and/or "char"
2641  * codes have the "high-bit" set, since these values are used to encode
2642  * various "special" pictures in some versions, and certain situations,
2643  * such as "multi-hued" or "clear" monsters, cause the attr/char codes
2644  * to be "scrambled" in various ways.
2645  *
2646  * Note that eventually we may use the "&" symbol for embedded treasure,
2647  * and use the "*" symbol to indicate multiple objects, though this will
2648  * have to wait for Angband 2.8.0 or later.  Note that currently, this
2649  * is not important, since only one object or terrain feature is allowed
2650  * in each grid.  If needed, "k_info[0]" will hold the "stack" attr/char.
2651  *
2652  * Note the assumption that doing "x_ptr = &x_info[x]" plus a few of
2653  * "x_ptr->xxx", is quicker than "x_info[x].xxx", if this is incorrect
2654  * then a whole lot of code should be changed...  XXX XXX
2655  */
2656 void map_info(int Ind, int y, int x, byte *ap, char *cp) {
2657 	player_type *p_ptr = Players[Ind];
2658 
2659 	cave_type *c_ptr;
2660 	byte *w_ptr;
2661 
2662 	feature_type *f_ptr;
2663 
2664 	int feat;
2665 
2666 	byte a;
2667 	char c;
2668 
2669 	int a_org;
2670 	bool lite_snow, keep = FALSE;
2671 
2672 	cave_type **zcave;
2673 	if (!(zcave = getcave(&p_ptr->wpos))) return;
2674 
2675 	/* Get the cave */
2676 	c_ptr = &zcave[y][x];
2677 	w_ptr = &p_ptr->cave_flag[y][x];
2678 
2679 
2680 	/* Feature code */
2681 	feat = c_ptr->feat;
2682 
2683 #if 0
2684 	/* bad hack to display visible wall instead of clear wall in sector00 events */
2685 	if (sector00separation &&
2686 	    *cp == ' ' && feat == FEAT_PERM_CLEAR &&
2687 	    p_ptr->wpos.wx == WPOS_SECTOR00_X &&
2688 	    p_ptr->wpos.wy == WPOS_SECTOR00_Y && p_ptr->wpos.wz == 0
2689 	    && sector00wall) {
2690 		if (!p_ptr->font_map_solid_walls) {
2691 			*cp = p_ptr->f_char[sector00wall];
2692 			a = p_ptr->f_attr[sector00wall];
2693 		} else { /* hack */
2694 			*cp = p_ptr->f_char_solid[sector00wall];
2695 			a = p_ptr->f_attr_solid[sector00wall];
2696 		}
2697 	}
2698 #else
2699 	/* bad hack to display visible wall instead of clear wall in sector00 events */
2700 	if (sector00separation &&
2701 	    feat == FEAT_PERM_CLEAR &&
2702 	    p_ptr->wpos.wx == WPOS_SECTOR00_X &&
2703 	    p_ptr->wpos.wy == WPOS_SECTOR00_Y && p_ptr->wpos.wz == 0
2704 	    && sector00wall)
2705 		feat = sector00wall;
2706 #endif
2707 
2708 	/* Access floor */
2709 	f_ptr = &f_info[feat];
2710 
2711 	/* Floors (etc) */
2712 	/* XXX XXX Erm, it is DIRTY.  should be replaced soon */
2713 //	if (feat <= FEAT_INVIS)
2714 	if (f_ptr->flags1 & (FF1_FLOOR)) {
2715 
2716 		/* Memorized (or visible) floor */
2717 		/* Hack -- space are visible to the dungeon master */
2718 		if (((*w_ptr & CAVE_MARK) ||
2719 		    ((((c_ptr->info & CAVE_LITE) &&
2720 			(*w_ptr & CAVE_VIEW)) ||
2721 		      ((c_ptr->info & CAVE_GLOW) &&
2722 		       (*w_ptr & CAVE_VIEW))) &&
2723 		     !p_ptr->blind)) || (p_ptr->admin_dm))
2724 		{
2725 			struct c_special *cs_ptr;
2726 
2727 			/* for FEAT_ILLUS_WALL, which aren't walls but floors! */
2728 			if (!p_ptr->font_map_solid_walls) {
2729 				/* Normal char */
2730 				(*cp) = p_ptr->f_char[feat];
2731 
2732 				/* Normal attr */
2733 				a = p_ptr->f_attr[feat];
2734 			} else { /* hack */
2735 				(*cp) = p_ptr->f_char_solid[feat];
2736 				a = p_ptr->f_attr_solid[feat];
2737 			}
2738 
2739 			/* Hack to display monster traps */
2740 			/* Illusory wall masks everythink */
2741 			if ((cs_ptr = GetCS(c_ptr, CS_MON_TRAP)) && c_ptr->feat != FEAT_ILLUS_WALL) {
2742 				/* Hack -- random hallucination */
2743 				if (p_ptr->image) {
2744 /*					image_random(ap, cp); */
2745 					image_object(ap, cp);
2746 					a = randint(15);
2747 				} else {
2748 					/* If trap isn't on door display it */
2749 					/* if (!(f_ptr->flags1 & FF1_DOOR)) c = '^'; */
2750 //					(*cp) = ';';
2751 					a = get_monster_trap_color(Ind,
2752 					    cs_ptr->sc.montrap.trap_kit,
2753 					    feat);
2754 				}
2755 				keep = TRUE;
2756 			}
2757 
2758 			/* Hack to display "runes of warding" which are coloured by GF_TYPE */
2759 			/* Illusory wall masks everythink */
2760 			if ((cs_ptr = GetCS(c_ptr, CS_RUNE)) && c_ptr->feat != FEAT_ILLUS_WALL) {
2761 				a = get_rune_color(Ind, cs_ptr->sc.rune.typ);
2762 				keep = TRUE;
2763 			}
2764 
2765 			/* Hack to display detected traps */
2766 			/* Illusory wall masks everythink */
2767 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS)) && c_ptr->feat != FEAT_ILLUS_WALL) {
2768 				int t_idx = cs_ptr->sc.trap.t_idx;
2769 				if (cs_ptr->sc.trap.found) {
2770 					/* Hack -- random hallucination */
2771 					if (p_ptr->image) {
2772 /*						image_random(ap, cp); */
2773 						image_object(ap, cp);
2774 						a = randint(15);
2775 					} else {
2776 						/* If trap isn't on door display it */
2777 						/* if (!(f_ptr->flags1 & FF1_DOOR)) c = '^'; */
2778 						(*cp) = '^';
2779 
2780 						a = get_trap_color(Ind, t_idx, feat);
2781 					}
2782 					keep = TRUE;
2783 				}
2784 			}
2785 
2786 			/* Quick Hack -- shop */
2787 			if ((cs_ptr = GetCS(c_ptr, CS_SHOP))) {
2788 				(*cp) = st_info[cs_ptr->sc.omni].d_char;
2789 				a = st_info[cs_ptr->sc.omni].d_attr;
2790 
2791 				a = manipulate_cave_colour(c_ptr, &p_ptr->wpos, x, y, a);
2792 			}
2793 
2794 			/* apply colour to OPEN house doors (which have FF1_FLOOR,
2795 			   are hence separated from close house doors - C. Blue */
2796 			else if ((cs_ptr = GetCS(c_ptr, CS_DNADOOR))) {
2797 				a = access_door_colour(Ind, cs_ptr->sc.ptr);
2798 
2799 				a = manipulate_cave_colour(c_ptr, &p_ptr->wpos, x, y, a);
2800 			}
2801 
2802 			/* don't apply special lighting/shading on traps/montraps/runes! */
2803 			else if (keep) {
2804 				/* nothing */
2805 			}
2806 
2807 			/* Special lighting effects */
2808 			else if (p_ptr->floor_lighting &&
2809 			    (a_org = manipulate_cave_colour_season(c_ptr, &p_ptr->wpos, x, y, a)) != -1 && /* dummy */
2810 			    ((lite_snow = ((f_ptr->flags2 & FF2_LAMP_LITE_SNOW) && /* dirty snow and clean slow */
2811 			    (a_org == TERM_WHITE || a_org == TERM_L_WHITE))) ||
2812 			    (f_ptr->flags2 & (FF2_LAMP_LITE | FF2_SPECIAL_LITE)) ||
2813 			    ((f_ptr->flags2 & FF2_LAMP_LITE_OPTIONAL) && p_ptr->view_lite_extra))) {
2814 				a = manipulate_cave_colour_daytime(c_ptr, &p_ptr->wpos, x, y, a_org);
2815 
2816 				/* Handle "blind" */
2817 				if (p_ptr->blind) {
2818 					/* Use "dark gray" */
2819 					a = TERM_L_DARK;
2820 				}
2821 
2822 				/* Handle "torch-lit" grids */
2823 				else if (((f_ptr->flags2 & FF2_LAMP_LITE) ||
2824 				    ((f_ptr->flags2 & FF2_LAMP_LITE_OPTIONAL) && p_ptr->view_lite_extra) ||
2825 				    lite_snow) &&
2826 				    ((c_ptr->info & CAVE_LITE) && (*w_ptr & CAVE_VIEW))) {
2827 					/* Torch lite */
2828 					if (p_ptr->view_lamp_floor) {
2829 #ifdef CAVE_LITE_COLOURS
2830 						if ((c_ptr->info & CAVE_LITE_WHITE)) {
2831 							if (!(f_ptr->flags2 & FF2_NO_LITE_WHITEN)) a = (a == TERM_L_DARK) ? TERM_SLATE ://<-specialty for ash
2832 							    TERM_WHITE;//normal
2833 						} else if ((c_ptr->info & CAVE_LITE_VAMP)) {
2834 							if (!(f_ptr->flags2 & FF2_NO_LITE_WHITEN)) a = (a == TERM_L_DARK) ? TERM_SLATE ://<-specialty for ash
2835 							    TERM_WHITE; /* usual glowing floor grids are TERM_WHITE, so lamp light shouldn't be darker (TERM_L_WHITE).. */
2836 						} else if (is_newer_than(&p_ptr->version, 4, 5, 2, 0, 0, 0) && p_ptr->view_animated_lite) {
2837 							if (is_newer_than(&p_ptr->version, 4, 5, 7, 2, 0, 0)) a = (a == TERM_L_DARK) ? TERM_LAMP_DARK : TERM_LAMP;//<-specialty: shaded ash
2838 							else a = (a == TERM_L_DARK) ? TERM_UMBER : TERM_LAMP;//<-specialty: shaded ash
2839 						}
2840 						else a = (a == TERM_L_DARK) ? TERM_UMBER : TERM_YELLOW;//<-specialty: shaded ash
2841 #else
2842 						a = TERM_YELLOW;
2843 #endif
2844 					}
2845 				}
2846 
2847 				/* Special flag */
2848 				if (p_ptr->view_shade_floor
2849 #ifndef SHADE_ALL_FLOOR
2850 				    && (!(f_ptr->flags2 & FF2_NO_SHADE) || lite_snow)
2851 #endif
2852 				    ) {
2853 					/* Handle "dark" grids */
2854 					if (!(c_ptr->info & (CAVE_GLOW | CAVE_LITE))) {
2855 						/* Use "dark gray" */
2856 						if (a != TERM_DARK) //<-hack: don't accidentally lighten up naturally-dark grids
2857 							a = TERM_L_DARK;
2858 					}
2859 					/* Handle "out-of-sight" grids */
2860 					else if (!(*w_ptr & CAVE_VIEW)) {
2861 #ifndef SHADE_ALL_FLOOR
2862 						/* Use "gray" */
2863 						if (a != TERM_DARK && a != TERM_L_DARK) //<-hack: don't accidentally lighten up naturally-dark grids (FEAT_ASH)
2864 							a = TERM_SLATE;
2865 #else
2866 						if (p_ptr->wpos.wz || !night_surface) /* not already shaded in m.c.c.daytime() above? */
2867 							a = manipulate_cave_colour_shade(c_ptr, &p_ptr->wpos, x, y, a);
2868 #endif
2869 					}
2870 				}
2871 			}
2872 			else a = manipulate_cave_colour(c_ptr, &p_ptr->wpos, x, y, a);
2873 
2874 			/* The attr */
2875 			(*ap) = a;
2876 		}
2877 
2878 		/* Unknown */
2879 		else {
2880 			/* Access darkness */
2881 			f_ptr = &f_info[FEAT_NONE];
2882 
2883 			/* Normal attr */
2884 			/* (*ap) = f_ptr->f_attr; */
2885 			(*ap) = p_ptr->f_attr[FEAT_NONE];
2886 
2887 			/* Normal char */
2888 			/* (*cp) = f_ptr->f_char; */
2889 			(*cp) = p_ptr->f_char[FEAT_NONE];
2890 		}
2891 	}
2892 
2893 	/* Non floors */
2894 	else {
2895 		/* Memorized grids */
2896 		/* Hack -- everything is visible to dungeon masters */
2897 		if ((*w_ptr & CAVE_MARK) || (p_ptr->admin_dm)) {
2898 			struct c_special *cs_ptr;
2899 
2900 			/* Apply "mimic" field */
2901 			//feat = f_info[feat].mimic;
2902 
2903 			/* Hack -- hide the secret door */
2904 			//if (feat == FEAT_SECRET && (cs_ptr = GetCS(c_ptr, CS_MIMIC)))
2905 			if ((cs_ptr = GetCS(c_ptr, CS_MIMIC))) {
2906 				feat = cs_ptr->sc.omni;
2907 			} else {
2908 				/* Apply "mimic" field */
2909 				feat = f_info[feat].mimic;
2910 			}
2911 
2912 			/* Access feature */
2913 			f_ptr = &f_info[feat];
2914 
2915 			if (!p_ptr->font_map_solid_walls) {
2916 				/* Normal char */
2917 				/* (*cp) = f_ptr->f_char; */
2918 				(*cp) = p_ptr->f_char[feat];
2919 
2920 				/* Normal attr */
2921 				/* a = f_ptr->f_attr; */
2922 				a = p_ptr->f_attr[feat];
2923 			} else { /* hack */
2924 				(*cp) = p_ptr->f_char_solid[feat];
2925 				a = p_ptr->f_attr_solid[feat];
2926 			}
2927 
2928 
2929 			/* Add trap color - Illusory wall masks everythink */
2930 			/* Hack to display detected traps */
2931 			/*
2932 			   if ((c_ptr->t_idx != 0) && (c_ptr->info & CAVE_TRDT) &&
2933 			   (c_ptr->feat != FEAT_ILLUS_WALL))
2934 			   if ((c_ptr->special.type == CS_TRAPS) && (c_ptr->special.sc.ptr->found))
2935 			*/
2936 			/* Hack to display detected traps */
2937 			if ((cs_ptr = GetCS(c_ptr, CS_TRAPS)) && c_ptr->feat != FEAT_ILLUS_WALL) {
2938 				int t_idx = cs_ptr->sc.trap.t_idx;
2939 				if (cs_ptr->sc.trap.found) {
2940 					/* Hack -- random hallucination */
2941 					if (p_ptr->image) {
2942 						image_object(ap, cp);
2943 						a = randint(15);
2944 					} else {
2945 						a = get_trap_color(Ind, t_idx, feat);
2946 					}
2947 					keep = TRUE;
2948 				}
2949 			}
2950 			/* Hack -- gee it's great to be back home */
2951 			if ((cs_ptr = GetCS(c_ptr, CS_DNADOOR))) {
2952 #if 0
2953 				if (access_door(Ind, cs_ptr->sc.ptr, FALSE)) {
2954 					a = TERM_L_GREEN;
2955 				} else {
2956 					struct dna_type *dna = cs_ptr->sc.ptr;
2957 					if (dna->owner && dna->owner_type)
2958 						a = TERM_L_DARK;
2959 				}
2960 #else
2961 				a = access_door_colour(Ind, cs_ptr->sc.ptr);
2962 #endif
2963 				keep = TRUE;
2964 			}
2965 
2966 			/* don't apply special lighting/shading on traps in 'walls' (secret doors) or closed doors */
2967 			if (keep) {
2968 				/* nothing */
2969 			}
2970 
2971 			/* Special lighting effects */
2972 			else if (p_ptr->wall_lighting &&
2973 			    (a_org = manipulate_cave_colour_season(c_ptr, &p_ptr->wpos, x, y, a)) != -1 && /* dummy */
2974 			    ((lite_snow = ((f_ptr->flags2 & FF2_LAMP_LITE_SNOW) && /* dirty snow and clean slow */
2975 			    (a_org == TERM_WHITE || a_org == TERM_L_WHITE))) ||
2976 			    (f_ptr->flags2 & (FF2_LAMP_LITE | FF2_SPECIAL_LITE)) ||
2977 			    ((f_ptr->flags2 & FF2_LAMP_LITE_OPTIONAL) && p_ptr->view_lite_extra))) {
2978 				a = manipulate_cave_colour_daytime(c_ptr, &p_ptr->wpos, x, y, a_org);
2979 
2980 				/* Handle "blind" */
2981 				if (p_ptr->blind) {
2982 					/* Use "dark gray" */
2983 					a = TERM_L_DARK;
2984 				}
2985 
2986 				/* Handle "torch-lit" grids */
2987 				else if (((f_ptr->flags2 & FF2_LAMP_LITE) ||
2988 				    ((f_ptr->flags2 & FF2_LAMP_LITE_OPTIONAL) && p_ptr->view_lite_extra) ||
2989 				    lite_snow) &&
2990 				    (c_ptr->info & CAVE_LITE)) {
2991 					/* Torch lite */
2992 					if (p_ptr->view_lamp_walls) {
2993 #ifdef CAVE_LITE_COLOURS
2994 						if ((c_ptr->info & CAVE_LITE_WHITE)) {
2995 							if (!(f_ptr->flags2 & FF2_NO_LITE_WHITEN) && a != TERM_WHITE) //don't darken max white
2996 								a = (a == TERM_L_DARK) ? TERM_SLATE ://<-specialty for magma vein/volcanic rock
2997 								    TERM_L_WHITE; /* for now: instead of TERM_WHITE; to distinguish lit granite from permanent walls */
2998 						} else if ((c_ptr->info & CAVE_LITE_VAMP)) {
2999 							//if (!(f_ptr->flags2 & FF2_NO_LITE_WHITEN)) a = TERM_SLATE; /* to make a difference to TERM_L_WHITE; for the time being (see above) */
3000 							if (!(f_ptr->flags2 & FF2_NO_LITE_WHITEN) && a != TERM_WHITE) //don't darken max white
3001 								a = (a == TERM_L_DARK) ? TERM_SLATE ://<-specialty for magma vein
3002 								    TERM_L_WHITE; /* TERM_SLATE just looks too weird */
3003 						} else if (is_newer_than(&p_ptr->version, 4, 5, 2, 0, 0, 0) && p_ptr->view_animated_lite) {
3004 							if (is_newer_than(&p_ptr->version, 4, 5, 7, 2, 0, 0)) a = (a == TERM_L_DARK) ? TERM_LAMP_DARK : TERM_LAMP;//<-specialty: shaded magma vein
3005 							else a = TERM_LAMP;//(a == TERM_L_DARK) ? TERM_L_UMBER : TERM_LAMP;//<-specialty: shaded magma vein
3006 						}
3007 						else a = (a == TERM_L_DARK) ? TERM_L_UMBER : TERM_YELLOW;//<-specialty: shaded magma vein
3008 #else
3009 						a = TERM_YELLOW;
3010 #endif
3011 					}
3012 				}
3013 
3014 				/* Handle "view_shade_walls" */
3015 				/* NOTE: The only prob here is that if magma doesn't have a different
3016 					 symbol from granite walls, for example if the player maps
3017 					 both to 'solid block' character, shaded granite walls and
3018 					 magma veins will look the same - C. Blue */
3019 				//else if (p_ptr->view_shade_walls && !(f_ptr->flags2 & FF2_NO_SHADE)) {
3020 				else if (p_ptr->view_shade_walls && (!(f_ptr->flags2 & FF2_NO_SHADE) || lite_snow)) {
3021 					/* Not glowing */
3022 					if (!(c_ptr->info & (CAVE_GLOW | CAVE_LITE))) {
3023 						/* Allow distinguishing permanent walls from granite */
3024 						if (a_org != TERM_WHITE) {
3025 							if (a_org == TERM_L_WHITE) a = TERM_SLATE;
3026 							else a = TERM_L_DARK;
3027 						}
3028 						/* don't "brighten up" if it was darkened by night */
3029 						else if (a == TERM_WHITE) a = TERM_L_WHITE;
3030 					}
3031 					/* Not viewable */
3032 					else if (!(*w_ptr & CAVE_VIEW)
3033 #ifdef DONT_SHADE_GLOW_AT_NIGHT
3034 					    && !(night_surface && !p_ptr->wpos.wz)
3035 #endif
3036 					    ) {
3037 						/* Allow distinguishing permanent walls from granite */
3038 						if (a_org != TERM_WHITE) {
3039 							if (a_org == TERM_L_WHITE) a = TERM_SLATE;
3040 							else a = TERM_L_DARK;
3041 						}
3042 						/* don't "brighten up" if it was darkened by night */
3043 						else if (a == TERM_WHITE) a = TERM_L_WHITE;
3044 					}
3045 
3046 #if 0 /* anyone know what the idea for this is? It causes a visual glitch, so disabling it for now */
3047 					/* Not glowing correctly */
3048 					else {
3049 						int xx, yy;
3050 
3051 						/* Hack -- move towards player */
3052 						yy = (y < p_ptr->py) ? (y + 1) : (y > p_ptr->py) ? (y - 1) : y;
3053 						xx = (x < p_ptr->px) ? (x + 1) : (x > p_ptr->px) ? (x - 1) : x;
3054 
3055 						/* Check for "local" illumination */
3056 						if (!(zcave[yy][xx].info & CAVE_GLOW)) {
3057 							/* Use "gray" */
3058 							a = TERM_SLATE;
3059 						}
3060 					}
3061 #endif
3062 				}
3063 			}
3064 			else a = manipulate_cave_colour(c_ptr, &p_ptr->wpos, x, y, a);
3065 
3066 			/* The attr */
3067 			(*ap) = a;
3068 
3069 			for (cs_ptr = c_ptr->special; cs_ptr; cs_ptr = cs_ptr->next) {
3070 				/* testing only - need c/a PRIORITIES!!! */
3071 				csfunc[cs_ptr->type].see(cs_ptr, cp, ap, Ind);
3072 			}
3073 		}
3074 
3075 		/* Unknown */
3076 		else {
3077 			/* Access darkness */
3078 			f_ptr = &f_info[FEAT_NONE];
3079 
3080 			/* Normal attr */
3081 			/* (*ap) = f_ptr->f_attr; */
3082 			(*ap) = p_ptr->f_attr[FEAT_NONE];
3083 
3084 			/* Normal char */
3085 			/* (*cp) = f_ptr->f_char; */
3086 			(*cp) = p_ptr->f_char[FEAT_NONE];
3087 		}
3088 	}
3089 
3090 
3091 	/**** Apply special random effects ****/
3092 /*	if (!avoid_other) */
3093 	if (((*w_ptr & CAVE_MARK) ||
3094 	((((c_ptr->info & CAVE_LITE) && (*w_ptr & CAVE_VIEW)) ||
3095 	  ((c_ptr->info & CAVE_GLOW) && (*w_ptr & CAVE_VIEW))) &&
3096 	 !p_ptr->blind)) || (p_ptr->admin_dm))
3097 	{
3098 		f_ptr = &f_info[feat];
3099 
3100 		/* Special terrain effect */
3101 		if (c_ptr->effect) {
3102 #if 0
3103 			(*ap) = spell_color(effects[c_ptr->effect].type);
3104 #else /* allow 'transparent' spells */
3105 			a = spell_color(effects[c_ptr->effect].type);
3106 			if (a != 127) (*ap) = a;
3107 #endif
3108 		}
3109 
3110 #if 1
3111 		/* Multi-hued attr */
3112 		/* TODO: this should be done in client-side too, so that
3113 		 * they shimmer when player isn't moving */
3114 		else if (f_ptr->flags1 & FF1_ATTR_MULTI) {
3115 			a = f_ptr->shimmer[rand_int(7)];
3116 
3117 			if (rand_int(8) != 1)
3118 				a = manipulate_cave_colour(c_ptr, &p_ptr->wpos, x, y, a);
3119 
3120 			(*ap) = a;
3121 		}
3122 #if 1
3123 		/* Give staircases different colours depending on dungeon flags -C. Blue :) */
3124 		if ((c_ptr->feat == FEAT_MORE) || (c_ptr->feat == FEAT_WAY_MORE) ||
3125 		    (c_ptr->feat == FEAT_WAY_LESS) || (c_ptr->feat == FEAT_LESS)) {
3126 		    struct dungeon_type *d_ptr;
3127 		    worldpos *tpos = &p_ptr->wpos;
3128 		    wilderness_type *wild = &wild_info[tpos->wy][tpos->wx];
3129 
3130 		    if (!tpos->wz) {
3131 			if ((c_ptr->feat == FEAT_MORE) || (c_ptr->feat == FEAT_WAY_MORE)) d_ptr = wild->dungeon;
3132 			else d_ptr = wild->tower;
3133 		    } else if (tpos->wz < 0) d_ptr = wild->dungeon;
3134 		    else d_ptr = wild->tower;
3135 
3136 		    /* Check for empty staircase without any connected dungeon/tower! */
3137 		    if (!d_ptr) {
3138 			    (*ap) = TERM_SLATE;
3139 		    } else {
3140 			    /* override colour from easiest to worst */
3141 			    get_staircase_colour(d_ptr, ap);
3142 		    }
3143 		}
3144 #endif
3145 
3146 #ifdef HOUSE_PAINTING
3147 		if (c_ptr->feat == FEAT_WALL_HOUSE && c_ptr->colour) {
3148  #ifdef HOUSE_PAINTING_HIDE_BAD_MODE
3149  			if (is_admin(p_ptr)) {
3150 				if (c_ptr->colour > 100) (*ap) = c_ptr->colour - 100 - 1;
3151 				else (*ap) = c_ptr->colour - 1;
3152  			} else if (c_ptr->colour > 100) {
3153 				if ((p_ptr->mode & MODE_EVERLASTING)) (*ap) = c_ptr->colour - 100 - 1;
3154 			} else {
3155 				if (!(p_ptr->mode & MODE_EVERLASTING)) (*ap) = c_ptr->colour - 1;
3156 			}
3157  #else
3158 			if (c_ptr->colour > 100) (*ap) = c_ptr->colour - 100 - 1;
3159 			else (*ap) = c_ptr->colour - 1;
3160  #endif
3161 		}
3162 #endif
3163 
3164 		/* jails */
3165 		if (c_ptr->info & CAVE_JAIL) (*ap) = TERM_L_DARK;
3166 
3167 #endif
3168 	}
3169 
3170 	/* Hack -- rare random hallucination, except on outer dungeon walls */
3171 	if (p_ptr->image && (!rand_int(256)) && !(f_info[c_ptr->feat].flags2 & FF2_BOUNDARY)) {
3172 		/* Hallucinate */
3173 		image_random(ap, cp);
3174 	}
3175 
3176 
3177 	/* Objects */
3178 	if (c_ptr->o_idx
3179 #ifdef FIX_NOTHINGS_ON_SIGHT
3180 	    && !nothing_test(&o_list[c_ptr->o_idx], p_ptr, &p_ptr->wpos, x, y, 5)
3181 #endif
3182 	    ) {
3183 		struct c_special *cs_ptr;
3184 
3185 		/* Hack - Traps override objects while searching - mikaelh */
3186 		if (!p_ptr->searching || !((cs_ptr = GetCS(c_ptr, CS_TRAPS)) && cs_ptr->sc.trap.found)) {
3187 			/* Get the actual item */
3188 			object_type *o_ptr = &o_list[c_ptr->o_idx];
3189 
3190 			/* Memorized objects */
3191 			/* Hack -- the dungeon master knows where everything is */
3192 			if ((p_ptr->obj_vis[c_ptr->o_idx]) || (p_ptr->admin_dm)) {
3193 				/* Normal char */
3194 				(*cp) = object_char(o_ptr);
3195 
3196 				/* Normal attr */
3197 				(*ap) = object_attr(o_ptr);
3198 
3199 				/* Hack -- always l.blue if underwater */
3200 //				if (feat == FEAT_WATER)
3201 				if (feat == FEAT_DEEP_WATER || feat == FEAT_SHAL_WATER)
3202 					(*ap) = TERM_L_BLUE;
3203 
3204 				/* hacks: mindcrafter 'crystals' are yellow, custom books' colour depends on their content! - C. Blue */
3205 				if (o_ptr->tval == TV_BOOK) {
3206 					if (o_ptr->pval >= __lua_M_FIRST && o_ptr->pval <= __lua_M_LAST)
3207 						(*ap) = TERM_YELLOW;
3208 					else if (is_custom_tome(o_ptr->sval))
3209 						(*ap) = get_book_name_color(Ind, o_ptr);
3210 				}
3211 
3212 				/* hack: colour of fancy shirts or custom objects can vary  */
3213 				if ((o_ptr->tval == TV_SOFT_ARMOR && o_ptr->sval == SV_SHIRT) ||
3214 				    (o_ptr->tval == TV_SPECIAL && o_ptr->sval == SV_CUSTOM_OBJECT)) {
3215 					if (!o_ptr->xtra1) o_ptr->xtra1 = (*ap); //wut.. remove this hack? should be superfluous anyway
3216 					(*ap) = o_ptr->xtra1;
3217 					/* new: also allow custom char */
3218 					if (o_ptr->xtra2) (*cp) = o_ptr->xtra2;
3219 				}
3220 
3221 				/* quest items can have custom appearance too */
3222 				if (o_ptr->tval == TV_SPECIAL && o_ptr->sval == SV_QUEST) {
3223 					(*cp) = o_ptr->xtra1;
3224 					(*ap) = o_ptr->xtra2;
3225 				}
3226 
3227 				/* Abnormal attr */
3228 /*      	                  if ((!avoid_other) && (!(((*ap) & 0x80) && ((*cp) & 0x80))) && (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) (*ap) = get_shimmer_color(); */
3229 				if (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)
3230 #ifdef CLIENT_SHIMMER
3231 					(*ap) = TERM_HALF;
3232 #else
3233 					(*ap) = get_shimmer_color();
3234 #endif
3235 /*					(*ap) = randint(15); */
3236 
3237 				/* hack: questors may have specific attr */
3238 				if (o_ptr->questor) (*ap) = q_info[o_ptr->quest - 1].questor[o_ptr->questor_idx].oattr;
3239 
3240 				/* Hack -- hallucination */
3241 				if (p_ptr->image) image_object(ap, cp);
3242 			}
3243 		}
3244 	}
3245 
3246 
3247 	/* Handle monsters */
3248 	if (c_ptr->m_idx > 0) {
3249 		monster_type *m_ptr = &m_list[c_ptr->m_idx];
3250 
3251 		if (c_ptr->m_idx >= m_max) {
3252 			/* Clear invalid monster references - mikaelh */
3253 
3254 			/* Log it */
3255 			s_printf("MIDX_FIX: Cleared an invalid monster reference (m_idx = %d, m_max = %d) (wpos = %d, %d, %d) (x = %d, y = %d)\n", c_ptr->m_idx, m_max, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz, x, y);
3256 
3257 			c_ptr->m_idx = 0;
3258 		}
3259 
3260 		/* Visible monster */
3261 		if (p_ptr->mon_vis[c_ptr->m_idx]) {
3262 			monster_race *r_ptr = race_inf(m_ptr);
3263 
3264 			/* hack: mindcrafters/rogues can see through
3265 			   shadowing (shadowed ego) / cloaking (master thief ego) */
3266 			if ((p_ptr->pclass == CLASS_MINDCRAFTER || p_ptr->pclass == CLASS_ROGUE) && p_ptr->lev >= 30 &&
3267 #if 0 /* this works, but maybe let's be more specific, in case some exceptional new re-power gets added that shouldn't be affected.. */
3268 			    (r_ptr->flags1 & RF1_CHAR_CLEAR) && (r_ptr->flags1 & RF1_ATTR_CLEAR) &&
3269 			    !(r_info[m_ptr->r_idx].flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)))
3270 #else
3271 			    (m_ptr->ego == RE_MASTER_THIEF || m_ptr->ego == RE_SHADOWED))
3272 #endif
3273 				/* slightly paranoid: we only remove the flags that REALLY weren't
3274 				   in the base version.. such cases shouldn't really occur though */
3275 				r_ptr->flags1 &= ~((r_ptr->flags1 & RF1_CHAR_CLEAR) | (r_ptr->flags1 & RF1_ATTR_CLEAR));
3276 
3277 			get_monster_color(Ind, m_ptr, r_ptr, c_ptr, ap, cp);
3278 		}
3279 	}
3280 
3281 	/* -APD-
3282 	   Taking D. Gandy's advice and making it display the char as a number if
3283 	   they are severly wounded (60% health or less)
3284 	   I multiply by 95 instead of 100 because it always rounds down.....
3285 	   and I want to give PCs a little more breathing room.
3286 	 */
3287 
3288 	else if (c_ptr->m_idx < 0) {
3289 		int Ind2 = 0 - c_ptr->m_idx;
3290 		player_type *p2_ptr = Players[Ind2];
3291 
3292 		if (!p2_ptr) {
3293 			/* Clear invalid players, I'm tired of crashes - mikaelh */
3294 			c_ptr->m_idx = 0;
3295 
3296 			/* Log it */
3297 			s_printf("MIDX_FIX: Cleared an invalid player m_idx (Ind = %d) (wpos = %d, %d, %d) (x = %d, y = %d)\n", Ind2, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz, x, y);
3298 		}
3299 
3300 		/* Check for doppelgangers - mikaelh */
3301 		else if (memcmp(&p_ptr->wpos, &p2_ptr->wpos, sizeof(struct worldpos)) != 0 || x != p2_ptr->px || y != p2_ptr->py) {
3302 			/* Clear doppelgangers */
3303 			c_ptr->m_idx = 0;
3304 
3305 			/* Log it */
3306 			s_printf("MIDX_FIX: Cleared a doppelganger (Ind = %d, \"%s\") (wpos = %d, %d, %d) (x = %d, y = %d)\n", Ind2, Players[Ind2]->name, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz, x, y);
3307 		}
3308 
3309 		/* Is that player visible? */
3310 		else if (p_ptr->play_vis[Ind2]) {
3311 			/* part 'A' now here (experimental, see below) */
3312 
3313 			/* Hack: For monster-forms, player_color() calls get_monster_color() which will
3314 			   result in color flickering if player is hallucinating, although this call
3315 			   should instead determine the colour an _outside_ player gets to see. So we
3316 			   have to temporarily suppress his hallucinations to get the correct value. */
3317 			int tmp_image = p2_ptr->image;
3318 			p2_ptr->image = 0;
3319 			a = player_color(Ind2);
3320 			p2_ptr->image = tmp_image;
3321 
3322 #if 0 /* player_color() should already handle all of this - C. Blue */
3323 			if ((p2_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p2_ptr->inventory[INVEN_BODY].sval == SV_COSTUME)) {
3324 				get_monster_color(Ind, NULL, &r_info[p2_ptr->inventory[INVEN_BODY].bpval], c_ptr, &a, &c);
3325 			}
3326 			else if (p2_ptr->body_monster) get_monster_color(Ind, NULL, &r_info[p2_ptr->body_monster], c_ptr, &a, &c);
3327 			else if (p2_ptr->fruit_bat) c = 'b';
3328 			else c = '@';
3329 #else
3330 			if ((p2_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p2_ptr->inventory[INVEN_BODY].sval == SV_COSTUME)) {
3331 				c = r_info[p2_ptr->inventory[INVEN_BODY].bpval].d_char;
3332 			}
3333 			else if (p2_ptr->body_monster) {
3334 				c = r_info[p2_ptr->body_monster].d_char;
3335 #if 1 /* just for fun */
3336 				if (p2_ptr->body_monster == RI_DOOR_MIMIC && p2_ptr->dummy_option_7) c = '\'';
3337 #endif
3338 			}
3339 			else if (p2_ptr->fruit_bat) c = 'b';
3340 			else c = '@';
3341 
3342 #endif
3343 			/* Always show party members as dark grey @. Allow pvp flickers still */
3344 			if (p_ptr->consistent_players) {
3345 				c = '@';
3346 				a = TERM_L_DARK;
3347 				if (p_ptr->black_breath && magik(50)) {
3348 					a = TERM_SLATE;
3349 				}
3350 			}
3351 
3352 			/* part 'A' end */
3353 
3354 			/* TERM_BNW if blood bonded - mikaelh */
3355 			if (check_blood_bond(Ind, Ind2))
3356 #ifdef EXTENDED_TERM_COLOURS
3357 				a |= is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0) ? TERM_OLD_BNW : TERM_BNW;
3358 #else
3359 				a |= TERM_BNW;
3360 #endif
3361 			/* new: renamed TERM_RLE (unused) to TERM_PVP for use for this: - C. Blue */
3362 			else if (is_newer_than(&p_ptr->version, 4, 4, 2, 0, 0, 0) &&
3363 			    (check_hostile(Ind, Ind2) || p2_ptr->stormbringer))
3364 #ifdef EXTENDED_TERM_COLOURS
3365 				a |= is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0) ? TERM_OLD_PVP : TERM_PVP;
3366 #else
3367 				a |= TERM_PVP;
3368 #endif
3369 
3370 			if (((p2_ptr->chp * 95) / (p2_ptr->mhp * 10)) > TURN_CHAR_INTO_NUMBER) {
3371 				/* part 'A' used to be here */
3372 			} else {
3373 				if (p2_ptr->chp < 0) c = '-';
3374 				else {
3375 					int num;
3376 					num = (p2_ptr->chp * 95) / (p2_ptr->mhp * 10);
3377 					c = '0' + num;
3378 				}
3379 			}
3380 
3381 			/* admins sees intensity of mana shields */
3382 			if (p_ptr->admin_dm && p2_ptr->tim_manashield && p2_ptr->msp > 0) {
3383 				if (((p2_ptr->csp * 100) / (p2_ptr->msp * 10)) < 10) {
3384 					int num;
3385 					num = (p2_ptr->csp * 100) / (p2_ptr->msp * 10);
3386 					c = '0' + num;
3387 				}
3388 			}
3389 
3390 			(*cp) = c;
3391 			(*ap) = a;
3392 
3393 			if (p_ptr->image) {
3394 				/* Change the other player into a hallucination */
3395 				image_monster(ap, cp);
3396 			}
3397 		}
3398 	}
3399 
3400 
3401 	if (!c_ptr->effect) return;
3402 
3403 	/* display blue raindrops */
3404 	if ((effects[c_ptr->effect].flags & EFF_RAINING)) {
3405 		(*ap) = TERM_BLUE;
3406 		if (wind_gust > 0) (*cp) = '/';
3407 		else if (wind_gust < 0) (*cp) = '\\';
3408 		else (*cp) = '|';
3409 	}
3410 	/* for WINTER_SEASON */
3411 	/* display white snowflakes */
3412 	if ((effects[c_ptr->effect].flags & EFF_SNOWING)) {
3413 		(*ap) = TERM_WHITE;
3414 		(*cp) = '*'; /* a little bit large maybe, but '.' won't be noticed on the other hand? */
3415 	}
3416 	/* for NEW_YEARS_EVE */
3417 	/* display fireworks */
3418 	if ((effects[c_ptr->effect].flags & (EFF_FIREWORKS1 | EFF_FIREWORKS2 | EFF_FIREWORKS3))) {
3419 		switch (effects[c_ptr->effect].type) {
3420 		case GF_FW_FIRE: (*ap) = TERM_FIRE; break;
3421 		case GF_FW_ELEC: (*ap) = TERM_ELEC; break;
3422 		case GF_FW_POIS: (*ap) = TERM_POIS; break;
3423 		case GF_FW_LITE: (*ap) = TERM_LITE; break;
3424 		case GF_FW_SHDI: (*ap) = TERM_SHIELDI; break;
3425 		case GF_FW_SHDM: (*ap) = TERM_SHIELDM; break;
3426 		case GF_FW_MULT: (*ap) = TERM_MULTI; break;
3427 		}
3428 		(*cp) = '*'; /* a little bit large maybe, but '.' won't be noticed on the other hand? */
3429 	}
3430 	/* for Nether Realm finishing */
3431 	if ((effects[c_ptr->effect].flags & (EFF_LIGHTNING1 | EFF_LIGHTNING2 | EFF_LIGHTNING3))) {
3432 		(*ap) = TERM_LITE;
3433 		switch (c_ptr->effect_xtra) {
3434 		case 0: (*cp) = '|'; break;
3435 		case 1: (*cp) = '/'; break;
3436 		case -1: (*cp) = '\\'; break;
3437 		case 2: (*cp) = '_'; break;
3438 		default: (*cp) = '*';
3439 		}
3440 	}
3441 
3442 /* #ifdef ARCADE_SERVER
3443         if ((effects[c_ptr->effect].flags & EFF_CROSSHAIR_A) || (effects[c_ptr->effect].flags & EFF_CROSSHAIR_B) || (effects[c_ptr->effect].flags & EFF_CROSSHAIR_C))
3444         {
3445 	        (*ap) = TERM_L_UMBER;
3446 	        (*cp) = '+';
3447         }
3448 #endif */
3449 }
3450 
3451 
3452 /*
3453  * Memorize the given grid (or object) if it is "interesting"
3454  *
3455  * This function should only be called on "legal" grids.
3456  *
3457  * This function should be called every time the "memorization" of
3458  * a grid (or the object in a grid) is called into question.
3459  *
3460  * Note that the player always memorized all "objects" which are seen,
3461  * using a different method than the one used for terrain features,
3462  * which not only allows a lot of optimization, but also prevents the
3463  * player from "knowing" when objects are dropped out of sight but in
3464  * memorized grids.
3465  *
3466  * Note that the player always memorizes "interesting" terrain features
3467  * (everything but floors and invisible traps).  This allows incredible
3468  * amounts of optimization in various places.
3469  *
3470  * Note that the player is allowed to memorize floors and invisible
3471  * traps under various circumstances, and with various options set.
3472  *
3473  * This function is slightly non-optimal, since it memorizes objects
3474  * and terrain features separately, though both are dependant on the
3475  * "player_can_see_bold()" macro.
3476  */
3477 void note_spot(int Ind, int y, int x)
3478 {
3479 	player_type *p_ptr = Players[Ind];
3480 	byte *w_ptr = &p_ptr->cave_flag[y][x];
3481 
3482 	cave_type **zcave;
3483 	cave_type *c_ptr;
3484 	if (!(zcave = getcave(&p_ptr->wpos))) return;
3485 	c_ptr = &zcave[y][x];
3486 
3487 	/* Hack -- memorize objects */
3488 	if (c_ptr->o_idx) {
3489 		/* Only memorize once */
3490 		if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
3491 			/* Memorize visible objects */
3492 			if (player_can_see_bold(Ind, y, x)) {
3493 				/* Memorize */
3494 				p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
3495 
3496 			}
3497 		}
3498 	}
3499 
3500 
3501 	/* Hack -- memorize grids */
3502 	if (!(*w_ptr & CAVE_MARK)) {
3503 		/* Memorize visible grids */
3504 		if (player_can_see_bold(Ind, y, x)) {
3505 			/* Memorize normal features */
3506 			if (!cave_plain_floor_grid(c_ptr)) {
3507 				/* Memorize */
3508 				*w_ptr |= CAVE_MARK;
3509 			}
3510 
3511 			/* Option -- memorize all perma-lit floors */
3512 			else if (p_ptr->view_perma_grids && (c_ptr->info & CAVE_GLOW)) {
3513 				/* Memorize */
3514 				*w_ptr |= CAVE_MARK;
3515 			}
3516 
3517 			/* Option -- memorize all torch-lit floors */
3518 			else if (p_ptr->view_torch_grids && (c_ptr->info & CAVE_LITE)) {
3519 				/* Memorize */
3520 				*w_ptr |= CAVE_MARK;
3521 			}
3522 		}
3523 	}
3524 }
3525 
3526 
3527 void note_spot_depth(struct worldpos *wpos, int y, int x)
3528 {
3529 	int i;
3530 
3531 	for (i = 1; i < NumPlayers + 1; i++)
3532 	{
3533 		if (Players[i]->conn == NOT_CONNECTED)
3534 			continue;
3535 
3536 		if (inarea(wpos, &Players[i]->wpos))
3537 		{
3538 			note_spot(i, y, x);
3539 		}
3540 	}
3541 }
3542 
3543 void everyone_lite_spot(struct worldpos *wpos, int y, int x)
3544 {
3545 	int i;
3546 
3547 	/* Check everyone */
3548 	for (i = 1; i < NumPlayers + 1; i++)
3549 	{
3550 		/* If he's not playing, skip him */
3551 		if (Players[i]->conn == NOT_CONNECTED)
3552 			continue;
3553 
3554 		/* If he's not here, skip him */
3555 		if (!inarea(wpos, &Players[i]->wpos))
3556 			continue;
3557 
3558 		/* Actually lite that spot for that player */
3559 		lite_spot(i, y, x);
3560 	}
3561 }
3562 
3563 void everyone_clear_ovl_spot(struct worldpos *wpos, int y, int x)
3564 {
3565 	int i;
3566 
3567 	/* Check everyone */
3568 	for (i = 1; i < NumPlayers + 1; i++) {
3569 		/* If he's not playing, skip him */
3570 		if (Players[i]->conn == NOT_CONNECTED)
3571 			continue;
3572 
3573 		/* If he's not here, skip him */
3574 		if (!inarea(wpos, &Players[i]->wpos))
3575 			continue;
3576 
3577 		/* Actually clear the overlay on that spot for that player */
3578 		clear_ovl_spot(i, y, x);
3579 	}
3580 }
3581 
3582 /*
3583  * Wipe the "CAVE_MARK" bit in everyone's array
3584  */
3585 void everyone_forget_spot(struct worldpos *wpos, int y, int x)
3586 {
3587 	int i;
3588 
3589 	/* Check everyone */
3590 	for (i = 1; i < NumPlayers + 1; i++)
3591 	{
3592 		/* If he's not playing, skip him */
3593 		if (Players[i]->conn == NOT_CONNECTED)
3594 			continue;
3595 
3596 		/* If he's not here, skip him */
3597 		if (!inarea(wpos, &Players[i]->wpos))
3598 			continue;
3599 
3600 		/* Forget the spot */
3601 		Players[i]->cave_flag[y][x] &= ~CAVE_MARK;
3602 	}
3603 }
3604 
3605 /*
3606  * Redraw (on the screen) a given MAP location
3607  */
3608 void lite_spot(int Ind, int y, int x)
3609 {
3610 	player_type *p_ptr = Players[Ind];
3611 	bool is_us = FALSE;
3612 
3613 	/* Redraw if on screen */
3614 	if (panel_contains(y, x)) {
3615 		int dispx, dispy;
3616 
3617 		byte a;
3618 		char c;
3619 
3620 		/* Handle "player" */
3621 		if ((y == p_ptr->py) && (x == p_ptr->px)) {
3622 			monster_race *r_ptr = &r_info[p_ptr->body_monster];
3623 
3624 			if ((p_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p_ptr->inventory[INVEN_BODY].sval == SV_COSTUME)) {
3625 				r_ptr = &r_info[p_ptr->inventory[INVEN_BODY].bpval];
3626 			}
3627 
3628 			/* Get the "player" attr */
3629 			a = r_ptr->d_attr;
3630 
3631 			/* Get the "player" char */
3632 			c = r_ptr->d_char;
3633 #if 1 /* just for fun */
3634 			if (p_ptr->body_monster == RI_DOOR_MIMIC && p_ptr->dummy_option_7) c = '\'';
3635 #endif
3636 
3637 /*			if (p_ptr->invis && !p_ptr->body_monster) {  - hmm why not always TERM_VIOLET */
3638 			if (p_ptr->invis) {
3639 				/* special invis colour */
3640 				a = TERM_VIOLET;
3641 			}
3642 			if (p_ptr->cloaked == 1) {
3643 				if (p_ptr->cloak_neutralized) a = TERM_SLATE;
3644 				else a = TERM_L_DARK;
3645 			}
3646 			/* Mana Shield and GOI also flicker */
3647 			if (p_ptr->tim_manashield && rand_int(2)) {
3648 				if (p_ptr->tim_manashield > 15) {
3649 					/* prevent too much violet colour in our mix.. */
3650 					if (a != TERM_VIOLET)
3651 						a = (randint(2) < 2) ? TERM_VIOLET : TERM_ORANGE;
3652 					else
3653 						a = (randint(2) < 2) ? TERM_L_RED : TERM_ORANGE;
3654 				} else {
3655 					a = TERM_BNW;
3656 				}
3657 			}
3658 			if (p_ptr->invuln && rand_int(4)) {
3659 				if (p_ptr->invuln > 5) {
3660 					switch (randint(5)) {
3661 					case 1: a = TERM_L_RED; break;
3662 					case 2: a = TERM_L_GREEN; break;
3663 					case 3: a = TERM_L_BLUE; break;
3664 					case 4: a = TERM_YELLOW; break;
3665 					case 5: a = TERM_VIOLET; break;
3666 					}
3667 				} else if (p_ptr->invuln_dur >= 5) { /* avoid animating normal stair-GoI */
3668 					a = TERM_BNW;
3669 				}
3670 			}
3671 
3672 			/* notice own Black Breath by colour instead just from occasional message */
3673 			if (p_ptr->black_breath && magik(50)) a = TERM_L_DARK;
3674 
3675 			/* see oneself burning in the sun */
3676 			if (p_ptr->sun_burn && magik(33)) a = TERM_FIRE;
3677 
3678 			/* Polymorph ring power running out */
3679 			if (p_ptr->tim_mimic && p_ptr->body_monster == p_ptr->tim_mimic_what && p_ptr->tim_mimic <= 100) {
3680 				if (!rand_int(10)) {
3681 					a = TERM_DISE;
3682 					c = '@';
3683 				}
3684 			}
3685 
3686 			/* Holy Martyr */
3687 			/* Admin wizards sometimes flicker black & white (TERM_BNW) */
3688 			if (p_ptr->shadow_running || p_ptr->martyr || p_ptr->admin_wiz)
3689 #ifdef EXTENDED_TERM_COLOURS
3690 				a += is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0) ? TERM_OLD_BNW : TERM_BNW;
3691 #else
3692 				a += TERM_BNW;
3693 #endif
3694 
3695 			if (p_ptr->team) {
3696 				if (magik(25)) { /* chance for showing him/her which team (s)he's in - mikaelh */
3697 					switch(p_ptr->team) {
3698 						case 1:
3699 							a = TERM_L_RED;
3700 							break;
3701 						case 2:
3702 							a = TERM_L_BLUE;
3703 							break;
3704 						default:
3705 							break;
3706 					}
3707 				}
3708 				else if ((has_ball(p_ptr) != -1) && magik(25)) a = TERM_ORANGE; /* game ball carrier has orange flickering - mikaelh */
3709 			}
3710 
3711 
3712 			if (p_ptr->consistent_players) {
3713 				a = TERM_WHITE;
3714 				if (p_ptr->tim_mimic > 0 && p_ptr->body_monster == p_ptr->tim_mimic_what) {
3715 					if (p_ptr->tim_mimic <= 100 && !rand_int(10)) a = TERM_WHITE;
3716 					else a = TERM_ORANGE;
3717 				}
3718 				if (p_ptr->tim_manashield && p_ptr->msp > 0 && p_ptr->csp > 0) {
3719 					a = TERM_YELLOW;
3720 				}
3721 				if (p_ptr->black_breath && magik(50)) {
3722 					a = TERM_SLATE;
3723 				}
3724 			}
3725 
3726 #ifdef ENABLE_SELF_FLASHING
3727 			/* display player in really easily spottable colours */
3728 			if (p_ptr->flash_self > 0) a = (p_ptr->flash_self % 2) ? TERM_L_RED : TERM_L_GREEN;
3729 #endif
3730 
3731 			/* bugfix on MASSIVE deaths (det/death) */
3732 			if (p_ptr->fruit_bat && !p_ptr->body_monster &&
3733 				!((p_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p_ptr->inventory[INVEN_BODY].sval == SV_COSTUME))) c = 'b';
3734 
3735 			if (p_ptr->consistent_players) c = '@';
3736 
3737 			if (p_ptr->chp < 0) c = '-';
3738 			else if (!p_ptr->tim_manashield) {
3739 				if (((p_ptr->chp * 95) / (p_ptr->mhp*10)) <= TURN_CHAR_INTO_NUMBER) {
3740 					int num;
3741 					num = (p_ptr->chp * 95) / (p_ptr->mhp * 10);
3742 					c = '0' + num;
3743 				}
3744 			} else if (p_ptr->msp > 0) {
3745 				if (((p_ptr->csp * 95) / (p_ptr->msp * 10)) <= TURN_CHAR_INTO_NUMBER) {
3746 					int num;
3747 					num = (p_ptr->csp * 95) / (p_ptr->msp * 10);
3748 					c = '0' + num;
3749 				}
3750 			}
3751 
3752 
3753 			/* >4.5.4: Mark that it is the player himself */
3754 			if (p_ptr->hilite_player) is_us = TRUE;
3755 		}
3756 
3757 		/* Normal (not player coords) */
3758 		else {
3759 			/* Examine the grid */
3760 			map_info(Ind, y, x, &a, &c);
3761 		}
3762 
3763 		/* Hack -- fake monochrome */
3764 		if (!use_color)  a = TERM_WHITE;
3765 
3766 		dispx = x - p_ptr->panel_col_prt;
3767 		dispy = y - p_ptr->panel_row_prt;
3768 
3769 		/* Only draw if different than buffered */
3770 		if (p_ptr->scr_info[dispy][dispx].c != c ||
3771 		    p_ptr->scr_info[dispy][dispx].a != a ||
3772 		    (x == p_ptr->px && y == p_ptr->py && !p_ptr->afk)) /* let's try disabling this when AFK to save bandwidth - mikaelh */
3773 		{
3774 			/* Modify screen buffer */
3775 			p_ptr->scr_info[dispy][dispx].c = c;
3776 			p_ptr->scr_info[dispy][dispx].a = a;
3777 
3778 			/* Compare against the overlay buffer */
3779 			if ((p_ptr->ovl_info[dispy][dispx].c != c) ||
3780 			    (p_ptr->ovl_info[dispy][dispx].a != a))
3781 			{
3782 				/* Tell client to redraw this grid */
3783 				if (is_us && is_newer_than(&p_ptr->version, 4, 5, 4, 0, 0, 0)) c |= 0x80;
3784 				Send_char(Ind, dispx, dispy, a, c);
3785 			}
3786 
3787 			/* Clear the overlay buffer */
3788 			p_ptr->ovl_info[dispy][dispx].c = 0;
3789 			p_ptr->ovl_info[dispy][dispx].a = 0;
3790 		}
3791 	}
3792 }
3793 
3794 
3795 /*
3796  * Draw something on the overlay layer.
3797  */
3798 void draw_spot_ovl(int Ind, int y, int x, byte a, char c)
3799 {
3800 	player_type *p_ptr = Players[Ind];
3801 
3802 	/* Redraw if on screen */
3803 	if (panel_contains(y, x))
3804 	{
3805 		int dispx, dispy;
3806 
3807 		/* Handle "player" */
3808 		if ((y == p_ptr->py) && (x == p_ptr->px))
3809 		{
3810 			/* Never redraw the player */
3811 			return;
3812 		}
3813 
3814 		/* Hack -- fake monochrome */
3815 		if (!use_color) a = TERM_WHITE;
3816 
3817 		dispx = x - p_ptr->panel_col_prt;
3818 		dispy = y - p_ptr->panel_row_prt;
3819 
3820 		/* Only draw if different than buffered */
3821 		if (p_ptr->ovl_info[dispy][dispx].c != c ||
3822 		    p_ptr->ovl_info[dispy][dispx].a != a)
3823 		{
3824 			/* Modify internal buffer */
3825 			p_ptr->ovl_info[dispy][dispx].c = c;
3826 			p_ptr->ovl_info[dispy][dispx].a = a;
3827 
3828 			/* Tell client to redraw this grid */
3829 			Send_char(Ind, dispx, dispy, a, c);
3830 		}
3831 	}
3832 }
3833 
3834 
3835 /*
3836  * Clear a spot on the overlay layer.
3837  */
3838 void clear_ovl_spot(int Ind, int y, int x)
3839 {
3840 	player_type *p_ptr = Players[Ind];
3841 
3842 	/* Redraw if on screen */
3843 	if (panel_contains(y, x)) {
3844 		int dispx, dispy;
3845 
3846 		dispx = x - p_ptr->panel_col_prt;
3847 		dispy = y - p_ptr->panel_row_prt;
3848 
3849 		if (p_ptr->ovl_info[dispy][dispx].c) {
3850 			/* Check if the overlay buffer is different from the screen buffer */
3851 			if ((p_ptr->ovl_info[dispy][dispx].a != p_ptr->scr_info[dispy][dispx].a) ||
3852 			    (p_ptr->ovl_info[dispy][dispx].c != p_ptr->scr_info[dispy][dispx].c)) {
3853 				/* Clear the overlay buffer */
3854 				p_ptr->ovl_info[dispy][dispx].c = 0;
3855 				p_ptr->ovl_info[dispy][dispx].a = 0;
3856 
3857 				/* Clear the screen buffer to force redraw */
3858 				p_ptr->scr_info[dispy][dispx].c = 0;
3859 				p_ptr->scr_info[dispy][dispx].a = 0;
3860 
3861 				/* Redraw */
3862 				lite_spot(Ind, y, x);
3863 			} else {
3864 				/* Clear the overlay buffer */
3865 				p_ptr->ovl_info[dispy][dispx].c = 0;
3866 				p_ptr->ovl_info[dispy][dispx].a = 0;
3867 
3868 				/* No redraw needed */
3869 			}
3870 		}
3871 	}
3872 }
3873 
3874 
3875 /*
3876  * Clear the entire overlay ler.
3877  */
3878 void clear_ovl(int Ind)
3879 {
3880 	player_type *p_ptr = Players[Ind];
3881 
3882 	int y, x;
3883 
3884 	for (y = p_ptr->panel_row_min; y <= p_ptr->panel_row_max; y++) {
3885 		for (x = p_ptr->panel_col_min; x <= p_ptr->panel_col_max; x++) {
3886 			clear_ovl_spot(Ind, y, x);
3887 		}
3888 	}
3889 }
3890 
3891 
3892 
3893 
3894 
3895 /*
3896  * Prints the map of the dungeon
3897  *
3898  * Note that, for efficiency, we contain an "optimized" version
3899  * of both "lite_spot()" and "print_rel()", and that we use the
3900  * "lite_spot()" function to display the player grid, if needed.
3901  */
3902 
3903 void prt_map(int Ind)
3904 {
3905 	player_type *p_ptr = Players[Ind];
3906 
3907 	int x, y;
3908 	int dispx, dispy;
3909 	byte a;
3910 	char c;
3911 
3912 	/* Make sure he didn't just change depth */
3913 	if (p_ptr->new_level_flag) return;
3914 
3915 	/* First clear the old stuff */
3916 	memset(p_ptr->scr_info, 0, sizeof(p_ptr->scr_info));
3917 
3918 	/* Clear the overlay buffer */
3919 	memset(p_ptr->ovl_info, 0, sizeof(p_ptr->ovl_info));
3920 
3921 	/* Dump the map */
3922 	for (y = p_ptr->panel_row_min; y <= p_ptr->panel_row_max; y++)
3923 	{
3924 		dispy = y - p_ptr->panel_row_prt;
3925 
3926 		/* Scan the columns of row "y" */
3927 		for (x = p_ptr->panel_col_min; x <= p_ptr->panel_col_max; x++)
3928 		{
3929 			/* Determine what is there */
3930 			map_info(Ind, y, x, &a, &c);
3931 
3932 			/* Hack -- fake monochrome */
3933 			if (!use_color) a = TERM_WHITE;
3934 
3935 			dispx = x - p_ptr->panel_col_prt;
3936 
3937 			/* Redraw that grid of the map */
3938 			p_ptr->scr_info[dispy][dispx].c = c;
3939 			p_ptr->scr_info[dispy][dispx].a = a;
3940 		}
3941 
3942 		/* Send that line of info */
3943 		Send_line_info(Ind, dispy);
3944 	}
3945 
3946 	/* Display player */
3947 	lite_spot(Ind, p_ptr->py, p_ptr->px);
3948 }
3949 
3950 
3951 
3952 
3953 /*
3954  * Display highest priority object in the RATIO by RATIO area
3955  */
3956 /*#define RATIO 3 */
3957 
3958 /*
3959  * Display the entire map
3960  */
3961 #define MAP_HGT (MAX_HGT / RATIO)
3962 #define MAP_WID (MAX_WID / RATIO)
3963 
3964 /*
3965  * Hack -- priority array (see below)
3966  *
3967  * Note that all "walls" always look like "secret doors" (see "map_info()").
3968  */
3969 static byte priority_table[][2] = {
3970 	/* Dark */
3971 	{ FEAT_NONE, 2 },
3972 
3973 	/* Dirt */
3974 	{ FEAT_DIRT, 3 },
3975 	{ FEAT_SAND, 3},
3976 	{ FEAT_MUD, 3},
3977 
3978 	/* Grass */
3979 	{ FEAT_GRASS, 4 },
3980 	{ FEAT_ASH, 4},
3981 	{ FEAT_ICE, 4},
3982 
3983 	/* Tree */
3984 	{ FEAT_BUSH, 5 },
3985 	{ FEAT_DEAD_TREE, 6 },
3986 	{ FEAT_TREE, 6 },
3987 
3988 	/* Water */
3989 	{ FEAT_DEEP_WATER, 7 },
3990 
3991 	/* Floors */
3992 	{ FEAT_FLOOR, 8 },
3993 
3994 	/* Walls */
3995 	{ FEAT_SECRET, 10 },
3996 
3997 	/* Quartz */
3998 	{ FEAT_QUARTZ, 11 },
3999 
4000 	/* Magma */
4001 	{ FEAT_MAGMA, 12 },
4002 
4003 	/* Rubble */
4004 	{ FEAT_RUBBLE, 13 },
4005 
4006 	/* Open doors */
4007 	{ FEAT_OPEN, 15 },
4008 	{ FEAT_BROKEN, 15 },
4009 
4010 	/* Closed doors */
4011 	{ FEAT_DOOR_HEAD + 0x00, 17 },
4012 
4013 	/* Hidden gold */
4014 	{ FEAT_QUARTZ_K, 19 },
4015 	{ FEAT_MAGMA_K, 19 },
4016 
4017 	/* water, lava, & trees oh my! -KMW- */
4018 	{ FEAT_DEEP_WATER, 20 },
4019 	{ FEAT_SHAL_WATER, 20 },
4020 	{ FEAT_DEEP_LAVA, 20 },
4021 	{ FEAT_SHAL_LAVA, 20 },
4022 	{ FEAT_DARK_PIT, 20 },
4023 	{ FEAT_MOUNTAIN, 20 },
4024 
4025 	/* Fountain */
4026 	{ FEAT_FOUNTAIN, 21 },
4027 	{ FEAT_FOUNTAIN_BLOOD, 21 },
4028 	{ FEAT_EMPTY_FOUNTAIN, 21 },
4029 
4030 	{ FEAT_SEALED_DOOR, 22 }, /* for pvp-arena */
4031 	{ FEAT_UNSEALED_DOOR, 22},
4032 	{ FEAT_ESCAPE_DOOR, 22}, /* for quests */
4033 
4034 	/* Shops */
4035 	{ FEAT_SHOP, 23 },
4036 
4037 	/* Void Jump Gates */
4038 	{ FEAT_BETWEEN_TEMP, 24 },
4039 	{ FEAT_BETWEEN, 24 },
4040 
4041 	/* Stairs */
4042 	{ FEAT_LESS, 25 },
4043 	{ FEAT_MORE, 25 },
4044 
4045 	/* Stairs */
4046 	{ FEAT_WAY_LESS, 25 },
4047 	{ FEAT_WAY_MORE, 25 },
4048 
4049 	{ FEAT_SHAFT_UP, 25 },
4050 	{ FEAT_SHAFT_DOWN, 25 },
4051 
4052 	/* Event Beacon (Dungeon Keeper) */
4053 	{ FEAT_BEACON, 26 },
4054 
4055 	/* End */
4056 	{ 0, 0 }
4057 };
4058 
4059 
4060 /*
4061  * Hack -- a priority function (see below)
4062  */
4063 static byte priority(byte a, char c) {
4064 	int i, p0, p1;
4065 
4066 	feature_type *f_ptr;
4067 
4068 	/* hack for shops: every shop's base door is actually '1' */
4069 	if (c >= '1' && c <= '9') c = '1';
4070 
4071 	/* Scan the table */
4072 	for (i = 0; TRUE; i++) {
4073 		/* Priority level */
4074 		p1 = priority_table[i][1];
4075 
4076 		/* End of table */
4077 		if (!p1) break;
4078 
4079 		/* Feature index */
4080 		p0 = priority_table[i][0];
4081 
4082 		/* Access the feature */
4083 		f_ptr = &f_info[p0];
4084 
4085 		/* Check character and attribute, accept matches.
4086 		   PROBLEM: Colour can be modified for various reasons:
4087 		   Seasons, effects, and especially _staircase type-colouring_!! - C. Blue */
4088 #if 0 /* for this reason, let's skip the colour check for now >_> */
4089 		if ((f_ptr->z_char == c) && (f_ptr->z_attr == a)) return (p1);
4090 #else
4091 		if (f_ptr->z_char == c) return (p1);
4092 #endif
4093 	}
4094 
4095 	/* Default */
4096 	return (20);
4097 }
4098 
4099 
4100 /*
4101  * Display a "small-scale" map of the dungeon in the active Term
4102  *
4103  * Note that the "map_info()" function must return fully colorized
4104  * data or this function will not work correctly.
4105  *
4106  * Note that this function must "disable" the special lighting
4107  * effects so that the "priority" function will work.
4108  *
4109  * Note the use of a specialized "priority" function to allow this
4110  * function to work with any graphic attr/char mappings, and the
4111  * attempts to optimize this function where possible.
4112  */
4113 
4114 
4115 void display_map(int Ind, int *cy, int *cx) {
4116 	player_type *p_ptr = Players[Ind];
4117 
4118 	int i, j, x, y;
4119 
4120 	byte ta;
4121 	char tc;
4122 
4123 	byte tp;
4124 
4125 	byte ma[MAP_HGT + 2][MAP_WID + 2];
4126 	char mc[MAP_HGT + 2][MAP_WID + 2];
4127 
4128 	byte mp[MAP_HGT + 2][MAP_WID + 2];
4129 
4130 	byte sa[80];
4131 	char sc[80];
4132 
4133 	bool old_floor_lighting;
4134 	bool old_wall_lighting;
4135 
4136 
4137 	/* Save lighting effects */
4138 	old_floor_lighting = p_ptr->floor_lighting;
4139 	old_wall_lighting = p_ptr->wall_lighting;
4140 
4141 	/* Disable lighting effects */
4142 	p_ptr->floor_lighting = FALSE;
4143 	p_ptr->wall_lighting = FALSE;
4144 
4145 
4146 	/* Clear the chars and attributes */
4147 	memset(ma, TERM_WHITE, sizeof(ma));
4148 	memset(mc, ' ', sizeof(mc));
4149 
4150 	/* No priority */
4151 	memset(mp, 0, sizeof(mp));
4152 
4153 	/* Fill in the map */
4154 	for (i = 0; i < p_ptr->cur_wid; ++i) {
4155 		for (j = 0; j < p_ptr->cur_hgt; ++j) {
4156 			/* Location */
4157 			x = i / RATIO + 1;
4158 			y = j / RATIO + 1;
4159 
4160 			/* Extract the current attr/char at that map location */
4161 			map_info(Ind, j, i, &ta, &tc);
4162 
4163 			/* Extract the priority of that attr/char */
4164 			tp = priority(ta, tc);
4165 /* duplicate code, maybe create function  player_char(Ind) .. */
4166 			/* Hack - Player(@) should always be displayed */
4167 			if (i == p_ptr->px && j == p_ptr->py) {
4168 				tp = 99;
4169 				ta = player_color(Ind);
4170 
4171 				if ((p_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (p_ptr->inventory[INVEN_BODY].sval == SV_COSTUME)) {
4172 					tc = r_info[p_ptr->inventory[INVEN_BODY].bpval].d_char;
4173 				}
4174 				else if (p_ptr->body_monster) tc = r_info[p_ptr->body_monster].d_char;
4175 				else if (p_ptr->fruit_bat) tc = 'b';
4176 				else if ((( p_ptr->chp * 95)/ (p_ptr->mhp * 10)) > TURN_CHAR_INTO_NUMBER) tc = '@';
4177 				else {
4178 					if (p_ptr->chp < 0) tc = '-';
4179 					else {
4180 						int num;
4181 						num = (p_ptr->chp * 95) / (p_ptr->mhp * 10);
4182 						tc = '0' + num;
4183 					}
4184 				}
4185 			}
4186 /* duplicate code end */
4187 			/* Save "best" */
4188 			if (mp[y][x] < tp) {
4189 				/* Save the char */
4190 				mc[y][x] = tc;
4191 
4192 				/* Save the attr */
4193 				ma[y][x] = ta;
4194 
4195 				/* Save priority */
4196 				mp[y][x] = tp;
4197 			}
4198 		}
4199 	}
4200 
4201 
4202 	/* Corners */
4203 	x = MAP_WID + 1;
4204 	y = MAP_HGT + 1;
4205 
4206 	/* Draw the corners */
4207 	mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+';
4208 
4209 	/* Draw the horizontal edges */
4210 	for (x = 1; x <= MAP_WID; x++) mc[0][x] = mc[y][x] = '-';
4211 
4212 	/* Draw the vertical edges */
4213 	for (y = 1; y <= MAP_HGT; y++) mc[y][0] = mc[y][x] = '|';
4214 
4215 
4216 	/* Display each map line in order */
4217 	for (y = 0; y < MAP_HGT+2; ++y) {
4218 		/* Clear the screen buffer */
4219 #if 0
4220 		memset(sa, 0, sizeof(sa));
4221 		memset(sc, 0, sizeof(sc));
4222 #else
4223 		/* Allow for creation of an empty border
4224 		   (or maybe instructions on how to navigate)
4225 		   to eg the left and right side of the map */
4226 		memset(sa, TERM_WHITE, sizeof(sa));
4227 		memset(sc, ' ', sizeof(sc));
4228 #endif
4229 
4230      		/* Display the line */
4231 		for (x = 0; x < MAP_WID+2; ++x) {
4232 			ta = ma[y][x];
4233 			tc = mc[y][x];
4234 
4235 			/* Hack -- fake monochrome */
4236 			if (!use_color) ta = TERM_WHITE;
4237 
4238 #if 0
4239 			/* Put the character into the screen buffer */
4240 			sa[x] = ta;
4241 			sc[x] = tc;
4242 #else /* add a symmetrical 'border' to the left and right side of the map */
4243 			sa[x + (80 - MAP_WID - 2) / 2] = ta;
4244 			sc[x + (80 - MAP_WID - 2) / 2] = tc;
4245 #endif
4246 		}
4247 
4248 		/* Send that line of info */
4249 		Send_mini_map(Ind, y, sa, sc);
4250 	}
4251 
4252 
4253 	/* Player location */
4254 	(*cy) = p_ptr->py / RATIO + 1;
4255 	(*cx) = p_ptr->px / RATIO + 1;
4256 
4257 
4258 	/* Restore lighting effects */
4259 	p_ptr->floor_lighting = old_floor_lighting;
4260 	p_ptr->wall_lighting = old_wall_lighting;
4261 }
4262 
4263 
4264 #define WILDMAP_SHOWS_STAIRS
4265 static void wild_display_map(int Ind, char mode) {
4266 	player_type *p_ptr = Players[Ind];
4267 
4268 	int x, y, type;
4269 	int max_wx, offset_x;
4270 	int max_wy;//, offset_y;
4271 
4272 	byte ta;
4273 	char tc;
4274 
4275 	/* map is displayed "full-screen" ie we can use all of the main window */
4276 	byte ma[MAX_WINDOW_HGT][MAX_WINDOW_WID];
4277 	char mc[MAX_WINDOW_HGT][MAX_WINDOW_WID];
4278 
4279 	byte sa[80];
4280 	char sc[80];
4281 
4282 	bool old_floor_lighting;
4283 	bool old_wall_lighting;
4284 	struct worldpos twpos;
4285 	twpos.wz = 0;
4286 
4287 	byte c_dun, c_tow;
4288 	int c_dun_diff, c_tow_diff, mmpx = 0, mmpy = 0;
4289 	bool admin = is_admin(p_ptr), sent_pos = FALSE;
4290 
4291 
4292 	if (CL_WINDOW_WID > MAX_WILD_X + 2) {//+ 2 for border
4293 		offset_x = (CL_WINDOW_WID - MAX_WILD_X) / 2 - 1;//-1 for border
4294 		max_wx = MAX_WILD_X + 2;
4295 	} else {
4296 		offset_x = 0;
4297 		max_wx = CL_WINDOW_WID;
4298 	}
4299 	if (CL_WINDOW_HGT > MAX_WILD_Y + 2) {//+ 2 for border
4300 		//offset_y = (CL_WINDOW_HGT - MAX_WILD_Y) / 2 - 1;//-1 for border
4301 		max_wy = MAX_WILD_Y + 2;
4302 	} else {
4303 		//offset_y = 0;
4304 		max_wy = CL_WINDOW_HGT;
4305 	}
4306 
4307 
4308 	/* Save lighting effects */
4309 	old_floor_lighting = p_ptr->floor_lighting;
4310 	old_wall_lighting = p_ptr->wall_lighting;
4311 
4312 	/* Disable lighting effects */
4313 	p_ptr->floor_lighting = FALSE;
4314 	p_ptr->wall_lighting = FALSE;
4315 
4316 
4317 	/* Clear the chars and attributes */
4318 	memset(ma, TERM_WHITE, sizeof(ma));
4319 	memset(mc, ' ', sizeof(mc));
4320 
4321 
4322 	/* Modify location */
4323 	if ((mode & ~0x1) == 0x0) {
4324 		p_ptr->tmp_x = p_ptr->wpos.wx;
4325 		p_ptr->tmp_y = p_ptr->wpos.wy;
4326 	}
4327 	if (mode & 0x2) p_ptr->tmp_y -= 9;//10..11*2
4328 	if (mode & 0x4) p_ptr->tmp_x += 9;//31..32*2
4329 	if (mode & 0x8) p_ptr->tmp_y += 9;//10..11*2
4330 	if (mode & 0x10) p_ptr->tmp_x -= 9;//31..32*2
4331 #if 0
4332 	/* limit */
4333 	if (p_ptr->tmp_x < 0) p_ptr->tmp_x = 0;
4334 	if (p_ptr->tmp_y < 0) p_ptr->tmp_y = 0;
4335 	if (p_ptr->tmp_x >= MAX_WILD_X) p_ptr->tmp_x = MAX_WILD_X - 1;
4336 	if (p_ptr->tmp_y >= MAX_WILD_Y) p_ptr->tmp_y = MAX_WILD_Y - 1;
4337 #else
4338 	/* limit, align so that the map fills out the screen,
4339 	   instead of always centering the '@-sector'. */
4340 	if (p_ptr->tmp_x < (max_wx + 0) / 2 - 1) p_ptr->tmp_x = (max_wx + 0) / 2 - 1;
4341 	if (p_ptr->tmp_y < (max_wy - 0) / 2 - 2) p_ptr->tmp_y = (max_wy - 0) / 2 - 2;
4342 	if (p_ptr->tmp_x > MAX_WILD_X - (max_wx - 0) / 2 + 1) p_ptr->tmp_x = MAX_WILD_X - (max_wx - 0) / 2 + 1;
4343 	if (p_ptr->tmp_y > MAX_WILD_Y - (max_wy + 0) / 2 - 0) p_ptr->tmp_y = MAX_WILD_Y - (max_wy + 0) / 2 - 0;
4344 #endif
4345 
4346 
4347 	/* for each row */
4348 	for (y = 0; y < max_wy; y++) {
4349 		/* for each column */
4350 		for (x = 0; x < max_wx; x++) {
4351 			/* Location */
4352 			twpos.wy = p_ptr->tmp_y + (max_wy) / 2 - y;
4353 			twpos.wx = p_ptr->tmp_x - (max_wx) / 2 + x;
4354 
4355 			if (twpos.wy >= 0 && twpos.wy < MAX_WILD_Y && twpos.wx >= 0 && twpos.wx < MAX_WILD_X)
4356 				type = determine_wilderness_type(&twpos);
4357 			/* if off the map, set to unknown type */
4358 			else type = -1;
4359 
4360 			/* if the player hasnt been here, dont show him the terrain */
4361 			/* Hack -- serverchez has knowledge of the full world */
4362 			if (!p_ptr->admin_dm)
4363 			if (!(p_ptr->wild_map[wild_idx(&twpos) / 8] & (1 << (wild_idx(&twpos) % 8)))) type = -1;
4364 			/* hack --  the town is always known */
4365 
4366 			switch (type) {
4367 				case WILD_LAKE: tc = '~'; ta = TERM_BLUE; break;
4368 				case WILD_GRASSLAND: tc = '.'; ta = TERM_GREEN; break;
4369 				case WILD_FOREST: tc = '*'; ta = TERM_GREEN; break;
4370 				case WILD_SWAMP:  tc = '%'; ta = TERM_VIOLET; break;
4371 				case WILD_DENSEFOREST: tc = '*'; ta = TERM_L_DARK; break;
4372 				case WILD_WASTELAND: tc = '.'; ta = TERM_UMBER; break;
4373 				case WILD_TOWN: tc = 'T'; ta = TERM_YELLOW; break;
4374 				case WILD_CLONE: tc = 'C'; ta = TERM_RED; break;
4375 				case WILD_MOUNTAIN: tc = '^'; ta = TERM_L_DARK; break;
4376 				case WILD_VOLCANO: tc = '^'; ta = TERM_RED; break;
4377 				case WILD_RIVER: tc = '~'; ta = TERM_L_BLUE; break;
4378 				case WILD_COAST: tc = ','; ta = TERM_L_UMBER; break;//TERM_YELLOW
4379 				case WILD_OCEAN: tc = '%'; ta = TERM_BLUE; break;
4380 				case WILD_DESERT: tc = '.'; ta = TERM_YELLOW; break;
4381 				case WILD_ICE: tc = '.'; ta = TERM_WHITE; break;
4382 				case -1: tc = ' '; ta = TERM_DARK; break;
4383 				default: tc = 'O'; ta = TERM_YELLOW; break;
4384 			}
4385 #ifdef WILDMAP_SHOWS_STAIRS
4386 			if (type != -1 && type != WILD_TOWN) {
4387 				dungeon_type *dun = wild_info[twpos.wy][twpos.wx].dungeon, *tow = wild_info[twpos.wy][twpos.wx].tower;
4388 				if (dun && !strcmp(d_info[dun->type].name + d_name, "The Shores of Valinor") && !admin) dun = NULL;
4389 				if (tow && !strcmp(d_info[tow->type].name + d_name, "The Shores of Valinor") && !admin) tow = NULL;
4390 				if (dun) {
4391 					if (tow) {
4392 						tc = 'X';
4393 						c_dun_diff = get_staircase_colour(dun, &c_dun);
4394 						c_tow_diff = get_staircase_colour(tow, &c_tow);
4395 						if (c_dun == c_tow) ta = c_dun;
4396 						else if (c_dun_diff > c_tow_diff) ta = c_dun;
4397 						else ta = c_tow;
4398 					} else {
4399 						tc = '>';
4400 						get_staircase_colour(dun, &ta);
4401 					}
4402 				} else if (tow) {
4403 					tc = '<';
4404 					get_staircase_colour(tow, &ta);
4405 				}
4406 			}
4407 #endif
4408 
4409 #if 0
4410 			/* put the @ in the center */
4411 			if ((y == (MAP_HGT + 2) / 2) && (x == (MAP_WID + 2) / 2)) {
4412 				tc = '@';
4413 				ta = TERM_WHITE;
4414 			}
4415 #else
4416 			/* since map is navigatable, only put @ if we are there */
4417 			if (twpos.wx == p_ptr->wpos.wx && twpos.wy == p_ptr->wpos.wy) {
4418 				if (is_older_than(&p_ptr->version, 4, 5, 5, 1, 0, 0)) {
4419 					/* directly "hard-sub" it ;) */
4420 					tc = '@';
4421 					ta = TERM_WHITE;
4422 				} else {
4423 					/* overlay a blinking '@' */
4424 					mmpx = x;
4425 					mmpy = y;
4426 					sent_pos = TRUE;
4427 				}
4428 			} else if (!sent_pos) {
4429 				/* allow overlay on map borders, as indicator */
4430 				if (twpos.wx == p_ptr->wpos.wx) mmpx = x;
4431 				if (twpos.wy == p_ptr->wpos.wy) mmpy = y;
4432 			}
4433 #endif
4434 
4435 			/* Save the char */
4436 			mc[y][x] = tc;
4437 
4438 			/* Save the attr */
4439 			ma[y][x] = ta;
4440 		}
4441 	}
4442 
4443 	/* Corners */
4444 	x = max_wx - 1;
4445 	y = max_wy - 1;
4446 
4447 	/* Draw the corners */
4448 	mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+';
4449 
4450 	/* Draw the horizontal edges */
4451 	for (x = 1; x < max_wx; x++) mc[0][x] = mc[y][x] = '-';
4452 
4453 	/* Draw the vertical edges */
4454 	for (y = 1; y < max_wy; y++) mc[y][0] = mc[y][x] = '|';
4455 
4456 
4457 	/* If we are off-screen, don't draw the usual '@' icon */
4458 	if (!sent_pos) {
4459 #if 0
4460 		/* Don't draw it at all */
4461 		Send_mini_map_pos(Ind, -1, 0, 0, 0);
4462 #else
4463 		/* Draw it on the map border as indicator:
4464 		     max_wx/wy - 2 (border size of 1 in each direction).
4465 		   Note: Does currently ignore left/right borders, since they don't exist atm. */
4466 
4467 		int yy = p_ptr->tmp_y + max_wy / 2;
4468 
4469 		/* On bottom border? */
4470 		if (p_ptr->wpos.wy < yy - (max_wy - 2)) Send_mini_map_pos(Ind, mmpx + offset_x, max_wy - 1, ma[max_wy - 1][mmpx], '-');
4471 		/* On top border? */
4472 		else if (p_ptr->wpos.wy > yy) Send_mini_map_pos(Ind, mmpx + offset_x, 0, ma[0][mmpx], '-');
4473 		/* On pfft? */
4474 		else Send_mini_map_pos(Ind, -1, 0, 0, 0); /* paranoia */
4475 #endif
4476 	} else Send_mini_map_pos(Ind, mmpx + offset_x, mmpy, ma[mmpy][mmpx], mc[mmpy][mmpx]);
4477 
4478 
4479 	/* Display each map line in order */
4480 	for (y = 0; y < max_wy; ++y) {
4481 		/* Clear the screen buffer */
4482 #if 0
4483 		memset(sa, 0, sizeof(sa));
4484 		memset(sc, 0, sizeof(sc));
4485 #else
4486 		/* Allow for creation of an empty border
4487 		   (or maybe instructions on how to navigate)
4488 		   to eg the left and right side of the map */
4489 		memset(sa, TERM_WHITE, sizeof(sa));
4490 		memset(sc, ' ', sizeof(sc));
4491 #endif
4492 
4493 		/* Display the line */
4494 		for (x = 0; x < max_wx; ++x) {
4495 			ta = ma[y][x];
4496 			tc = mc[y][x];
4497 
4498 			/* Hack -- fake monochrome */
4499 			if (!use_color) ta = TERM_WHITE;
4500 
4501 			/* Put the character into the screen buffer */
4502 #if 0
4503 			sa[x] = ta;
4504 			sc[x] = tc;
4505 #else /* add a symmetrical 'border' to the left and right side of the map */
4506 			sa[x + offset_x] = ta;
4507 			sc[x + offset_x] = tc;
4508 #endif
4509 		}
4510 
4511 		/* Send that line of info */
4512 		Send_mini_map(Ind, y, sa, sc);
4513 	}
4514 
4515 	/* Restore lighting effects */
4516 	p_ptr->floor_lighting = old_floor_lighting;
4517 	p_ptr->wall_lighting = old_wall_lighting;
4518 }
4519 
4520 
4521 /*
4522  * Display a "small-scale" map of the dungeon for the player
4523  */
4524 
4525  /* in the wilderness, have several scales of maps availiable... adding one
4526     "wilderness map" mode now that will represent each level with one character.
4527  */
4528 
4529 void do_cmd_view_map(int Ind, char mode) {
4530 	int cy, cx;
4531 
4532 	/* Display the map */
4533 
4534 	/* if not in town or the dungeon, do normal map */
4535 	/* is player in a town or dungeon? */
4536 	/* only off floor ATM */
4537 	if ((Players[Ind]->wpos.wz != 0 || (istown(&Players[Ind]->wpos)))
4538 	    && !(mode & 0x1))
4539 		display_map(Ind, &cy, &cx);
4540 	/* do wilderness map */
4541 	/* pfft, fix me pls, Evileye ;) */
4542 	/* pfft. fixed */
4543 	else wild_display_map(Ind, mode);
4544 	/*else display_map(Ind, &cy, &cx); */
4545 }
4546 
4547 
4548 
4549 
4550 
4551 
4552 
4553 
4554 
4555 
4556 /*
4557  * Some comments on the cave grid flags.  -BEN-
4558  *
4559  *
4560  * One of the major bottlenecks in previous versions of Angband was in
4561  * the calculation of "line of sight" from the player to various grids,
4562  * such as monsters.  This was such a nasty bottleneck that a lot of
4563  * silly things were done to reduce the dependancy on "line of sight",
4564  * for example, you could not "see" any grids in a lit room until you
4565  * actually entered the room, and there were all kinds of bizarre grid
4566  * flags to enable this behavior.  This is also why the "call light"
4567  * spells always lit an entire room.
4568  *
4569  * The code below provides functions to calculate the "field of view"
4570  * for the player, which, once calculated, provides extremely fast
4571  * calculation of "line of sight from the player", and to calculate
4572  * the "field of torch lite", which, again, once calculated, provides
4573  * extremely fast calculation of "which grids are lit by the player's
4574  * lite source".  In addition to marking grids as "GRID_VIEW" and/or
4575  * "GRID_LITE", as appropriate, these functions maintain an array for
4576  * each of these two flags, each array containing the locations of all
4577  * of the grids marked with the appropriate flag, which can be used to
4578  * very quickly scan through all of the grids in a given set.
4579  *
4580  * To allow more "semantically valid" field of view semantics, whenever
4581  * the field of view (or the set of torch lit grids) changes, all of the
4582  * grids in the field of view (or the set of torch lit grids) are "drawn"
4583  * so that changes in the world will become apparent as soon as possible.
4584  * This has been optimized so that only grids which actually "change" are
4585  * redrawn, using the "temp" array and the "GRID_TEMP" flag to keep track
4586  * of the grids which are entering or leaving the relevent set of grids.
4587  *
4588  * These new methods are so efficient that the old nasty code was removed.
4589  *
4590  * Note that there is no reason to "update" the "viewable space" unless
4591  * the player "moves", or walls/doors are created/destroyed, and there
4592  * is no reason to "update" the "torch lit grids" unless the field of
4593  * view changes, or the "light radius" changes.  This means that when
4594  * the player is resting, or digging, or doing anything that does not
4595  * involve movement or changing the state of the dungeon, there is no
4596  * need to update the "view" or the "lite" regions, which is nice.
4597  *
4598  * Note that the calls to the nasty "los()" function have been reduced
4599  * to a bare minimum by the use of the new "field of view" calculations.
4600  *
4601  * I wouldn't be surprised if slight modifications to the "update_view()"
4602  * function would allow us to determine "reverse line-of-sight" as well
4603  * as "normal line-of-sight", which would allow monsters to use a more
4604  * "correct" calculation to determine if they can "see" the player.  For
4605  * now, monsters simply "cheat" somewhat and assume that if the player
4606  * has "line of sight" to the monster, then the monster can "pretend"
4607  * that it has "line of sight" to the player.
4608  *
4609  *
4610  * The "update_lite()" function maintains the "CAVE_LITE" flag for each
4611  * grid and maintains an array of all "CAVE_LITE" grids.
4612  *
4613  * This set of grids is the complete set of all grids which are lit by
4614  * the players light source, which allows the "player_can_see_bold()"
4615  * function to work very quickly.
4616  *
4617  * Note that every "CAVE_LITE" grid is also a "CAVE_VIEW" grid, and in
4618  * fact, the player (unless blind) can always "see" all grids which are
4619  * marked as "CAVE_LITE", unless they are "off screen".
4620  *
4621  *
4622  * The "update_view()" function maintains the "CAVE_VIEW" flag for each
4623  * grid and maintains an array of all "CAVE_VIEW" grids.
4624  *
4625  * This set of grids is the complete set of all grids within line of sight
4626  * of the player, allowing the "player_has_los_bold()" macro to work very
4627  * quickly.
4628  *
4629  *
4630  * The current "update_view()" algorithm uses the "CAVE_XTRA" flag as a
4631  * temporary internal flag to mark those grids which are not only in view,
4632  * but which are also "easily" in line of sight of the player.  This flag
4633  * is always cleared when we are done.
4634  *
4635  *
4636  * The current "update_lite()" and "update_view()" algorithms use the
4637  * "CAVE_TEMP" flag, and the array of grids which are marked as "CAVE_TEMP",
4638  * to keep track of which grids were previously marked as "CAVE_LITE" or
4639  * "CAVE_VIEW", which allows us to optimize the "screen updates".
4640  *
4641  * The "CAVE_TEMP" flag, and the array of "CAVE_TEMP" grids, is also used
4642  * for various other purposes, such as spreading lite or darkness during
4643  * "lite_room()" / "unlite_room()", and for calculating monster flow.
4644  *
4645  *
4646  * Any grid can be marked as "CAVE_GLOW" which means that the grid itself is
4647  * in some way permanently lit.  However, for the player to "see" anything
4648  * in the grid, as determined by "player_can_see()", the player must not be
4649  * blind, the grid must be marked as "CAVE_VIEW", and, in addition, "wall"
4650  * grids, even if marked as "perma lit", are only illuminated if they touch
4651  * a grid which is not a wall and is marked both "CAVE_GLOW" and "CAVE_VIEW".
4652  *
4653  *
4654  * To simplify various things, a grid may be marked as "CAVE_MARK", meaning
4655  * that even if the player cannot "see" the grid, he "knows" the terrain in
4656  * that grid.  This is used to "remember" walls/doors/stairs/floors when they
4657  * are "seen" or "detected", and also to "memorize" floors, after "wiz_lite()",
4658  * or when one of the "memorize floor grids" options induces memorization.
4659  *
4660  * Objects are "memorized" in a different way, using a special "marked" flag
4661  * on the object itself, which is set when an object is observed or detected.
4662  *
4663  *
4664  * A grid may be marked as "CAVE_ROOM" which means that it is part of a "room",
4665  * and should be illuminated by "lite room" and "darkness" spells.
4666  *
4667  *
4668  * A grid may be marked as "CAVE_ICKY" which means it is part of a "vault",
4669  * and should be unavailable for "teleportation" destinations.
4670  * Note that CAVE_ICKY is also used for other purposes like houses. - C. Blue
4671  *
4672  *
4673  * The "view_perma_grids" allows the player to "memorize" every perma-lit grid
4674  * which is observed, and the "view_torch_grids" allows the player to memorize
4675  * every torch-lit grid.  The player will always memorize important walls,
4676  * doors, stairs, and other terrain features, as well as any "detected" grids.
4677  *
4678  * Note that the new "update_view()" method allows, among other things, a room
4679  * to be "partially" seen as the player approaches it, with a growing cone of
4680  * floor appearing as the player gets closer to the door.  Also, by not turning
4681  * on the "memorize perma-lit grids" option, the player will only "see" those
4682  * floor grids which are actually in line of sight.
4683  *
4684  * And my favorite "plus" is that you can now use a special option to draw the
4685  * "floors" in the "viewable region" brightly (actually, to draw the *other*
4686  * grids dimly), providing a "pretty" effect as the player runs around, and
4687  * to efficiently display the "torch lite" in a special color.
4688  *
4689  *
4690  * Some comments on the "update_view()" algorithm...
4691  *
4692  * The algorithm is very fast, since it spreads "obvious" grids very quickly,
4693  * and only has to call "los()" on the borderline cases.  The major axes/diags
4694  * even terminate early when they hit walls.  I need to find a quick way
4695  * to "terminate" the other scans.
4696  *
4697  * Note that in the worst case (a big empty area with say 5% scattered walls),
4698  * each of the 1500 or so nearby grids is checked once, most of them getting
4699  * an "instant" rating, and only a small portion requiring a call to "los()".
4700  *
4701  * The only time that the algorithm appears to be "noticeably" too slow is
4702  * when running, and this is usually only important in town, since the town
4703  * provides about the worst scenario possible, with large open regions and
4704  * a few scattered obstructions.  There is a special "efficiency" option to
4705  * allow the player to reduce his field of view in town, if needed.
4706  *
4707  * In the "best" case (say, a normal stretch of corridor), the algorithm
4708  * makes one check for each viewable grid, and makes no calls to "los()".
4709  * So running in corridors is very fast, and if a lot of monsters are
4710  * nearby, it is much faster than the old methods.
4711  *
4712  * Note that resting, most normal commands, and several forms of running,
4713  * plus all commands executed near large groups of monsters, are strictly
4714  * more efficient with "update_view()" that with the old "compute los() on
4715  * demand" method, primarily because once the "field of view" has been
4716  * calculated, it does not have to be recalculated until the player moves
4717  * (or a wall or door is created or destroyed).
4718  *
4719  * Note that we no longer have to do as many "los()" checks, since once the
4720  * "view" region has been built, very few things cause it to be "changed"
4721  * (player movement, and the opening/closing of doors, changes in wall status).
4722  * Note that door/wall changes are only relevant when the door/wall itself is
4723  * in the "view" region.
4724  *
4725  * The algorithm seems to only call "los()" from zero to ten times, usually
4726  * only when coming down a corridor into a room, or standing in a room, just
4727  * misaligned with a corridor.  So if, say, there are five "nearby" monsters,
4728  * we will be reducing the calls to "los()".
4729  *
4730  * I am thinking in terms of an algorithm that "walks" from the central point
4731  * out to the maximal "distance", at each point, determining the "view" code
4732  * (above).  For each grid not on a major axis or diagonal, the "view" code
4733  * depends on the "cave_floor_bold()" and "view" of exactly two other grids
4734  * (the one along the nearest diagonal, and the one next to that one, see
4735  * "update_view_aux()"...).
4736  *
4737  * We "memorize" the viewable space array, so that at the cost of under 3000
4738  * bytes, we reduce the time taken by "forget_view()" to one assignment for
4739  * each grid actually in the "viewable space".  And for another 3000 bytes,
4740  * we prevent "erase + redraw" ineffiencies via the "seen" set.  These bytes
4741  * are also used by other routines, thus reducing the cost to almost nothing.
4742  *
4743  * A similar thing is done for "forget_lite()" in which case the savings are
4744  * much less, but save us from doing bizarre maintenance checking.
4745  *
4746  * In the worst "normal" case (in the middle of the town), the reachable space
4747  * actually reaches to more than half of the largest possible "circle" of view,
4748  * or about 800 grids, and in the worse case (in the middle of a dungeon level
4749  * where all the walls have been removed), the reachable space actually reaches
4750  * the theoretical maximum size of just under 1500 grids.
4751  *
4752  * Each grid G examines the "state" of two (?) other (adjacent) grids, G1 & G2.
4753  * If G1 is lite, G is lite.  Else if G2 is lite, G is half.  Else if G1 and G2
4754  * are both half, G is half.  Else G is dark.  It only takes 2 (or 4) bits to
4755  * "name" a grid, so (for MAX_RAD of 20) we could use 1600 bytes, and scan the
4756  * entire possible space (including initialization) in one step per grid.  If
4757  * we do the "clearing" as a separate step (and use an array of "view" grids),
4758  * then the clearing will take as many steps as grids that were viewed, and the
4759  * algorithm will be able to "stop" scanning at various points.
4760  * Oh, and outside of the "torch radius", only "lite" grids need to be scanned.
4761  */
4762 
4763 
4764 
4765 
4766 
4767 
4768 
4769 
4770 /*
4771  * Actually erase the entire "lite" array, redrawing every grid
4772  */
4773 void forget_lite(int Ind)
4774 {
4775 	player_type *p_ptr = Players[Ind];
4776 	int i, x, y;
4777 
4778 	cave_type **zcave;
4779 	struct worldpos *wpos = &p_ptr->wpos;
4780 	if (!(zcave = getcave(&p_ptr->wpos))) return;
4781 
4782 
4783 	/* None to forget */
4784 	if (!(p_ptr->lite_n)) return;
4785 
4786 	/* Clear them all */
4787 	for (i = 0; i < p_ptr->lite_n; i++)
4788 	{
4789 		int j;
4790 
4791 		y = p_ptr->lite_y[i];
4792 		x = p_ptr->lite_x[i];
4793 
4794 		/* Forget "LITE" flag */
4795 		p_ptr->cave_flag[y][x] &= ~CAVE_LITE;
4796 		zcave[y][x].info &= ~(CAVE_LITE | CAVE_LITE_VAMP | CAVE_LITE_WHITE);
4797 
4798 		for (j = 1; j <= NumPlayers; j++)
4799 		{
4800 			/* Make sure player is connected */
4801 			if (Players[j]->conn == NOT_CONNECTED)
4802 				continue;
4803 
4804 			/* Make sure player is on the level */
4805 			if (!inarea(wpos, &Players[j]->wpos))
4806 				continue;
4807 
4808 			/* Ignore the player that we're updating */
4809 			if (j == Ind)
4810 				continue;
4811 
4812 			/* If someone else also lites this spot relite it */
4813 			if (Players[j]->cave_flag[y][x] & CAVE_LITE) {
4814 				zcave[y][x].info |= CAVE_LITE;
4815 				switch (Players[j]->lite_type) {
4816 				case 1: zcave[y][x].info |= CAVE_LITE_VAMP; break;
4817 				case 2: zcave[y][x].info |= CAVE_LITE_WHITE;
4818 				}
4819 			}
4820 		}
4821 
4822 		/* Redraw */
4823 		everyone_lite_spot(wpos, y, x);
4824 	}
4825 
4826 	/* None left */
4827 	p_ptr->lite_n = 0;
4828 }
4829 
4830 
4831 /*
4832  * XXX XXX XXX
4833  *
4834  * This macro allows us to efficiently add a grid to the "lite" array,
4835  * note that we are never called for illegal grids, or for grids which
4836  * have already been placed into the "lite" array, and we are never
4837  * called when the "lite" array is full.
4838  *
4839  * Note that I'm assuming that we can use "p_ptr", because this macro
4840  * should only be called from functions that have it defined at the
4841  * top.  --KLJ--
4842  */
4843 #define cave_lite_hack(Y,X) \
4844     switch (p_ptr->lite_type) { \
4845     case 0: zcave[Y][X].info &= ~(CAVE_LITE_WHITE | CAVE_LITE_VAMP); break; \
4846     case 1: if (!(zcave[Y][X].info & (CAVE_LITE | CAVE_LITE_WHITE))) zcave[Y][X].info |= CAVE_LITE_VAMP; break; \
4847     case 2: if (!(zcave[Y][X].info & CAVE_LITE)) zcave[Y][X].info |= CAVE_LITE_WHITE; \
4848     } \
4849     zcave[Y][X].info |= CAVE_LITE; \
4850     p_ptr->cave_flag[Y][X] |= CAVE_LITE; \
4851     p_ptr->lite_y[p_ptr->lite_n] = (Y); \
4852     p_ptr->lite_x[p_ptr->lite_n] = (X); \
4853     p_ptr->lite_n++
4854 
4855 /*
4856  * Update the set of grids "illuminated" by the player's lite.
4857  *
4858  * This routine needs to use the results of "update_view()"
4859  *
4860  * Note that "blindness" does NOT affect "torch lite".  Be careful!
4861  *
4862  * We optimize most lites (all non-artifact lites) by using "obvious"
4863  * facts about the results of "small" lite radius, and we attempt to
4864  * list the "nearby" grids before the more "distant" ones in the
4865  * array of torch-lit grids.
4866  *
4867  * We will correctly handle "large" radius lites, though currently,
4868  * it is impossible for the player to have more than radius 3 lite.
4869  *
4870  * We assume that "radius zero" lite is in fact no lite at all.
4871  *
4872  *     Torch     Lantern     Artifacts
4873  *     (etc)
4874  *                              ***
4875  *                 ***         *****
4876  *      ***       *****       *******
4877  *      *@*       **@**       ***@***
4878  *      ***       *****       *******
4879  *                 ***         *****
4880  *                              ***
4881  */
4882 void update_lite(int Ind)
4883 {
4884 	player_type *p_ptr = Players[Ind];
4885 	int i, x, y, min_x, max_x, min_y, max_y;
4886 
4887 	struct worldpos *wpos = &p_ptr->wpos;
4888 	cave_type **zcave;
4889 	if (!(zcave = getcave(wpos))) return;
4890 
4891 	/*** Special case ***/
4892 
4893 	/* Hack -- Player has no lite */
4894 	if (p_ptr->cur_lite <= 0 && p_ptr->cur_vlite <= 0)
4895 	{
4896 		/* Forget the old lite */
4897 		forget_lite(Ind);
4898 
4899 		/* Draw the player */
4900 		lite_spot(Ind, p_ptr->py, p_ptr->px);
4901 
4902 		/* All done */
4903 		return;
4904 	}
4905 
4906 
4907 	/*** Save the old "lite" grids for later ***/
4908 
4909 	/* Clear them all */
4910 	for (i = 0; i < p_ptr->lite_n; i++)
4911 	{
4912 		int j;
4913 
4914 		y = p_ptr->lite_y[i];
4915 		x = p_ptr->lite_x[i];
4916 
4917 		/* Mark the grid as not "lite" */
4918 		p_ptr->cave_flag[y][x] &= ~CAVE_LITE;
4919 		zcave[y][x].info &= ~(CAVE_LITE | CAVE_LITE_VAMP | CAVE_LITE_WHITE);
4920 
4921 		for (j = 1; j <= NumPlayers; j++)
4922 		{
4923 			/* Make sure player is connected */
4924 			if (Players[j]->conn == NOT_CONNECTED)
4925 				continue;
4926 
4927 			/* Make sure player is on the level */
4928 			if (!inarea(wpos, &Players[j]->wpos))
4929 				continue;
4930 
4931 			/* Ignore the player that we're updating */
4932 			if (j == Ind)
4933 				continue;
4934 
4935 			/* If someone else also lites this spot relite it */
4936 			if (Players[j]->cave_flag[y][x] & CAVE_LITE) {
4937 				zcave[y][x].info |= CAVE_LITE;
4938                                 switch (Players[j]->lite_type) {
4939                                 case 1: zcave[y][x].info |= CAVE_LITE_VAMP; break;
4940                                 case 2: zcave[y][x].info |= CAVE_LITE_WHITE;
4941                                 }
4942 			}
4943 		}
4944 		/* Mark the grid as "seen" */
4945 		zcave[y][x].info |= CAVE_TEMP;
4946 
4947 		/* Add it to the "seen" set */
4948 		p_ptr->temp_y[p_ptr->temp_n] = y;
4949 		p_ptr->temp_x[p_ptr->temp_n] = x;
4950 		p_ptr->temp_n++;
4951 	}
4952 
4953 	/* None left */
4954 	p_ptr->lite_n = 0;
4955 
4956 
4957 	/*** Collect the new "lite" grids ***/
4958 
4959 	/* Player grid */
4960 	cave_lite_hack(p_ptr->py, p_ptr->px);
4961 
4962 	/* Radius 1 -- torch radius */
4963 	if (p_ptr->cur_lite >= 1 || p_ptr->cur_vlite >= 1) {
4964 		/* Adjacent grid */
4965 		cave_lite_hack(p_ptr->py+1, p_ptr->px);
4966 		cave_lite_hack(p_ptr->py-1, p_ptr->px);
4967 		cave_lite_hack(p_ptr->py, p_ptr->px+1);
4968 		cave_lite_hack(p_ptr->py, p_ptr->px-1);
4969 
4970 		/* Diagonal grids */
4971 		cave_lite_hack(p_ptr->py+1, p_ptr->px+1);
4972 		cave_lite_hack(p_ptr->py+1, p_ptr->px-1);
4973 		cave_lite_hack(p_ptr->py-1, p_ptr->px+1);
4974 		cave_lite_hack(p_ptr->py-1, p_ptr->px-1);
4975 	}
4976 
4977 	/* Radius 2 -- lantern radius */
4978 	if (p_ptr->cur_lite >= 2 || p_ptr->cur_vlite >= 2) {
4979 		/* South of the player */
4980 //		if (cave_floor_bold(zcave, p_ptr->py+1, p_ptr->px))
4981 		/* cave_los includes dark pits */
4982 		if (cave_los(zcave, p_ptr->py+1, p_ptr->px))
4983 		{
4984 			cave_lite_hack(p_ptr->py+2, p_ptr->px);
4985 			cave_lite_hack(p_ptr->py+2, p_ptr->px+1);
4986 			cave_lite_hack(p_ptr->py+2, p_ptr->px-1);
4987 		}
4988 
4989 		/* North of the player */
4990 //		if (cave_floor_bold(zcave, p_ptr->py-1, p_ptr->px))
4991 		if (cave_los(zcave, p_ptr->py-1, p_ptr->px)) {
4992 			cave_lite_hack(p_ptr->py-2, p_ptr->px);
4993 			cave_lite_hack(p_ptr->py-2, p_ptr->px+1);
4994 			cave_lite_hack(p_ptr->py-2, p_ptr->px-1);
4995 		}
4996 
4997 		/* East of the player */
4998 //		if (cave_floor_bold(zcave, p_ptr->py, p_ptr->px+1))
4999 		if (cave_los(zcave, p_ptr->py, p_ptr->px+1)) {
5000 			cave_lite_hack(p_ptr->py, p_ptr->px+2);
5001 			cave_lite_hack(p_ptr->py+1, p_ptr->px+2);
5002 			cave_lite_hack(p_ptr->py-1, p_ptr->px+2);
5003 		}
5004 
5005 		/* West of the player */
5006 //		if (cave_floor_bold(zcave, p_ptr->py, p_ptr->px-1))
5007 		if (cave_los(zcave, p_ptr->py, p_ptr->px-1)) {
5008 			cave_lite_hack(p_ptr->py, p_ptr->px-2);
5009 			cave_lite_hack(p_ptr->py+1, p_ptr->px-2);
5010 			cave_lite_hack(p_ptr->py-1, p_ptr->px-2);
5011 		}
5012 	}
5013 
5014 	/* Radius 3+ -- artifact radius */
5015 	if (p_ptr->cur_lite >= 3 || p_ptr->cur_vlite >= 3) {
5016 		int d, p;
5017 
5018 		/* Maximal radius */
5019 		p = p_ptr->cur_lite;
5020 		if (p_ptr->cur_vlite > p) p = p_ptr->cur_vlite;
5021 
5022 		/* Paranoia -- see "LITE_MAX" */
5023 		if (p > LITE_CAP) p = LITE_CAP;
5024 
5025 		/* South-East of the player */
5026 //		if (cave_floor_bold(zcave, p_ptr->py+1, p_ptr->px+1))
5027 		if (cave_los(zcave, p_ptr->py+1, p_ptr->px+1)) {
5028 			cave_lite_hack(p_ptr->py+2, p_ptr->px+2);
5029 		}
5030 
5031 		/* South-West of the player */
5032 //		if (cave_floor_bold(zcave, p_ptr->py+1, p_ptr->px-1))
5033 		if (cave_los(zcave, p_ptr->py+1, p_ptr->px-1)) {
5034 			cave_lite_hack(p_ptr->py+2, p_ptr->px-2);
5035 		}
5036 
5037 		/* North-East of the player */
5038 //		if (cave_floor_bold(zcave, p_ptr->py-1, p_ptr->px+1))
5039 		if (cave_los(zcave, p_ptr->py-1, p_ptr->px+1)) {
5040 			cave_lite_hack(p_ptr->py-2, p_ptr->px+2);
5041 		}
5042 
5043 		/* North-West of the player */
5044 //		if (cave_floor_bold(zcave, p_ptr->py-1, p_ptr->px-1))
5045 		if (cave_los(zcave, p_ptr->py-1, p_ptr->px-1)) {
5046 			cave_lite_hack(p_ptr->py-2, p_ptr->px-2);
5047 		}
5048 
5049 		/* Maximal north */
5050 		min_y = p_ptr->py - p;
5051 		if (min_y < 0) min_y = 0;
5052 
5053 		/* Maximal south */
5054 		max_y = p_ptr->py + p;
5055 		if (max_y > p_ptr->cur_hgt-1) max_y = p_ptr->cur_hgt-1;
5056 
5057 		/* Maximal west */
5058 		min_x = p_ptr->px - p;
5059 		if (min_x < 0) min_x = 0;
5060 
5061 		/* Maximal east */
5062 		max_x = p_ptr->px + p;
5063 		if (max_x > p_ptr->cur_wid-1) max_x = p_ptr->cur_wid-1;
5064 
5065 		/* Scan the maximal box */
5066 		for (y = min_y; y <= max_y; y++) {
5067 			for (x = min_x; x <= max_x; x++) {
5068 				int dy = (p_ptr->py > y) ? (p_ptr->py - y) : (y - p_ptr->py);
5069 				int dx = (p_ptr->px > x) ? (p_ptr->px - x) : (x - p_ptr->px);
5070 
5071 				/* Skip the "central" grids (above) */
5072 				if ((dy <= 2) && (dx <= 2)) continue;
5073 
5074 				/* Hack -- approximate the distance */
5075 				d = (dy > dx) ? (dy + (dx>>1)) : (dx + (dy>>1));
5076 
5077 				/* Skip distant grids */
5078 				if (d > p) continue;
5079 
5080 				/* Viewable, nearby, grids get "torch lit" */
5081 				if (player_has_los_bold(Ind, y, x)) {
5082 					/* This grid is "torch lit" */
5083 					cave_lite_hack(y, x);
5084 				}
5085 			}
5086 		}
5087 	}
5088 
5089 
5090 	/*** Complete the algorithm ***/
5091 
5092 	/* Draw the new grids */
5093 	for (i = 0; i < p_ptr->lite_n; i++) {
5094 		y = p_ptr->lite_y[i];
5095 		x = p_ptr->lite_x[i];
5096 
5097 		/* Update fresh grids */
5098 		if (zcave[y][x].info & CAVE_TEMP) continue;
5099 
5100 		/* Note */
5101 		note_spot_depth(wpos, y, x);
5102 
5103 		/* Redraw */
5104 		everyone_lite_spot(wpos, y, x);
5105 	}
5106 
5107 	/* Clear them all */
5108 	for (i = 0; i < p_ptr->temp_n; i++) {
5109 		y = p_ptr->temp_y[i];
5110 		x = p_ptr->temp_x[i];
5111 
5112 		/* No longer in the array */
5113 		zcave[y][x].info &= ~CAVE_TEMP;
5114 
5115 		/* Update stale grids */
5116 		if (p_ptr->cave_flag[y][x] & CAVE_LITE) continue;
5117 
5118 		/* Redraw */
5119 		everyone_lite_spot(wpos, y, x);
5120 	}
5121 
5122 	/* None left */
5123 	p_ptr->temp_n = 0;
5124 }
5125 
5126 
5127 
5128 
5129 
5130 
5131 
5132 /*
5133  * Clear the viewable space
5134  */
5135 void forget_view(int Ind)
5136 {
5137 	player_type *p_ptr = Players[Ind];
5138 	int i;
5139 
5140 	byte *w_ptr;
5141 
5142 	/* None to forget */
5143 	if (!(p_ptr->view_n)) return;
5144 
5145 	/* Clear them all */
5146 	for (i = 0; i < p_ptr->view_n; i++)
5147 	{
5148 		int y = p_ptr->view_y[i];
5149 		int x = p_ptr->view_x[i];
5150 
5151 		/* Access the grid */
5152 		w_ptr = &p_ptr->cave_flag[y][x];
5153 
5154 		/* Forget that the grid is viewable */
5155 		*w_ptr &= ~CAVE_VIEW;
5156 
5157 		/* Update the screen */
5158 		lite_spot(Ind, y, x);
5159 	}
5160 
5161 	/* None left */
5162 	p_ptr->view_n = 0;
5163 }
5164 
5165 
5166 
5167 /*
5168  * This macro allows us to efficiently add a grid to the "view" array,
5169  * note that we are never called for illegal grids, or for grids which
5170  * have already been placed into the "view" array, and we are never
5171  * called when the "view" array is full.
5172  *
5173  * I'm again assuming that using p_ptr is OK (see above) --KLJ--
5174  */
5175 #define cave_view_hack(W,Y,X) \
5176     (*(W)) |= CAVE_VIEW; \
5177     p_ptr->view_y[p_ptr->view_n] = (Y); \
5178     p_ptr->view_x[p_ptr->view_n] = (X); \
5179     p_ptr->view_n++
5180 
5181 
5182 
5183 #ifdef USE_OLD_UPDATE_VIEW
5184 /*
5185  * Helper function for "update_view()" below
5186  *
5187  * We are checking the "viewability" of grid (y,x) by the player.
5188  *
5189  * This function assumes that (y,x) is legal (i.e. on the map).
5190  *
5191  * Grid (y1,x1) is on the "diagonal" between (py,px) and (y,x)
5192  * Grid (y2,x2) is "adjacent", also between (py,px) and (y,x).
5193  *
5194  * Note that we are using the "CAVE_XTRA" field for marking grids as
5195  * "easily viewable".  This bit is cleared at the end of "update_view()".
5196  *
5197  * This function adds (y,x) to the "viewable set" if necessary.
5198  *
5199  * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
5200  */
5201 
5202 
5203 static bool update_view_aux(int Ind, int y, int x, int y1, int x1, int y2, int x2)
5204 {
5205 	player_type *p_ptr = Players[Ind];
5206 
5207 	bool f1, f2, v1, v2, z1, z2, wall;
5208 
5209 	cave_type *c_ptr;
5210 	byte *w_ptr;
5211 
5212 	cave_type *g1_c_ptr;
5213 	cave_type *g2_c_ptr;
5214 
5215 	byte *g1_w_ptr;
5216 	byte *g2_w_ptr;
5217 
5218 	struct worldpos *wpos = &p_ptr->wpos;
5219 	cave_type **zcave;
5220 	if (!(zcave = getcave(wpos))) return FALSE;
5221 
5222 	if (y < 0 || y >= MAX_HGT || x < 0 || x >= MAX_WID) return(FALSE);
5223 
5224 	/* Access the grids */
5225 	g1_c_ptr = &zcave[y1][x1];
5226 	g2_c_ptr = &zcave[y2][x2];
5227 
5228 	g1_w_ptr = &p_ptr->cave_flag[y1][x1];
5229 	g2_w_ptr = &p_ptr->cave_flag[y2][x2];
5230 
5231 
5232 	/* Check for walls */
5233 	f1 = (cave_los_grid(g1_c_ptr));
5234 	f2 = (cave_los_grid(g2_c_ptr));
5235 
5236 	/* Totally blocked by physical walls */
5237 	if (!f1 && !f2) return (TRUE);
5238 
5239 
5240 	/* Check for visibility */
5241 	v1 = (f1 && (*(g1_w_ptr) & CAVE_VIEW));
5242 	v2 = (f2 && (*(g2_w_ptr) & CAVE_VIEW));
5243 
5244 	/* Totally blocked by "unviewable neighbors" */
5245 	if (!v1 && !v2) return (TRUE);
5246 
5247 
5248 	/* Access the grid */
5249 	c_ptr = &zcave[y][x];
5250 	w_ptr = &p_ptr->cave_flag[y][x];
5251 
5252 
5253 	/* Check for walls */
5254 	wall = (!cave_los_grid(c_ptr));
5255 
5256 
5257 	/* Check the "ease" of visibility */
5258 	z1 = (v1 && (g1_c_ptr->info & CAVE_XTRA));
5259 	z2 = (v2 && (g2_c_ptr->info & CAVE_XTRA));
5260 
5261 	/* Hack -- "easy" plus "easy" yields "easy" */
5262 	if (z1 && z2)
5263 	{
5264 		c_ptr->info |= CAVE_XTRA;
5265 
5266 		cave_view_hack(w_ptr, y, x);
5267 
5268 		return (wall);
5269 	}
5270 
5271 	/* Hack -- primary "easy" yields "viewed" */
5272 	if (z1)
5273 	{
5274 		cave_view_hack(w_ptr, y, x);
5275 
5276 		return (wall);
5277 	}
5278 
5279 
5280 	/* Hack -- "view" plus "view" yields "view" */
5281 	if (v1 && v2)
5282 	{
5283 		/* c_ptr->info |= CAVE_XTRA; */
5284 
5285 		cave_view_hack(w_ptr, y, x);
5286 
5287 		return (wall);
5288 	}
5289 
5290 
5291 	/* Mega-Hack -- the "los()" function works poorly on walls */
5292 	if (wall)
5293 	{
5294 		cave_view_hack(w_ptr, y, x);
5295 
5296 		return (wall);
5297 	}
5298 
5299 
5300 	/* Hack -- check line of sight */
5301 	if (los(wpos, p_ptr->py, p_ptr->px, y, x))
5302 	{
5303 		cave_view_hack(w_ptr, y, x);
5304 
5305 		return (wall);
5306 	}
5307 
5308 
5309 	/* Assume no line of sight. */
5310 	return (TRUE);
5311 }
5312 
5313 
5314 
5315 /*
5316  * Calculate the viewable space
5317  *
5318  *  1: Process the player
5319  *  1a: The player is always (easily) viewable
5320  *  2: Process the diagonals
5321  *  2a: The diagonals are (easily) viewable up to the first wall
5322  *  2b: But never go more than 2/3 of the "full" distance
5323  *  3: Process the main axes
5324  *  3a: The main axes are (easily) viewable up to the first wall
5325  *  3b: But never go more than the "full" distance
5326  *  4: Process sequential "strips" in each of the eight octants
5327  *  4a: Each strip runs along the previous strip
5328  *  4b: The main axes are "previous" to the first strip
5329  *  4c: Process both "sides" of each "direction" of each strip
5330  *  4c1: Each side aborts as soon as possible
5331  *  4c2: Each side tells the next strip how far it has to check
5332  *
5333  * Note that the octant processing involves some pretty interesting
5334  * observations involving when a grid might possibly be viewable from
5335  * a given grid, and on the order in which the strips are processed.
5336  *
5337  * Note the use of the mathematical facts shown below, which derive
5338  * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
5339  * hypotenuse of a right triangle is primarily determined by the length
5340  * of the longest side, when one side is small, and is strictly less
5341  * than one-and-a-half times as long as the longest side when both of
5342  * the sides are large.
5343  *
5344  *   if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
5345  *   if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
5346  *
5347  *   hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
5348  *
5349  * These observations are important because the calculation of the actual
5350  * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
5351  * while for small values (up to about 20 or so), the approximations above
5352  * are correct to within an error of at most one grid or so.
5353  *
5354  * Observe the use of "full" and "over" in the code below, and the use of
5355  * the specialized calculation involving "limit", all of which derive from
5356  * the observations given above.  Basically, we note that the "circle" of
5357  * view is completely contained in an "octagon" whose bounds are easy to
5358  * determine, and that only a few steps are needed to derive the actual
5359  * bounds of the circle given the bounds of the octagon.
5360  *
5361  * Note that by skipping all the grids in the corners of the octagon, we
5362  * place an upper limit on the number of grids in the field of view, given
5363  * that "full" is never more than 20.  Of the 1681 grids in the "square" of
5364  * view, only about 1475 of these are in the "octagon" of view, and even
5365  * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
5366  * entries to completely contain the actual field of view.
5367  *
5368  * Note also the care taken to prevent "running off the map".  The use of
5369  * explicit checks on the "validity" of the "diagonal", and the fact that
5370  * the loops are never allowed to "leave" the map, lets "update_view_aux()"
5371  * use the optimized "cave_floor_bold()" macro, and to avoid the overhead
5372  * of multiple checks on the validity of grids.
5373  *
5374  * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
5375  * "ws","wn" variables.  They work like this: While travelling down the
5376  * south-bound strip just to the east of the main south axis, as soon as
5377  * we get to a grid which does not "transmit" viewing, if all of the strips
5378  * preceding us (in this case, just the main axis) had terminated at or before
5379  * the same point, then we can stop, and reset the "max distance" to ourself.
5380  * So, each strip (named by major axis plus offset, thus "se" in this case)
5381  * maintains a "blockage" variable, initialized during the main axis step,
5382  * and checks it whenever a blockage is observed.  After processing each
5383  * strip as far as the previous strip told us to process, the next strip is
5384  * told not to go farther than the current strip's farthest viewable grid,
5385  * unless open space is still available.  This uses the "k" variable.
5386  *
5387  * Note the use of "inline" macros for efficiency.  The "cave_floor_grid()"
5388  * macro is a replacement for "cave_floor_bold()" which takes a pointer to
5389  * a cave grid instead of its location.  The "cave_view_hack()" macro is a
5390  * chunk of code which adds the given location to the "view" array if it
5391  * is not already there, using both the actual location and a pointer to
5392  * the cave grid.  See above.
5393  *
5394  * By the way, the purpose of this code is to reduce the dependancy on the
5395  * "los()" function which is slow, and, in some cases, not very accurate.
5396  *
5397  * It is very possible that I am the only person who fully understands this
5398  * function, and for that I am truly sorry, but efficiency was very important
5399  * and the "simple" version of this function was just not fast enough.  I am
5400  * more than willing to replace this function with a simpler one, if it is
5401  * equally efficient, and especially willing if the new function happens to
5402  * derive "reverse-line-of-sight" at the same time, since currently monsters
5403  * just use an optimized hack of "you see me, so I see you", and then use the
5404  * actual "projectable()" function to check spell attacks.
5405  *
5406  * Well, I for one don't understand it, so I'm hoping I didn't screw anything
5407  * up while trying to do this. --KLJ--
5408  */
5409 
5410  /* Hmm, this function doesn't seem to be very "mangworld" friendly...
5411     lets add some speedbumps/sanity checks.
5412     -APD-
5413 
5414     With my new "invisible wall" code this shouldn't be neccecary.
5415 
5416  */
5417 
5418 /* TODO: Hrm, recent variants seem to get better algorithm
5419  * - let's port them! */
5420 
5421 void update_view(int Ind)
5422 {
5423 	player_type *p_ptr = Players[Ind];
5424 
5425 	int n, m, d, k, y, x, z;
5426 
5427 	int se, sw, ne, nw, es, en, ws, wn;
5428 
5429 	int full, over;
5430 
5431 	int y_max = MAX_HGT - 1;
5432 	int x_max = MAX_WID - 1;
5433 
5434 	cave_type *c_ptr;
5435 	byte *w_ptr;
5436 	bool unmap = FALSE;
5437 
5438 	cave_type **zcave;
5439 	struct worldpos *wpos;
5440 	wpos = &p_ptr->wpos;
5441 	if (!(zcave = getcave(wpos))) return;
5442 
5443 	if (p_ptr->wpos.wz) {
5444 		dun_level *l_ptr = getfloor(&p_ptr->wpos);
5445 		if (l_ptr && l_ptr->flags1 & LF1_NO_MAP) unmap = TRUE;
5446 	}
5447 
5448 
5449 	/*** Initialize ***/
5450 
5451 	/* Optimize */
5452 	if (p_ptr->view_reduce_view && istown(wpos)) /* town */
5453 	{
5454 		/* Full radius (10) */
5455 		full = MAX_SIGHT / 2;
5456 
5457 		/* Octagon factor (15) */
5458 		over = MAX_SIGHT * 3 / 4;
5459 	}
5460 
5461 	/* Normal */
5462 	else
5463 	{
5464 		/* Full radius (20) */
5465 		full = MAX_SIGHT;
5466 
5467 		/* Octagon factor (30) */
5468 		over = MAX_SIGHT * 3 / 2;
5469 	}
5470 
5471 
5472 	/*** Step 0 -- Begin ***/
5473 
5474 	/* Save the old "view" grids for later */
5475 	for (n = 0; n < p_ptr->view_n; n++) {
5476 		y = p_ptr->view_y[n];
5477 		x = p_ptr->view_x[n];
5478 
5479 		/* Access the grid */
5480 		c_ptr = &zcave[y][x];
5481 		w_ptr = &p_ptr->cave_flag[y][x];
5482 
5483 		/* Mark the grid as not in "view" */
5484 		*w_ptr &= ~(CAVE_VIEW);
5485 
5486 		/* Mark the grid as "seen" */
5487 		c_ptr->info |= CAVE_TEMP;
5488 
5489 		/* Add it to the "seen" set */
5490 		p_ptr->temp_y[p_ptr->temp_n] = y;
5491 		p_ptr->temp_x[p_ptr->temp_n] = x;
5492 		p_ptr->temp_n++;
5493 	}
5494 
5495 	/* Start over with the "view" array */
5496 	p_ptr->view_n = 0;
5497 
5498 
5499 	/*** Step 1 -- adjacent grids ***/
5500 
5501 	/* Now start on the player */
5502 	y = p_ptr->py;
5503 	x = p_ptr->px;
5504 
5505 	/* Access the grid */
5506 	c_ptr = &zcave[y][x];
5507 	w_ptr = &p_ptr->cave_flag[y][x];
5508 
5509 	/* Assume the player grid is easily viewable */
5510 	c_ptr->info |= CAVE_XTRA;
5511 
5512 	/* Assume the player grid is viewable */
5513 	cave_view_hack(w_ptr, y, x);
5514 
5515 
5516 	/*** Step 2 -- Major Diagonals ***/
5517 
5518 	/* Hack -- Limit */
5519 	z = full * 2 / 3;
5520 
5521 	/* Scan south-east */
5522 	for (d = 1; d <= z; d++) {
5523 //superfluous		if (!in_bounds_array(y+d, x+d)) break;
5524 		if (y + d >= MAX_HGT) break;
5525 		c_ptr = &zcave[y+d][x+d];
5526 		w_ptr = &p_ptr->cave_flag[y+d][x+d];
5527 		c_ptr->info |= CAVE_XTRA;
5528 		cave_view_hack(w_ptr, y+d, x+d);
5529 		if (!cave_los_grid(c_ptr)) break;
5530 	}
5531 
5532 	/* Scan south-west */
5533 	for (d = 1; d <= z; d++) {
5534 //superfluous		if (!in_bounds_array(y+d, x-d)) break;
5535 		if (y + d >= MAX_HGT) break;
5536 		c_ptr = &zcave[y+d][x-d];
5537 		w_ptr = &p_ptr->cave_flag[y+d][x-d];
5538 		c_ptr->info |= CAVE_XTRA;
5539 		cave_view_hack(w_ptr, y+d, x-d);
5540 		if (!cave_los_grid(c_ptr)) break;
5541 	}
5542 
5543 	/* Scan north-east */
5544 	for (d = 1; d <= z; d++) {
5545 //superfluous		if (!in_bounds_array(y-d, x+d)) break;
5546 		if (d > y) break;
5547 		c_ptr = &zcave[y-d][x+d];
5548 		w_ptr = &p_ptr->cave_flag[y-d][x+d];
5549 		c_ptr->info |= CAVE_XTRA;
5550 		cave_view_hack(w_ptr, y-d, x+d);
5551 		if (!cave_los_grid(c_ptr)) break;
5552 	}
5553 
5554 	/* Scan north-west */
5555 	for (d = 1; d <= z; d++) {
5556 //superfluous		if (!in_bounds_array(y-d, x-d)) break;
5557 		if (d > y) break;
5558 		c_ptr = &zcave[y-d][x-d];
5559 		w_ptr = &p_ptr->cave_flag[y-d][x-d];
5560 		c_ptr->info |= CAVE_XTRA;
5561 		cave_view_hack(w_ptr, y-d, x-d);
5562 		if (!cave_los_grid(c_ptr)) break;
5563 	}
5564 
5565 
5566 	/*** Step 3 -- major axes ***/
5567 
5568 	/* Scan south */
5569 	for (d = 1; d <= full; d++) {
5570 		/*if (y + d >= MAX_HGT) break;*/
5571 		c_ptr = &zcave[y+d][x];
5572 		w_ptr = &p_ptr->cave_flag[y+d][x];
5573 		c_ptr->info |= CAVE_XTRA;
5574 		cave_view_hack(w_ptr, y+d, x);
5575 		if (!cave_los_grid(c_ptr)) break;
5576 //superfluous		if (!in_bounds_array(y+d+1, x)) break;
5577 	}
5578 
5579 	/* Initialize the "south strips" */
5580 	se = sw = d;
5581 
5582 	/* Scan north */
5583 	for (d = 1; d <= full; d++) {
5584 		/*if (d > y) break;*/
5585 		c_ptr = &zcave[y-d][x];
5586 		w_ptr = &p_ptr->cave_flag[y-d][x];
5587 		c_ptr->info |= CAVE_XTRA;
5588 		cave_view_hack(w_ptr, y-d, x);
5589 		if (!cave_los_grid(c_ptr)) break;
5590 //superfluous		if (!in_bounds_array(y-d-1, x)) break;
5591 	}
5592 
5593 	/* Initialize the "north strips" */
5594 	ne = nw = d;
5595 
5596 	/* Scan east */
5597 	for (d = 1; d <= full; d++) {
5598 		c_ptr = &zcave[y][x+d];
5599 		w_ptr = &p_ptr->cave_flag[y][x+d];
5600 		c_ptr->info |= CAVE_XTRA;
5601 		cave_view_hack(w_ptr, y, x+d);
5602 		if (!cave_los_grid(c_ptr)) break;
5603 //superfluous		if (!in_bounds_array(y, x+d+1)) break;
5604 	}
5605 
5606 	/* Initialize the "east strips" */
5607 	es = en = d;
5608 
5609 	/* Scan west */
5610 	for (d = 1; d <= full; d++) {
5611 		c_ptr = &zcave[y][x-d];
5612 		w_ptr = &p_ptr->cave_flag[y][x-d];
5613 		c_ptr->info |= CAVE_XTRA;
5614 		cave_view_hack(w_ptr, y, x-d);
5615 		if (!cave_los_grid(c_ptr)) break;
5616 //superfluous		if (!in_bounds_array(y, x-d-1)) break;
5617 	}
5618 
5619 	/* Initialize the "west strips" */
5620 	ws = wn = d;
5621 
5622 
5623 	/*** Step 4 -- Divide each "octant" into "strips" ***/
5624 
5625 	/* Now check each "diagonal" (in parallel) */
5626 	for (n = 1; n <= over / 2; n++) {
5627 		int ypn, ymn, xpn, xmn;
5628 
5629 
5630 		/* Acquire the "bounds" of the maximal circle */
5631 		z = over - n - n;
5632 		if (z > full - n) z = full - n;
5633 		while ((z + n + (n>>1)) > full) z--;
5634 
5635 
5636 		/* Access the four diagonal grids */
5637 		ypn = y + n;
5638 		ymn = y - n;
5639 		xpn = x + n;
5640 		xmn = x - n;
5641 
5642 
5643 		/* South strip */
5644 		if (ypn < y_max) {
5645 			/* Maximum distance */
5646 			m = MIN(z, y_max - ypn);
5647 
5648 			/* East side */
5649 			if ((xpn <= x_max) && (n < se)) {
5650 				/* Scan */
5651 				for (k = n, d = 1; d <= m; d++) {
5652 					/*if (ypn + d >= MAX_HGT) break; */
5653 
5654 					/* Check grid "d" in strip "n", notice "blockage" */
5655 					if (update_view_aux(Ind, ypn+d, xpn, ypn+d-1, xpn-1, ypn+d-1, xpn))
5656 					{
5657 						if (n + d >= se) break;
5658 					}
5659 
5660 					/* Track most distant "non-blockage" */
5661 					else
5662 					{
5663 						k = n + d;
5664 					}
5665 				}
5666 
5667 				/* Limit the next strip */
5668 				se = k + 1;
5669 			}
5670 
5671 			/* West side */
5672 			if ((xmn >= 0) && (n < sw)) {
5673 				/* Scan */
5674 				for (k = n, d = 1; d <= m; d++) {
5675 					/*if (ypn + d >= MAX_HGT) break;*/
5676 
5677 					/* Check grid "d" in strip "n", notice "blockage" */
5678 					if (update_view_aux(Ind, ypn+d, xmn, ypn+d-1, xmn+1, ypn+d-1, xmn))
5679 					{
5680 						if (n + d >= sw) break;
5681 					}
5682 
5683 					/* Track most distant "non-blockage" */
5684 					else
5685 					{
5686 						k = n + d;
5687 					}
5688 
5689 				}
5690 
5691 				/* Limit the next strip */
5692 				sw = k + 1;
5693 			}
5694 		}
5695 
5696 
5697 		/* North strip */
5698 		if (ymn > 0)
5699 		{
5700 			/* Maximum distance */
5701 			m = MIN(z, ymn);
5702 
5703 			/* East side */
5704 			if ((xpn <= x_max) && (n < ne))
5705 			{
5706 				/* Scan */
5707 				for (k = n, d = 1; d <= m; d++)
5708 				{
5709 					/*if (d > ymn) break;*/
5710 
5711 					/* Check grid "d" in strip "n", notice "blockage" */
5712 					if (update_view_aux(Ind, ymn-d, xpn, ymn-d+1, xpn-1, ymn-d+1, xpn))
5713 					{
5714 						if (n + d >= ne) break;
5715 					}
5716 
5717 					/* Track most distant "non-blockage" */
5718 					else
5719 					{
5720 						k = n + d;
5721 					}
5722 				}
5723 
5724 				/* Limit the next strip */
5725 				ne = k + 1;
5726 			}
5727 
5728 			/* West side */
5729 			if ((xmn >= 0) && (n < nw))
5730 			{
5731 				/* Scan */
5732 				for (k = n, d = 1; d <= m; d++)
5733 				{
5734 					/*if (d > ymn) break;*/
5735 
5736 					/* Check grid "d" in strip "n", notice "blockage" */
5737 					if (update_view_aux(Ind, ymn-d, xmn, ymn-d+1, xmn+1, ymn-d+1, xmn))
5738 					{
5739 						if (n + d >= nw) break;
5740 					}
5741 
5742 					/* Track most distant "non-blockage" */
5743 					else
5744 					{
5745 						k = n + d;
5746 					}
5747 				}
5748 
5749 				/* Limit the next strip */
5750 				nw = k + 1;
5751 			}
5752 		}
5753 
5754 
5755 		/* East strip */
5756 		if (xpn < x_max)
5757 		{
5758 			/* Maximum distance */
5759 			m = MIN(z, x_max - xpn);
5760 
5761 			/* South side */
5762 			if ((ypn <= x_max) && (n < es))
5763 			{
5764 				/* Scan */
5765 				for (k = n, d = 1; d <= m; d++)
5766 				{
5767 					/*if (ypn >= MAX_HGT) break;*/
5768 
5769 					/* Check grid "d" in strip "n", notice "blockage" */
5770 					if (update_view_aux(Ind, ypn, xpn+d, ypn-1, xpn+d-1, ypn, xpn+d-1))
5771 					{
5772 						if (n + d >= es) break;
5773 					}
5774 
5775 					/* Track most distant "non-blockage" */
5776 					else
5777 					{
5778 						k = n + d;
5779 					}
5780 				}
5781 
5782 				/* Limit the next strip */
5783 				es = k + 1;
5784 			}
5785 
5786 			/* North side */
5787 			if ((ymn >= 0) && (n < en))
5788 			{
5789 				/* Scan */
5790 				for (k = n, d = 1; d <= m; d++)
5791 				{
5792 					/*if (ymn >= MAX_HGT) break;*/
5793 
5794 					/* Check grid "d" in strip "n", notice "blockage" */
5795 					if (update_view_aux(Ind, ymn, xpn+d, ymn+1, xpn+d-1, ymn, xpn+d-1))
5796 					{
5797 						if (n + d >= en) break;
5798 					}
5799 
5800 					/* Track most distant "non-blockage" */
5801 					else
5802 					{
5803 						k = n + d;
5804 					}
5805 				}
5806 
5807 				/* Limit the next strip */
5808 				en = k + 1;
5809 			}
5810 		}
5811 
5812 
5813 		/* West strip */
5814 		if (xmn > 0)
5815 		{
5816 			/* Maximum distance */
5817 			m = MIN(z, xmn);
5818 
5819 			/* South side */
5820 			if ((ypn <= y_max) && (n < ws))
5821 			{
5822 				/* Scan */
5823 				for (k = n, d = 1; d <= m; d++)
5824 				{
5825 					/*if (ypn >= MAX_HGT) break;*/
5826 
5827 					/* Check grid "d" in strip "n", notice "blockage" */
5828 					if (update_view_aux(Ind, ypn, xmn-d, ypn-1, xmn-d+1, ypn, xmn-d+1))
5829 					{
5830 						if (n + d >= ws) break;
5831 					}
5832 
5833 					/* Track most distant "non-blockage" */
5834 					else
5835 					{
5836 						k = n + d;
5837 					}
5838 				}
5839 
5840 				/* Limit the next strip */
5841 				ws = k + 1;
5842 			}
5843 
5844 			/* North side */
5845 			if ((ymn >= 0) && (n < wn))
5846 			{
5847 				/* Scan */
5848 				for (k = n, d = 1; d <= m; d++)
5849 				{
5850 					/*if (ymn >= MAX_HGT) break;*/
5851 
5852 					/* Check grid "d" in strip "n", notice "blockage" */
5853 					if (update_view_aux(Ind, ymn, xmn-d, ymn+1, xmn-d+1, ymn, xmn-d+1))
5854 					{
5855 						if (n + d >= wn) break;
5856 					}
5857 
5858 					/* Track most distant "non-blockage" */
5859 					else
5860 					{
5861 						k = n + d;
5862 					}
5863 				}
5864 
5865 				/* Limit the next strip */
5866 				wn = k + 1;
5867 			}
5868 		}
5869 	}
5870 
5871 
5872 	/*** Step 5 -- Complete the algorithm ***/
5873 
5874 	/* Update all the new grids */
5875 	for (n = 0; n < p_ptr->view_n; n++)
5876 	{
5877 		y = p_ptr->view_y[n];
5878 		x = p_ptr->view_x[n];
5879 
5880 		/* Access the grid */
5881 		c_ptr = &zcave[y][x];
5882 
5883 		/* Clear the "CAVE_XTRA" flag */
5884 		c_ptr->info &= ~CAVE_XTRA;
5885 
5886 		/* Update only newly viewed grids */
5887 		if (c_ptr->info & CAVE_TEMP) continue;
5888 
5889 		/* Note */
5890 		note_spot(Ind, y, x);
5891 
5892 		/* Redraw */
5893 		lite_spot(Ind, y, x);
5894 	}
5895 
5896 	/* Wipe the old grids, update as needed */
5897 	for (n = 0; n < p_ptr->temp_n; n++)
5898 	{
5899 		y = p_ptr->temp_y[n];
5900 		x = p_ptr->temp_x[n];
5901 
5902 		/* Access the grid */
5903 		c_ptr = &zcave[y][x];
5904 		w_ptr = &p_ptr->cave_flag[y][x];
5905 
5906 		/* No longer in the array */
5907 		c_ptr->info &= ~CAVE_TEMP;
5908 
5909 		/* Update only non-viewable grids */
5910 		if (*w_ptr & CAVE_VIEW) continue;
5911 
5912 		/* Forget it, dude */
5913 		if (unmap)
5914 		{
5915 			u16b this_o_idx, next_o_idx = 0;
5916 
5917 			*w_ptr &= ~CAVE_MARK;
5918 
5919 			/* make player forget of objects too */
5920 			/* too bad, traps cannot be forgotten this way.. */
5921 			for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
5922 			{
5923 				/* Acquire next object */
5924 				next_o_idx = o_list[this_o_idx].next_o_idx;
5925 
5926 				/* Forget the object */
5927 				p_ptr->obj_vis[this_o_idx] = FALSE;
5928 			}
5929 		}
5930 
5931 		/* Redraw */
5932 		lite_spot(Ind, y, x);
5933 	}
5934 
5935 	/* None left */
5936 	p_ptr->temp_n = 0;
5937 }
5938 #else	/* USE_OLD_UPDATE_VIEW */
5939 /* New update_view code from ToME... but it was slower than ours in fact.
5940  * pfft
5941  */
5942 
5943 /*
5944  * Maximum number of grids in a single octant
5945  */
5946 #define VINFO_MAX_GRIDS 161
5947 
5948 
5949 /*
5950  * Maximum number of slopes in a single octant
5951  */
5952 #define VINFO_MAX_SLOPES 126
5953 
5954 
5955 /*
5956  * Mask of bits used in a single octant
5957  */
5958 #define VINFO_BITS_3 0x3FFFFFFF
5959 #define VINFO_BITS_2 0xFFFFFFFF
5960 #define VINFO_BITS_1 0xFFFFFFFF
5961 #define VINFO_BITS_0 0xFFFFFFFF
5962 
5963 
5964 /*
5965  * Forward declare
5966  */
5967 typedef struct vinfo_type vinfo_type;
5968 
5969 
5970 /*
5971  * The 'vinfo_type' structure
5972  */
5973 struct vinfo_type
5974 {
5975 	s16b grid_y[8];
5976 	s16b grid_x[8];
5977 
5978 	u32b bits_3;
5979 	u32b bits_2;
5980 	u32b bits_1;
5981 	u32b bits_0;
5982 
5983 	vinfo_type *next_0;
5984 	vinfo_type *next_1;
5985 
5986 	byte y;
5987 	byte x;
5988 	byte d;
5989 	byte r;
5990 };
5991 
5992 
5993 
5994 /*
5995  * The array of "vinfo" objects, initialized by "vinfo_init()"
5996  */
5997 static vinfo_type vinfo[VINFO_MAX_GRIDS];
5998 
5999 
6000 
6001 
6002 /*
6003  * Slope scale factor
6004  */
6005 #define SCALE 100000L
6006 
6007 
6008 /*
6009  * Forward declare
6010  */
6011 typedef struct vinfo_hack vinfo_hack;
6012 
6013 
6014 /*
6015  * Temporary data used by "vinfo_init()"
6016  *
6017  *	- Number of grids
6018  *
6019  *	- Number of slopes
6020  *
6021  *	- Slope values
6022  *
6023  *	- Slope range per grid
6024  */
6025 struct vinfo_hack {
6026 
6027 	int num_slopes;
6028 
6029 	long slopes[VINFO_MAX_SLOPES];
6030 
6031 	long slopes_min[MAX_SIGHT+1][MAX_SIGHT+1];
6032 	long slopes_max[MAX_SIGHT+1][MAX_SIGHT+1];
6033 };
6034 
6035 
6036 
6037 /*
6038  * Sorting hook -- comp function -- array of long's (see below)
6039  *
6040  * We use "u" to point to an array of long integers.
6041  */
6042 /* Ind is utter dummy. */
6043 static bool ang_sort_comp_hook_longs(int Ind, vptr u, vptr v, int a, int b)
6044 {
6045 	long *x = (long*)(u);
6046 
6047 	return (x[a] <= x[b]);
6048 }
6049 
6050 
6051 /*
6052  * Sorting hook -- comp function -- array of long's (see below)
6053  *
6054  * We use "u" to point to an array of long integers.
6055  */
6056 static void ang_sort_swap_hook_longs(int Ind, vptr u, vptr v, int a, int b)
6057 {
6058 	long *x = (long*)(u);
6059 
6060         long temp;
6061 
6062         /* Swap */
6063         temp = x[a];
6064         x[a] = x[b];
6065         x[b] = temp;
6066 }
6067 
6068 
6069 
6070 /*
6071  * Save a slope
6072  */
6073 static void vinfo_init_aux(vinfo_hack *hack, int y, int x, long m)
6074 {
6075 	int i;
6076 
6077 	/* Handle "legal" slopes */
6078 	if ((m > 0) && (m <= SCALE))
6079 	{
6080 		/* Look for that slope */
6081 		for (i = 0; i < hack->num_slopes; i++)
6082 		{
6083 			if (hack->slopes[i] == m) break;
6084 		}
6085 
6086 		/* New slope */
6087 		if (i == hack->num_slopes)
6088 		{
6089 			/* Paranoia */
6090 			if (hack->num_slopes >= VINFO_MAX_SLOPES)
6091 			{
6092 				quit_fmt("Too many slopes (%d)!",
6093 			         	VINFO_MAX_SLOPES);
6094 			}
6095 
6096 			/* Save the slope, and advance */
6097 			hack->slopes[hack->num_slopes++] = m;
6098 		}
6099 	}
6100 
6101 	/* Track slope range */
6102 	if (hack->slopes_min[y][x] > m) hack->slopes_min[y][x] = m;
6103 	if (hack->slopes_max[y][x] < m) hack->slopes_max[y][x] = m;
6104 }
6105 
6106 
6107 
6108 /*
6109  * Initialize the "vinfo" array
6110  *
6111  * Full Octagon (radius 20), Grids=1149
6112  *
6113  * Quadrant (south east), Grids=308, Slopes=251
6114  *
6115  * Octant (east then south), Grids=161, Slopes=126
6116  *
6117  * This function assumes that VINFO_MAX_GRIDS and VINFO_MAX_SLOPES
6118  * have the correct values, which can be derived by setting them to
6119  * a number which is too high, running this function, and using the
6120  * error messages to obtain the correct values.
6121  */
6122 errr vinfo_init(void)
6123 {
6124 	int i, y, x;
6125 
6126 	long m;
6127 
6128 	vinfo_hack *hack;
6129 
6130 	int num_grids = 0;
6131 
6132 	int queue_head = 0;
6133 	int queue_tail = 0;
6134 	vinfo_type *queue[VINFO_MAX_GRIDS*2];
6135 
6136 
6137 	/* Make hack */
6138 	MAKE(hack, vinfo_hack);
6139 
6140 
6141 	/* Analyze grids */
6142 	for (y = 0; y <= MAX_SIGHT; ++y)
6143 	{
6144 		for (x = y; x <= MAX_SIGHT; ++x)
6145 		{
6146 			/* Skip grids which are out of sight range */
6147 			if (distance(0, 0, y, x) > MAX_SIGHT) continue;
6148 
6149 			/* Default slope range */
6150 			hack->slopes_min[y][x] = 999999999;
6151 			hack->slopes_max[y][x] = 0;
6152 
6153 			/* Paranoia */
6154 			if (num_grids >= VINFO_MAX_GRIDS)
6155 			{
6156 				quit_fmt("Too many grids (%d >= %d)!",
6157 				         num_grids, VINFO_MAX_GRIDS);
6158 			}
6159 
6160 			/* Count grids */
6161 			num_grids++;
6162 
6163 			/* Slope to the top right corner */
6164 			m = SCALE * (1000L * y - 500) / (1000L * x + 500);
6165 
6166 			/* Handle "legal" slopes */
6167 			vinfo_init_aux(hack, y, x, m);
6168 
6169 			/* Slope to top left corner */
6170 			m = SCALE * (1000L * y - 500) / (1000L * x - 500);
6171 
6172 			/* Handle "legal" slopes */
6173 			vinfo_init_aux(hack, y, x, m);
6174 
6175 			/* Slope to bottom right corner */
6176 			m = SCALE * (1000L * y + 500) / (1000L * x + 500);
6177 
6178 			/* Handle "legal" slopes */
6179 			vinfo_init_aux(hack, y, x, m);
6180 
6181 			/* Slope to bottom left corner */
6182 			m = SCALE * (1000L * y + 500) / (1000L * x - 500);
6183 
6184 			/* Handle "legal" slopes */
6185 			vinfo_init_aux(hack, y, x, m);
6186 		}
6187 	}
6188 
6189 
6190 	/* Enforce maximal efficiency */
6191 	if (num_grids < VINFO_MAX_GRIDS)
6192 	{
6193 		quit_fmt("Too few grids (%d < %d)!",
6194 		         num_grids, VINFO_MAX_GRIDS);
6195 	}
6196 
6197 	/* Enforce maximal efficiency */
6198 	if (hack->num_slopes < VINFO_MAX_SLOPES)
6199 	{
6200 		quit_fmt("Too few slopes (%d < %d)!",
6201 		         hack->num_slopes, VINFO_MAX_SLOPES);
6202 	}
6203 
6204 
6205 	/* Sort slopes numerically */
6206 	ang_sort_comp = ang_sort_comp_hook_longs;
6207 
6208 	/* Sort slopes numerically */
6209 	ang_sort_swap = ang_sort_swap_hook_longs;
6210 
6211 	/* Sort the (unique) slopes */
6212 	ang_sort(0, hack->slopes, NULL, hack->num_slopes);
6213 
6214 
6215 
6216 	/* Enqueue player grid */
6217 	queue[queue_tail++] = &vinfo[0];
6218 
6219 	/* Process queue */
6220 	while (queue_head < queue_tail)
6221 	{
6222 		int e;
6223 
6224 		vinfo_type *p;
6225 
6226 
6227 		/* Index */
6228 		e = queue_head;
6229 
6230 		/* Dequeue next grid */
6231 		p = queue[queue_head++];
6232 
6233 		/* Location of main grid */
6234 		y = vinfo[e].grid_y[0];
6235 		x = vinfo[e].grid_x[0];
6236 
6237 
6238 		/* Compute grid offsets */
6239 		vinfo[e].grid_y[0] = +y; vinfo[e].grid_x[0] = +x;
6240 		vinfo[e].grid_y[1] = +x; vinfo[e].grid_x[1] = +y;
6241 		vinfo[e].grid_y[2] = +x; vinfo[e].grid_x[2] = -y;
6242 		vinfo[e].grid_y[3] = +y; vinfo[e].grid_x[3] = -x;
6243 		vinfo[e].grid_y[4] = -y; vinfo[e].grid_x[4] = -x;
6244 		vinfo[e].grid_y[5] = -x; vinfo[e].grid_x[5] = -y;
6245 		vinfo[e].grid_y[6] = -x; vinfo[e].grid_x[6] = +y;
6246 		vinfo[e].grid_y[7] = -y; vinfo[e].grid_x[7] = +x;
6247 
6248 
6249 		/* Analyze slopes */
6250 		for (i = 0; i < hack->num_slopes; ++i)
6251 		{
6252 			m = hack->slopes[i];
6253 
6254 			/* Memorize intersection slopes (for non-player-grids) */
6255 			if ((e > 0) &&
6256 			    (hack->slopes_min[y][x] < m) &&
6257 			    (m < hack->slopes_max[y][x]))
6258 			{
6259 				switch (i / 32)
6260 				{
6261 					case 3: vinfo[e].bits_3 |= (1L << (i % 32)); break;
6262 					case 2: vinfo[e].bits_2 |= (1L << (i % 32)); break;
6263 					case 1: vinfo[e].bits_1 |= (1L << (i % 32)); break;
6264 					case 0: vinfo[e].bits_0 |= (1L << (i % 32)); break;
6265 				}
6266 			}
6267 		}
6268 
6269 
6270 		/* Default */
6271 		vinfo[e].next_0 = &vinfo[0];
6272 
6273 		/* Grid next child */
6274 		if (distance(0, 0, y, x+1) <= MAX_SIGHT)
6275 		{
6276 			if ((queue[queue_tail-1]->grid_y[0] != y) ||
6277 			    (queue[queue_tail-1]->grid_x[0] != x + 1))
6278 			{
6279 				vinfo[queue_tail].grid_y[0] = y;
6280 				vinfo[queue_tail].grid_x[0] = x + 1;
6281 				queue[queue_tail] = &vinfo[queue_tail];
6282 				queue_tail++;
6283 			}
6284 
6285 			vinfo[e].next_0 = &vinfo[queue_tail - 1];
6286 		}
6287 
6288 
6289 		/* Default */
6290 		vinfo[e].next_1 = &vinfo[0];
6291 
6292 		/* Grid diag child */
6293 		if (distance(0, 0, y+1, x+1) <= MAX_SIGHT)
6294 		{
6295 			if ((queue[queue_tail-1]->grid_y[0] != y + 1) ||
6296 			    (queue[queue_tail-1]->grid_x[0] != x + 1))
6297 			{
6298 				vinfo[queue_tail].grid_y[0] = y + 1;
6299 				vinfo[queue_tail].grid_x[0] = x + 1;
6300 				queue[queue_tail] = &vinfo[queue_tail];
6301 				queue_tail++;
6302 			}
6303 
6304 			vinfo[e].next_1 = &vinfo[queue_tail - 1];
6305 		}
6306 
6307 
6308 		/* Hack -- main diagonal has special children */
6309 		if (y == x) vinfo[e].next_0 = vinfo[e].next_1;
6310 
6311 
6312 		/* Extra values */
6313 		vinfo[e].y = y;
6314 		vinfo[e].x = x;
6315 		vinfo[e].d = ((y > x) ? (y + x/2) : (x + y/2));
6316 		vinfo[e].r = ((!y) ? x : (!x) ? y : (y == x) ? y : 0);
6317 	}
6318 
6319 
6320 	/* Verify maximal bits XXX XXX XXX */
6321 	if (((vinfo[1].bits_3 | vinfo[2].bits_3) != VINFO_BITS_3) ||
6322 	    ((vinfo[1].bits_2 | vinfo[2].bits_2) != VINFO_BITS_2) ||
6323 	    ((vinfo[1].bits_1 | vinfo[2].bits_1) != VINFO_BITS_1) ||
6324 	    ((vinfo[1].bits_0 | vinfo[2].bits_0) != VINFO_BITS_0))
6325 	{
6326 		quit("Incorrect bit masks!");
6327 	}
6328 
6329 
6330 	/* Kill hack */
6331 	KILL(hack, vinfo_hack);
6332 
6333 
6334 	/* Success */
6335 	return (0);
6336 }
6337 
6338 
6339 void update_view(int Ind)
6340 {
6341 	player_type *p_ptr = Players[Ind];
6342 
6343 
6344 	int full, over;
6345 	int o, n;
6346 	int y, x;
6347 	u16b info;
6348 
6349 #if 0
6350 	int y_max = p_ptr->cur_hgt - 1;
6351 	int x_max = p_ptr->cur_wid - 1;
6352 #else	/* Inefficient, but prevents south-west dead angle bug.. */
6353 	int y_max = MAX_HGT - 1;
6354 	int x_max = MAX_WID - 1;
6355 #endif	/* 0 */
6356 
6357 	int py = p_ptr->py;
6358 	int px = p_ptr->px;
6359 
6360 
6361 	cave_type *c_ptr;
6362 	byte *w_ptr;
6363 	bool unmap = FALSE;
6364 
6365 	cave_type **zcave;
6366 	struct worldpos *wpos;
6367 	wpos = &p_ptr->wpos;
6368 	if (!(zcave = getcave(wpos))) return;
6369 	if (p_ptr->wpos.wz) {
6370 		dun_level *l_ptr = getfloor(&p_ptr->wpos);
6371 		if (l_ptr && l_ptr->flags1 & LF1_NO_MAP) unmap = TRUE;
6372 	}
6373 
6374 
6375 	/*** Initialize ***/
6376 
6377 #if 0
6378 	/* Optimize */
6379 	if (p_ptr->view_reduce_view && istown(wpos)) /* town */
6380 	{
6381 		/* Full radius (10) */
6382 		full = MAX_SIGHT / 2;
6383 
6384 		/* Octagon factor (15) */
6385 		over = MAX_SIGHT * 3 / 4;
6386 	}
6387 
6388 	/* Normal */
6389 	else
6390 	{
6391 		/* Full radius (20) */
6392 		full = MAX_SIGHT;
6393 
6394 		/* Octagon factor (30) */
6395 		over = MAX_SIGHT * 3 / 2;
6396 	}
6397 #endif	// 0
6398 
6399 	/* It's needed, none..? XXX */
6400 	p_ptr->temp_n = 0;
6401 
6402 	/*** Step 0 -- Begin ***/
6403 
6404 	/* Save the old "view" grids for later */
6405 	for (n = 0; n < p_ptr->view_n; n++)
6406 	{
6407 		y = p_ptr->view_y[n];
6408 		x = p_ptr->view_x[n];
6409 
6410 		/* Access the grid */
6411 		c_ptr = &zcave[y][x];
6412 		w_ptr = &p_ptr->cave_flag[y][x];
6413 
6414 		/* Mark the grid as not in "view" */
6415 		*w_ptr &= ~(CAVE_VIEW);
6416 
6417 		/* Save "CAVE_SEEN" grids */
6418 		if (*w_ptr & (CAVE_XTRA))
6419 		{
6420 			/* Set "CAVE_TEMP" flag */
6421 			info |= (CAVE_TEMP);
6422 
6423 			/* Save grid for later */
6424 			p_ptr->temp_y[p_ptr->temp_n] = y;
6425 			p_ptr->temp_x[p_ptr->temp_n++] = x;
6426 		}
6427 
6428 		/* Mark the grid as "seen" */
6429 		*w_ptr &= ~(CAVE_XTRA);
6430 	}
6431 
6432 	/* Start over with the "view" array */
6433 	p_ptr->view_n = 0;
6434 
6435 
6436 	/*** Step 1 -- adjacent grids ***/
6437 
6438 	/* Now start on the player */
6439 	y = py;
6440 	x = px;
6441 
6442 	/* Access the grid */
6443 	c_ptr = &zcave[y][x];
6444 	w_ptr = &p_ptr->cave_flag[y][x];
6445 
6446 	/* Assume the player grid is easily viewable */
6447 /*	c_ptr->info |= CAVE_XTRA; */
6448 
6449 	/* Assume the player grid is viewable */
6450 	cave_view_hack(w_ptr, y, x);
6451 
6452 	if (c_ptr->info & (CAVE_GLOW | CAVE_LITE))
6453 	{
6454 		/* Mark as "CAVE_SEEN" */
6455 		*w_ptr |= (CAVE_XTRA);
6456 	}
6457 
6458 
6459 	/*** Step 2 -- octants ***/
6460 
6461 	/* Scan each octant */
6462 	for (o = 0; o < 8; o++)
6463 	{
6464 		vinfo_type *p;
6465 
6466 		/* Last added */
6467 		vinfo_type *last = &vinfo[0];
6468 
6469 		/* Grid queue */
6470 		int queue_head = 0;
6471 		int queue_tail = 0;
6472 		vinfo_type *queue[VINFO_MAX_GRIDS*2];
6473 
6474 		/* Slope bit vector */
6475 		u32b bits0 = VINFO_BITS_0;
6476 		u32b bits1 = VINFO_BITS_1;
6477 		u32b bits2 = VINFO_BITS_2;
6478 		u32b bits3 = VINFO_BITS_3;
6479 
6480 		/* Reset queue */
6481 		queue_head = queue_tail = 0;
6482 
6483 		/* Initial grids */
6484 		queue[queue_tail++] = &vinfo[1];
6485 		queue[queue_tail++] = &vinfo[2];
6486 
6487 		/* Process queue */
6488 		while (queue_head < queue_tail)
6489 		{
6490 			/* Dequeue next grid */
6491 			p = queue[queue_head++];
6492 
6493 			/* Check bits */
6494 			if ((bits0 & (p->bits_0)) ||
6495 			    (bits1 & (p->bits_1)) ||
6496 			    (bits2 & (p->bits_2)) ||
6497 			    (bits3 & (p->bits_3)))
6498 			{
6499 				/* Extract coordinate value */
6500 				y = py + p->grid_y[o];
6501 				x = px + p->grid_x[o];
6502 
6503 				/* Access the grid */
6504 				c_ptr = &zcave[y][x];
6505 				w_ptr = &p_ptr->cave_flag[y][x];
6506 
6507 				/* Get grid info */
6508 				info = c_ptr->info;
6509 
6510 				/* Handle wall */
6511 /*				if (info & (CAVE_WALL)) */
6512 				if (!cave_los_grid(c_ptr))
6513 				{
6514 					/* Clear bits */
6515 					bits0 &= ~(p->bits_0);
6516 					bits1 &= ~(p->bits_1);
6517 					bits2 &= ~(p->bits_2);
6518 					bits3 &= ~(p->bits_3);
6519 
6520 					/* Newly viewable wall */
6521 					if (!(*w_ptr & (CAVE_VIEW)))
6522 					{
6523 						/* Mark as viewable */
6524 						/* *w_ptr |= (CAVE_VIEW); */
6525 
6526 #if 0	/* cannot handle other players' lite.. */
6527 						/* Torch-lit grids */
6528 						if (p->d < radius)
6529 						{
6530 							/* Mark as "CAVE_SEEN" and torch-lit */
6531 							info |= (CAVE_SEEN | CAVE_PLIT);
6532 						}
6533 
6534 						/* Monster-lit grids */
6535 						else if (info & (CAVE_MLIT))
6536 						{
6537 							/* Mark as "CAVE_SEEN" */
6538 							info |= (CAVE_SEEN);
6539 						}
6540 						else
6541 #endif	/* 0 */
6542 
6543 						/* Perma-lit grids */
6544 						if (info & (CAVE_GLOW | CAVE_LITE))
6545 						{
6546 							/* Hack -- move towards player */
6547 							int yy = (y < py) ? (y + 1) : (y > py) ? (y - 1) : y;
6548 							int xx = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
6549 
6550 #ifdef UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION
6551 							/* seemingly it's not used in ToME too */
6552 
6553 							/* Check for "complex" illumination */
6554 							if ((!(cave[yy][xx].info & (CAVE_WALL)) &&
6555 							      (cave[yy][xx].info & (CAVE_GLOW))) ||
6556 							    (!(cave[y][xx].info & (CAVE_WALL)) &&
6557 							      (cave[y][xx].info & (CAVE_GLOW))) ||
6558 							    (!(cave[yy][x].info & (CAVE_WALL)) &&
6559 							      (cave[yy][x].info & (CAVE_GLOW))))
6560 							{
6561 								/* Mark as seen */
6562 								info |= (CAVE_SEEN);
6563 							}
6564 
6565 #else /* UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION */
6566 
6567 							/* Check for "simple" illumination */
6568 							if (zcave[yy][xx].info & (CAVE_GLOW))
6569 							{
6570 								/* Mark as seen */
6571 								*w_ptr |= (CAVE_XTRA);
6572 							}
6573 
6574 #endif /* UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION */
6575 
6576 						}
6577 
6578 						/* Save cave info */
6579 						/* c_ptr->info = info; */
6580 
6581 						/* Save in array */
6582 						cave_view_hack(w_ptr, y, x);
6583 					}
6584 				}
6585 
6586 				/* Handle non-wall */
6587 				else
6588 				{
6589 					/* Enqueue child */
6590 					if (last != p->next_0)
6591 					{
6592 						queue[queue_tail++] = last = p->next_0;
6593 					}
6594 
6595 					/* Enqueue child */
6596 					if (last != p->next_1)
6597 					{
6598 						queue[queue_tail++] = last = p->next_1;
6599 					}
6600 
6601 					/* Newly viewable non-wall */
6602 					if (!(*w_ptr & (CAVE_VIEW)))
6603 					{
6604 						/* Mark as "viewable" */
6605 						/* *w_ptr |= (CAVE_VIEW); */
6606 
6607 #if 0
6608 
6609 						/* Torch-lit grids */
6610 						if (p->d < radius)
6611 						{
6612 							/* Mark as "CAVE_SEEN" and torch-lit */
6613 							info |= (CAVE_SEEN | CAVE_PLIT);
6614 						}
6615 
6616 						/* Perma-lit or monster-lit grids */
6617 						else if (info & (CAVE_GLOW | CAVE_MLIT))
6618 						{
6619 							/* Mark as "CAVE_SEEN" */
6620 							info |= (CAVE_SEEN);
6621 						}
6622 #endif	/* 0 */
6623 
6624 						if (info & (CAVE_GLOW | CAVE_LITE))
6625 						{
6626 							/* Mark as "CAVE_SEEN" */
6627 							*w_ptr |= (CAVE_XTRA);
6628 						}
6629 
6630 						/* Save cave info */
6631 						/* c_ptr->info = info; */
6632 
6633 						/* Save in array */
6634 						cave_view_hack(w_ptr, y, x);
6635 					}
6636 				}
6637 			}
6638 		}
6639 	}
6640 
6641 
6642 
6643 	/*** Step 3 -- Complete the algorithm ***/
6644 
6645 #if 0	/* not here (?) */
6646 	/* Handle blindness */
6647 	if (p_ptr->blind)
6648 	{
6649 		/* Process "new" grids */
6650 		for (i = 0; i < fast_view_n; i++)
6651 		{
6652 			/* Location */
6653 			y = view_y[i];
6654 			x = view_x[i];
6655 
6656 			/* Grid cannot be "CAVE_SEEN" */
6657 			cave[y][x].info &= ~(CAVE_SEEN);
6658 		}
6659 	}
6660 #endif	/* 0 */
6661 
6662 	/* Update all the new grids */
6663 	for (n = 0; n < p_ptr->view_n; n++)
6664 	{
6665 		y = p_ptr->view_y[n];
6666 		x = p_ptr->view_x[n];
6667 
6668 		/* Access the grid */
6669 		c_ptr = &zcave[y][x];
6670 		w_ptr = &p_ptr->cave_flag[y][x];
6671 
6672 #if 0
6673 		/* Clear the "CAVE_XTRA" flag */
6674 		c_ptr->info &= ~CAVE_XTRA;
6675 
6676 		/* Update only newly viewed grids */
6677 		if (c_ptr->info & CAVE_TEMP) continue;
6678 #endif	/* 0 */
6679 
6680 		if (!((*w_ptr & (CAVE_XTRA)) && !(c_ptr->info & (CAVE_TEMP)))) continue;
6681 
6682 		/* Note */
6683 		note_spot(Ind, y, x);
6684 
6685 		/* Redraw */
6686 		lite_spot(Ind, y, x);
6687 	}
6688 
6689 	/* Wipe the old grids, update as needed */
6690 	for (n = 0; n < p_ptr->temp_n; n++)
6691 	{
6692 		y = p_ptr->temp_y[n];
6693 		x = p_ptr->temp_x[n];
6694 
6695 		/* Access the grid */
6696 		c_ptr = &zcave[y][x];
6697 		w_ptr = &p_ptr->cave_flag[y][x];
6698 
6699 		/* No longer in the array */
6700 		c_ptr->info &= ~CAVE_TEMP;
6701 
6702 		/* Update only non-viewable grids */
6703 //		if (*w_ptr & CAVE_VIEW) continue;
6704 		if ((*w_ptr & (CAVE_XTRA))) continue;
6705 
6706 		/* Forget it, dude */
6707 		if (unmap)
6708 		{
6709 			u16b this_o_idx, next_o_idx = 0;
6710 
6711 			*w_ptr &= ~CAVE_MARK;
6712 
6713 			/* make player forget of objects too */
6714 			/* too bad, traps cannot be forgotten this way.. */
6715 			for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
6716 			{
6717 				/* Acquire next object */
6718 				next_o_idx = o_list[this_o_idx].next_o_idx;
6719 
6720 				/* Forget the object */
6721 				p_ptr->obj_vis[this_o_idx] = FALSE;
6722 			}
6723 		}
6724 
6725 		/* Redraw */
6726 		lite_spot(Ind, y, x);
6727 	}
6728 
6729 	/* None left */
6730 	p_ptr->temp_n = 0;
6731 }
6732 #endif	/* USE_OLD_UPDATE_VIEW */
6733 
6734 
6735 
6736 
6737 
6738 
6739 /*
6740  * Hack -- provide some "speed" for the "flow" code
6741  * This entry is the "current index" for the "when" field
6742  * Note that a "when" value of "zero" means "not used".
6743  *
6744  * Note that the "cost" indexes from 1 to 127 are for
6745  * "old" data, and from 128 to 255 are for "new" data.
6746  *
6747  * This means that as long as the player does not "teleport",
6748  * then any monster up to 128 + MONSTER_FLOW_DEPTH will be
6749  * able to track down the player, and in general, will be
6750  * able to track down either the player or a position recently
6751  * occupied by the player.
6752  */
6753 /*static int flow_n = 0;*/
6754 
6755 
6756 /*
6757  * Hack -- forget the "flow" information
6758  */
6759 void forget_flow(void)
6760 {
6761 
6762 #ifdef MONSTER_FLOW
6763 
6764 	int x, y;
6765 
6766 	/* Nothing to forget */
6767 	if (!flow_n) return;
6768 
6769 	/* Check the entire dungeon */
6770 	for (y = 0; y < cur_hgt; y++)
6771 	{
6772 		for (x = 0; x < cur_wid; x++)
6773 		{
6774 			/* Forget the old data */
6775 			cave[y][x].cost = 0;
6776 			cave[y][x].when = 0;
6777 		}
6778 	}
6779 
6780 	/* Start over */
6781 	flow_n = 0;
6782 
6783 #endif
6784 
6785 }
6786 
6787 
6788 #ifdef MONSTER_FLOW
6789 
6790 /*
6791  * Hack -- Allow us to treat the "seen" array as a queue
6792  */
6793 static int flow_head = 0;
6794 static int flow_tail = 0;
6795 
6796 
6797 /*
6798  * Take note of a reachable grid.  Assume grid is legal.
6799  */
6800 static void update_flow_aux(int y, int x, int n)
6801 {
6802 	cave_type *c_ptr;
6803 
6804 	int old_head = flow_head;
6805 
6806 
6807 	/* Get the grid */
6808 	c_ptr = &cave[y][x];
6809 
6810 	/* Ignore "pre-stamped" entries */
6811 	if (c_ptr->when == flow_n) return;
6812 
6813 	/* Ignore "walls" and "rubble" */
6814 	if (c_ptr->feat >= FEAT_RUBBLE) return;
6815 
6816 	/* Save the time-stamp */
6817 	c_ptr->when = flow_n;
6818 
6819 	/* Save the flow cost */
6820 	c_ptr->cost = n;
6821 
6822 	/* Hack -- limit flow depth */
6823 	if (n == MONSTER_FLOW_DEPTH) return;
6824 
6825 	/* Enqueue that entry */
6826 	temp_y[flow_head] = y;
6827 	temp_x[flow_head] = x;
6828 
6829 	/* Advance the queue */
6830 	if (++flow_head == TEMP_MAX) flow_head = 0;
6831 
6832 	/* Hack -- notice overflow by forgetting new entry */
6833 	if (flow_head == flow_tail) flow_head = old_head;
6834 }
6835 
6836 #endif
6837 
6838 
6839 /*
6840  * Hack -- fill in the "cost" field of every grid that the player
6841  * can "reach" with the number of steps needed to reach that grid.
6842  * This also yields the "distance" of the player from every grid.
6843  *
6844  * In addition, mark the "when" of the grids that can reach
6845  * the player with the incremented value of "flow_n".
6846  *
6847  * Hack -- use the "seen" array as a "circular queue".
6848  *
6849  * We do not need a priority queue because the cost from grid
6850  * to grid is always "one" and we process them in order.
6851  */
6852 void update_flow(void)
6853 {
6854 
6855 #ifdef MONSTER_FLOW
6856 
6857 	int x, y, d;
6858 
6859 	/* Hack -- disabled */
6860 	if (!flow_by_sound && !flow_by_smell) return;
6861 
6862 	/* Paranoia -- make sure the array is empty */
6863 	if (temp_n) return;
6864 
6865 	/* Cycle the old entries (once per 128 updates) */
6866 	if (flow_n == 255)
6867 	{
6868 		/* Rotate the time-stamps */
6869 		for (y = 0; y < cur_hgt; y++)
6870 		{
6871 			for (x = 0; x < cur_wid; x++)
6872 			{
6873 				int w = cave[y][x].when;
6874 				cave[y][x].when = (w > 128) ? (w - 128) : 0;
6875 			}
6876 		}
6877 
6878 		/* Restart */
6879 		flow_n = 127;
6880 	}
6881 
6882 	/* Start a new flow (never use "zero") */
6883 	flow_n++;
6884 
6885 
6886 	/* Reset the "queue" */
6887 	flow_head = flow_tail = 0;
6888 
6889 	/* Add the player's grid to the queue */
6890 	update_flow_aux(py, px, 0);
6891 
6892 	/* Now process the queue */
6893 	while (flow_head != flow_tail)
6894 	{
6895 		/* Extract the next entry */
6896 		y = temp_y[flow_tail];
6897 		x = temp_x[flow_tail];
6898 
6899 		/* Forget that entry */
6900 		if (++flow_tail == TEMP_MAX) flow_tail = 0;
6901 
6902 		/* Add the "children" */
6903 		for (d = 0; d < 8; d++)
6904 		{
6905 			/* Add that child if "legal" */
6906 			update_flow_aux(y+ddy_ddd[d], x+ddx_ddd[d], cave[y][x].cost+1);
6907 		}
6908 	}
6909 
6910 	/* Forget the flow info */
6911 	flow_head = flow_tail = 0;
6912 
6913 #endif
6914 
6915 }
6916 
6917 
6918 
6919 
6920 
6921 
6922 
6923 /*
6924  * Hack -- map the current panel (plus some) ala "magic mapping"
6925  */
6926 void map_area(int Ind) {
6927 	player_type *p_ptr = Players[Ind];
6928 	int             i, x, y, y1, y2, x1, x2;
6929 
6930 	cave_type       *c_ptr;
6931 	byte            *w_ptr;
6932 
6933 /*	dungeon_type	*d_ptr = getdungeon(&p_ptr->wpos); */
6934 	dun_level		*l_ptr = getfloor(&p_ptr->wpos);
6935 	worldpos *wpos = &p_ptr->wpos;
6936 	cave_type **zcave;
6937 
6938 	/* anti-exploit */
6939 	if (!local_panel(Ind)) return;
6940 
6941 	if (!(zcave = getcave(wpos))) return;
6942 /*	if (d_ptr && d_ptr->flags & DUNGEON_NO_MAP) return; */
6943 	if (l_ptr && (l_ptr->flags1 & LF1_NO_MAGIC_MAP)) return;
6944 	if (in_sector00(wpos) && (sector00flags1 & LF1_NO_MAGIC_MAP)) return;
6945 
6946 	/* Pick an area to map */
6947 	y1 = TRADPANEL_ROW_MIN - randint(10);
6948 	y2 = TRADPANEL_ROW_MAX + randint(10);
6949 	x1 = TRADPANEL_COL_MIN - randint(20);
6950 	x2 = TRADPANEL_COL_MAX + randint(20);
6951 
6952 	/* Speed -- shrink to fit legal bounds */
6953 	if (y1 < 1) y1 = 1;
6954 	if (y2 > p_ptr->cur_hgt-2) y2 = p_ptr->cur_hgt-2;
6955 	if (x1 < 1) x1 = 1;
6956 	if (x2 > p_ptr->cur_wid-2) x2 = p_ptr->cur_wid-2;
6957 
6958 	/* Scan that area */
6959 	for (y = y1; y <= y2; y++) {
6960 		for (x = x1; x <= x2; x++) {
6961 			c_ptr = &zcave[y][x];
6962 			w_ptr = &p_ptr->cave_flag[y][x];
6963 
6964 			/* All non-walls are "checked" */
6965 //			if (c_ptr->feat < FEAT_SECRET)
6966 			if (!is_wall(c_ptr)) {
6967 				/* Memorize normal features */
6968 //				if (c_ptr->feat > FEAT_INVIS)
6969 				if (!cave_plain_floor_grid(c_ptr)) {
6970 					/* Memorize the object */
6971 					*w_ptr |= CAVE_MARK;
6972 				}
6973 
6974 				/* Memorize known walls */
6975 				for (i = 0; i < 8; i++) {
6976 					c_ptr = &zcave[y + ddy_ddd[i]][x + ddx_ddd[i]];
6977 					w_ptr = &p_ptr->cave_flag[y + ddy_ddd[i]][x + ddx_ddd[i]];
6978 
6979 					/* Memorize walls (etc) */
6980 //					if (c_ptr->feat >= FEAT_SECRET)
6981 					if (is_wall(c_ptr)) {
6982 						/* Memorize the walls */
6983 						*w_ptr |= CAVE_MARK;
6984 					}
6985 				}
6986 			}
6987 		}
6988 	}
6989 
6990 	/* Redraw map */
6991 	p_ptr->redraw |= (PR_MAP);
6992 
6993 	/* Window stuff */
6994 	p_ptr->window |= (PW_OVERHEAD);
6995 }
6996 
6997 /* Mindcrafter's magic mapping spell - C. Blue */
6998 /* This spell's behaviour:
6999    easy, old: like magic mapping, combined with short-time esp
7000    good, new: like magic mapping, without any esp */
7001 #define MML_NEW
7002 void mind_map_level(int Ind, int pow) {
7003 	player_type *p_ptr = Players[Ind];
7004 	int m, y, x, rad;
7005 	int i, j, plist[MAX_PLAYERS + 1], plist_size = 1;
7006 
7007 	monster_race	*r_ptr;
7008 	monster_type	*m_ptr;
7009 	cave_type       *c_ptr;
7010 
7011 	dun_level	*l_ptr = getfloor(&p_ptr->wpos);
7012 	struct worldpos *wpos = &p_ptr->wpos;
7013 	cave_type **zcave;
7014 	if (!(zcave = getcave(wpos))) return;
7015 
7016 	/* for mindcrafters too (NR requires) */
7017 	if (l_ptr && l_ptr->flags1 & LF1_NO_MAGIC_MAP) return;
7018 	if (in_sector00(wpos) && (sector00flags1 & LF1_NO_MAGIC_MAP)) return;
7019 
7020 	/* build list of players to share the vision with */
7021 	/* oneself too */
7022 	plist[0] = Ind;
7023 	for (i = 1; i <= NumPlayers; i++) {
7024 		/* Skip self */
7025 		if (i == Ind) continue;
7026 		/* Skip disconnected players */
7027 		if (Players[i]->conn == NOT_CONNECTED) continue;
7028 		/* Skip DM if not DM himself */
7029 		if (Players[i]->admin_dm && !p_ptr->admin_dm) continue;
7030 		/* Skip Ghosts */
7031 		if (Players[i]->ghost && !Players[i]->admin_dm) continue;
7032 		/* Skip players not on this depth */
7033 		if (!inarea(&Players[i]->wpos, &p_ptr->wpos)) continue;
7034 		/* Skip players not in the same party */
7035 		if (Players[i]->party == 0 || p_ptr->party != Players[i]->party) continue;
7036 		/* Skip players who haven't opened their mind */
7037 		if (!(Players[i]->esp_link_flags & LINKF_OPEN)) continue;
7038 
7039 		/* add him */
7040 		plist[plist_size++] = i;
7041 	}
7042 
7043 	/* Is grid in LOS of a monster with a mind? */
7044 	for (m = m_top - 1; m >= 0; m--) {
7045 		/* Access the monster */
7046 		m_ptr = &m_list[m_fast[m]];
7047 		r_ptr = race_inf(m_ptr);
7048 
7049 		if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
7050 
7051 		/* sleeping */
7052 //hypnosis yay		if (m_ptr->csleep) continue;
7053 
7054 		/* no mind */
7055 		if ((r_ptr->flags9 & RF9_IM_PSI) ||
7056 		    (r_ptr->flags2 & RF2_EMPTY_MIND) ||
7057 		    (r_ptr->flags3 & RF3_NONLIVING))
7058 			continue;
7059 
7060 		/* 'clouded' */
7061 		if ((r_ptr->flags9 & RF9_RES_PSI) ||
7062 		    (r_ptr->flags2 & RF2_WEIRD_MIND) ||
7063 		    (r_ptr->flags3 & RF3_UNDEAD))
7064 			rad = (pow + 1) / 2;
7065 		else	rad = pow;
7066 
7067 		/* test nearby grids */
7068 		for (y = m_ptr->fy - rad; y < m_ptr->fy + rad; y++)
7069 		for (x = m_ptr->fx - rad; x < m_ptr->fx + rad; x++) {
7070 
7071 			if (!in_bounds(y, x)) continue;
7072 
7073 			if (distance(y, x, m_ptr->fy, m_ptr->fx) > rad ||
7074 			    distance(y, x, m_ptr->fy, m_ptr->fx) > r_ptr->aaf ||
7075 			    !los(wpos, y, x, m_ptr->fy, m_ptr->fx))
7076 				continue;
7077 
7078 			/* Access the grid */
7079 			c_ptr = &zcave[y][x];
7080 
7081 			/* Memorize all objects */
7082 			if (c_ptr->o_idx) {
7083 				for (i = 0; i < plist_size; i++) {
7084 					Players[plist[i]]->obj_vis[c_ptr->o_idx]= TRUE;
7085 				}
7086 			}
7087 
7088 #if 0 /* like wiz-lite? */
7089  #if 1 /* should be enabled too if CAVE_MARK below is enabled.. */
7090 			/* perma-lite grid? */
7091 			c_ptr->info |= (CAVE_GLOW);
7092  #endif
7093  #if 1
7094 			/* Process all non-walls */
7095 			//if (c_ptr->feat < FEAT_SECRET)
7096 			{
7097 				/* Memorize normal features */
7098 //				if (c_ptr->feat > FEAT_INVIS)
7099 				if (!cave_plain_floor_grid(c_ptr)) {
7100 					for (i = 0; i < plist_size; i++) {
7101 						/* Memorize the grid */
7102 						Players[plist[i]]->cave_flag[y][x] |= CAVE_MARK;
7103 					}
7104 				}
7105 
7106 				/* Normally, memorize floors (see above) */
7107 				else if (p_ptr->view_perma_grids && !p_ptr->view_torch_grids) {
7108 					for (i = 0; i < plist_size; i++) {
7109 						/* Memorize the grid */
7110 						Players[plist[i]]->cave_flag[y][x] |= CAVE_MARK;
7111 					}
7112 				}
7113 			}
7114  #endif
7115 #else /* like magic mapping? */
7116 			/* All non-walls are "checked" */
7117 //			if (c_ptr->feat < FEAT_SECRET)
7118 			if (!is_wall(c_ptr)) {
7119 				/* Memorize normal features */
7120 //				if (c_ptr->feat > FEAT_INVIS) {
7121 				if (!cave_plain_floor_grid(c_ptr)) {
7122 					for (i = 0; i < plist_size; i++) {
7123 						/* Memorize the feature */
7124 						Players[plist[i]]->cave_flag[y][x] |= CAVE_MARK;
7125  #ifdef MML_NEW
7126 						lite_spot(plist[i], y, x);
7127  #endif
7128 					}
7129 				}
7130 
7131 				/* Memorize known walls */
7132 				for (j = 0; j < 8; j++) {
7133 					if (!in_bounds(y + ddy_ddd[j], x + ddx_ddd[j])) continue;
7134 
7135 					/* Memorize walls (etc) */
7136 //					if (c_ptr->feat >= FEAT_SECRET)
7137 					if (is_wall(&zcave[y + ddy_ddd[j]][x + ddx_ddd[j]])) {
7138 						for (i = 0; i < plist_size; i++) {
7139 							/* Memorize the walls */
7140 							Players[plist[i]]->cave_flag[y + ddy_ddd[j]][x + ddx_ddd[j]] |= CAVE_MARK;
7141  #ifdef MML_NEW
7142 							lite_spot(plist[i], y + ddy_ddd[j], x + ddx_ddd[j]);
7143  #endif
7144 						}
7145 					}
7146 				}
7147 			}
7148 #endif
7149 		}
7150 
7151 #if 0 /* this will be overheady, since it requires prt_map() here as a bad \
7152          hack, and PR_MAP/PU_MONSTERS commented out in for-loop below. \
7153          See same for-loop for clean solution as good alternative! */
7154 		prt_map(plist[i]); /* bad hack */
7155 		/* like detect_creatures(), not excluding invisible monsters though */
7156 		for (i = 0; i < plist_size; i++) {
7157 			if (Players[plist[i]]->mon_vis[m_fast[m]]) continue;
7158 			Players[plist[i]]->mon_vis[m_fast[m]] = TRUE;
7159 			lite_spot(plist[i], m_ptr->fy, m_ptr->fx);
7160 			Players[plist[i]]->mon_vis[m_fast[m]] = FALSE; /* the usual hack: don't update screen after this */
7161 		}
7162 #elif defined(MML_NEW) /* new attempt */
7163 		/* like detect_creatures(), not excluding invisible monsters though */
7164 		for (i = 0; i < plist_size; i++) {
7165 			if (Players[plist[i]]->mon_vis[m_fast[m]]) continue;
7166 			Players[plist[i]]->mon_vis[m_fast[m]] = TRUE;
7167 			lite_spot(plist[i], m_ptr->fy, m_ptr->fx);
7168 			Players[plist[i]]->mon_vis[m_fast[m]] = FALSE; /* the usual hack: don't update screen after this */
7169 		}
7170 #endif
7171 	}
7172 
7173 	/* Specialty: Detect all dungeon stores! */
7174 	//TODO: Store the 1 or maybe 2 stores in the l_ptr array instead -_-' */
7175 	for (y = 0; y < MAX_HGT; y++)
7176 		for (x = 0; x < MAX_WID; x++) {
7177 			if (zcave[y][x].feat != FEAT_SHOP) continue;
7178 			for (i = 0; i < plist_size; i++) {
7179 				Players[plist[i]]->cave_flag[y][x] |= CAVE_MARK;
7180 				lite_spot(plist[i], y, x);
7181 			}
7182 		}
7183 
7184 #ifndef MML_NEW
7185 	for (i = 0; i < plist_size; i++) {
7186  #if 1
7187 		/* clean solution instead: give some temporary ESP (makes sense also).
7188 		 Note however: this is thereby becoming an auto-projectable ESP spell^^ */
7189 		set_tim_esp(plist[i], 10);
7190  #endif
7191 
7192 		/* Update the monsters */
7193 		Players[plist[i]]->update |= (PU_MONSTERS);
7194 		/* Redraw map */
7195 		Players[plist[i]]->redraw |= (PR_MAP);
7196 		/* Window stuff */
7197 		Players[plist[i]]->window |= (PW_OVERHEAD);
7198 	}
7199 #endif
7200 }
7201 
7202 /*
7203  * Light up the dungeon using "claravoyance"
7204  *
7205  * This function "illuminates" every grid in the dungeon, memorizes all
7206  * "objects", memorizes all grids as with magic mapping, and, under the
7207  * standard option settings (view_perma_grids but not view_torch_grids)
7208  * memorizes all floor grids too.
7209  *
7210  * Note that if "view_perma_grids" is not set, we do not memorize floor
7211  * grids, since this would defeat the purpose of "view_perma_grids", not
7212  * that anyone seems to play without this option.
7213  *
7214  * Note that if "view_torch_grids" is set, we do not memorize floor grids,
7215  * since this would prevent the use of "view_torch_grids" as a method to
7216  * keep track of what grids have been observed directly.
7217  */
7218 void wiz_lite(int Ind) {
7219 	player_type *p_ptr = Players[Ind];
7220 	int             y, x, i;
7221 
7222 	cave_type       *c_ptr;
7223 	byte            *w_ptr;
7224 
7225 /*	dungeon_type	*d_ptr = getdungeon(&p_ptr->wpos); */
7226 	dun_level *l_ptr = getfloor(&p_ptr->wpos);
7227 	struct worldpos *wpos = &p_ptr->wpos;
7228 	cave_type **zcave;
7229 
7230 	/* don't ruin the mood ^^ */
7231 	bool mood = (wpos->wz == 0 && (season_halloween || season_newyearseve));
7232 
7233 	if (!(zcave = getcave(wpos))) return;
7234 
7235 /*	if (d_ptr && d_ptr->flags & DUNGEON_NO_MAP) return; */
7236 	if (l_ptr && l_ptr->flags1 & LF1_NO_MAGIC_MAP) return;
7237 	if (in_sector00(wpos) && (sector00flags1 & LF1_NO_MAGIC_MAP)) return;
7238 
7239 	/* Scan all normal grids */
7240 	for (y = 1; y < p_ptr->cur_hgt-1; y++) {
7241 		/* Scan all normal grids */
7242 		for (x = 1; x < p_ptr->cur_wid-1; x++) {
7243 			/* Access the grid */
7244 			c_ptr = &zcave[y][x];
7245 			if (mood && !(c_ptr->info & CAVE_ICKY)) continue;
7246 			w_ptr = &p_ptr->cave_flag[y][x];
7247 
7248 			/* Memorize all objects */
7249 			if (c_ptr->o_idx) {
7250 				/* Memorize */
7251 				p_ptr->obj_vis[c_ptr->o_idx]= TRUE;
7252 			}
7253 
7254 			/* Process all non-walls */
7255 			//if (c_ptr->feat < FEAT_SECRET) <- deprecated; use next line if you want "clean" wizlite ;) - C. Blue
7256 //			if (!(f_info[c_ptr->feat].flags1 & FF1_WALL))
7257 			{
7258 				/* Scan all neighbors */
7259 				for (i = 0; i < 9; i++) {
7260 					int yy = y + ddy_ddd[i];
7261 					int xx = x + ddx_ddd[i];
7262 
7263 					/* Get the grid */
7264 					c_ptr = &zcave[yy][xx];
7265 					if (mood && !(c_ptr->info & CAVE_ICKY)) continue; //if this were commented out, house walls would be *bright*
7266 					w_ptr = &p_ptr->cave_flag[yy][xx];
7267 
7268 					/* Perma-lite the grid */
7269 					c_ptr->info |= (CAVE_GLOW);
7270 
7271 					/* Memorize normal features */
7272 //					if (c_ptr->feat > FEAT_INVIS)
7273 					if (!cave_plain_floor_grid(c_ptr)) {
7274 						/* Memorize the grid */
7275 						*w_ptr |= CAVE_MARK;
7276 					}
7277 
7278 					/* Normally, memorize floors (see above) */
7279 					if (p_ptr->view_perma_grids && !p_ptr->view_torch_grids) {
7280 						/* Memorize the grid */
7281 						*w_ptr |= CAVE_MARK;
7282 					}
7283 				}
7284 			}
7285 		}
7286 	}
7287 
7288 	/* Update the monsters */
7289 	p_ptr->update |= (PU_MONSTERS);
7290 
7291 	/* Redraw map */
7292 	p_ptr->redraw |= (PR_MAP);
7293 
7294 	/* Window stuff */
7295 	p_ptr->window |= (PW_OVERHEAD);
7296 
7297 }
7298 
7299 
7300 /* from PernA	- Jir - */
7301 void wiz_lite_extra(int Ind)
7302 {
7303 	player_type *p_ptr = Players[Ind];
7304 	int y, x;
7305 	struct worldpos *wpos = &p_ptr->wpos;
7306 //	dun_level *l_ptr = getfloor(wpos);
7307 	cave_type **zcave;
7308 	cave_type *c_ptr;
7309 
7310 	/* don't ruin the mood ^^ */
7311 	bool mood = (wpos->wz == 0 && (season_halloween || season_newyearseve));
7312 
7313 	if (!(zcave = getcave(wpos))) return;
7314 
7315 /*	if (d_ptr && d_ptr->flags & DUNGEON_NO_MAP) return; */
7316 
7317 	for (y = 0; y < p_ptr->cur_hgt; y++) {
7318 		for (x = 0; x < p_ptr->cur_wid; x++) {
7319 			c_ptr = &zcave[y][x];
7320 			if (mood && !(c_ptr->info & CAVE_ICKY)) continue;
7321 			/* ligten up all grids and remember features */
7322 //			c_ptr->info |= (CAVE_GLOW | CAVE_MARK);
7323 			/* lighten up all grids */
7324 			c_ptr->info |= CAVE_GLOW;
7325 		}
7326 	}
7327 
7328 
7329 	/* remember features too? */
7330 //	if (!(l_ptr && l_ptr->flags1 & LF1_NO_MAGIC_MAP))
7331 	wiz_lite(Ind);
7332 
7333 
7334 	for (x = 1; x <= NumPlayers; x++) {
7335 		p_ptr = Players[x];
7336 
7337 		/* Only works for players on the level */
7338 		if (!inarea(wpos, &p_ptr->wpos)) continue;
7339 
7340 		/* Update some things */
7341 		p_ptr->update |= (PU_VIEW | PU_DISTANCE);
7342 		p_ptr->redraw |= PR_MAP;
7343 		p_ptr->window |= PW_OVERHEAD;
7344 	}
7345 
7346 }
7347 
7348 /*
7349  * Forget the dungeon map (ala "Thinking of Maud...").
7350  */
7351 void wiz_dark(int Ind) {
7352 	player_type *p_ptr, *q_ptr = Players[Ind];
7353 	struct worldpos *wpos;
7354 	cave_type **zcave;
7355 	cave_type *c_ptr;
7356 	int y, x, i;
7357 	object_type *o_ptr;
7358 
7359 	wpos = &q_ptr->wpos;
7360 	if (!(zcave = getcave(wpos))) return;
7361 
7362 	/* Check for every other player */
7363 
7364 	for (i = 1; i <= NumPlayers; i++) {
7365 		p_ptr = Players[i];
7366 
7367 		/* Only works for players on the level */
7368 		if (!inarea(wpos, &p_ptr->wpos)) continue;
7369 
7370 		o_ptr = &p_ptr->inventory[INVEN_LITE];
7371 
7372 		/* Bye bye light */
7373 		if (o_ptr->k_idx &&
7374 		    ((o_ptr->sval == SV_LITE_TORCH) || (o_ptr->sval == SV_LITE_LANTERN))
7375 		    && (!o_ptr->name1) && o_ptr->timeout) {
7376 			bool refilled = FALSE;
7377 
7378 			disturb(Ind, 0, 0);
7379 
7380 			/* If flint is ready, refill at once */
7381 			if (TOOL_EQUIPPED(p_ptr) == SV_TOOL_FLINT &&
7382 			    !p_ptr->paralyzed) {
7383 				msg_print(Ind, "You prepare a flint...");
7384 				refilled = do_auto_refill(Ind);
7385 				if (!refilled) msg_print(Ind, "Oops, you're out of fuel!");
7386 			}
7387 
7388 			if (!refilled) {
7389 				msg_print(i, "Your light suddenly empties.");
7390 
7391 				/* No more light, it's Rogues day today :) */
7392 				o_ptr->timeout = 0;
7393 			}
7394 		}
7395 
7396 		/* Forget every grid */
7397 		for (y = 0; y < p_ptr->cur_hgt; y++) {
7398 			for (x = 0; x < p_ptr->cur_wid; x++) {
7399 				byte *w_ptr = &p_ptr->cave_flag[y][x];
7400 				c_ptr = &zcave[y][x];
7401 
7402 				/* Process the grid */
7403 				*w_ptr &= ~CAVE_MARK;
7404 				c_ptr->info &= ~CAVE_GLOW;
7405 
7406 				/* Forget every object */
7407 				if (c_ptr->o_idx)
7408 				{
7409 					/* Forget the object */
7410 					p_ptr->obj_vis[c_ptr->o_idx] = FALSE;
7411 				}
7412 			}
7413 		}
7414 
7415 		/* Mega-Hack -- Forget the view and lite */
7416 		p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
7417 
7418 		/* Update the view and lite */
7419 		p_ptr->update |= (PU_VIEW | PU_LITE);
7420 
7421 		/* Update the monsters */
7422 		p_ptr->update |= (PU_MONSTERS);
7423 
7424 		/* Redraw map */
7425 		p_ptr->redraw |= (PR_MAP);
7426 
7427 		/* Window stuff */
7428 		p_ptr->window |= (PW_OVERHEAD);
7429 	}
7430 }
7431 
7432 #ifdef ARCADE_SERVER
7433 extern int check_feat(worldpos *wpos, int y, int x)
7434 {
7435         cave_type **zcave;
7436         cave_type *c_ptr;
7437 
7438         if (!(zcave = getcave(wpos))) return(0);
7439 
7440         if (!in_bounds(y, x)) return(0);
7441 
7442         c_ptr = &zcave[y][x];
7443 	return(c_ptr->feat);
7444 }
7445 #endif
7446 
7447 /*
7448  * Change the "feat" flag for a grid, and notice/redraw the grid
7449  * (Adapted from PernAngband)
7450  */
7451 bool level_generation_time = FALSE;
7452 void cave_set_feat(worldpos *wpos, int y, int x, int feat)
7453 {
7454 	player_type *p_ptr;
7455 	cave_type **zcave;
7456 	cave_type *c_ptr;
7457 //	struct c_special *cs_ptr;
7458 	int i;
7459 
7460 	if (!(zcave = getcave(wpos))) return;
7461 	if (!in_bounds(y, x)) return;
7462 	c_ptr = &zcave[y][x];
7463 
7464 	/* Trees in greater fire become dead trees at once */
7465 	if ((feat == FEAT_TREE || feat == FEAT_BUSH) &&
7466 	    (c_ptr->feat == FEAT_SHAL_LAVA ||
7467 	    c_ptr->feat == FEAT_FIRE ||
7468 	    c_ptr->feat == FEAT_GREAT_FIRE))
7469 		feat = FEAT_DEAD_TREE;
7470 
7471 	/* Don't mess with inns please! */
7472 	if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) return;
7473 
7474 	/* in Nether Realm, floor is always nether mist (or lava)! */
7475 	if (in_netherrealm(wpos)) switch (feat) {
7476 		case FEAT_IVY:
7477 		case FEAT_SHAL_WATER:
7478 		case FEAT_DEEP_WATER:
7479     		case FEAT_ICE:
7480 	    	case FEAT_FLOOR:
7481     		case FEAT_DIRT:
7482 	        case FEAT_GRASS:
7483     		case FEAT_SAND:
7484 	        case FEAT_ASH:
7485 	        case FEAT_MUD:
7486 	/*	case FEAT_PUDDLE: new feature to be added: same as shallow water, but dries out after a while */
7487 	        case FEAT_FLOWER: feat = FEAT_NETHER_MIST;
7488 	}
7489 	/* todo: submerged ruins/small water cave only water floor, grinding ice only ice floor.
7490 	   maybe add d_info flags for this stuff instead of hard-coding here */
7491 
7492 	/* Change the feature */
7493 	c_ptr->feat = feat;
7494 	aquatic_terrain_hack(zcave, x, y);
7495 
7496 	if (level_generation_time) return;
7497 
7498 	/* XXX it's not needed when called from generate.c */
7499 	for (i = 1; i <= NumPlayers; i++) {
7500 		p_ptr = Players[i];
7501 
7502 		/* Only works for players on the level */
7503 		if (!inarea(wpos, &p_ptr->wpos)) continue;
7504 
7505 		/* Notice */
7506 		note_spot(i, y, x);
7507 
7508 		/* Redraw */
7509 		lite_spot(i, y, x);
7510 	}
7511 }
7512 
7513 /*
7514  * This is a copy of cave_set_feat that is used for "live" changes to the world
7515  * by players and monsters. More specific restrictions can be placed here.
7516  * NOTE: We assume, that allow_terraforming() has already been checked before
7517  *       cave_set_feat_live() is actually called.
7518  */
7519 void cave_set_feat_live(worldpos *wpos, int y, int x, int feat) {
7520 	player_type *p_ptr;
7521 	cave_type **zcave;
7522 	cave_type *c_ptr;
7523 	struct c_special *cs_ptr;
7524 	int i;
7525 //	struct town_type *t_ptr; /* have town keep track of number of feature changes (not yet implemented) */
7526 
7527 	if (!(zcave = getcave(wpos))) return;
7528 	if (!in_bounds(y, x)) return;
7529 	c_ptr = &zcave[y][x];
7530 
7531 	/* apply town-specific restrictions, preserving the intended town layout */
7532 	if (istown(wpos)) {
7533 #if 0
7534 		t_ptr = &town[wild_info[wpos->wx][wpos->wy].town_idx];
7535 
7536 		switch (feat) {
7537 		case FEAT_TREE:
7538 		case FEAT_BUSH:
7539 			if (TOWN_TERRAFORM_TREES == 0) return;
7540 			break;
7541 		case FEAT_WALL_EXTRA:
7542 		case FEAT_QUARTZ:
7543 		case FEAT_MAGMA:
7544 			if (TOWN_TERRAFORM_WALLS == 0) return;
7545 			break;
7546 		case FEAT_SHAL_WATER:
7547 		case FEAT_DEEP_WATER:
7548 			if (TOWN_TERRAFORM_WATER == 0) return;
7549 			break;
7550 		case FEAT_GLYPH:
7551 		case FEAT_RUNE:
7552 			if (TOWN_TERRAFORM_GLYPHS == 0) return;
7553 			break;
7554 		}
7555 
7556 		switch (c_ptr->feat) {
7557 		case FEAT_TREE:
7558 		case FEAT_BUSH:
7559 			if (TOWN_TERRAFORM_TREES == 0) return;
7560 			break;
7561 		case FEAT_WALL_EXTRA:
7562 		case FEAT_QUARTZ:
7563 		case FEAT_MAGMA:
7564 			if (TOWN_TERRAFORM_WALLS == 0) return;
7565 			break;
7566 		case FEAT_SHAL_WATER:
7567 		case FEAT_DEEP_WATER:
7568 			if (TOWN_TERRAFORM_WATER == 0) return;
7569 			break;
7570 		case FEAT_GLYPH:
7571 		case FEAT_RUNE:
7572 			if (TOWN_TERRAFORM_GLYPHS == 0) return;
7573 			break;
7574 		}
7575 #else
7576 		/* hack: only allow around store entrances */
7577 		if (feat == FEAT_GLYPH || feat == FEAT_RUNE) {
7578 			return; //disallow glyphs
7579 
7580 			for (i = 0; i < 9; i++)
7581 				if (zcave[y + ddy_ddd[i]][x + ddx_ddd[i]].feat == FEAT_SHOP) break;
7582 			/* no nearby store entrance found? */
7583 			if (i == 9) return;
7584 		}
7585 #endif
7586 	}
7587 
7588 	/* No runes of protection / glyphs of warding on non-empty grids - C. Blue */
7589 	if ((feat == FEAT_GLYPH || feat == FEAT_RUNE) && !(cave_clean_bold(zcave, y, x) && /* cave_clean_bold also checks for object absence */
7590 	    ((c_ptr->feat == FEAT_NONE) ||
7591 	    (c_ptr->feat == FEAT_FLOOR) ||
7592 	    (c_ptr->feat == FEAT_DIRT) ||
7593 	    (c_ptr->feat == FEAT_LOOSE_DIRT) || /* used for gardens (fields) in wild.c */
7594 	    (c_ptr->feat == FEAT_CROP) || /* used for gardens (fields) in wild.c */
7595 	    (c_ptr->feat == FEAT_GRASS) ||
7596 	    (c_ptr->feat == FEAT_ICE) ||
7597 	    (c_ptr->feat == FEAT_SAND) ||
7598 	    (c_ptr->feat == FEAT_ASH) ||
7599 	    (c_ptr->feat == FEAT_MUD) ||
7600 	    (c_ptr->feat == FEAT_FLOWER) ||
7601 	    (c_ptr->feat == FEAT_NETHER_MIST))))
7602 		return;
7603 
7604 	/* Don't mess with inns please! */
7605 	if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) return;
7606 
7607 	/* No terraforming on impossible ground -
7608 	   compare twall_erosion() for consistency */
7609 #if 0
7610 	if ((feat == FEAT_TREE || feat == FEAT_BUSH || feat == FEAT_FLOOR ||
7611 	    feat == FEAT_WALL_EXTRA || feat == FEAT_QUARTZ || feat == FEAT_MAGMA) &&
7612 	    feat_mud, feat_dirt, etc.... just #else maybe easier?..
7613 	    (c_ptr->feat == FEAT_DEEP_LAVA ||
7614 	    c_ptr->feat == FEAT_DEEP_WATER))
7615 #else
7616 	if (c_ptr->feat == FEAT_DEEP_LAVA || c_ptr->feat == FEAT_DEEP_WATER)
7617 #endif
7618 		return;
7619 
7620 	/* in Nether Realm, floor is always nether mist (or lava)! */
7621 	if (in_netherrealm(wpos)) switch (feat) {
7622 		case FEAT_IVY:
7623 		case FEAT_SHAL_WATER:
7624 		case FEAT_DEEP_WATER:
7625     		case FEAT_ICE:
7626 	    	case FEAT_FLOOR:
7627     		case FEAT_DIRT:
7628 	        case FEAT_GRASS:
7629     		case FEAT_SAND:
7630 	        case FEAT_ASH:
7631 	        case FEAT_MUD:
7632 	/*	case FEAT_PUDDLE: new feature to be added: same as shallow water, but dries out after a while */
7633 	        case FEAT_FLOWER: feat = FEAT_NETHER_MIST;
7634 	}
7635 
7636 	/* todo: submerged ruins/small water cave only water floor, grinding ice only ice floor.
7637 	   maybe add d_info flags for this stuff instead of hard-coding here */
7638 
7639 
7640 
7641 	/* Trees in greater fire become dead trees at once */
7642 	if ((feat == FEAT_TREE || feat == FEAT_BUSH) &&
7643 	    (c_ptr->feat == FEAT_SHAL_LAVA ||
7644 	    c_ptr->feat == FEAT_FIRE ||
7645 	    c_ptr->feat == FEAT_GREAT_FIRE))
7646 		feat = FEAT_DEAD_TREE;
7647 
7648 	/* Clear mimic feature left by a secret door - mikaelh */
7649 	if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
7650 		cs_erase(c_ptr, cs_ptr);
7651 
7652 	/* Change the feature */
7653 	if (c_ptr->feat != feat) c_ptr->info &= ~CAVE_NEST_PIT; /* clear teleport protection for nest grid if it gets changed */
7654 	c_ptr->feat = feat;
7655 
7656 	for (i = 1; i <= NumPlayers; i++) {
7657 		p_ptr = Players[i];
7658 
7659 		/* Only works for players on the level */
7660 		if (!inarea(wpos, &p_ptr->wpos)) continue;
7661 
7662 #if 0 /* done in melee2.c when a monster eats a wall, so it's visible from afar, if level is mapped, that "walls turn black" */
7663 		/* Forget the spot */
7664 		Players[i]->cave_flag[y][x] &= ~CAVE_MARK;
7665 #endif
7666 
7667 		/* Notice */
7668 		note_spot(i, y, x);
7669 
7670 		/* Redraw */
7671 		lite_spot(i, y, x);
7672 
7673 		/* Update some things */
7674 		p_ptr->update |= (PU_VIEW | PU_DISTANCE);
7675 //		p_ptr->update |= PU_FLOW;
7676 
7677 //		p_ptr->redraw |= PR_MAP;
7678 //		p_ptr->window |= PW_OVERHEAD;
7679 	}
7680 }
7681 
7682 
7683 
7684 /*
7685  * Calculate "incremental motion". Used by project() and shoot().
7686  * Assumes that (*y,*x) lies on the path from (y1,x1) to (y2,x2).
7687  */
7688 void mmove2(int *y, int *x, int y1, int x1, int y2, int x2)
7689 {
7690 	int dy, dx, dist, shift;
7691 
7692 	/* Extract the distance travelled */
7693 	dy = (*y < y1) ? y1 - *y : *y - y1;
7694 	dx = (*x < x1) ? x1 - *x : *x - x1;
7695 
7696 	/* Number of steps */
7697 	dist = (dy > dx) ? dy : dx;
7698 
7699 	/* We are calculating the next location */
7700 	dist++;
7701 
7702 
7703 	/* Calculate the total distance along each axis */
7704 	dy = (y2 < y1) ? (y1 - y2) : (y2 - y1);
7705 	dx = (x2 < x1) ? (x1 - x2) : (x2 - x1);
7706 
7707 	/* Paranoia -- Hack -- no motion */
7708 	if (!dy && !dx) return;
7709 
7710 
7711 	/* Move mostly vertically */
7712 	if (dy > dx)
7713 	{
7714 
7715 #if 0
7716 
7717 		int k;
7718 
7719 		/* Starting shift factor */
7720 		shift = dy >> 1;
7721 
7722 		/* Extract a shift factor */
7723 		for (k = 0; k < dist; k++)
7724 		{
7725 			if (shift <= 0) shift += dy;
7726 			shift -= dx;
7727 		}
7728 
7729 		/* Sometimes move along minor axis */
7730 		if (shift <= 0) (*x) = (x2 < x1) ? (*x - 1) : (*x + 1);
7731 
7732 		/* Always move along major axis */
7733 		(*y) = (y2 < y1) ? (*y - 1) : (*y + 1);
7734 
7735 #endif
7736 
7737 		/* Extract a shift factor */
7738 		shift = (dist * dx + (dy-1) / 2) / dy;
7739 
7740 		/* Sometimes move along the minor axis */
7741 		(*x) = (x2 < x1) ? (x1 - shift) : (x1 + shift);
7742 
7743 		/* Always move along major axis */
7744 		(*y) = (y2 < y1) ? (y1 - dist) : (y1 + dist);
7745 	}
7746 
7747 	/* Move mostly horizontally */
7748 	else
7749 	{
7750 
7751 #if 0
7752 
7753 		int k;
7754 
7755 		/* Starting shift factor */
7756 		shift = dx >> 1;
7757 
7758 		/* Extract a shift factor */
7759 		for (k = 0; k < dist; k++)
7760 		{
7761 			if (shift <= 0) shift += dx;
7762 			shift -= dy;
7763 		}
7764 
7765 		/* Sometimes move along minor axis */
7766 		if (shift <= 0) (*y) = (y2 < y1) ? (*y - 1) : (*y + 1);
7767 
7768 		/* Always move along major axis */
7769 		(*x) = (x2 < x1) ? (*x - 1) : (*x + 1);
7770 
7771 #endif
7772 
7773 		/* Extract a shift factor */
7774 		shift = (dist * dy + (dx-1) / 2) / dx;
7775 
7776 		/* Sometimes move along the minor axis */
7777 		(*y) = (y2 < y1) ? (y1 - shift) : (y1 + shift);
7778 
7779 		/* Always move along major axis */
7780 		(*x) = (x2 < x1) ? (x1 - dist) : (x1 + dist);
7781 	}
7782 }
7783 
7784 
7785 /*
7786  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
7787  * at the final destination, assuming no monster gets in the way.
7788  *
7789  * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
7790  */
7791 #ifdef DOUBLE_LOS_SAFETY
7792 static bool projectable_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range);
7793 bool projectable(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7794 	return (projectable_DLS(wpos, y1, x1, y2, x2, range) || projectable_DLS(wpos, y2, x2, y1, x1, range));
7795 }
7796 static bool projectable_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7797 #else
7798 bool projectable(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7799 #endif
7800 	int dist, y, x;
7801 	cave_type **zcave;
7802 	if (!(zcave = getcave(wpos))) return FALSE;
7803 
7804 #ifdef DOUBLE_LOS_SAFETY
7805 	/* catch ball-spell related call in project() which adds '+ dir * 99' aka distance of 99 */
7806 	if (!in_bounds(y1, x1)) return(FALSE);
7807 #endif
7808 
7809 	/* Start at the initial location */
7810 	y = y1, x = x1;
7811 
7812 	/* See "project()" */
7813 	for (dist = 0; dist <= range; dist++) {
7814 		/* Never pass through walls */
7815 		if (dist && !cave_los(zcave, y, x)) break;
7816 
7817 		/* Stopped by protected grids (Inn doors, also stopping monsters' ranged attacks!) */
7818                 if (f_info[zcave[y][x].feat].flags1 & (FF1_BLOCK_LOS | FF1_BLOCK_CONTACT)) break;
7819 
7820 		/* Check for arrival at "final target" */
7821 		if ((x == x2) && (y == y2)) return (TRUE);
7822 
7823 		/* Calculate the new location */
7824 		mmove2(&y, &x, y1, x1, y2, x2);
7825 	}
7826 
7827 	/* Assume obstruction */
7828 	return (FALSE);
7829 }
7830 
7831 /* Same as projectable(), but allows targetting the first grid in a wall */
7832 #ifdef DOUBLE_LOS_SAFETY
7833 static bool projectable_wall_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range);
7834 bool projectable_wall(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7835 	return (projectable_wall_DLS(wpos, y1, x1, y2, x2, range) || projectable_wall_DLS(wpos, y2, x2, y1, x1, range));
7836 }
7837 static bool projectable_wall_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7838 #else
7839 bool projectable_wall(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7840 #endif
7841 	int dist, y, x;
7842 	cave_type **zcave;
7843 	if (!(zcave = getcave(wpos))) return(FALSE);
7844 
7845 #ifdef DOUBLE_LOS_SAFETY
7846 	/* catch ball-spell related call in project() which adds '+ dir * 99' aka distance of 99 */
7847 	if (!in_bounds(y1, x1)) return(FALSE);
7848 #endif
7849 
7850 	/* Start at the initial location */
7851 	y = y1, x = x1;
7852 
7853 	/* See "project()" */
7854 	for (dist = 0; dist <= range; dist++) {
7855 		/* Protected grids prevent targetting */
7856 		if (f_info[zcave[y][x].feat].flags1 & (FF1_BLOCK_LOS | FF1_BLOCK_CONTACT)) break;
7857 
7858 		/* Check for arrival at "final target" */
7859 		if ((x == x2) && (y == y2)) return (TRUE);
7860 
7861 		/* Never go through walls */
7862 		if (dist && !cave_los(zcave, y, x)) break;
7863 
7864 		/* Calculate the new location */
7865 		mmove2(&y, &x, y1, x1, y2, x2);
7866 	}
7867 
7868 	/* Assume obstruction */
7869 	return (FALSE);
7870 }
7871 
7872 /* like projectable_wall(), but assumes that only _permanent walls_ are really obstacles to us
7873    (for movement strategies of PASS_WALL/KILL_WALL monsters) - C. Blue */
7874 #ifdef DOUBLE_LOS_SAFETY
7875 static bool projectable_wall_perm_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range);
7876 bool projectable_wall_perm(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7877 	return (projectable_wall_perm_DLS(wpos, y1, x1, y2, x2, range) || projectable_wall_perm_DLS(wpos, y2, x2, y1, x1, range));
7878 }
7879 static bool projectable_wall_perm_DLS(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7880 #else
7881 bool projectable_wall_perm(struct worldpos *wpos, int y1, int x1, int y2, int x2, int range) {
7882 #endif
7883 	int dist, y, x;
7884 	cave_type **zcave;
7885 	if (!(zcave = getcave(wpos))) return(FALSE);
7886 
7887 	/* Start at the initial location */
7888 	y = y1, x = x1;
7889 
7890 	/* See "project()" */
7891 	for (dist = 0; dist <= range; dist++) {
7892 		/* Protected grids prevent targetting */
7893 		if (f_info[zcave[y][x].feat].flags1 & FF1_PERMANENT) break;
7894 
7895 		/* Check for arrival at "final target" */
7896 		if ((x == x2) && (y == y2)) return (TRUE);
7897 
7898 		/* Calculate the new location */
7899 		mmove2(&y, &x, y1, x1, y2, x2);
7900 	}
7901 
7902 	/* Assume obstruction */
7903 	return (FALSE);
7904 }
7905 
7906 /*
7907  * Created for shoot_till_kill mode in do_cmd_fire().
7908  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
7909  * at the final destination, and if no monster/hostile player is in the way. - C. Blue
7910  * Note: Only sleeping monsters are tested for!
7911  * Note: The hostile-player part is commented out for efficiency atm.
7912  *
7913  */
7914 #ifdef DOUBLE_LOS_SAFETY
7915 static bool projectable_real_DLS(int Ind, int y1, int x1, int y2, int x2, int range);
7916 bool projectable_real(int Ind, int y1, int x1, int y2, int x2, int range) {
7917 	return ((projectable_DLS(&Players[Ind]->wpos, y1, x1, y2, x2, range) || projectable_DLS(&Players[Ind]->wpos, y2, x2, y1, x1, range))
7918 	    /* important: make sure we really don't hit an awake monster from our direction of shooting :-p  : */
7919 	    && projectable_real_DLS(Ind, y1, x1, y2, x2, range));
7920 }
7921 static bool projectable_real_DLS(int Ind, int y1, int x1, int y2, int x2, int range) {
7922 	int dist, y = y1, x = x1;
7923 	cave_type **zcave;
7924 	if (!(zcave = getcave(&Players[Ind]->wpos))) return FALSE;
7925 
7926 	for (dist = 0; dist <= range; dist++) {
7927 		if ((x == x2) && (y == y2)) return (TRUE);
7928 
7929 		/* Never pass through SLEEPING monsters */
7930                 if (dist && (zcave[y][x].m_idx > 0)
7931 		    && target_able(Ind, zcave[y][x].m_idx)
7932 		    && m_list[zcave[y][x].m_idx].csleep) break;
7933 
7934 #if 0
7935 		/* Never pass through hostile player */
7936                 if (dist && zcave[y][x].m_idx < 0) {
7937 			if (check_hostile(Ind, -zcave[y][x].m_idx)) break;
7938 		}
7939 #endif
7940 		mmove2(&y, &x, y1, x1, y2, x2);
7941 	}
7942 	return (FALSE);
7943 }
7944 #else
7945 bool projectable_real(int Ind, int y1, int x1, int y2, int x2, int range) {
7946 	int dist, y, x;
7947 	cave_type **zcave;
7948 	if (!(zcave = getcave(&Players[Ind]->wpos))) return FALSE;
7949 
7950 	/* Start at the initial location */
7951 	y = y1, x = x1;
7952 
7953 	/* See "project()" */
7954 	for (dist = 0; dist <= range; dist++) {
7955 		/* Never pass through walls */
7956 		if (dist && !cave_los(zcave, y, x)) break;
7957 
7958 		/* Stopped by protected grids (Inn doors, also stopping monsters' ranged attacks!) */
7959                 if (f_info[zcave[y][x].feat].flags1 & (FF1_BLOCK_LOS | FF1_BLOCK_CONTACT)) break;
7960 
7961 		/* Check for arrival at "final target" */
7962 		if ((x == x2) && (y == y2)) return (TRUE);
7963 
7964 		/* Never pass through SLEEPING monsters */
7965                 if (dist && (zcave[y][x].m_idx > 0)
7966 		    && target_able(Ind, zcave[y][x].m_idx)
7967 		    && m_list[zcave[y][x].m_idx].csleep) break;
7968 
7969 #if 0
7970 		/* Never pass through hostile player */
7971                 if (dist && zcave[y][x].m_idx < 0) {
7972 			if (check_hostile(Ind, -zcave[y][x].m_idx)) break;
7973 		}
7974 #endif
7975 
7976 		/* Calculate the new location */
7977 		mmove2(&y, &x, y1, x1, y2, x2);
7978 	}
7979 
7980 	/* Assume obstruction */
7981 	return (FALSE);
7982 }
7983 #endif
7984 
7985 /* Relates to projectable_real like projectable_wall to projectable */
7986 #ifdef DOUBLE_LOS_SAFETY
7987 static bool projectable_wall_real_DLS(int Ind, int y1, int x1, int y2, int x2, int range);
7988 bool projectable_wall_real(int Ind, int y1, int x1, int y2, int x2, int range) {
7989 	return ((projectable_wall_DLS(&Players[Ind]->wpos, y1, x1, y2, x2, range) || projectable_wall_DLS(&Players[Ind]->wpos, y2, x2, y1, x1, range))
7990 	    /* important: make sure we really don't hit an awake monster from our direction of shooting :-p  : */
7991 	    && projectable_wall_real_DLS(Ind, y1, x1, y2, x2, range));
7992 }
7993 static bool projectable_wall_real_DLS(int Ind, int y1, int x1, int y2, int x2, int range) {
7994 	int dist, y, x;
7995 	cave_type **zcave;
7996 	if (!(zcave = getcave(&Players[Ind]->wpos))) return FALSE;
7997 
7998 	/* Start at the initial location */
7999 	y = y1, x = x1;
8000 
8001 	/* See "project()" */
8002 	for (dist = 0; dist <= range; dist++) {
8003 		/* Check for arrival at "final target" */
8004 		if ((x == x2) && (y == y2)) return (TRUE);
8005 
8006 		/* Never pass through SLEEPING monsters */
8007                 if (dist && (zcave[y][x].m_idx > 0)
8008 		    && target_able(Ind, zcave[y][x].m_idx)
8009 		    && m_list[zcave[y][x].m_idx].csleep) break;
8010 
8011 #if 0
8012 		/* Never pass through hostile player */
8013                 if (dist && zcave[y][x].m_idx < 0) {
8014 			if (check_hostile(Ind, -zcave[y][x].m_idx)) break;
8015 		}
8016 #endif
8017 
8018 		/* Calculate the new location */
8019 		mmove2(&y, &x, y1, x1, y2, x2);
8020 	}
8021 
8022 	/* Assume obstruction */
8023 	return (FALSE);
8024 }
8025 #else
8026 bool projectable_wall_real(int Ind, int y1, int x1, int y2, int x2, int range)
8027 {
8028 	int dist, y, x;
8029 	cave_type **zcave;
8030 	if (!(zcave = getcave(&Players[Ind]->wpos))) return FALSE;
8031 
8032 	/* Start at the initial location */
8033 	y = y1, x = x1;
8034 
8035 	/* See "project()" */
8036 	for (dist = 0; dist <= range; dist++) {
8037 		/* Stopped by protected grids (Inn doors, also stopping monsters' ranged attacks!) */
8038                 if (f_info[zcave[y][x].feat].flags1 & (FF1_BLOCK_LOS | FF1_BLOCK_CONTACT)) break;
8039 
8040 		/* Check for arrival at "final target" */
8041 		if ((x == x2) && (y == y2)) return (TRUE);
8042 
8043 		/* Never pass through walls */
8044 		if (dist && !cave_los(zcave, y, x)) break;
8045 
8046 		/* Never pass through SLEEPING monsters */
8047                 if (dist && (zcave[y][x].m_idx > 0)
8048 		    && target_able(Ind, zcave[y][x].m_idx)
8049 		    && m_list[zcave[y][x].m_idx].csleep) break;
8050 
8051 #if 0
8052 		/* Never pass through hostile player */
8053                 if (dist && zcave[y][x].m_idx < 0) {
8054 			if (check_hostile(Ind, -zcave[y][x].m_idx)) break;
8055 		}
8056 #endif
8057 
8058 		/* Calculate the new location */
8059 		mmove2(&y, &x, y1, x1, y2, x2);
8060 	}
8061 
8062 	/* Assume obstruction */
8063 	return (FALSE);
8064 }
8065 #endif
8066 
8067 /*
8068  * Standard "find me a location" function
8069  *
8070  * Obtains a legal location within the given distance of the initial
8071  * location, and with "los()" from the source to destination location.
8072  *
8073  * This function is often called from inside a loop which searches for
8074  * locations while increasing the "d" distance.
8075  *
8076  * Currently the "m" parameter is unused.
8077  *
8078  * But now the "m" parameter specifies whether "los" is necessary.
8079  */
8080 /* if d<16, consider using tdi,tdy,tdx; considerably quicker! */
8081 void scatter(struct worldpos *wpos, int *yp, int *xp, int y, int x, int d, int m)
8082 {
8083 	int nx, ny;
8084 //	long tries = 100000;
8085 	/* Reduced to 10k to lessen lockups - mikaelh */
8086 	long tries = 10000;
8087 
8088         cave_type **zcave;
8089         if (!(zcave = getcave(wpos))) {
8090 		(*yp) = y;
8091 		(*xp) = x;
8092 		return;
8093 	}
8094 
8095 	/* Pick a location */
8096 	while (TRUE)
8097 	{
8098 		/* Don't freeze in infinite loop!
8099 		   Conditions: wpos is not allocated.
8100 		   Note: los() returns TRUE if x==nx and y==ny.
8101 		   Due to the conditions, following code will probably cause panic save,
8102 		   that's still better than infinite loop though. */
8103 		tries--;
8104 		if (!tries) {
8105 s_printf("!!! INFINITE LOOP IN scatter() !!! -- Please reboot server and do '/unsta %d,%d,%d (%d,%d; %d,%d; %d %d)'\n",
8106     wpos->wx, wpos->wy,wpos->wz, yp, xp, y, x, d, m);
8107 			ny = y;
8108 			nx = x;
8109 			break;
8110 		}
8111 
8112 		/* Pick a new location */
8113 		ny = rand_spread(y, d);
8114 		nx = rand_spread(x, d);
8115 
8116 		/* Ignore illegal locations and outer walls */
8117 		if (!in_bounds(ny, nx)) continue;
8118 
8119 		/* Ignore "excessively distant" locations */
8120 		if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
8121 
8122 		/* Require "line of sight" */
8123 		if (m || los(wpos, y, x, ny, nx)) break;
8124 	}
8125 
8126 	/* Save the location */
8127 	(*yp) = ny;
8128 	(*xp) = nx;
8129 }
8130 
8131 /*
8132  * Track a new monster
8133  */
8134 void health_track(int Ind, int m_idx)
8135 {
8136 	player_type *p_ptr = Players[Ind];
8137 
8138 	/* Track a new guy */
8139 	p_ptr->health_who = m_idx;
8140 
8141 	/* Redraw (later) */
8142 	p_ptr->redraw |= (PR_HEALTH);
8143 }
8144 
8145 /*
8146  * Update the health bars for anyone tracking a monster
8147  */
8148 void update_health(int m_idx)
8149 {
8150 	player_type *p_ptr;
8151 	int i;
8152 
8153 	/* Each player */
8154 	for (i = 1; i <= NumPlayers; i++)
8155 	{
8156 		p_ptr = Players[i];
8157 
8158 		/* Check connection */
8159 		if (p_ptr->conn == NOT_CONNECTED)
8160 			continue;
8161 
8162 		/* See if he is tracking this monster */
8163 		if (p_ptr->health_who == m_idx)
8164 		{
8165 			/* Redraw */
8166 			p_ptr->redraw |= (PR_HEALTH);
8167 		}
8168 	}
8169 }
8170 
8171 
8172 
8173 /*
8174  * Hack -- track the given monster race
8175  *
8176  * Monster recall is disabled for now --KLJ--
8177  */
8178 void recent_track(int r_idx)
8179 {
8180 	/* Save this monster ID */
8181 	/*recent_idx = r_idx;*/
8182 
8183 	/* Window stuff */
8184 	/*p_ptr->window |= (PW_MONSTER);*/
8185 }
8186 
8187 
8188 
8189 
8190 /*
8191  * Something has happened to disturb the player.
8192  *
8193  * The first arg indicates a major disturbance, which affects search.
8194  *
8195  * The second arg is currently unused, but could induce output flush.
8196  *
8197  * All disturbance cancels repeated commands, resting, and running.
8198  */
8199 void disturb(int Ind, int stop_search, int keep_resting) {
8200 	player_type *p_ptr = Players[Ind];
8201 
8202 	/* Calm down from silly running */
8203 	p_ptr->corner_turn = 0;
8204 
8205 	/* Cancel auto-commands */
8206 	/* command_new = 0; */
8207 
8208 	/* Cancel repeated commands */
8209 	if (p_ptr->command_rep) {
8210 		/* Cancel */
8211 		p_ptr->command_rep = 0;
8212 #ifdef ENABLE_XID_SPELL
8213 		p_ptr->current_item = -1; //unnecessary?
8214 #endif
8215 
8216 		/* Hack -- Clear the buffer */
8217 		Handle_clear_buffer(Ind);
8218 
8219 		/* Redraw the state (later) */
8220 		p_ptr->redraw |= (PR_STATE);
8221 	}
8222 
8223 	/* Cancel Resting */
8224 	if (!keep_resting && p_ptr->resting) {
8225 		/* Cancel */
8226 		p_ptr->resting = 0;
8227 
8228 		/* Redraw the state (later) */
8229 		p_ptr->redraw |= (PR_STATE);
8230 	}
8231 
8232 	/* Cancel running */
8233 	if (p_ptr->running) {
8234 		/* Cancel */
8235 		p_ptr->running = 0;
8236 
8237 		/* Calculate torch radius */
8238 		p_ptr->update |= (PU_TORCH);
8239 	}
8240 
8241 	/* Cancel searching if requested */
8242 	if (stop_search && p_ptr->searching) {
8243 		/* Cancel */
8244 		p_ptr->searching = FALSE;
8245 
8246 		/* Recalculate bonuses */
8247 		p_ptr->update |= (PU_BONUS);
8248 
8249 		/* Redraw stuff */
8250 		p_ptr->redraw |= (PR_STATE | PR_MAP);
8251 
8252 		/* cancel cloaking preparations too */
8253 		stop_cloaking(Ind);
8254 	}
8255 }
8256 
8257 
8258 
8259 
8260 
8261 /*
8262  * Hack -- Check if a level is a "quest" level
8263  */
8264 /* FIXME - use worldpos and dungeon array! */
8265 bool is_xorder(struct worldpos *wpos) {
8266 	/* not implemented yet :p */
8267 	return (FALSE);
8268 #if 0
8269 	int i;
8270 
8271 	/* Town is never a quest */
8272 	if (!level) return (FALSE);
8273 
8274 	/* Check quests */
8275 	for (i = 0; i < MAX_XO_IDX; i++) {
8276 		/* Check for quest */
8277 		if (xo_list[i].level == level) return (TRUE);
8278 	}
8279 
8280 	/* Nope */
8281 	return (FALSE);
8282 #endif
8283 }
8284 
8285 /*
8286  * handle spell effects
8287  */
8288 static int effect_pop(int who)
8289 {
8290 	int i, cnt = 0;
8291 
8292 	for (i = 1; i < MAX_EFFECTS; i++)	/* effects[0] is not used */
8293 	{
8294 		if (!effects[i].time) return i;
8295 		if (effects[i].who == who)
8296 		{
8297 			if (++cnt > MAX_EFFECTS_PLAYER) return -1;
8298 		}
8299 
8300 	}
8301 	return -1;
8302 }
8303 
8304 int new_effect(int who, int type, int dam, int time, int interval, worldpos *wpos, int cy, int cx, int rad, s32b flags)
8305 {
8306 	int i, who2 = who;
8307 /*	player_type *p_ptr = NULL; */
8308 #if 0 /* isn't this wrong? */
8309 	if (who < 0 && who != PROJECTOR_EFFECT)
8310 		who2 = 0 - Players[0 - who]->id;
8311 #else
8312 	if (who < 0 && who > PROJECTOR_UNUSUAL)
8313 		who2 = 0 - Players[0 - who]->id;
8314 #endif
8315 
8316         if ((i = effect_pop(who2)) == -1) return -1;
8317 	effects[i].interval = interval;
8318         effects[i].type = type;
8319         effects[i].dam = dam;
8320         effects[i].time = time;
8321         effects[i].flags = flags;
8322         effects[i].cx = cx;
8323         effects[i].cy = cy;
8324         effects[i].rad = rad;
8325         effects[i].who = who2;
8326 		wpcopy(&effects[i].wpos, wpos);
8327 #ifdef ARCADE_SERVER
8328 if (type == 209)
8329 {
8330 msg_broadcast(0, "mh");
8331 if (flags > 0)
8332 msg_broadcast(0, "some flags");
8333 else
8334 msg_broadcast(0, "no flags");
8335 }
8336 /*        if ((flags & EFF_CROSSHAIR_A) || (flags & EFF_CROSSHAIR_B) || (flags & EFF_CROSSHAIR_C))
8337         {
8338         msg_broadcast(0, "making an effect");
8339         player_type *pfft_ptr = Players[interval];
8340         pfft_ptr->e = i;
8341         } */
8342 #endif
8343 
8344         return i;
8345 }
8346 
8347 bool allow_terraforming(struct worldpos *wpos, byte feat) {
8348 	bool bree = in_bree(wpos);
8349 	bool town = istown(wpos) || isdungeontown(wpos);
8350 	bool townarea = istownarea(wpos, MAX_TOWNAREA);
8351 //unused atm	bool dungeon_town = isdungeontown(wpos);
8352 	bool sector00 = (in_sector00(wpos));
8353 	bool valinor = in_valinor(wpos);
8354 	bool nr_bottom = in_netherrealm(wpos) && getlevel(wpos) == netherrealm_end;
8355 	bool arena_pvp = (wpos->wx == WPOS_PVPARENA_X && wpos->wy == WPOS_PVPARENA_Y && wpos->wz == WPOS_PVPARENA_Z);
8356 	bool arena_monster = (ge_special_sector && wpos->wx == WPOS_ARENA_X && wpos->wy == WPOS_ARENA_Y && wpos->wz == WPOS_ARENA_Z);
8357 
8358 	/* usually allow all changes (normal dungeons and town-unrelated world map) */
8359 	if (!arena_monster && !arena_pvp && !bree && !town && !townarea && !sector00 && !valinor && !nr_bottom) return(TRUE);
8360 
8361 	/* preserve arenas; disallow trees for balancing (pvp-arena) */
8362 	if (arena_pvp || arena_monster) return(FALSE);
8363 
8364 	switch (feat) {
8365 	/* water is annoying in all towns - mikaelh */
8366 	case FEAT_SHAL_WATER:
8367 	case FEAT_DEEP_WATER:
8368 		if (town) return(FALSE);
8369 		break;
8370 
8371 	/* allow only harmless as well as non-obstructing changes: */
8372 	case FEAT_IVY:
8373 	case FEAT_DEAD_TREE:
8374         case FEAT_ICE:
8375 		if (town || sector00 || valinor || nr_bottom) return(FALSE);
8376 		break;
8377 
8378 	case FEAT_WALL_EXTRA: /* tested by earthquake() and destroy_area() */
8379 	case FEAT_SHAL_LAVA:
8380 	case FEAT_DEEP_LAVA:
8381 		if (town || townarea || sector00 || valinor || nr_bottom) return(FALSE);
8382 		break;
8383 
8384 	case FEAT_TREE: /* also for 'digging' and 'stone2mud' */
8385 	case FEAT_BUSH: /* just moved here because FEAT_TREE is also here */
8386 		if (town || sector00 || valinor || nr_bottom) return(FALSE);
8387 		break;
8388 
8389 	case FEAT_GLYPH:
8390 	case FEAT_RUNE:
8391 		/* generally allow in town, restrictions are applied in cave_set_feat_live().) */
8392 		if (sector00 || valinor || nr_bottom) return(FALSE);
8393 		break;
8394 
8395 	/* don't allow any changes at all to preserve the visuals 100% */
8396         case FEAT_NONE:
8397     	case FEAT_FLOOR:
8398         case FEAT_DIRT:
8399         case FEAT_GRASS:
8400         case FEAT_SAND:
8401         case FEAT_ASH:
8402         case FEAT_MUD:
8403         case FEAT_FLOWER:
8404 /*	case FEAT_PUDDLE: new feature to be added: same as shallow water, but dries out after a while */
8405 		if (town || valinor || nr_bottom) return(FALSE);
8406 		break;
8407 
8408 	/* generate.c uses these for staircases in towns */
8409 	case FEAT_MORE:
8410 	case FEAT_LESS:
8411 	case FEAT_WAY_MORE:
8412 	case FEAT_WAY_LESS:
8413 	case FEAT_BETWEEN:
8414 	case FEAT_BEACON:
8415 		break;
8416 
8417 	/* forgot any? just paranoia */
8418 	default: ;
8419 	}
8420 
8421 	return (TRUE);
8422 }
8423 
8424 /*
8425  * Queues a spot for redrawing at the beginning of the next turn.
8426  * Can be used for leaving temporary effects on the screen for one turn.
8427  */
8428 void everyone_lite_later_spot(struct worldpos *wpos, int y, int x) {
8429 	struct worldspot *wspot;
8430 
8431 	if (lite_later_num >= lite_later_alloc) {
8432 		/* Grow the array to meet the demand */
8433 		GROW(lite_later, lite_later_alloc, lite_later_alloc * 2, struct worldspot);
8434 		lite_later_alloc *= 2;
8435 	}
8436 
8437 	/* Add a new spot to the array */
8438 	wspot = &lite_later[lite_later_num];
8439 	lite_later_num++;
8440 
8441 	wpcopy(&wspot->wpos, wpos);
8442 	wspot->x = x;
8443 	wspot->y = y;
8444 }
8445 
8446 /* change between the four seasons - C. Blue
8447     s:		the season (0..3 -> spring,summer,autumn,winter)
8448     force:	true -> force redrawing all sectors
8449 		even if season didn't change. */
8450 void season_change(int s, bool force) {
8451 	int x, y;
8452 	struct worldpos wpos;
8453 
8454 	/* if 'force' is off, at least ensure correct weather frequency here: */
8455 #if defined CLIENT_WEATHER_GLOBAL || !defined CLIENT_SIDE_WEATHER
8456 	/* adjust weather somewhat according to season! (server-side or global weather) */
8457 	switch (s) {
8458 	case SEASON_SPRING: /* rain relatively often */
8459 		weather_frequency = 2; break;
8460 	case SEASON_SUMMER: /* rain rarely */
8461 		weather_frequency = 1; break;
8462 	case SEASON_AUTUMN: /* rain very often */
8463 		weather_frequency = 3; break;
8464 	case SEASON_WINTER: /* snow relatively often */
8465 		weather_frequency = 2; break;
8466 	}
8467 #else
8468 	/* adjust weather somewhat according to season! (client-side non-global weather) */
8469 	switch (s) {
8470 	case SEASON_SPRING: /* rain relatively often */
8471 		max_clouds_seasonal = MAX_CLOUDS / 10; break;
8472 	case SEASON_SUMMER: /* rain rarely */
8473 		max_clouds_seasonal = MAX_CLOUDS / 14; break;
8474 	case SEASON_AUTUMN: /* rain very often */
8475 		max_clouds_seasonal = MAX_CLOUDS / 7; break;
8476 	case SEASON_WINTER: /* snow pretty often */
8477 		max_clouds_seasonal = MAX_CLOUDS / 8; break;
8478 	}
8479 #endif
8480 
8481 	if ((season == s) && !force) return;
8482 	season = s;
8483 
8484 	/* make wilderness more lively again */
8485 	lively_wild(0);
8486 
8487 	/* rebuild wilderness + town layout everywhere! */
8488 	wpos.wz = 0;
8489 	for (x = 0; x < MAX_WILD_X; x++)
8490 	for (y = 0; y < MAX_WILD_Y; y++) {
8491 		wpos.wx = x;
8492 		wpos.wy = y;
8493 		if (getcave(&wpos)) regenerate_cave(&wpos);
8494 	}
8495 
8496 	s_printf("(%s) SEASON_CHANGE: %d", showtime(), s);
8497 	if (s == SEASON_SPRING) {
8498 		s_printf(" spring");
8499 		world_surface_msg("\374\377GSpring has arrived.");
8500 	}
8501 	if (s == SEASON_SUMMER) {
8502 		s_printf(" summer");
8503 		world_surface_msg("\374\377GSummer has come.");
8504 	}
8505 	if (s == SEASON_AUTUMN) {
8506 		s_printf(" autumn");
8507 		world_surface_msg("\374\377GAutumn paints the scenery.");
8508 	}
8509 	if (s == SEASON_WINTER) {
8510 		s_printf(" winter");
8511 		world_surface_msg("\374\377GWinter embraces the lands.");
8512 	}
8513 	s_printf("\n");
8514 
8515 	/* redraw map for all players */
8516 	for (x = 1; x <= NumPlayers; x++) Players[x]->redraw |= PR_MAP;
8517 
8518 	/* make all clouds terminate soon, to account for changed climate situation */
8519 	for (x = 0; x < MAX_CLOUDS; x++) {
8520 		/* does cloud exist? */
8521 		if (cloud_dur[x]) /* also affects 'dur = -1' clouds */
8522 			cloud_dur[x] = 5 + rand_int(10); /* terminate in 5..15 seconds */
8523 	}
8524 }
8525 
8526 /* Update players' client-side weather. - C. Blue
8527    entered_level = TRUE : player just newly entered this sector
8528    weather_changed = TRUE : weather just changed, reset the player's
8529      client-side weather synchronization timings (see c-xtra1.c).
8530    NOTE: if entered_level is TRUE, so should be weather_changed!
8531    panel_redraw is only TRUE if we also want to instantly redraw the current
8532    panel without waiting for usual number of client ticks.
8533    NOTE: Called on opportunities (ie when player moves around)
8534          and also by players_weather(). */
8535 #if 1
8536 /* make rain fall down slower? */
8537  #define WEATHER_GEN_TICKS 3
8538  #define WEATHER_SNOW_MULT 3
8539 #else
8540 /* make rain fall down faster? */
8541  #define WEATHER_GEN_TICKS 2
8542  #define WEATHER_SNOW_MULT 4
8543 #endif
8544 void player_weather(int Ind, bool entered_level, bool weather_changed, bool panel_redraw) {
8545 	player_type *p_ptr = Players[Ind];
8546 	int w;
8547 
8548 	/* running custom weather for debugging purpose? */
8549 	if (p_ptr->custom_weather) return;
8550 
8551 	/* not in dungeon? erase weather and exit */
8552 	if (p_ptr->wpos.wz) {
8553 		if (!entered_level) return;
8554 		/* erase weather */
8555 		Send_weather(Ind, -1, 0, WEATHER_GEN_TICKS,
8556 		    WEATHER_GEN_TICKS, WEATHER_GEN_TICKS,
8557 		    FALSE, TRUE);
8558 		return;
8559 	}
8560 
8561 	/* no weather in sector00 during events */
8562 	if (in_sector00(&p_ptr->wpos)) {
8563 		if (!entered_level) return;
8564 		/* erase weather */
8565 		Send_weather(Ind, -1, 0, WEATHER_GEN_TICKS,
8566 		    WEATHER_GEN_TICKS, WEATHER_GEN_TICKS,
8567 		    FALSE, TRUE);
8568 		return;
8569 	}
8570 
8571 #ifdef CLIENT_WEATHER_GLOBAL /* use global weather instead of sector-specific? */
8572 	w = ((entered_level) ? ((weather) ? 200 : -1) : 0);
8573 	Send_weather(Ind,
8574 	    weather + w
8575 	    + ((weather_changed && (w != -1)) ? 10000 : 0)
8576 	    + ((weather && panel_redraw) ? 20000 : 0),
8577 /*	    (wind_gust > 0 ? 1 : (wind_gust < 0 ? 2 : 0))
8578 	    + ((wind_gust != 0) && (season == SEASON_WINTER) ? 4 : 0), */
8579 	    (wind_gust > 0 ? 2 * (season == SEASON_WINTER ? WEATHER_SNOW_MULT : 1) * WEATHER_GEN_TICKS - 1
8580 	    : (wind_gust < 0 ? 2 * (season == SEASON_WINTER ? WEATHER_SNOW_MULT : 1) * WEATHER_GEN_TICKS : 0)),
8581 	    WEATHER_GEN_TICKS,
8582 	    (season == SEASON_WINTER) ? 5 : 8,
8583 	    (season == SEASON_WINTER) ? WEATHER_SNOW_MULT * WEATHER_GEN_TICKS :
8584 	    /* hack: for non-windy rainfall, accelerate raindrop falling speed by 1: */
8585 	    (wind_gust ? 1 * WEATHER_GEN_TICKS : WEATHER_GEN_TICKS - 1),
8586 	    FALSE, TRUE); /* no virtual cloud if weather is global */
8587 
8588 #else /* send his worldmap sector's specific weather situation */
8589 	w = ((entered_level) ? ((wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_type) ? 200 : -1) : 0); /* +(n*10): pre-generate n particles? */
8590  #if 0 /* buggy? */
8591 	Send_weather(Ind,
8592 	    wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_type + w
8593  #else
8594 	Send_weather(Ind,
8595 	    ((w == -1) ? -1 : (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_type + w))
8596  #endif
8597 	    + ((weather_changed && (w != -1)) ? 10000 : 0) /* sync panel? */
8598  #if 0 /* glitchy? paranoia maybe */
8599 	    + (weather && panel_redraw ? 20000 : 0),
8600  #else
8601 	    + ((weather && panel_redraw && (w != -1)) ? 20000 : 0), /* insta-refresh? */
8602  #endif
8603 	    wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_wind,
8604 	    WEATHER_GEN_TICKS,
8605 	    wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_intensity,
8606 	    wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_speed,
8607 	    TRUE, FALSE); /* <- apply clouds! */
8608 
8609  #ifdef TEST_SERVER /* DEBUG */
8610  #if 0
8611  s_printf("  updated weather for player %d to type %d (real: %d).\n", Ind,
8612     wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_type + w
8613     + ((weather_changed && (w != -1)) ? 10000 : 0)
8614     + (weather && panel_redraw ? 20000 : 0),
8615     wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_type);
8616  s_printf("  (wind %d, intensity %d, speed %d)\n",
8617     wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_wind,
8618     wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_intensity,
8619     wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].weather_speed);
8620  #endif
8621  #endif
8622 #endif
8623 }
8624 
8625 
8626 /* The is_stairs/is_doors hack in monster_can_cross_terrain() that allows
8627    aquatic monsters to cross doors and stairs in 'underwater' levels had the
8628    bad side effect of causing aquatic monsters on normal levels to seek out
8629    stairs/doors and get stuck on them. To fix this in turn, I added CAVE_WATERY
8630    and this hack that applies it. - C. Blue */
8631 void aquatic_terrain_hack(cave_type **zcave, int x, int y) {
8632 	int d, xx, yy;
8633 
8634 	if (!is_always_passable(zcave[y][x].feat)) return;
8635 
8636 	for (d = 1; d <= 9; d++) {
8637 		if (d == 5) continue;
8638 		xx = x + ddx[d];
8639 		yy = y + ddy[d];
8640 		if (!in_bounds(yy, xx)) continue;
8641 		if (zcave[yy][xx].feat == FEAT_DEEP_WATER) {
8642 			zcave[y][x].info |= CAVE_WATERY;
8643 			return;
8644 		}
8645 	}
8646 }
8647 
8648 /* Special wpos that ought to keep monsters and/or objects instead of deleting
8649    or compacting them, even though the floor might not necessarily be kept
8650    static. - C. Blue
8651    Added for IDDC static towns, could maybe also be used for quests. */
8652 bool sustained_wpos(struct worldpos *wpos) {
8653 	if (is_fixed_irondeepdive_town(wpos, getlevel(wpos))) return TRUE;
8654 	return FALSE;
8655 }
8656