## 4. Construccion de Robots (Robot construction)

Este capitulo explica lo que se necesita saber para construir tus propios robots. Lo mas importante es conocer el lenguaje de mensajes, formado aproximadamente por 35 comandos usados para comunicarse con el programa servidor. Es también muy útil estudiarse los robots de ejemplo del directorio `Robots/`.

## 4.1 Leer Mensajes (Reading messages)

Al comienzo de cada secuencia el proceso robot es lanzado por el servidor y asigna dos pipes (tuberias), una para la entrada y otra para la salida. Estas estan conectadas a `stdin` y a `stdout`, por lo que desde el punto de vista del robot, este se comunica con el servidor mediante la salida estandar y mediante la entrada estandar.

Esto significa que los robots pueden ser escritos en casi cualquier lenguaje de programación. De todas formas, el robot ha de ser capaz de saber cuando recibe un mensaje. Para ello hay al menos tres métodos, que son:

Standard in blocks:

  Este es el método mas simple. Es como si siempre hubiera un mensaje esperando. Lo malo es que con este método no puedes hacer ningun cálculo mientras esperas nuevos mensajes.

  Para elegir este metodo, manda la siguiente opcion en cuanto el programa comience.:

      "cout << "RobotOption " << USE_NON_BLOCKING << " " << 0 << endl;"

  Ten en cuenta que esto es codigo c++. Si no usas c++ simplemente imprime en la salida estandar al mensaje mostrado. endl es lo mismo que 'end of line'.

Select:

  Usar la funcion `select` hace posible que el robot tenga un mejor control a la hora de recibir nuevos mensajes. Te permite, por ejemplo, leer nuevos mensajes disponibles, hacer algunos calculos, mandar comandos y esperar mensajes. Para aprender mas sobre `select`, lee la documentacion de Unix (las paginas man o la informacion del emacs).

  Para seleccionar el metodo select, envia la siguiente opcion en cuanto el programa comience

      cout << "RobotOption " << USE_NON_BLOCKING << " " << 1 << endl;

  Ten en cuenta que esto es codigo c++.

Signals:

  Si quieres, puedes indicarle a RealTimeBattle que envie una señal al robot en cuanto este disponible un nuevo mensaje. Este metodo permite al robot estar continuamente informado por el servidor incluso cuando el robot esta ocupado calculando algo. Si no estas seguro de como usar las señales, mira en la documetnacion de unix o estudia los otros robots para aprender mas.

  Para seleccionar este metodo, envia la siguiente opcion en cuanto se inice el programa:

      cout << "RobotOption " << USE_NON_BLOCKING << " " << 1 << endl;
      cout << "RobotOption " << SIGNAL << " " << SIGUSR1 << endl;

  Se trata de codigo c++.

  Puedes seleccionar cualquier señal en lugar de `SIGUSR1`

Como apoyo para la implementacion de estos tres metodos, el robot `rotate_and_fire` ha sido escrito en tres versiones diferentes. Tomate la libertad de estudiar y coger código de este robot, si quieres.

No es recomendable estar continuamente mirando si hay mensajes nuevos, ya que esto ralentiza los procesos de una forma considerable, y en una competition-mode el robot moririía por salirse del tiempo de CPU.

## 4.2 Messagetypes.h

El fichero `Messagetypes.h` es una buena fuente de informacion sobre el lenguaje de mensajes. Es un fichero c/c++ (un include, vamos), pero se puede reescribir facilmente para usarlo con otros lenguajes. Aquí encontrarás un listado de los mensajes, los avisos (los warning), objetos, opciones de juego y opciones de los robots.

## 4.3 Cheating

Desde el momento en que el prograso de la batalla es en tiempo real con procesos reales, es posible escribir programas que 'hagan trampas' de una manera u otra. Por ejemplo examinando los otros robots o incluso al RealTimeBattle mismamente para obtener mas informacion, usando muchos recursos para 'ahogar' a los otros robots, etc... Esta no es la manera de vencer a los oponentes, por supuesto, asi que intentaremos erradicarlo al maximo posible.

En el modo competicion (competition-mode) los robots tienen un uso limitado de CPU, por lo que un robot no puede usar toda la CPU. Esta 'norma' podria ser saltada lanzando procesos hijos. Aunque sería fácilmente detectable un robot con comportamiento sospechoso.

No es posible prevenir todas las maneras de 'hacer trampas' en RealTimeBattle. Por ejemplo esta permitido leer y escribir en ficheros, pero recuerda que los organizadores de las competiciones pueden prohibir esto si quieren. Poniendo permisos sobre los executables de los robots y sobre los directorios esto se puede hacer facilmente.

Es posible que haya mas formas de hacer cosas 'ilegales' con los robots. Si detectas una de estas formas, por favor manda un bug report. De todas formas es responsabilidad del organizador del torneo asegurarse de que se cumplen todas las normas.

## 4.4 Mensajes a los Robots (Messages to robots)

Initialize [first? (int)]

  Este es el primer mensaje que el robot recibirá. Si el argumento es uno, esta es la primera secuencia del torneo y se deberá mandar el nombre y el color (Name and Colour) al servidor, o de lo contrario el esperaría los mensajes de nombre (YourName) y color (YourColor). Ver debajo.

YourName [name (string)]

  El nombre actual del robot.

YourColour [colour (hex)]

  Color actual del robot. Cambialo si no te gusta el actual.

GameOption [option (int)] [value (double)]

  Al comienzo de cada juego, se enviarán a los robots un número de parámetros, que pueden ser útiles al robot. Para obtener una lista de ellos, mira en el fichero Messagetypes.h la sección de `game_option_type`. En el capitulo de opciones (options chapter) encontraras información mas detallada de cada opción.

  debug level es enviado al robot como una opcion de juego, aunque no se haya indicado en las opciones.

GameStarts

  Este mensaje es enviado cuando comienza el juego.

Radar [distance (double)] [observed object type (int)] [radar angle (double)]

  Este mensaje ofrece información sobre el radar en cada turno. Recuerda que el angulo del radar es relativo al frontal del robot y viene dado en radianes.

Info [time (double)] [speed (double)] [cannon angle (double)]

  El mensaje Info siempre sigue al mensage Radar. Ofrece mayor información sobre el estado del Robot. 'Time' es el tiempo transcurrido desde el comienzo del juego. Esto no tiene porque ser igual que el tiempo real transcurrido, debido a la escala de tiempo (time scale) y al max timestep.

Coordinates [x (double)] [y (double)] [angle (double)]

  Informa sobre la posición actual del robot. Este mensaje se envia solo si la opción Send robot coordinates es 1 o 2. Si es 1 las coordenadas son enviadas relativas a las posicion de comienzo, aunque el robot no sabe exactamente donde empieza, pero si sabe si se ha movido de su punto de origen.

RobotInfo [energy level (double)] [teammate? (int)]

  Si detectas un robot con el radar, este mensaje será enviado a continuación, dando información sobre el robot. Se dará el nivel de energía del oponente asi como tu propia energia (ver abajo). El segundo argumento es solo interesante en el modo equipo (team-mate), que aun no esta implementado. 1 significa compañero de equipo y 2 significa enemigo.

RotationReached [what has reached(int)]

  Cuando la opción SEND_ROTATION_REACHED esta puesta adecuadamente, este mensaje es enviado cuando un giro (realizado mediante RotateTo o RotateAmount) ha finalizado o bien cuando se modifica la dirección (sweeping). El argumento corresponde a la opción 'what to rotate', como en Rotate.

Energy [energy level(double)]

  Al final de cada turno el robot conocerá su nivel de energía. De todas formas, no sera un numero exacto, sino un numero limitado a los niveles de energia (energy levels).

RobotsLeft [number of robots (int)]

  Al principio de cada juego y cuando un robot muera, el número restante de robots sera enviado a todos los robots que aun esten vivos.

Collision [colliding object type (int)] [angle relative robot (double)]

  Cuando un robot se golpea o es golpeado por algo recibe este mensaje. En el fichero Messagetypes.h puedes encontrar una lista de los tipos de objeto. Obtendrás el ángulo desde el cual la colisión ha ocurrido (angulo relativo al robot) y el tipo de objeto contra el que has chocado, aunque no recibiraá la información de la gravedad del choque. Esto puede ser determinado, indirectamente, por el decremento de la energía.

Warning [warning type (int)] [message (string)]

  Un mensaje de aviso (warning) sera enviado al robot en caso de que ocurra algun problema. Actualmente hay siete mensajes de aviso que pueden ser enviados, que son:

  `UNKNOWN_MESSAGE:` El servidor ha recibido un mensaje que no puede reconocer.

  `PROCESS_TIME_LOW:` El uso de la CPU ha sobrepasado el porcentaje de CPU (CPU warning percentage). Solo en modo competicion (competition-mode).

  `MESSAGE_SENT_IN_ILLEGAL_STATE:` El mensaje que se ha recibido no se puede procesar en ese momento del juego. Por ejemplo cuando envia un mensaje Rotate antes de comenzar el juego.

  `UNKNOWN_OPTION:` Cuando el robot envía una opción (robot option)con un nombre inválido o con un argumento incorrecto para esa opcion.

  `OBSOLETE_KEYWORD:` Ese 'keyword' (comando) esta obsoleto y no debería ser usado nunca mas. Para mas informacion mira en el fichero `ChangeLog`.

  `NAME_NOT_GIVEN:` El robot no ha enviado su nombre antes de que el juego comience. Esto sucede si el tiempo de inicio (robot startup time) es demasiado corto o bien el robot no ha enviado su nombre lo suficientemente pronto.

  `COLOUR_NOT_GIVEN:` El robot no ha enviado su color antes de que el juego comience.

Dead

  El robot ha muerto. No intentes enviar nuevos mensajes hasta el final del juego, ya que el servidor no los leerá.

GameFinishes

  El juego actual ha finalizado. Preparate para el siguiente !!!

ExitRobot

  Sal del programa inmediatamente!!! Sino sera matado (killed) a la fuerza.

## 4.5 Mensajes de los Robots (Messages from robots)

RobotOption [option nr (int)] [value (int)]

  Actualmente solo hay dos opciones disponibles:

  `SIGNAL:` Le comunica al servidor que envie una señal cuando haya un mensaje esperando. El argumento determinará esa señal. Envia este mensage (con el argumento SIGUSR1, por ejemplo) tan pronto como estes listo para recibir la señal. Por defecto es 0, lo que significa que no se envie ninguna señal.

  `SEND_SIGNAL:` Le indica al servidor que envie SIGUSR1 cuando haya un mensaje esperando. Envia este mensaje (con argumento 1 (=cierto)) tan pronto como estes preparado para recibir la señal. Por defecto es falso.

  `SEND_ROTATION_REACHED:` Activa esta opcion si quieres que el servidor te envie un mensaje RotationReached cuando finalize una rotacion. Con un valor de 1, el mensaje será enviado cuando finalice un RotateTo o bien un RotateAmount. Con un valor 2, los cambios en la direccion sweep (de barrido) seran también notificados. Por defecto esta opcion esta a 0, con lo que ningun mensaje sera enviado.

  `USE_NON_BLOCKING:` Selecciona como funciona la lectura de mensajes (reading messages). Esta opcion será enviada tan pronto como el programa comienza. Esta opcion debe ser activada siempre, ya que no hay disponbible ningun valor por defecto.

Name [name (string)]

  Cuando se recibe un mensaje de inicializacion (Initialize) con un argumento a 1, indicando que esa es la primera secuencia, debes enviar tanto el nombre como el color del robot.

Colour [home colour (hex)] [away colour (hex)]

  Mirar arriba. Los colores son como las camisetas de fútbol, el color propio es usado excepto que ya este ocupado por otro. Si no se pueden utilizar ninguno de los colores indicados, se escogerá uno aleatoriamente.

Rotate [what to rotate (int)] [angular velocity (double)]

  Fija la velocidad angular del robot, del cañón y/o del radar. 'what to rotate' 1 para el robot, 2 para el cañón, 4 para el radar o una suma de cualquiera de los tres para fijar la velocidad de rotación de mas de uno a la vez. La velocidad angular viene dada en radianes por segundo y esta limitada a maxima velocidad de rotacion (Robot (cannon/radar) max rotate speed).

RotateTo [what to rotate (int)] [angular velocity (double)] [end angle (double)]

  Como Rotate, pero rotará a un angulo dado. Ten en cuenta que los angulos del radar y del cañón son relativos al ángulo del robot. No podras usar este comando para rotar el robot, para ello utiliza RotateAmount.

RotateAmount [what to rotate (int)] [angular velocity (double)] [angle (double)]

  Como Rotate, pero rotará de una forma relativa al angulo actual.

Sweep [what to rotate (int)] [angular velocity (dbl)] [left angle (dbl)] [right angle (dbl)]

  Como rotate, pero fija el radar y/o el cañón en un modo de barrido (sweep). No sera válido para el robot.

Accelerate [value (double)]

  Fija la aceleracion del robot. El valor sera fijado entre los valores aceleracion maxima/minima (Robot max/min acceleration).

Brake [portion (double)]

  Activa el freno. Freno total (portion= 1.0) significa que el rozamiento en la direccion del robot es igual al Slide friction.

Shoot [shot energy (double)]

  Dispara con la energia dada. Las opciones de disparo (The shot options) te darán mas información.

Print [message (string)]

  Muestra un mensaje en la ventana de mensajes (message window).

Debug [message (string)]

  Muestra mensajes en la ventana de mensaje (message window) si estamos en modo debug (debug-mode).

DebugLine [angle1 (double)] [radius1 (double)] [angle2 (double)] [radius2 (double)]

  Dibuja una linea directamente sobre la arena. Solo esta disponible en el máximo nivel de debug (5), de lo contrario se enviara un aviso (warning message) . Los argumentos son el punto inicial y el punto final de la linea dada en coordenadas polares relativas al robot.

DebugCircle [center angle (double)] [center radius (double)] [circle radius (double)]

  Similar a la opcion anterior, pero dibuja un circulo. Los primeros dos argumentos indican el angulo y el radio del punto central relativo al robot. El tercer argumento indica el radio del circulo.