1 /* NetHack may be freely redistributed.  See license for details. */
2 
3 #include "vulture_sdl.h" /* XXX this must be the first include,
4                              no idea why but it won't compile otherwise */
5 
6 extern "C" {
7 	#include "hack.h"
8 }
9 
10 #include "levelwin.h"
11 #include "hotspot.h"
12 #include "minimap.h"
13 #include "toolbar.h"
14 #include "contextmenu.h"
15 #include "map.h"
16 #include "messagewin.h"
17 
18 
19 #include "vulture_win.h"
20 #include "vulture_gra.h"
21 #include "vulture_opt.h"
22 #include "vulture_tile.h"
23 #include "vulture_mou.h"
24 #include "vulture_gen.h"
25 #include "vulture_main.h"
26 
27 /* ??????????
28  * without this the file will occasionally fail to compile, seemingly at random
29  */
30 #undef min
31 #undef max
32 #define min(a, b) (((a) < (b)) ? (a) : (b))
33 #define max(a, b) (((a) > (b)) ? (a) : (b))
34 
35 #define VULTURE_CLIPMARGIN 200
36 
37 
38 levelwin *levwin;
39 int vulture_map_draw_msecs = 0;
40 int vulture_map_draw_lastmove = 0;
41 int vulture_map_highlight_objects = 0;
42 
43 
levelwin(mapdata * data)44 levelwin::levelwin(mapdata *data) : window(NULL), map_data(data)
45 {
46 	v_type = V_WINTYPE_LEVEL;
47 
48 	x = 0;
49 	y = 0;
50 	w = vulture_screen->w;
51 	h = vulture_screen->h;
52 	need_redraw = 1;
53 
54 
55 	/* upper left scroll hotspot */
56 	new hotspot(this, 0,      0,      20,     20,     V_HOTSPOT_SCROLL_UPLEFT,    "scroll diagonally");
57 	/* upper right scroll hotspot */
58 	new hotspot(this, w - 20, 0,      20,     20,     V_HOTSPOT_SCROLL_UPRIGHT,   "scroll diagonally");
59 	/* left scroll hotspot */
60 	new hotspot(this, 0,      20,     20,     h - 40, V_HOTSPOT_SCROLL_LEFT,      "scroll left");
61 	/* right scroll hotspot */
62 	new hotspot(this, w - 20, 20,     20,     h - 40, V_HOTSPOT_SCROLL_RIGHT,     "scroll right");
63 	/* bottom left scroll hotspot */
64 	new hotspot(this, 0,      h - 20, 20,     20,     V_HOTSPOT_SCROLL_DOWNLEFT,  "scroll diagonally");
65 	/* bottom scroll hotspot */
66 	new hotspot(this, 20,     h - 20, w - 40, 20,     V_HOTSPOT_SCROLL_DOWN,      "scroll down");
67 	/* upper left scroll hotspot */
68 	new hotspot(this, w - 20, h - 20, 20,     20,     V_HOTSPOT_SCROLL_DOWNRIGHT, "scroll diagonally");
69 
70 	/* create the minimap now, so that it's drawn _under_ the message window */
71 	new minimap(this, map_data);
72 
73 	/*NOTE: the upper scroll hotspot gets created later in ::init(),
74 	* so that it covers the message window */
75 
76 	clip_tl_x = 999999;
77 	clip_tl_y = 999999;
78 	clip_br_x = 0;
79 	clip_br_y = 0;
80 
81 	levwin = this;
82 
83 	map_data->add_viewer(this);
84 }
85 
86 
init()87 void levelwin::init()
88 {
89 	int i, j;
90 
91 	/* Initialize map */
92 	for (i = 0; i < ROWNO; i++) {
93 		for (j = 0; j < COLNO; j++) {
94 			map_deco[i][j] = 0;
95 			room_indices[i][j] = 0;
96 
97 			clear_walls(i,j);
98 		}
99 	}
100 
101 	w = vulture_screen->w;
102 	h = vulture_screen->h;
103 
104 	/* create the upper scroll hotspot. NOTE that all other scroll hotspots
105 	// 		* are created earlier in the ctor */
106 	new hotspot(this, 20, 0, w - 40, 20, V_HOTSPOT_SCROLL_UP, "scroll up");
107 
108 	/* Toolbar1: inventory, map, cast spell, extended commands */
109 	const tb_buttondesc tb1_desc[6] = {
110 		{V_HOTSPOT_BUTTON_INVENTORY, "Inventory"},
111 		{V_HOTSPOT_BUTTON_MAP, "Map"},
112 		{V_HOTSPOT_BUTTON_SPELLBOOK, "Cast spell"},
113 		{V_HOTSPOT_BUTTON_EXTENDED, "Extended commands"},
114 		{V_HOTSPOT_BUTTON_DISCOVERIES, "Show discoveries"},
115     {0,""}
116 	};
117 
118 	new toolbar(this, V_WIN_TOOLBAR1, vulture_opts.show_actiontb,
119 				w - 215, h - 84, V_FILENAME_TOOLBAR1, tb1_desc);
120 
121 	/* Toolbar 2: look at, previous messages, options, help */
122 	const tb_buttondesc tb2_desc[6] = {
123 		{V_HOTSPOT_BUTTON_GOLD, "Gold"},
124 		{V_HOTSPOT_BUTTON_LOOK, "Look"},
125 		{V_HOTSPOT_BUTTON_MESSAGES, "Old messages"},
126 		{V_HOTSPOT_BUTTON_OPTIONS, "Options"},
127 		{V_HOTSPOT_BUTTON_IFOPTIONS, "Interface Options"},
128 		{V_HOTSPOT_BUTTON_HELP, "Help"}
129 	};
130 
131 	new toolbar(this, V_WIN_TOOLBAR2, vulture_opts.show_helptb,
132 				w - 255, h - 45, V_FILENAME_TOOLBAR2, tb2_desc);
133 
134 	/* select wall style */
135 	switch (vulture_opts.wall_style)
136 	{
137 		case V_WALL_DISPLAY_STYLE_FULL:
138 			walltiles = (struct walls*)walls_full; break;
139 
140 		case V_WALL_DISPLAY_STYLE_HALF_HEIGHT:
141 			walltiles = (struct walls*)walls_half; break;
142 
143 		default:
144 			walltiles = (struct walls*)walls_half; break;
145 	}
146 
147 	view_x = COLNO/2;
148 	view_y = ROWNO/2;
149 }
150 
151 
~levelwin()152 levelwin::~levelwin()
153 {
154 	map_data->del_viewer(this);
155 }
156 
157 
set_view(int x,int y)158 void levelwin::set_view(int x, int y)
159 {
160 	view_x = x;
161 	view_y = y;
162 }
163 
164 
165 /* check whether the map needs recentering */
need_recenter(int map_x,int map_y)166 bool levelwin::need_recenter(int map_x, int map_y)
167 {
168 	int screen_x, screen_y;
169 
170 	map_x -= view_x;
171 	map_y -= view_y;
172 	screen_x = vulture_screen->w/2 + V_MAP_XMOD*(map_x - map_y);
173 	screen_y = vulture_screen->h/2 + V_MAP_YMOD*(map_x + map_y);
174 
175 	/* if the player is within the outer 1/4 of the screen, the map needs recentering  */
176 	if ((screen_x >= vulture_screen->w/4) && (screen_x < vulture_screen->w * 3 / 4) &&
177 		(screen_y >= vulture_screen->h/4) && (screen_y < vulture_screen->h * 3 / 4))
178 		return true;
179 
180 	return false;
181 }
182 
183 
force_redraw(void)184 void levelwin::force_redraw(void)
185 {
186     need_redraw = 1;
187 
188     clip_tl_x = 0;
189     clip_tl_y = 0;
190     clip_br_x = w;
191     clip_br_y = h;
192 }
193 
194 
195 
draw()196 bool levelwin::draw()
197 {
198 	int i, j, dir_idx;
199 	vulture_tile * cur_tile;
200 	int x, y;
201 	int tile_id, shadelevel;
202 	int map_tr_x, map_tr_y, __i, __j, diff, sum;
203 	int map_centre_x = this->w / 2;
204 	int map_centre_y = this->h / 2;
205 	int map_back, map_darkness, map_obj, map_mon;
206 
207 	unsigned long startticks = SDL_GetTicks();
208 
209 	static int cur_dlevel = -1;
210 	static int prev_cx = -1;
211 	static int prev_cy = -1;
212 
213 	if (cur_dlevel != u.uz.dlevel)
214 	{
215 		init_floor_decors(10);
216 		cur_dlevel = u.uz.dlevel;
217 	}
218 
219 
220 	if (prev_cx != view_x ||
221 		prev_cy != view_y ||
222 		map_data->map_swallow != V_TILE_NONE)
223 	{
224 		clip_tl_x = this->abs_x;
225 		clip_tl_y = this->abs_y;
226 		clip_br_x = this->abs_x + this->w;
227 		clip_br_y = this->abs_y + this->h;
228 	}
229 	else
230 	{
231 		clip_tl_x = min(clip_tl_x, 0);
232 		clip_tl_y = min(clip_tl_y, 0);
233 		clip_br_x = max(clip_br_x, this->abs_x + this->w - 1);
234 		clip_br_y = max(clip_br_y, this->abs_y + this->h - 1);
235 	}
236 
237 	if (clip_tl_x >= this->w + this->abs_x ||
238 	    clip_tl_y >= this->h + this->abs_y)
239 		/* nothing changed onscreen */
240 		return 1;
241 
242 	prev_cx = view_x;
243 	prev_cy = view_y;
244 
245 	/* Only draw on map area */
246 	vulture_set_draw_region(clip_tl_x, clip_tl_y,
247 							clip_br_x, clip_br_y);
248 
249 	/* If swallowed draw ONLY the engulf tile and the player! */
250 	if (u.uswallow && map_data->map_swallow != V_TILE_NONE) {
251 		/* Clear map area */
252 		SDL_FillRect(vulture_screen, NULL, CLR32_BLACK);
253 
254 		x = map_centre_x + V_MAP_XMOD*(u.ux - u.uy + view_y - view_x);
255 		y = map_centre_y + V_MAP_YMOD*(u.ux + u.uy - view_y - view_x);
256 
257 		/* engulf tile */
258 		vulture_put_tile(x, y, map_data->map_swallow);
259 
260 		/* player */
261 		vulture_put_tile(x, y, map_data->get_glyph(MAP_MON, u.ux, u.uy));
262 
263 		vulture_invalidate_region(clip_tl_x, clip_tl_y,
264 								clip_br_x - clip_tl_x,
265 								clip_br_y - clip_tl_y);
266 		return 1;
267 	}
268 	else
269 		map_data->map_swallow = V_TILE_NONE;
270 
271 
272 	/* prevent double redraws if the map view just moved under the mouse cursor */
273 	map_highlight = mouse_to_map(vulture_get_mouse_pos());
274 
275 	/* coords of the top right corner */
276 	map_tr_x = (-V_MAP_YMOD * (map_centre_x + 50) + V_MAP_XMOD * (map_centre_y + 50) +
277 					V_MAP_XMOD * V_MAP_YMOD) / (2 * V_MAP_XMOD * V_MAP_YMOD);
278 	map_tr_y =  (V_MAP_YMOD * (map_centre_x + 50) + V_MAP_XMOD * (map_centre_y + 50) +
279 					V_MAP_XMOD * V_MAP_YMOD) / (2 * V_MAP_XMOD * V_MAP_YMOD);
280 
281 	/* without the +-1 small corners within the viewport are not drawn */
282 	diff = map_tr_x - map_tr_y - 1;
283 	sum  = map_tr_x + map_tr_y + 1;
284 
285 	for (__i = - map_tr_y; __i <= map_tr_y; __i++)
286 	{
287 		i = view_y + __i;
288 
289 		for (__j = diff + __i; __j + __i <= sum; __j++)
290 		{
291 			j = view_x + __j;
292 
293 			x = map_centre_x + V_MAP_XMOD*(__j - __i);
294 			y = map_centre_y + V_MAP_YMOD*(__j + __i);
295 
296 			if (j < 1 || j >= COLNO || i < 0 || i >= ROWNO)
297 			{
298 				vulture_put_tile(x, y, V_MISC_OFF_MAP);
299 				continue;
300 			}
301 
302 			map_back = map_data->get_glyph(MAP_BACK, j, i);
303 			map_darkness = map_data->get_glyph(MAP_DARKNESS, j, i);
304 
305 			/*
306 			Draw Vulture's tiles, in order:
307 			pass 1
308 				1. Floor
309 				2. Floor edges
310 
311 			pass 2
312 				1. North & west walls
313 				2. Furniture
314 				3. Traps
315 				4. Objects
316 				5. Monsters
317 				6. Effects
318 				7. South & east walls
319 			*/
320 
321 			/* 0. init walls and floor edges for this tile*/
322 			if (map_back == V_TILE_WALL_GENERIC ||
323 				map_back == V_MISC_UNMAPPED_AREA)
324 				get_wall_tiles(i, j);
325 			else
326 				/* certain events (amnesia or a secret door being discovered)
327 				* require us to clear walls again. since we cannot check for those cases
328 				* we simply clear walls whenever we don't set any... */
329 				clear_walls(i, j);
330 
331 			if (map_back == V_TILE_FLOOR_WATER ||
332 				map_back == V_TILE_FLOOR_ICE ||
333 				map_back == V_TILE_FLOOR_LAVA ||
334 				map_back == V_TILE_FLOOR_AIR)
335 				/* these tiles get edges */
336 				get_floor_edges(i, j);
337 			else
338 				/* everything else doesn't. However we can't just assume a tile that doesn't need egdes doesn't have any:
339 				* pools may be dried out by fireballs, and suddenly we have a pit with edges :(
340 				* Therefore we always clear them explicitly */
341 				clear_floor_edges(i ,j);
342 
343 
344 			/* 2. Floor */
345 			tile_id = map_back;
346 			shadelevel = 0;
347 
348 			if ((tile_id >= V_TILE_FLOOR_COBBLESTONE) &&
349 				(tile_id <= V_TILE_FLOOR_DARK)) {
350 				tile_id = get_floor_tile(tile_id, i, j);
351 				shadelevel = map_darkness;
352 			}
353 			else if(tile_id == V_TILE_NONE || tile_id == V_TILE_WALL_GENERIC)
354 				tile_id = V_MISC_UNMAPPED_AREA;
355 
356 			vulture_put_tile_shaded(x, y, tile_id, shadelevel);
357 
358 			/* shortcut for unmapped case */
359 			if (tile_id == V_MISC_UNMAPPED_AREA)
360 				continue;
361 
362 			if (vulture_opts.highlight_cursor_square &&
363 				(j == map_highlight.x && i == map_highlight.y))
364 				vulture_put_tile(x, y, V_MISC_FLOOR_HIGHLIGHT);
365 
366 			/* 3. Floor edges */
367 			for (dir_idx = 0; dir_idx < 12; dir_idx++)
368 				vulture_put_tile(x, y, maptile_floor_edge[i][j].dir[dir_idx]);
369 		}
370 	}
371 
372 	for (__i = - map_tr_y; __i <= map_tr_y; __i++)
373 	{
374 		i = view_y + __i;
375 		if (i < 0 || i >= ROWNO)
376 			continue;
377 
378 		for (__j = diff + __i; __j + __i <= sum; __j++)
379 		{
380 			j = view_x + __j;
381 			if (j < 1 || j >= COLNO)
382 				continue;
383 			/* Find position of tile centre */
384 			x = map_centre_x + V_MAP_XMOD*(__j - __i);
385 			y = map_centre_y + V_MAP_YMOD*(__j + __i);
386 
387 			map_back = map_data->get_glyph(MAP_BACK, j, i);
388 			map_obj = map_data->get_glyph(MAP_OBJ, j, i);
389 			map_mon = map_data->get_glyph(MAP_MON, j, i);
390 
391 			/* 1. West and north walls */
392 			if (j > 1)
393 				vulture_put_tile_shaded(x, y, maptile_wall[i][j].west,
394 										map_data->get_glyph(MAP_DARKNESS, j-1, i));
395 			if (i > 1)
396 				vulture_put_tile_shaded(x, y, maptile_wall[i][j].north,
397 										map_data->get_glyph(MAP_DARKNESS, j, i-1));
398 
399 			/* shortcut for unmapped case */
400 			if (map_back != V_MISC_UNMAPPED_AREA ||
401 				map_obj != V_TILE_NONE) {
402 				/* 2. Furniture*/
403 				vulture_put_tile(x, y, map_data->get_glyph(MAP_FURNITURE, j, i));
404 
405 
406 				/* 3. Traps */
407 				vulture_put_tile(x, y, map_data->get_glyph(MAP_TRAP, j, i));
408 
409 
410 				/* 4. Objects */
411 				vulture_put_tile(x, y, map_obj);
412 
413 
414 				/* 5. Monsters */
415 				if ((cur_tile = vulture_get_tile(map_mon)) != NULL) {
416 					vulture_put_tile(x, y, map_mon);
417 					if (iflags.hilite_pet && map_data->get_glyph(MAP_PET, j, i))
418 						vulture_put_img(x + cur_tile->xmod, y + cur_tile->ymod - 10,
419 									vulture_get_tile(V_MISC_HILITE_PET)->graphic);
420 				}
421 
422 				/* 6. Effects */
423 				vulture_put_tile(x, y, map_data->get_glyph(MAP_SPECIAL, j, i));
424 			}
425 
426 			/* 7. South & East walls */
427 			if (i < ROWNO - 1)
428 				vulture_put_tile_shaded(x, y, maptile_wall[i][j].south,
429 										map_data->get_glyph(MAP_DARKNESS, j, i+1));
430 			if (j < COLNO - 1)
431 				vulture_put_tile_shaded(x, y, maptile_wall[i][j].east,
432 										map_data->get_glyph(MAP_DARKNESS, j+1, i));
433 		}
434 	}
435 
436 	/* draw object highlights if requested */
437 	if (vulture_map_highlight_objects)
438 	{
439 		for (__i = - map_tr_y; __i <= map_tr_y; __i++)
440 		{
441 			i = view_y + __i;
442 			if (i < 0 || i >= ROWNO)
443 				continue;
444 
445 			for (__j = diff + __i; __j + __i <= sum; __j++)
446 			{
447 				j = view_x + __j;
448 				if (j < 1 || j >= COLNO)
449 					continue;
450 
451 				x = map_centre_x + V_MAP_XMOD*(__j - __i);
452 				y = map_centre_y + V_MAP_YMOD*(__j + __i);
453 
454 				vulture_put_tilehighlight(x, y, map_data->get_glyph(MAP_OBJ, j, i));
455 			}
456 		}
457 	}
458 	/* Restore drawing region */
459 	vulture_set_draw_region(0, 0, vulture_screen->w-1, vulture_screen->h-1);
460 
461 	vulture_invalidate_region(clip_tl_x, clip_tl_y,
462 							clip_br_x - clip_tl_x,
463 							clip_br_y - clip_tl_y);
464 
465 	clip_tl_x = 999999;
466 	clip_tl_y = 999999;
467 	clip_br_x = 0;
468 	clip_br_y = 0;
469 
470 	vulture_tilecache_age();
471 
472 	vulture_map_draw_msecs = SDL_GetTicks() - startticks;
473 	vulture_map_draw_lastmove = moves;
474 
475 	return true;
476 }
477 
478 
handle_timer_event(window * target,void * result,int time)479 eventresult levelwin::handle_timer_event(window* target, void* result, int time)
480 {
481   std::string ttext;
482 	point mappos, mouse;
483 
484 	mouse = vulture_get_mouse_pos();
485 	mappos = mouse_to_map(mouse);
486 
487 	/* hovering on a border: scroll */
488 	if (target != this && target->menu_id)
489 	{
490 		int increment = (time / 500) + 1;
491 		switch (target->menu_id)
492 		{
493 			case V_HOTSPOT_SCROLL_UPLEFT:
494 				view_x-=increment; break;
495 			case V_HOTSPOT_SCROLL_UP:
496 				view_x-=increment; view_y-=increment; break;
497 			case V_HOTSPOT_SCROLL_UPRIGHT:
498 				view_y-=increment; break;
499 			case V_HOTSPOT_SCROLL_LEFT:
500 				view_x-=increment; view_y+=increment; break;
501 			case V_HOTSPOT_SCROLL_RIGHT:
502 				view_x+=increment; view_y-=increment; break;
503 			case V_HOTSPOT_SCROLL_DOWNLEFT:
504 				view_y+=increment; break;
505 			case V_HOTSPOT_SCROLL_DOWN:
506 				view_x+=increment; view_y+=increment; break;
507 			case V_HOTSPOT_SCROLL_DOWNRIGHT:
508 				view_x+=increment; break;
509 		}
510 
511 		view_x = (view_x < 0) ? 0 : view_x;
512 		view_y = (view_y < 0) ? 0 : view_y;
513 		view_x = (view_x > COLNO) ? COLNO : view_x;
514 		view_y = (view_y > ROWNO) ? ROWNO : view_y;
515 
516 		need_redraw = 1;
517 		return V_EVENT_HANDLED_REDRAW;
518 	}
519 
520 	/* hovering over the map: display a tooltip */
521 	if (time < HOVERTIMEOUT)
522 		return V_EVENT_HANDLED_NOREDRAW;
523 
524 	if (target != this && !target->caption.empty())
525 		vulture_mouse_set_tooltip(target->caption);
526 	else {
527 		ttext = map_data->map_square_description(mappos, 1);
528 		if(!ttext.empty())
529 			vulture_mouse_set_tooltip(ttext);
530 	}
531 
532 	return V_EVENT_HANDLED_NOREDRAW;
533 }
534 
535 
handle_mousemotion_event(window * target,void * result,int xrel,int yrel,int state)536 eventresult levelwin::handle_mousemotion_event(window* target, void* result, int xrel,
537                                              int yrel, int state)
538 {
539 	point mouse, mappos;
540 
541 	mouse = vulture_get_mouse_pos();
542 	mappos = mouse_to_map(mouse);
543 
544 	if (target != this && target->menu_id)
545 	{
546 		/* show a map scroll cursor if the mouse is in the edge zone */
547 		switch (target->menu_id)
548 		{
549 			case V_HOTSPOT_SCROLL_UPLEFT:
550 				vulture_set_mcursor(V_CURSOR_SCROLLUPLEFT); break;
551 			case V_HOTSPOT_SCROLL_UP:
552 				vulture_set_mcursor(V_CURSOR_SCROLLUP); break;
553 			case V_HOTSPOT_SCROLL_UPRIGHT:
554 				vulture_set_mcursor(V_CURSOR_SCROLLUPRIGHT); break;
555 			case V_HOTSPOT_SCROLL_LEFT:
556 				vulture_set_mcursor(V_CURSOR_SCROLLLEFT); break;
557 			case V_HOTSPOT_SCROLL_RIGHT:
558 				vulture_set_mcursor(V_CURSOR_SCROLLRIGHT); break;
559 			case V_HOTSPOT_SCROLL_DOWNLEFT:
560 				vulture_set_mcursor(V_CURSOR_SCROLLDOWNLEFT); break;
561 			case V_HOTSPOT_SCROLL_DOWN:
562 				vulture_set_mcursor(V_CURSOR_SCROLLDOWN); break;
563 			case V_HOTSPOT_SCROLL_DOWNRIGHT:
564 				vulture_set_mcursor(V_CURSOR_SCROLLDOWNRIGHT); break;
565 			default:
566 				vulture_set_mcursor(get_map_cursor(mappos));
567 		}
568 	}
569 	else
570 		/* select a cursor for the current position */
571 		vulture_set_mcursor(get_map_cursor(mappos));
572 
573 	/* if the highlight option is on, store the map position of the mouse
574 	* and refresh the current and previous positions */
575 	if (vulture_opts.highlight_cursor_square &&
576 		(map_highlight.x != mappos.x || map_highlight.y != mappos.y))
577 	{
578 		mouse = map_to_mouse(map_highlight);
579 		add_to_clipregion(mouse.x - V_MAP_XMOD, mouse.y - V_MAP_YMOD,
580 							mouse.x + V_MAP_XMOD, mouse.y + V_MAP_YMOD);
581 		mouse = map_to_mouse(mappos);
582 		add_to_clipregion(mouse.x - V_MAP_XMOD, mouse.y - V_MAP_YMOD,
583 							mouse.x + V_MAP_XMOD, mouse.y + V_MAP_YMOD);
584 
585 		map_highlight = mappos;
586 		need_redraw = 1;
587 		return V_EVENT_HANDLED_REDRAW;
588 	}
589 
590 	return V_EVENT_HANDLED_NOREDRAW;
591 }
592 
593 
handle_mousebuttonup_event(window * target,void * result,int mouse_x,int mouse_y,int button,int state)594 eventresult levelwin::handle_mousebuttonup_event(window* target, void* result,
595                                             int mouse_x, int mouse_y, int button, int state)
596 {
597 	point mouse, mappos;
598 
599 	mouse = vulture_get_mouse_pos();
600 	mappos = mouse_to_map(mouse);
601 
602 	return map_data->handle_click(result, button, mappos);
603 }
604 
605 
handle_keydown_event(window * target,void * result,int sym,int mod,int unicode)606 eventresult levelwin::handle_keydown_event(window* target, void* result, int sym, int mod, int unicode)
607 {
608 	int translated_key, key;
609 	int macronum, i;
610 
611 	switch (sym) {
612 		case SDLK_TAB:
613 			map::toggle();
614 			return V_EVENT_HANDLED_REDRAW;
615 
616 		/* F1- F6 trigger macros */
617 		case SDLK_F1:
618 		case SDLK_F2:
619 		case SDLK_F3:
620 		case SDLK_F4:
621 		case SDLK_F5:
622 		case SDLK_F6:
623 			macronum = sym - SDLK_F1;
624 			if (!vulture_opts.macro[macronum][0])
625 				break;
626 
627 			((vulture_event*)result)->num = vulture_opts.macro[macronum][0];
628 			for (i = strlen(vulture_opts.macro[macronum]) - 1; i > 0; i--)
629 				vulture_eventstack_add(vulture_opts.macro[macronum][i], -1, -1, V_RESPOND_ANY);
630 			return V_EVENT_HANDLED_FINAL;
631 
632 		/* CTRL+SHIFT+o opens the interface options */
633 		case SDLK_o:
634 			if (!(mod & KMOD_SHIFT) || !(mod & KMOD_CTRL))
635 				break;
636 			vulture_iface_opts();
637 			return V_EVENT_HANDLED_REDRAW;
638 
639 		/* CTRL+SHIFT+p shows the message log */
640 		case SDLK_p:
641 			if (!(mod & KMOD_SHIFT) || !(mod & KMOD_CTRL))
642 				break;
643 			msgwin->view_all();
644 			return V_EVENT_HANDLED_REDRAW;
645 
646 		default:
647 			break;
648 	}
649 
650 	/* all other keys are converted and passed to the core */
651 	key = vulture_make_nh_key(sym, mod, unicode);
652 
653 	if (!key)
654 		return V_EVENT_HANDLED_NOREDRAW;
655 
656 	if (mapwin && isdigit(key))
657 		translated_key = key;
658 	else
659 		translated_key = vulture_translate_key(key);
660 
661 	if (translated_key) {
662 		((vulture_event*)result)->num = translated_key;
663 		return V_EVENT_HANDLED_FINAL;
664 	}
665 	return V_EVENT_HANDLED_NOREDRAW;
666 }
667 
668 
handle_resize_event(window * target,void * result,int res_w,int res_h)669 eventresult levelwin::handle_resize_event(window* target, void* result, int res_w, int res_h)
670 {
671 	window *winelem;
672 
673 	if (this == target) {
674 		w = res_w;
675 		h = res_h;
676 
677 		/* update window scrolling activation regions */
678 		for (winelem = first_child; winelem; winelem = winelem->sib_next) {
679 			switch (winelem->menu_id) {
680 				/* case V_HOTSPOT_SCROLL_UPLEFT: never needs updating on resize*/
681 				case V_HOTSPOT_SCROLL_UP:
682 					winelem->w = w - 40;
683 					break;
684 
685 				case V_HOTSPOT_SCROLL_UPRIGHT:
686 					winelem->x = w - 20;
687 					break;
688 
689 				case V_HOTSPOT_SCROLL_LEFT:
690 					winelem->h = h - 40;
691 					break;
692 
693 				case V_HOTSPOT_SCROLL_RIGHT:
694 					winelem->h = h - 40;
695 					winelem->x = w - 20;
696 					break;
697 
698 				case V_HOTSPOT_SCROLL_DOWNLEFT:
699 					winelem->y = h - 20;
700 					break;
701 
702 				case V_HOTSPOT_SCROLL_DOWN:
703 					winelem->y = h - 20;
704 					winelem->w = w - 40;
705 					break;
706 
707 				case V_HOTSPOT_SCROLL_DOWNRIGHT:
708 					winelem->x = w - 20;
709 					winelem->y = h - 20;
710 					break;
711 			}
712 		}
713 	}
714 	return V_EVENT_HANDLED_NOREDRAW;
715 }
716 
717 
map_update(glyph_type type,int prev_glyph,int new_glyph,int x,int y)718 void levelwin::map_update(glyph_type type, int prev_glyph, int new_glyph, int x, int y)
719 {
720 	int pixel_x, pixel_y;
721 	int tl_x = 99999, tl_y = 99999, br_x = 0, br_y = 0;
722 	vulture_tile *oldtile, *newtile;
723 
724 	pixel_x = (this->w / 2) + V_MAP_XMOD*(x - y + view_y - view_x);
725 	pixel_y = (this->h / 2) + V_MAP_YMOD*(x + y - view_y - view_x);
726 
727 	if (pixel_x < -VULTURE_CLIPMARGIN ||
728 		pixel_y < -VULTURE_CLIPMARGIN ||
729 		pixel_x > vulture_screen->w + VULTURE_CLIPMARGIN ||
730 		pixel_y > vulture_screen->h + VULTURE_CLIPMARGIN)
731 		return;
732 
733 	oldtile = vulture_get_tile(prev_glyph);
734 	newtile = vulture_get_tile(new_glyph);
735 
736 	if (type != MAP_BACK) {
737 		if (oldtile) {
738 			tl_x = oldtile->xmod;
739 			tl_y = oldtile->ymod;
740 
741 			br_x = oldtile->xmod + oldtile->graphic->w;
742 			br_y = oldtile->ymod + oldtile->graphic->h;
743 		}
744 
745 		if (newtile) {
746 			tl_x = min(newtile->xmod, tl_x);
747 			tl_y = min(newtile->ymod, tl_y);
748 
749 			br_x = max(br_x, newtile->xmod + newtile->graphic->w);
750 			br_y = max(br_y, newtile->ymod + newtile->graphic->h);
751 		}
752 
753 		tl_x += pixel_x;
754 		tl_y += pixel_y;
755 		br_x += pixel_x;
756 		br_y += pixel_y;
757 
758 		if (type == MAP_MON)
759 			/* allow for the heart icon on pets */
760 			tl_y -= 10;
761 	}
762 	else {
763 		/* floor tiles tend to be placeholders until we reach draw_level,
764 			* so we do this manually */
765 		tl_x = pixel_x - 56;
766 		tl_y = pixel_y - 100; /* 100 pixels accounts for possible walls, too */
767 		br_x = pixel_x + 56;
768 		br_y = pixel_y + 22;
769 	}
770 
771 	add_to_clipregion(tl_x, tl_y, br_x, br_y);
772 }
773 
774 
map_clear()775 void levelwin::map_clear()
776 {
777 	int i, j;
778 
779 	for (i = 0; i < ROWNO; i++)
780 		for (j = 0; j < COLNO; j++) {
781 			clear_floor_edges(i, j);
782 			clear_walls(i, j);
783 		}
784 }
785 
mouse_to_map(point mouse)786 point levelwin::mouse_to_map(point mouse)
787 {
788 	point mappos, px_offset;
789 
790 	px_offset.x = mouse.x - (w / 2) + (view_x - view_y) * V_MAP_XMOD;
791 	px_offset.y = mouse.y - (h / 2) + (view_x + view_y)*V_MAP_YMOD;
792 
793 	mappos.x = ( V_MAP_YMOD * px_offset.x + V_MAP_XMOD * px_offset.y +
794 			V_MAP_XMOD*V_MAP_YMOD)/(2*V_MAP_XMOD*V_MAP_YMOD);
795 	mappos.y = (-V_MAP_YMOD * px_offset.x + V_MAP_XMOD * px_offset.y +
796 			V_MAP_XMOD*V_MAP_YMOD)/(2*V_MAP_XMOD*V_MAP_YMOD);
797 
798 	return mappos;
799 }
800 
801 
map_to_mouse(point mappos)802 point levelwin::map_to_mouse(point mappos)
803 {
804 	int map_centre_x = w / 2;
805 	int map_centre_y = h / 2;
806 	point mouse;
807 
808 	mouse.x = map_centre_x + V_MAP_XMOD*(mappos.x - mappos.y + view_y - view_x);
809 	mouse.y = map_centre_y + V_MAP_YMOD*(mappos.x + mappos.y - view_y - view_x);
810 
811 	/* FIXME Why does this happen sometimes ? */
812 	if ( mouse.x < 0 ) mouse.x = 0;
813 	if ( mouse.y < 0 ) mouse.y = 0;
814 
815 	return mouse;
816 }
817 
818 
toggle_uiwin(int menuid,bool enabled)819 void levelwin::toggle_uiwin(int menuid, bool enabled)
820 {
821 	window *win = this->first_child;
822 	while (win)
823 	{
824 		if (win->menu_id == menuid)
825 			win->visible = enabled;
826 		win = win->sib_next;
827 	}
828 
829 	force_redraw();
830 }
831 
832 
add_to_clipregion(int tl_x,int tl_y,int br_x,int br_y)833 void levelwin::add_to_clipregion(int tl_x, int tl_y, int br_x, int br_y)
834 {
835 	clip_tl_x = min(clip_tl_x, tl_x);
836 	clip_tl_y = min(clip_tl_y, tl_y);
837 	clip_br_x = max(clip_br_x, br_x);
838 	clip_br_y = max(clip_br_y, br_y);
839 }
840 
841 
set_wall_style(int style)842 void levelwin::set_wall_style(int style)
843 {
844 	switch (style)
845 	{
846 		case V_WALL_DISPLAY_STYLE_FULL:
847 			walltiles = (struct walls*)walls_full; break;
848 		case V_WALL_DISPLAY_STYLE_HALF_HEIGHT:
849 			walltiles = (struct walls*)walls_half; break;
850 	}
851 }
852 
853 
854 /* get room index is only used to semi-randomly select room decorations
855 * therefore the number we return can be as bogus as we want, so long as
856 * it's consistently the same. Using the current depth will provide a bit of
857 * variety on the maze levels...*/
get_room_index(int x,int y)858 int levelwin::get_room_index(int x, int y)
859 {
860 	int rindex;
861 	if (nroom == 0) /* maze levels */
862 		return u.uz.dlevel;
863 
864 	if (In_mines(&u.uz)) /* The mines are a patchwork dungeon otherwise :( */
865 		return (u.uz.dlevel + nroom); /* cleverly prevent a repetitive sequence :P */
866 
867 	rindex = room_indices[y][x];
868 	if (!rindex)
869 		return (u.uz.dlevel + nroom);
870 
871 	return rindex;
872 }
873 
874 
875 
876 /*
877 * Convert wall tile index (ie. wall type) to an associated decoration style.
878 */
get_wall_decor(int floortype,int wally,int wallx,int floory,int floorx)879 int levelwin::get_wall_decor(
880 	int floortype,
881 	int wally, int wallx,
882 	int floory, int floorx
883 )
884 {
885 	int roomid;
886 
887 #ifdef REINCARNATION
888 	if (Is_rogue_level(&u.uz))
889 		return V_WALL_LIGHT;
890 #endif
891 
892 	switch (floortype)
893 	{
894 		case V_TILE_FLOOR_ROUGH:
895 		case V_TILE_FLOOR_ROUGH_LIT:
896 			return V_WALL_ROUGH;
897 		case V_MISC_FLOOR_NOT_VISIBLE:
898 		case V_TILE_FLOOR_COBBLESTONE:
899 		{
900 			roomid = get_room_index(floorx, floory);
901 			switch(roomid % 4)
902 			{
903 				case 0: return V_WALL_STUCCO;
904 				case 1: return V_WALL_BRICK + ((wally*wallx+wally+wallx)%5);
905 				case 2: return V_WALL_VINE_COVERED;
906 				case 3: return V_WALL_MARBLE;
907 			}
908 		}
909 		default:
910 			return V_WALL_BRICK;
911 	}
912 }
913 
914 
915 /*
916 * Convert floor tile index (ie. floor type) to an associated decoration style.
917 */
get_floor_decor(int floorstyle,int floory,int floorx)918 int levelwin::get_floor_decor(int floorstyle, int floory, int floorx)
919 {
920 	int roomid;
921 #ifdef REINCARNATION
922 	if (Is_rogue_level(&u.uz))
923 		return V_FLOOR_DARK;
924 #endif
925 
926 	switch (floorstyle)
927 	{
928 		case V_TILE_FLOOR_ROUGH:     return V_FLOOR_ROUGH;
929 		case V_TILE_FLOOR_ROUGH_LIT: return V_FLOOR_ROUGH_LIT;
930 		case V_TILE_FLOOR_COBBLESTONE:
931 		{
932 			roomid = get_room_index(floorx, floory);
933 			switch(roomid % 4)
934 			{
935 				case 0: return V_FLOOR_CERAMIC;
936 				case 1: return V_FLOOR_COBBLESTONE;
937 				case 2: return V_FLOOR_MOSS_COVERED;
938 				case 3: return V_FLOOR_MARBLE;
939 			}
940 		}
941 		case V_TILE_FLOOR_WATER:     return V_FLOOR_WATER;
942 		case V_TILE_FLOOR_ICE:       return V_FLOOR_ICE;
943 		case V_TILE_FLOOR_AIR:       return V_FLOOR_AIR;
944 		case V_TILE_FLOOR_LAVA:      return V_FLOOR_LAVA;
945 		case V_TILE_FLOOR_DARK:      return V_FLOOR_DARK;
946 		default:                     return V_FLOOR_COBBLESTONE;
947 	}
948 }
949 
950 
951 
init_floor_decors(int num_decors)952 void levelwin::init_floor_decors(int num_decors)
953 {
954 	int i, j, k;
955 	int lx, ly;
956 
957 	if (!nroom)
958 		return; /* the level doesn't have distinct rooms, so do nothing */
959 
960 	/* after putting a decor in room roomno, we calculate (roomno + 5) modulo nroom.
961 	* (nroom is the global containing the number of rooms on the level) */
962 	int roomno = 0;
963 	/* when roomno wraps we also add wrapadd, to ensure that a different bunch of rooms gets the next few decorations
964 	* this will distibute decorations seemingly at random but repeatably throughout the level
965 	* (rooms are sorted from left to right, so a step of 1 would leave most decorations on the left side)*/
966 	int wrapadd = (nroom % 5) ? 0 : 1;
967 
968 	/* if placing a decor fails, try at most retries other rooms */
969 	int retries;
970 
971 	/* did we manage to place the deco?  */
972 	int placed;
973 
974 	int old_deco, old_deco2;
975 	int deco_height;
976 	int deco_width;
977 	int xoffset, yoffset;
978 
979 	int current_deco = V_FLOOR_CARPET;
980 
981 	/* reset the room indices and map decor arrays */
982 	for (i = 0; i < ROWNO; i++)
983 	{
984 		memset(room_indices[i], 0, COLNO);
985 		memset(map_deco[i], 0, COLNO);
986 	}
987 
988 	/* init room indices */
989 	for (i = 0; i < nroom; i++)
990 		for (j = rooms[i].ly; j <= rooms[i].hy; j++)
991 			memset(&room_indices[j][rooms[i].lx], (i+1), (rooms[i].hx-rooms[i].lx+1));
992 
993 	/* do no more if we're on the rogue level or in the mines, because decors there look dumb */
994 #ifdef REINCARNATION
995 	if (Is_rogue_level(&u.uz))
996 		return;
997 #endif
998 	s_level * lev;
999 	if (In_mines(&u.uz) && ((lev = Is_special(&u.uz)) == 0 || !lev->flags.town))
1000 		return;
1001 
1002 	for (i = 0; i < num_decors; i++)
1003 	{
1004 		retries = nroom;
1005 		placed = 0;
1006 		switch (roomno % 3)
1007 		{
1008 			case 0: current_deco = V_FLOOR_CARPET; break;
1009 			case 1: current_deco = V_FLOOR_MURAL; break;
1010 			case 2: current_deco = V_FLOOR_MURAL2; break;
1011 		}
1012 
1013 		deco_width = floorstyles[current_deco].x;
1014 		deco_height = floorstyles[current_deco].y;
1015 
1016 		while (retries-- && !placed)
1017 		{
1018 			lx = rooms[roomno].lx;
1019 			ly = rooms[roomno].ly;
1020 			while (ly <= rooms[roomno].hy && (old_deco = (map_deco[ly][lx] >> 4)) != 0)
1021 			{
1022 				while (lx <= rooms[roomno].hx && (old_deco2 = (map_deco[ly][lx] >> 4)) != 0)
1023 					lx += floorstyles[old_deco2-1].x;
1024 				ly += floorstyles[old_deco-1].y;
1025 				lx = rooms[roomno].lx;
1026 			}
1027 
1028 			if ((rooms[roomno].hx - lx + 1) >= deco_width &&
1029 				(rooms[roomno].hy - ly + 1) >= deco_height)
1030 			{
1031 				placed = 1;
1032 				for (j=0; j<deco_height; j++)
1033 					for (k=0; k<deco_width;k++)
1034 						map_deco[ly+j][lx+k] = ((current_deco+1) << 4) + (j*deco_width+k);
1035 			}
1036 		}
1037 
1038 		if (!retries && !placed)
1039 			/* placing this one failed, so trying to place others is futile  */
1040 			break;
1041 
1042 		roomno += 5;
1043 		if (roomno > nroom)
1044 			roomno = (roomno % nroom) + wrapadd;
1045 	}
1046 
1047 	/* centre the decorations in the rooms, as the previous code always plces them in the top corner*/
1048 	for (i = 0; i < nroom; i++)
1049 	{
1050 		lx = rooms[i].lx;
1051 		ly = rooms[i].ly;
1052 
1053 		while (map_deco[ly][lx] != 0 && lx <= rooms[i].hx)
1054 			lx++;
1055 
1056 		deco_width = lx - rooms[i].lx;
1057 		lx = rooms[i].lx;
1058 
1059 		while (map_deco[ly][lx] != 0 && ly <= rooms[i].hy)
1060 			ly++;
1061 
1062 		deco_height = ly - rooms[i].ly;
1063 		xoffset = (int)((rooms[i].lx + rooms[i].hx + 1)/2.0 - deco_width/2.0);
1064 		yoffset = (int)((rooms[i].ly + rooms[i].hy + 1)/2.0 - deco_height/2.0);
1065 
1066 		for (j = deco_height-1; j >= 0; j--)
1067 			for (k = deco_width-1; k >= 0; k--)
1068 				map_deco[yoffset + j][xoffset + k] = map_deco[rooms[i].ly + j][rooms[i].lx + k];
1069 
1070 		for (j = rooms[i].ly; j < yoffset; j++)
1071 			memset(&map_deco[j][rooms[i].lx], 0, (rooms[i].hx-rooms[i].lx+1));
1072 
1073 		for (j = rooms[i].ly; j <= rooms[i].hy; j++)
1074 			memset(&map_deco[j][rooms[i].lx], 0, (xoffset - rooms[i].lx));
1075 	}
1076 }
1077 
1078 
get_wall_tiles(int y,int x)1079 void levelwin::get_wall_tiles(int y, int x)
1080 {
1081 	int style;
1082 	int bg_west, bg_north, bg_east, bg_south;
1083 
1084 	if (!level.locations[x][y].seenv)
1085 		return;
1086 
1087 	/* x - 1: west wall  */
1088 	bg_west = map_data->get_glyph(MAP_BACK, x - 1, y);
1089 	if (x > 0 && bg_west != V_TILE_WALL_GENERIC && bg_west != V_MISC_UNMAPPED_AREA) {
1090 		style = get_wall_decor(bg_west, y, x, y, x-1);
1091 		maptile_wall[y][x].west = walltiles[style].west;
1092 	}
1093 	else
1094 		maptile_wall[y][x].west = V_TILE_NONE;
1095 
1096 	/* y - 1: north wall  */
1097 	bg_north = map_data->get_glyph(MAP_BACK, x, y - 1);
1098 	if (y > 0 && bg_north != V_TILE_WALL_GENERIC && bg_north != V_MISC_UNMAPPED_AREA) {
1099 		style = get_wall_decor(bg_north, y, x, y - 1, x);
1100 		maptile_wall[y][x].north = walltiles[style].north;
1101 	}
1102 	else
1103 		maptile_wall[y][x].north = V_TILE_NONE;
1104 
1105 	/* x + 1: east wall  */
1106 	bg_east = map_data->get_glyph(MAP_BACK, x + 1, y);
1107 	if (x < COLNO - 1 && bg_east != V_TILE_WALL_GENERIC && bg_east != V_MISC_UNMAPPED_AREA) {
1108 		style = get_wall_decor(bg_east, y, x, y, x + 1);
1109 		maptile_wall[y][x].east = walltiles[style].east;
1110 	}
1111 	else
1112 		maptile_wall[y][x].east = V_TILE_NONE;
1113 
1114 	/* y + 1: south wall  */
1115 	bg_south = map_data->get_glyph(MAP_BACK, x, y + 1);
1116 	if (y < ROWNO - 1 && bg_south != V_TILE_WALL_GENERIC && bg_south != V_MISC_UNMAPPED_AREA) {
1117 		style = get_wall_decor(bg_south, y, x, y + 1, x);
1118 		maptile_wall[y][x].south = walltiles[style].south;
1119 	}
1120 	else
1121 		maptile_wall[y][x].south = V_TILE_NONE;
1122 }
1123 
1124 
1125 
get_floor_tile(int tile,int y,int x)1126 int levelwin::get_floor_tile(int tile, int y, int x)
1127 {
1128 	int style;
1129 	int deco_pos;
1130 	unsigned char deco = map_deco[y][x];
1131 
1132 	if (deco && tile == V_TILE_FLOOR_COBBLESTONE) {
1133 		style = (deco >> 4) - 1;
1134 		deco_pos = (int)(deco & 0x0F);
1135 		return floorstyles[style].array[deco_pos];
1136 	}
1137 
1138 	style = get_floor_decor(tile, y, x);
1139 	deco_pos = floorstyles[style].x * (y % floorstyles[style].y) + (x % floorstyles[style].x);
1140 	return floorstyles[style].array[deco_pos];
1141 }
1142 
1143 
1144 
get_floor_edges(int y,int x)1145 void levelwin::get_floor_edges(int y, int x)
1146 {
1147 	int i, x2, y2;
1148 	int tile = map_data->get_glyph(MAP_BACK, x, y);
1149 	int style = V_FLOOR_EDGE_COBBLESTONE;
1150 
1151 	point s_delta[4] = {{-1,0}, {0,-1}, {1,0}, {0,1}};
1152 	point d_delta[4] = {{-1,1}, {-1,-1}, {1,-1}, {1,1}};
1153 
1154 	/* Default: no floor edges around tile */
1155 	clear_floor_edges(y, x);
1156 
1157 	/* straight sections */
1158 	for (i = 0; i < 4; i++) {
1159 		x2 = x+s_delta[i].x;
1160 		y2 = y+s_delta[i].y;
1161 		if (x > 0 && x < COLNO-s_delta[i].x && y > 0 && y < ROWNO-s_delta[i].y &&
1162 			tile != map_data->get_glyph(MAP_BACK, x2, y2) &&
1163 			tile + map_data->get_glyph(MAP_BACK, x2, y2) !=
1164 			V_TILE_FLOOR_WATER + V_TILE_FLOOR_ICE) /* this prevents borders between water and ice*/
1165 				maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i];
1166 	}
1167 
1168 
1169 	/* "inward pointing" corners */
1170 	for (i = 4; i < 8; i++) {
1171 		if ((maptile_floor_edge[y][x].dir[(i+3)%4] != V_TILE_NONE) &&
1172 			(maptile_floor_edge[y][x].dir[i%4]) != V_TILE_NONE)
1173 
1174 			maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i];
1175 	}
1176 
1177 
1178 	/* "outward pointing" corners */
1179 	for (i = 8; i < 12; i++) {
1180 		x2 = x+d_delta[i%4].x;
1181 		y2 = y+d_delta[i%4].y;
1182 		if ((maptile_floor_edge[y][x].dir[(i+3)%4] == V_TILE_NONE) &&
1183 			(maptile_floor_edge[y][x].dir[i%4] == V_TILE_NONE) &&
1184 			x > 0 && x < COLNO - 1 && y > 0 && y < ROWNO - 1 &&
1185 			tile != map_data->get_glyph(MAP_BACK, x2, y2) &&
1186 			tile + map_data->get_glyph(MAP_BACK, x2, y2) !=
1187 			V_TILE_FLOOR_WATER + V_TILE_FLOOR_ICE)
1188 			maptile_floor_edge[y][x].dir[i] = flooredges[style].dir[i];
1189 	}
1190 
1191 /*    for (i = 0; i < 12; i++)
1192 		if (!maptile_floor_edge[y][x].dir[i])
1193 			maptile_floor_edge[y][x].dir[i] = V_TILE_NONE;*/
1194 }
1195 
clear_walls(int y,int x)1196 void levelwin::clear_walls(int y, int x)
1197 {
1198 	maptile_wall[y][x].west = V_TILE_NONE;
1199 	maptile_wall[y][x].north = V_TILE_NONE;
1200 	maptile_wall[y][x].east = V_TILE_NONE;
1201 	maptile_wall[y][x].south = V_TILE_NONE;
1202 }
1203 
1204 
1205 
clear_floor_edges(int y,int x)1206 void levelwin::clear_floor_edges(int y, int x)
1207 {
1208 	int i;
1209 	for (i = 0; i < 12; i++)
1210 		maptile_floor_edge[y][x].dir[i] = V_TILE_NONE;
1211 }
1212 
1213 
1214 /* select an appropriate cursor for the given location */
get_map_cursor(point mappos)1215 int levelwin::get_map_cursor(point mappos)
1216 {
1217 	if ((mappos.x < 1) || (mappos.x >= COLNO) ||
1218 		(mappos.y < 0) || (mappos.y >= ROWNO))
1219 		return V_CURSOR_TARGET_INVALID;
1220 
1221 	/* whatis: look or teleport */
1222 	if (vulture_whatis_active)
1223 		return V_CURSOR_TARGET_HELP;
1224 
1225 	/* monsters and objects get a red circle */
1226 	if (map_data->get_glyph(MAP_MON, mappos.x, mappos.y) != V_TILE_NONE &&
1227 		((mappos.x != u.ux) || (mappos.y != u.uy)))
1228 		return V_CURSOR_TARGET_RED;
1229 
1230 	if (map_data->get_glyph(MAP_OBJ, mappos.x, mappos.y) != V_TILE_NONE)
1231 		return V_CURSOR_TARGET_RED;
1232 
1233 	/* other valid visible locations  */
1234 	if (map_data->get_glyph(MAP_BACK, mappos.x, mappos.y) != V_TILE_NONE) {
1235 		int furniture = map_data->get_glyph(MAP_FURNITURE, mappos.x, mappos.y);
1236 		/* Closed doors get an 'open door' cursor */
1237 		if ((furniture == V_MISC_VDOOR_WOOD_CLOSED) ||
1238 			(furniture == V_MISC_HDOOR_WOOD_CLOSED))
1239 			return V_CURSOR_OPENDOOR;
1240 
1241 		/* Stairs and ladders get a 'stairs' cursor */
1242 		if ((furniture == V_MISC_STAIRS_UP) || (furniture == V_MISC_STAIRS_DOWN) ||
1243 			(furniture == V_MISC_LADDER_UP) || (furniture == V_MISC_LADDER_DOWN))
1244 			return V_CURSOR_STAIRS;
1245 
1246 		/* Fountains get a 'goblet' cursor */
1247 		if (furniture == V_MISC_FOUNTAIN)
1248 			return V_CURSOR_GOBLET;
1249 
1250 		if (map_data->get_glyph(MAP_BACK, mappos.x, mappos.y) != V_TILE_WALL_GENERIC)
1251 			return V_CURSOR_TARGET_GREEN;
1252 	}
1253 
1254 	return V_CURSOR_TARGET_INVALID;
1255 }
1256 
1257