JUGADOR VIRTUAL DE PÓKER TEXAS HOLD’EM
Alberto Álvarez Polegre Lucas Bernalte Pérez David Díaz Chinea
Ingeniería de Telecomunicación Ingeniería de Telecomunicación Ingeniería de Telecomunicación
Universidad Carlos III de Madrid Universidad Carlos III de Madrid Universidad Carlos III de Madrid
100085949@[Link] 100294293@[Link] 100294308@[Link]
RESUMEN la grande). La primera de estas tres rondas se conoce como Flop y
El póquer es un juego de cartas de los llamados de "apuestas", en en ella se mostrarán en la mesa tres cartas sacadas del montón de
los que los jugadores, con todas o parte de sus cartas ocultas, cartas que no se ha repartido. Posteriormente pasamos al Turn
hacen apuestas sobre una puja inicial, recayendo la suma total de donde solo se enseña una carta conocida como Cuarta Calle. Por
las apuestas en el jugador o jugadores con la mejor combinación último, se gira una última carta, Quinta Calle, en la ronda llamada
de cartas. River, formando las cinco Cartas Comunes. Con tres de estas
cartas mostradas combinadas con las dos obtenidas al principio de
Palabras Clave la partida el jugador deberá formar su mano de cartas con las que
Póker, Texas Hold „em, probabilidad, jugada, mano, estrategia. intentar ganar la partida. Así pues a partir de aquí se presentan las
manos posibles que puede tener cada jugador, ordenadas de mayor
1. INTRODUCCIÓN a menor valor.
El Texas Hold‟em es una variación del conocido juego de cartas
conocido como Póker. En este juego se utilizan las 52 cartas de la Escalera Real de Color
baraja inglesa, las cuales tienen los valores, de menor a mayor, 2,
3, 4, 5, 6, 7, 8, 9, 10, J, Q, K y A, en las cuatro combinaciones de
palos diferentes: trébol , corazones , picas , y diamantes .
En el póker se realizan una serie de apuestas en las que el jugador
que obtenga la mejor combinación de cartas será el ganador de
esta, llevándose el bote acumulado que será la suma de todo lo
apostado por el resto de jugadores. Además el jugador también
La mejor jugada del póker. Comprende las cartas 10, J, Q, K y A
puede obtener el premio si el resto de jugadores de la mesa se ha
del mismo palo.
retirado de la partida. Cada jugador será eliminado si pierde todas
las fichas que ha apostado.
Escalera de Color
2. REGLAMENTO
Esta variación se caracteriza sobre todo porque cada jugador
obtiene dos cartas boca abajo al inicio de la partida, que serán
siempre fijas. Dichas cartas serán reveladas al final de la ronda
por parte de los jugadores que queden al cerrar las apuestas, en
caso de que todos se retiren si el que no lo haga lo desea, o si los
apostantes que siguen en la partida apuestan todas sus fichas Cinco cartas de orden consecutivo del mismo palo. Cuanto mayor
restantes (jugada conocida como All-In). sea la carta más alta de la escalera, mejor es el ranking de la
mano. En este ejemplo la carta más alta es el 10; vencería a una
A partir de aquí cada jugador comienza apostando a continuación escalera de color con un 9 de carta más alta.
de la ciega grande (jugador que parte obligatoriamente con la
apuesta mínima, de modo que el jugador solo puede igualarla o
aumentarla si no quiere retirarse) siguiendo las agujas del reloj. A
Póker
esta ronda se le denomina, en términos del juego, Pre-Flop, y si
quedan más de dos jugadores tras esta se seguirá apostando.
Posteriormente se inicia una fase de tres rondas conocida como
Post-Flop, cada una con sus respectivas rondas de apuestas y ,en
cuanto a las mismas, a partir de aquí el jugador puede pasar (no
apostar nada) solo si los anteriores han pasado o es él el primero;
retirarse de la partida, igualar la apuesta o subirla. En este caso la Cuatro cartas del mismo valor. Cuanto más alto es el valor de
ronda la iniciará el jugador a la izquierda de la ciega grande, estas cuatro cartas, más alto es el ranking de la mano. En caso de
conocido como ciega pequeña (apuesta inicialmente la mitad que empate gana la mano cuya quinta carta sea más alta.
Una doble pareja está formada por dos cartas del mismo valor en
combinación con otras dos cartas también de un mismo valor,
Full pero diferente al valor de las dos primeras. Cuando dos manos
muestran doble pareja, gana la mano cuya pareja es más alta.
Como siempre, en caso de empate decide la carta más alta.
Pareja
Esta jugada reúne 3 cartas de un valor y 2 de otro. Cuando se
comparan dos fulls, gana el que tiene el valor de las tres cartas
más alto. Así pues, un full 7-7-7-2-2 supera a un full 5-5-5-A-A.
En caso de que los tríos sean del mismo valor en dos manos, gana
la mano que tenga la pareja de cartas restante más alta, con lo que Dos cartas del mismo valor. Cuanto más alto es el valor de la
por ejemplo 7-7-7-A-A superaría a 7-7-7-K-K. pareja, más alto es su ranking. En caso de igualdad, se recurre a la
carta más alta.
Color
Carta Más Alta
Cuando ningún jugador consigue formar una de las jugadas arriba
expuestas, gana la mano aquel que tiene la carta más alta. Y en
caso de empate, se usa la siguiente carta más alta.
El color lo forman cinco cartas no consecutivas del mismo palo. 3. OBJETIVO Y PRESENTACIÓN DEL
Gana el desempate entre dos colores aquel que tenga la carta más MODELO
alta.
3.1 Introducción
Escalera Primero, decir que un modelo que simule el comportamiento de
un humano jugando al póker, es casi inviable, por la cantidad de
factores que influyen, tanto dentro del juego como factores
externos.
El modelo que se presenta aquí, y la inmensa mayoría de modelos
existentes son modelos simplificados, que sólo tienen en cuenta
factores internos del juego y siempre será una máquina, luego
Para la escalera se precisan cinco cartas de valor consecutivo. siempre pensará “con la cabeza fría” y elegirá la mejor jugada en
Entre dos escaleras gana la que sea más alta. Por otra parte, el As cada momento.
puede usarse para formar la escalera A-K-Q-J-10, que sería una A corto plazo puede no resultar victorioso, pero este modelo sigue
Escalera Real, y también la escalera 5-4-3-2-A. un criterio de probabilidades, por el cual está comprobado que a
[Link]. xx medio/largo plazo se obtienen ganancias.
Trío
Nuestro modelo empezará siguiendo una determinada estrategia, y
podrá ir cambiando a lo largo de la partida, dependiendo del
comportamiento del rival.
3.2 Modelos de jugador de Póker
Podemos analizar que básicamente hay distintos tipos
Lo componen tres cartas del mismo valor. Entre dos tríos gana el
de jugadores de Póker. Encontramos que podemos agrupar a los
que está formado por cartas más altas. Si ambos tríos están
diferentes tipos de jugadores en cuatro categorías, de acuerdo a
formados por cartas del mismo valor, decide el desempate la carta
dos criterios: tight y loose y por otro aggressive y passive.
más alta de las dos restantes de que consta la mano, y si esas dos
cartas fueran iguales, se compararían las quintas cartas de cada Así podemos empezar por explicar que significa tight y loose y
mano. aggressive y passive.
De acuerdo con la cantidad de manos de Póker podemos
Doble Pareja clasificar a un jugador como tight o loose. Un jugador loose juega
muchas y diferentes manos. En cambio uno tight juega pocas
manos y además con buenas cartas, es decir que tiene muchas
posibilidades de ganar.
Asimismo, encontramos los jugadores pasivos y agresivos. En
general el jugador pasivo sigue las apuestas del otro de la mesa de
Póker, en cambio el agresivo sube con frecuencia la apuesta y 3.4.2 Fuerza de la mano
toma la iniciativa. La fuerza de la mano es la probabilidad que tiene ésta de ganar la
jugada sin saber qué cartas tienen nuestros adversarios. La fuerza
de la mano inicial (en el pre-flop) se basa en la tabla del punto 3.3.
3.3 Fuerza de la mano inicial A partir de aquí se calculará de la siguiente manera:
-En el Flop: ODDS*4 + 1 (%)
-En el Turn: ODDS*2 - 1 (%)
-En el River: ODDS (%)
*ODDS: Las ODDS son las cartas que faltan por salir para tener la
mano ganadora a la que aspira el jugador.
3.4.3 Ratio de ganancia
El ratio de ganancia es la cantidad de fichas que ganarás (en %) en
función de la apuesta que se haga y la cantidad de fichas en el
bote. Por ejemplo, si la apuesta es 20 fichas y hay 40 fichas en el
bote, entonces el ratio de ganancia será 20/(20+40) = 0.333.
3.4.4 Ratio de devolución
El ratio de devolución es (en media) la proporción en que se
multiplicará la apuesta si se continúa jugando esa mano. Se
calcula como el cociente entre la fuerza de la mano y el ratio de
ganancia. Normalmente, seguiremos jugando esa mano si este
parámetro es igual o superior a 1 (como se mostrará en el punto
4).
3.4.5 Ratio de subida
El ratio de subida es la cantidad de fichas que se apostarán en caso
de que se decida ver y subir. Se calcula teniendo en cuenta los 3
parámetros anteriores de la siguiente forma:
3.4.6 Probabilidad total
La probabilidad total es la suma de la fuerza de la mano con un
Random de C++. Esta parámetro ha de ser igual o superior a la
probabilidad umbral para jugar la mano.
3.4.7 Random
Para simular de mejor manera el jugador virtual, utilizaremos la
función de C++ Random y así poder hacer un jugador más
imprevisible. En todas las tomas de decisiones utilizaremos esta
función.
4. DESARROLLO DEL JUEGO
3.4 Parámetros en los que basar las
4.1 Pre-Flop
decisiones. El jugador comprobará si es ciega grande o pequeña y pondrá la
En esta sección explicares los parámetros en los que se basa el cantidad de fichas necesarias que estas indiquen.
jugador para tomar una decisión u otra.
if (ciega_grande == true)
3.4.1 Probabilidad umbral Poner_ciega_grande();
La probabilidad umbral es la probabilidad mínima de ganar que
debe tener la mano para jugar. Está es diferente dependiendo la if (ciega_pequeña == true)
cantidad de jugadores en mesa. Por debajo se este umbral, se Poner_ciega_pequeña();
considera que la mano tiene muy pocas probabilidades de ganar y
se supone una pérdida innecesaria de fichas. A lo largo de la
partida, dependiendo del tipo de jugadores a los que nos Luego, se reparten dos cartas a cada jugador, y en ese momento
enfrentemos, esta probabilidad umbral variará a más o menos. calculamos la probabilidad que tiene nuestra mano de ganar
(fuerza de la mano), dependiendo del número de jugadores, de
nuestra posición en la mesa y de si hemos sido ciega (grande o
pequeña) o no.
Diagrama de las fases del juego:
if (ciega_grande == true || ciega_pequeña == true)
{
Poner ciega
probabilidad_total = Fuerza_mano(mano_inicial) +
Random(0,0.2) - Random(0,0.2) + 0.05; Irse
else
probabilidad_total = Fuerza_mano(mano_incial) + Calcular FM Igualar
Random(0,0.2) - Random(0,0.2);
}
Subir
Mientras las apuestas no hayan sido igualadas, calcularemos el
ratio de ganancia y el ratio de devolución para realizar la jugada.
Teniendo en cuenta estos parámetros y los factores Random
jugaremos (función Jugar) de un modo u otro (Irse, Igualar o Flop
Subir). Irse
A lo largo de las manos, se analizará a los adversarios y teniendo
en cuenta la variables para este análisis jugaremos siguiendo una
estrategia u otra (definidas en el punto 3.2). Calcular FM Igualar
4.2 Flop
Con esto llegamos al Flop, donde se reparten tres cartas Subir
comunitarias. A partir de este momento nuestra mano pasará a
tener 5 cartas, y la probabilidad para calcular la fuerza de la mano
se calculará por un método señalado anteriormente. Hay que
señalar que este método no es del todo exacto, pero nos da una
muy buena aproximación de nuestras probabilidades de ganar la Turn
mano.
Irse
Como ya se hiciera en el Pre-Flop, calcularemos de nuevo los
parámetros básicos para la toma de decisiones y en función de
ellos jugaremos (función Jugar). Calcular FM Igualar
4.3 Turn
Igual que en las fases anteriores, realizaremos un tipo de jugada u
otra según los parámetros básicos. Subir
4.4 River
En esta última fase se decidirá quién gana finalmente esa mano
después de las apuestas. River
Irse
Como añadido, el jugador hará un All in (apostarlo todo) si sus
fichas actuales son diez veces menos que sus fichas iniciales para
intentar salvar la partida (o perder inmediatamente). Calcular FM Igualar
Subir
*FM: Fuerza de la mano
Subir(ratio_subida);
}
5. TOMA DE DECISIONES (función Jugar)
En el código se ha implementado una función que decidirá cómo
jugar teniendo en cuenta el ratio de devolución.
5.4 Ratio de devolución superior a 1.3
Después de calcular este parámetros, se entrará en una serie de En cuanto nuestro ratio de devolución sea superior a 1.3
condiciones para saber si ver la apuesta, subirla (o hacer un farol) significará que tenemos una mano difícilmente de ganar. Para este
o irse. caso igualaremos con un 30% y subiremos con un 70%. Tampoco
nos iremos en ningún caso.
5.1 Ratio de devolución inferior a 0.8
Este caso se considera una mano realmente mala, por lo que con
el 95% de probabilidad el jugador se irá, con un 5% subirá la else
apuesta (farol) y en ningún caso igualará.
{
if (aleatoriedad > 0.3)
if (ratio_devolucion < 0.8)
Subir(ratio_subida);
{
if (aleatoriedad <= 0.3)
if (aleatoriedad > 0.05)
Igualar();
Irse();
}
if (aleatoriedad <= 0.05)
Subir(ratio_subida);
El hecho de tomar una decisión u otra dependerá del factor de
} aleatoriedad que nos brinda la función Random de C++. Cuánto
apostar en caso de subida lo determinará el ratio de subirá que se
calcula con la fórmula vista en el punto 3.4.5.
5.2 Ratio de devolución inferior a 1 En cuanto se igualen las apuesta de resolverá la jugada y se verá
En este caso nuestra mano seguirá siendo bastante mala, por lo qué jugador gana ese mano.
que lo más lógico sería irse. No obstante, ha mejorado con
respecto al caso anterior conque nuestras probabilidades
cambiarán. Con un 80% de probabilidad nos iremos, subiremos
con un 15% (farol) y tan solo con un 5% igualaremos la apuesta.
Diagrama del ratio de devolución:
if (ratio_devolucion < 1)
Si
{ Irse (95%)
if (aleatoriedad > 0.15)
Irse();
if (aleatoriedad <= 0.15 && 0.05 < aleatoriedad) RD < 0.8 Igualar (0%)
Subir(ratio_subida);
Subir (5%)
if (aleatoriedad <= 0.05)
Igualar();
}
Si
Irse (80%)
5.3 Ratio de devolución inferior a 1.3
En este punto nuestra mano ya se considerará buena y tendremos
opciones reales de hacernos con el boto final. Así que en este caso RD < 1 Igualar (5%)
igualaremos la apuesta con un 60% de probabilidad y subiremos
con un 40%. En ningún caso nos iremos.
Subir (15%)
if (ratio_devolicion < 1.3)
{
if (aleatoriedad > 0.4)
Igualar();
if (aleatoriedad <= 0.4)
7. BIBLIOGRAFÍA
Si [1] Wikipedia, La Enciclopedia Libre, [Link]
Irse (0%) [2] Cowboy Programming, Programming Poker AI
[3] Reglas del Póker, Tipos de jugaroes,
[Link]/Hay-diferentes-tipos-de-jugadores-
RD < 1.3 Igualar (60%) de-poker
[4] Apuntes de la asignatura Inteligencia en Redes de
Subir (40%) Comunicación, Universidad Carlos III de Madrid
[5] Probabilidades Póker, [Link]
[6] World Series of Poker: Tournoment of Championship,
vídeojuego PlayStation 2
[7] Poker Stars, [Link]
Si
Irse (0%) 8. ANEXO. PSEUDO CÓDIGO EN C++
// Variables
RD > 1.3 Igualar (30%)
int numero_jugadores,
probabilidad_umbral, probabilidad_total,
Subir (70%) aletoriedad;
int fichas_iniciales,
fichas_disponibles, bote, apuesta,
ratio_devolucion, ratio_subida;
*RR: Ratio de devolución bool ciega_grande, ciega_pequeña,
apuesta_igualada, hablo, perder;
char mano_inicial [2],
6. CONCLUSIONES cartas_comunitarias [5];
El juego está basado en la minimización del factor suerte, luego // Funciones (sólo se define Jugar())
sólo sería rentable tras un número bastante grande de manos. Y void Poner_ciega_grande(void);
todo esto teniendo en cuenta sólo factores del juego, aunque no se void Poner_ciega_pequeña(void);
hayan contemplado todos (sería demasiado trabajoso y casi
void Igualar(void);
inviable).
void Irse(void);
Si la máquina se enfrentara a un jugador principiante, lo más void Subir(int);
probable es que gane, puesto que todas las probabilidades usadas, void All_in(void);
fórmulas y estrategias son reales. Está comprobado que si se juega int Fuerza_mano(char);
de esa forma se obtienen beneficios a largo plazo. Esto, sumado a
que una máquina siempre piensa fríamente y que siempre va a
int Ratio_ganancia(int, int);
elegir la que cree que es su mejor opción, la hace un rival muy bool Jugar(int, int, int, int);
difícil de batir. bool Resolucion_jugada(void);
Por otro lado, si tenemos el juego muy estudiado y sabemos cuál
es la mejor opción, podríamos predecir el comportamiento del
void main(void)
jugador virtual. {
// Cálculo de probabilidad umbral
Cabe mencionar, en cuanto al tema de poker y la inteligencia
suponiendo un máximo de cuatro jugadores
artificial, el ordenador Polaris, que se usó como experimento,
switch (numero_jugadores)
contra Phil Laak y Ali Eslami, dos jugadores de póquer de Los
Ángeles clasificados entre los mejores del mundo. Aunqué ganó y {
empató las 2 primeras partidas (de 500 manos cada una), al final case 2:
el resultado se decantó para el lado humano. probabilidad_umbral = 0.58;
case 3:
Todo esto demuestra que a pesar de los años de estudio de la
inteligencia artificial, todavía estamos en una constante evolución probabilidad_umbral = 0.42;
y nos queda mucho camino por recorrer. case 4:
probabilidad_umbral = 0.32;
}
// Inicio de la partida Fuerza_mano, ratio_devolucion,
while (1) aletoriedad);
{ }
// Se ponen las ciegas }
if (ciega_grande == true)
Poner_ciega_grande(); // Turn (cuatro cartas comunitarias)
if (ciega_pequeña == true) probabilidad_total =
Poner_ciega_pequeña(); Fuerza_mano(mano_inicial,
cartas_comunitarias)
// Se reparte la mano (dos cartas + Random(0,0.2) -
privadas) Random(0,0.2);
if (ciega_grande == true || if (probabilidad_total >=
ciega_pequeña == true) probabilidad_umbral)
{ {
probabilidad_total = while (apuesta_igualada == false
Fuerza_mano(mano_inicial) + || perder == false)
Random(0,0.2) - Random(0,0.2) + 0.05; {
else Ratio_ganancia(bote,
probabilidad_total = apuesta);
Fuerza_mano(mano_incial) + Random(0,0.2) ratio_devolucion =
- Random(0,0.2); Fuerza_mano / Ratio_ganancia;
} aleatoriedad = Random(0,1);
Jugar(Ratio_ganancia,
// Pre-Flop Fuerza_mano, ratio_devolucion,
if (probabilidad_total >= aletoriedad);
probabilidad_umbral) }
{ }
while (apuesta_igualada == false)
{ // River (cinco cartas comunitarias)
Ratio_ganancia(bote, probabilidad_total =
apuesta); Fuerza_mano(mano_inicial,
ratio_devolucion = cartas_comunitarias)
Fuerza_mano / Ratio_ganancia; + Random(0,0.2) -
aleatoriedad = Random(0,1); Random(0,0.2);
if (probabilidad_total >=
Jugar(Ratio_ganancia, Fuerza_mano, probabilidad_umbral)
ratio_devolucion, aletoriedad); {
} while (apuesta_igualada == false
} || perder == false)
{
// Flop (tres cartas comunitarias) Ratio_ganancia(bote,
probabilidad_total = apuesta);
Fuerza_mano(mano_inicial, ratio_devolucion =
cartas_comunitarias) Fuerza_mano / Ratio_ganancia;
+ Random(0,0.2) - aleatoriedad = Random(0,1);
Random(0,0.2); Jugar(Ratio_ganancia,
if (probabilidad_total >= Fuerza_mano, ratio_devolucion,
probabilidad_umbral) aletoriedad);
{ }
while (apuesta_igualada == false }
|| perder == false)
{ bool Jugar(void){
Ratio_ganancia(bote, if (hablo == true)
apuesta); {
ratio_devolucion = if (fichas_disponibles <
Fuerza_mano / Ratio_ganancia; fichas_iniciales / 10)
aleatoriedad = Random(0,1); All_in();
Jugar(Ratio_ganancia, else
if (ratio_devolucion < 0.8) mano
//Muy mala mano {
{ if (aletoriedad
if (aleatoriedad > > 0.4)
0.05) Igualar();
Irse(); if (aletoriedad
if (aleatoriedad <= <= 0.4)
0.05)
// Farol ratio_subida = (10*Ratio_ganancia)
* fichas_disponibles /
ratio_subida = (10*Ratio_ganancia) (100*Fuerza_mano);
* fichas_disponibles /
(100*Fuerza_mano); Subir(ratio_subida);
}
Subir(ratio_subida); else
} // Muy
else if buena mano
(ratio_devolucion < 1) // Mala {
mano if (aletoriedad
{ > 0.3)
if (aletoriedad
> 0.15) ratio_subida = (10*Ratio_ganancia)
Irse(); * fichas_disponibles /
if (aletoriedad (100*Fuerza_mano);
<= 0.15 && 0.05 < Aletoriedad)
// Farol Subir(ratio_subida);
if (aletoriedad
ratio_subida = (10*Ratio_ganancia) <= 0.3)
* fichas_disponibles / Igualar();
(100*Fuerza_mano); }
}
Subir(ratio_subida); else
if (aletoriedad Esperar_turno();
<= 0.05)
Igualar(); perder =
} Resolucion_jugada();
else if }
(ratio_devolicion < 1.3) // Buena