-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblackjack_ev.py
More file actions
126 lines (106 loc) · 4.32 KB
/
Copy pathblackjack_ev.py
File metadata and controls
126 lines (106 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""
Módulo: blackjack_ev.py
Descripción: Simulación de Monte Carlo para calcular el Valor Esperado (EV)
y el Retorno al Jugador (RTP) en Blackjack aplicando Estrategia Básica.
"""
import numpy as np
import pandas as pd
class SimuladorBlackjack:
def __init__(self, num_decks=6, num_simulaciones=10000):
self.num_decks = num_decks
self.num_simulaciones = num_simulaciones
self.resultados = []
def _crear_zapato(self):
"""Crea el 'zapato' combinando múltiples barajas estándar."""
# Las cartas 10, J, Q, K valen 10. El As vale 11 inicialmente.
carta_base = [2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11]
zapato = carta_base * 4 * self.num_decks
np.random.shuffle(zapato)
return zapato
def _calcular_valor(self, mano):
"""Calcula el valor óptimo de una mano manejando el As (1 u 11)."""
total = sum(mano)
ases = mano.count(11)
while total > 21 and ases > 0:
total -= 10
ases -= 1
return total
def _estrategia_basica(self, suma_jugador, carta_crupier):
"""
Estrategia básica simplificada para decidir Hit (H) o Stand (S).
- Si la suma es menor o igual a 11: Pide carta (H).
- Si la suma es 17 o más: Se planta (S).
- Si es 12-16: Se planta si el crupier muestra una carta baja (2-6), si no, pide.
"""
if suma_jugador <= 11:
return 'H'
elif suma_jugador >= 17:
return 'S'
else:
if carta_crupier in [2, 3, 4, 5, 6]:
return 'S' # El crupier es propenso a pasarse
else:
return 'H'
def simular_mano(self, zapato):
"""Simula una mano individual de Blackjack."""
if len(zapato) < 15: # Renovar zapato si quedan pocas cartas
zapato = self._crear_zapato()
mano_jugador = [zapato.pop(), zapato.pop()]
mano_crupier = [zapato.pop(), zapato.pop()]
# Turno del jugador
while True:
val_jugador = self._calcular_valor(mano_jugador)
if val_jugador >= 21:
break
accion = self._estrategia_basica(val_jugador, mano_crupier[0])
if accion == 'H':
mano_jugador.append(zapato.pop())
else:
break
val_jugador = self._calcular_valor(mano_jugador)
if val_jugador > 21:
return -1, zapato # Jugador se pasa (Pierde)
# Turno del crupier (regla fija: pide hasta 17 o más)
while self._calcular_valor(mano_crupier) < 17:
mano_crupier.append(zapato.pop())
val_crupier = self._calcular_valor(mano_crupier)
if val_crupier > 21:
return 1, zapato # Crupier se pasa (Gana jugador)
elif val_jugador > val_crupier:
return 1, zapato
elif val_jugador < val_crupier:
return -1, zapato
else:
return 0, zapato # Empate (Push)
def ejecutar_simulacion(self):
"""Ejecuta la simulación masiva de Monte Carlo."""
print(f"Iniciando simulación de {self.num_simulaciones} manos de Blackjack...")
zapato = self._crear_zapato()
resultados = []
for _ in range(self.num_simulaciones):
resultado, zapato = self.simular_mano(zapato)
resultados.append(resultado)
# Análisis con Pandas
df = pd.DataFrame(resultados, columns=["Resultado"])
conteo = df["Resultado"].value_counts()
victorias = conteo.get(1, 0)
derrotas = conteo.get(-1, 0)
empates = conteo.get(0, 0)
# Cálculo de métricas
ev = (victorias - derrotas) / self.num_simulaciones
rtp = ((victorias + (empates * 0.5)) / self.num_simulaciones) * 100
resumen = {
"Total Manos": self.num_simulaciones,
"Victorias": victorias,
"Derrotas": derrotas,
"Empates": empates,
"Valor Esperado (EV)": round(ev, 4),
"Retorno al Jugador (RTP %)": round(rtp, 2)
}
return resumen
if __name__ == "__main__":
sim = SimuladorBlackjack(num_simulaciones=50000)
metricas = sim.ejecutar_simulacion()
print("\n--- RESULTADOS DE LA SIMULACIÓN DE BLACKJACK ---")
for k, v in metricas.items():
print(f"{k}: {v}")