#include <algorithm>
#include <cstdio>
#include <queue>

#include "prologin.hh"

using namespace std;

const int oo = 1E9;

/*Position Position(int x, int y)
{
	Position retour;
	retour.x = x;
	retour.y = y;
	return retour;
}*/

struct Position
{
	int x, y, dist, prop;
	Position(int x = 0, int y = 0, int dist = 0, int prop = -1) : x(x), y(y), dist(dist), prop(prop) {}
	Position operator+(const Position& droite) const
	{
		return Position(x + droite.x, y + droite.y, dist + droite.dist, prop);
	}
	position pos()
	{
		position retour;
		retour.x = x;
		retour.y = y;
		return retour;
	}
};

case_type type_case(Position pos)
{
	return type_case(pos.pos());
}

Position dirs[4] = {Position(-1,0,1), Position(1,0,1), Position(0,-1,1), Position(0,1,1)};

int id, adv;

void partie_init()
{
	id = moi();
	adv = adversaire();
}

int propTuyau[TAILLE_TERRAIN][TAILLE_TERRAIN];

void jouer_tour()
{
	for(int iLig = 0; iLig < TAILLE_TERRAIN; ++iLig)
		for(int iCol = 0; iCol < TAILLE_TERRAIN; ++iCol)
			propTuyau[iCol][iLig] = -1;
	calculerProp();
	for(int iAction = 0; iAction < 4; ++iAction)
	{
		int closest = oo;
		int xMin = 0, yMin = 0;
		for(int iLig = 0; iLig < TAILLE_TERRAIN; ++iLig)
			for(int iCol = 0; iCol < TAILLE_TERRAIN; ++iCol)
				if(propTuyau[iCol][iLig] == id)
				{
					bool utile = false;
					for(int iDir = 0; iDir < 4; ++iDir)
					{
						Position newPos = Position(iCol, iLig) + dirs[iDir];
						utile = utile || (newPos.x >= 0 && newPos.x < TAILLE_TERRAIN && newPos.y >= 0 && newPos.y < TAILLE_TERRAIN && est_libre(newPos.pos()));
					}
					if(utile)
					{
						vector<Position> depart;
						depart.push_back(Position(iCol, iLig));
						int dist = plusProches(depart, PULSAR).front().dist;
						if(dist < closest)
						{
							closest = dist;
							xMin = iCol;
							yMin = iLig;
						}
					}
				}
		closest = oo;
		int x = 0, y = 0;
		for(int iDir = 0; iDir < 4; ++iDir)
		{
			Position newPos = Position(xMin, yMin) + dirs[iDir];
			if(newPos.x >= 0 && newPos.x < TAILLE_TERRAIN && newPos.y >= 0 && newPos.y < TAILLE_TERRAIN && est_libre(newPos.pos()))
			{
				vector<Position> depart;
				depart.push_back(newPos);
				int dist = plusProches(depart, PULSAR).front().dist;
				if(dist < closest)
				{
					closest = dist;
					x = newPos.x;
					y = newPos.y;
				}
			}
		}
		construire(Position(x, y).pos());
		propTuyau[x][y] = id;
	}
}

void partie_fin()
{
}

int idDejaVu = 0;
int dejaVu[TAILLE_TERRAIN][TAILLE_TERRAIN];

void calculerProp()
{
	++idDejaVu;
	queue<Position> file;
	auto base = ma_base();
	for(auto pos = base.begin(); pos != base.end(); ++pos)
		file.push(Position(pos->x, pos->y, 0, id));
	base = base_ennemie();
	for(auto pos = base.begin(); pos != base.end(); ++pos)
		file.push(Position(pos->x, pos->y, 0, adv));
	while(file.size())
	{
		Position curPos = file.front();
		file.pop();
		if(dejaVu[curPos.x][curPos.y] < idDejaVu)
		{
			dejaVu[curPos.x][curPos.y] = idDejaVu;
			propTuyau[curPos.x][curPos.y] = curPos.prop;
			for(int iDir = 0; iDir < 4; ++iDir)
			{
				Position newPos = curPos + dirs[iDir];
				if(newPos.x >= 0 && newPos.x < TAILLE_TERRAIN && newPos.y >= 0 && newPos.y < TAILLE_TERRAIN && est_tuyau(newPos.pos()))
					file.push(newPos);
			}
		}
	}
}

vector<Position> plusProchesPulsars(vector<Position> departs)
{
	++idDejaVu;
	queue<Position> file;
	vector<Position> reponse;
	for(auto depart = departs.begin(); depart != departs.end(); ++depart)
		file.push(*depart);
	while(file.size() && (reponse.empty() || reponse.front().dist < file.front().dist))
	{
		Position curPos = file.front();
		file.pop();
		if(type_case(curPos) == PULSAR)
			reponse.push_back(curPos);
		if(dejaVu[curPos.x][curPos.y] < idDejaVu && type_case(curPos) != PULSAR)
		{
			dejaVu[curPos.x][curPos.y] = idDejaVu;
			for(int iDir = 0; iDir < 4; ++iDir)
			{
				Position newPos = curPos + dirs[iDir];
				if(newPos.x >= 0 && newPos.x < TAILLE_TERRAIN && newPos.y >= 0 && newPos.y < TAILLE_TERRAIN && type_case(newPos) != TUYAU && type_case(newPos) != SUPER_TUYAU && type_case(newPos) != INTERDIT)
					file.push(newPos);
			}
		}
	}
	if(reponse.empty())
		reponse.push_back(Position(10, 10, oo));
	return reponse;
}
