Skip to content

Commit

Permalink
Fix bug where points were calculated wrong upon me_voy_al_mazo.
Browse files Browse the repository at this point in the history
  • Loading branch information
marianogappa committed Jul 24, 2024
1 parent e3cb0cc commit b1df69a
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 38 deletions.
5 changes: 1 addition & 4 deletions truco/action_any_quiero.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,7 @@ func (a ActionSayTrucoNoQuiero) Run(g *GameState) error {
}
g.TrucoSequence.AddStep(a.GetName())
g.IsRoundFinished = true
cost, err := g.TrucoSequence.Cost()
if err != nil {
return err
}
cost := g.TrucoSequence.Cost()
g.RoundsLog[g.RoundNumber].TrucoPoints = cost
g.RoundsLog[g.RoundNumber].TrucoWinnerPlayerID = g.TurnOpponentPlayerID
g.Players[g.TurnOpponentPlayerID].Score += cost
Expand Down
37 changes: 23 additions & 14 deletions truco/action_me_voy_al_mazo.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,30 @@ func (a ActionSayMeVoyAlMazo) IsPossible(g GameState) bool {
}

func (a ActionSayMeVoyAlMazo) Run(g *GameState) error {
var cost int
if g.TrucoSequence.IsEmpty() && g.IsEnvidoFinished {
// Envido is finished, so either the envido cost was updated already, or it's zero
cost = 1
}
if g.EnvidoSequence.IsEmpty() && g.TrucoSequence.IsEmpty() && !g.IsEnvidoFinished {
cost = 2
}
if g.IsEnvidoFinished && !g.TrucoSequence.IsEmpty() {
var err error
cost, err = g.TrucoSequence.Cost()
if err != nil {
return err
cost := func() int {
if g.TrucoSequence.IsEmpty() {
if g.IsEnvidoFinished {
// In this case:
// - Envido was played, "no quiero" happened and score was updated already.
// - Envido was played, "quiero" happened and score either was or will be updated after this.
// - Envido wasn't played, and it "expired" after first faceoff.
//
// In all cases, the cost is 0 for envido, so just 1 point for truco.
return 1
}
// Envido is not finished. This can only happen if it wasn't played but can still be.
// So the cost is 1 point for envido and 1 point for truco.
return 2
}
}
// If truco was played, let's start by calculating its cost
_cost := g.TrucoSequence.Cost()
// If envido wasn't finished (wasn't played but can still be), we must add 1 point
if !g.IsEnvidoFinished {
_cost++
}
return _cost
}()

g.RoundsLog[g.RoundNumber].TrucoPoints = cost
g.RoundsLog[g.RoundNumber].TrucoWinnerPlayerID = g.TurnOpponentPlayerID
g.Players[g.TurnOpponentPlayerID].Score += cost
Expand Down
75 changes: 75 additions & 0 deletions truco/action_me_voy_al_mazo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package truco

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestScoreAfterMeVoyAlMazo(t *testing.T) {
type testStep struct {
action Action
expectedScorePlayer0AfterRunning int
expectedScorePlayer1AfterRunning int
}

tests := []struct {
name string
hands []Hand
steps []testStep
}{
{
name: "quiero_vale_cuatro_accepted_leads_to_5_points",
steps: []testStep{
{
action: NewActionSayTruco(0),
expectedScorePlayer0AfterRunning: 0,
expectedScorePlayer1AfterRunning: 0,
},
{
action: NewActionSayQuieroRetruco(1),
expectedScorePlayer0AfterRunning: 0,
expectedScorePlayer1AfterRunning: 0,
},
{
action: NewActionSayQuieroValeCuatro(0),
expectedScorePlayer0AfterRunning: 0,
expectedScorePlayer1AfterRunning: 0,
},
{
action: NewActionSayTrucoQuiero(1),
expectedScorePlayer0AfterRunning: 0,
expectedScorePlayer1AfterRunning: 0,
},
{
action: NewActionSayMeVoyAlMazo(0),
expectedScorePlayer0AfterRunning: 0,
expectedScorePlayer1AfterRunning: 5, // 1 for envido, 4 for vale cuatro
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defaultHands := []Hand{
{Unrevealed: []Card{{Number: 1, Suit: ORO}, {Number: 2, Suit: ORO}, {Number: 3, Suit: ORO}}},
{Unrevealed: []Card{{Number: 4, Suit: ORO}, {Number: 5, Suit: ORO}, {Number: 6, Suit: ORO}}},
}
if len(tt.hands) == 0 {
tt.hands = defaultHands
}
gameState := New(withDeck(newTestDeck(tt.hands)))

require.Equal(t, 0, gameState.TurnPlayerID)

for i, step := range tt.steps {
err := gameState.RunAction(step.action)
require.NoError(t, err)
assert.Equal(t, step.expectedScorePlayer0AfterRunning, gameState.Players[0].Score, "at step %v expected player 0's score to be %v but got %v", i, step.expectedScorePlayer0AfterRunning, gameState.Players[0].Score)
assert.Equal(t, step.expectedScorePlayer1AfterRunning, gameState.Players[1].Score, "at step %v expected player 1's score to be %v but got %v", i, step.expectedScorePlayer1AfterRunning, gameState.Players[1].Score)
}
})
}
}
6 changes: 1 addition & 5 deletions truco/action_reveal_card.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ func (a *ActionRevealCard) Run(g *GameState) error {
if g.TrucoSequence.IsEmpty() {
score = 1
} else {
cost, err := g.TrucoSequence.Cost()
if err != nil {
return err
}
score = cost
score = g.TrucoSequence.Cost()
}

g.Players[g.CardRevealSequence.WinnerPlayerID()].Score += score
Expand Down
4 changes: 4 additions & 0 deletions truco/action_son_mejores.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,9 @@ func (a ActionSaySonMejores) Run(g *GameState) error {

func (a ActionSaySonMejores) YieldsTurn(g GameState) bool {
// In son_buenas/son_mejores/no_quiero, the turn should go to whoever started the sequence
// Unless the game should end due to the points won by this action.
if g.Players[a.PlayerID].Score+g.RoundsLog[g.RoundNumber].EnvidoPoints >= MaxPoints {
return false
}
return g.TurnPlayerID != g.EnvidoSequence.StartingPlayerID
}
18 changes: 5 additions & 13 deletions truco/truco_sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ const (
SAY_QUIERO_VALE_CUATRO = "say_quiero_vale_cuatro"
SAY_TRUCO_QUIERO = "say_truco_quiero"
SAY_TRUCO_NO_QUIERO = "say_truco_no_quiero"

TRUCO_COST_NOT_READY = -1
)

var (
validTrucoSequenceCosts = map[string]int{
SAY_TRUCO: COST_NOT_READY,
fmt.Sprintf("%s,%s", SAY_TRUCO, SAY_QUIERO_RETRUCO): COST_NOT_READY,
fmt.Sprintf("%s,%s,%s", SAY_TRUCO, SAY_QUIERO_RETRUCO, SAY_QUIERO_VALE_CUATRO): COST_NOT_READY,
SAY_TRUCO: 1,
fmt.Sprintf("%s,%s", SAY_TRUCO, SAY_QUIERO_RETRUCO): 2,
fmt.Sprintf("%s,%s,%s", SAY_TRUCO, SAY_QUIERO_RETRUCO, SAY_QUIERO_VALE_CUATRO): 3,
fmt.Sprintf("%s,%s", SAY_TRUCO, SAY_TRUCO_QUIERO): 2,
fmt.Sprintf("%s,%s,%s", SAY_TRUCO, SAY_TRUCO_QUIERO, SAY_QUIERO_RETRUCO): 2,
fmt.Sprintf("%s,%s,%s", SAY_TRUCO, SAY_QUIERO_RETRUCO, SAY_TRUCO_QUIERO): 3,
Expand Down Expand Up @@ -93,14 +91,8 @@ func (ts *TrucoSequence) IsFinished() bool {
return last == SAY_TRUCO_QUIERO || last == SAY_TRUCO_NO_QUIERO
}

func (ts TrucoSequence) Cost() (int, error) {
if !ts.isValid() {
return COST_NOT_READY, errInvalidTrucoSequence
}
if !ts.IsFinished() {
return COST_NOT_READY, errUnfinishedTrucoSequence
}
return validTrucoSequenceCosts[ts.String()], nil
func (ts TrucoSequence) Cost() int {
return validTrucoSequenceCosts[ts.String()]
}

func (ts TrucoSequence) IsSubsequenceStart() bool {
Expand Down
3 changes: 1 addition & 2 deletions truco/truco_sequence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ func TestTrucoSequence(t *testing.T) {
continue
}

cost, err := gameState.TrucoSequence.Cost()
require.NoError(t, err)
cost := gameState.TrucoSequence.Cost()
assert.Equal(t, step.expectedCostAfterRunning, cost, "at step %v expected cost %v but got %v", i, step.expectedCostAfterRunning, cost)
}
})
Expand Down

0 comments on commit b1df69a

Please sign in to comment.