From e3cb0ccd38ae73a25cce6044eb0b2ed51b1a01c2 Mon Sep 17 00:00:00 2001 From: Mariano Gappa Date: Tue, 23 Jul 2024 21:24:23 +0100 Subject: [PATCH] Fix issue with finishing game showing envido score. --- truco/action_any_quiero.go | 6 +++--- truco/truco.go | 28 +++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/truco/action_any_quiero.go b/truco/action_any_quiero.go index f69a1c8..a58671b 100644 --- a/truco/action_any_quiero.go +++ b/truco/action_any_quiero.go @@ -47,9 +47,6 @@ func (a ActionSayEnvidoScore) IsPossible(g GameState) bool { } func (a ActionRevealEnvidoScore) IsPossible(g GameState) bool { - if !g.IsRoundFinished { - return false - } if !g.EnvidoSequence.WasAccepted() { return false } @@ -60,6 +57,9 @@ func (a ActionRevealEnvidoScore) IsPossible(g GameState) bool { if roundLog.EnvidoWinnerPlayerID != a.PlayerID { return false } + if !g.IsRoundFinished && g.Players[a.PlayerID].Score+roundLog.EnvidoPoints < MaxPoints { + return false + } revealedHand := Hand{Revealed: g.Players[a.PlayerID].Hand.Revealed} return revealedHand.EnvidoScore() != g.Players[a.PlayerID].Hand.EnvidoScore() } diff --git a/truco/truco.go b/truco/truco.go index 683ec39..a50bc0e 100644 --- a/truco/truco.go +++ b/truco/truco.go @@ -7,6 +7,10 @@ import ( "log" ) +// MaxPoints is the points a player must reach to win the game. +// It is set as a const in case support for 15 points games is needed in the future. +const MaxPoints = 30 + // GameState represents the state of a Truco game. It is the central struct to this package. // // If you want to implement a client, you should look at ClientGameState instead. @@ -65,7 +69,7 @@ type GameState struct { IsRoundFinished bool `json:"isRoundFinished"` // IsGameEnded is true if the whole game is ended, rather than an individual round. This happens when - // a player reaches 30 points. + // a player reaches MaxPoints points. IsGameEnded bool `json:"isGameEnded"` // WinnerPlayerID is the player ID of the player who won the game. This is only set when `IsGameEnded` is @@ -94,7 +98,7 @@ type Player struct { // Hands contains the revealed and unrevealed cards of the player. Hand *Hand `json:"hand"` - // Score is the player's scores (from 0 to 30). + // Score is the player's scores (from 0 to MaxPoints). Score int `json:"score"` } @@ -229,8 +233,8 @@ func (g *GameState) RunAction(action Action) error { // Handle end of game due to score for playerID := range g.Players { - if g.Players[playerID].Score >= 30 { - g.Players[playerID].Score = 30 + if g.Players[playerID].Score >= MaxPoints { + g.Players[playerID].Score = MaxPoints g.IsGameEnded = true g.WinnerPlayerID = playerID } @@ -312,6 +316,7 @@ var ( ) func (g GameState) CalculatePossibleActions() []Action { + envidoScore := g.Players[g.TurnPlayerID].Hand.EnvidoScore() opponentEnvidoScore := g.Players[g.TurnOpponentPlayerID].Hand.EnvidoScore() @@ -348,6 +353,19 @@ func (g GameState) CalculatePossibleActions() []Action { NewActionRevealEnvidoScore(g.TurnOpponentPlayerID, opponentEnvidoScore), ) + // The reveal_envido_score action happens in two cases: + // 1. Round has ended and player hasn't shown envido score yet + // 2. Round is going on, but player would win the game by revealing the score + // + // In both cases, this should be the only action available. So don't check others. + actionRevealEnvidoScore := NewActionRevealEnvidoScore(g.TurnPlayerID, envidoScore) + if actionRevealEnvidoScore.IsPossible(g) { + allActions = []Action{ + actionRevealEnvidoScore, + NewActionRevealEnvidoScore(g.TurnOpponentPlayerID, opponentEnvidoScore), + } + } + possibleActions := []Action{} for _, action := range allActions { if action.IsPossible(g) { @@ -526,7 +544,7 @@ type ClientGameState struct { PossibleActions []json.RawMessage `json:"possibleActions"` // IsGameEnded is true if the whole game is ended, rather than an individual round. This happens when - // a player reaches 30 points. + // a player reaches MaxPoints points. IsGameEnded bool `json:"isGameEnded"` IsRoundFinished bool `json:"isRoundFinished"`