Arquitetura Avançada de Poker Bots: Equidade e Testes
Um poker bot avançado transforma um loop de eventos confiável em um sistema mensurável de decisões. A evolução não é simplesmente "adicionar IA". Ela envolve snapshots imutáveis de decisão, características explícitas de poker, equidade baseada em ranges, mãos reproduzíveis e um ciclo experimental capaz de provar que uma policy mudou. Preserve a proteção de ações legais do bot básico. Toda a inteligência fica atrás dela.
Série sobre arquitetura de poker bots: Parte 2 de 3. Comece com Arquitetura Básica de Poker Bots se o seu runtime ainda rejeita ações. Continue com Arquitetura Profissional de Poker Bots. Compare opções operacionais em Custo de um Poker Bot em 2026.
O que muda na arquitetura avançada de um poker bot?
Um poker bot avançado separa fatos, estimativas, policy e execução. Os fatos vêm do turno mais recente do servidor: pot, board, stacks, ações legais, ID da mão e token. As estimativas incluem equidade e range do oponente. A policy usa ambos para retornar uma intenção. A execução compara essa intenção com os fatos uma última vez.
Essa distinção importa porque estimativas podem estar erradas. Um modelo de oponente pode atribuir um range restrito demais. Uma simulação de Monte Carlo pode ter erro amostral. Nenhum desses erros deve produzir um raise inválido ou uma resposta para um turno expirado. A camada externa permanece determinística, mesmo quando a policy interna se torna probabilística.
| Classe de dado | Exemplo | Confiança | Responsável |
|---|---|---|---|
| Fato do servidor | pot = 180, raise máximo 1,640 | Oficial | Adaptador do protocolo |
| Fato derivado | pot odds, stack efetivo, posição | Exato se as entradas estiverem corretas | Camada de características |
| Estimativa | 43% de equidade no showdown | Amostrada ou modelada | Serviço de equidade |
| Crença | oponente abre 31% do botão | Incerta | Modelo de oponente |
| Intenção | call porque a equidade supera o preço | Saída da policy | Estratégia |
Nunca reduza tudo a um único dicionário sem tipos. Quando a confiança e a responsabilidade desaparecem, um range estimado começa a parecer tão confiável quanto o limite de raise fornecido pelo servidor.
Como snapshots imutáveis de decisão devem funcionar?
Um snapshot imutável de decisão é uma entrada completa e somente leitura, capturada a partir de um your_turn. Ele impede que eventos atrasados da rede alterem os dados enquanto o cálculo de equidade ou o modelo estão em execução. Também se torna a unidade reproduzida nos testes.
from dataclasses import dataclass
from typing import Literal
Action = Literal["fold", "check", "call", "raise", "all_in"]
@dataclass(frozen=True)
class DecisionSnapshot:
hand_id: str
turn_token: str
street: str
hole: tuple[str, str]
board: tuple[str, ...]
pot: float
stack: float
to_call: float
opponents: int
position: str
legal: tuple[Action, ...]
min_raise: float | None
max_raise: float | None
@property
def pot_odds(self) -> float:
return self.to_call / (self.pot + self.to_call) if self.to_call else 0.0
@property
def stack_to_pot(self) -> float:
return self.stack / self.pot if self.pot else float("inf")Crie o snapshot de forma síncrona quando o turno chegar. Depois, passe-o a uma tarefa assíncrona de decisão. Antes de enviar o resultado, compare novamente hand_id e turn_token com o turno ativo. Os tokens do Open Poker são consumidos após uma ação, e cada novo your_turn invalida o anterior. Portanto, trabalho obsoleto deve ser descartado, não repetido.
A referência de tipos de mensagem documenta os campos da conexão. Seu normalizador também deve aceitar table_state depois de uma reconexão, pois a seção hero, específica do jogador, contém as cartas fechadas e as ações legais atuais.
Como equidade e pot odds se transformam em uma decisão?
A equidade responde com que frequência uma mão recebe o pot no showdown contra um range presumido. Pot odds indicam a parcela mínima necessária para um call ficar no zero a zero. O call tem expectativa positiva em fichas quando a equidade estimada supera call / (pot + call), antes dos ajustes por apostas futuras, erro no range e objetivos do torneio.
Se o pot é 180 e o call custa 60, as pot odds são 60 / 240 = 25%. Uma estimativa de 38% de equidade supera esse limite bruto em 13 pontos percentuais. Não pague todo spot com uma vantagem de um ponto. Variância de Monte Carlo, range impreciso do oponente e ações futuras podem apagar uma margem pequena. Usamos uma margem de segurança explícita e a registramos.
from dataclasses import dataclass
@dataclass(frozen=True)
class EquityResult:
equity: float
trials: int
range_name: str
def call_has_margin(snapshot: DecisionSnapshot, result: EquityResult,
margin: float = 0.03) -> bool:
return (
"call" in snapshot.legal
and result.equity >= snapshot.pot_odds + margin
)A calculadora de equidade por Monte Carlo mostra uma implementação em Python. Para primitivas de avaliação mantidas por terceiros, a documentação do avaliador do PokerKit é um ponto de partida melhor do que escrever um classificador de mãos durante um projeto de estratégia.
Como um modelo de oponente deve representar a incerteza?
Um modelo de oponente deve armazenar contagens e taxas suavizadas, não rótulos como "agressivo" ou "fish". Características iniciais úteis incluem participação voluntária pré-flop, taxa de raise pré-flop, oportunidades e ações de 3-bet, agressividade pós-flop, oportunidades de fold diante de uma aposta e mãos observadas no showdown. Toda taxa precisa de um denominador.
Um jogador que deu raise duas vezes em quatro oportunidades tem uma taxa observada de 50% e quase nenhuma certeza. A suavização bayesiana impede que amostras mínimas alterem demais a policy. Com uma distribuição a priori Beta, uma taxa pode ser estimada como (successes + alpha) / (opportunities + alpha + beta). Uma priori neutra Beta(2, 2) transforma dois raises em quatro oportunidades em 4 / 8 = 50%, enquanto zero raises em uma oportunidade vira 2 / 5 = 40%, não um zero tratado como certeza.
Segmente estatísticas por situações que mudam a estratégia. Posição e street importam. Uma "agressividade" geral da mesa mistura um open raise de under the gun com um check-raise no river. Comece com poucos grupos que você consegue preencher, não cinquenta células esparsas. Nosso guia de modelagem de oponentes explica melhor decaimento, evidências de showdown e limites para exploits.
Mantenha uma policy de referência que ignore características dos oponentes. Sem ela, você não consegue saber se a adaptação ajudou ou se o bot inteiro apenas teve uma boa semana.
O que a interface da policy avançada deve retornar?
A policy avançada deve retornar a intenção da ação, a intenção do valor, códigos de motivo, valores das características e metadados do modelo. Uma string simples como "call" é pequena demais para análise. Um texto livre é flexível demais para o código. Use um registro tipado.
from dataclasses import dataclass, field
@dataclass(frozen=True)
class DecisionIntent:
action: Action
amount: float | None
reason_code: str
confidence: float
features: dict[str, float] = field(default_factory=dict)
policy_version: str = "range-equity-v3"
def decide(snapshot: DecisionSnapshot, eq: EquityResult) -> DecisionIntent:
features = {
"equity": eq.equity,
"pot_odds": snapshot.pot_odds,
"spr": snapshot.stack_to_pot,
}
if snapshot.to_call == 0 and "check" in snapshot.legal:
return DecisionIntent("check", None, "free_action", 1.0, features)
if call_has_margin(snapshot, eq):
confidence = min(1.0, (eq.equity - snapshot.pot_odds) * 4)
return DecisionIntent("call", None, "equity_clears_price", confidence, features)
return DecisionIntent("fold", None, "equity_below_price", 0.8, features)A proteção de execução continua responsável pelo ajuste aos limites e pelo fallback. Se a policy propuser um call depois que o turno ativo mudar, descarte-o. Se ela propuser um raise ausente da lista legal, substitua-o por check ou fold e incremente uma métrica de violação da policy. Uma correção silenciosa esconde bugs. Correção com telemetria mantém a mesa segura e a falha visível.
Como replays de mãos testam todo o caminho de decisão?
Replays de mãos passam eventos gravados do servidor pelo mesmo normalizador e pela mesma policy usados ao vivo, sem abrir um socket. Eles encontram bugs que testes unitários isolados não percebem: estado que vaza entre mãos, posição derivada de um assento vazio, evento duplicado ou um valor null que chega à aritmética.
Armazene uma mensagem JSON por linha, preservando a ordem de chegada. Um executor de replay pode carregar o arquivo e chamar os handlers reais. Substitua a aleatoriedade por uma seed fixa e os serviços externos por respostas gravadas. A saída deve ser uma sequência de registros de decisão que um teste possa comparar com o comportamento aprovado.
import json
import random
from pathlib import Path
def replay(path: str, engine) -> list[dict]:
random.seed(20260812)
decisions = []
for line in Path(path).read_text(encoding="utf-8").splitlines():
event = json.loads(line)
result = engine.apply(event)
if result is not None:
decisions.append(result)
return decisions
def test_replay_never_emits_illegal_action(engine):
for item in replay("fixtures/three_hands.jsonl", engine):
assert item["action"] in item["legal"]Testes baseados em propriedades são úteis para proteções de ações. Gere conjuntos aleatórios de ações legais e limites de raise, depois confirme que a saída sempre foi oferecida e sempre está dentro dos limites. O Hypothesis foi feito para esse estilo de teste. Você não precisa de testes de propriedades para cada opinião sobre poker, mas os invariantes do protocolo merecem esse cuidado.
Como avaliar uma mudança de estratégia?
Avalie uma mudança de estratégia com policies pareadas, rótulos de versão fixos, métricas operacionais e mãos suficientes para expor a incerteza. Não implante um range novo e compare suas próximas 200 mãos com o resultado da terça-feira passada. A mistura de oponentes, as posições e a variância das cartas também mudaram.
Acompanhe pelo menos estas métricas:
| Métrica | Por que importa |
|---|---|
| Ações ilegais por 1.000 turnos | Critério rígido de correção |
| Latência de decisão p50, p95, p99 | Detecta falhas na cauda escondidas pelas médias |
| Taxa de fallback | Mostra instabilidade da policy ou das dependências |
| bb/100 com intervalo de confiança | Resultado da estratégia normalizado pelos blinds |
| Estimativa ajustada para all-ins | Reduz parte da variância no showdown |
| VPIP, PFR, taxa de 3-bet | Explica como o comportamento mudou |
| Taxa de fold por street | Encontra leaks estratégicos evidentes |
Use números aleatórios comuns em um simulador quando possível: execute as policies A e B com as mesmas distribuições de cartas e ações dos oponentes. O jogo ao vivo não permite controlar todo o ambiente, então registre a composição da mesa e compare janelas mais longas. O artigo sobre o OpenSpiel, do Google DeepMind, descreve um framework de avaliação e pesquisa para jogos, inclusive jogos de informação imperfeita. Ele é útil localmente, enquanto a arena ao vivo do Open Poker testa o protocolo e a diversidade de oponentes.
Uma mudança não é promovida apenas porque seu bb/100 é positivo. Ela deve manter em zero os critérios de correção, preservar a latência dentro do orçamento e melhorar um objetivo declarado sem causar uma regressão inaceitável em outro ponto.
Onde um LLM se encaixa no nível avançado?
Um LLM se encaixa atrás da mesma interface de policy como consultor seletivo, não como cliente de rede ou autoridade sobre legalidade. Forneça a ele um snapshot compacto, ações legais exatas, pot odds calculadas, um range estimado e um schema JSON rígido. Valide a resposta e mantenha um fallback determinístico.
Desvie do modelo as decisões óbvias. Um check gratuito, um fold obrigatório segundo uma tabela pré-flop rígida ou um tamanho de raise já escolhido por uma regra determinística de valor não precisam de uma chamada remota. O roteamento seletivo reduz custos e facilita o controle da latência. O guia de poker bot com LLM mostra o padrão básico de conexão, mas um runtime avançado deve adicionar validação de schema, prompts versionados, cancelamento por prazo e fixtures de replay.
Somos céticos quanto ao uso de justificativas em linguagem natural como evidência de avaliação. Um modelo pode produzir uma explicação convincente para uma ação ruim. Julgue a ação pelos resultados, testes contrafactuais e métricas estáveis. Mantenha o texto para depuração, mas confie nas características estruturadas e no registro do experimento.
FAQ
O que torna um poker bot avançado?
Um bot avançado usa snapshots imutáveis de turno, características derivadas explícitas, equidade baseada em ranges, estatísticas dos oponentes, testes de replay e experimentos versionados. Mais código de estratégia, por si só, não torna a arquitetura avançada.
Quantas simulações de Monte Carlo um poker bot deve executar?
Comece com 2.000 a 5.000 simulações por decisão e faça benchmarks no seu hardware. Use mais apenas quando a estimativa mudar decisões o suficiente para justificar a latência. Registre tanto o número de simulações quanto o tempo de execução.
De quantos dados preciso para modelar oponentes?
Use suavização desde a primeira observação, mas mantenha a adaptação pequena até que cada estatística tenha um denominador relevante. Não existe uma contagem mágica de mãos, pois oportunidades de 3-bet aparecem com muito menos frequência do que oportunidades de participação pré-flop.
Devo otimizar a taxa de vitória ou o lucro em fichas?
Use big blinds por 100 mãos para relatórios comparáveis de estratégia e fichas brutas para medir o impacto na temporada. Sempre publique a incerteza e as métricas operacionais. Uma estimativa pontual sem contagem de mãos nem intervalo convida a uma falsa confiança.
Testes de replay podem provar que uma estratégia de poker vence?
Não. Replays provam o comportamento determinístico e detectam regressões em situações conhecidas. Simulações e experimentos ao vivo testam o desempenho contra distribuições de mãos e oponentes.
Quando versões da policy, replays de mãos e métricas tornam cada mudança auditável, a próxima restrição é operacional. Arquitetura Profissional de Poker Bots cobre ressincronização, orçamentos de prazo, isolamento de falhas, avaliação em modo shadow e lançamentos seguros para um bot que opera sem supervisão.