
#include "ZoneManager.h"

#include "MemoryManager/debugNew.h"

using namespace ground;

ZoneManager* ZoneManager::zoneManager;

ZoneManager::ZoneManager()
{
	map = NULL;
	this->zoneHaveBeenComputed = false;
	strongZone.clear();
	naturalAxe.clear();
	forestZone.clear();
}

ZoneManager::~ZoneManager()
{
	//on supprime les zone de la mémoire
	this->unloadComputedZone();

	//on rend la mémoire des variable
}

ZoneManager& ZoneManager::getInstance()
{
	if(zoneManager==NULL) {
		zoneManager = new ZoneManager();
	}
	return *zoneManager;
}

void ZoneManager::destroy()
{
	delete zoneManager;
	zoneManager = NULL;
}

void ZoneManager::unloadComputedZone()
{
	if(this->zoneHaveBeenComputed) {
		this->zoneHaveBeenComputed = false;

		//on supprime les zone fortes de la mémoire
		std::map<int,ZoneStrong*>::iterator itSZ;
		for(itSZ=strongZone.begin();itSZ!=strongZone.end();itSZ++) {
			delete itSZ->second;
		}
		strongZone.clear();

		//on supprime les axes naturels
		std::map<int,AxeNatural*>::iterator itAN;
		for(itAN=naturalAxe.begin();itAN!=naturalAxe.end();itAN++) {
			delete itAN->second;
		}
		naturalAxe.clear();

		//on supprime les forets
		std::map<int,ZoneForest*>::iterator itFZ;
		for(itFZ=forestZone.begin();itFZ!=forestZone.end();itFZ++) {
			delete itFZ->second;
		}
		forestZone.clear();

		//on ne pointe plus sur un map
		map = NULL;
	}
}

void ZoneManager::loadZoneAxe(GroundMap& t, std::string file){
	Case *** c = t.getCases();
	int w = t.getWidth(); 
	int h = t.getHeight();
	map = &t;
	file += ".info";
	FILE * fichier = fopen(file.c_str(),"rb");
	if (fichier != NULL){
		printf("loading map analyse informations from file \"%s\"\n",file.c_str());
		float dangerZoneInensity;
		float naturalAxeIntensity;
		float strongZoneIntensity;
		int dangerZoneId;
		int naturalAxeId;
		int strongZoneId;
		int forestZoneId;
		for (int i = 0; i < w; i++){
			for (int j = 0; j < h; j++){
				fread(&dangerZoneInensity,sizeof(float),1,fichier);
				fread(&dangerZoneId,sizeof(int),1,fichier);
				fread(&naturalAxeIntensity,sizeof(float),1,fichier);
				fread(&naturalAxeId,sizeof(int),1,fichier);
				fread(&strongZoneIntensity,sizeof(float),1,fichier);
				fread(&strongZoneId,sizeof(int),1,fichier);
				fread(&forestZoneId,sizeof(int),1,fichier);
				c[i][j]->setDangerZoneIntensity(dangerZoneInensity);
				c[i][j]->setDangerZoneID(dangerZoneId);
				c[i][j]->setNaturalAxeIntensity(naturalAxeIntensity);
				c[i][j]->setNaturalAxeID(naturalAxeId);
				c[i][j]->setStrongZoneIntensity(strongZoneIntensity);
				c[i][j]->setStrongZoneID(strongZoneId);
				c[i][j]->setForestZoneID(forestZoneId);
			}
		}
		/////////////////////////////////////
		////////// MISE EN CLASSES //////////
		/////////////////////////////////////
		float min,max,med;

		//zone forte
		for(int i=0;i<w;i+=1){
			for(int j=0;j<h;j+=1){
				if( c[i][j]->isPassable() && c[i][j]->getStrongZoneIntensity()>0.0f && c[i][j]->getStrongZoneID()==-1 ){
					ZoneStrong* s = new ZoneStrong();
					s->id = this->strongZone.size();	//l'identifiant libre suivant
					s->cases.clear();
					this->strongZone[s->id] = s;		//enregistrement de la zone
					this->rec_computeStrongZoneFromACase(c[i][j],s);//parcour récursif de la zone pour enregistrement

					//calcul attribut de collision
					s->computeCollisionArea();

					//calcul des attributs de la zone forte
					min = 9999.0f;
					max = -9999.0f;
					med = 0.0f;			//contiendra la somme en attendant le calcul de la moyenne final
					for(std::vector<Case*>::iterator it = s->cases.begin() ; it!=s->cases.end() ;it++ )
					{
						if((*it)->getElevation()<min) min = (*it)->getElevation();
						if((*it)->getElevation()>max) min = (*it)->getElevation();
						med += (*it)->getElevation();
					}
					s->maxValue = max;
					s->minValue = min;
					s->medValue = med/s->cases.size();	//la taille n'est jamais null(sinon on aurai pas créer de zone)
				}
			}
		}
		//axe naturel
		for(int i=0;i<w;i+=1){
			for(int j=0;j<h;j+=1){
				if( c[i][j]->isPassable() && c[i][j]->getNaturalAxeIntensity()>0.0f && c[i][j]->getNaturalAxeID()==-1 ){
					AxeNatural* n = new AxeNatural();
					n->id = this->naturalAxe.size();	//l'identifiant libre suivant
					n->cases.clear();
					this->naturalAxe[n->id] = n;		//enregistrement de l'axe
					this->rec_computeNaturalAxeFromACase(c[i][j],n);//parcour récursif de l'axe pour enregistrement

					//calcul attribut de collision
					n->computeCollisionArea();

					//calcul des attributs de la zone forte
					min = 9999.0f;
					max = -9999.0f;
					med = 0.0f;			//contiendra la somme en attendant le calcul de la moyenne final
					for(std::vector<Case*>::iterator it = n->cases.begin() ; it!=n->cases.end() ;it++ )
					{
						if((*it)->getElevation()<min) min = (*it)->getElevation();
						if((*it)->getElevation()>max) min = (*it)->getElevation();
						med += (*it)->getElevation();
					}
					n->maxValue = max;
					n->minValue = min;
					n->medValue = med/n->cases.size();	//la taille n'est jamais null(sinon on aurai pas créer de zone)
				}
			}
		}
		//foret
		for(int i=0;i<w;i+=1){
			for(int j=0;j<h;j+=1){
				if( c[i][j]->isPassable() && map->getCases()[i][j]->getForestZoneID()==-1 &&
				( map->getCases()[i][j]->getGroundType()== FOREST ||
				  map->getCases()[i][j]->getGroundType()== OREE)
				) {
					ZoneForest* f = new ZoneForest();
					f->id = this->forestZone.size();	//l'identifiant libre suivant
					f->cases.clear();
					this->forestZone[f->id] = f;		//enregistrement de l'axe
					this->rec_computeForestZoneFromACase(c[i][j],f);//parcour récursif de l'axe pour enregistrement

					//calcul attribut de collision
					f->computeCollisionArea();
				}
			}
		}
		this->zoneHaveBeenComputed = true;
		printf("loading finished\n");
	}else{
		printf("computing map analyse informations\n");
		computeZoneAxe(t);
		printf("map analyse finished.\n");
		// sauvegarde des donnée
		printf("saving map analyse informations on file \"%s\"\n",file.c_str());
		FILE * save = fopen(file.c_str(),"wb");
		if (save != NULL){
			float dangerZoneInensity;
			float naturalAxeIntensity;
			float strongZoneIntensity;
			int dangerZoneId;
			int naturalAxeId;
			int strongZoneId;
			int forestZoneId;
			for (int i = 0; i < w; i++){
				for (int j = 0; j < h; j++){
					dangerZoneInensity = c[i][j]->getDangerZoneIntensity();
					naturalAxeIntensity = c[i][j]->getNaturalAxeIntensity();
					strongZoneIntensity = c[i][j]->getStrongZoneIntensity();
					dangerZoneId = c[i][j]->getDangerZoneID();
					naturalAxeId = c[i][j]->getNaturalAxeID();
					strongZoneId = c[i][j]->getStrongZoneID();
					forestZoneId = c[i][j]->getForestZoneID();
					fwrite(&dangerZoneInensity,sizeof(float),1,save);
					fwrite(&dangerZoneId,sizeof(int),1,save);
					fwrite(&naturalAxeIntensity,sizeof(float),1,save);
					fwrite(&naturalAxeId,sizeof(int),1,save);
					fwrite(&strongZoneIntensity,sizeof(float),1,save);
					fwrite(&strongZoneId,sizeof(int),1,save);
					fwrite(&forestZoneId,sizeof(int),1,save);
				}
			}
			printf("map analyse informations saving finished\n"); 
		}else{
			printf("unable to open \"%s\" file\n",file.c_str());
		}

	}
}


void ZoneManager::computeZoneAxe(GroundMap& t)
{
	if(zoneHaveBeenComputed) this->unloadComputedZone();
	this->zoneHaveBeenComputed = true;

	map = &t;
	int w = (int)t.getWidth();
	int h = (int)t.getHeight();
	Case*** c = t.getCases();
	float sum = 0.0f;
	float dist = 0.0f;
	float tmp = 0.0f;
	const float scale = (256.0f*RAPPORT_HAUTEUR)*(ARCHER_TIR_DISTANCE)*(ARCHER_TIR_DISTANCE);//l'échelle pour avoir danger entre 0 et 1
	const float placeForte_oreeDuBois = 0.2f;	//1.0f de valeur pour orée du bois près de 5 case de foret
	const float placeDanger_oreeDuBoisScale = 0.11f;

	///////////////////////////////////////////
	////////// CALCUL ZONE DE DANGER //////////
	///////////////////////////////////////////

	//prise en compte du facteur hauteur sur une zone d'influence de rayon la distance de tir d'un archer
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			if(!c[i][j]->isPassable()) continue;

			for(int i2=i-(int)ARCHER_TIR_DISTANCE;i2<=i+(int)ARCHER_TIR_DISTANCE;i2++) {
				for(int j2=j-(int)ARCHER_TIR_DISTANCE;j2<=j+(int)ARCHER_TIR_DISTANCE;j2++) {
					if(i2>=0 && j2>=0 && i2<w && j2<h) {
						float dist = sqrt((float)((i-i2)*(i-i2)+(j-j2)*(j-j2)));	//distance entre les deux case
						if( dist!=0.0f && dist <= ARCHER_TIR_DISTANCE ) {
							//intensité du danger
							tmp = c[i2][j2]->getElevation() - c[i][j]->getElevation();
							if(tmp>0)
								sum += tmp;
						}
					}
				}
			}
			c[i][j]->setDangerZoneIntensity(sum);	//enregistrement de la somme
			sum = 0.0f;								//remise a 0 pour prochaine case
		}
	}
	//on normalise le danger par rapport a la zone si celui ci est supérieur a 0. Sinon, on met a 0 le danger
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			//si l'intensité est >0, on scale, sinon on met a 0.
			c[i][j]->getDangerZoneIntensity()>0.0f ? c[i][j]->setDangerZoneIntensity( c[i][j]->getDangerZoneIntensity()/scale ) : c[i][j]->setDangerZoneIntensity(0.0f);
		}
	}
	//prise en compte de l'orée du bois
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			if(!c[i][j]->isPassable()) continue;

			//on ne s'occupe pas du terrain de foret
			if( c[i][j]->getGroundType()==FOREST || c[i][j]->getGroundType()==FOREST ) continue;

			//on va parcourir les point au alentour a distance de tir d'un archer
			for(int i2=i-(int)ARCHER_TIR_DISTANCE;i2<=i+(int)ARCHER_TIR_DISTANCE;i2++) {
				for(int j2=j-(int)ARCHER_TIR_DISTANCE;j2<=j+(int)ARCHER_TIR_DISTANCE;j2++) {
					//pas le meme point ou pas un point en dehors de la carte
					if( i2>=0 && j2>=0 && i2<w && j2<h && !(j==j2 && i==i2) ) {
						float dist = sqrt((float)((i-i2)*(i-i2)+(j-j2)*(j-j2)));	//distance entre les deux case
						if( c[i2][j2]->getGroundType() == FOREST ) {
							//la case est proche de l'orée d'un bois et donc on augmente l'intensité de son danger
							c[i][j]->setDangerZoneIntensity( c[i][j]->getDangerZoneIntensity() + placeDanger_oreeDuBoisScale*(ARCHER_TIR_DISTANCE-dist)/ARCHER_TIR_DISTANCE );
						}
					}
				}
			}
		}
	}
	
	///////////////////////////////////////
	////////// CALCUL ZONE FORTE //////////
	///////////////////////////////////////

	//prise en compte du facteur hauteur
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			if(!c[i][j]->isPassable()) continue;

			for(int i2=i-(int)ARCHER_TIR_DISTANCE;i2<=i+(int)ARCHER_TIR_DISTANCE;i2++) {
				for(int j2=j-(int)ARCHER_TIR_DISTANCE;j2<=j+(int)ARCHER_TIR_DISTANCE;j2++) {
					if(i2>=0 && j2>=0 && i2<w && j2<h) {
						float dist = sqrt((float)((i-i2)*(i-i2)+(j-j2)*(j-j2)));	//distance entre les deux case
						if( dist!=0.0f && dist <= ARCHER_TIR_DISTANCE ) {
							//intensité de l'avantage
							tmp = c[i][j]->getElevation() - c[i2][j2]->getElevation();
							if(tmp>0)
								sum += tmp;
						}
					}
				}
			}
			c[i][j]->setStrongZoneIntensity(sum*1.15f);	//enregistrement de la somme
			sum = 0.0f;								//remise a 0 pour prochaine case
		}
	}
	//prise en compte de l'orée du bois
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			if(!c[i][j]->isPassable()) continue;

			//si l'intensité est >0, on scale, sinon on met a 0.(pour le calcul précedent de prise en compte du facteur hauteur)
			c[i][j]->getStrongZoneIntensity()>0.0f ? c[i][j]->setStrongZoneIntensity( c[i][j]->getStrongZoneIntensity()/scale ) : c[i][j]->setStrongZoneIntensity(0.0f);

			if( c[i][j]->getGroundType()== OREE ) {
				//la case est à l'orée du bois : on augmente son intensité en tant que place forte.
				//si la case a de la foret a coté, on augmente son intensité(foret plus grosse)
				c[i][j]->setStrongZoneIntensity( c[i][j]->getStrongZoneIntensity() + placeForte_oreeDuBois + placeForte_oreeDuBois*getNextWoodCount(i,j) );
			}
		}
	}
	
	////////////////////////////////////////
	////////// CALCUL AXE NATUREL //////////
	////////////////////////////////////////

	ground::MatrixPathFinder* p = new ground::MatrixPathFinder();
	p->enableStencil(false);
	Point2D start,end;
	std::vector<Point2D> path;
	p->setMatrix((AbstractCase***)c,w,h);
	std::vector<Point2D>::iterator it;
	//on cherche les chemin en étoile autour des cases testes
	const float naturalAxe_addContributionPATH = 0.01f;	//0.00125f   0.008f
	const float pi2 = 2*3.141592654f;
	const float step = pi2/8.0f;
	const float radius = 20.0f;
	const int stepC = 4;
	for(int i=0;i<w;i+=stepC) {
		for(int j=0;j<h;j+=stepC) {
			if(!c[i][j]->isPassable()) continue;

			start.setCoord((float)(i),(float)(j));
			for(float alpha=0;alpha<pi2;alpha+=step) {
				end.setCoord( (int)((float)i+ radius*cos(alpha)), (int)((float)j+ radius*sin(alpha)) );
				if( end.getX()<0 || end.getY()<0 || end.getX()>=w || end.getY()>=h ||
					!c[i][j]->isPassable() )
					continue;

				p->findPath(start,end);
				path = p->getPath();
				//on va itérer sur les case pour augmenter la valeur axe naturel
				for(it=path.begin();it!=path.end();it++) {
					this->addNaturalAxeContribution((int)(it->getX()),(int)(it->getY()),4,naturalAxe_addContributionPATH);
				}
				path.clear();
			}
		}
	}
	delete p;

	
	///////////////////////////////////////
	////////// SCALE DES VALEURS //////////
	///////////////////////////////////////

	//zone forte
	for(int i=0;i<w;i+=1) {
		for(int j=0;j<h;j+=1) {
			//si la case n'est pas passable ou si c'est de la l'orée de foret, on ne scale pas
			if(!c[i][j]->isPassable() || c[i][j]->getGroundType()==OREE) continue;
			c[i][j]->setStrongZoneIntensity( c[i][j]->getStrongZoneIntensity()>1.0f ? (c[i][j]->getStrongZoneIntensity()-1.0f) : 0.0f );
		}
	}
	//axe naturel
	for(int i=0;i<w;i+=1) {
		for(int j=0;j<h;j+=1) {
			//si la case n'est pas passable, on ne scale pas
			if(!c[i][j]->isPassable()) continue;
			c[i][j]->setNaturalAxeIntensity( c[i][j]->getNaturalAxeIntensity() - naturalAxe_addContributionPATH*radius*stepC*step );
			c[i][j]->setNaturalAxeIntensity( c[i][j]->getNaturalAxeIntensity()>1.0f ? (c[i][j]->getNaturalAxeIntensity()-1.0f) : 0.0f );
		}
	}

	
	/////////////////////////////////////
	////////// MISE EN CLASSES //////////
	/////////////////////////////////////
	float min,max,med;

	//zone forte
	for(int i=0;i<w;i+=1){
		for(int j=0;j<h;j+=1){
			if( c[i][j]->isPassable() && c[i][j]->getStrongZoneIntensity()>0.0f && c[i][j]->getStrongZoneID()==-1 ){
				ZoneStrong* s = new ZoneStrong();
				s->id = this->strongZone.size();	//l'identifiant libre suivant
				s->cases.clear();
				this->strongZone[s->id] = s;		//enregistrement de la zone
				this->rec_computeStrongZoneFromACase(c[i][j],s);//parcour récursif de la zone pour enregistrement

				//calcul attribut de collision
				s->computeCollisionArea();

				//calcul des attributs de la zone forte
				min = 9999.0f;
				max = -9999.0f;
				med = 0.0f;			//contiendra la somme en attendant le calcul de la moyenne final
				for(std::vector<Case*>::iterator it = s->cases.begin() ; it!=s->cases.end() ;it++ )
				{
					if((*it)->getElevation()<min) min = (*it)->getElevation();
					if((*it)->getElevation()>max) min = (*it)->getElevation();
					med += (*it)->getElevation();
				}
				s->maxValue = max;
				s->minValue = min;
				s->medValue = med/s->cases.size();	//la taille n'est jamais null(sinon on aurai pas créer de zone)
			}
		}
	}
	//axe naturel
	for(int i=0;i<w;i+=1){
		for(int j=0;j<h;j+=1){
			if( c[i][j]->isPassable() && c[i][j]->getNaturalAxeIntensity()>0.0f && c[i][j]->getNaturalAxeID()==-1 ){
				AxeNatural* n = new AxeNatural();
				n->id = this->naturalAxe.size();	//l'identifiant libre suivant
				n->cases.clear();
				this->naturalAxe[n->id] = n;		//enregistrement de l'axe
				this->rec_computeNaturalAxeFromACase(c[i][j],n);//parcour récursif de l'axe pour enregistrement

				//calcul attribut de collision
				n->computeCollisionArea();

				//calcul des attributs de la zone forte
				min = 9999.0f;
				max = -9999.0f;
				med = 0.0f;			//contiendra la somme en attendant le calcul de la moyenne final
				for(std::vector<Case*>::iterator it = n->cases.begin() ; it!=n->cases.end() ;it++ )
				{
					if((*it)->getElevation()<min) min = (*it)->getElevation();
					if((*it)->getElevation()>max) min = (*it)->getElevation();
					med += (*it)->getElevation();
				}
				n->maxValue = max;
				n->minValue = min;
				n->medValue = med/n->cases.size();	//la taille n'est jamais null(sinon on aurai pas créer de zone)
			}
		}
	}
	//foret
	for(int i=0;i<w;i+=1){
		for(int j=0;j<h;j+=1){
			if( c[i][j]->isPassable() && map->getCases()[i][j]->getForestZoneID()==-1 &&
			( map->getCases()[i][j]->getGroundType()== FOREST ||
			  map->getCases()[i][j]->getGroundType()== OREE)
		    ) {
				ZoneForest* f = new ZoneForest();
				f->id = this->forestZone.size();	//l'identifiant libre suivant
				f->cases.clear();
				this->forestZone[f->id] = f;		//enregistrement de l'axe
				this->rec_computeForestZoneFromACase(c[i][j],f);//parcour récursif de l'axe pour enregistrement

				//calcul attribut de collision
				f->computeCollisionArea();
			}
		}
	}

}

int ZoneManager::getNextWoodCount(int i, int j)
{
	int res = 0;
	for(int i2=i-1;i2<=i+1;i2++) {
		for(int j2=j-1;j2<=j+1;j2++) {
			if(i2>=0 && j2>=0 && i2<(int)(map->getWidth()) && j2<(int)(map->getHeight())) {
				if( map->getCases()[i2][j2]->getGroundType()==FOREST )
					res++;
			}
		}
	}
	return res;
}

void ZoneManager::addNaturalAxeContribution(int i, int j, int k, float contrib)
{
	float tmp;

	for(int i2=i-k;i2<=i+k;i2++) {
		for(int j2=j-k;j2<=j+k;j2++) {
			if(i2>=0 && j2>=0 && i2<(int)(map->getWidth()) && j2<(int)(map->getHeight())) {
				if(!map->getCases()[i2][j2]->isPassable()) continue;

				tmp = sqrt((float)((i-i2)*(i-i2) + (j-j2)*(j-j2)));
				map->getCases()[i2][j2]->setNaturalAxeIntensity( map->getCases()[i2][j2]->getNaturalAxeIntensity() + ((float)k-tmp)*contrib/k);
			}
		}
	}
}

void ZoneManager::rec_computeStrongZoneFromACase(Case*c, ZoneStrong*z)
{
	static int dep[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };	//les déplacement avec une 4-connexités des zones
	int x = (int)c->getCoord()[0];
	int y = (int)c->getCoord()[1];
	int xc, yc;

	//on ajoute la case à la zone
	z->cases.push_back(c);
	//on donne l'id de la zone à la case
	c->setStrongZoneID(z->id);

	for(int i=0;i<4;i++){
		xc = x+dep[i][0];
		yc = y+dep[i][1];
		if(xc<0 || xc>=(int)map->getWidth() || yc<0 || yc>=(int)map->getHeight()) continue;

		if( map->getCases()[xc][yc]->isPassable() &&
			map->getCases()[xc][yc]->getStrongZoneIntensity()>0.0f && map->getCases()[xc][yc]->getStrongZoneID()==-1 &&
			( (map->getCases()[xc][yc]->getGroundType()==OREE && c->getGroundType()==OREE) ||	//que de la l'orée
				(map->getCases()[xc][yc]->getGroundType()!=OREE && c->getGroundType()!=OREE)		//autre que de l'orée
			)
			)
		{
			this->rec_computeStrongZoneFromACase(map->getCases()[xc][yc],z);
		}
	}
}

void ZoneManager::rec_computeNaturalAxeFromACase(Case*c, AxeNatural*a)
{
	static int dep[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };	//les déplacement avec une 4-connexités des zones
	int x = (int)c->getCoord()[0];
	int y = (int)c->getCoord()[1];
	int xc, yc;

	//on ajoute la case à la zone
	a->cases.push_back(c);
	//on donne l'id de la zone à la case
	c->setNaturalAxeID(a->id);

	for(int i=0;i<4;i++) {
		xc = x+dep[i][0];
		yc = y+dep[i][1];
		if(xc<0 || xc>=(int)map->getWidth() || yc<0 || yc>=(int)map->getHeight()) continue;

		if( map->getCases()[xc][yc]->isPassable() &&
			map->getCases()[xc][yc]->getNaturalAxeIntensity()>0.0f && map->getCases()[xc][yc]->getNaturalAxeID()==-1 ) {
			this->rec_computeNaturalAxeFromACase(map->getCases()[xc][yc],a);
		}
	}
}

void ZoneManager::rec_computeForestZoneFromACase(Case*c, ZoneForest*f)
{
	static int dep[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };	//les déplacement avec une 4-connexités des zones
	int x = (int)c->getCoord()[0];
	int y = (int)c->getCoord()[1];
	int xc, yc;

	//on ajoute la case à la zone
	f->cases.push_back(c);
	//on donne l'id de la zone à la case
	c->setForestZoneID(f->id);

	for(int i=0;i<4;i++) {
		xc = x+dep[i][0];
		yc = y+dep[i][1];
		if(xc<0 || xc>=(int)map->getWidth() || yc<0 || yc>=(int)map->getHeight()) continue;

		if( map->getCases()[xc][yc]->isPassable() && map->getCases()[xc][yc]->getForestZoneID()==-1 &&
			( map->getCases()[xc][yc]->getGroundType()== FOREST ||
			  map->getCases()[xc][yc]->getGroundType()== OREE)
		  ) {
			this->rec_computeForestZoneFromACase(map->getCases()[xc][yc],f);
		}
	}
}

const std::map<int,ZoneStrong*>& ZoneManager::getZoneStrong()
{
	return this->strongZone;
}

const std::map<int,AxeNatural*>& ZoneManager::getAxeNatural()
{
	return this->naturalAxe;
}

const std::map<int,ZoneForest*>& ZoneManager::getZoneForest()
{
	return this->forestZone;
}

