Agentes de IA¶
Diseño completo: design/06-agentes.md. Código: src/musst/agents/.
Niveles¶
| Nivel | Clase | Técnica |
|---|---|---|
| Sencillo | SimpleBot |
Heurísticas de fuerza de mano por lance; ruido del 15 % y faroles ocasionales (errores razonables) |
| Medio | AgentBot("medio") |
Agentes de cartas, probabilidad (Monte Carlo, 90 muestras) y marcador |
| Profesional | AgentBot("profesional") |
Todos los agentes + PlayerModel con memoria + farol + pareja (300-800 muestras) |
Qué hace cada nivel (diferencias claras)¶
| Sencillo | Medio | Profesional | |
|---|---|---|---|
| Fuerza de su mano | Heurística | Monte Carlo (90 manos) | Monte Carlo (300; 800 en jugadas críticas) |
| Lee los envites del rival | No | Solo en el lance actual | Sí, ponderado por lo que sabe de cada rival |
| Conoce a cada jugador (PlayerModel) | No | No | Sí: farol, agresividad, qué envida con buena y mala mano |
| Conteo (cartas pedidas, descartes) | No | No | Sí |
| Tantos de jugada de la pareja (pares/juego) | No | Solo los suyos | Los de toda la pareja |
| Descarte | Heurístico | Heurístico | Simulado (30 reposiciones por opción) |
| Errores deliberados | 15 % | 30 % en decisiones ajustadas | Ninguno |
| Faroles | 5 % | Deliberados, 10 % de las manos flojas | Deliberados, 7 % |
| Órdago | Con mano muy fuerte | P(ganar) ≥ 0.8 o desesperación; yendo por delante, P ≥ 0.85 (también para ver uno) | P(ganar) ≥ 0.8 o desesperación; yendo por delante, P ≥ 0.85 (también para ver uno) |
| Señas | Si le mira cualquiera | Si le mira su compañero | Solo si le mira su compañero y ningún rival |
| Aprende entre partidas | No | No | Sí: perfiles y autocrítica |
Agentes¶
| Agente | Clase | Produce |
|---|---|---|
| Orquestador | Orchestrator |
Elige agentes; activa el análisis profundo ante órdagos, apuestas ≥ 8 o el final de la partida |
| Cartas | CardAgent |
Fuerza de la propia mano en cada lance |
| Comportamiento | BehaviourAgent |
Agresividad, farol, aceptación y subidas de cada rival en el contexto actual (lance × marcador) |
| Probabilidad | ProbabilityAgent |
P(ganar el lance), P(el rival acepta), P(ganar | acepta), para envite y órdago |
| Farol | BluffAgent |
P(el rival que envida farolea) por Bayes |
| Marcador | ScoreAgent |
Apetito de riesgo, umbral de órdago, valor del juego, utilidad de un tanto |
| Pareja | PartnerAgent |
P(mi compañero acepta si yo no quiero) |
| Estrategia | StrategyAgent |
Candidatas legales con su valor esperado (EV) |
| Juez | Judge |
argmax EV − λ·riesgo·(1 − confianza) → Decision |
| Reglas | motor | La autoridad es siempre MusGame.validate |
Probabilidad con selección adversa¶
Para cada mundo muestreado (cartas no vistas repartidas de forma compatible con las declaraciones públicas):
- Se pondera por la verosimilitud de los envites rivales:
P(envite | fuerza) = 0.5·farol^n + (1 − farol)·σ((fuerza − τ)/0.05), con un umbral τ que sube con cada reenvite y baja si el rival es agresivo (aprendido por el PlayerModel). - Se anota si ganamos el lance y si el rival aceptaría (su fuerza ≥ umbral de aceptación).
Así se obtienen P(ganar), P(acepta) y P(ganar | acepta). Sin esto, el bot sobrestima sus envites: quien acepta suele tener buena mano.
El tanteo manda (agente de marcador y estrategia)¶
No es lo mismo un envite a 5-5 que a 39-10. Además del apetito de riesgo del ScoreAgent:
- A punto de salir. Si a la pareja le faltan tantos que ya cobra con un «no quiero» (p. ej.
le falta 1 y envida a grande), echa órdago con P(ganarlo) ≥ 0,3 (
ORDAGO_TO_FINISH): si no lo quieren, ha ganado la partida; si lo quieren, se juega con buenas opciones. Con una mano sin ninguna opción, no. - Rival a punto de ganar (le faltan 5 o menos,
RIVAL_CLOSE): más agresivo. Ir por delante deja de ser motivo para reservarse el órdago, y farolea más. - Un «no quiero» que regala la partida se valora como perder la partida (no como perder 1 o 2 tantos): si al rival le faltan los tantos que cobraría, el bot quiere el envite o el órdago.
Pruebas en tests/unit/test_tanteo_agresivo.py.
DecisionExplanation¶
bot = ProBot()
...
bot.last_decision.explanation()
# {'decision': 'BET_2',
# 'factors': {'p_win': 0.71, 'confidence': 0.93, 'p_accept_bet': 0.34, 'ev': 1.42, 'risk': 0.6},
# 'confidence': 0.74,
# 'agents_consulted': ['cartas', 'comportamiento', 'probabilidad', 'marcador', 'pareja'],
# 'alternatives': [{'action': 'BET_2', 'ev': 1.42, 'risk': 0.6}, ...],
# 'narrative': 'EV(BET_2)=+1.42; EV(PASS)=+0.71; EV(BET_4)=+1.10'}
En el servidor, las explicaciones se guardan por partida y solo se ven en el modo desarrollo
(MUSST_DEV_MODE=1, ruta /api/dev/games/{id}). Nunca se envían al jugador durante la partida.