Resultados finales disponibles
Introducción
Después de mi KOTH anterior con temas pesados ( guerra de fantasía , pandemia mundial ...), estoy de vuelta con un nuevo juego alegre. Esta vez, te enfrentas a una situación de "juego de mesa". Se coloca una pila de monedas al revés en el centro de una mesa realmente grande, ¡y está decidido a obtener su parte del botín!
Glosario
Monedas : fichas que pueden ser volteadas o no.
Sin voltear : monedas colocadas en la mesa con su valor apuntando hacia abajo. Este es el estado predeterminado de las monedas.
Volteado : monedas colocadas en la mesa con su valor apuntando hacia arriba.
Local : se refiere a tu pila de monedas.
Global : se refiere a la pila de monedas en el centro.
Principio
Al comienzo del juego, cada jugador comienza con 0 puntos y 0 monedas. (lanzadas o no). El juego está basado en turnos. Durante su turno, los jugadores pueden realizar hasta 3 acciones interactuando con el montón de monedas en el centro de la mesa, su propio montón de monedas o con otros jugadores.
El orden de juego se define aleatoriamente al comienzo del juego. El orden de los jugadores en la lista de argumentos representa el orden de turno, y va de izquierda a derecha en esa lista. "Siguiente" y "Anterior" se refieren respectivamente a "a la derecha en esa lista" y "a la izquierda en esa lista" con un bucle si eres el último de ambos lados.
El juego dura 50 rondas o hasta que haya 0 monedas en el centro al final de un turno de jugador (lo que significa que terminarás tus 3 acciones incluso si la pila está vacía después de tu primera acción, y puedes volver a poner monedas para dejar El juego continúa). El número inicial de monedas globales se define al azar con esta fórmula:
(2 ^ nb_players) + (nb_players * 10) - random(1 + (nb_players ^ 2))`
Cada acción te dará puntos (o te hará perder algunos) y al final del juego, cada moneda que tengas se agregará a tus puntos ( -1 para no tirada, +2 para tirada ). El jugador con la puntuacion mas alta gana.
El controlador le proporciona entrada a través de argumentos de comando, y su programa tiene que salir a través de stdout.
Sintaxis
Entrada
Cada vez que se llama a su programa, recibirá argumentos en este formato:
Round;YourPlayerId;Coins;PlayerId_Points_Flipped_Unflipped;PlayerId_Points_Flipped_Unflipped;...
Las rondas están indexadas en 1.
Entrada de ejemplo
6;2;52;1_20_3_12;0_-2_0_1;2_12_1_0
Aquí, ves que es la sexta ronda y eres el jugador 2. Hay 52 monedas en la pila central. Tienes 12 puntos, 1 moneda volteada y 0 monedas sin voltear. Los puntos pueden ser negativos.
Salida
Debe generar tres caracteres (sin espacio, sin separador), cada uno de los cuales corresponde a una acción que realizará este turno. El orden de los personajes determina el orden de las acciones. Puede generar las mismas acciones varias veces. En caso de que no haya suficientes monedas para completar su acción, utilizará el máximo de monedas disponibles y contará puntos solo para las monedas utilizadas.
N
: No hacer nada
1
: Tome 1 moneda de la pila central [Efectos: +1 local sin voltear / -1 punto / -1 global sin voltear]
2
: Tome 2 monedas de la pila central [Efectos: +2 local sin voltear / -2 puntos / -2 global sin voltear]
3
: tome 3 monedas de la pila central [Efectos: +3 local sin voltear / -3 puntos / -3 global sin voltear]
A
: coloque 1 moneda de su pila [Efectos: -1 local sin voltear / +1 punto / +1 global sin voltear]
B
: Ponga 2 monedas de su pila [Efectos: -2 locales sin voltear / +2 puntos / +2 global sin voltear]
C
: Ponga 3 monedas de su pila [Efectos: -3 locales sin voltear / +3 puntos / +3 global sin voltear]
X
: Retire 1 moneda de su pila[Efectos: -1 local sin voltear / 0 puntos]
Y
: Retire 2 monedas de su pila [Efectos: -2 locales sin voltear / 0 punto]
Z
: Retire 3 monedas de su pila [Efectos: -3 locales sin voltear / 0 punto]
R
: Rotar monedas al jugador anterior [Efectos: -1 punto por recibo sin voltear, +2 puntos por volcado recibido / aplica a todos los jugadores]
T
: Rotar monedas al siguiente jugador [Efectos: -1 punto por recibo sin voltear, +2 puntos por volcado recibido / aplica a todos los jugadores]
F
: Flip 1 moneda [Efectos: -1 local sin voltear / +1 local volteado / +2 punto]
U
: Desenrollar 1 moneda [Efectos: +1 local sin voltear / -1 local volteado / -2 punto]
Salida de ejemplo
2FF
: Toma dos monedas y lanza dos monedas, anotando -2 + 2 + 2 = 2 points
Si su salida es incorrecta, el controlador asumirá NNN
.
Controlador
Puedes encontrar el controlador en GitHub . También contiene dos samplebots, escritos en Java. Para que se ejecute, consulte el proyecto y ábralo en su Java IDE. El punto de entrada en el main
método de la clase Game
. Se requiere Java 8.
Para agregar bots, primero necesita la versión compilada para Java (archivos .class) o las fuentes para los idiomas interpretados. Colóquelos en la carpeta raíz del proyecto. Luego, cree una nueva clase Java en el players
paquete (puede tomar un ejemplo en los bots ya existentes). Esta clase debe implementarse Player
para anular el método String getCmd()
. La cadena devuelta es el comando de shell para ejecutar sus bots. Por ejemplo, puede hacer una obra bot rubí con este comando: return "C:\Ruby\bin\ruby.exe MyBot.rb";
. Finalmente, agregue el bot en la matriz de jugadores en la parte superior de la Game
clase.
Reglas
- Los bots no deben escribirse para vencer o admitir otros bots específicos.
- Se permite escribir en archivos. Escribe a "yoursubmissionname.txt", la carpeta se vaciará antes de que comience el juego. Otros recursos externos están prohibidos.
- Su envío tiene 1 segundo para responder.
- Proporcione comandos para compilar y ejecutar sus envíos.
Idiomas soportados
Intentaré admitir todos los idiomas, pero debe estar disponible en línea de forma gratuita. Proporcione instrucciones para la instalación si no está utilizando un lenguaje "convencional".
A partir de ahora, puedo ejecutar: Java 6-7-8, PHP, Ruby, Perl, Python 2-3, Lua, R, node.js, Haskell, Kotlin, C ++ 11.
Resultados finales
Estos son los resultados de 100 juegos (se suman puntos):
1. BirdInTheHand: 1017790
2. Balance: 851428
3. SecondBest: 802316
4. Crook: 739080
5. Jim: 723440
6. Flipper: 613290
7. Wheeler: 585516
8. Oracle: 574916
9. SimpleBot: 543665
10. TraderBot: 538160
11. EgoisticalBot: 529567
12. RememberMe: 497513
13. PassiveBot: 494441
14. TheJanitor: 474069
15. GreedyRotation: 447057
16. Devil: 79212
17. Saboteur: 62240
Los resultados individuales de los juegos están disponibles aquí: http://pasted.co/63f1e924 (con monedas iniciales y número de rondas por juego).
Una recompensa de 50 reputaciones se otorga al ganador: Bird In The Hand de Martin Büttner .
Gracias a todos por su participación, nos vemos el próximo KOTH ~
fuente
Respuestas:
Pájaro en la mano, rubí
Si ninguno de nosotros tiene un error en sus programas, el algoritmo principal de esto es muy similar al Oracle de Mathias. Basado en la suposición de que antes de la ronda final no podemos saber con qué monedas terminaremos, evaluamos el conjunto actual de movimientos basándose únicamente en los puntos recibidos de inmediato, ignorando por completo qué tipo de monedas terminaremos con. Como solo hay 14 3 = 2744 conjuntos de movimientos posibles, podemos simularlos fácilmente para determinar cuántos puntos aportarán.
Sin embargo, si un conjunto de movimientos finaliza el juego (ya sea porque reduce el bote global a cero o porque esta es la ronda 50 y somos los últimos en moverse), entonces también tiene en cuenta las monedas que posee al final de el conjunto de movimientos para determinar el valor del conjunto de movimientos. Primero consideré terminar el juego siempre que fuera posible, pero esto resultaría en un movimiento horrible
333
cuando solo quedan 9 monedas en el bote.Si hay varios conjuntos de movimientos que dan el mismo resultado, elegimos uno aleatorio. (Podría cambiar esto para sesgarlo a favor de conjuntos de movimientos que terminen el juego).
fuente
Oracle, Python 3
Actualización: cambió el orden de los diversos intentos para favorecer la pila baja de monedas sobre las rotaciones.
Intenta cada salida posible y mantén la que produzca la cantidad máxima de puntos para este turno.
fuente
deepcopy
complejidad del espacio (por lo tanto, el tiempo [ ]) manteniendo solo vecinos relevantes. Sin embargo, no estoy seguro de cómo impactará las cosas.filter_neighbors
y modificadoinvalid_move
para tener en cuenta las aclaraciones en la pregunta. Sin embargo, no puedo reproducir el error:$ python oracle.py '4;7;2040;8_-28_1_10;9_-43_0_9;2_-10_4_3;6_-24_6_3;0_6_2_12;1_48_3_0;10_21_4_8;5_6_5_1;4_-12_3_7;7_10_1_3;3_1_1_0'
imprimeTTR
Rotación codiciosa, rubí
Esto es bastante similar al enfoque de ArtOfCode, excepto que esto comprueba de qué vecino podemos obtener más puntos, y elige en
C
lugar deF
si terminamos con 3 o más monedas después de la rotación.Después de escribir esto, estoy bastante seguro de que un mejor enfoque sería simplemente elegir con avidez lo mejor de todos los movimientos cada vez, precediendo a la rotación tomando, si es posible (en lugar de apegarse a un fijo "desbloquear, rotar, deshacerse de "patrón sin voltear").
Esto tampoco tiene en cuenta los puntos implícitos representados por las monedas que realmente posee (basado en el supuesto de que el juego durará suficientes rondas que probablemente no terminaré guardando mis monedas de todos modos).
fuente
Flipper, Python 2
Flipper recoge monedas e intenta girar sin voltear a volteado. Flipper no es un jugador inteligente, pero trata de ser una fuerza positiva en el juego.
Flipper solo necesita el
python flipper.py <arg>
para correr.fuente
SimpleBot, Python 3
SimpleBot es, bueno, simple. Ha desarrollado una estrategia y la va a seguir.
Correr:
donde el contenido del
main.py
archivo es:fuente
Balance, Lua
Balance intentará mantener el equilibrio en su token, minimizando la pérdida en caso de que alguien use el
R
yT
acciones contra él. Él piensa que este estilo de vida es el verdadero y debe aplicarse a cualquiera que no mantenga un buen equilibrio de monedas lanzadas / lanzadas, por lo que todos los que estén cerca de él serán castigados tan pronto como pueda hacer que pierdan puntos.Necesita el siguiente comando para ejecutarse:
Donde el archivo balance.lua contiene el siguiente código:
fuente
El conserje, Python 3
Intenta limpiar el desorden que hacen los otros jugadores con todas estas monedas y volver a ponerlas en la piscina.
Intenta devolver todas sus monedas sin voltear, si tiene algunas monedas volteadas, las desplegará y si se deshace de todas sus monedas, obtendrá las de otra persona.
fuente
Crook, R
Correr:
Rscript Crook.R
Básicamente, intercambia sus monedas con sus vecinos solo si el intercambio es desigual a su favor. Si no es posible un intercambio beneficioso, entonces intercambia monedas con la pila global de una manera que mantiene su relación intacta pero genera algunos puntos.
Editar: agregué un poco de profundidad a este bot al hacer que verifique las siguientes y anteriores pilas de 2 y 3 jugadores en lugar de solo la siguiente y verifique si, en general, es beneficioso rotar tantas veces.
2da Edición : Siguiendo la idea de @ MartinBüttner, el bot ahora realiza un "RT" o "TR", si sería más beneficioso para él que para sus vecinos (si no me equivoco al implementarlo :)).
fuente
RTR
para que obtengas el puntaje de sus monedas dos veces.Jim, Ruby
basado en la codiciosa rotación de Martin Büttner .
rotará de una forma u otra, dependiendo de lo que le dará más puntos en comparación con el mejor jugador. Luego, voltea por dinero rápido.
fuente
TraderBot
Este bot intenta rotar siempre que sea el que tome más puntos en esa acción. Si no puede rotar, intenta deshacerte de las monedas no plegadas o toma un poco más para cambiarlas en las siguientes acciones.
import java.util.List;
clase pública TraderBot {
Para ejecutar: simplemente agréguelo a la misma carpeta que los bots predeterminados y luego cree la siguiente clase
Luego agregue esa clase a la
Player[] players
matriz.fuente
Rodador
Wheeler calculó el mejor movimiento posible al rotar las monedas.
fuente
Saboteador, Python 2
La aleatoriedad significa que probablemente no saboteará muy bien, pero luego creo que tendré que esperar hasta el 'final' (cuántos turnos / monedas quedan) y ENTONCES rotar, después de mirar a los jugadores accesibles cercanos para robar ... en realidad, solo hacer una rotación parece realmente pobre, teniendo en cuenta que otras personas también pueden usar rotaciones. No creo que esto funcione muy bien ...
fuente
SecondBest, Python 3
Este programa pasará por todas las combinaciones posibles de 3 movimientos y elegirá la segunda mejor.
Porque si tienes el movimiento perfecto, probablemente sea una trampa.
Editar: entrada eliminada comentada
Editar: el código estaba imprimiendo un movimiento legal aleatorio. Ahora debería devolver el segundo mejor resultado.
fuente
Bot del diablo
Aunque su producción es solo la mitad del número del diablo, los resultados deberían ser bastante desastrosos. Tomando 9 monedas cada turno, eventualmente agota la pila de monedas. Dado que este bot nunca arroja ninguna de las monedas que toma, es extremadamente malo para cualquier otra persona sentada junto a él cuando hay una rotación (-9 puntos por cada turno tomado por este bot).
Mando:
python3 devil.py
Espero hacer algunos bots reales más adelante.
fuente
Recuérdame, Python 3
Este programa contiene una cantidad significativa de datos incorporados de una prueba contra el bot fijo SecondBest.
se debe aprender acerca de lo que se mueve son los mejores para usar, pero no utilizar la entrada de otros jugadores.
Editar: se eliminó el cálculo de puntos innecesarios
Editar: entrada de jugador sin comentarios
fuente