#include "scGame.h"
#include "Wumbo-Texture.h"
#include "Wumbo-Functions.h"
#include "Wumbo-Sprite.h"
#include "Wumbo-Renderer.h"
#include "Wumbo-Types.h"

#include "Thinker.h"
#include "Krampus.h"
#include "Elf.h"
#include "scYouLose.h"
#include "scYouWin.h"
#include <cmath>


int LEVEL_GENERATOR_WAIT_TIME = 5;

int reindeers[] = {DASHER,DANCER,PRANCER,COMET,BLITZEN};

int CHOSEN_REINDEER;
int CANDYCANES = 1;

#include "CandyCane.h"




#if PLATFORM_PC
#include <SFML/Graphics.hpp>
#if PLATFORM_WINDOWS
void crossPlatformMessageBox(std::string message)
{
	char *bob = new char[message.length()+12];
	sprintf(bob,message.c_str(),LEVEL_GENERATOR_WAIT_TIME);
	MessageBoxA(NULL,bob,"868-KRAMPUS",MB_OK | MB_ICONERROR);
	delete bob;
}
#elif PLATFORM_APPLE
#include <Appkit/NSAlert.h>
void crossPlatformMessageBox(std::string message)
{
	char *bob = new char[message.length()+12];
	sprintf(bob,message.c_str(),LEVEL_GENERATOR_WAIT_TIME);
	[NSAlert alertWithMessageText:@"868-KRAMPUS" defaultButton:@"Okay" alternateButton:nil otherButton:nil informativeTextWithFormat:[NSString stringWithFormat:@"%s",bob]];
	delete bob;
}
#endif
#endif


std::vector<Elf*> elves;
Krampus *krampus;

int endPortalX;
int endPortalY;

extern int PATHFIND_SUCCESS;
extern int PATHFIND_FAILURE;
extern int PATHFIND_ENDISADJACENT;
extern int findPath(int x, int y, int destX, int destY, int *savedX, int *savedY);

bool allElvesAreAtTargets()
{
	for(int i=0;i<elves.size();i++)
		if (!elves.at(i)->isAtTarget())
			return false;
	return true;
}

Wumbo::Texture *texSuper;//
Wumbo::Sprite *sprKrampus;//
Wumbo::Sprite *sprElf[4];///
Wumbo::Sprite *sprReindeer;//
Wumbo::Sprite *sprIce;//
Wumbo::Sprite *sprTree;//
Wumbo::Sprite *sprSanta;//
Wumbo::Sprite *sprHealth[4];//
Wumbo::Sprite *sprAttacks[9];//
Wumbo::Sprite *sprAttacksVERT[9];//
Wumbo::Sprite *sprRect;
Wumbo::Sprite *sprTile;
Wumbo::Sprite *sprFont[54];
Wumbo::Sprite *sprEndPortal;
Wumbo::Sprite *sprCoal;

Wumbo::Sprite *sprFrozen;
Wumbo::Sprite *sprParalyze;
Wumbo::Sprite *sprCandyCane;

int screen[BOARD_SIZE][BOARD_SIZE];

void drawSprite(Wumbo::Sprite *spr, int x, int y, float scaleX = 1.f, float scaleY = 1.f, int r = 255, int g = 255, int b = 255, int a = -1)
{
	spr->setPosition(x,y);
	spr->setScale(scaleX,scaleY);
	if (a == -1)
		a = (spr->getColor() & 0xFF);
	spr->setColor(r,g,b,a);
	spr->draw();
}

void drawRect(int x, int y, int width, int height, int r = 255, int g = 255, int b = 255, int a = -1)
{
	sprRect->setPosition(x,y);
	sprRect->setScale(width,height);
	if (a == -1)
		a = (sprRect->getColor() & 0xFF);
	sprRect->setColor(r,g,b,a);
	sprRect->draw();
}

void drawText(std::string text, int x, int y, float scale, int r = 255, int g = 255, int b = 255)
{
	int xx = x;
	int yy = y;
	int frame = 0;
	for(int i=0;i<text.length();i++)
	{
		if (text.at(i) == ' ')
		{
			xx += TILE_SIZE*scale;
			continue;
		}
		if (text.at(i) == '#')
		{
			xx = x;
			yy += TILE_SIZE*scale;
			continue;
		}
		if (text.at(i) >= 'A' && text.at(i) <= 'Z')
			frame = text.at(i)-'A';
		if (text.at(i) >= 'a' && text.at(i) <= 'z')
			frame = text.at(i)-'a';
		if (text.at(i) >= '0' && text.at(i) <= '9')
			frame = text.at(i)-'0'+32;
		if (text.at(i) == '.')
			frame = 26;
		if (text.at(i) == '!')
			frame = 27;
		if (text.at(i) == '?')
			frame = 28;
		sprFont[frame]->setPosition(xx,yy);
		sprFont[frame]->setScale(scale,scale);
		sprFont[frame]->setColor(r,g,b,(sprFont[frame]->getColor() & 0xFF));
		sprFont[frame]->draw();
		xx += TILE_SIZE*scale;
	}
}

int distance(int x, int y, int x2, int y2)
{
	return sqrt((float)((x-x2)*(x-x2)+(y-y2)*(y-y2)));
}

bool scGame::generateLevel(int krampusStartX, int krampusStartY, time_t startTime)
{
	bool retVal = false;
	for(int x=0;x<BOARD_SIZE;x++)
		for(int y=0;y<BOARD_SIZE;y++)
		{
			int v = rand() % 10;
			screen[x][y] = 0;
			bool canBuild = true;
			if (krampusStartX != -1)
				if (krampusStartX == x && krampusStartY == y)
					canBuild = false;
			if (canBuild)
			{
				if (v < 1)
					screen[x][y] = 1;
				else if (v < 2)
					screen[x][y] = 1;
			}
		}
	bool krampusYes = false;
	int kx, ky;
	while(!krampusYes)
	{
		if (time(NULL)-startTime > LEVEL_GENERATOR_WAIT_TIME)
			return false;
		if (krampusStartX == -1)
		{
			switch(rand() % 4)
			{
			case 0:
				kx = rand() % BOARD_SIZE;
				ky = 0;
				break;
			case 1:
				kx = rand() % BOARD_SIZE;
				ky = BOARD_SIZE-1;
				break;
			case 2:
				kx = 0;
				ky = rand() % BOARD_SIZE;
				break;
			case 3:
				kx = BOARD_SIZE-1;
				ky = rand() % BOARD_SIZE;
				break;
			}
		}
		else
		{
			kx = krampusStartX;
			ky = krampusStartY;
		}
		if (krampusStartX == -1) //if this is the first go, make the end as far away as possible. otherwise just rando it.
		{
			int minDist = 0;
			int d;
			if ((d = distance(kx,ky,0,0)) > minDist)
			{
				minDist = d;
				endPortalX = 0;
				endPortalY = 0;
			}
			if ((d = distance(kx,ky,BOARD_SIZE-1,0)) > minDist)
			{
				minDist = d;
				endPortalX = BOARD_SIZE-1;
				endPortalY = 0;
			}
			if ((d = distance(kx,ky,0,BOARD_SIZE-1)) > minDist)
			{
				minDist = d;
				endPortalX = 0;
				endPortalY = BOARD_SIZE-1;
			}
			if ((d = distance(kx,ky,BOARD_SIZE-1,BOARD_SIZE-1)) > minDist)
			{
				minDist = d;
				endPortalX = BOARD_SIZE-1;
				endPortalY = BOARD_SIZE-1;
			}
		}
		else
		{
			do
			{
				switch(rand() % 4)
				{
				case 0:
					endPortalX = 0;
					endPortalY = 0;
					break;
				case 1:
					endPortalX = BOARD_SIZE-1;
					endPortalY = 0;
					break;
				case 2:
					endPortalX = 0;
					endPortalY = BOARD_SIZE-1;
					break;
				case 3:
					endPortalX = BOARD_SIZE-1;
					endPortalY = BOARD_SIZE-1;
					break;
				}
			}
			while(endPortalX == kx && endPortalY == ky);
		}
		screen[endPortalX][endPortalY] = 0;
		if (screen[kx][ky] == 0)
		{
			int findX, findY;
			int r = findPath(kx,ky,endPortalX,endPortalY,&findX,&findY);
			if (r != PATHFIND_FAILURE)
			{
				retVal = true;
				krampusYes = true;
			}
			else
			{
				printf("unable to find a path. regen.\n");
				return false;
			}
		}
		else
			printf("nope. start has a block. find new start.\n");
	}
	krampus->setMoveCount(1);
	krampus->setPosition(TILE_SIZE*kx,TILE_SIZE*ky);
	krampus->setMyTurn(true);
	while(elves.size() > 0)
	{
		delete elves.at(0);
		elves.erase(elves.begin());
	}
	candies.clear();
	int placed = 0;
	std::vector<Wumbo::vec2di> freespaces;
	for(int i=0;i<BOARD_SIZE;i++)
		for(int j=0;j<BOARD_SIZE;j++)
		{
			if (screen[i][j] == 0)
				freespaces.push_back(Wumbo::vec2di(i,j));
		}

	while(placed < 5)
	{
		int xx, yy;
		int i = rand() % freespaces.size();
		candies.push_back(new CandyCane(freespaces.at(i).x,freespaces.at(i).y));
		freespaces.erase(freespaces.begin()+i);
		placed++;
	}


	int elfCount = 2;
	while(elfCount > 0)
	{
		for(int x=0;x<BOARD_SIZE;x++)
			for(int y=0;y<BOARD_SIZE;y++)
			{
				if (rand() % 15 == 0 && screen[x][y] == 0 && x != kx && y != ky)
				{
					Elf *e = new Elf(this);
					e->setPosition(TILE_SIZE*x,TILE_SIZE*y);
					e->setMyTurn(false);
					e->setMoveCount(1);
					elves.push_back(e);
					elfCount--;
				}
			}
	}


	return retVal;
}

void scGame::makeNewLevel(int xx, int yy)
{
	currentLevel++;
	krampus->hp += 3;
	if (krampus->hp > 9)
		krampus->hp = 9;
	time_t startTime = time(NULL);
	while(!generateLevel(xx,yy,startTime))
	{
		if (time(NULL)-startTime > LEVEL_GENERATOR_WAIT_TIME)
		{
			if (LEVEL_GENERATOR_WAIT_TIME == 1)
				crossPlatformMessageBox("An error has occurred:\n\nThe level generator took more than 1 second to find a valid map.");
			else
				crossPlatformMessageBox("An error has occurred:\n\nThe level generator took more than %i seconds to find a valid map.");
			program->getSFMLWindow()->close();
			return;
		}
	}
}


scGame::scGame()
{
	program = NULL;
}
scGame::scGame(Wumbo::Program *prog)
{
	program = prog;
}
void scGame::begin()
{
	LEVELNUMBER = 1;
	srand(time(NULL));
	CHOSEN_REINDEER = reindeers[rand()%5];
	currentLevel = -1;
	texSuper = new Wumbo::Texture();
	texSuper->load(Wumbo::BundleResource("tileset.png"));

	Wumbo::Renderer *rend = program->getRenderer();
	
	sprKrampus = new Wumbo::Sprite(rend);
	sprKrampus->setTexture(texSuper);
	sprKrampus->setSubrectPixels(0,		0,0,128,128);
	sprKrampus->setSize(TILE_SIZE,TILE_SIZE);

	for(int i=0;i<4;i++)
	{
		sprElf[i] = new Wumbo::Sprite(rend);
		sprElf[i]->setTexture(texSuper);
		sprElf[i]->setSubrectPixels(0,	128*(i+1),0,128,128);
		sprElf[i]->setSize(TILE_SIZE,TILE_SIZE);
	}

	sprReindeer = new Wumbo::Sprite(rend);
	sprReindeer->setTexture(texSuper);
	sprReindeer->setSubrectPixels(0,		640,0,128,128);
	sprReindeer->setSize(TILE_SIZE,TILE_SIZE);

	sprIce = new Wumbo::Sprite(rend);
	sprIce->setTexture(texSuper);
	sprIce->setSubrectPixels(0,		768,0,128,128);
	sprIce->setSize(TILE_SIZE,TILE_SIZE);

	sprTree = new Wumbo::Sprite(rend);
	sprTree->setTexture(texSuper);
	sprTree->setSubrectPixels(0,		128,256,128,128);
	sprTree->setSize(TILE_SIZE,TILE_SIZE);

	sprSanta = new Wumbo::Sprite(rend);
	sprSanta->setTexture(texSuper);
	sprSanta->setSubrectPixels(0,		896,0,128,128);
	sprSanta->setSize(TILE_SIZE,TILE_SIZE);

	sprCoal = new Wumbo::Sprite(rend);
	sprCoal->setTexture(texSuper);
	sprCoal->setSubrectPixels(0,		768,256,128,128);
	sprCoal->setSize(TILE_SIZE,TILE_SIZE);

	for(int i=0;i<9;i++)
	{
		sprAttacks[i] = new Wumbo::Sprite(rend);
		sprAttacks[i]->setTexture(texSuper);
		sprAttacks[i]->setSubrectPixels(0,		128*(i % 8),128*(1 + i/8),128,128);
		sprAttacks[i]->setSize(TILE_SIZE,TILE_SIZE);
	}

	for(int i=0;i<9;i++)
	{
		int xx = 896, yy = 384;
		switch(i)
		{
		case RUDOLPH:
			xx = 0;
			break;
		case COMET:
			xx = 128;
			break;
		case CUPID:
			xx = 256;
			break;
		case BLITZEN:
			xx = 384;
			break;
		default:
			xx = 896;
			break;
		}
		sprAttacksVERT[i] = new Wumbo::Sprite(rend);
		sprAttacksVERT[i]->setTexture(texSuper);
		sprAttacksVERT[i]->setSubrectPixels(0,		xx,yy,128,128);
		sprAttacksVERT[i]->setSize(TILE_SIZE,TILE_SIZE);
	}

	for(int i=0;i<4;i++)
	{
		sprHealth[i] = new Wumbo::Sprite(rend);
		sprHealth[i]->setTexture(texSuper);
		sprHealth[i]->setSubrectPixels(0,		64*(14 + i % 2),64*(4 + i/2),64,64);
		sprHealth[i]->setSize(64,64);
	}

	for(int i=0;i<54;i++)
	{
		sprFont[i] = new Wumbo::Sprite(rend);
		sprFont[i]->setTexture(texSuper);
		sprFont[i]->setSubrectPixels(0,		128*(i % 8),128*(4 + i/8),128,128);
		sprFont[i]->setSize(128,128);
	}

	sprRect = new Wumbo::Sprite(rend);
	sprRect->setTexture(texSuper);
	sprRect->setSubrectPixels(0,		896,896,128,128);
	sprRect->setSize(1,1);

	sprTile = new Wumbo::Sprite(rend);
	sprTile->setTexture(texSuper);
	sprTile->setSubrectPixels(0,		256,256,128,128);
	sprTile->setSize(TILE_SIZE,TILE_SIZE);

	sprEndPortal = new Wumbo::Sprite(rend);
	sprEndPortal->setTexture(texSuper);
	sprEndPortal->setSubrectPixels(0,		384,256,128,128);
	sprEndPortal->setSize(TILE_SIZE,TILE_SIZE);

	sprFrozen = new Wumbo::Sprite(rend);
	sprFrozen->setTexture(texSuper);
	sprFrozen->setSubrectPixels(0,		512,256,128,128);
	sprFrozen->setSize(TILE_SIZE,TILE_SIZE);

	sprParalyze = new Wumbo::Sprite(rend);
	sprParalyze->setTexture(texSuper);
	sprParalyze->setSubrectPixels(0,		640,256,128,128);
	sprParalyze->setSize(TILE_SIZE,TILE_SIZE);

	sprCandyCane = new Wumbo::Sprite(rend);
	sprCandyCane->setTexture(texSuper);
	sprCandyCane->setSubrectPixels(0,		512,384,128,128);
	sprCandyCane->setSize(TILE_SIZE,TILE_SIZE);

	krampus = new Krampus(this);
	makeNewLevel(-1,-1);
}
void scGame::update()
{
}
void scGame::render()
{
	glClearColor(0.6f,0.6f,0.6f,1.f);
	glClear(GL_COLOR_BUFFER_BIT);
	texSuper->bind();
	for(int i=0;i<BOARD_SIZE*BOARD_SIZE;i++)
	{
		int x = (i % BOARD_SIZE);
		int y = (i / BOARD_SIZE);
		drawSprite(sprTile,TILE_SIZE*x,TILE_SIZE*y);
		if (screen[x][y] == 1)
			drawSprite(sprTree,TILE_SIZE*x,TILE_SIZE*y);
		if (screen[x][y] == 2)
			drawSprite(sprIce,TILE_SIZE*x,TILE_SIZE*y);
		if (x == endPortalX && y == endPortalY)
			drawSprite(sprEndPortal,TILE_SIZE*x,TILE_SIZE*y);
	}
	for(int i=0;i<BOARD_SIZE*BOARD_SIZE;i++)
	{
		int x = (i % BOARD_SIZE);
		int y = (i / BOARD_SIZE);
		
		if (screen[x][y] == 11)
			drawRect(TILE_SIZE*x,TILE_SIZE*y,TILE_SIZE,TILE_SIZE,255,0,0,128);
		if (screen[x][y] == 20)
			drawRect(TILE_SIZE*x,TILE_SIZE*y,TILE_SIZE,TILE_SIZE,0,255,255,128);
	}
	drawRect(768,0,256,768,128,128,128,255);
	for(int i=0;i<9;i++)
	{
		if (i < krampus->hp)
			drawSprite(sprHealth[2], 768 + 48 + TILE_SIZE/2*(i % 3), 64 + 48 + 16 + TILE_SIZE/2*(i / 3));
		else
			drawSprite(sprHealth[0], 768 + 48 + TILE_SIZE/2*(i % 3), 64 + 48 + 16 + TILE_SIZE/2*(i / 3));
	}
	int tx = 768+48, ty = 64 + 16;
	if (CHOSEN_REINDEER == DASHER)
		drawText("DASHER",tx,ty,.25,0,0,0);//.25f);
	if (CHOSEN_REINDEER == DANCER)
		drawText("DANCER",tx,ty,.25,0,0,0);//.25f);
	if (CHOSEN_REINDEER == PRANCER)
		drawText("PRANCER",tx,ty,.25,0,0,0);//.25f);
	if (CHOSEN_REINDEER == COMET)
		drawText("COMET",tx,ty,.25,0,0,0);//.25f);
	if (CHOSEN_REINDEER == BLITZEN)
		drawText("BLITZEN",tx,ty,.25,0,0,0);//.25f);
	drawSprite(sprCandyCane,768+32,16,.5,.5);
	char cand[20] = "";
	sprintf(cand,"%i",CANDYCANES);
	printf("%s\n",cand);
	drawText(cand,768+96,32,.25,0,0,0);//.25f);
	if (krampus->isMyTurn())
	{
		krampus->doMyTurn();
		if (krampus->isAtTarget())
		{
			//printf("krampus at target\n");
			if (krampus->getGridWithAirQuotesX() == endPortalX && krampus->getGridWithAirQuotesY() == endPortalY)
			{
				LEVELNUMBER++;
				if (LEVELNUMBER == 9)
				{
					program->setScene(new scYouWin(program));
					return;
				}
				makeNewLevel(krampus->getGridWithAirQuotesX(),krampus->getGridWithAirQuotesY());
			}
		}
		if (krampus->isEndOfTurn())
		{
			//printf("krampus end\n");
			krampus->setMyTurn(false);
			for(int i=0;i<elves.size();i++)
				elves.at(i)->setMyTurn(true);
		}
	}
	else
	{
		for(int i=0;i<elves.size();i++)
			elves.at(i)->think();
		for(int i=0;i<elves.size();i++)
			elves.at(i)->doMyTurn();
		bool endOfAllElvesTurns = true;
		for(int i=0;i<elves.size();i++)
			if (!elves.at(i)->isEndOfTurn())
			{
				endOfAllElvesTurns = false;
				i = elves.size();
			}
		if (endOfAllElvesTurns)
		{
			printf("elf end\n");
			for(int i=0;i<elves.size();i++)
				elves.at(i)->tryToAttack();
			krampus->setMyTurn(true);
			for(int i=0;i<elves.size();i++)
				elves.at(i)->setMyTurn(false);
		}
	}
	for(int i=0;i<candies.size();i++)
		drawSprite(sprCandyCane,TILE_SIZE*candies.at(i)->x,TILE_SIZE*candies.at(i)->y);
	for(int i=0;i<elves.size();i++)
		elves.at(i)->render();		
	krampus->render();			
	for(int i=0;i<elves.size();i++)
	{
		if (elves.at(i)->isDead())
		{
			delete elves.at(i);
			elves.erase(elves.begin()+i);
		}
	}
	if (krampus->hp <= 0)
	{
		program->setScene(new scYouLose(program));
		return;
	}
}
void scGame::end()
{
	delete krampus;
	while(elves.size() > 0)
	{
		delete elves.at(0);
		elves.erase(elves.begin());
	}
}
void scGame::onClose()
{
}

int PATHFIND_SUCCESS = 1;
int PATHFIND_FAILURE = 0;
int PATHFIND_ENDISADJACENT = 2;

class AINode
{
public:
	int x;
	int y;
	int generation;
	AINode *camefrom;
};

AINode *getNewNode(int x, int y, int generation, AINode *camefrom)
{
	if (x < 0)
		return NULL;
	if (y < 0)
		return NULL;
	if (x >= BOARD_SIZE)
		return NULL;
	if (y >= BOARD_SIZE)
		return NULL;
	if (screen[x][y] != 0 && screen[x][y] != 20)
		return NULL;
	AINode *node = new AINode();
	node->x = x;
	node->y = y;
	node->generation = generation;
	node->camefrom = camefrom;
}

int findPath(int x, int y, int destX, int destY, int *savedX, int *savedY)
{
	if ((x-1 == destX && y == destY) ||
		(x+1 == destX && y == destY) ||
		(x == destX && y == destY-1) ||
		(x == destX && y == destY+1))
		return PATHFIND_ENDISADJACENT;

	int visited[BOARD_SIZE][BOARD_SIZE];

	memset(visited,0,sizeof(int)*BOARD_SIZE*BOARD_SIZE);

	std::vector<AINode*> finishers;

	AINode *startNode = new AINode();
	startNode->x = x;
	startNode->y = y;
	startNode->generation = 0;
	startNode->camefrom = NULL;

	std::vector<AINode*> Q;
	Q.push_back(startNode);
	for(int i=0;i<Q.size();i++)
	{
		AINode *current = Q.at(i);
		visited[current->x][current->y] = 1;
		if (current->x == destX && current->y == destY)
		{
			//printf("I REACHED %i %i! I WIN! break out now\n",destX,destY);
			finishers.push_back(current);
			//i = Q.size() * 5;
		}
		else
		{
			if (!visited[current->x-1][current->y])
			{
				AINode *n = getNewNode(current->x-1,current->y,current->generation+1,current);
				if (n != NULL)
					Q.push_back(n);
			}
			if (!visited[current->x+1][current->y])
			{
				AINode *n = getNewNode(current->x+1,current->y,current->generation+1,current);
				if (n != NULL)
					Q.push_back(n);
			}
			if (!visited[current->x][current->y-1])
			{
				AINode *n = getNewNode(current->x,current->y-1,current->generation+1,current);
				if (n != NULL)
					Q.push_back(n);
			}
			if (!visited[current->x][current->y+1])
			{
				AINode *n = getNewNode(current->x,current->y+1,current->generation+1,current);
				if (n != NULL)
					Q.push_back(n);
			}
		}
	}
	
	int result = PATHFIND_FAILURE;
	AINode *firstOptimum = new AINode();
	firstOptimum->generation = 200000;
	AINode *optimum = firstOptimum;
	if (finishers.size() > 0)
	{
		for(int i=0;i<finishers.size();i++) // iterate over all of the finishers
		{
			if (finishers.at(i)->generation < optimum->generation) // but just the valid ones, and see if it's shorter than the last valid one
				optimum = finishers.at(i);
		}
		bool done = false;
		AINode *e = optimum;
		while(!done)
		{
			if (e != NULL)
			{
				if (e->camefrom != NULL) // if the previous tile in this path exists
				{
					if (e->camefrom->camefrom == NULL)	// if the tile before the previous one exists (not the first tile in the path).
														// so this checks if this is the second tile.
					{
						if (screen[e->x][e->y] == 11)	// if this tile is marked as an elf tile, we're screwed.
						{
							result = PATHFIND_ENDISADJACENT;	// so say that the path ends adjacent to us.
							*savedX = e->x;
							*savedY = e->y;
							done = true;
						}
						else							//  otherwise, the second tile in the path is FREE! WOO.
						{
							*savedX = e->x;
							*savedY = e->y;
							result = PATHFIND_SUCCESS;
							done = true;
						}
					}
				}
				e = e->camefrom;
			}
			else
				done = true;
		}
	} // end if size > 0

	while(Q.size() > 0)
	{
		delete Q.at(0);
		Q.erase(Q.begin());
	}
	delete firstOptimum;
	return result;
}

/*class AIWalker
{
public:
	int myvisited[BOARD_SIZE][BOARD_SIZE];
	int x;
	int y;
	int generation;
	bool valid;
	AIWalker *previous;
};


int findPath(int x, int y, int destX, int destY, int *savedX, int *savedY)
{
	if ((x-1 == destX && y == destY) ||
		(x+1 == destX && y == destY) ||
		(x == destX && y == destY-1) ||
		(x == destX && y == destY+1))
		return PATHFIND_ENDISADJACENT;

	int visited[BOARD_SIZE][BOARD_SIZE];

	memset(visited,0,sizeof(int)*BOARD_SIZE*BOARD_SIZE);

	std::vector<AIWalker*> finishers;

	AIWalker *walker = new AIWalker();
	memcpy(walker->myvisited,visited,sizeof(int)*BOARD_SIZE*BOARD_SIZE);
	walker->x = x;
	walker->y = y;
	walker->valid = true;
	walker->generation = 0;
	walker->previous = NULL;

	std::vector<AIWalker*> Q;
	Q.push_back(walker);
	for(int i=0;i<Q.size();i++)
	{
		AIWalker *current = Q.at(i);
		visited[current->x][current->y] = 1;
		if (screen[current->x][current->y] == 11 && current != walker)
			current->valid = false;
		if (current->x == destX && current->y == destY)
		{
			//printf("I REACHED %i %i! I WIN! break out now\n",destX,destY);
			finishers.push_back(current);
			i = Q.size() * 5;
		}
		else
		{
			std::vector<AIWalker*> kids;
			if (current->x-1 >= 0)
			{
				if (screen[current->x-1][current->y] == 0 || screen[current->x-1][current->y] == 11 || screen[current->x-1][current->y] == 20)
					if (current->myvisited[current->x-1][current->y] == 0)
					{
						AIWalker *kid = new AIWalker();
						kid->x = current->x-1;
						kid->y = current->y;
						kid->valid = current->valid;
						kid->generation = current->generation+1;
						kid->previous = current;
						kids.push_back(kid);
					}
			}
			if (current->x+1 < BOARD_SIZE)
			{
				if (screen[current->x+1][current->y] == 0 || screen[current->x+1][current->y] == 11 || screen[current->x+1][current->y] == 20)
					if (current->myvisited[current->x+1][current->y] == 0)
					{
						AIWalker *kid = new AIWalker();
						kid->x = current->x+1;
						kid->y = current->y;
						kid->valid = current->valid;
						kid->generation = current->generation+1;
						kid->previous = current;
						kids.push_back(kid);
					}
			}
			if (current->y-1 >= 0)
			{
				if (screen[current->x][current->y-1] == 0 || screen[current->x][current->y-1] == 11 || screen[current->x][current->y-1] == 20)
					if (current->myvisited[current->x][current->y-1] == 0)
					{
						AIWalker *kid = new AIWalker();
						kid->x = current->x;
						kid->y = current->y-1;
						kid->valid = current->valid;
						kid->generation = current->generation+1;
						kid->previous = current;
						kids.push_back(kid);
					}
			}
			if (current->y+1 < BOARD_SIZE)
			{
				if (screen[current->x][current->y+1] == 0 || screen[current->x][current->y+1] == 11 || screen[current->x][current->y+1] == 20)
					if (current->myvisited[current->x][current->y+1] == 0)
					{
						AIWalker *kid = new AIWalker();
						kid->x = current->x;
						kid->y = current->y+1;
						kid->valid = current->valid;
						kid->generation = current->generation+1;
						kid->previous = current;
						kids.push_back(kid);
					}
			}
			bool allBastardChildren = true;
			for(int qbob=0;qbob<kids.size();qbob++)
			{
				if (screen[kids.at(qbob)->x][kids.at(qbob)->y] != 11)
				{
					allBastardChildren = false;
					memcpy(kids.at(qbob)->myvisited,current->myvisited,sizeof(int)*BOARD_SIZE*BOARD_SIZE);
					Q.push_back(kids.at(qbob));
				}
			}
			if (allBastardChildren)
				finishers.push_back(current);
		} // end if current = dest
	}
	
	int result = PATHFIND_FAILURE;
	AIWalker *firstLongest = new AIWalker();
	firstLongest->generation = 0;
	AIWalker *longest = firstLongest;
	if (finishers.size() > 0)
	{
		for(int i=0;i<finishers.size();i++) // iterate over all of the finishers
		{
			if (finishers.at(i)->generation > longest->generation) // but just the valid ones, and see if it's shorter than the last valid one
				longest = finishers.at(i);
		}
		bool done = false;
		AIWalker *e = longest;
		while(!done)
		{
			if (e->previous != NULL) // if the previous tile in this path exists
			{
				if (e->previous->previous == NULL)	// if the tile before the previous one exists (not the first tile in the path).
													// so this checks if this is the second tile.
				{
					if (screen[e->x][e->y] == 11)	// if this tile is marked as an elf tile, we're screwed.
					{
						result = PATHFIND_ENDISADJACENT;	// so say that the path ends adjacent to us.
						*savedX = e->x;
						*savedY = e->y;
						done = true;
					}
					else							//  otherwise, the second tile in the path is FREE! WOO.
					{
						*savedX = e->x;
						*savedY = e->y;
						result = PATHFIND_SUCCESS;
						done = true;
					}
				}
			}
			e = e->previous;
		}
	} // end if size > 0

	while(Q.size() > 0)
	{
		delete Q.at(0);
		Q.erase(Q.begin());
	}
	delete firstLongest;
	return result;
}*/