Files
snatchgame/game-design-mermaid.md
josedario87 f89331a3db feat: implement variable token offers and auto-round advancement
- Add variable offer system where P1 can offer any amount of tokens
- Players start with 10 tokens each (P1: pavos, P2: elotes)
- Implement offer/request mechanism with token validation
- Auto-advance rounds after P2 actions or P1 no-offer
- G2: Force offer by default, disable no-offer button when forced
- G3: Wait for shame decision after snatch before advancing
- G4: Implement inverse sanction (P1 gets requested without giving offered)
- Reset rounds to 1 when changing game variants
- Fix OfferControls responsiveness issues
- Hide offer controls after active offer
- Update all G1-G5 components with proper offer flow
2025-08-07 23:53:18 -06:00

283 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SnatchGame Diagramas Mermaid
Este índice reúne los diagramas claves para implementar el juego y verificar los flujos. Puedes abrir cada `.mmd` con la extensión oficial de Mermaid o verlos embebidos abajo.
## Visión general del ciclo
```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]
```
## Orquestación global (200 jugadores, G1->G5)
```mermaid
%% tournament-orchestration.mmd
flowchart TD
Start[Init torneo] --> PhaseG1[Phase G1: iniciar]
PhaseG1 --> MatchG1[Emparejar 200 jugadores al azar]
MatchG1 --> RoomsG1[Crear rooms P1-P2 y asignar roles]
RoomsG1 --> PlayG1[Jugar 3 rondas en paralelo]
PlayG1 --> CommitG1[Commit solo resultado de ronda 3]
CommitG1 --> WaitAllG1[Esperar que TODOS terminen]
WaitAllG1 --> RematchG2[Reemparejar todos al azar]
RematchG2 --> PhaseG2[Phase G2: iniciar]
PhaseG2 --> MatchG2[Emparejar 200 jugadores al azar]
MatchG2 --> RoomsG2[Crear rooms y roles]
RoomsG2 --> PlayG2[Jugar 3 rondas en paralelo]
PlayG2 --> CommitG2[Commit ronda 3]
CommitG2 --> WaitAllG2[Esperar TODOS]
WaitAllG2 --> RematchG3[Reemparejar]
RematchG3 --> PhaseG3[Phase G3: iniciar]
PhaseG3 --> MatchG3
MatchG3 --> RoomsG3
RoomsG3 --> PlayG3
PlayG3 --> CommitG3
CommitG3 --> WaitAllG3
WaitAllG3 --> RematchG4
RematchG4 --> PhaseG4[Phase G4: iniciar]
PhaseG4 --> MatchG4
MatchG4 --> RoomsG4
RoomsG4 --> PlayG4
PlayG4 --> CommitG4
CommitG4 --> WaitAllG4
WaitAllG4 --> RematchG5
RematchG5 --> PhaseG5[Phase G5: iniciar]
PhaseG5 --> MatchG5
MatchG5 --> RoomsG5
RoomsG5 --> PlayG5
PlayG5 --> CommitG5
CommitG5 --> End[Fin del torneo]
```
## Máquina de estados (Room/Partida)
```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)
end note
```
## Secuencia por ronda (cliente-servidor)
```mermaid
%% game-sequence.mmd
sequenceDiagram
participant P1 as Player 1
participant P2 as Player 2
participant S as Server/Room
participant AJ as AutoJudge G4
S->>P1: startRound(gameType, roundNo, role=P1)
S->>P2: startRound(gameType, roundNo, role=P2)
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
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
end
end
opt G3 repudio
P1->>S: shameToken: assign yes or no
S-->>P2: actualizar contador vergüenza (próxima partida)
end
end
end
S-->>P1: endRound
S-->>P2: endRound
```
## Variantes de juego
### G1 Sin derechos de propiedad (oferta variable)
```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]
```
### 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]
```
### 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]
```
### 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]
```
### 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]
```
## Emparejamiento en masa (fase Gx)
```mermaid
%% matchmaking.mmd
sequenceDiagram
participant OR as Orchestrator
participant MM as Matchmaker
participant P as PlayerPool
participant R as RoomFactory
OR->>MM: start phase (Gx) for ALL
MM->>P: collect all available players (200)
MM->>P: shuffle randomly
loop pair players
MM->>R: create room with pair (P1,P2) and roles
R-->>MM: roomId
end
MM-->>OR: rooms created for all pairs
OR->>R: broadcast startRound(1) to all rooms
```
## Modelo de datos (mínimo)
```mermaid
%% data-model.mmd
classDiagram
class Player {
+string id
+string name
+int pavoTokens // tokens tipo P1
+int eloteTokens // tokens tipo P2
+number shameTokens // visible en próxima partida
}
note for Player "Scoring: como P1 => pavo*1 + elote*2; como P2 => elote*1 + pavo*2; total = suma"
class GameSession {
+string id
+string gameType // G1..G5
+string player1Id
+string player2Id
+int currentRound // 1..3
+Round[] rounds // length=3
+Date createdAt
}
class Round {
+int index // 1,2,3
+string p1Action // offer|no_offer|forced_offer
+string p2Action // accept|reject|snatch|null
+boolean forcedByP2 // G2
+boolean reported // G4
+boolean shameAssigned // G3
+number outcomeP1
+number outcomeP2
+boolean isThird
}
class LeaderboardEntry {
+string playerId
+number scoreAsP1 // P1: pavo*1 + elote*2
+number scoreAsP2 // P2: elote*1 + pavo*2
+number aggregateScore // scoreAsP1 + scoreAsP2
+Date updatedAt
}
Player "1" -- "0..*" GameSession : participa
GameSession "1" o-- "3" Round : incluye
Player "1" -- "0..*" LeaderboardEntry : puntuación
```
---
Notas:
- Solo el resultado de la R3 se agrega al leaderboard/analytics.
- G2 introduce `forcedByP2`; G3, `shameAssigned` y contador visible en la siguiente partida; G4, `reported` y sanción del juez.
- El servidor es autoritativo; clientes no mutan estado.