#include "empire.h"

enum maineditstate
{
	MFIRST,
	MLOAD,
	MNEW,
	MEDIT,
	MEXIT,
	MCHECK,
	MSAVE
};

enum editstate
{
	NORMAL,
	MAPCHECK,
	AIPROFILE,
	RESIZE,
	MOVETILES,
	NAMEMAP
};

extern volatile int counter;

void text_box(int x, int y, int w, int h, char *ret, int leng, int spaces, string title);

void refresh_maplist();
int any_unit_here(int tx, int ty);
int mapcolor(int set, int num);
string unit_name(int i);

void clear_all_units();;
void draw_selection(int set, int x);
void delete_map(string mapname);
void draw_minimap(int x, int y, string file);
void remove_previous_HQ(int player, int ignorex, int ignorey);
void map_message(string message);
void draw_trans_tile(int set, int num, int x, int y);
void move_tiles(int x1, int y1, int x2, int y2, int dx, int dy);
bool HQ_exists(int playernum);
bool base_exists(int playernum);
enum maineditstate mfirst();
enum maineditstate mload();
enum maineditstate mnew();
enum maineditstate medit();
enum maineditstate mcheck();
enum maineditstate save_map();
int datafile_size(DATAFILE *data);
enum editstate do_aiselect();
enum editstate moving_tiles();
enum editstate resize_map();
enum editstate name_map();
bitmapdat *set_datafile(int set);

float length;
float height;

extern int SIDEBAR_WIDTH, BOTTOMBAR_HEIGHT;

_button option[34];
_button selection[18];



void clear_all_units()
{
	player[0].reset();
	player[1].reset();
	player[2].reset();
	player[3].reset();
}

int mapedit()
{
	static bool first = true;
	static enum maineditstate status = MFIRST;
	if (first)
	{
		worldmap = _map(15, 15);
		clear_all_units();
		minimap.create();
		first = false;
	}
	switch(status)
	{
		case MFIRST:
			status = mfirst();
			break;
		case MLOAD:
			status = mload();
			break;
		case MNEW:
			status = mnew();
			break;
		case MEDIT:
			status = medit();
			break;
		case MCHECK:
			status = mcheck();
			break;
		case MSAVE:
			status = save_map();
			break;
		case MEXIT:
			status = MFIRST;
			return MENU;
			break;
	}
	return MAPEDIT;
}





enum maineditstate mfirst()
{
	static bool first = true;

	if (first)
	{
		const float xratio = float(global.screen_width) / 800.0;

		player[0].number = 0;
		player[1].number = 1;
		player[2].number = 2;
		player[3].number = 0;
		player[0].tintcolor = player_color(0, 0);
		player[1].tintcolor = player_color(1, 0);
		player[2].tintcolor = player_color(2, 0);
		player[3].tintcolor = player_color(0, 2);

		option[2].init(10,  global.screen_height - 30, 100, 20, "Back");

		option[0].init(int(230 * xratio), global.screen_height - 50, int(100 * xratio), 40, "New Map");
		option[1].init(int(340 * xratio), global.screen_height - 50, int(100 * xratio), 40, "Load Map");
		option[3].init(int(450 * xratio), global.screen_height - 50, int(100 * xratio), 40, "Continue Map");

		clear_particles();
		play_song(MENU_THEME);

		first = false;
	}

	glb.draw_fullscreen(13);
	option[0].check();
	option[1].check();
	option[2].check();
	option[3].check();
	draw_mouse();
	if (option[0].clicked())
	{
		clear_all_units();
		first = true;
		return MNEW;
	}
	if (option[1].clicked())
	{
		clear_all_units();
		first = true;
		return MLOAD;
	}
	if ((option[2].clicked()) || (key[KEY_ESC]))
	{
		worldmap.close();
		clear_all_units();
		first = true;
		play_song(TITLE_THEME);
		return MEXIT;
	}
	if (option[3].clicked())
	{
		first = true;
		return MEDIT;
	}
	return MFIRST;
}





enum maineditstate mload()
{
	static bool first = true;
	static _listbox mapbox;
	static int oldselection;

	string ainame;
	int sel;
	string s;

	const int minimapx = global.screen_width / 2 + 40;
	const int minimapy = (global.screen_height - 150) / 2;

	if (first)
	{
		const int mapbox_w = 300 * int(float(global.screen_width) / 800.0);
		const int mapbox_h = 400 * int(float(global.screen_height) / 600.0);

		refresh_maplist();

		mapbox.init(global.screen_width / 2 - 10 - mapbox_w, (global.screen_height - mapbox_h) / 2, mapbox_w, mapbox_h);
		for (unsigned int i = 0; i < maplist.size(); i++)
			mapbox.additem(maplist[i], false);

		option[0].init(10, global.screen_height - 30, 100, 20, "Back");
		option[1].init(minimapx + 70, mapbox.get_y() + mapbox_h - 17, 80, 17, "Delete Map");
		option[2].init(minimapx - 15, minimapy + 155, 180, 40, "Load Map");

		oldselection = -1;

		first = false;
	}

	glb.draw_fullscreen(13);
	buffer_rectrounded(mapbox.get_x() - 40, mapbox.get_y() - 40, minimapx + 190, mapbox.get_y() + mapbox.get_h() + 40, BLACK, 0.6, 15.0);
	mapbox.check();
	option[0].check();

	if (mapbox.size() == 0)
		buffer_textout_centre_ex(big, "No maps found", mapbox.get_x() + ((minimapx + 150 - mapbox.get_x()) / 2), mapbox.get_y() - 32, RED);

	sel = mapbox.getsel();
	if (sel != -1)
	{
		if (sel != oldselection)
		{
			stringstream path;

			path << "maps/";

			s = maplist[sel];
			s.erase(0, 5);  //get rid of the number of players

			path << s << ".map";

			draw_minimap(minimapx, minimapy, path.str());

			oldselection = sel;
		}
		else
		{
			minimap.draw(false, minimapx, minimapy, false, true);
		}
		option[1].check();
		option[2].check();

		if (option[1].clicked())
		{
			s = maplist[sel];
			s.erase(0, 5);
			delete_map(s);

			refresh_maplist();

			oldselection = -1;
			mapbox.setsel(-1);

			mapbox.clear();
			for (unsigned int i = 0; i < maplist.size(); i++)
				mapbox.additem(maplist[i], false);
		}

		if (option[2].clicked())
		{
			stringstream path;

			path << "maps/";

			s = maplist[sel];
			s.erase(0, 5);

			path << s << ".map";

			if (worldmap.load(path.str()))
			{
				s = maplist[sel];
				s.erase(0, 5); //get rid of the (2P) / (3P) / (4P)
				load_ai(s);

				for (int i = 0; i < 4; i++)
				{
					for (int j = 0; j < 50; j++)
					{
						if (player[i].unit[j].exists == 1)
							player[i].unit[j].ready = 1;
					}
				}

				first = true;
				return MEDIT;
			}
		}
	}

	if (option[0].clicked())
	{
		first = true;
		return MFIRST;
	}

	draw_mouse();
	return MLOAD;
}





enum maineditstate mnew()
{
	const float xratio = float(global.screen_width) / 800.0;
	const float yratio = float(global.screen_height) / 600.0;

	static bool first = true;
	int i;
	char msg[30];

	const int box_w = int(180 * xratio);
	const int box_h = int(170 * yratio);
	const int box_x = (global.screen_width / 2) - (box_w / 2);
	const int box_y = (global.screen_height / 2) - (box_h / 2);

	if (first)
	{
		const int optionw = int(40 * xratio);
		const int optionh = int(15 * xratio);

		length = (XTILES <= MAP_MAX_L) ? XTILES : MAP_MAX_L;
		height = (YTILES <= MAP_MAX_H) ? YTILES : MAP_MAX_H;

		option[0].init(int(box_x + (box_w / 2) - 55 * xratio), int(box_y + 30 * yratio), optionw, optionh, "+");
		option[1].init(int(box_x + (box_w / 2) - 55 * xratio), int(box_y + 65 * yratio), optionw, optionh, "-");
		option[2].init(int(box_x + (box_w / 2) + 15 * xratio), int(box_y + 30 * yratio), optionw, optionh, "+");
		option[3].init(int(box_x + (box_w / 2) + 15 * xratio), int(box_y + 65 * yratio), optionw, optionh, "-");
		option[4].init(int(box_x + 10 * xratio), int(box_y + box_h - 65 * yratio), int(box_w - 20 * xratio), int(20 * yratio), "Create New");
		option[5].init(int(box_x + 10 * xratio), int(box_y + box_h - 30 * yratio), int(box_w - 20 * xratio), int(20 * yratio), "Cancel");

		first = false;
	}

	glb.draw_fullscreen(13);

	buffer_rectfill(box_x, box_y, box_x + box_w, box_y + box_h, GREY, 0.8);
	buffer_rect(box_x, box_y, box_x + box_w, box_y + box_h, WHITE, 0.8);
	buffer_textout_centre_ex(big, "Map Size", global.screen_width / 2, box_y, BLACK);

	sprintf(msg, "%-1d", int(length));
	buffer_textout_centre_ex(big, msg, int(box_x + (box_w / 2) - 35 * xratio), box_y + int(45 * yratio), BLACK);
	sprintf(msg, "%-1d", int(height));
	buffer_textout_centre_ex(big, msg, int(box_x + (box_w / 2) + 35 * xratio), box_y + int(45 * yratio), BLACK);

	buffer_textout_centre_ex(big, "x", box_x + (box_w / 2), box_y + int(45 * yratio), BLACK);

	i = 0;
	while (i < 6)
	{
		option[i].check();
		i++;
	}
	if (option[0].mousedown() == 1)
	{
		if (length < MAP_MAX_L)
		{
			length += .25;
		}
	}
	if (option[1].mousedown() == 1)
	{
		if (length > XMIN)
		{
			length -=.25;
		}
		else
		{
			length = XMIN;
		}
	}
	if (option[2].mousedown() == 1)
	{
		if (height < MAP_MAX_H)
		{
			height += .25;
		}
	}
	if (option[3].mousedown() == 1)
	{
		if (height > YMIN)
		{
			height -=.25;
		}
		else
		{
			height = YMIN;
		}
	}
	if (option[4].clicked())
	{
		worldmap = _map(int(length), int(height));

		clear_all_units();
		player[0].tintcolor = player_color(0, 0);
		player[1].tintcolor = player_color(1, 0);
		player[2].tintcolor = player_color(2, 0);
		player[3].tintcolor = player_color(0, 2);

		minimap.create();

		first = true;
		return MEDIT;
	}
	if (option[5].clicked())
	{
		first = true;
		load_default_ai();
		return MFIRST;
	}

	draw_mouse();
	return MNEW;
}





enum maineditstate medit()
{
	const int SCROLL_CONSTANT = 8;
	const int leftx = global.screen_width - SIDEBAR_WIDTH;
	const int minimapx = leftx + 5;
	const int minimapy = 447;

	char msg[30];
	static bool first = true;
	static enum editstate state;
	static int selected = -1;
	static int set = 0;
	static int owner = -1;
	static int page;
	static int offsetx, offsety;
	int mx = mouse_x;
	int my = mouse_y;

	if (first)
	{
		const int bottombutton_y = global.screen_height - BOTTOMBAR_HEIGHT + 5;
		const int bottombutton_h = BOTTOMBAR_HEIGHT - 8;

		option[0].init(leftx + 10, 256, 60, 20, "<");
		option[1].init(leftx + 90, 256, 60, 20, ">");
		option[20].init(leftx + 5, 300, 150, 15, "Land");
		option[21].init(leftx + 5, 320, 150, 15, "River");
		option[22].init(leftx + 5, 340, 150, 15, "Sea");
		option[29].init(leftx + 5, 360, 150, 15, "Shoal");
		option[26].init(leftx + 5, 380, 150, 15, "Buildings");
		option[33].init(leftx + 5, 400, 150, 15, "Special");
		option[27].init(leftx + 5, 420, 150, 15, "Units");
		option[25].init(5, bottombutton_y, 70, bottombutton_h, "Back");
		option[28].init(110, bottombutton_y, 70, bottombutton_h, "Check");
		option[30].init(185, bottombutton_y, 70, bottombutton_h, "AI");
		option[31].init(290, bottombutton_y, 70, bottombutton_h, "Resize");
		option[32].init(365, bottombutton_y, 70, bottombutton_h, "Copy Tiles");
		option[24].init(470, bottombutton_y, 80, bottombutton_h, "Name");
		option[23].init(555, bottombutton_y, 80, bottombutton_h, "Save");

		worldmap.camera.jump_to((worldmap.get_length() - XTILES) / 2, (worldmap.get_height() - YTILES) / 2);

		set = 0;
		page = 0;
		owner = -1;
		selected = -1;
		offsetx = 0;
		offsety = 0;

		draw_selection(set, page);

		first = false;
	}

	worldmap.draw();

	//draw a grid
	for (int i = 0; i < XTILES; i++)
		buffer_vline(i * MAP_TILE_SIZE, 0, YTILES * MAP_TILE_SIZE, WHITE, 0.5);
	for (int i = 0; i < YTILES; i++)
		buffer_hline(0, i * MAP_TILE_SIZE, leftx, WHITE, 0.5);

	//draw the borders of the menu bars
	buffer_rectfill(0, YTILES * MAP_TILE_SIZE, leftx, global.screen_height, BLACK);
	buffer_rectfill(0, global.screen_height - BOTTOMBAR_HEIGHT, leftx, global.screen_height, BLACK);
	buffer_rectfill_gradient(0, global.screen_height - BOTTOMBAR_HEIGHT, leftx, global.screen_height - BOTTOMBAR_HEIGHT + 3, WHITE, WHITE, VDGREY, VDGREY);
	buffer_rectfill_gradient(leftx, 0, leftx + 3, global.screen_height, WHITE, DGREY, BLACK, WHITE);
	buffer_rectfill_gradient(leftx + 3, 0, global.screen_width, global.screen_height, GREY, GREY, DGREY, DGREY);

	if (!(mouse_b & 1) && (state != NAMEMAP))
	{  //the screen can't scroll while the mouse button is down
		const int scrollx = worldmap.camera.get_scroll_x();
		const int scrolly = worldmap.camera.get_scroll_y();

		if (key[KEY_LEFT])
		{
			offsetx += SCROLL_CONSTANT;  //we don't want smooth scrolling in the map editor
			if (offsetx > MAP_TILE_SIZE)
			{
				offsetx = 0;
				worldmap.camera.jump_to(scrollx - 1, scrolly);
			}
		}
		if (key[KEY_RIGHT])
		{
			offsetx -= SCROLL_CONSTANT;
			if (offsetx < -MAP_TILE_SIZE)
			{
				offsetx = 0;
				worldmap.camera.jump_to(scrollx + 1, scrolly);
			}
		}

		if (key[KEY_DOWN])
		{
			offsety -= SCROLL_CONSTANT;
			if (offsety < -MAP_TILE_SIZE)
			{
				offsety = 0;
				worldmap.camera.jump_to(scrollx, scrolly + 1);
			}
		}
		if (key[KEY_UP])
		{
			offsety += SCROLL_CONSTANT;
			if (offsety > MAP_TILE_SIZE)
			{
				offsety = 0;
				worldmap.camera.jump_to(scrollx, scrolly - 1);
			}
		}
	}  //scrolling needs to come before the state check, since the map needs to be able to scroll during stuff like tile copying
	//but NOT for naming the map, because we use the arrow keys there for the text box

	switch(state)
	{
		default:
		case NORMAL:
			break;
		case MAPCHECK:
			state = NORMAL;
			return MCHECK;
			break;
		case AIPROFILE:
			state = do_aiselect();
			break;
		case RESIZE:
			state = resize_map();
			break;
		case MOVETILES:
			state = moving_tiles();
			break;
		case NAMEMAP:
			state = name_map();
			break;
	}

	if (state != NORMAL)
	{
		do_particles();
		draw_mouse();
		return MEDIT;
	}

	buffer_textout_right_ex(normal, "Left mouse: Lay Tile [+Ctrl: Remove Unit]", leftx - 5, 5, WHITE);
	option[20].check();
	option[21].check();
	option[22].check();
	option[23].check();
	option[24].check();
	option[25].check();
	option[26].check();
	option[27].check();
	option[28].check();
	option[29].check();
	option[30].check();
	option[31].check();
	option[32].check();
	option[33].check();

	if (option[28].clicked())
	{  //check map
		first = true;
		return MCHECK;
	}
	if (option[25].clicked())
	{  //back
		first = true;
		return MFIRST;
	}

	if (option[23].clicked())
	{  //save map
		return MSAVE;
	}

	if (option[24].clicked())
	{  //name map
		state = NAMEMAP;
		return MEDIT;
	}

	if (option[30].clicked())
	{  //select AI profile
		state = AIPROFILE;
		return MEDIT;
	}
	if (option[31].clicked())
	{
		state = RESIZE;
		return MEDIT;
	}
	if (option[32].clicked())
	{
		state = MOVETILES;
		return MEDIT;
	}

	if (option[20].clicked())
	{  //switch to the land tiles
		set = 0;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[21].clicked())
	{  //switch to the river tiles
		set = 1;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[22].clicked())
	{  //switch to the sea tiles
		set = 2;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[29].clicked())
	{  //switch to the shoal tiles
		set = 3;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[26].clicked())
	{  //switch to the building tiles
		set = 4;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[33].clicked())
	{  //switch to the special tiles
		set = 6;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}
	if (option[27].clicked())
	{  //switch to unit placement
		set = 5;
		page = 0;
		selected = -1;
		draw_selection(set, 0);
	}

	option[0].check();
	option[1].check();
	if (option[0].clicked())
	{  //previous page
		if (page > 0)
		{
			page--;
			draw_selection(set, page * 18);
		}
	}
	if (option[1].clicked())
	{  //next page
		int maxitems = 0;

		if (set != 5)  //if it's not the mapunits set (which isn't a bitmapdat)
		{
			if (set == 4)
			{
				maxitems = set_datafile(set)->size * 4;
			}
			else maxitems = set_datafile(set)->size;
		}
		else
		{
			maxitems = NUM_UNITS * 4;
		}

		if ((page + 1) * 18 < maxitems)
		{
			page++;
			draw_selection(set, page * 18);
		}
	}

	for (int i = 0; i < 18; i++)
	{
		selection[i].check();
		if ((set == 4) && (i + page * 18 < buildings.size * 5 - 1))  //buildings
		{
			int team = -1;
			int building = 0;

			buffer_draw_sprite(land.bmp(3), selection[i].x, selection[i].y);

			if ((page == 0) && (i < 4))
			{
				team = i;
			}
			else
			{
				team = ((i + page * 18) - 4) % 5 - 1;
			}

			building = i + page * 18;
			if (building < 4)
			{
				building = 0;  //set to HQ
			}
			else
			{
				building -= 4;  //minus the HQs
				building /= 5;  //5 ownership types per building
				building++;  //offset by one to account for the HQs
			}

			switch(team)
			{
				case -1:
					buffer_draw_sprite(buildings.bmp(building), selection[i].x, selection[i].y);
					break;
				case 0:
					buffer_draw_tinted_sprite(buildings.bmp(building), selection[i].x, selection[i].y, ol::Rgba(RED, 150));
					break;
				case 1:
					buffer_draw_tinted_sprite(buildings.bmp(building), selection[i].x, selection[i].y, ol::Rgba(BLUE, 150));
					break;
				case 2:
					buffer_draw_tinted_sprite(buildings.bmp(building), selection[i].x, selection[i].y, ol::Rgba(MGREEN, 150));
					break;
				case 3:
					buffer_draw_tinted_sprite(buildings.bmp(building), selection[i].x, selection[i].y, ol::Rgba(DYELLOW, 150));
					break;
			}
		}
		else if ((set == 5) && (i + page * 18 < NUM_UNITS * 4))
		{
			switch((i + page * 18) % 4)
			{
				case 0:
					buffer_draw_tinted_sprite(units[(i + page * 18) / 4].bmp(0), selection[i].x, selection[i].y, ol::Rgba(RED, 150));
					break;
				case 1:
					buffer_draw_tinted_sprite(units[(i + page * 18) / 4].bmp(0), selection[i].x, selection[i].y, ol::Rgba(BLUE, 150));
					break;
				case 2:
					buffer_draw_tinted_sprite(units[(i + page * 18) / 4].bmp(0), selection[i].x, selection[i].y, ol::Rgba(MGREEN, 150));
					break;
				case 3:
					buffer_draw_tinted_sprite(units[(i + page * 18) / 4].bmp(0), selection[i].x, selection[i].y, ol::Rgba(DYELLOW, 150));
					break;
			}
		}
		if (selection[i].mousedown())  //not clicked() anymore, was a bit annoying
		{
			if (set == 4)
			{
				if (i + page * 18 < 4)
				{
					selected = 0;
					owner = i;
				}
				else
				{
					selected = ((i + page * 18) - 4) / 5 + 1;
					owner = ((i + page * 18) - 4) % 5 - 1;
				}
			}
			else
			{
				selected = i + page * 18;
			}
		}
	}

	if ((selected != -1) && (my < MAP_TILE_SIZE * YTILES) && (mx < leftx))
	{
		if (set != 5)  //if it's a tile that's selected, not a unit
		{  //give a translucent preview of the tile under the mouse
			if (set == 4)
			{
				switch(owner)
				{
					case -1:
						buffer_draw_sprite(buildings.bmp(selected), mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2, .75);
						break;
					case 0:
						buffer_draw_tinted_sprite(buildings.bmp(selected), mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2, ol::Rgba(RED, 150), .75);
						break;
					case 1:
						buffer_draw_tinted_sprite(buildings.bmp(selected), mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2, ol::Rgba(BLUE, 150), .75);
						break;
					case 2:
						buffer_draw_tinted_sprite(buildings.bmp(selected), mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2, ol::Rgba(MGREEN, 150), .75);
						break;
					case 3:
						buffer_draw_tinted_sprite(buildings.bmp(selected), mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2, ol::Rgba(DYELLOW, 150), .75);
						break;
				}
			}
			else
			{
				draw_trans_tile(set, selected, mx - MAP_TILE_SIZE / 2, my - MAP_TILE_SIZE / 2);
			}
		}
	}

	if ((mouse_b & 1) && (my < global.screen_height - BOTTOMBAR_HEIGHT) && (mx < leftx))
	{  //place a tile/unit on the map if the mouse is pressed or remove a unit
		_tile *tile = worldmap.get_mouseover_tile(mx, my);

		if (tile == 0) {} //don't do anything if the mouse is clicked and not over a tile
		else
		{
			if ((key[KEY_LCONTROL]) || (key[KEY_RCONTROL]))
			{  //if the mouse clicks while holding ctrl, remove the unit the mouse is on
				_unit *u = tile->unit_here_ptr();

				if (u != 0)
				{  //can't just use u->kill(), it expects the explosion code to clean up afterwards
					u->health = 0;
					u->exists = 0;
					tile->set_unit(-1, -1);
				}
			}
			else if (selected != -1)
			{
				if (set != 5)  //if it's tiles, not units being placed
				{
					if ((!tile->same_type(set, selected)) || ((set == 4) && (tile->get_owner() != owner)))
					{   //from the tile to be placed
						if (set == 4)
						{
							if (selected == 0)
							{  //if it's an HQ being placed, remove previous HQ for that player
								remove_previous_HQ(owner, tile->x, tile->y);
							}
						}
						play_sound(S_TILEDOWN);
						tile->change_type(set, selected);
						tile->change_owner(owner);
						minimap.create();  //recreate the minimap when a tile is changed
					}
				}
				else if (tile->unit_here_ptr() == 0) //if a unit is being placed, and there's no unit here already
				{
					int newunit = player[selected % 4].create_unit(selected / 4, tile->x, tile->y, selected % 4);

					if (newunit != -1)
						player[selected % 4].unit[newunit].ready = 1;
				}
			}
		}
	}

	minimap.draw(true, minimapx, minimapy);
	if (mouse_b & 1)
	{  //center the map on the area of the minimap that was clicked
		int mm_mousex = (mouse_x - minimapx - ((150 - minimap.bmp->Width()) / 2)) / 3;
		int mm_mousey = (mouse_y - minimapy - ((150 - minimap.bmp->Height()) / 2)) / 3;

		if ((mm_mousex >= 0) && (mm_mousex < worldmap.get_length()))
		{
			if ((mm_mousey >= 0) && (mm_mousey < worldmap.get_height()))
			{
				worldmap.camera.jump_to(mm_mousex - XTILES / 2, mm_mousey - YTILES / 2);
			}
		}
	}

	_tile *tile = worldmap.get_mouseover_tile(mx, my);
	if (tile != 0)
	{  //show the mouse's tile coordinates
		sprintf(msg, "%-1d, %-1d", tile->x, tile->y);
		buffer_textout_ex(normal, msg, 5, 5, WHITE);
	}
	do_particles();
	draw_mouse();

	return MEDIT;
}




enum editstate resize_map()
{
	static bool first = true;
	static _button up[2], down[2], ok, cancel;
	char msg[30];

	const float xratio = float(global.screen_width) / 800.0;
	const float yratio = float(global.screen_height) / 600.0;
	const int box_w = int(180 * xratio);
	const int box_h = int(170 * yratio);
	const int box_x = (global.screen_width / 2) - (box_w / 2);
	const int box_y = (global.screen_height / 2) - (box_h / 2);

	if (first)
	{
		const int optionw = int(40 * xratio);
		const int optionh = int(15 * xratio);

		length = float(worldmap.get_length());
		height = float(worldmap.get_height());

		up[0].init(int(box_x + (box_w / 2) - 55 * xratio), int(box_y + 30 * yratio), optionw, optionh, "+");
		up[1].init(int(box_x + (box_w / 2) + 15 * xratio), int(box_y + 30 * yratio), optionw, optionh, "+");
		down[0].init(int(box_x + (box_w / 2) - 55 * xratio), int(box_y + 65 * yratio), optionw, optionh, "-");
		down[1].init(int(box_x + (box_w / 2) + 15 * xratio), int(box_y + 65 * yratio), optionw, optionh, "-");

		ok.init(int(box_x + 10 * xratio), int(box_y + box_h - 65 * yratio), int(box_w - 20 * xratio), int(20 * yratio), "Resize");
		cancel.init(int(box_x + 10 * xratio), int(box_y + box_h - 30 * yratio), int(box_w - 20 * xratio), int(20 * yratio), "Cancel");

		first = false;
	}

	buffer_rectfill(box_x, box_y, box_x + box_w, box_y + box_h, GREY, 0.8);
	buffer_rect(box_x, box_y, box_x + box_w, box_y + box_h, WHITE, 0.8);
	buffer_textout_centre_ex(big, "Map Size", global.screen_width / 2, box_y, BLACK);

	sprintf(msg, "%-1d", int(length));
	buffer_textout_centre_ex(big, msg, int(box_x + (box_w / 2) - 35 * xratio), box_y + int(45 * yratio), BLACK);
	sprintf(msg, "%-1d", int(height));
	buffer_textout_centre_ex(big, msg, int(box_x + (box_w / 2) + 35 * xratio), box_y + int(45 * yratio), BLACK);

	buffer_textout_centre_ex(big, "x", box_x + (box_w / 2), box_y + int(45 * yratio), BLACK);

	up[0].check();
	up[1].check();
	down[0].check();
	down[1].check();
	ok.check();
	cancel.check();

	if (up[0].mousedown() == 1)
	{
		if (length < MAP_MAX_L)
		{
			length += .25;
		}
	}
	if (down[0].mousedown() == 1)
	{
		if (length > XMIN)
		{
			length -=.25;
		}
		else
		{
			length = XMIN;
		}
	}
	if (up[1].mousedown() == 1)
	{
		if (height < MAP_MAX_H)
		{
			height += .25;
		}
	}
	if (down[1].mousedown() == 1)
	{
		if (height > YMIN)
		{
			height -=.25;
		}
		else
		{
			height = YMIN;
		}
	}

	if (ok.clicked())
	{
		first = true;
		worldmap.resize(int(length), int(height));
		minimap.create();
		return NORMAL;
	}
	if (cancel.clicked())
	{
		length = int(worldmap.get_length());
		height = int(worldmap.get_height());
		first = true;
		return NORMAL;
	}

	draw_mouse();
	return RESIZE;
}




enum editstate moving_tiles()
{
	const int leftx = global.screen_width - SIDEBAR_WIDTH;

	static int phase = 0;
	static _loc topleft, bottomright;
	int mx = mouse_x;
	int my = mouse_y;
	_tile *tile = worldmap.get_mouseover_tile(mx, my);

	if ((my >= global.screen_height - BOTTOMBAR_HEIGHT) || (mx >= leftx))
		tile = 0;

	if (mouse_rclicked())
	{
		phase = 0;
		return NORMAL;
	}

	switch(phase)
	{
		case 0:
			buffer_textout_right_ex(normal, "Select one corner of the area to be copied    Right Mouse: Cancel", leftx - 5, 5, WHITE);
			buffer_vline(mx - 5, my - 5, my + 15, BLACK);
			buffer_hline(mx - 5, my - 5, mx + 15, BLACK);
			break;
		case 1:
			buffer_textout_right_ex(normal, "Select the opposite corner of the area to be copied    Right Mouse: Cancel", leftx - 5, 5, WHITE);
			buffer_vline((topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE + 40, RED);
			buffer_hline((topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE,
					     (topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE + 40, RED);
			buffer_vline(mx + 20, my + 20, my, BLACK);
			buffer_hline(mx + 20, my + 20, mx, BLACK);
			break;
		case 2:
			buffer_textout_right_ex(normal, "Select top-left corner of new location    Right Mouse: Cancel", leftx - 5, 5, WHITE);
			buffer_vline((topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE + 40, RED);
			buffer_hline((topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE,
					     (topleft.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE,
					     (topleft.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE + 40, RED);
			buffer_vline((bottomright.x - worldmap.camera.get_scroll_x() + 1) * MAP_TILE_SIZE - 1,
					     (bottomright.y - worldmap.camera.get_scroll_y() + 1) * MAP_TILE_SIZE - 1,
					     (bottomright.y - worldmap.camera.get_scroll_y()) * MAP_TILE_SIZE - 10, RED);
			buffer_hline((bottomright.x - worldmap.camera.get_scroll_x() + 1) * MAP_TILE_SIZE - 1,
					     (bottomright.y - worldmap.camera.get_scroll_y() + 1) * MAP_TILE_SIZE - 1,
					     (bottomright.x - worldmap.camera.get_scroll_x()) * MAP_TILE_SIZE - 10, RED);
			break;
	}

	if ((mouse_clicked()) && (tile != 0))
	{  //place a tile/unit on the map if the mouse is pressed or remove a unit
		switch(phase)
		{
			case 0:  //select top left edge
				topleft.x = tile->x;
				topleft.y = tile->y;
				phase++;
				break;
			case 1:  //select bottom right edge
				bottomright.x = tile->x;
				bottomright.y = tile->y;

				if (topleft.x > bottomright.x)
				{  //ensure that topleft is really the top-left location
					int temp = topleft.x;
					topleft.x = bottomright.x;
					bottomright.x = temp;
				}
				if (topleft.y > bottomright.y)
				{
					int temp = topleft.y;
					topleft.y = bottomright.y;
					bottomright.y = temp;
				}

				phase++;
				break;
			case 2:
				move_tiles(topleft.x, topleft.y, bottomright.x, bottomright.y, tile->x, tile->y);
				phase = 0;
				return NORMAL;
				break;
		}
	}

	tile = worldmap.get_mouseover_tile(mx, my);
	if (tile != 0)
	{  //show the mouse's tile coordinates
		char msg[20];
		sprintf(msg, "%-1d, %-1d", tile->x, tile->y);
		buffer_textout_ex(normal, msg, 5, 5, WHITE);
	}

	return MOVETILES;
}

void move_tiles(int x1, int y1, int x2, int y2, int dx, int dy)
{
	const int width = x2 - x1 + 1;
	const int height = y2 - y1 + 1;
	int i, j, z;

	_tile *HQs[4];
	if ((x2 < x1) || (y2 < y1))
	{  //if the bottom-right corner wasn't lower and right-er than the top-left
		return;
	}
	_tile temp[width][height];

	for (int q = 0; q < 4; q++)
		HQs[q] = NULL;

	z = 0;
	j = 0;
	for (int y = y1; y <= y2; y++)
	{
		i = 0;
		for (int x = x1; x <= x2; x++)
		{
			temp[i][j] = *worldmap.get_tile(x, y);
			if (temp[i][j].is_HQ())
			{
				HQs[z] = worldmap.get_tile(x, y);
				z++;
			}
			i++;
		}
		j++;
	}

	j = 0;
	for (int y = dy; ((j < height) && (y < worldmap.get_height())); y++)
	{
		i = 0;
		for (int x = dx; ((i < width) && (x < worldmap.get_length())); x++)
		{
			_tile &tile = *(worldmap.get_tile(x, y));
			tile = temp[i][j];
			tile.x = x;
			tile.y = y;

			i++;
		}
		j++;
	}

	for (int q = 0; q < 4; q++)
	{  //if an HQ was moved, replace its previous location with a grass tile
		if (HQs[q] != NULL)
			HQs[q]->change_type(0, 3);
	}

	minimap.create();
}




enum editstate name_map()
{
	static bool first = true;
	static _textline name;
	const int namebox_w = 300;
	const int namebox_h = 125;
	const int namebox_x = (MAP_TILE_SIZE * XTILES - namebox_w) / 2;
	const int namebox_y = (MAP_TILE_SIZE * YTILES - namebox_h) / 2;
	const int text_w = 200;

	if (first)
	{
		name.init(namebox_x + (namebox_w - text_w) / 2, namebox_y + namebox_h - 50, text_w, 20, true);
		name.set_text(worldmap.get_name());

		first = false;
	}

	buffer_rectrounded(namebox_x, namebox_y, namebox_x + namebox_w, namebox_y + namebox_h, BLACK, 0.7, 7);
	buffer_textout_centre_ex(big, "Name Map", namebox_x + (namebox_w / 2), namebox_y + 25, WHITE);
	string newname = name.check(0.5);

	if (key[KEY_ESC])
	{
		first = true;
		return NORMAL;
	}

	if ((newname != "/NOTHING YET/") && (newname != ""))
	{
		worldmap.set_name(newname);
		first = true;
		return NORMAL;
	}

	return NAMEMAP;
}





void draw_selection(int set, int x)
{
	const int leftx = global.screen_width - SIDEBAR_WIDTH;

	int i, j, z;
	bitmapdat *selected;

	if ((set != 5) && (set != 4))
	{
		selected = set_datafile(set);
		z = selected->size;
		i = 0;
		j = 0;
		while (j < 6)
		{
			if (x + i < z)
			{
				selection[i].init(leftx + 25, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "", selected->bmp(x + i));
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			if (x + i < z)
			{
				selection[i].init(leftx + 65, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "", selected->bmp(x + i));
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			if (x + i < z)
			{
				selection[i].init(leftx + 105, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "", selected->bmp(x + i));
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			j++;
		}
	}
	else //buildings or mapunits
	{
		if (set == 4)
		{
			selected = set_datafile(4);
			z = selected->size * 5 - 1;
		}
		else z = NUM_UNITS * 4;
		j = 0;
		i = 0;
		while (j < 6)
		{
			if (x + i < z)
			{
				selection[i].init(leftx + 25, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "");
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			if (x + i < z)
			{
				selection[i].init(leftx + 65, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "");
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			if (x + i < z)
			{
				selection[i].init(leftx + 105, 20 + j * 40, MAP_TILE_SIZE, MAP_TILE_SIZE, "");
			}
			else
			{
				selection[i].init(0, -10, 0, 0);  //basically make it unclickable
			}
			i++;
			j++;
		}
	}
}

bitmapdat *set_datafile(int set)
{
	switch(set)
	{
		case 0:
			return &land;
			break;
		case 1:
			return &river;
			break;
		case 2:
			return &sea;
			break;
		case 3:
			return &shoal;
			break;
		case 4:
			return &buildings;
			break;
		case 6:
			return &special;
			break;
	}
	return &shoal;  //it should never get here, but returning shoal should make the error obvious if drawn
}

int datafile_size(DATAFILE *data)
{
	int size = 0;
	while (data[size].type != DAT_END)
		size++;
	return size;
}

int add_aifiles(const char *filename, int attrib, void *param)
{
	char *fname = (char*)malloc(sizeof(char) * (strlen(filename) + 1));
	strcpy(fname, get_filename(filename));
	fname[strlen(fname) - 3] = '\0';  //remove extension
	((_listbox*)param)->additem(fname, false);
	free(fname);
	return 0;
}
enum editstate do_aiselect()
{
	const int rows = NUM_UNITS / 2 + NUM_UNITS % 2;
	static bool first = true;
	static int sel;
	static _button done, save, changeweight[MAX_UNITS * 2], changelimit[MAX_UNITS * 2];
	static _listbox presets;
	char t[50];
	int i, j, k;

	if (first)
	{
		done.init(65, 415, 80, 15, "Done");
		save.init(65, 385, 145, 15, "Save as a Preset");

		presets.init(65, 65, 145, 310);
		for_each_file_ex("ai/*.ai", 0, FA_DIREC, add_aifiles, &presets);
		presets.sort();

		i = 0;
		while (i < 2)
		{
			j = 0;
			while (j < rows)
			{
				changeweight[2 * (j + (rows * i))].init(280 + (160 * i), 65 + (35 * j), 13, 30, "<");
				changeweight[2 * (j + (rows * i)) + 1].init(315 + (160 * i), 65 + (35 * j), 13, 30, ">");
				changelimit[2 * (j + (rows * i))].init(340 + (160 * i), 65 + (35 * j), 13, 30, "<");
				changelimit[2 * (j + (rows * i)) + 1].init(375 + (160 * i), 65 + (35 * j), 13, 30, ">");
				j++;
			}
			i++;
		}

		sel = -1;
		first = false;
	}

	buffer_rectfill(50, 50, 590, 460, GREY, 0.85);
	buffer_rect(50, 50, 590, 460, DGREY);
	buffer_rect(48, 48, 592, 462, DGREY);
	buffer_rect(280, 65, 328, 445, DGREY);
	buffer_rect(340, 65, 388, 445, DGREY);
	buffer_rect(440, 65, 488, 445, DGREY);
	buffer_rect(500, 65, 548, 445, DGREY);
	done.check();
	save.check();

	buffer_textout_ex(normal, "AI profile presets:", 70, 53, BLACK);
	presets.check();
	buffer_textout_ex(normal, "Weight", 285, 52, BLACK);
	buffer_textout_ex(normal, "Limit", 350, 52, BLACK);

	i = 0;
	while (i < 2)
	{
		j = 0;
		while (j < rows)
		{
			if (j + (rows * i) < NUM_UNITS)
			{
				k = j + (rows * i);
				buffer_draw_sprite(units[k].bmp(0), 240 + (160 * i), 65 + (35 * j));

				changeweight[2 * k].check();
				if (changeweight[2 * k].clicked())
				{
					if (theai.weight[k] > 0)
						theai.weight[k]--;
				}

				changeweight[2 * k + 1].check();
				if (changeweight[2 * k + 1].clicked())
				{
					if (theai.weight[k] < 101)
						theai.weight[k]++;
				}


				changelimit[2 * k].check();
				if (changelimit[2 * k].clicked())
				{
					if (theai.limit[k] > 0)
						theai.limit[k]--;
				}

				changelimit[2 * k + 1].check();
				if (changelimit[2 * k + 1].clicked())
				{
					if (theai.limit[k] < 51)
						theai.limit[k]++;
				}

				sprintf(t, "%-1d", theai.weight[j + (rows * i)]);
				buffer_textout_centre_ex(normal, t, 304 + (160 * i), 76 + (35 * j), BLACK);
				sprintf(t, "%-1d", theai.limit[j + (rows * i)]);
				buffer_textout_centre_ex(normal, t, 364 + (160 * i), 76 + (35 * j), BLACK);
			}
			j++;
		}
		i++;
	}

	/*i = 0;
  while (i < NUM_UNITS * 2)
  {
    if (changeweight[i].clicked())
    {
      if (i % 2 == 0)
      {
        if (theai.weight[i / 2] > 0)
        {
          theai.weight[i / 2]--;
        }
      }
      else
      {
        if (theai.weight[i / 2] < 101)
        {
          theai.weight[i / 2]++;
        }
      }
			presets.unselect();
			sel = -1;
    }
    if (changelimit[i].clicked())
    {
      if (i % 2 == 0)
      {
        if (theai.limit[i / 2] > 0)
        {
          theai.limit[i / 2]--;
        }
      }
      else
      {
        if (theai.limit[i / 2] < 51)
        {
          theai.limit[i / 2]++;
        }
      }
			presets.unselect();
			sel = -1;
    }
    i++;
  }*/

	if ((presets.getsel() != -1) && (presets.getsel() != sel))
	{
		sprintf(t, "ai/%s.ai", presets.selected());
		load_ai_from_file(t);
		sel = presets.getsel();
	}

	if (save.clicked())
	{
		sprintf(t, "New Profile");
		text_box(200, 200, 240, 40, t, 35, 1, "Name the AI profile:");
		if (strcmp(t, "_CANCEL_") != 0)
		{
			save_new_aiprofile(t);

			i = 0;
			j = 0;
			while (i < presets.size())
			{
				if (strcmp(t, presets.getitem(i)) == 0)
				{
					j = 1;
				}
				i++;
			}
			if (j == 0)
				presets.additem(t, false);
		}
	}
	if (done.clicked())
	{
		first = true;
		//set_mouse_range(0, 0, 639, 479);
		return NORMAL;
	}
	draw_mouse();
	return AIPROFILE;
}





enum maineditstate save_map()
{
	char t[50] = "";
	static bool first = true;
	static bool failure = false;
	static string failstring = "";

	if (worldmap.get_name() != "")
	{
		empdebug("Saving map:");
		empdebug(worldmap.get_name());

		buffer_rectfill(390, 446, 640, 453, LGREY);
		delete_map(worldmap.get_name());
		sprintf(t, "maps/");
		strcat(t, worldmap.get_name().c_str());
		strcat(t, ".map");
		ofstream m(t);
		sprintf(t, "maps/");
		strcat(t, worldmap.get_name().c_str());
		strcat(t, ".ai");
		ofstream a(t);
		if ((m.bad()) || (a.bad()))
		{
			failure = true;
			failstring = "Unable to save ";
			failstring += worldmap.get_name();
		}
		else
		{
			m << worldmap.get_length() << "\n";
			m << worldmap.get_height() << "\n";
			if (HQ_exists(3) == 1)  //if 4 player map
			{
				m << "4" << "\n";
			}
			else if (HQ_exists(2) == 1)  //if 3 player map
			{
				m << "3" << "\n";
			}
			else  //2 player map
			{
				m << "2" << "\n";
			}

			for (int y = 0; y < worldmap.get_height(); y++)
			{  //saving the tiles
				for (int x = 0; x < worldmap.get_length(); x++)
				{
					_tile *tile = worldmap.get_tile(x, y);
					m << (tile->get_set() * 100) + tile->get_number() << " ";
					m << tile->get_owner() << " ";
				}
				m << "\n";
			}

			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 50; j++)
				{
					if (player[i].unit[j].exists)
					{
						m << player[i].unit[j].tilex << "\n";
						m << player[i].unit[j].tiley << "\n";
						m << player[i].unit[j].type << "\n";
						m << i << "\n";  // the unit's owner
					}
				}
			}
			m << "-1\n";

			for (int i = 0; i < NUM_UNITS; i++)
				a << theai.weight[i] << "\n" << theai.limit[i] << "\n";

			m.close();
			a.close();
		}

		if (!failure)
		{
			counter = 0;
			create_particle((global.screen_width / 2) - normal.Width("Map Saved") / 2, global.screen_height / 2, P_FADETEXT, WHITE, "Map Saved");
			medit();
			return MEDIT;
		}
	}
	else
	{
		failure = true;
		failstring = "The map needs a name";
	}

	if (failure)
	{
		if (first)
		{
			map_message("CLEAR");
			map_message(failstring);
			first = false;
		}

		worldmap.draw();
		buffer_rectfill(0, 385, 640, 480, LGREY);
		buffer_hline(0, 384, 640, BLACK);
		map_message("-");

		if (key[KEY_ENTER])
		{
			failure = false;
			first = true;
			return MEDIT;
		}
	}
	return MSAVE;
}





void draw_minimap(int x, int y, string file)
{
	static string previous = "";

	if (file != previous)
	{
		empdebug("Recreating minimap...");
		empdebug("  Reading data from file...");

		worldmap.load(file);
		empdebug("  ...done.  Calling minimap.create()...");

		minimap.create();
		empdebug("  Done");
		minimap.a = 1.0;

		previous = file;
	}
	minimap.draw(false, x, y, false);
}





void delete_map(string mapname)
{
	vector<string> fname;
	string temp;
	string fullfile = "maps/";
	fullfile += mapname;
	fullfile += ".map";
	delete_file(fullfile.c_str());
	fullfile = "maps/";
	fullfile += mapname;
	fullfile += ".ai";
	delete_file(fullfile.c_str());
}



void remove_previous_HQ(int player, int ignorex, int ignorey)
{
	for (int y = 0; y < worldmap.get_height(); y++)
	{
		for (int x = 0; x < worldmap.get_length(); x++)
		{
			if ((x != ignorex) || (y != ignorey))
			{
				_tile *t = worldmap.get_tile(x, y);
				if ((t->is_HQ()) && (t->owned_by(player)))
				{
					t->reset();
				}
			}
		}
	}
}





enum maineditstate mcheck()
{
	const int leftx = global.screen_width - SIDEBAR_WIDTH;

	static bool checked = false;

	char themessage[40];
	int i;

	worldmap.draw();

	//draw a grid
	for (int i = 0; i < XTILES; i++)
		buffer_vline(i * MAP_TILE_SIZE, 0, YTILES * MAP_TILE_SIZE, WHITE, 0.5);
	for (int i = 0; i < YTILES; i++)
		buffer_hline(0, i * MAP_TILE_SIZE, leftx, WHITE, 0.5);

	//draw the borders of the menu bars
	buffer_rectfill(0, YTILES * MAP_TILE_SIZE, leftx, global.screen_height, BLACK);
	buffer_rectfill(0, global.screen_height - BOTTOMBAR_HEIGHT, leftx, global.screen_height, BLACK);
	buffer_rectfill_gradient(0, global.screen_height - BOTTOMBAR_HEIGHT, leftx, global.screen_height - BOTTOMBAR_HEIGHT + 3, WHITE, WHITE, VDGREY, VDGREY);
	buffer_rectfill_gradient(leftx, 0, leftx + 3, global.screen_height, WHITE, DGREY, BLACK, WHITE);
	buffer_rectfill_gradient(leftx + 3, 0, global.screen_width, global.screen_height, GREY, GREY, DGREY, DGREY);

	if (!checked)
	{
		empdebug("Checking map for problems...");
		map_message("CLEAR");
		if (!HQ_exists(0))
		{
			map_message("Player 1 has no HQ");
		}
		if (!HQ_exists(1))
		{
			map_message("Player 2 has no HQ");
		}
		i = 0;
		while (i < 4)
		{
			if (HQ_exists(i))
			{
				if (!base_exists(i) && (player[i].units_in_play() == 0))
				{
					sprintf(themessage, "Player %d has no bases or units", i + 1);
					map_message(themessage);
				}
			}
			else if (base_exists(i) || (player[i].units_in_play() > 0))
			{
				if (!HQ_exists(i))
				{
					sprintf(themessage, "Player %d has no HQ", i + 1);
					map_message(themessage);
				}
			}
			i++;
		}
		empdebug("Finished checking map");
		checked = true;
	}

	map_message("-");
	if (key[KEY_ENTER])
	{
		checked = false;
		return MEDIT;
	}
	return MCHECK;
}

void map_message(string message)
{
	static vector<string> display;

	const int box_w = 300;
	const int box_h = 125 + (12 * display.size());
	const int box_x = (MAP_TILE_SIZE * XTILES - box_w) / 2;
	const int box_y = (MAP_TILE_SIZE * YTILES - box_h) / 2;

	if (message == "CLEAR")
	{
		display.clear();
		return;
	}
	else if (message == "-")
	{  //do nothing but display the previous messages
	}
	else
	{
		display.push_back(message);
		return;
	}

	buffer_rectrounded(box_x, box_y, box_x + box_w, box_y + box_h, BLACK, 0.7, 7);

	if (display.empty())
		buffer_textout_centre_ex(big, "No Map Errors Found", box_x + (box_w / 2), box_y + 5, WHITE);
	else
		buffer_textout_centre_ex(big, "Map Errors", box_x + (box_w / 2), box_y + 5, WHITE);

	for (unsigned int i = 0; i < display.size(); i++)
		buffer_textout_centre_ex(med, display[i].c_str(), box_x + (box_w / 2), box_y + 40 + (12 * i), RED);

	buffer_textout_centre_ex(normal, "Press Enter", box_x + (box_w / 2), box_y + box_h - 15, WHITE);
}

bool HQ_exists(int playernum)
{
	for (int y = 0; y < worldmap.get_height(); y++)
	{
		for (int x = 0; x < worldmap.get_length(); x++)
		{
			_tile *t = worldmap.get_tile(x, y);
			if (t->is_HQ())
			{
				if (t->owned_by(playernum))
				{
					return true;
				}
			}
		}
	}
	return false;
}

bool base_exists(int playernum)
{
	for (int y = 0; y < worldmap.get_height(); y++)
	{
		for (int x = 0; x < worldmap.get_length(); x++)
		{
			_tile *t = worldmap.get_tile(x, y);
			if (t->is_unit_producing())
			{
				if (t->owned_by(playernum))
				{
					return true;
				}
			}
		}
	}
	return false;
}

void draw_trans_tile(int set, int num, int x, int y)
{
	buffer_blit_clipped(set_datafile(set)->bmp(num), x, y, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, 0.66);
}
