Documente Academic
Documente Profesional
Documente Cultură
Índice
Página
Índice 1
ROBOCODE 2
Nuestros robots 3
Lucha individual 6
Lucha en equipo 7
Código 9
AcosoYDerribo.java 9
ALoLoco.java 12
Ataque.java 13
Codigo.java 14
Inicio.java 15
JDKRobot.java 16
Jefe.java 19
Orden.java 23
Registro.java 26
RobotColors.java 26
SoldadoRaso.java 27
Solo.java 29
Victoria.java 29
ROBOCODE
Robocode es un entorno gratuito de simulación de guerras de robots, desarrollado por
Alphaworks de IBM, en el que hay que programar uno o varios tanques en Java para
pelear en el campo de batalla contra tanques programados por otros jugadores.
Para ello cuenta con un completo API con clases que representan los elementos más
diversos que intervienen en la batalla:
Todo tipo de eventos que deben afectar al comportamiento del tanque, como impactos
recibidos, balas o enemigos detectados, choques contra paredes u otros tanques…
Los robots vienen estructurados de forma jerárquica, desde el Robot simple hasta el
AdvancedRobot(que permite llamadas no bloqueantes) o el TeamRobot(tipo de robot
avanzado que tiene constancia de la existencia de más robots pertenecientes a un mismo
equipo y soporta el paso de mensajes entre sus integrantes).
Definir su comportamiento pasa por dar contenido a los métodos del robot que
gestionan los eventos, así como de su método run.
Para ello se utilizan los métodos que ofrecen las clases de la jerarquía Robot, que
permiten la rotación y desplazamiento del tanque, el retroceso. También el giro del
cañón y del radar o métodos que informan de determinados aspectos del tanque o de su
posición, orientación, estado. Se contempla también la posibilidad de envío de mensajes
entre tanques, etc.
Ejemplos:
En el API nos encontramos con los siguientes métodos (muy usados en nuestro
programa):
Nuestros robots
O lo que hace posible que los tanques distingan momentos de ataque individual (cada
uno otea por ahí y elige sus propios objetivos) o que sepan adaptarse y colaborar para
organizar una emboscada a un único rival a la orden de su jefe.
La Orden que lleva el tanque en cada momento es la que se encarga de responder a los
eventos que recoge el robot, en lugar de ser el robot quien directamente lo hace. Es
decir, dependiendo de la situación que se esté dando en el combate nuestros robots
actúan de una determinada manera o de otra (ejecutará una orden u otra).
Así no será raro observar que un tanque inicialmente se comporte como jefe y luego
como soldado, o que en principio pasee ‘a lo loco’ casi sin disparar por toda la pantalla
y al final se dedique a buscar objetivos y arremeter contra ellos.
Solo existe un único tipo de tanque JDKRobot, y dependerá de que al iniciar la partida
encuentre a más integrantes de su equipo o no el que adquiera un comportamiento
colaborativo (esperará ordenes de su jefe o se proclamará jefe y antepondrá los
objetivos del equipo a los suyos propios) o autónomo (buscará sus propios objetivos e
intentará llegar hasta donde el solo pueda).
Además de esto el equipo dispone del Jefe que cuando lo vea necesario mandará al
equipo nuevas órdenes que determinarán sus comportamientos a partir de este
momento. El líder es capaz de delegar su poder en otro tanque cuando es derribado, o
incluso de intercambiar su función con otro tanque más debilitado (puesto que el jefe se
limita a estar en un segundo plano detectando enemigos sin tomar partido en las batallas
de forma demasiado arriesgada, por lo que siempre tendrá mas vida que los que se están
arriesgando por luchar).
Con todo esto conseguimos que todos los tanques tengan idea de todo lo que ocurre en
el terreno de juego consiguiendo una coordinación absoluta entre todos.
Vamos a realizar a continuación un pequeño esquema que dejará más claro cómo es esta
comunicación entre componentes del equipo:
- El JDKRobot tiene una Orden inicial denominada Inicio. Se encarga de detectar si hay
compañeros o no, y si los hay de elegir jefe.
- En función de que esté solo o no, siendo jefe o no siéndolo, la orden siguiente será
distinta.
- Cuando un tanque que está solo encuentra un enemigo se auto ordena atacarle (cambia
su orden por otra que lleve a cabo el ataque al enemigo elegido). Cuando un jefe detecta
enemigos ordena a los soldados disponibles atacarle.
Una vez que el tanque sabe si hay compañeros o no en el terreno de juego puede
suceder lo siguiente:
Lucha individual
En este apartado vamos a explicar lo que ocurre en nuestro programa cuando se realiza
una lucha individual (está luchando un solo JDKRobot). Para ello explicaremos paso a
paso lo que ocurre desde que se inicia la batalla hasta que esta termina.
1. Inicialmente todo tanque ejecuta la orden Inicio para saber cual es el papel que tiene
asignado en este combate.
En este caso al ver que no hay equipo se asigna un color y un nombre y empieza a
ejecutar la orden Solo.
4. Si detectamos que hemos ganado pasamos a ejecutar la orden Victoria: Tiritamos, nos
movemos para adelante y para atrás unos pocos píxeles. Esto tiene como fin evitar
ejecutar otro tipo de acciones que puedan ponernos en peligro, es decir, acciones que
nos quiten vida (por ejemplo chocar contra paredes).
Lucha en equipo
En este apartado vamos a explicar lo que ocurre en nuestro programa cuando se realiza
una lucha en equipo (están luchando cinco JDKRobots). Para ello explicaremos paso a
paso lo que ocurre desde que se inicia la batalla hasta que esta termina.
1. Inicialmente todo tanque ejecuta la orden Inicio para saber cual es el papel que tiene
asignado en este combate.
Si es el que tiene nombre menor se autoasigna como el jefe (Ejecuta la orden Jefe) y
guarda en una lista los nombres de los tanques de su equipo. Y manda al resto de los
componentes del equipo el color del mismo (elegido aleatoriamente) y la orden que
deben llevar a cabo: ALoLoco.
En lo referente al color es fácil distinguir al jefe del resto, pues es de color ligeramente
más oscuro que los demás miembros del equipo y con el cañón negro.
2. Si es el jefe:
Da vueltas pegado a los bordes de la pantalla girando el visor para ver donde están los
enemigos. En el momento que detecta uno puede reaccionar de dos maneras distintas:
- Si estoy en condiciones que no me suponen una gran posibilidad de fallo, disparo.
- Si disparar implica poder fallar, no dispara, y mando por broadcast una nueva orden
para todos los demás integrantes del equipo: AcosoYDerribo.
3. Si no es el jefe:
Ejecuta la orden de ALoLoco mientras que el que está ejecutando la orden Jefe no le
mande ninguna orden nueva.
Esta orden lo que hace es que el tanque no esté nunca quieto, y que cuando encuentre un
tanque enemigo dispare.
Tanto en un caso como en el otro, cuando se gana se ejecuta al orden Victoria. Lo que
hace esta orden es hacer que el tanque tiemble para que no haga cosas que le
perjudiquen.
Código
En este apartado vamos a pasar a mostrar nuestro código convenientemente comentado
para el fácil entendimiento del mismo.
AcosoYDerribo.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden AcosoYDerribo.
*Cuando se da esta orden el tanque que la recibe sigue y ataca hasta acabar con el al enemigo de nombre
*pasado como parámetro en el constructor.
*
*Implementa un algoritmo de predicción de la trayectoria del enemigo para acertar con más facilidad si el
*enemigo está en movimiento.
*
*Su principal utilidad es para realizar emboscadas a un tanque enemigo entre varios miembros del equipo.
*
*Cuando se recibe un impacto de un aliado nos retiramos de la trayectoria de este. De esta forma
*fácilmente todos los tanques que realizan la emboscada se sitúan más o menos en círculo en torno al
*enemigo.
*/
this.nombreObjetivo=nombreObjetivo;
}
//El cañón dará vueltas para encontrar al enemigo y dispararle lo antes posible.
jdk.setTurnGunLeft(1000);
//Nos vamos moviendo un poco.
jdk.ahead(mover);
jdk.back(mover);
}
jdk.turnGunRight(normalRelativeAngle(theta - jdk.getGunHeading()));
// Ahora podemos disparar al enemigo
jdk.fire(3);
//Vamos a colocar al tanque en la zona correcta
ponerEnSuSitio(e,theta);
}
//Hacemos un barrido con el cañón en un margen estrechito para volver a localizar al objetivo
jdk.setTurnGunRight(20);
}
if(e.getDistance()<minDist){
jdk.turnRight(normalRelativeAngle(theta - jdk.getHeading()));
jdk.back(minDist-e.getDistance());
}
if(e.getDistance()>maxDist){
jdk.turnRight(normalRelativeAngle(theta - jdk.getHeading()));
jdk.ahead(e.getDistance()-minDist);
}
}
if(event.getName().equals(nombreObjetivo)){
jdk.nuevaOrden(new ALoLoco());
}
}
jdk.turnRight(90);
jdk.setTurnGunLeft(90);
mover=150;
}
ALoLoco.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden ALoLoco.
*La ejecutarán los tanques cuando no tengan otra orden que ejecutar con el fin de que su posición sea
*difícil de predecir.
*Se mueven 'pseudoaleatoriamente' y cuando detectan un objetivo además le disparan.
*/
//Solo dispara si es enemigo y si no hay indicios de que es difícil darle, en función de su velocidad y
//su distancia.
if (!jdk.isTeammate(e.getName()) && e.getVelocity()*e.getDistance()<50)
jdk.fire(3);
}
if (movingForward){
jdk.setBack(40000);
movingForward = false;
}
else{
jdk.setAhead(40000);
movingForward = true;
}
}
}
Ataque.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden Ataque.
*Esta orden es una variante de AcosoYDerribo. La ejecutarán los tanques que están sin equipo cuando
*han fijado un objetivo.
*La principal variación es que con esta orden se colocará más cerca del objetivo y girará en círculo hasta
*acabar con el enemigo.
*/
super(nombreObjetivo);
this.distance=distance;
//Queremos estar más cerca del enemigo de lo que está previsto para emboscadas.
maxDist=100;
minDist=150;
}
//Nos colocamos a la distancia requerida en torno al enemigo, disparamos y nos posicionamos para
//empezar a girar en círculo.
if(distance>maxDist)jdk.ahead(distance - maxDist);
else jdk.back(minDist -distance);
jdk.fire(3);
jdk.turnRight(45);
jdk.turnGunLeft(45);
}
Codigo.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
package jdk;
/*
*Cuando los tanques quieren comunicarse entre ellos se enviarán códigos.
*/
this.c=c;
}
return c;
}
}
Inicio.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden Inicio.
*Es la 'orden' que ejecutarán todos los tanques al inicio de la batalla para tomar conciencia de quienes son
*los integrantes del equipo, decidir quien es el jefe e inicializar sus colores y actividad en la partida.
*/
try{
//Mando los colores
jdk.broadcastMessage(c);
//Pongo a los demás a moverse a lo loco para evitar que sean alcanzados fácilmente hasta nueva
//orden.
jdk.broadcastMessage(new ALoLoco());
}
catch(IOException ioe){
//Avanzamos por hacer algo. Si no hasta que se reciba la 1º orden no sabremos que hacer y podemos
//entrar en un bucle vacío.
jdk.ahead(100);
}
//En la orden de inicio, solo voy a aceptar (aparte de lo que se recoge en RobotJDK) el color del equipo.
JDKRobot.java
/*
*Robocode.
*Quipo: JDK.
Inteligencia en Redes de Comunicaciones 16 Jessica Rivero Espinosa (100025022)
David del Valle Agudo (100025228)
Practica Final: ROBOCODE
/*
*JDKRobot: Robots que forman los JDKs
*Estos robots extienden toda la funcionalidad de los TeamRobots para conseguir un comportamiento más
*complejo y adaptable a la situación. Además permite que los integrantes de estos equipos tengan un alto
*grado de colaboración en equipo.
*
*Para conseguirlo cada JDKRobot contiene una 'unidad de comportamiento' denominada 'Orden' que se
*encarga de responder a los eventos que recoge el robot, en lugar de ser el robot quien directamente lo
*hace.
*
*Para adaptarse a las nuevas condiciones de entorno que se presenten, el tanque simplemente cambiará la
*Orden que ejecuta.
*
*Cuando el líder desee que los tanques del equipo ejecuten una determinada acción, enviará a los tanques
*que considere oportuno nuevos objetos Ordenes que determinarán sus comportamientos a partir de este
*momento.
*
*Los tanques además pueden comunicarse mandándose Códigos.
*/
//PROPIEDADES
private Orden orden;//Ordenes que ejecuta el tanque actualmente.
//MÉTODOS
//Método run: Comportamiento por defecto.
//Nueva orden
//Método que se ejecuta para cambiar de orden.
orden=o;
orden.soy(this);//indicamos quien soy a la orden que voy a realizar.
}
return orden;
}
//Reencamino todos los eventos para que se ejecuten en el contexto de la orden actual encomendada.
orden.impactoAImpacto(event);}
orden.impactoAcertado(event);}
orden.impactoFallido(event);}
orden.impactoRecibido(event);}
orden.colision(event);}
orden.pared(event);}
orden.muerte(event);}
orden.enemigoDetectado(event);}
orden.enemigoMatado(event);}
orden.penalizacion(event);}
orden.eventoPrivado(event);}
orden.victoria(event);}
}
Jefe.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden Jefe.
*Es la Orden que ejecutará el tanque que se declara líder del equipo. Su misión será la de buscar
*objetivos, ordenar a los tanques del equipo atacarlos, dejar heredero si muere...
*
*Intentará en la medida de lo posible salvar el pellejo dando vueltas por los bordes del terreno de juego.
*Solo se despegará del borde ante ataques.
*/
//METODOS
this.registroEquipo=registroEquipo;
this.registroEnemigos=registroEnemigos;
}
//Acción normal del jefe. Dar vueltas sin separarse de las paredes.
if (!jdk.isTeammate(e.getName())){
//Si no es del equipo, no se mueve mucho, no está muy lejos y me encuentro suficientemente bien le
//ataco, para evitar perder energía a lo tonto. Somos el jefe y tenemos la obligación de mantenernos
//vivos todo lo que podamos.
}
}
}
}
//Si le tenemos en frente mejor cambiamos la trayectoria puesto que si no nos moveremos hacia
//él y seremos fácilmente alcanzables.
if (e.getBearing() > -90 && e.getBearing() < 90){
jdk.turnRight(45);
jdk.back(100);
jdk.turnRight(45);
}
//Si no avanzamos y ya está
else
jdk.ahead(100);
jdk.setTurnGunRight(2000);//Seguimos dando vueltas al cañón (con el radar).
}
int codigo=c.getCodigo();
if (codigo==Codigo.MUERTO){
//Si se nos ha muerto uno:
//Le eliminamos de nuestro registro y llamamos a la familia: una baja más.
Registro r=buscarEnEquipo(robotOrigen);
if(r!=null)registroEquipo.remove(r);
//Si solo quedo yo o quedamos menos de dos, tengo que cambiar de estrategia, será mejor si cada
//uno intenta salvar su pellejo por si solo. Todos soldado raso y que sea lo que dios quiera.
if(registroEquipo.size()<2){
jdk.nuevaOrden(new SoldadoRaso());
try{
jdk.broadcastMessage(new SoldadoRaso());//Por si queda otro.
}
//IOException
}
}
}
}
if((e.getBearing()%90)==0){
//Me están disparando desde la dirección en la que me desplazo.
jdk.turnRight(45);//Cambiamos de dirección
jdk.ahead(moveAmount);//Y avanzamos.
}
}
//Me matan:
//Si quedan más de dos miembros del equipo deberíamos reorganizar el grupo antes de morir
heroicamente.
if(registroEquipo.size()>2){
//El primero será el nuevo jefe.
Registro jefe=(Registro)registroEquipo.elementAt(0);
registroEquipo.remove(jefe);
try{
jdk.sendMessage(jefe.nombre,new Jefe(registroEquipo,registroEnemigos));//Defiende lo que yo
no he podido defender.
}
//IOException
}
}
else{
try{
//Con los que quedan no hay para reorganizar el equipo. Cada uno que haga lo que pueda.
jdk.broadcastMessage(new SoldadoRaso());
}
//IOException
}
}
}
for(int i=0;i<registroEquipo.size();i++)
if(!(((Registro)registroEquipo.elementAt(i)).nombre.equals(s)))
return (Registro)registroEquipo.elementAt(i);
return null;
}
for(int i=0;i<registroEnemigos.size();i++)
if(!(((Registro)registroEnemigos.elementAt(i)).nombre.equals(s)))
return (Registro)registroEnemigos.elementAt(i);
//Pero si hemos encontrado un enemigo nuevo del que no teníamos constancia, lo creamos
Registro r=new Registro();
r.nombre=s;
registroEnemigos.addElement(r);
return r;
}
}
Orden.java
/*
*Robocode.
*Quipo: JDK.
Inteligencia en Redes de Comunicaciones 22 Jessica Rivero Espinosa (100025022)
David del Valle Agudo (100025228)
Practica Final: ROBOCODE
/*
*
* Clase Orden.
*
* Las clases que extienden de esta representan el comportamiento de tanques.
* Todo tanque contendrá un objeto 'Orden' y todo lo que hace el tanque viene determinado por las
* acciones que contiene su 'Orden'.
*
* Cuando el mando del equipo quiere encomendar otra misión a este tanque le envía un nuevo
* objeto Orden, a partir de este momento, y hasta nueva orden, el comportamiento del tanque en
* todos los aspectos estará determinado por lo que contiene el nuevo objeto Orden.
*
* La clase Orden responde a todos los posibles eventos que puede recibir un tanque.
*
* En ningún caso es necesario definir la acción de todos los métodos, solo las de los métodos que
* se consideren oportunos para cumplir una orden.
*
*/
//PROPIEDADES
JDKRobot jdk; //Robot cuya acción ahora está controlando esta Orden.
//MÉTODOS
//IDENTIFICACIÓN
//EJECUCIÓN
//--------
//Lo que debe ejecutar el 'run' del tanque al que se le ha mandado esta orden.
//En inicio se ejecutan las acciones de inicialización que se suelen incluir al comienzo del método run.
//En ejecutar se realizan las acciones que se suelen realizar dentro del bucle while que hay dentro del
run
//normalmente.
//Nota. no hay que poner en código el buche, el método ejecutar se ejecuta en un bucle dentro del 'run'
//del robot .
try{
jdk.broadcastMessage(new Codigo(Codigo.MUERTO));
}
//IOException
}
}
//Cuando no hacemos nada en mucho tiempo el juego nos avisa. Tiene penalización (onSkippedTurn)
}
//Cuando nuestra bala choca con otra bala (onBulletHitBullet)
//Método que se ejecuta cuando una bala que hemos lanzado se pierde (onBulletMissed)
jdk.nuevaOrden(new Victoria());
}
//RECEPCIÓN DE CÓDIGOS
//--------------------
//Método para recibir un código. Un código es un entero que indica una tiene un significado para el que
//lo recibe. este significado está definido en la clase Código.
//RECEPCIÓN DE MENSAJES: Puede haber objetos pasados como mensajes específicos para esta
orden.
}
}
Registro.java
package jdk;
/**
* Donde el jefe guarda los datos de los miembros del equipo y de los enemigos.
*/
RobotColors.java
package jdk;
import java.awt.Color;
import java.lang.Math;
/**
* RobotColors - A serializable class to send Colors to teammates
*/
public RobotColors(){
//El color se elige aleatoriamente
int rL=(int)Math.round(Math.random()*200);
int gL=(int)Math.round(Math.random()*200);
int bL=(int)Math.round(Math.random()*200);
int r=rL+55;
int g=gL+55;
int b=bL+55;
this.bodyColor = new Color(r,g,b);
this.gunColor = new Color(r,g,b);
this.radarColor = new Color(r,g,b);
this.bodyColorL = new Color(rL,gL,bL);
this.gunColorL = new Color(0,0,0);
this.radarColorL = new Color(0,0,0);
}
SoldadoRaso.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden SoldadoRaso.
*La ejecutan los tanques cuando el equipo está muy mermado.
*Tienen un comportamiento 'camicace'. Buscan cualquier objetivo y van contra el hasta que mueren o
*muere.
*No obstante si tiene poca energía pide relevo a el jefe (por si todavía esta vivo que le releve).
*/
//METODOS
//Acción normal del soldadoRaso. Gira sobre si mismo buscando objetivos.
jdk.turnRight(5 * turnDirection);
jdk.ahead(e.getDistance() - 20);
jdk.scan();
}
//Si nos dan giramos, al desviarnos de nuestra trayectoria es menos probable que nos den de nuevo.
jdk.turnRight(15);
}
Solo.java
/*
*Robocode.
*Quipo: JDK.
*David del Valle Agudo Y Jessica Rivero Espinosa.
*/
/*
*Orden Solo.
*Es una modificación de la clase ALoLoco para permitir al tanque desenvolverse solo.
*
*Para tanques que están solos en el terreno de juego.
*Son autosuficientes. Fijan un objetivo y se auto ordenan atacarle.
*/
if (!jdk.isTeammate(e.getName())){
//Si no es del equipo lo disparamos antes de nada.
jdk.fire(3);
//Nos orientamos hacia el y volvemos a disparar.
jdk.turnRight(e.getBearing());
jdk.fire(3);
//Y ahora nos ordenamos atacarlo hasta acabar con él.
jdk.nuevaOrden(new Ataque(e.getName(),e.getDistance()));
}
}
}
Victoria.java
package jdk; //Jessi & David Killer team. :-)
import robocode.*;
import java.io.*;
import java.awt.Color;
import java.lang.Math;
import java.util.*;
/**
*Orden que se ejecuta en cuanto se detecta la victoria de nuestro equipo. Es para evitar hacer cualquier
*otra cosa que pueda perjudicar al equipo, por ejemplo seguir disparando.
*/
//Simplemente oscilamos.
jdk.ahead(2);
jdk.back(2);
}
}