Rangos por posición para bots de póker: deja de abrir desde cualquier asiento
Tu bot de póker no debería jugar las mismas manos desde todas las posiciones. En No-Limit Hold'em 6-max, el botón actúa último después del flop y las ciegas lo hacen primero. Esa diferencia determina qué manos generan fichas y cuáles desgastan el stack poco a poco.
Parte de: La guía completa para crear un bot de póker con IA en 2026, la guía principal sobre frameworks, lógica de decisión, equity, pruebas y dónde competir.
Conclusiones clave
- Los rangos de posición son una ventaja económica porque solucionan los errores preflop antes de que la mano se vuelva cara.
- Las posiciones tempranas exigen aperturas tight. Desde posiciones tardías se puede robar con mayor frecuencia porque quedan menos jugadores por actuar.
- Empieza por implementar los rangos como conjuntos de códigos de mano. Añade el modelado de rivales cuando esa base ya funcione.
¿Por qué es tan importante la posición?
La posición importa porque quien actúa más tarde dispone de más información. La documentación de estrategia de Open Poker trata las posiciones tempranas, las tardías y las ciegas como contextos distintos (documentación de acciones y estrategia). En una mesa 6-max, cada órbita incluye seis posiciones y 30 fichas forzadas con ciegas 10/20.
Si un bot abre KTo desde UTG, todavía quedan cinco jugadores que pueden castigarlo. Si abre la misma mano desde el botón, solo deben responder las dos ciegas. Las cartas son iguales; el riesgo, no.
Aquí es donde muchos bots principiantes pierden sin que resulte evidente. Calculan un único valor hand_strength() y lo aplican desde cualquier posición. Puede bastar con manos obvias como ases, pero falla con las que deciden buena parte de una temporada: suited connectors, ases débiles, parejas pequeñas y broadways marginales.
¿Cuáles son las seis posiciones útiles de una mesa?
Usa seis categorías: UTG, HJ, CO, BTN, SB y BB. Open Poker envía dealer_seat en hand_start; el bot conoce su asiento a partir de table_joined y puede calcular la posición relativa con esos dos valores (documentación de WebSocket).
POSITIONS_6MAX = ["SB", "BB", "UTG", "HJ", "CO", "BTN"]
def position_name(hero_seat, dealer_seat, active_seats):
ordered = sorted(active_seats)
dealer_index = ordered.index(dealer_seat)
relative = ordered[(dealer_index + 1) % len(ordered):] + ordered[:dealer_index + 1]
# relative[0] is small blind, relative[1] is big blind in a full hand.
seat_to_position = {
seat: POSITIONS_6MAX[i]
for i, seat in enumerate(relative[: len(POSITIONS_6MAX)])
}
return seat_to_position[hero_seat]Las mesas reales pueden estar incompletas. Si solo hay tres bots sentados, reduce la lógica a BTN, SB y BB. No asumas que existe UTG cuando solo hay tres jugadores activos.
¿Qué rangos de apertura debería utilizar un primer bot?
Empieza con un rango más tight de lo que imaginas. Una base práctica es abrir un 12 % desde UTG, 16 % desde HJ, 22 % desde CO, 35 % desde BTN y mantener cautela en la ciega pequeña. No son rangos de solver perfectos, pero frenan los peores fallos mientras mejoras la lógica postflop.
| Posición | Objetivo abierto | Manos de ejemplo |
|---|---|---|
| UTG | 12% | 77+, AJ+, KQ, AQo+ |
| HJ | 16% | 66+, AT+, KJ+, QJ, AJo+ |
| CO | 22% | 55+, A8s+, KT+, QT+, JT, ATo+, KQo |
| BTN | 35% | 22+, más ases suited, broadways y suited connectors |
| SB | 28% | Subir manos que funcionen bien heads-up y foldear la basura |
| BB | Defender según el precio | Hacer call según las pot odds y la jugabilidad de la mano |
Los porcentajes exactos importan menos que el patrón: tight desde posiciones tempranas, amplio en el botón y cuidadoso desde las ciegas. Esta estructura corrige más bots principiantes que otra heurística postflop.
Para incorporar la profundidad del stack, combina estos rangos con la gestión de stacks para bots de póker. Un bot con 50 bb y otro con 250 bb no deben tratar igual las parejas pequeñas.
¿Cómo se codifican rangos en Python?
Codifica las manos como cadenas breves: AA, AKs, AQo. Las parejas repiten el rango; las manos suited terminan en s y las offsuit en o. El formato es compacto para rangos escritos a mano y fácil de depurar en los logs.
RANK_ORDER = "23456789TJQKA"
def hand_code(cards):
r1, s1 = cards[0][0], cards[0][1]
r2, s2 = cards[1][0], cards[1][1]
if r1 == r2:
return r1 + r2
high, low = sorted([r1, r2], key=RANK_ORDER.index, reverse=True)
suited = "s" if s1 == s2 else "o"
return high + low + suited
OPEN_RANGES = {
"UTG": {"77", "88", "99", "TT", "JJ", "QQ", "KK", "AA", "AJs", "AQs", "AKs", "KQs", "AQo", "AKo"},
"HJ": {"66", "77", "88", "99", "TT", "JJ", "QQ", "KK", "AA", "ATs", "AJs", "AQs", "AKs", "KJs", "KQs", "QJs", "AJo", "AQo", "AKo"},
"CO": {"55", "66", "77", "88", "99", "TT", "JJ", "QQ", "KK", "AA", "A8s", "A9s", "ATs", "AJs", "AQs", "AKs", "KTs", "KJs", "KQs", "QTs", "QJs", "JTs", "ATo", "AJo", "AQo", "AKo", "KQo"},
"BTN": {"22", "33", "44", "55", "66", "77", "88", "99", "TT", "JJ", "QQ", "KK", "AA", "A2s", "A3s", "A4s", "A5s", "A6s", "A7s", "A8s", "A9s", "ATs", "AJs", "AQs", "AKs", "K9s", "KTs", "KJs", "KQs", "Q9s", "QTs", "QJs", "J9s", "JTs", "T9s", "98s", "87s", "A9o", "ATo", "AJo", "AQo", "AKo", "KTo", "KJo", "KQo", "QJo"},
}
def should_open(position, cards):
return hand_code(cards) in OPEN_RANGES.get(position, set())El enfoque parece rudimentario, y esa es una ventaja. Cuando el bot pierde un stack, puedes imprimir position=CO hand=KTo open=False y entender la decisión al instante.
¿Cómo se utilizan rangos con acciones válidas?
Solo debes abrir cuando no hay una apuesta previa y la subida es legal. Open Poker indica exactamente qué acciones están permitidas, incluido raise con importes mínimo y máximo. El importe de la subida representa el total, no la cantidad adicional, un error frecuente en los bots (documentación de acciones).
def preflop_decision(msg, hole_cards, position):
actions = {a["action"]: a for a in msg["valid_actions"]}
# Free option in the big blind.
if "check" in actions:
return "check", None
if "raise" in actions and should_open(position, hole_cards):
return "raise", actions["raise"]["min"]
# Facing a raise: use a tighter continue range for now.
if "call" in actions and hand_code(hole_cards) in {"TT", "JJ", "QQ", "KK", "AA", "AQs", "AKs", "AKo"}:
return "call", None
return "fold", NoneEste rango de call es tight a propósito. Ampliarlo demasiado es una de las formas más rápidas de convertir un bot preflop competente en un perdedor postflop. Cuando hayas añadido equity Monte Carlo, amplía los calls según el precio y las tendencias del rival.
¿Cuándo deberían cambiar los rangos?
Los rangos deben adaptarse a la profundidad del stack, al número de jugadores y a los rivales. Los buy-ins de Open Poker van de 1000 a 5000 fichas, mientras que cada temporada comienza con 5000 fichas y ciegas fijas de 10/20 (documentación de temporadas). Por tanto, un mismo bot puede jugar con 50, 100 o 250 bb.
Usa tres ajustes:
| Contexto | Ajuste |
|---|---|
| Short stack por debajo de 60bb | Eliminar conectores especulativos del mismo palo y pares pequeños |
| Stack profundo de más de 150 bb | Añadir suited connectors y parejas pequeñas en posiciones tardías |
| Ciegas loose | Robar más y apostar por valor con mayor amplitud |
| Ciegas tight | Ampliar las aperturas desde botón y cutoff |
No añadas los cuatro ajustes el primer día. Demuestra primero que el rango base supera a la antigua estrategia de puntuación única. Después deja que el modelado de oponentes ajuste el botón y las ciegas.
¿Cómo se prueba un rango nuevo?
Prueba un solo cambio de rango cada vez. Los ajustes preflop parecen pequeños, pero afectan a todas las calles posteriores porque el bot llega al flop con otra distribución de manos. Si amplías el botón, relajas la defensa de la ciega grande y cambias el tamaño de apuesta en el mismo despliegue, no sabrás qué ajuste funcionó.
Usa este bucle de prueba:
- Elige una posición, normalmente BTN o BB.
- Cambia entre 5 y 10 manos de ese rango.
- Ejecuta al menos 300 manos.
- Compara la tendencia de las fichas, las recompras y las grandes manos perdedoras.
- Conserva el cambio solo si los logs explican el resultado.
La señal más rápida no es el win rate, sino las manos que entraron preflop y perdieron más de 20 bb. Revisa esas manos primero. Si el nuevo rango del botón añade cinco manos offsuit marginales que pierden botes inflados una y otra vez, retíralas. Si roban las ciegas y rara vez llegan al showdown, sigue probando.
El juego real premia una disciplina poco vistosa. Los buenos bots no necesitan una creatividad heroica preflop. Necesitan menos manos dominadas desde posiciones tempranas y una presión más controlada desde las tardías.
Preguntas frecuentes
¿Debería un bot de póker utilizar rangos perfectos de solver?
Al principio, no. Los rangos de solver presuponen un árbol de juego y una respuesta concreta del rival. Una tabla sencilla para 6-max es más fácil de probar y registrar, y suele superar a un gráfico copiado que el bot no sabe jugar postflop.
¿Cómo debe defender la ciega grande?
La ciega grande debe defender según el precio. Pagar 20 en un bote de 90 exige mucha menos equity que pagar 200 en uno de 300. Empieza por las pot odds y después descarta las manos con mala jugabilidad postflop.
¿Qué rango debo usar para un bot sin código?
Empieza con la plantilla The Shark. La documentación de Bot Builder la define con 0,30 de tightness y 0,75 de aggression, una base más sólida que las plantillas loose para la mayoría de los usuarios nuevos.
¿Pueden los rangos por posición sustituir la evaluación de manos?
No. Los rangos deciden si entrar en la mano antes del flop. La evaluación de manos y la equity orientan las decisiones cuando aparecen las cartas comunitarias. Necesitas ambas.