Calculadora de póquer

¿Cómo haría uno para escribir una calculadora de póquer?

Conecte las manos iniciales 1-X y luego devuelva el porcentaje de ganancias.

Respuestas (2)

No estoy familiarizado con .NET y esas cosas. Probablemente debería mencionar que yo mismo no soy un programador profesional. Pero seguramente hay muchas bibliotecas geniales en C puro. Utilizando C++ y CPU i5, personalmente obtengo alrededor de 4,4 millones de manos/s en Monte Carlo con 3 jugadores y 2,3 millones con 6 jugadores. Pero eso es solo Monte-Carlo sin optimizar. La enumeración de fuerza bruta va a una velocidad de 190 millones de manos/seg. Entonces sus 205,476,480 tableros no me dan mucho miedo. Este número es realmente incorrecto: debería haberlo calculado como combin(48,5) = 1,712,304. A 190M/s eso es un instante. Así que puedo suponer que el cuello de botella es el algoritmo de evaluación manual.

Aquí tienes:

  1. MUCHO código sobre evaluación de manos presentado en el artículo "El resumen del gran evaluador de manos de póquer": XPokerEval . Te recomendaría pokersource ya que ha sido portado a todo tipo de idiomas. El evaluador TwoPlusTwo muestra un excelente punto de referencia de enumeración, pero falla en Monte Carlo debido a errores de caché.

  2. De vuelta al buen Holdem Showdown de C. Steve Brecher. Muy buena pieza. Me lo pasé muy bien diseccionándolo y optimizándolo. Búscalo en Google, solo puedo publicar 1 enlace :(

  3. Ace_eval de Ashley. Es un programa de golf con un tamaño inferior a 600 bytes y sin tablas de búsqueda. La versión sin golf funciona bastante rápido. Realmente me gustó su formato de valor de mano, así que lo uso yo mismo.

  4. Estufa de póquer de Andrew Prock. Este me hizo querer dejar de intentar programar. Utiliza un algoritmo de enumeración altamente optimizado. Trillones de manos/segundo no es algo fuera de lo común. Busque las publicaciones de adrian20xx en twoplustwo y PokerAI para obtener una explicación detallada.

En lo que respecta a Montecarlo, noté que el cuello de botella también es el barajado de la cubierta. He llegado con este algoritmo:

#define PUT_CARD_TO_BACK(X) {tmp=deck[N];deck[N--]=deck[X];deck[X]=tmp;} 
//put card in the back of the deck    
void shuffleDeal (int myCard1,int myCard2, int nPlayers, int*deck){
    int N=51,i,k;
    PUT_CARD_TO_BACK(myCard1);
    PUT_CARD_TO_BACK(myCard2);
    for (i=0;i<(nPlayers*2+5);i++){
        k=rand()%(N+1);
        PUT_CARD_TO_BACK(k);
    }
}

Aquí tengo que generar solo la cantidad necesaria de números aleatorios, las cartas dadas y las cartas elegidas al azar se colocan en la parte posterior de la baraja en el orden especificado y puedo usarlas como cartas de mesa o de mano como esta:

#define BOARD deck[45],deck[46],deck[47],deck[48],deck[49]
#define HERO deck[50],deck[51]
#define OPP1 deck[43],deck[44]

En caso de que sea necesario evaluar un pequeño número de manos (menos de 100M), creo que debería usar una enumeración exhaustiva. De lo contrario, 100,000 iteraciones de Monte Carlo funcionan bien. La salida de un programa depende completamente de usted dependiendo de lo que esté tratando de analizar. Espero haber ayudado de alguna manera :)

Gracias. Obtengo una desviación en 100,000 y ni siquiera desaparece en 1 millón. Creo que tienes razón sobre combin(48,5). Necesito pensar en cómo enumerarlos. Y no quiero usar una biblioteca o simulaciones previas a la ejecución. Quiero escribir una calculadora de póquer independiente.
Todas las combinaciones se enumeran así for(c1 = 0; c1 < 52; c1++) { if (CardsExtracted[c1]) continue; for(c2 = c1 + 1; c2 < 52; c2++) { if (CardsExtracted[c2]) continue; for(c3 = c2 + 1; c3 < 52; c3++) { if (CardsExtracted[c3]) continue; for(c4 = c3 + 1; c4 < 52; c4++) { if (CardsExtracted[c4]) continue; for(c5 = c4 + 1; c5 < 52; c5++) { if (CardsExtracted[c5]) continue;Esa es una manera ingenua. La opción es optimizarlo de forma similar a pokerstove, pero no sé si vale la pena el esfuerzo.
Vaya, ¡alguien usó mi evaluador! Me alegro de que te haya gustado.

Características importantes para mí:

  • total y porcentaje en empate de victorias y derrotas
  • proporción de probabilidades de manos
    dan un empate 1/2 victoria
  • descomponer en todas las manos el
    porcentaje de escalera de color hasta el pct de la carta más alta lo
    necesito para la depuración de todos modos

  • se desglosa aún más en todas las manos
    cuando gana / empata, ¿lo hizo como qué mano
    ?

  • Opción de correr cara a cara contra cada uno
    , así que en lugar de correr como JJ contra AA, KK, AK, hazlo por separado en uno
    (los tableros son diferentes: JJ versus AA no elimina KK y AK)

Diseño:

  • las propiedades de clase de carta
    rango, palo y out
    usar una propiedad booleana para out (en una mano) fue mucho más conveniente que eliminar las cartas del mazo que estaban fuera,
    así que al principio simplemente cree un mazo de 52 y utilícelo para básicamente todo.

  • propiedades de clase de jugador
    victorias, empates, pérdidas
    de esos tres todo lo demás se calcula

  • el símbolo Unicode para un club se parecía mucho a una espada, así que usé un trébol

  • ordenar las manos (puntuación de la mano) le dio a la escalera de color un valor de 8 hasta 0 para la mano alta
    le dio al as un valor de 14 hasta dos un valor de 2
    en el caso de una escalera agregue el as con un valor de 1
    para los pateadores incluir la mano hecha como parte del inicio de la
    mano pateadora y pateadora son solo dos dígitos
    mano * 100000000 + pateadora.0 * 1000000 + pateadora.1 * 10000 + pateadora.2 * 100 + pateadora.3
    por lo que el as sobre el bote rey es
    614130000
    para color y carta alta, en realidad podría entrar en 5 pateadores, pero dejo que sea un empate

  • barajar
    en lugar de barajar todo el mazo, solo toma la cantidad requerida de cartas al azar
    . Acabo de usar .NET al azar.

  • evalúe
    el barajado del tablero y luego un jugador a la vez obtenga el orden (puntuación de la mano)
    registre la victoria, el empate y la derrota del jugador

Esto me tomó alrededor de 20 horas, pero soy un desarrollador
. Me cambié a una nueva versión de .NET y Visual Studio y quería un proyecto para practicar.

En una PC de gama media obtengo unas 10.000 combinaciones aleatorias en 20 segundos. Un 100.000 tarda unos 3 minutos.

Puede obtener hasta un 10 % de error con solo 10 000 barajadas, pero solo con la planificación puede ser suficiente. En el % más alto, el error es menor. El % más pequeño como 2 7 fuera de la suite es un error mayor, pero eso es lo que normalmente no le interesa.

En una máquina más rápida con 8 núcleos podría procesar 8 manos en paralelo, por lo que obtendría 100,000 hasta el rango de 10 segundos.

Supongo que las calculadoras en línea que son instantáneas procesan todas las combinaciones como 20 millones de barajadas cada una y las almacenan. No estoy muy seguro de cómo lo hacen.

Porque la velocidad podría dejar de calcular una mano cuando sabes que está muerta. Pero eso sería mucho más lógico y quería el detalle en todas las manos.

En el aprendizaje automático, puedes hacer algo llamado poda, pero no soy lo suficientemente fuerte para eso y nuevamente quería los detalles.

4 manos no es el doble de largo que 2 como el mismo número de barajas. Y obtienes una mayor precisión para el mismo número de barajes, ya que hay menos tableros posibles.

Con el enfoque de fuerza bruta, ejecutar todo el tablero no es práctico. Con dos manos hay 48*47*46*45*44 tableros = 205.476.480. Incluso en 100.000 en 10 segundos que es como 6 horas.

Con 10 millones, un método Monte Carlo será muy preciso.

ingrese la descripción de la imagen aquí