Juego del hambre: comer o morir
Si no comes, mueres. Si comes, vives (hasta que mueras). Usted va a morir, así que trate de morir el pasado.
Visión de conjunto
Hay una isla poblada con una manada de presas. Tú controlas un paquete de cinco depredadores. Su objetivo es mantener viva su manada. Haz esto comiendo presas. Las presas tienden a huir de los depredadores y, de lo contrario, intentan permanecer en una bandada. Por supuesto, su paquete estará en el mismo campo que cualquier otro paquete , por lo que la competencia tratará de comerlos antes de que pueda. No dejes que esto te desanime, o morirás de hambre.
Cómo jugar
Cree y envíe un programa de línea de comando para dirigir su paquete. Recibirá información de estado del programa de control en STDIN y enviará comandos en STDOUT. El formato se detalla a continuación. Cada programa solo se ejecutará una vez y debe permanecer en ejecución hasta que no haya más miembros del paquete con vida. Deberá leer la entrada a medida que ingresa y responder rápidamente. Hay un tiempo de espera estricto de 200 ms para cada respuesta. Si no ha respondido para entonces, su paquete no recibirá nuevas instrucciones para el turno actual.
Si el controlador no puede ejecutar su programa, no se considerará válido. Incluya la cadena de línea de comando que necesitaré para ejecutar su envío. Si hay instrucciones especiales (para configurar compiladores, etc.), inclúyalas. Si no puedo hacerlo funcionar, le pediré ayuda en los comentarios. Si no responde, no podré aceptar su envío.
El torneo se llevará a cabo en un sistema Linux de 64 bits. Tenga esto en cuenta al dar las instrucciones necesarias.
Detalles
La posición y dirección de cada criatura tienen la forma de un par de números de coma flotante de doble precisión (por ejemplo
double
) que representan sus coordenadasx
yy
, respectivamente.Cada criatura se considera un punto. Esto significa que pueden superponerse y ocupar el mismo espacio. No te dejarán de lado, y no existe un concepto de colisión con otras criaturas.
La isla es un cuadrado, 500 unidades a un lado. Si intentas aventurarte más allá de esos límites, estarás sujeto al borde. El origen
{0,0}
está en la esquina superior izquierda, con unx
aumento hacia la derecha y uny
aumento hacia abajo. Nuevamente, el mapa no se ajusta .El juego comienza con más de 1500 presas (packCount * 50) . Se reunirán en el centro de la isla, pero rápidamente decidirán comenzar a moverse.
Los paquetes se organizarán en un círculo uniformemente espaciado alrededor del perímetro. El orden del paquete se baraja, así que no cuente con comenzar en una ubicación en particular.
Los animales de presa pueden ver a todos los demás animales dentro de un radio de 30 unidades. Se pueden mover a un máximo de 6.0 unidades por turno.
Los depredadores pueden ver a todos los demás animales dentro de un radio de 50 unidades. Pueden moverse a un máximo de 6.1 unidades por turno. Esto significa que pueden ver presas antes de ser vistas y (apenas) superarlas.
Los depredadores viven y mueren según su nivel de hambre . Comienza en 1000 y disminuye en uno cada turno. Si, después del movimiento, un depredador está dentro de 1 unidad de presa, se lo comerá automáticamente. Esto elimina la presa y establece el hambre del depredador en 1000. Cada depredador solo puede comer una presa por turno. Si hay más de uno dentro del rango, se comerá el que el bucle llegue primero (no necesariamente el más cercano). Un depredador muere si su hambre llega a cero.
Los paquetes comienzan con cinco miembros cada uno. Cada 5000 turnos, todos los paquetes que aún estén en el juego generarán un nuevo miembro. Se colocará dentro del rango visible de un miembro del paquete. Asegúrese de que sus entradas puedan manejar más de cinco miembros.
Cada 1000 turnos, se generarán más presas. El número de nuevas presas será el número de depredadores vivos menos uno.
Los depredadores no pueden atacar a otros depredadores. Comen presas cuando lo atrapan. Eso es.
El orden dentro de un turno es:
- Todas las presas toman decisiones
- Todos los depredadores toman decisiones.
- Todas las presas se mueven
- Todos los depredadores se mueven / comen
El orden en que cada paquete toma sus decisiones / movimientos será aleatorio en cada turno.
Protocolo (general)
Todas las comunicaciones se realizan en formato de cadena US-ASCII
. Los números se convierten en cadenas usando Java Double.toString()
o Integer.toString()
. Su salida debe estar formateada para que Java la pueda leer Double.valueOf(String)
(no generará números enteros). Para obtener detalles sobre los formatos analizables, consulte la documentación deDouble
. Todos los campos de una línea están separados por el \t
carácter estándar , y las líneas nuevas lo están \n
. La cadena completa terminará en un byte nulo \0
.
En los ejemplos a continuación, estoy usando <>
para marcar los campos por razones de legibilidad. Estos no están presentes en las cadenas reales.
Protocolo (entrada)
La cadena de entrada varía en longitud, dependiendo de cuántas criaturas son visibles para su paquete. Puede superar los 100k caracteres, así que prepárate para eso. La configuración básica es:
Línea 0: información básica sobre el juego.
turn
es el número de turno actual, y los recuentos son el número total de presas y depredadores que quedan en el campo. Estos estáninteger
en forma de cadena.<turn>\t<preyCount>\t<predatorCount>\n
Línea 1: los ID únicos y los niveles de hambre de los miembros de tu manada. Estos no se dan en el mismo orden para cada entrada. Use los identificadores únicos para rastrear miembros individuales, no el orden en que aparecen en la entrada. De nuevo, estos son
integer
como cadenas. Para un paquete de dos, esto sería:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Línea 2: las posiciones de los miembros de su manada, en el mismo orden que se indica en la línea 1 . Estos son
double
como una cadena:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
Las siguientes líneas son la visibilidad de cada miembro del paquete, en el mismo orden que se da en la línea 1 . Estos se darán como dos líneas por miembro.
El primero para cada uno consiste en ubicaciones para la presa que puede ver. El segundo es la ubicación de los depredadores que puede ver. Estas ubicaciones no son únicas en su conjunto. Por ejemplo, si dos miembros de la manada pueden ver el mismo animal, estará en la cadena de ambos miembros. Además, sus propios miembros de la manada se incluirán. Si desea excluirlos, puede comparar ubicaciones con sus propios miembros. Todas las ubicaciones están en double
formato de cadena.
Para cada miembro vivo:
<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n
Finalmente, el último personaje será \0
, al comienzo de la siguiente línea.
Excepción: si recibe la entrada dead\0
, su paquete está muerto. Termine su programa con gracia, por favor. El controlador debería cerrar todos los procesos vivos cuando está cerrado, pero prefiero no tener procesos zombies por todas partes. Como cortesía, puede incluir un tiempo de espera de entrada. Por ejemplo, mi clase de ejemplo finaliza si no recibe información durante 15 segundos.
Protocolo (salida)
La salida es simple. Dará un par de double
valores para cada miembro del paquete en vivo. Estos representan el movimiento que le gustaría que tomaran en este turno. Por ejemplo, si tu criatura se encuentra actualmente {100.0, 100.0}
y les das un comando {-1.0, 1.0}
, se moverán a {99.0, 101.0}
. Todos los números estarán en una sola línea, separados por tabulación.
Por ejemplo, si tuviera 3 miembros de la manada vivos, esta sería una respuesta válida:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
Esto se movería sus criaturas por {1.0,-1.0}
, {2.0,-2.0}
y {3.0,-3.0}
. El pedido es el mismo que el recibido en la entrada. ¡No olvides el final \0
!
Si da una entrada no válida, seguirán malos resultados. Si un número único no se puede analizar a double
, se convertirá en cero. Si la cadena en su conjunto no se puede analizar, no se darán nuevas instrucciones, y todo su paquete utilizará las instrucciones del turno anterior.
Todas las direcciones se sujetarán a una distancia máxima de 6.1 unidades. Puede moverse más lento que esto si lo desea. Por ejemplo, {1, 0}
te moverá una unidad. {6,8}
(distancia 10) solo te moverá 6.1 unidades, y se reducirá a alrededor {3.66, 4.88}
. La dirección permanece constante.
Importante: El programa de control lee su STDOUT y STDERR. Si lanza una excepción e imprime en STDERR, es muy poco probable que el mensaje tenga la forma de una respuesta válida. Intenta evitar hacer esto.
Programa de Control / Pruebas
La fuente del controlador se puede encontrar aquí en bitbucket.org . Deberá compilarlo antes de ejecutarlo. La clase principal es Game
, y todas las clases están en el paquete predeterminado. Para ejecutar, incluya el comando de cada paquete como un argumento separado. Por ejemplo, si desea ejecutar un Java ChaserPack y un Python LazyPack.py, puede usar:
java Game "java ChaserPack" "python LazyPack.py"
En el mapa, las presas aparecen en verde y los depredadores en rojo. Sin embargo, el paquete que sea el primer paquete dado como argumento tendrá un color azul. Esto tiene la intención de distinguirlos más fácilmente para propósitos de prueba. Los depredadores también parpadearán en blanco durante cinco cuadros cuando coman.
El juego continuará hasta que el último depredador muera de hambre, escribiendo en la consola a medida que ocurran eventos de hambre o extinción. Una vez que se completa el juego, se otorgará la puntuación para cada paquete. Si quiere no quiere ver los eventos de inanición / extinción, puede usar el -silent
argumento. Entonces solo generará el puntaje final. Debe pasar esto como primer argumento :
java Game -silent "java ChaserCat" "./someOtherPack"
Se incluye un paquete esqueleto de Java llamado GenericPack
. Incluye las operaciones básicas de entrada / salida necesarias. Está allí para dar un claro ejemplo de cómo analizar y responder. Si desea agregar una plantilla en otro idioma, avíseme.
También se incluye un depredador basado en la plantilla, ChaserPack
. No se incluirá en el torneo, y solo se incluye con fines de prueba. Se desempeña bastante mal, debido a un defecto de objetivo intencional. Si no puedes vencerlo, sigue intentándolo.
A continuación se muestra un ejemplo de ejecución del programa de control (haga clic para ver el video). La calidad del video no es excelente (lo siento), pero puedes tener una idea de cómo se mueve la presa. ( precaución: audio )
Puntuación
El ganador será determinado por torneo, ganando puntos en cada ronda.
Cada ronda continúa hasta que todos los depredadores estén muertos. Cada paquete se puntuará según el momento en que su último miembro murió de hambre. Luego se les asignarán puntos según el orden. Los puntos se acumularán durante diez rondas, y el vencedor es el paquete con los puntos totales más altos.
El primer lugar para cada ronda recibirá 100 puntos. Para cada lugar después de eso, la recompensa se reducirá en un 20% (redondeado hacia abajo). Esto continuará hasta que los puntos lleguen a cero (después del puesto 17). Los lugares mayores de 18 años no recibirán puntos por la ronda. Los paquetes que empaten recibirán puntos iguales. Por ejemplo:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
El máximo de puntos posibles en el transcurso del torneo es 1000, desde el primer lugar las diez veces.
Si varios programas finalizan el torneo empatado en el primer lugar, se llevará a cabo otro torneo de diez rondas con solo las entradas del primer lugar enviadas. Esto continuará hasta que emerja un vencedor.
Intentaré organizar un torneo aproximadamente semanalmente, o cuando lleguen nuevas presentaciones.
Reglas adicionales (¡juega limpio!)
No puede leer ni escribir en ningún recurso externo. Como no va a invocar su programa varias veces, cualquier información de estado puede almacenarse internamente.
No interfiera con otros procesos / presentaciones. Esto no significa que no intentes robar a sus presas, sobrepasarlas, etc. Significa que no interfieras con la ejecución del proceso. Esto queda a mi discreción.
Los concursantes están limitados a un máximo de tres entradas. Si envía más, solo calificaré los tres primeros. Si desea revocar uno, bórrelo.
Las entradas pueden no existir únicamente para apuntalar otras entradas. Cada uno debe jugar para ganar por su propio mérito.
Su programa puede generar un máximo de un proceso secundario a la vez ( descendientes totales , no directos). De cualquier manera, asegúrese de no pasar el tiempo de espera. No puede invocar la
Game
clase en sí de ninguna manera.
Resultados - 29 de abril de 2014
Aquí están los resultados del último torneo de diez rondas:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Los paquetes enviados antes de las 09:00 EDT del 29/04/2014 se incluyen en esta ejecución.
También puede ver los detalles de cada ronda . Por alguna razón, decidí numerar las rondas hacia atrás, por lo que comienza con la "ronda 10".
Actualizaciones
23/04/2014: FGreg informó un error relacionado con los tiempos de espera (¡gracias!). Se ha implementado una solución, por lo que los evaluadores querrán actualizar su código de programa de control.