/***********************************************************************************************/
/***********************************************************************************************/
/**		DISSENY DE SISTEMES DE SUPERVISIÓ																	  **/
/**																													  **/ 
/**		JAVASSOCER: AGENTS UTILITZANT CONSENSOS ADAPTATIUS												  **/
/**		Xavier Armangué Quintana																				  **/
/**		Robert Martí Marly																						  **/
/**		5è EINF - Gener 1999 -																					  **/
/***********************************************************************************************/
/***********************************************************************************************/
package ou7kou.Equips;

import  EDU.gatech.cc.is.util.Vec2;
import  EDU.gatech.cc.is.abstractrobot.*;
import  java.lang.Math;
import  java.util.Enumeration;
import  EDU.gatech.cc.is.communication.*;
import  ou7kou.Fuzzy;		// Classe que conté la implementacio dels conjunts fuzzy.
import  ou7kou.Utils;		// Classe que conté altres funcions utilitzades.


/* Equip 1ou7kou Team: Agents amb conscensos adaptatius */
public class ou7kou extends ControlSystemSS
{
	private Enumeration messagesin;		// Conjunt de missatges rebuts

	/* Constants */ 
	public static final double GOAL_WIDTH =  0.42; 		// Amplada de la porteria
	public static final double BALL_RADIUS = 0.01; 		// Radi de la pilota
	public static final double RADI_ROBOT = 0.06;		// Radi del robot
	public static final int JUGADORS = 5;					// Nombre de jugadors propis.
	/* conjunt de decisions */
	public static final int 
			XUTAR = 11,
			ANAR_PILOTA = 12,
			ATURAR = 13,
			DEFENSAR = 14,
			COBRIR= 15,
			RECUPERAR = 16,
			OBERT_DRETA = 17,
			OBERT_ESQUERRA = 18,
			ATACAR = 19,
			ZONA_ATAC = 20,
			ZONA_DEFENSA = 21,
			RES=22,
			MAX_DEC=22;
                   
   /* Variables */
   	long temps_act;									// Temps actual
	// Posicions absolutes: jugador, pilota, porteria pròpia i porteria contrària
   	Vec2 jo, pilota, portaprop, portacont;	
	// Posicions relatives: jugador-pilota,jugador-porteria pròpia
   	Vec2 jo_pilota, jo_portaprop;
	int RobotID,			// Identificador del robot
		Segona_decisio;	// Si la decisió escollida no es pot fer, es farà segona decisió.

	Fuzzy f=new Fuzzy(); 
	Utils u;
	double decisions[]=new double[MAX_DEC];		// Taula de les possibles possibles decisions
	// Taula de consensos: necessitat del jugador -> consensos[RobotID]
	//							 prestigi del companys  -> consensos[i] on i<>RobotID								
	double consensos[]=new double[JUGADORS];		

	boolean canvi_decisio=false;			// Si s'ha canviat de decisió en l'anterior acció
	int ID_canvi_decisio;					// Id del robot amb el que hi havia conflicte
	double decisio_canvi_decisio;		// Valor de la decisió del company que provoca el canvi 
	
/*********************************************************************************************/
/**		Mètode que configura la classe																		**/
/*********************************************************************************************/
   public void Configure()
   {
		int i;
		Vec2 temp,jo;

		RobotID = abstract_robot.getPlayerNumber(temps_act);	// Identificador del robot
      jo = abstract_robot.getPosition(temps_act);				// Posicio del robot
		
		temp = abstract_robot.getOurGoal(temps_act);				// vector jo-porta pròpia
      portaprop = new Vec2( temp.x, temp.y );
      portaprop.add(jo);												// Posició porta pròpia	

      temp = abstract_robot.getOpponentsGoal(temps_act);		// Vector jo-porta contrària
      portacont = new Vec2( temp.x, temp.y );
      portacont.add(jo);												// Posició de la porta contrària	

		if (portaprop.x<0)			// Si som de l'equip de l'Oest
		{
			if (RobotID==2) RobotID=4;		// Canviem els ids per a tenir els robots ben posicionats
			else if (RobotID==4) RobotID=2;		
		}
				
		// Definició de les segones decisions: si no poden fer una acció el robot farà la segona_decisió
		switch (RobotID)
		{
			case 0:
					Segona_decisio=COBRIR;				// Porter: anar a cobrir la porteria
				break;
			case 1:
					Segona_decisio=ZONA_DEFENSA;		// Defensa:zona de defensa a l'alçada de la pilota
				break;
			case 2:
					Segona_decisio=OBERT_DRETA;		// Mig dret: Zona lateral dreta
				break;
			case 4:
					Segona_decisio=OBERT_ESQUERRA;	// Mig esquerra: Zona lateral esquerra
				break;
			case 3:
					Segona_decisio=ZONA_ATAC;			// Davanter: Zona d'Atac
				break;
		}
	   messagesin = abstract_robot.getReceiveChannel();	// messagein: missatges rebuts
		
		for (i=0;i<JUGADORS;i++)
		{
			consensos[i]=0.5;							// Valor inicial de necessitat i prestigis
		}
   }

/*********************************************************************************************/
/**		Coordenada inferior de la porteria contrària														**/
/*********************************************************************************************/
   Vec2 bottom_goalpost()
   {
      return new Vec2( portacont.x, portacont.y - GOAL_WIDTH/2 );
   }

/*********************************************************************************************/
/**		Coordenada superior de la porteria contrària														**/
/*********************************************************************************************/
   Vec2 top_goalpost()
   {
      return new Vec2( portacont.x, portacont.y + GOAL_WIDTH/2 );
   }

/*********************************************************************************************/
/**		Coordenada inferior de la porteria pròpia															**/
/*********************************************************************************************/
   Vec2 bottom_propipost()
   // returns location of their bottom goalpost
   {
      return new Vec2( portaprop.x, portaprop.y - GOAL_WIDTH/2 );
   }

/*********************************************************************************************/
/**		Coordenada superior de la porteria pròpia															**/
/*********************************************************************************************/
   Vec2 top_propipost()
   {
      return new Vec2( portaprop.x, portaprop.y + GOAL_WIDTH/2 );
   }

/*********************************************************************************************/
/**		Retorna la necessitat del porter en funció de la posició	de la pilota						**/
/*********************************************************************************************/
	double necessitat_porter(Vec2 pos,Vec2 portacont)
	{
		double res;
		
		if (portacont.x<0)
		{
			if (pos.x>f.DIST_ZO_MIN) res=1;
			else res=(1/(f.DIST_ZO_MIN-portacont.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN-portacont.x));
		}
		else 
		{
			if (pos.x<-f.DIST_ZO_MIN) res=1;
			else res=(-1/(f.DIST_ZO_MIN-portacont.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN-portacont.x));
		}
		return res;
	}

/*********************************************************************************************/
/**		Retorna la necessitat del defensa en funció de la posició de la pilota 					**/
/*********************************************************************************************/
	double necessitat_defensa(Vec2 pos,Vec2 portacont)
	{
		double res;

		if( portacont.x > 0 ) 
	    	{ 
			if (pos.x > -f.DIST_ZO_MIN) res=1;
			else res=(-1/(f.DIST_ZO_MIN-portacont.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN-portacont.x));
		}
		else
		{ 
			if (pos.x > f.DIST_ZO_MIN) res=1;
			else res=(1/(f.DIST_ZO_MIN-portacont.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN-portacont.x));
		}
		return res;
	}


/*********************************************************************************************/
/**		Retorna la necessitat del mig dret en funció de la posició de la pilota					**/
/*********************************************************************************************/
	double necessitat_mig_dret(Vec2 pos,Vec2 portaprop)
	{
		double res;
		double inc=0.15;
		
		if (portaprop.x>0)
		{
			if (pos.y>f.DIST_OB_MAX-inc) res=1;
			else res=(1/(f.DIST_OB_MAX+0.76-inc))*pos.y+(1-(f.DIST_OB_MAX-inc)/(f.DIST_OB_MAX+0.76-inc));
		}
		else 
		{
			if (pos.y<-f.DIST_OB_MAX+inc) res=1;
			else res=(-1/(f.DIST_OB_MAX-inc+0.76))*pos.y+(1-(f.DIST_OB_MAX-inc)/(f.DIST_OB_MAX+0.76-inc));
		}
		return res;
	}

/*********************************************************************************************/
/**		Retorna la necessitat del mig esquerra en funció de la posició de la pilota				**/
/*********************************************************************************************/
	double necessitat_mig_esquerra(Vec2 pos,Vec2 portaprop)
	{
		double res;
		double inc=0.15;
		
		if (portaprop.x<0)
		{
			if (pos.y>f.DIST_OB_MAX-inc) res=1;
			else res=(1/(f.DIST_OB_MAX-inc+0.76))*pos.y+(1-(f.DIST_OB_MAX-inc)/(f.DIST_OB_MAX+0.76-inc));
		}
		else 
		{
			if (pos.y<-f.DIST_OB_MAX+inc) res=1;
			else res=(-1/(f.DIST_OB_MAX-inc+0.76))*pos.y+(1-(f.DIST_OB_MAX-inc)/(f.DIST_OB_MAX+0.76-inc));
		}
		return res;
	}

/*********************************************************************************************/
/**		Retorna la necessitat del davanter en funció de la posició de la pilota					**/
/*********************************************************************************************/
	double necessitat_davanter(Vec2 pos,Vec2 portaprop)
	{
		double res;
		
		if (portaprop.x>0)
		{
			if (pos.x<-f.DIST_ZO_MIN) res=1;
			else res=(-1/(f.DIST_ZO_MIN+portaprop.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN+portaprop.x));
		}
		else 
		{
			if (pos.x>f.DIST_ZO_MIN) res=1;
			else res=(1/(f.DIST_ZO_MIN+portaprop.x))*pos.x+(1-f.DIST_ZO_MIN/(f.DIST_ZO_MIN+portaprop.x));
		}
		return res;
	}


/*********************************************************************************************/
/**		Inicialització de les variables a cada Take Step												**/
/*********************************************************************************************/
 	void iniVars()
   {
		int i;
      temps_act = abstract_robot.getTime();

		for (i=0;i<MAX_DEC;i++) decisions[i]=0;

      jo = abstract_robot.getPosition(temps_act);		// Posició del jugador

      jo_pilota = abstract_robot.getBall(temps_act);	// Vector jo-pilota
      pilota = new Vec2( jo_pilota.x, jo_pilota.y );	// Posició de la pilota
      pilota.add( jo );

      jo_portaprop = abstract_robot.getOurGoal(temps_act); // Vector jo-porta pròpia

   }

/*********************************************************************************************/
/**		Take Step																									**/
/*********************************************************************************************/
   public int TakeStep()
   {
		Vec2   resultat,posicio,pilota_porta;
		double velocitat;
		int 	decidit;
		String text="";
		StringMessage m=new StringMessage(); 

 		iniVars();		// Inicialitazió de les variables
		switch (RobotID)
		{
			case 0:/* Regles de decisió del Porter */
					decisions[XUTAR]=f.TenirPilota(jo_pilota)*
										 f.XutClar(jo,pilota,portaprop,top_goalpost(),bottom_goalpost());
					decisions[COBRIR]=f.CampContrari(jo,portaprop);
					decisions[COBRIR]=u.Or(decisions[COBRIR],f.MigCamp(jo));
					decisions[COBRIR]=u.Or(decisions[COBRIR],f.CampPropi(jo,portaprop)*f.ObertDreta(jo,portaprop));
					decisions[COBRIR]=u.Or(decisions[COBRIR],f.CampPropi(jo,portaprop)*f.ObertEsquerra(jo,portaprop));
					decisions[DEFENSAR]=f.ZonaPorteria(jo,portaprop)*f.Centrat(jo);
					decisions[ANAR_PILOTA]=f.Davant(jo,pilota,portaprop);

					consensos[RobotID]=necessitat_porter(pilota,portacont);	// necessitat del porter
				break;

			case 1:/* Regles de decisió del Defensa */
					decisions[XUTAR]=f.TenirPilota(jo_pilota)*
										 f.XutClar(jo,pilota,portaprop,top_goalpost(),bottom_goalpost());
					decisions[ZONA_DEFENSA]=f.ZonaGol(jo,portaprop);
					decisions[ZONA_DEFENSA]=u.Or(decisions[ZONA_DEFENSA],f.ZonaGol(pilota,portaprop));
					decisions[ZONA_DEFENSA]=u.Or(decisions[ZONA_DEFENSA],f.CampContrari(jo,portaprop)*f.LlunyPilota(jo_pilota));
					decisions[ANAR_PILOTA]=f.Davant(pilota,jo,portaprop)*f.CampPropi(jo,portaprop)*f.CampPropi(pilota,portaprop);
					decisions[ANAR_PILOTA]=u.Or(decisions[ANAR_PILOTA],f.Davant(pilota,jo,portaprop)*f.CampPropi(jo,portaprop)*f.MigCamp(pilota));
					decisions[RECUPERAR]=f.Davant(jo,pilota,portaprop);

					consensos[RobotID]=necessitat_defensa(pilota,portacont); // necessitat del defensa
				break;

			case 2:/* Regles de decisió del Mig dret */
					decisions[XUTAR]=f.TenirPilota(jo_pilota)*
										 f.XutClar(jo,pilota,portaprop,top_goalpost(),bottom_goalpost());
					decisions[ATACAR]=f.CampContrari(pilota,portaprop)*f.ObertDreta(pilota,portaprop);
					decisions[ATACAR]=u.Or(decisions[ATACAR],f.CampContrari(pilota,portaprop)*f.Centrat(pilota));
					decisions[OBERT_DRETA]=f.ObertEsquerra(pilota,portaprop)*f.CampContrari(jo,portaprop);
					decisions[OBERT_DRETA]=u.Or(decisions[OBERT_DRETA],f.ObertEsquerra(pilota,portaprop)*f.MigCamp(jo));
					decisions[ATURAR]=f.ObertEsquerra(pilota,portaprop)*f.ZonaPorteria(jo,portaprop)*f.ObertDreta(jo,portaprop);
					decisions[RECUPERAR]=f.CampPropi(pilota,portaprop)*f.Davant(jo,pilota,portaprop)*f.ObertDreta(pilota,portaprop);
					decisions[RECUPERAR]=u.Or(decisions[RECUPERAR],f.CampPropi(pilota,portaprop)*f.Davant(jo,pilota,portaprop)*f.Centrat(pilota));
					decisions[ANAR_PILOTA]=f.CampPropi(pilota,portaprop)*f.Davant(pilota,jo,portaprop)*f.ObertDreta(pilota,portaprop);
					decisions[ANAR_PILOTA]=u.Or(decisions[ANAR_PILOTA],f.CampPropi(pilota,portaprop)*f.Davant(pilota,jo,portaprop)*f.Centrat(pilota));

					consensos[RobotID]=necessitat_mig_dret(pilota,portaprop); //necessitat del mig dret
				break;

			case 4: /* Regles de decisió del mig esquerra */
					decisions[XUTAR]=f.TenirPilota(jo_pilota)*
										 f.XutClar(jo,pilota,portaprop,top_goalpost(),bottom_goalpost());
					decisions[ATACAR]=f.CampContrari(pilota,portaprop)*f.ObertEsquerra(pilota,portaprop);
					decisions[ATACAR]=u.Or(decisions[ATACAR],f.CampContrari(pilota,portaprop)*f.Centrat(pilota));
					decisions[OBERT_ESQUERRA]=f.ObertDreta(pilota,portaprop)*f.CampContrari(jo,portaprop);
					decisions[OBERT_ESQUERRA]=u.Or(decisions[OBERT_ESQUERRA],f.ObertDreta(pilota,portaprop)*f.MigCamp(jo));
					decisions[ATURAR]=f.ObertDreta(pilota,portaprop)*f.ZonaPorteria(jo,portaprop)*f.ObertEsquerra(jo,portaprop);
					decisions[RECUPERAR]=f.CampPropi(pilota,portaprop)*f.Davant(jo,pilota,portaprop)*f.ObertEsquerra(pilota,portaprop);
					decisions[RECUPERAR]=u.Or(decisions[RECUPERAR],f.CampPropi(pilota,portaprop)*f.Davant(jo,pilota,portaprop)*f.Centrat(pilota));
					decisions[ANAR_PILOTA]=f.CampPropi(pilota,portaprop)*f.Davant(pilota,jo,portaprop)*f.ObertEsquerra(pilota,portaprop);
					decisions[ANAR_PILOTA]=u.Or(decisions[ANAR_PILOTA],f.CampPropi(pilota,portaprop)*f.Davant(pilota,jo,portaprop)*f.Centrat(pilota));

					consensos[RobotID]=necessitat_mig_esquerra(pilota,portaprop); //necessitat del mig esquerra
				break;

			case 3: /* Regles de decisió del davanter */
					decisions[XUTAR]=f.TenirPilota(jo_pilota)*
										 f.XutClar(jo,pilota,portaprop,top_goalpost(),bottom_goalpost());
					decisions[RECUPERAR]=f.Davant(jo,pilota,portaprop)*f.CampContrari(pilota,portaprop);
					decisions[ATACAR]=u.Or(f.Davant(pilota,jo,portaprop)*f.MigCamp(pilota),f.Davant(pilota,jo,portaprop)*f.CampContrari(pilota,portaprop));
					decisions[ZONA_ATAC]=f.CampPropi(pilota,portaprop);

					consensos[RobotID]=necessitat_davanter(pilota,portaprop);	// necessitat del davanter
				break;
		}

		/* Prendre una desició */
		decidit=u.Decisio(decisions); 	// Busca el valor màxim resultatnt de cada decisió
		if (decidit==0) decidit=RES;		// No fa cap acció

		/* Communicació amb els companys */
		m.sender=RobotID;
		m.val=(new Integer(decidit)).toString();
		m.val=m.val.concat(" ");
		m.val=m.val.concat((new Double(decisions[u.Decisio(decisions)])).toString());
		abstract_robot.broadcast(m);		// Enviar missatge a tots el companys

		while (messagesin.hasMoreElements())		// Rebre tots els missatges
		{
			StringMessage recvd =(StringMessage)messagesin.nextElement();	// rebre missatge
			String missatge=recvd.toString();

			double certesa_company;
			int 	id_company,decisio_company;
			
			id_company=u.ID_company(missatge);				// id del company que ha enviat el missatge
			decisio_company=u.decisio_company(missatge);	// decisió del company
			certesa_company=u.certesa_company(missatge);	// certesa de la decisió del company

			/* Algoritme adaptatiu de prestigis */
			if ((canvi_decisio)&&(id_company==ID_canvi_decisio))	
			{
				if (decisio_company==decisio_canvi_decisio)
				{
					switch(id_company)
					{
						case 0:	consensos[id_company]=necessitat_porter(pilota,portacont);break;
						case 1:	consensos[id_company]=necessitat_defensa(pilota,portacont);break;
						case 2:	consensos[id_company]=necessitat_mig_dret(pilota,portaprop);break;
						case 3:	consensos[id_company]=necessitat_davanter(pilota,portaprop);break;
						case 4:	consensos[id_company]=necessitat_mig_esquerra(pilota,portaprop);break;
					}
				}
				if (consensos[id_company]>1) consensos[id_company]=1;
				if (consensos[id_company]<0) consensos[id_company]=0;
				canvi_decisio=false;
			}
			/* Consens amb les decisions dels altres companys */
			switch(decidit)
			{
				case XUTAR:
						/* Mirar si hi ha incompatibilitats entre les decisions del company */
						switch(decisio_company)
						{
							case XUTAR:
							case ANAR_PILOTA:
							case ATACAR:
									if (decisions[decidit]*consensos[RobotID]<certesa_company*consensos[id_company])
									{	// canviem la nostra decisió
										decidit=Segona_decisio;
										canvi_decisio=true;
										ID_canvi_decisio=id_company;
										decisio_canvi_decisio=decisio_company;
									}
								break;
						}
					break;

				case ANAR_PILOTA:
						/* Mirar si hi ha incompatibilitats entre les decisions del company */
						switch(decisio_company)
						{
							case XUTAR:
							case RECUPERAR:
							case ANAR_PILOTA:
							case ATACAR:
									if (decisions[decidit]*consensos[RobotID]<certesa_company*consensos[id_company])
									{	// canviar la nostra decisió
										decidit=Segona_decisio;
										canvi_decisio=true;
										ID_canvi_decisio=id_company;
										decisio_canvi_decisio=decisio_company;
									}
								break;
						}
					break;
				case RECUPERAR:
						/* Mirar si hi ha incompatibilitats entre les decisions del company */
						switch(decisio_company)
						{
							case RECUPERAR:
							case ANAR_PILOTA:
									if (decisions[decidit]*consensos[RobotID]<certesa_company*consensos[id_company])
									{	// canviem la nostra decisió
										decidit=Segona_decisio;
										canvi_decisio=true;
										ID_canvi_decisio=id_company;
										decisio_canvi_decisio=decisio_company;
									}
								break;
						}
					break;

				case ATACAR:
						/* Mirar si hi ha incompatibilitats entre les decisions del company */
						switch(decisio_company)
						{
							case XUTAR:
							case ANAR_PILOTA:
							case ATACAR:
									if (decisions[decidit]*consensos[RobotID]<certesa_company*consensos[id_company])
									{	// canviar la decisió
										decidit=Segona_decisio;
										canvi_decisio=true;
										ID_canvi_decisio=id_company;
										decisio_canvi_decisio=decisio_company;
									}
								break;
						}
					break;
			}
		}

		/* Realitzar l'acció decidida */
		switch(decidit)
		{
			case XUTAR: text="Xutar ";
									resultat=jo_pilota;	// anar a la pilota
									velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case DEFENSAR: text="Defensar ";
									pilota_porta=new Vec2(portaprop);
									pilota_porta.sub(pilota);
									pilota_porta.setr(-0.35);			// vector pilota-porta amb un mòdul de 0.35
									posicio=new Vec2(portaprop);
									posicio.add(pilota_porta);
									resultat=new Vec2(posicio);		
									resultat.sub(jo);					// Posició defensa: entre la pilota i la porteria
									if (resultat.r<0.05) velocitat=0.0;	// Aturar
									else velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat);
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case ANAR_PILOTA: 	text="Anar pilota ";
									pilota_porta=new Vec2(portaprop);
									pilota_porta.sub(pilota);
									pilota_porta.setr(0.05);
									posicio=new Vec2(pilota);
									posicio.add(pilota_porta);
									resultat=new Vec2(posicio);	// Anar a poca distancia darrera la pilota
									resultat.sub(jo);
									velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
									break;

			case ATACAR: 	text="Atacar ";
									pilota_porta=new Vec2(portacont);
									pilota_porta.sub(pilota);
									pilota_porta.setr(-0.05);
									posicio=new Vec2(pilota);
									posicio.add(pilota_porta);
									resultat=new Vec2(posicio);	//anar darrera la pilota, encarar-se i xutar 
									resultat.sub(jo);
									velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
									break;

			case RECUPERAR: 	text="Recuperar ";
									pilota_porta=new Vec2(portaprop);
									pilota_porta.sub(pilota);
									pilota_porta.setr(0.2);
									posicio=new Vec2(pilota);
									posicio.add(pilota_porta);
									resultat=new Vec2(posicio);	// anar darrera la pilota.
									resultat.sub(jo);
									velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
									break;

			case OBERT_DRETA:	text="Obert dreta ";
									posicio=new Vec2(pilota.x,0.4*portaprop.x/Math.abs(portaprop.x));
									resultat=posicio;
									resultat.sub(jo);				// anar al lateral dret, a l'alçada x de la pilota
									if (resultat.r<0.05) velocitat=0.0;
									else velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case OBERT_ESQUERRA:text="Obert esquerra ";
									posicio=new Vec2(pilota.x,-0.4*portaprop.x/Math.abs(portaprop.x));
									resultat=posicio;
									resultat.sub(jo);				// anar al lateral esquerra, a l'alçada x de la pilota
									if (resultat.r<0.05) velocitat=0.0;
									else velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case ZONA_ATAC:text="Zona atac ";
									posicio=new Vec2(-0.4*portaprop.x/Math.abs(portaprop.x),pilota.y);
									resultat=posicio;
									resultat.sub(jo);				// anar a zona d'atac, a l'alçada y de la pilota
									if (resultat.r<0.05) velocitat=0.0;
									else velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case ZONA_DEFENSA:text="Zona defensa ";
									posicio=new Vec2(0.4*portaprop.x/Math.abs(portaprop.x),pilota.y);
									resultat=posicio;
									resultat.sub(jo);				// anar a zona de defensa
									if (resultat.r<0.05) velocitat=0.0;
									else velocitat=1.0;
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
								   if (abstract_robot.canKick(temps_act))
								            abstract_robot.kick(temps_act);
									break;

			case COBRIR:   text="COBRIR ";
									resultat=jo_portaprop;
									velocitat=1.0;					// cobrir la porteria
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
									break;

			case ATURAR: 	text="Aturar ";
									resultat=jo_pilota;
									velocitat=0.0;					// para el robot
							  		abstract_robot.setSteerHeading(temps_act, resultat.t);
								   abstract_robot.setSpeed(temps_act, velocitat); 
									break;

			default:	 		text="Res ";
									velocitat=0;						// cap acció
									abstract_robot.setSpeed(temps_act, 0.0); 
									break;
		}

		abstract_robot.setDisplayString(text);				// mostrar texte
      return(CSSTAT_OK);
   }
}

