Cara de póquer
Introducción
Leo disfruta jugar al póker, pero su trabajo en Tech Inc. es demasiado exigente para que aprenda a jugar bien. Leo, siendo un informático, no se desanima. Decide dedicar más tiempo del necesario para aprender póker y usarlo para escribir un bot de póker que lo ayude a jugar mejor. Pero ahora Leo tiene un problema: para entender cómo jugar un poco mejor, Leo necesita observar múltiples juegos de múltiples "personas", pero las "personas" necesitan diferentes estilos de juego para mejorar la calidad y la realidad del juego.
El reto
Leo recuerda que en realidad hay un sitio web dedicado a los desafíos de programación, ¡y está solicitando su ayuda! Su trabajo es escribir un programa que juegue "Pokerface", una versión modificada del póker de 5 cartas. El programa tomará la entrada como una mano de 5 cartas en cualquier formato que desee, después de lo cual el programa generará:
- Exactamente (distingue entre mayúsculas y minúsculas) "verdadero" "1" o "t" si el jugador desea intercambiar cartas, de lo contrario, cualquier otra salida no vacía.
- Si es verdadero, una lista de índices de cartas y / o nombres de cartas que el jugador desea intercambiar.
- Un solo número entre 0 y 3, que especifica cuántas cartas adicionales quiere el jugador.
- Imprime la mano que el jugador desea usar.
(Ver formato a continuación)
Reglas de Pokerface
- Dado que pokerface es un juego de aventuras basado en texto, las cartas deben presentarse de manera consistente. Las tarjetas están representadas por dos códigos de personaje, el primer personaje es el palo y el segundo es el nombre de la tarjeta.
- Tarjetas:
- 2-9 = 2-9
- 10 = T
- Jack = J
- Reina = Q
- Rey = K
- As = A
- Trajes:
- Picas = S
- Clubes = C
- Corazones = H
- Diamante = D
- Tarjetas:
Entonces el as de espadas sería SA, el 10 de corazones es HT, el 4to de diamantes es D4, etc.
- Una sola ronda de Pokerface consta de cuatro pasos:
- La baraja se reorganiza y se reparte una mano de cinco cartas a cada jugador.
- Cada jugador tiene la oportunidad de intercambiar tantas cartas como quiera.
- Cada jugador tiene la oportunidad de ganar hasta tres cartas más.
- Cada jugador debe revelar su mejor mano.
- La mejor mano gana y gana un punto para ese jugador. En caso de empate, ambos jugadores obtienen un punto.
- En un solo juego, se juegan diez rondas y el jugador con más puntos gana y gana un solo "punto de victoria". En caso de empate, ambos jugadores ganan un punto de victoria.
- Leo realmente no tiene una gran cantidad de dinero, por lo que su bot puede suponer que este es un mundo perfecto sin apuestas.
Manos
- Las manos tienen exactamente 5 cartas de longitud (entrada inicial y salida final).
- Las manos se clasifican de acuerdo con las reglas descritas aquí .
De entrada y salida
- Leo solo conoce Java, por lo que su programa debe ser ejecutable a través de la API de proceso (línea de comando) y usar STDIN y STDOUT para entrada y salida, respectivamente.
- Para cada paso de entrada y salida detallado anteriormente, la entrada y la salida deben existir en una línea.
- Debe haber al menos una nueva línea posterior después de la salida final. (Esto se debe a la forma en que se lee la entrada de STDIN)
- No se permiten entradas / salidas extrañas, aparte de los espacios iniciales y finales. El analizador simplemente no entiende cosas como
final_hand=...
odraw 0
. - Al dibujar, la salida es un número entero único, cuando el intercambio de salida es una lista de enteros y / o cartas definidas a continuación, y cuando se reparte la mano original, la salida es una lista de cartas definidas a continuación.
- Todos los números de entrada / salida deben ser enteros positivos en la base 10.
- Puede definir el formato para la entrada de la tarjeta (consulte el formato de publicación a continuación).
- Verdadero se define como exactamente "verdadero", "1" o "t" y falso es cualquier otro valor no vacío.
- Durante el paso de intercambio:
- Los índices de las tarjetas se deben generar con al menos un espacio entre ellos (p
3 4 0
. Ej. ) - Los nombres de las tarjetas deben aparecer con al menos un espacio entre ellos (p
H4 S8
. Ej. ) - Los nombres e índices de las tarjetas pueden mezclarse en la salida (p
0 H7 3 D3
. Ej. ) - Se permiten espacios finales y principales.
- La entrada como resultado de la salida del reproductor anterior se formateará según lo especificado por el
bot.jlsc
archivo, en el mismo orden en que se solicitó
- Los índices de las tarjetas se deben generar con al menos un espacio entre ellos (p
- El número de cartas que un jugador quiere agregar a su mano puede tener espacios iniciales y finales.
- Las manos deben salir con al menos un espacio entre ellas (por ejemplo
H4 D5 CA
), se permiten espacios finales y espacios iniciales. - No es necesario que las manos salgan en el orden correcto (por ejemplo,
H4 D4 C4 DA SA
yH4 DA D4 SA C4
ambas representan 4, 4, 4, As, As, que es una casa llena). - Si desea construir una estrategia analizando las manos de los oponentes, puede almacenar datos en un
<botname>/data
directorio.- Después de que los bots de la competencia hayan mostrado sus manos, se escribirán en cada directorio de datos de bots, en hands.txt, con cada mano en una nueva línea (separada por \ n). El archivo se codificará en US_ASCII.
- Después de que su bot solicite nuevas tarjetas o tarjetas de intercambio, las tarjetas se ingresarán según el formato que especifique en el
bot.jlsc
archivo.
Formato de publicación
- Cada publicación debe incluir dos cosas:
- El código fuente de su bot, o un enlace a un repositorio público.
- Un archivo zip que contiene:
- La versión compilada / ejecutable de su bot (si el archivo es un archivo .exe u otro archivo no descompilable, solo incluya instrucciones de compilación en su publicación).
- Un
bot.jlsc
archivo, ver más abajo (nota al margen: la extensión .jlsc se debe solo a un proyecto paralelo mío, un formato de configuración. El archivo a continuación coincide con la sintaxis adecuada, así que no se preocupe).
- El archivo .zip debe tener el mismo nombre que su bot.
- Si no tiene acceso a Windows o alguna otra utilidad de compresión, o no puede hacer un .zip por alguna razón, simplemente incluya el texto del archivo bot.jlsc en su publicación
archivo bot.jlsc:
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
Dónde:
- "cmd" es el comando de línea de comando de Windows para ejecutar su bot. Tenga en cuenta que su bot estará en el directorio
<botname>
, así que ajuste el comando en consecuencia. - "nombre" es el nombre de tu bot.
- "link" es el enlace a tu respuesta, tendrás que editarlo después de publicarlo.
- "input_hand" es cómo desea que se formatee la operación original (con $ {#} representando las tarjetas 0-4).
- "input_1" es cómo desea que se formatee la entrada de una tarjeta adicional.
- "input_2" es cómo desea que se formatee la entrada de dos tarjetas adicionales.
- "input_3" es cómo desea que se formatee la entrada de tres tarjetas adicionales.
- "input_4" es cómo desea que se formatee la entrada de cuatro tarjetas adicionales.
Detalles específicos
- Estas lagunas no están permitidas (ver 'trampas comunes')
- No puede escribir un bot, siempre saldrá la mejor mano posible, siempre, dentro del conjunto de reglas. (es decir, no hay bots de fuerza bruta de larga duración, nada debería ser tan "bueno" como LeoBot)
- Su bot debe ejecutarse en ~ 100 ms o menos (Lenient en este punto, máximo de ~ 1 segundo)
- Cualquier salida del bot después de su mano elegida será ignorada.
- Las lagunas estándar no están permitidas.
- Sí, sé que Linux es mejor, pero tengo una PC con Windows, así que asegúrese de que la versión compilada / ejecutable de su programa se pueda ejecutar desde la línea de comandos de Windows.
- Ya tengo Python y Java instalados en mi computadora, pero estoy dispuesto a actualizar a nuevas versiones e instalar otros entornos, así que especifique qué tipo de entorno requiere su programa.
- No puede escribir un bot que haga lo mismo que otro bot en todos los casos. Los bots de spam están permitidos, pero desaconsejados.
- Tu bot solo puede usar cartas que tenga. Las cartas perdidas a través del intercambio o no tratadas para empezar son salidas inválidas en la mano final.
- La entrada y salida solo pueden contener caracteres ASCII.
Torneos
- Los torneos se ejecutarán cuando tenga el tiempo (mi agenda está casi tan llena como la de Leo, así que esto puede ser un poco infrecuente. Disculpe las molestias).
- Los bots se enfrentarán entre sí en juegos de 4 personas, y habrá un juego para cada posible subconjunto de bots (es decir, muchos juegos).
- Este proceso se repetirá cinco veces.
- Debido a la forma en que el manejador del torneo forma los grupos de bots, se agregarán hasta tres bots de relleno para que el número de bots sea divisible por 4. Estos bots simplemente devolverán la mano con la que se repartieron originalmente.
- Después de cada ronda y juego, los puntajes de los bots se calcularán en función de la cantidad de juegos que ganaron.
- Múltiples bots pueden compartir una posición (empates para el primer ganado por primera publicación).
- Después de que termine un torneo, los puntajes se agregarán al final de esta publicación.
Puntuación
Reglas normales de KoTH. Los bots que ganan más juegos ganan el desafío.
LeoBot
El bot de Leo es bastante inteligente. No intercambia ninguna carta, eso es demasiado difícil, pero solicita la cantidad máxima de cartas adicionales, y determina la mejor mano posible que puede hacer, y juega esa mano. La lógica principal de leobot está a continuación.
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
Tenga en cuenta que si LeoBot gana constantemente los torneos, y hay una buena cantidad de entradas, dejaré de incluirlo en la carrera.
Links importantes
Descargo de responsabilidad
Leo y Tech Inc. son elementos de la historia y cualquier parecido con empresas o personas de la vida real es puramente involuntario. (Sin embargo, cuando la 'situación' de Leo agrega o resta condiciones a la pregunta, en realidad son parte de la pregunta ...)
"f"q+
cumple con los requisitos mínimos. Si hay 10 personas en competencia, esto probablemente supere a todas las entradas no tontas (la entrada no tonta probablemente tenga> 75 caracteres, 5 * 10 (puntaje de bot tonto, último) = 50 <75 (puntaje de bot inteligente muy pequeño (primero))). Por lo tanto, probablemente deberías eliminar codegolf de este desafío