From 0c0f23c008b46be1902f374b2b023371c2931c9f Mon Sep 17 00:00:00 2001 From: josedario87 Date: Sun, 10 Aug 2025 16:44:48 -0600 Subject: [PATCH] arreglados los mermaids --- g1-no-property.mmd | 26 +- g2-counterproductive-rule.mmd | 37 ++- g3-shame-token.mmd | 37 ++- g4-min-property-rights.mmd | 45 +++- g5-cheap-talk.mmd | 31 ++- game-design-mermaid.md | 438 ++++++++++++++++++++++++++-------- game-overview.mmd | 73 +++++- game-sequence.mmd | 110 +++++---- game-state-machine.mmd | 84 +++++-- 9 files changed, 680 insertions(+), 201 deletions(-) diff --git a/g1-no-property.mmd b/g1-no-property.mmd index 7aaa9af..8875561 100644 --- a/g1-no-property.mmd +++ b/g1-no-property.mmd @@ -1,6 +1,22 @@ flowchart TD - A1[P1: Proponer oferta? (pavos/elotes + pedido)] -->|No ofrecer| O1[Sin cambios] - A1 -->|Ofrecer| B1[P2: Aceptar / Rechazar / Robar] - B1 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B1 -->|Rechazar| O3[Sin cambios] - B1 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G1: Sin derechos de propiedad] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A1{P1: Ofrecer tokens?} + A1 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A1 -->|Proponer oferta| B1[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + B1 --> C1[UI: Ocultar OfferControls
Mostrar oferta a ambos jugadores] + C1 --> D1{P2: Una sola decisión} + D1 -->|Aceptar| O2[Intercambiar tokens:
P1 da oferta, recibe pedido
P2 da pedido, recibe oferta
→ Auto-avance] + D1 -->|Rechazar| O3[Sin cambios en tokens
→ Auto-avance] + D1 -->|Robar| O4[P2 recibe oferta
P1 pierde oferta
Sin pago de P2
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#1a237e,stroke:#fff,color:#fff + style Init fill:#283593,stroke:#fff,color:#fff + style A1 fill:#4527a0,stroke:#fff,color:#fff + style B1 fill:#512da8,stroke:#fff,color:#fff + style C1 fill:#37474f,stroke:#fff,color:#fff + style D1 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff diff --git a/g2-counterproductive-rule.mmd b/g2-counterproductive-rule.mmd index 11e86a4..f237c5a 100644 --- a/g2-counterproductive-rule.mmd +++ b/g2-counterproductive-rule.mmd @@ -1,9 +1,30 @@ flowchart TD - A2[P2: Forzar?] -->|Sí| F2[P1: Debe proponer oferta] - A2 -->|No| B2[P1: Proponer oferta?] - F2 --> C2[P2: Acción final] - B2 -->|No ofrecer| O1[Sin cambios] - B2 -->|Ofrecer| C2[P2: Aceptar / Rechazar / Robar] - C2 -->|Aceptar| O2[Intercambiar según oferta/pedido] - C2 -->|Rechazar| O3[Sin cambios] - C2 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G2: Regla contraproductiva] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A2[P2: Checkbox 'Forzar oferta'
🔲 Activo por defecto] + A2 -->|forcedByP2 = true| F2[P1 DEBE ofrecer
Botón 'No ofrecer' deshabilitado] + A2 -->|forcedByP2 = false| B2{P1: Ofrecer tokens?} + + F2 --> C2[P1 especifica oferta obligatoria:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + B2 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + B2 -->|Proponer oferta| C2 + + C2 --> D2[UI: Ocultar OfferControls
Mostrar detalles oferta] + D2 --> E2{P2: Una sola decisión} + + E2 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + E2 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + E2 -->|Robar| O4[P2 recibe oferta sin pagar
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#6a1b9a,stroke:#fff,color:#fff + style Init fill:#7b1fa2,stroke:#fff,color:#fff + style A2 fill:#8e24aa,stroke:#fff,color:#fff + style F2 fill:#ab47bc,stroke:#fff,color:#fff + style B2 fill:#4527a0,stroke:#fff,color:#fff + style C2 fill:#512da8,stroke:#fff,color:#fff + style D2 fill:#37474f,stroke:#fff,color:#fff + style E2 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff diff --git a/g3-shame-token.mmd b/g3-shame-token.mmd index 4cbe390..f461d8b 100644 --- a/g3-shame-token.mmd +++ b/g3-shame-token.mmd @@ -1,8 +1,31 @@ flowchart TD - A3[P1: Proponer oferta?] -->|No ofrecer| O1[Sin cambios] - A3 -->|Ofrecer| B3[P2: Aceptar / Rechazar / Robar] - B3 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B3 -->|Rechazar| O3[Sin cambios] - B3 -->|Robar| C3[P1: Asignar ficha de vergüenza?] - C3 -->|Sí| O4a[+1 vergüenza para P2] - C3 -->|No| O4b[Sin vergüenza] + Start[G3: Token de repudio/vergüenza] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A3{P1: Ofrecer tokens?} + A3 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A3 -->|Proponer oferta| B3[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B3 --> C3[UI: Ocultar OfferControls
Mostrar detalles oferta] + C3 --> D3{P2: Una sola decisión} + + D3 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D3 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D3 -->|Robar| E3[P2 recibe oferta sin pagar
UI: Ocultar botones P2] + + E3 --> F3{P1: ¿Asignar vergüenza?} + F3 -->|Asignar| O4a[P2.shameTokens += 1
😶 Visible en UI
→ Auto-avance] + F3 -->|No asignar| O4b[Sin penalización
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#e65100,stroke:#fff,color:#fff + style Init fill:#ef6c00,stroke:#fff,color:#fff + style A3 fill:#4527a0,stroke:#fff,color:#fff + style B3 fill:#512da8,stroke:#fff,color:#fff + style C3 fill:#37474f,stroke:#fff,color:#fff + style D3 fill:#455a64,stroke:#fff,color:#fff + style E3 fill:#bf360c,stroke:#fff,color:#fff + style F3 fill:#ff6f00,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4a fill:#ff3d00,stroke:#fff,color:#fff + style O4b fill:#616161,stroke:#fff,color:#fff diff --git a/g4-min-property-rights.mmd b/g4-min-property-rights.mmd index a9ad18d..1e2ab75 100644 --- a/g4-min-property-rights.mmd +++ b/g4-min-property-rights.mmd @@ -1,9 +1,38 @@ flowchart TD - A4[P1: Proponer oferta?] -->|No ofrecer| O1[Sin cambios] - A4 -->|Ofrecer| B4[P2: Aceptar / Rechazar / Robar] - B4 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B4 -->|Rechazar| O3[Sin cambios] - B4 -->|Robar| C4[P1: ¿Denunciar?] - C4 -->|No| O4[Transferir solo lo ofrecido a P2] - C4 -->|Sí| J4[AutoJudge revierte robo (confisca oferta a P2)] - J4 --> O5[Restituir oferta a P1] + Start[G4: Derechos mínimos de propiedad] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A4{P1: Ofrecer tokens?} + A4 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A4 -->|Proponer oferta| B4[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B4 --> C4[UI: Ocultar OfferControls
Mostrar detalles oferta] + C4 --> D4{P2: Una sola decisión} + + D4 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D4 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D4 -->|Robar| E4[P2 recibe oferta sin pagar
UI: Ocultar botones P2] + + E4 --> F4{P1: ¿Denunciar al juez?} + F4 -->|No denunciar| O4[Robo exitoso
→ Auto-avance] + F4 -->|Denunciar| J4[⚖️ AutoJudge actúa] + + J4 --> S1[Paso 1 - Revertir robo:
Devolver tokens ofrecidos a P1] + S1 --> S2[Paso 2 - Sanción inversa:
P1 recibe lo pedido sin dar nada
P2 pierde lo pedido] + S2 --> O5[Sanción aplicada
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#b71c1c,stroke:#fff,color:#fff + style Init fill:#c62828,stroke:#fff,color:#fff + style A4 fill:#4527a0,stroke:#fff,color:#fff + style B4 fill:#512da8,stroke:#fff,color:#fff + style C4 fill:#37474f,stroke:#fff,color:#fff + style D4 fill:#455a64,stroke:#fff,color:#fff + style E4 fill:#d32f2f,stroke:#fff,color:#fff + style F4 fill:#e53935,stroke:#fff,color:#fff + style J4 fill:#1b5e20,stroke:#fff,color:#fff + style S1 fill:#2e7d32,stroke:#fff,color:#fff + style S2 fill:#388e3c,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#bf360c,stroke:#fff,color:#fff + style O5 fill:#43a047,stroke:#fff,color:#fff diff --git a/g5-cheap-talk.mmd b/g5-cheap-talk.mmd index 01782a7..45348d1 100644 --- a/g5-cheap-talk.mmd +++ b/g5-cheap-talk.mmd @@ -1,7 +1,26 @@ flowchart TD - Pre[Chat previo 1 min - no vinculante] --> A5[P1: Proponer oferta?] - A5 -->|No ofrecer| O1[Sin cambios] - A5 -->|Ofrecer| B5[P2: Aceptar / Rechazar / Robar] - B5 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B5 -->|Rechazar| O3[Sin cambios] - B5 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G5: Cheap Talk] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> Pre[💬 Chat no vinculante
Ambos jugadores pueden escribir
Sin compromisos] + Pre --> A5{P1: Ofrecer tokens?} + A5 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A5 -->|Proponer oferta| B5[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B5 --> C5[UI: Ocultar OfferControls
Mostrar detalles oferta] + C5 --> D5{P2: Una sola decisión} + + D5 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D5 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D5 -->|Robar| O4[P2 recibe oferta sin pagar
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#004d40,stroke:#fff,color:#fff + style Init fill:#00695c,stroke:#fff,color:#fff + style Pre fill:#00796b,stroke:#fff,color:#fff + style A5 fill:#4527a0,stroke:#fff,color:#fff + style B5 fill:#512da8,stroke:#fff,color:#fff + style C5 fill:#37474f,stroke:#fff,color:#fff + style D5 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff diff --git a/game-design-mermaid.md b/game-design-mermaid.md index c538fb2..66a5a5b 100644 --- a/game-design-mermaid.md +++ b/game-design-mermaid.md @@ -7,13 +7,72 @@ Este índice reúne los diagramas claves para implementar el juego y verificar l ```mermaid %% game-overview.mmd flowchart TD - A[Emparejar jugadores al azar] --> B[Asignar roles P1/P2] - B --> C[Seleccionar variante G1..G5] - C --> D[Iniciar partida de 3 rondas] - D --> R1[Ronda 1] --> R2[Ronda 2] --> R3[Ronda 3] - R3 --> E[Registrar SOLO resultado de R3] - E --> F[Actualizar leaderboard/analytics] - F --> G[Reemparejar y posible cambio de roles] + A[Demo Play] --> B[Asignar roles P1/P2] + B --> C{Jugadores pueden cambiar variante} + C --> |G1| G1[Sin derechos de propiedad] + C --> |G2| G2[Regla contraproductiva] + C --> |G3| G3[Token de repudio] + C --> |G4| G4[Derechos mínimos] + C --> |G5| G5[Cheap talk] + + G1 --> D[P1: 10 pavos, P2: 10 elotes] + G2 --> D + G3 --> D + G4 --> D + G5 --> D + + D --> E[Iniciar ronda] + E --> F{P1 ofrece?
❗G2: Si P2 fuerza, DEBE ofrecer} + F -->|Sí| G[P1 propone oferta variable] + F -->|No| H[No ofrecer → siguiente ronda] + + G --> I{P2 decide} + I -->|Aceptar| J[Intercambiar tokens] + I -->|Rechazar| K[Sin cambios] + I -->|Robar| L[P2 toma oferta sin pagar] + + J --> M[Auto-avance a siguiente ronda] + K --> M + L --> N{Variante especial?} + N -->|G3| O[P1: ¿Asignar vergüenza?] + N -->|G4| P[P1: ¿Denunciar?] + N -->|Otros| M + + O --> M + P --> Q[Sanción: P1 recibe pedido sin dar oferta] + Q --> M + + M --> R{Ronda < 3?} + R -->|Sí| E + R -->|No| S[Fin del juego → Status: FINISHED] + S --> T[Cambiar variante reinicia todo] + + %%{init: {'theme':'dark'}}%% + style A fill:#1a1a2e,stroke:#fff,color:#fff + style B fill:#16213e,stroke:#fff,color:#fff + style C fill:#0f3460,stroke:#fff,color:#fff + style D fill:#1e3a5f,stroke:#fff,color:#fff + style E fill:#2d4059,stroke:#fff,color:#fff + style F fill:#533e85,stroke:#fff,color:#fff + style G fill:#2e7d32,stroke:#fff,color:#fff + style G1 fill:#304ffe,stroke:#fff,color:#fff + style G2 fill:#6a1b9a,stroke:#fff,color:#fff + style G3 fill:#e65100,stroke:#fff,color:#fff + style G4 fill:#b71c1c,stroke:#fff,color:#fff + style G5 fill:#004d40,stroke:#fff,color:#fff + style H fill:#424242,stroke:#fff,color:#fff + style I fill:#1a237e,stroke:#fff,color:#fff + style J fill:#2e7d32,stroke:#fff,color:#fff + style K fill:#757575,stroke:#fff,color:#fff + style L fill:#d32f2f,stroke:#fff,color:#fff + style M fill:#37474f,stroke:#fff,color:#fff + style N fill:#4527a0,stroke:#fff,color:#fff + style O fill:#ff6f00,stroke:#fff,color:#fff + style P fill:#c62828,stroke:#fff,color:#fff + style Q fill:#b71c1c,stroke:#fff,color:#fff + style R fill:#455a64,stroke:#fff,color:#fff + style S fill:#212121,stroke:#fff,color:#fff + style T fill:#263238,stroke:#fff,color:#fff ``` ## Orquestación global (200 jugadores, G1->G5) @@ -62,23 +121,73 @@ flowchart TD ```mermaid %% game-state-machine.mmd stateDiagram-v2 - [*] --> Lobby - Lobby --> Matching : join/ready - Matching --> Setup : asignar roles + variante - Setup --> PreChat : si G5 (cheap talk) - Setup --> Round1 : si no G5 - PreChat --> Round1 : fin ventana chat (1 min) - Round1 --> Round2 : resultado cerrado - Round2 --> Round3 : resultado cerrado - Round3 --> PostGame : resultado cerrado - PostGame --> Commit : registrar solo R3 - Commit --> Rematch : liberar jugadores - Rematch --> [*] - - note right of Round1 - Las decisiones pueden ser: - - Secuenciales (G1,G2,G3,G4,G5) - - Simultáneas (si en el futuro aplica) + [*] --> DemoPlay + + DemoPlay --> Waiting : quickPlay() + Waiting --> Playing : 2 jugadores conectados + + state Playing { + [*] --> VariantSelection + VariantSelection --> RoundActive : seleccionar G1-G5 + + state RoundActive { + [*] --> OfferPhase + + state OfferPhase { + [*] --> CheckForce + CheckForce --> ForcedOffer : G2 && forcedByP2 + CheckForce --> OptionalOffer : !forcedByP2 + ForcedOffer --> ProposeOffer : debe ofrecer + OptionalOffer --> ProposeOffer : ofrecer + OptionalOffer --> NoOffer : no ofrecer + } + + ProposeOffer --> P2Decision : offerActive=true + NoOffer --> NextRound : auto-avance + + state P2Decision { + [*] --> WaitingP2 + WaitingP2 --> Accept : p2Action + WaitingP2 --> Reject : p2Action + WaitingP2 --> Snatch : p2Action + } + + Accept --> TokenExchange : intercambiar + Reject --> NoChange : sin cambios + Snatch --> CheckVariant : robar tokens + + TokenExchange --> NextRound : auto-avance + NoChange --> NextRound : auto-avance + + state CheckVariant { + [*] --> CheckG3G4 + CheckG3G4 --> ShameDecision : G3 + CheckG3G4 --> ReportDecision : G4 + CheckG3G4 --> NextRound : otros + } + + ShameDecision --> NextRound : asignar/no asignar + ReportDecision --> Sanction : denunciar + ReportDecision --> NextRound : no denunciar + Sanction --> NextRound : aplicar sanción inversa + } + + NextRound --> RoundActive : round < 3 + NextRound --> Finished : round = 3 + } + + Finished --> VariantSelection : cambiar variante reinicia + Playing --> Finished : 3 rondas completadas + + note right of VariantSelection + Cualquier jugador puede + cambiar variante en + cualquier momento + end note + + note right of P2Decision + Una sola acción + permitida por oferta end note ``` @@ -87,55 +196,80 @@ stateDiagram-v2 ```mermaid %% game-sequence.mmd sequenceDiagram - participant P1 as Player 1 - participant P2 as Player 2 + participant P1 as Player 1 (10 pavos) + participant P2 as Player 2 (10 elotes) participant S as Server/Room - participant AJ as AutoJudge G4 + participant UI as UI Components - S->>P1: startRound(gameType, roundNo, role=P1) - S->>P2: startRound(gameType, roundNo, role=P2) + Note over P1,P2: Inicio de Demo Play + S->>P1: Asignar rol P1, tokens iniciales + S->>P2: Asignar rol P2, tokens iniciales + + Note over UI: Jugadores pueden cambiar variante en cualquier momento + P1->>S: setVariant(G1-G5) + S->>S: resetRound(), currentRound=1, status=PLAYING + S-->>P1: broadcast variantChanged + S-->>P2: broadcast variantChanged - alt G2 (P2 decide forzar) - P2->>S: decide(force or no_force) - S-->>P1: forcedOffer = true/false - else Otros juegos - Note over P1,P2: Sin decision previa de P2 - end + loop Cada Ronda (1-3) + alt G2 - Regla contraproductiva + Note over P2: Checkbox "Forzar oferta" (activo por defecto) + P2->>S: p2Force(true/false) + S-->>UI: forcedByP2 = true/false + Note over P1: Si forzado, botón "No ofrecer" deshabilitado + end - alt no_offer - P1->>S: noOffer() - S-->>P1: sin cambios de tokens - S-->>P2: sin cambios de tokens - else oferta - P1->>S: proposeOffer({offer:{pavo,elote}, request:{pavo,elote}}) - S-->>P2: offerAvailable - P2->>S: actionP2(accept / reject / snatch) - alt accept - S-->>P1: transfer ambos lados (según oferta/pedido) - S-->>P2: transfer ambos lados (según oferta/pedido) - else reject - S-->>P1: sin cambios - S-->>P2: sin cambios - else snatch - S-->>P2: transferir solo lo ofrecido a P2 - opt G4 denuncia - P1->>S: report: yes or no - alt report=yes - S->>AJ: aplicar sanción - AJ-->>S: confiscar oferta a P2 y revertir a P1 - else report=no - Note over P1,P2: Se mantiene el robo + alt G5 - Cheap talk + Note over P1,P2: Chat no vinculante por 1 minuto + end + + alt P1 decide ofrecer + P1->>S: proposeOffer({offerPavo, offerElote, requestPavo, requestElote}) + S->>S: Validar tokens disponibles + S-->>UI: offerActive = true, ocultar OfferControls + S-->>P2: Mostrar oferta y botones de decisión + + P2->>S: p2Action(accept/reject/snatch) + S->>S: Prevenir múltiples acciones (if p2Action exists, return) + + alt accept + S->>S: Intercambiar tokens ambos lados + S->>S: Auto-avanzar ronda + else reject + S->>S: Sin cambios en tokens + S->>S: Auto-avanzar ronda + else snatch + S->>S: P2 recibe oferta sin pagar + + alt G3 - Token de vergüenza + S-->>UI: Mostrar botones vergüenza a P1 + P1->>S: assignShame(true/false) + alt true + S->>P2: shameTokens += 1 + end + S->>S: Auto-avanzar ronda + else G4 - Derechos mínimos + S-->>UI: Mostrar botones denuncia a P1 + P1->>S: report(true/false) + alt true + S->>S: Revertir robo + S->>S: P1 recibe pedido sin dar oferta (sanción inversa) + end + S->>S: Auto-avanzar ronda + else Otros + S->>S: Auto-avanzar ronda end end - opt G3 repudio - P1->>S: shameToken: assign yes or no - S-->>P2: actualizar contador vergüenza (próxima partida) - end + else P1 no ofrece + P1->>S: noOffer() + S->>S: p1Action = "no_offer" + S->>S: Auto-avanzar ronda end end - S-->>P1: endRound - S-->>P2: endRound + Note over S: Después de ronda 3 + S->>S: gameStatus = FINISHED + Note over UI: Al cambiar variante, reinicia todo ``` ## Variantes de juego @@ -144,64 +278,172 @@ sequenceDiagram ```mermaid %% g1-no-property.mmd flowchart TD - A1[P1: Proponer oferta? (pavos/elotes + pedido)] -->|No ofrecer| O1[Sin cambios] - A1 -->|Ofrecer| B1[P2: Aceptar / Rechazar / Robar] - B1 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B1 -->|Rechazar| O3[Sin cambios] - B1 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G1: Sin derechos de propiedad] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A1{P1: Ofrecer tokens?} + A1 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A1 -->|Proponer oferta| B1[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + B1 --> C1[UI: Ocultar OfferControls
Mostrar oferta a ambos jugadores] + C1 --> D1{P2: Una sola decisión} + D1 -->|Aceptar| O2[Intercambiar tokens:
P1 da oferta, recibe pedido
P2 da pedido, recibe oferta
→ Auto-avance] + D1 -->|Rechazar| O3[Sin cambios en tokens
→ Auto-avance] + D1 -->|Robar| O4[P2 recibe oferta
P1 pierde oferta
Sin pago de P2
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#1a237e,stroke:#fff,color:#fff + style Init fill:#283593,stroke:#fff,color:#fff + style A1 fill:#4527a0,stroke:#fff,color:#fff + style B1 fill:#512da8,stroke:#fff,color:#fff + style C1 fill:#37474f,stroke:#fff,color:#fff + style D1 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff ``` ### G2 – Regla contraproductiva (P2 puede forzar) – oferta variable ```mermaid %% g2-counterproductive-rule.mmd flowchart TD - A2[P2: Forzar?] -->|Sí| F2[P1: Debe proponer oferta] - A2 -->|No| B2[P1: Proponer oferta?] - F2 --> C2[P2: Acción final] - B2 -->|No ofrecer| O1[Sin cambios] - B2 -->|Ofrecer| C2[P2: Aceptar / Rechazar / Robar] - C2 -->|Aceptar| O2[Intercambiar según oferta/pedido] - C2 -->|Rechazar| O3[Sin cambios] - C2 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G2: Regla contraproductiva] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A2[P2: Checkbox 'Forzar oferta'
🔲 Activo por defecto] + A2 -->|forcedByP2 = true| F2[P1 DEBE ofrecer
Botón 'No ofrecer' deshabilitado] + A2 -->|forcedByP2 = false| B2{P1: Ofrecer tokens?} + + F2 --> C2[P1 especifica oferta obligatoria:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + B2 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + B2 -->|Proponer oferta| C2 + + C2 --> D2[UI: Ocultar OfferControls
Mostrar detalles oferta] + D2 --> E2{P2: Una sola decisión} + + E2 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + E2 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + E2 -->|Robar| O4[P2 recibe oferta sin pagar
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#6a1b9a,stroke:#fff,color:#fff + style Init fill:#7b1fa2,stroke:#fff,color:#fff + style A2 fill:#8e24aa,stroke:#fff,color:#fff + style F2 fill:#ab47bc,stroke:#fff,color:#fff + style B2 fill:#4527a0,stroke:#fff,color:#fff + style C2 fill:#512da8,stroke:#fff,color:#fff + style D2 fill:#37474f,stroke:#fff,color:#fff + style E2 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff ``` ### G3 – Token de repudio (vergüenza) – oferta variable ```mermaid %% g3-shame-token.mmd flowchart TD - A3[P1: Proponer oferta?] -->|No ofrecer| O1[Sin cambios] - A3 -->|Ofrecer| B3[P2: Aceptar / Rechazar / Robar] - B3 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B3 -->|Rechazar| O3[Sin cambios] - B3 -->|Robar| C3[P1: Asignar ficha de vergüenza?] - C3 -->|Sí| O4a[+1 vergüenza para P2] - C3 -->|No| O4b[Sin vergüenza] + Start[G3: Token de repudio/vergüenza] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A3{P1: Ofrecer tokens?} + A3 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A3 -->|Proponer oferta| B3[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B3 --> C3[UI: Ocultar OfferControls
Mostrar detalles oferta] + C3 --> D3{P2: Una sola decisión} + + D3 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D3 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D3 -->|Robar| E3[P2 recibe oferta sin pagar
UI: Ocultar botones P2] + + E3 --> F3{P1: ¿Asignar vergüenza?} + F3 -->|Asignar| O4a[P2.shameTokens += 1
😶 Visible en UI
→ Auto-avance] + F3 -->|No asignar| O4b[Sin penalización
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#e65100,stroke:#fff,color:#fff + style Init fill:#ef6c00,stroke:#fff,color:#fff + style A3 fill:#4527a0,stroke:#fff,color:#fff + style B3 fill:#512da8,stroke:#fff,color:#fff + style C3 fill:#37474f,stroke:#fff,color:#fff + style D3 fill:#455a64,stroke:#fff,color:#fff + style E3 fill:#bf360c,stroke:#fff,color:#fff + style F3 fill:#ff6f00,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4a fill:#ff3d00,stroke:#fff,color:#fff + style O4b fill:#616161,stroke:#fff,color:#fff ``` ### G4 – Derechos mínimos de propiedad (juez) – oferta variable ```mermaid %% g4-min-property-rights.mmd flowchart TD - A4[P1: Proponer oferta?] -->|No ofrecer| O1[Sin cambios] - A4 -->|Ofrecer| B4[P2: Aceptar / Rechazar / Robar] - B4 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B4 -->|Rechazar| O3[Sin cambios] - B4 -->|Robar| C4[P1: ¿Denunciar?] - C4 -->|No| O4[Transferir solo lo ofrecido a P2] - C4 -->|Sí| J4[AutoJudge revierte robo (confisca oferta a P2)] - J4 --> O5[Restituir oferta a P1] + Start[G4: Derechos mínimos de propiedad] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> A4{P1: Ofrecer tokens?} + A4 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A4 -->|Proponer oferta| B4[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B4 --> C4[UI: Ocultar OfferControls
Mostrar detalles oferta] + C4 --> D4{P2: Una sola decisión} + + D4 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D4 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D4 -->|Robar| E4[P2 recibe oferta sin pagar
UI: Ocultar botones P2] + + E4 --> F4{P1: ¿Denunciar al juez?} + F4 -->|No denunciar| O4[Robo exitoso
→ Auto-avance] + F4 -->|Denunciar| J4[⚖️ AutoJudge actúa] + + J4 --> S1[Paso 1 - Revertir robo:
Devolver tokens ofrecidos a P1] + S1 --> S2[Paso 2 - Sanción inversa:
P1 recibe lo pedido sin dar nada
P2 pierde lo pedido] + S2 --> O5[Sanción aplicada
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#b71c1c,stroke:#fff,color:#fff + style Init fill:#c62828,stroke:#fff,color:#fff + style A4 fill:#4527a0,stroke:#fff,color:#fff + style B4 fill:#512da8,stroke:#fff,color:#fff + style C4 fill:#37474f,stroke:#fff,color:#fff + style D4 fill:#455a64,stroke:#fff,color:#fff + style E4 fill:#d32f2f,stroke:#fff,color:#fff + style F4 fill:#e53935,stroke:#fff,color:#fff + style J4 fill:#1b5e20,stroke:#fff,color:#fff + style S1 fill:#2e7d32,stroke:#fff,color:#fff + style S2 fill:#388e3c,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#bf360c,stroke:#fff,color:#fff + style O5 fill:#43a047,stroke:#fff,color:#fff ``` ### G5 – Cheap talk (conversación previa) – oferta variable ```mermaid %% g5-cheap-talk.mmd flowchart TD - Pre[Chat previo 1 min - no vinculante] --> A5[P1: Proponer oferta?] - A5 -->|No ofrecer| O1[Sin cambios] - A5 -->|Ofrecer| B5[P2: Aceptar / Rechazar / Robar] - B5 -->|Aceptar| O2[Intercambiar según oferta/pedido] - B5 -->|Rechazar| O3[Sin cambios] - B5 -->|Robar| O4[Transferir solo lo ofrecido a P2] + Start[G5: Cheap Talk] --> Init[P1: 10 pavos
P2: 10 elotes] + Init --> Pre[💬 Chat no vinculante
Ambos jugadores pueden escribir
Sin compromisos] + Pre --> A5{P1: Ofrecer tokens?} + A5 -->|No ofrecer| O1[Sin cambios
→ Siguiente ronda] + A5 -->|Proponer oferta| B5[P1 especifica:
- Ofrecer: X pavos, Y elotes
- Pedir: A pavos, B elotes] + + B5 --> C5[UI: Ocultar OfferControls
Mostrar detalles oferta] + C5 --> D5{P2: Una sola decisión} + + D5 -->|Aceptar| O2[Intercambiar tokens
→ Auto-avance] + D5 -->|Rechazar| O3[Sin cambios
→ Auto-avance] + D5 -->|Robar| O4[P2 recibe oferta sin pagar
→ Auto-avance] + + %%{init: {'theme':'dark'}}%% + style Start fill:#004d40,stroke:#fff,color:#fff + style Init fill:#00695c,stroke:#fff,color:#fff + style Pre fill:#00796b,stroke:#fff,color:#fff + style A5 fill:#4527a0,stroke:#fff,color:#fff + style B5 fill:#512da8,stroke:#fff,color:#fff + style C5 fill:#37474f,stroke:#fff,color:#fff + style D5 fill:#455a64,stroke:#fff,color:#fff + style O1 fill:#424242,stroke:#fff,color:#fff + style O2 fill:#2e7d32,stroke:#fff,color:#fff + style O3 fill:#757575,stroke:#fff,color:#fff + style O4 fill:#d32f2f,stroke:#fff,color:#fff ``` ## Emparejamiento en masa (fase Gx) diff --git a/game-overview.mmd b/game-overview.mmd index c40f8d4..638dfca 100644 --- a/game-overview.mmd +++ b/game-overview.mmd @@ -1,9 +1,68 @@ flowchart TD - A[Emparejar jugadores al azar] --> B[Asignar roles P1/P2] - B --> C[Seleccionar variante G1..G5] - C --> D[Iniciar partida de 3 rondas] - D --> R1[Ronda 1] --> R2[Ronda 2] --> R3[Ronda 3] - R3 --> E[Registrar SOLO resultado de R3] - E --> F[Actualizar leaderboard/analytics] - F --> G[Reemparejar y posible cambio de roles] + A[Demo Play] --> B[Asignar roles P1/P2] + B --> C{Jugadores pueden cambiar variante} + C --> |G1| G1[Sin derechos de propiedad] + C --> |G2| G2[Regla contraproductiva] + C --> |G3| G3[Token de repudio] + C --> |G4| G4[Derechos mínimos] + C --> |G5| G5[Cheap talk] + + G1 --> D[P1: 10 pavos, P2: 10 elotes] + G2 --> D + G3 --> D + G4 --> D + G5 --> D + + D --> E[Iniciar ronda] + E --> F{P1 ofrece?
❗G2: Si P2 fuerza, DEBE ofrecer} + F -->|Sí| G[P1 propone oferta variable] + F -->|No| H[No ofrecer → siguiente ronda] + + G --> I{P2 decide} + I -->|Aceptar| J[Intercambiar tokens] + I -->|Rechazar| K[Sin cambios] + I -->|Robar| L[P2 toma oferta sin pagar] + + J --> M[Auto-avance a siguiente ronda] + K --> M + L --> N{Variante especial?} + N -->|G3| O[P1: ¿Asignar vergüenza?] + N -->|G4| P[P1: ¿Denunciar?] + N -->|Otros| M + + O --> M + P --> Q[Sanción: P1 recibe pedido sin dar oferta] + Q --> M + + M --> R{Ronda < 3?} + R -->|Sí| E + R -->|No| S[Fin del juego → Status: FINISHED] + S --> T[Cambiar variante reinicia todo] + + %%{init: {'theme':'dark'}}%% + style A fill:#1a1a2e,stroke:#fff,color:#fff + style B fill:#16213e,stroke:#fff,color:#fff + style C fill:#0f3460,stroke:#fff,color:#fff + style D fill:#1e3a5f,stroke:#fff,color:#fff + style E fill:#2d4059,stroke:#fff,color:#fff + style F fill:#533e85,stroke:#fff,color:#fff + style G fill:#2e7d32,stroke:#fff,color:#fff + style G1 fill:#304ffe,stroke:#fff,color:#fff + style G2 fill:#6a1b9a,stroke:#fff,color:#fff + style G3 fill:#e65100,stroke:#fff,color:#fff + style G4 fill:#b71c1c,stroke:#fff,color:#fff + style G5 fill:#004d40,stroke:#fff,color:#fff + style H fill:#424242,stroke:#fff,color:#fff + style I fill:#1a237e,stroke:#fff,color:#fff + style J fill:#2e7d32,stroke:#fff,color:#fff + style K fill:#757575,stroke:#fff,color:#fff + style L fill:#d32f2f,stroke:#fff,color:#fff + style M fill:#37474f,stroke:#fff,color:#fff + style N fill:#4527a0,stroke:#fff,color:#fff + style O fill:#ff6f00,stroke:#fff,color:#fff + style P fill:#c62828,stroke:#fff,color:#fff + style Q fill:#b71c1c,stroke:#fff,color:#fff + style R fill:#455a64,stroke:#fff,color:#fff + style S fill:#212121,stroke:#fff,color:#fff + style T fill:#263238,stroke:#fff,color:#fff diff --git a/game-sequence.mmd b/game-sequence.mmd index f531482..5e28a62 100644 --- a/game-sequence.mmd +++ b/game-sequence.mmd @@ -1,55 +1,75 @@ sequenceDiagram - participant P1 as Player 1 - participant P2 as Player 2 + participant P1 as Player 1 (10 pavos) + participant P2 as Player 2 (10 elotes) participant S as Server/Room - participant AJ as AutoJudge G4 + participant UI as UI Components - S->>P1: startRound(gameType, roundNo, role=P1) - S->>P2: startRound(gameType, roundNo, role=P2) + Note over P1,P2: Inicio de Demo Play + S->>P1: Asignar rol P1, tokens iniciales + S->>P2: Asignar rol P2, tokens iniciales + + Note over UI: Jugadores pueden cambiar variante en cualquier momento + P1->>S: setVariant(G1-G5) + S->>S: resetRound(), currentRound=1, status=PLAYING + S-->>P1: broadcast variantChanged + S-->>P2: broadcast variantChanged - alt G2 (P2 decide forzar) - P2->>S: decide(force or no_force) - S-->>P1: forcedOffer = true/false - else Otros juegos - Note over P1,P2: Sin decision previa de P2 - end + loop Cada Ronda (1-3) + alt G2 - Regla contraproductiva + Note over P2: Checkbox "Forzar oferta" (activo por defecto) + P2->>S: p2Force(true/false) + S-->>UI: forcedByP2 = true/false + Note over P1: Si forzado, botón "No ofrecer" deshabilitado + end - P1->>S: actionP1(offer or no_offer) - o forzado en G2 - S-->>P2: notifyP1Action(offer or no_offer) + alt G5 - Cheap talk + Note over P1,P2: Chat no vinculante por 1 minuto + end - alt no_offer - S-->>P1: outcome(10,10) - S-->>P2: outcome(10,10) - else offer - P2->>S: actionP2(accept / reject / snatch) - alt accept - S-->>P1: outcome(15,15) - S-->>P2: outcome(15,15) - else reject - S-->>P1: outcome(10,10) - S-->>P2: outcome(10,10) - else snatch - opt G4 denuncia - P1->>S: report: yes or no - alt report=yes - S->>AJ: aplicar sancion - AJ-->>S: confiscar tokens P2 - S-->>P1: outcome(10,0) - S-->>P2: outcome(10,0) - else report=no - S-->>P1: outcome(5,20) - S-->>P2: outcome(5,20) - end - opt G3 repudio - P1->>S: shameToken: assign yes or no - S-->>P2: actualizar contador verguenza (proxima partida) + alt P1 decide ofrecer + P1->>S: proposeOffer({offerPavo, offerElote, requestPavo, requestElote}) + S->>S: Validar tokens disponibles + S-->>UI: offerActive = true, ocultar OfferControls + S-->>P2: Mostrar oferta y botones de decisión + + P2->>S: p2Action(accept/reject/snatch) + S->>S: Prevenir múltiples acciones (if p2Action exists, return) + + alt accept + S->>S: Intercambiar tokens ambos lados + S->>S: Auto-avanzar ronda + else reject + S->>S: Sin cambios en tokens + S->>S: Auto-avanzar ronda + else snatch + S->>S: P2 recibe oferta sin pagar + + alt G3 - Token de vergüenza + S-->>UI: Mostrar botones vergüenza a P1 + P1->>S: assignShame(true/false) + alt true + S->>P2: shameTokens += 1 + end + S->>S: Auto-avanzar ronda + else G4 - Derechos mínimos + S-->>UI: Mostrar botones denuncia a P1 + P1->>S: report(true/false) + alt true + S->>S: Revertir robo + S->>S: P1 recibe pedido sin dar oferta (sanción inversa) + end + S->>S: Auto-avanzar ronda + else Otros + S->>S: Auto-avanzar ronda end + end + else P1 no ofrece + P1->>S: noOffer() + S->>S: p1Action = "no_offer" + S->>S: Auto-avanzar ronda end end - opt Round3 - persistir resultado R3 - S->>S: actualizar leaderboard y analytics - end - S-->>P1: endRound - S-->>P2: endRound - end + Note over S: Después de ronda 3 + S->>S: gameStatus = FINISHED + Note over UI: Al cambiar variante, reinicia todo diff --git a/game-state-machine.mmd b/game-state-machine.mmd index 3141e46..d000b42 100644 --- a/game-state-machine.mmd +++ b/game-state-machine.mmd @@ -1,20 +1,70 @@ stateDiagram-v2 - [*] --> Lobby - Lobby --> Matching : join/ready - Matching --> Setup : asignar roles + variante - Setup --> PreChat : si G5 (cheap talk) - Setup --> Round1 : si no G5 - PreChat --> Round1 : fin ventana chat (1 min) - Round1 --> Round2 : resultado cerrado - Round2 --> Round3 : resultado cerrado - Round3 --> PostGame : resultado cerrado - PostGame --> Commit : registrar solo R3 - Commit --> Rematch : liberar jugadores - Rematch --> [*] - - note right of Round1 - Las decisiones pueden ser: - - Secuenciales (G1,G2,G3,G4,G5) - - Simultáneas (si en el futuro aplica) + [*] --> DemoPlay + + DemoPlay --> Waiting : quickPlay() + Waiting --> Playing : 2 jugadores conectados + + state Playing { + [*] --> VariantSelection + VariantSelection --> RoundActive : seleccionar G1-G5 + + state RoundActive { + [*] --> OfferPhase + + state OfferPhase { + [*] --> CheckForce + CheckForce --> ForcedOffer : G2 && forcedByP2 + CheckForce --> OptionalOffer : !forcedByP2 + ForcedOffer --> ProposeOffer : debe ofrecer + OptionalOffer --> ProposeOffer : ofrecer + OptionalOffer --> NoOffer : no ofrecer + } + + ProposeOffer --> P2Decision : offerActive=true + NoOffer --> NextRound : auto-avance + + state P2Decision { + [*] --> WaitingP2 + WaitingP2 --> Accept : p2Action + WaitingP2 --> Reject : p2Action + WaitingP2 --> Snatch : p2Action + } + + Accept --> TokenExchange : intercambiar + Reject --> NoChange : sin cambios + Snatch --> CheckVariant : robar tokens + + TokenExchange --> NextRound : auto-avance + NoChange --> NextRound : auto-avance + + state CheckVariant { + [*] --> CheckG3G4 + CheckG3G4 --> ShameDecision : G3 + CheckG3G4 --> ReportDecision : G4 + CheckG3G4 --> NextRound : otros + } + + ShameDecision --> NextRound : asignar/no asignar + ReportDecision --> Sanction : denunciar + ReportDecision --> NextRound : no denunciar + Sanction --> NextRound : aplicar sanción inversa + } + + NextRound --> RoundActive : round < 3 + NextRound --> Finished : round = 3 + } + + Finished --> VariantSelection : cambiar variante reinicia + Playing --> Finished : 3 rondas completadas + + note right of VariantSelection + Cualquier jugador puede + cambiar variante en + cualquier momento + end note + + note right of P2Decision + Una sola acción + permitida por oferta end note