import java.util.*;
import java.awt.*;

public class Creature extends Entite{
	
	boolean dansLeVide=false;
 					
 	String strType=new String();	
 	String typedelobjet=new String();	
 	String strModele=new String();	
	
	
	
	
	boolean open=false;
	
	boolean aCrie=false;
	
	private boolean aVuPerso=false;
	private Point versPersoPt=new Point(0,0);
	private Point veutAllerPt=new Point(0,0);
	
	private Entite objet=new Entite();
	private Entite matos=new Entite();
	
	private String espece=new String();
	private String nom=new String();
	
	//private String nomEquipement=new String(); 
	
	private boolean hostiliteBol=false;  //TRUE = HOSTILE
	private short prioriteInitiale=1;
	private short priorite=1;
	
	//	1 survie : fuit plus facilement, si perso tout pret devient hostile
	//  2 destruction: fuit plus difficilement, si hostile et voit le perso alors attaque
	//  3 or: caricature de nain
	//  4 nourriture: glouton
	//  5 vol: leprechaun
	//  6 protection : garde une zone
	//  7 patrouille : suit un circuit
	//
	//  la priorite est combinée à :
	// - l'hostilité
	// - le fait de voir ou non le perso
	// - la distance au perso
	//
	//
	//	voit perso -> si hostile	 -> priorite ? -> si proche, sinon
	//
	//				  si pas hostile -> priorite ? -> si proche, sinon		
	//
	//
	//	ne voit pas perso	-> priorite ?
	//
	//
	//
	
	int maxPower=0;
	int currentPower=0;
	
	
	
	
	
	
	private boolean mort=false;
	
	private String typeObjet=new String();
	private boolean visible=true;
	private String tileStr=new String();
	private String tileStrMort=new String();
	private int coordX=0;
	private int coordY=0;
	private int vue=0;
	private int rapidite=0;
	
	private boolean aBougeBol=false;
	
	
	
	
	//POUVOIRS////////////////////
	private boolean passemuraille=false;
	private boolean regenere=false;
	boolean nightvision=false;
	//////////////////////////////
	
	/////////ETATS///////////////////
	private int dureeEffetPoisonned=0;
	private boolean poisonned=false;
	private int effetPoison=0;
	//////////////////////////////////
	
	
	
	private int baseAtk=0;
	private int atkModifiee=0;
	private int baseDef=0;
	private int defModifiee=0;
	private int maxHitPoints=0;
	private int currentHitPoints=0;
	
	private int force=0;
	private int dexterite=0;
	private int intelligence=0;
	private int constitution=0;
	
	/////SKILLS/////////
	//int perception=0;
	//int discretion=0;
	//int melee=0;
	//int distance=0;
	//int magie=0;
	//int attunement=0;
	//int crocheter=0;
	//int pieges=0;
	//int identification=0;
	//int baratin=0;
	////////////////////
	
	
	private int niveau=0;
	
	//////////////////////
	private Vector equipementVect=new Vector();
	
	private int bonusAtkArme=0;
	private int bonusDefArmure=0;
	//////////////////////
	//////////////////////
	private Entite arme=new Entite();
	private Entite armure=new Entite();
	
	private boolean volant=false;
	
	
	private String nomE=new String();
	
	private boolean flee=false;
	
	String cri=new String();
	
	Monde monde;
	
	
	public Creature(Monde world,boolean ded,String especeC,String name,String nameE,boolean hostil,String typeObjetC,boolean visibleC,String tileStrC,String tileStrMortC,String shout){
	
		monde=world;
		espece=especeC;
		nom=name;
		nomE=nameE;
		hostiliteBol=hostil;
		mort=ded;
		typeObjet=typeObjetC;
		visible=visibleC;
		tileStr=tileStrC;
		tileStrMort=tileStrMortC;
		
		//nomEquipement=nom;
		
		cri=shout;
		
	}
	
	
	/*
	public void bruit(){
		new ThreadSon(cri,0).start();
	}*/
	
	public int getMaxPower(){
		return maxPower;
	}
	
	public void setMaxPower(int mxPower){
		maxPower=mxPower;
	}
	
	public int getCurrentPower(){
		return currentPower;
	}
	
	public void setCurrentPower(int currentPow){
		currentPower=currentPow;
	}
	
	
	public short getPrioriteInitiale(){
		return prioriteInitiale;
	}
	public void setPrioriteInitiale(short p){
		prioriteInitiale=p;
	}
	public short getPriorite(){
		return priorite;
	}
	public void setPriorite(short p){
		priorite=p;
	}
	
	
	
	public boolean getNightvision(){
		return nightvision;
	}
	public void setNightvision(boolean nv){
		nightvision=nv;
	}
	
	
	public void crier(Monde monde,int vx,int vy){
		
		
		float vol=0;
		int px=monde.perso.getCooX();
		int py=monde.perso.getCooY();
		
		int dx=Math.abs(vx-px);
		int dy=Math.abs(vy-py);
		
		if(dx>dy){vol=(float)dx*(-1);
		}
		else{vol=(float)dy*(-1);
		}
		
		vol=Math.round(vol/2);
		
		if(vol<-20){vol=-20;
		}
		
	
		new ThreadSon(cri,vol).start();
		
	}
	
	
		//////////////////////////////////////////
		
	public boolean getDansLeVide(){
	
		return dansLeVide;	
	}	
		
		
	public boolean getFlee(){
		
		return flee;
	}
	
	public void setFlee(boolean fl){
		flee=fl;
	}
	
	public String getNomE(){
		return nomE;
	}
	
	
	
	
	public String getCri(){
		return cri;
	}
	
	public boolean getVolant(){
		return volant;
	}
	
	public void setVolant(boolean v){
		volant=v;
	}
	
	
	
	public void effetNourriture(Personnage perso){
		
		
	}
	
	
	public void effetNourritureSECONDAIRE(Personnage perso){
		
		if(this.getPoisonned() && this.getDureeEffetPoisonned()>0){
			perso.message("C est empoisonne, vous vous sentez mal",false);
			perso.message("You are poisonned now",true);
			
			perso.setDegatPoisonned(perso.getDegatPoisonned()+this.getDegatPoisonned());
			perso.setPoisonned(true);
			perso.setDureeEffetPoisonned(perso.getDureeEffetPoisonned()+this.getDureeEffetPoisonned());
		}	
		
		
		//perso.setDegatPoisonned(perso.getDegatPoisonned()+5);
		//perso.setPoisonned(true);
		//perso.setDureeEffetPoisonned(perso.getDureeEffetPoisonned()+((int)(Math.abs(Math.random()*100))+1));
			
		
		
	}
	
	
	
	
	
	public int getNiveau(){
		return niveau;
	}
	
	public void setArmeEquipe(Entite w){
		if(!w.getCasse()){
		
			arme=w;
			//getEquipementVect().add(arme);
			setbonusAtkArme(arme.getBonusAtk());
		}	
	}
	
	public void setArmureEquipe(Entite a){
		if(!a.getCasse()){
			armure=a;
			//getEquipementVect().add(armure);
			setbonusDefArmure(armure.getBonusDef());
		}	
	}
	
	public Entite getArmeEquipe(){
		return arme;
	}
	
	public Entite getArmureEquipe(){
		return armure;
	}
	
	
	public void unequipArme(Entite arme){
		//getEquipementVect().remove(arme);
		setbonusAtkArme(0);
	
	}
	
	public void unequipArmure(Entite armure){
		//getEquipementVect().remove(armure);
		setbonusDefArmure(0);
	}
	
	
		
	
	
	public void setMort(Monde monde,boolean ded, int x, int y){
		mort=ded;
		
		
		
		if(mort==true){
		
			if(!equipementVect.isEmpty()){
				
				for(Enumeration en = equipementVect.elements();en.hasMoreElements();){
	                
	 				try{
	 					matos=(Entite) en.nextElement();
						//String typedelobjet=objet.getTypeObjet();
						//String strClass = (objet.getClass().getName());
						//String strModele= objet.getModele();
						//System.out.println(objet.getNom());
						
						monde.grille[x][y].add(matos);
						//equipementVect.remove(objet);
						
						
						
					}
					catch(NoSuchElementException exc){};
				}
				
				
				for(Enumeration en = equipementVect.elements();en.hasMoreElements();){
                
 				try{
 					matos=(Entite) en.nextElement();
					//String typedelobjet=objet.getTypeObjet();
					//String strClass = (objet.getClass().getName());
					//String strModele= objet.getModele();
					//System.out.println(objet.getNom());
					
					//monde.grille[x][y].add(objet);
					equipementVect.remove(matos);
					
					
					
				}
				catch(NoSuchElementException exc){};
				}

				
				
			}
			
		
		}
		
		///Les élémentaires disparaissent.
		if(mort==true && getClass().getName().compareTo("ElementalCategory")==0){
			monde.grille[x][y].remove(this);
		}
		
	}
	
	

	public boolean getMort(){
		return mort;
	}
	
	
	
	public Vector getEquipementVect(){
		
		return equipementVect;
	}
	
	public void setEquipementVect(Vector equip){
		equipementVect=equip;
	}
	
	
	
	public int getbonusAtkArme(){
		return bonusAtkArme;
	}
	
	public void setbonusAtkArme(int bonWeap){
		bonusAtkArme=bonWeap;
	}
	
	public int getbonusDefArmure(){
		return bonusDefArmure;
	}
	
	public void setbonusDefArmure(int bonDef){
		bonusDefArmure=bonDef;
	}
	
	
	public int getBaseAtk(){
		return baseAtk;
	}
	
	public void setBaseAtk(int atkBase){
		baseAtk=atkBase;
		
	}
	
	public int getAtkModifiee(){
		atkModifiee=getBaseAtk()+getbonusAtkArme();
		return atkModifiee;
	}
	
	/*
	public void setAtkModifiee(int atkModif){
		atkModifiee=atkModif;
		
	}*/
	
	public int getBaseDef(){
		return baseDef;
	}
	
	public void setBaseDef(int defBase){
		baseDef=defBase;
	}
	
	public int getDefModifiee(){
		defModifiee=getBaseDef()+getbonusDefArmure();
		return defModifiee;
	}
	
	/*
	public void setDefModifiee(int defModif){
		defModifiee=defModif;
		
	}*/
	
	
	public int getForce(){
		return force;
	}
	
	public void setForce(int fo){
		force=fo;
	}
	
	public int getDexterite(){
		return dexterite;
	}
	
	public void setDexterite(int dex){
		dexterite=dex;
	}
	
	public int getIntelligence(){
		return intelligence;
	}
	
	public void setIntelligence(int intel){
		intelligence=intel;
	}
	
	public int getConstitution(){
		return constitution;
	}
	
	public void setConstitution(int co){
		constitution=co;
	}
	

	/*
	public String getNomDequipement(){//PAS TERRIBLE
		return nomEquipement;
	}
	
	public void setNomDequipement(String nomEquip){//PAS TERRIBLE
		nomEquipement=nomEquip;
	}*/
	
	
	//////////////////////////////////////////////////
	////////// ETATS /////////////////////////////////
	//////////////////////////////////////////////////
	public void setDureeEffetPoisonned(int dp){
		dureeEffetPoisonned=dp;
	}
	public int getDureeEffetPoisonned(){
		return dureeEffetPoisonned;
	}
	public void setPoisonned(boolean sp){
		poisonned=sp;
	}
	public boolean getPoisonned(){
		return poisonned;
	}
	public void setDegatPoisonned(int dp){
		effetPoison=dp;
	}
	public int getDegatPoisonned(){
		return effetPoison;
	}
	
	public boolean getPasseMuraille(){
		return passemuraille;
	}
	
	public void setPasseMuraille(boolean passW){
		passemuraille=passW;
	}
	
	
	public void setRegenere(boolean rg){
		regenere=rg;
	}
	public boolean getRegenere(){
		return regenere;
	}
	///////////////////////////////////////////////
	///////////////////////////////////////////////
	///////////////////////////////////////////////
	
	
	
	public int getMaxHitPts(){
		return maxHitPoints;
	}
	
	public void setMaxHitPts(int mxHitPts){
		maxHitPoints=mxHitPts;
	}
	
	public int getCurrentHitPts(){
		return currentHitPoints;
	}
	
	public void setCurrentHitPts(int currentHitPts){
		currentHitPoints=currentHitPts;
	}
	
	
	public String getEspece(){
		return espece;
	}
	
	public int getRapidite(){
		return rapidite;	
	}
	
	public void setRapidite(int rapid){
		rapidite=rapid;
	}
	
	public int getVue(){
		return vue;
	}
	
	public void setVue(int view){
		
		vue=view;
	}
	
	
	public boolean getHostilite(){
		return hostiliteBol;
	}
	
	public void setHostilite(boolean hostil){
		hostiliteBol=hostil;
	}
	
	
	public void setABouge(boolean ilabouge){
		aBougeBol=ilabouge;
	}
	
	public boolean getABouge(){
		return aBougeBol;
	}
	
	
	public int getCooX(){
		return coordX;
	}
	
	public int getCooY(){
		return coordY;
	}
	
	public void setCooX(int cooX){
		coordX=cooX;
	}
	
	public void setCooY(int cooY){
		coordY=cooY;
	}
	
	
	public String getNom(){
		return nom;
	}
	
	
	
	public boolean getVisible(){
		return visible;
	}
	
	public void setVisible(boolean visibility){
		visible=visibility;
	}
	
	
	
	
	public String getTileStr(){
		
		if(mort==true){return tileStrMort;
		}
		else return tileStr;
		
		
	}
	
	
	public String getTileStrVivant(){
		return tileStr;
	}
	
	public String getTileStrMort(){
		return tileStrMort;
	}
	
	
	public String getTypeObjet(){
		return typeObjet;
	}
	





	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	


	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	//////////LOS ANALYSE ENVIRONNEMENT////////////////////
	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	
	
	//LOS ANALYSE
	ArrayList objetsVusParCreature=new ArrayList();
	
	
	public void radar(Monde monde){
		Point creaturePt=new Point(0,0);
		Point studyLOSPt=new Point(0,0);
		Point[] tabloPt;
		Entite ici=new Entite();
		boolean bloque=false;
		
		//monde.getBordureMONDE();
		try	{							
			objetsVusParCreature.clear();
			objetsVusParCreature.trimToSize();
			creaturePt=new Point(getCooX(),getCooY()); //centre
	    	studyLOSPt=new Point(getCooX(),getCooY());
	    	
	    	for(int i=0;i<monde.getBordureMONDE().size();i++){
	    	
	    		tabloPt=bresenham_line(creaturePt,(Point)monde.getBordureMONDE().get(i));
	    		
	    		bloque=false;
	    		
	    		for(int b=0;b<tabloPt.length;b++){
	    			studyLOSPt=tabloPt[b];
	    				
	    				if(!bloque  && aPorteeDeVue(studyLOSPt)){
		    			//parcours dans studyPt
							for(int z=0;z<monde.grille[(int)studyLOSPt.getX()][(int)studyLOSPt.getY()].size();z++){
			    				
			    				
			    				
			    				
			    				try{		
						 			ici = (Entite)monde.grille[(int)studyLOSPt.getX()][(int)studyLOSPt.getY()].get(z);
			    					
			    					
			    					if(	//!bloque  && 
			    						//ici.getClass().getName().compareTo("Gate")!=0 &&
				    					 ici.getTypeObjet().compareTo("Obstacle")!=0 &&
				    					 ici.getClass().getName().compareTo("VraiVide")!=0 &&
				    					 ici.getClass().getName().compareTo("Vide")!=0 &&
				    					 ici.getClass().getName().compareTo("Ombrage")!=0 &&
				    					 ici.getClass().getName().compareTo("Surface")!=0 &&
				    					 !ici.equals(this)&&
			    					 	!objetsVusParCreature.contains(ici)
			    					 ){
										objetsVusParCreature.add(ici);
									}
			    						
			    					
			    					
									
									if((ici.getClass().getName().compareTo("Gate")==0 || ici.getTypeObjet().compareTo("Obstacle")==0) 
											&& !ici.getCasse() 
											&& !ici.getOuvert()
											&& !getPasseMuraille())
									{
										bloque=true;
									}
									
								
			    				
			    				}
								catch(NoSuchElementException exc){};
		    				
			    				
			    			}
		    			}
	    			
	    		}
	    	
	    	}
			
		}
		catch(Exception e){e.printStackTrace();}
		
		
		/////////////
		////TEST/////
		/////////////
		Entite ici2=new Entite();
		
		for(int i=0;i<objetsVusParCreature.size();i++){
			ici2=(Entite)objetsVusParCreature.get(i);
			
			//calcul distance entre creature et l'objet.
			int iciX=(int)monde.getCoordonneesXY(ici2).getX();
			int iciY=(int)monde.getCoordonneesXY(ici2).getY();
			
			int diffX=this.getCooX()-iciX;
			int diffY=this.getCooY()-iciY;
			
			int dist= (int)Math.sqrt(Math.pow(diffX,2) + Math.pow(diffY,2));
			
			
			System.out.println(this.getNom()+"(p:"+this.getPriorite()+") see : "+ici2.getNom()+" distance ="+dist);
	    				
		}
		/////////////
		/////////////
		/////////////
	
	}
	/////////////////////////////////////////
	/////////////////////////////////////////
	public boolean aPorteeDeVue(Point stPt){ //pour le LOS d'analyse
		
		boolean rep=false;
		
		/*
		if(Math.abs(this.getCooX()-stPt.getX())<=this.getVue() && Math.abs(this.getCooY()-stPt.getY())<=this.getVue()){
		
			rep=true;
		}*/
		
		
			int diffX=this.getCooX()-(int)stPt.getX();
			int diffY=this.getCooY()-(int)stPt.getY();
			
			int dist= (int)Math.sqrt(Math.pow(diffX,2) + Math.pow(diffY,2));
			
			if(dist<=this.getVue()){rep=true;}
		
		
		
		return rep;
	}
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	
	
	
	
	
	
	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	///////////////MOUVEMENT = TOUR DE LA CREATURE ////////
	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////	
	public void mouvement(Monde monde,int origineX,int origineY){
		
		
		int destinationX=0;
		int destinationY=0;
		
		
		//LANCE ANALYSE DE L'ENVIRONNEMENT*********************
		//if(!getMort()){radar(monde);}
		
		
		
		
		//se deplace vers le perso si alignementStr="hostile" et si getEtat()==false
		//sinon si etat=false random
		//sinon rien
		
		
		//si vivant et hostile
		if(getHostilite() && !getMort()){
			
			//if(Math.abs(origineX-monde.perso.getCooX())<=this.getVue() && Math.abs(origineY-monde.perso.getCooY())<=this.getVue()){
			
			if(persoEstDansLOSCreature(monde)){
				
				if(!aCrie && persoAPorteeDeVue(monde)){
					crier(monde,origineX,origineY);
					aCrie=true;
				}
				
				
				aVuPerso=true;
				veutAllerPt=new Point(monde.perso.getCooX(),monde.perso.getCooY()); /// modifié par variation
				
				
				
				//lancer methode se diriger vers perso
				versPersoPt=chercheVersPerso(monde,origineX,origineY,flee); /// modifié par variation
				double destiXTemp=versPersoPt.getX();
				double destiYTemp=versPersoPt.getY();
				int destiX=(int)destiXTemp;
				int destiY=(int)destiYTemp;
				
				
				
				///analyse arrivée
				Point destinationPt=analyseMouvementArrivee(monde,this,monde.grille[destiX][destiY],origineX,origineY,destiX,destiY);
				
				//System.out.println("destiX "+destiX+" destiY"+destiY);
				
				
				double destX=destinationPt.getX();
				double destY=destinationPt.getY();
				destinationX=(int)destX;
				destinationY=(int)destY;
			}	
			else{
				if(!aVuPerso){
				
					Point destinationPt=destinationAleatoire(monde,this,origineX,origineY);
					double destX=destinationPt.getX();
					double destY=destinationPt.getY();
					destinationX=(int)destX;
					destinationY=(int)destY;
				}
				else{ // va là où il a vu le perso pour la dernière fois /// modifié par variation
					Point destinationPtTemp=veutAllerA(origineX,origineY,(int)veutAllerPt.getX(),(int)veutAllerPt.getY());
					double destiXTemp=destinationPtTemp.getX();
					double destiYTemp=destinationPtTemp.getY();
					int destiX=(int)destiXTemp;
					int destiY=(int)destiYTemp;
					
					
					
					
					Point destinationPt=analyseMouvementArrivee(monde,this,monde.grille[destiX][destiY],origineX,origineY,destiX,destiY);
			
					
					double destX=destinationPt.getX();
					double destY=destinationPt.getY();
					destinationX=(int)destX;
					destinationY=(int)destY;
					
					//System.out.println("Creature avait vu le perso en "+veutAllerPt.getX()+" "+veutAllerPt.getY());
					
				}
				
				
			}		
			
			
		}
		
		
		
		
		
		//si vivant mais pas hostile
		if(!this.getHostilite() && !this.getMort()){
			
			Point destinationPt=destinationAleatoire(monde,this,origineX,origineY);
			double destX=destinationPt.getX();
			double destY=destinationPt.getY();
			destinationX=(int)destX;
			destinationY=(int)destY;
			
		}
		
		
		
		
		//si mort
		if(this.getMort()){
			destinationX=origineX;
			destinationY=origineY;
		}
		
		else{
			monde.grille[origineX][origineY].remove(this);
			monde.grille[destinationX][destinationY].add(this);	
		
			this.setCooX(destinationX);
			this.setCooY(destinationY);
		
		
			//analyseDuSol(monde,getCooX(),getCooY());
		}
		
	}
	
	
	///////////////////////////////////////
	///////////////////////////////////////
	///////////////////////////////////////
	///////////////////////////////////////
	///////////////////////////////////////
	public Point variationDeMouvement(Point oriPt, Point desPt){
		// utilisé dans chercheVersPerso et veutAllerA
		
		//System.out.println("VARIATION MOUVEMENT");
		
		int difX=(int)(oriPt.getX()-desPt.getX());
		int difY=(int)(oriPt.getY()-desPt.getY());
		
		int modX=0;
		int modY=0;
		int modShrt=0;
		
		if((int)(Math.random()*100)+1<30){modShrt=1;}
		else{modShrt=0;}
		
		
		if((int)(Math.random()*100)+1<50 && modShrt==1){modShrt=-1;}
		
		boolean al=false;
		if((int)(Math.random()*100)+1<50){al=true;}
		
		
		if(difX>0){ 
			if(difY==0){	//va à l'ouest
				modY=modShrt;
			}
			else if(difY>0){		// nord ouest
				if(al){
					modY=Math.abs(modShrt);
				}
				else{
					modX=Math.abs(modShrt);
				}
						
			}
			else if(difY<0){ 	// sud ouest
				if(al){
					modY=(-1)*Math.abs(modShrt);
				}
				else{
					modX=Math.abs(modShrt);
				}
				
			}	
 		}
 		
 		else if(difX<0){ 
 			if(difY==0){	//est
 				modY=modShrt;
 			}
 			else if(difY>0){		// nord est
 				if(al){
					modY=Math.abs(modShrt);
				}
				else{
					modX=(-1)*Math.abs(modShrt);
				}
 				
			}
			else if(difY<0){ 	// sud est
				if(al){
					modY=(-1)*Math.abs(modShrt);
				}
				else{
					modX=(-1)*Math.abs(modShrt);
				}
				
			}
 				
 		}
 		
 		else if(difX==0){
 			if(difY<0){		//sud 
 				modX=modShrt;	
 			}
 			else if(difY>0){		// nord
 				modX=modShrt;	
 			}
 			
 			else if(difY==0){
 				modX=0;
 				modY=0;
 			
 			}
 		}
 		
 		//System.out.println("modX "+modX+"  modY "+modY);
		
		return new Point((int)desPt.getX()+modX,(int)desPt.getY()+modY);
	}
	
	///////////////////////////////////////
	///////////////////////////////////////
	///////////////////////////////////////
	///////////////////////////////////////
	
	public Point veutAllerA(int ox,int oy, int dx, int dy){
		
 		double differenceCoordX=ox-dx;
 		double differenceCoordY=oy-dy;
 		
 		int destX=ox;
 		int destY=oy;
 		
 		if(differenceCoordX<0){ destX=ox+1;
 		}
 		if(differenceCoordX>0){ destX=ox-1;
 		}
 		if(differenceCoordY<0){ destY=oy+1;
 		}
 		if(differenceCoordY>0){ destY=oy-1;
 		}
 		
		//System.out.println("Veut Aller :"+destX+" "+destY);
		
		/////////////////////////////////////
		//VARIATION DU MOUVEMENT/////////////   le remettre ?????????????
		
		
		//// le remettre ?????????????
		Point vraieArriveePt=variationDeMouvement(new Point(ox,oy),new Point(destX,destY));
		
		
		//System.out.println("***TEST de variation du mouvement depuis chercheVersPerso***");
		//System.out.println(getNom()+": Origine  "+new Point(ox,oy));
		//System.out.println(getNom()+": Arrivee  "+new Point(destX,destY));
		//System.out.println(getNom()+": Arrivee2 "+vraieArriveePt);
		
		
		//	le remettre ?????????????
		return vraieArriveePt;		
		/////////////////////////////////////
		/////////////////////////////////////
		
		//return new Point(destX,destY);
		
		
	}
	
	///////////////////////////////////////
	
	public boolean persoAPorteeDeVue(Monde monde){ //ne sert que pour le cri
		
		boolean rep=false;
		
		/*if(Math.abs(this.getCooX()-monde.perso.getCooX())<=this.getVue() && Math.abs(this.getCooY()-monde.perso.getCooY())<=this.getVue()){
		
			rep=true;
		}*/
		
		
			int diffX=this.getCooX()-monde.perso.getCooX();
			int diffY=this.getCooY()-monde.perso.getCooY();
			
			int dist= (int)Math.sqrt(Math.pow(diffX,2) + Math.pow(diffY,2));
			
			if(dist<=this.getVue()){rep=true;}
		
		
		
		return rep;
	}
	
	
	
	
	
	
	
	///////////////////////////////////
	///////////////////////////////////
	
	public boolean persoEstDansLOSCreature(Monde monde){
		
		boolean reponse=false;
		
		//System.out.println(getNom()+" nightvision:"+getNightvision());
		//System.out.println("Perso discretion "+monde.perso.discretion);
		//System.out.println(getNom()+" INT:"+getIntelligence());
		
		
		if(monde.perso.getInvisible()){return false;
		}
		
		
		/*
		if(getPasseMuraille()){reponse=true;
		}
		*/
		
		
		
		/////////LOS CREATURE///////////////////
		
		if(Math.abs(this.getCooX()-monde.perso.getCooX())<=this.getVue() && Math.abs(this.getCooY()-monde.perso.getCooY())<=this.getVue()){
			Entite ici=new Entite();
			Point creatPt=new Point(this.getCooX(),this.getCooY());
			Point persoPt=new Point(monde.perso.getCooX(),monde.perso.getCooY());	
			Point studyPt=new Point(this.getCooX(),this.getCooY());
			
			
			Point[] tabloPt=bresenham_line(creatPt,persoPt);
			
			
			
			for(int b=0;b<tabloPt.length;b++){	
				
				
				studyPt=tabloPt[b];
				
				
				/////perso caché par les tenebres
				if(monde.eclairageGrid[(int)studyPt.getX()][(int)studyPt.getY()]==2 && !getNightvision()){
					//System.out.println(getNom()+" vision bloquee par tenebres");
					return false;	
				}	
				/////////////////
				
				
				//parcours dans studyPt
				for(int i=0;i<monde.grille[(int)studyPt.getX()][(int)studyPt.getY()].size();i++){
						
		 			try{
		 					
		 				ici = (Entite) monde.grille[(int)studyPt.getX()][(int)studyPt.getY()].get(i);
	 					
						if((ici.getClass().getName().compareTo("Gate")==0 || ici.getTypeObjet().compareTo("Obstacle")==0) && !ici.getCasse() && !ici.getOuvert()&&!getPasseMuraille()){
							//System.out.println(getNom()+ "Obstacle en "+studyPt);
							return false;
						}
						
					}
					catch(NoSuchElementException exc){};
				}
				
				
			}
			
			
			//parcourir la ligne depuis creatPt jusqu'à persoPt à la 
			//recherche d'un obstacle.
			//si obstacle return false.
		
			reponse=true;
		}
		
		////test d'int vs discretion perso
		if(reponse){
			reponse=intVSPersoDiscretion(monde);
		}
		
		return reponse;
	}
	
	///////////////////////////////////
	///////////////////////////////////
	///////////////////////////////////
	
	public boolean intVSPersoDiscretion(Monde monde){
		/////discretion du perso VS int de la creature
		
		//if(monde.perso.getStealthmode() && (monde.perso.discretion*roll()*2>getIntelligence()*roll())){
		if(monde.perso.getStealthmode()){
			
			int creaIntRoll=getIntelligence()*roll();
			int persoDiscRoll=monde.perso.discretion*roll();
			
			if(!monde.getNuit() || monde.perso.getEstEclaireParObjetProche()){
				persoDiscRoll=persoDiscRoll/2;
				//System.out.println("MAUVAISE CONDITIONS DE DISCRETION");
			}
			
			if((monde.getNuit()||monde.perso.indexTerrainZ>0) && monde.perso.getEstEclaireParCeQuilPorte() ){
				//System.out.println("IMPOSSIBLE DE SE CACHER DANS CES CONDITIONS");
				persoDiscRoll=0;
			}
			
			//System.out.println(persoDiscRoll+" VS "+creaIntRoll);
			
			if(persoDiscRoll>creaIntRoll){
				monde.message(getNom()+" ne vous voit pas...",false);
				monde.message(getNomE()+" dont see you...",true);
				return false;
			}
			else{
				monde.message(getNom()+" vous voit...",false);
				monde.message(getNomE()+" see you...",true);
			}
			
		}
		return true;
	}
	
	///////////////////////////////////
	///////////////////////////////////
	///////////////////////////////////
	
	
	public Point chercheVersPerso(Monde monde,int origineX,int origineY,boolean fuite){
		
		
		//// (IMPLANTER UN PATHFINDING ICI)
		//Point versPersoPt=new Point(0,0);
		
		int coordPersoX=monde.perso.getCooX();
 		int coordPersoY=monde.perso.getCooY();
 		
 		double differenceCoordX=origineX-coordPersoX;
 		double differenceCoordY=origineY-coordPersoY;
 		
 		int destX=origineX;
 		int destY=origineY;
 		
 		if(!fuite){
 		
	 		if(differenceCoordX<0){ destX=origineX+1;
	 		}
	 		if(differenceCoordX>0){ destX=origineX-1;
	 		}
	 		if(differenceCoordY<0){ destY=origineY+1;
	 		}
	 		if(differenceCoordY>0){ destY=origineY-1;
	 		}
 		}
 		else{
 			if(differenceCoordX<0){ destX=origineX-1;
	 		}
	 		if(differenceCoordX>0){ destX=origineX+1;
	 		}
	 		if(differenceCoordY<0){ destY=origineY-1;
	 		}
	 		if(differenceCoordY>0){ destY=origineY+1;
	 		}
 		}
 		
 		
 		
		
		/////////////////////////////////////
		//VARIATION DU MOUVEMENT/////////////      le remettre ???
		
		// le remettre ???
		Point vraieArriveePt=variationDeMouvement(new Point(origineX,origineY),new Point(destX,destY));
		
		//System.out.println("***TEST de variation du mouvement depuis chercheVersPerso***");
		//System.out.println(getNom()+": Origine  "+new Point(origineX,origineY));
		//System.out.println(getNom()+": Arrivee  "+new Point(destX,destY));
		//System.out.println(getNom()+": Arrivee2 "+vraieArriveePt);
		
		
		// le remettre ???
		return vraieArriveePt;
		/////////////////////////////////////
		/////////////////////////////////////
		
		
		
		
		//return new Point(destX,destY);
		///////////////////////////////////////////////////
	}
	
	
	
	
	
	///////////////////////////////////////////////////////////////////////////////////
	//////////////////////////ANALYSE DU SOL///////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////////
	public void analyseDuSol(Monde monde,int xAct,int yAct){///////
		
		dansLeVide=false;
	
		
		if(!monde.grille[xAct][yAct].isEmpty()){
			//Entite objet=new Entite();
				
			for(int i=0;i<monde.grille[xAct][yAct].size();i++){
					
		 					
	 			try{
	 					
	 					
	 				objet = (Entite) monde.grille[xAct][yAct].get(i);		
		 					
 					
 							
					strType = (objet.getClass().getName());
					typedelobjet=objet.getTypeObjet();
					strModele= objet.getModele();
					
					
					/*
					if(strType.compareTo("Ombrage")!=0 && typedelobjet.compareTo("PJ")!=0 && typedelobjet.compareTo("Surface")!=0){
						//monde.jeuPan.messagesPanel.remplissageMessages("Au sol : "+typedelobjet+" "+strType+"  Poids:"+objet.getPoids());
						monde.jeuPan.messagesPanel.remplissageMessages("Au sol de cette creature : "+objet.getNom()+"  Poids:"+objet.getPoids());
				
					}
					*/
					
					if(objet.getClass().getName().compareTo("VraiVide")==0){
						dansLeVide=true;
					}
					
					
					
					//////MARCHE SUR UN PIEGE ////////////
					if(strType.compareTo("Piege")==0 && !getVolant()&& !getPasseMuraille()){
						monde.declencheurPiege(this,objet,xAct,yAct);
					}
					
						
				}
				catch(NoSuchElementException exc){};
			 }
			 
		}
		
		
		
		//System.out.println(getNom()+" SUR SOL "+surSol);
		//System.out.println(getNom()+" VOLANT "+getVolant());
		//TEST DANS LE VIDE
		if(getDansLeVide() && !getVolant()){
			
			System.out.println(getNom()+" tombe !!! .....et s'ecrase");
			new ThreadSon("./sons/fall_down_level.wav",0).start();
			setMort(monde,true,0,0);
			
		}
		
		
		
		
	}
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	public Point destinationAleatoire(Monde monde,Entite laCreature,int origineX,int origineY){
		
		int arriveX=0;
		int arriveY=0;
		double aleaDestDouble=Math.random()*10;
		int aleaDest=(int)aleaDestDouble;
		
		//System.out.println("ALEA "+aleaDest);
		
		if(aleaDest==1){
			arriveX=origineX-1;
			arriveY=origineY+1;
		}
		if(aleaDest==2){
			arriveX=origineX;
			arriveY=origineY+1;
		}
		if(aleaDest==3){
			arriveX=origineX+1;
			arriveY=origineY+1;
		}
		if(aleaDest==4){
			arriveX=origineX-1;
			arriveY=origineY;
		}
		if(aleaDest==5 || aleaDest==0 || aleaDest==10){
			arriveX=origineX;
			arriveY=origineY;
		}
		if(aleaDest==6){
			arriveX=origineX+1;
			arriveY=origineY;
		}
		if(aleaDest==7){
			arriveX=origineX-1;
			arriveY=origineY-1;
		}
		if(aleaDest==8){
			arriveX=origineX;
			arriveY=origineY-1;
		}
		if(aleaDest==9){
			arriveX=origineX+1;
			arriveY=origineY-1;
		}
		
		
		//Vector vecteurDest=monde.grille[arriveX][arriveY];
		Point arrivePt=analyseMouvementArrivee(monde,laCreature,monde.grille[arriveX][arriveY],origineX,origineY,arriveX,arriveY);
		return arrivePt;
	}
	
	//////////////////////////////////////////////////////////////////////////////////
	///
	//////////////////////////////////////////////////////////////////////////////////
	
	
	public Point analyseMouvementArrivee(Monde monde,Entite laCreature,ArrayList vectDestination,int xDep,int yDep,int xDest,int yDest){
			
			
			
			Point pointCoord=new Point(xDest,yDest);
			boolean sortie=false;
			boolean pj=false;
			boolean obstacle=false;
			boolean gate=false;
			boolean creature=false;
			
			boolean gateOuvert=false;
			boolean creatureMorte=false;
			
			boolean eau=false;
			boolean passage=false;
			
			boolean hostiliteCreature=laCreature.getHostilite();
			
			
			
			if(!vectDestination.isEmpty()){
				//Entite objet=new Entite();
				for(int i=0;i<vectDestination.size();i++){
					
		 					
	 			try{
	 					
	 					
	 				objet = (Entite)vectDestination.get(i);
						
						
						typedelobjet=objet.getTypeObjet();
						
						////////////////////////
						// traitement sortie du terrain
						if(xDest>=monde.tailleGrille-10 || xDest<=9 || yDest>=monde.tailleGrille-10 || yDest<=9){
							sortie=true;
						}
						////////////////////////
						// presence PJ
						if(typedelobjet.compareTo("PJ")==0){
							pj=true;
						}
						////////////////////////
						// presence obstacle
						if(typedelobjet.compareTo("Obstacle")==0 && objet.getCasse()==false){
							obstacle=true;
						}
						
						
						////////////////////
						//presence / detection piege
						if(objet.getClass().getName().compareTo("Piege")==0 && objet.getCasse()==false  && !getVolant()){
							if(getIntelligence()*roll()>=objet.getComplexitePiege()){obstacle=true;}
						}
						
						
						
						////////////////////////
						// presence gate
						if(objet.getClass().getName().compareTo("Gate")==0){
							gate=true;
							gateOuvert=objet.getOuvert();
						}
						////////////////////////
						// presence creature
						if(typedelobjet.compareTo("Creature")==0){
							creature=true;
							creatureMorte=objet.getMort();
						}
						
						///presence passage
						if(typedelobjet.compareTo("Passage")==0  && !objet.getCasse()){
							passage=true;
						}
						//presence eau
						if(typedelobjet.compareTo("Water")==0){
							eau=true;
						}
						
						
						//TRAITEMENT
						// Attention à l'ordre !!!
						
						////////////////////////
						if(creature==true){
							pointCoord=new Point(xDep,yDep);
							if(creatureMorte==true){
								pointCoord=new Point(xDest,yDest);
							}
							
							
						}
						
						////////////////////////
						if(gate==true){
							pointCoord=new Point(xDep,yDep);
							if(gateOuvert==true || laCreature.getPasseMuraille()==true || objet.getCasse()){
								pointCoord=new Point(xDest,yDest);
							}
							
							/*else if(objet.getCasse()==true){
								pointCoord=new Point(xDest,yDest);
							}*/
							
							else if((aVuPerso||getFlee()) && JetContreDifficulte(this.getIntelligence(),50) && objet.getUnlocked()){
								objet.setOuvert(true);////////////////////////////////////
								objet.bruit(monde,0,0);
								
							}
							
							//System.out.println("aVuPerso "+aVuPerso);
						}
						
						////////////////////////
						if(obstacle==true){
							pointCoord=new Point(xDep,yDep);
							if(laCreature.getPasseMuraille()==true){
								pointCoord=new Point(xDest,yDest);
							}
						}
						
						////////////////////////
						if(eau){
							pointCoord=new Point(xDep,yDep);
							if(passage){
								pointCoord=new Point(xDest,yDest);	
							}
						}
						
						
						
						////////////////////////
						if(sortie==true){
							pointCoord=new Point(xDep,yDep);
						}
						
						////////////////////////
						if(pj==true){
							pointCoord=new Point(xDep,yDep);
							if(hostiliteCreature==true){
								//System.out.println("La creature est hostile et attaque");
								monde.combatMelee(laCreature,objet,xDest,yDest);
							}
							else{
								//System.out.println("Cette creature vous epargne");
							}
						}
						
						
					}
					catch(NoSuchElementException exc){};
				}
				
			}
			
			
			return pointCoord;
			
	}
	
	
	///////////////////////////////////////////////////////
	/////////// JET DE DES/////////////////////////////////
	///////////////////////////////////////////////////////
	/*
	public int rollxdy(int x,int y,boolean openended){
		
		int jet=(int)(Math.abs(Math.random()*y))+1;
		
		int jetFinal=jet*x;
		
		
		//OPEN-ENDED +
		if(openended==true && y==100 && jetFinal>=96){
			
			int jetSup=rollxdy(1,100,true);
			
			jetFinal=jetFinal+jetSup;
			
		}
		
		
		//OPEN-ENDED -
		if(openended==true && y==100 && jetFinal<=4){
			
			int jetSup=rollxdy(1,100,true);
			
			jetFinal=jetFinal-jetSup;
			
		}
		
		
		
		return jetFinal;
		
		
		
	}
	*/
	
	
	
	
	
	
	////////////////////////////
	////////////////////////////
	public int roll(){
		int d1=(int)(Math.abs(Math.random()*10))+1;
		int d2=(int)(Math.abs(Math.random()*10))+1;
		
		int result=d1+d2;
		
		if(d1==1 && d2==1 && !open){
			return result;
		}
		
		if(d1==d2){
			open=true;
			result=result+roll();
		}
		
		open=false;
		return result;
	}
	
	////////////////////////////
	////////////////////////////
	public boolean JetContreDifficulte(int stat,int diff){
		
		if(stat*roll()>=diff){
			return true;
		}
		else{return false;}
		
	}
	////////////////////////////
	////////////////////////////	
	
	
	
	
    public final static Point[] bresenham_line(Point pt1, Point pt2) {
        return bresenham_line(pt1.x, pt1.y, pt2.x, pt2.y);
    }

   
    public final static Point[] bresenham_line(int x1, int y1, int x2, int y2) {
        
        int i;
        int d, x, y, ax, ay, sx, sy, dx, dy, t;

        dx = x2 - x1;
        ax = Math.abs(dx) << 1;
        sx = sign(dx);
        dy = y2 - y1;
        ay = Math.abs(dy) << 1;
        sy = sign(dy);

        t = Math.max(Math.abs(dx), Math.abs(dy)) + 1;
        Point[] ret_val = new Point[t];

        x = x1;
        y = y1;
        if (ax > ay) { /* x dominant */
            d = ay - (ax >> 1);
            for (i = 0;;) {
                ret_val[i++] = new Point(x, y);
                //ret_val[i].x = x; ret_val[i++].y = y;
                if (x == x2)
                    return ret_val;
                if (d >= 0) {
                    y += sy;
                    d -= ax;
                }
                x += sx;
                d += ay;
            }
        } else { /* y dominant */
            d = ax - (ay >> 1);
            for (i = 0;;) {
                ret_val[i++] = new Point(x, y);
                //ret_val[i].x = x; ret_val[i++].y = y;
                if (y == y2)
                    return ret_val;
                if (d >= 0) {
                    x += sx;
                    d -= ay;
                }
                y += sy;
                d += ax;
            }
        }
    }
    
    
    /**
     * Return sign of number.
     * 
     * @param x short
     * @return int sign -1, 1
     */
    public static final int sign(short x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x int
     * @return int sign -1, 1
     */
    public static final int sign(int x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x long
     * @return int sign -1, 1
     */
    public static final int sign(long x) {
        return (x < 0) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x float
     * @return int sign -1, 1
     */
    public static final int sign(float x) {
        return (x < 0f) ? -1 : 1;
    }

    /**
     * Return sign of number.
     * 
     * @param x double
     * @return int sign -1, 1
     */
    public static final int sign(double x) {
        return (x < 0d) ? -1 : 1;
    }
	
	
	
}