Skip to content

Commit

Permalink
Award envido points when envido is revealed.
Browse files Browse the repository at this point in the history
  • Loading branch information
marianogappa committed Jul 19, 2024
1 parent 7fc169e commit 9034e13
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 32 deletions.
5 changes: 3 additions & 2 deletions main_wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ func trucoRunAction(this js.Value, p []js.Value) interface{} {

func trucoBotRunAction(this js.Value, p []js.Value) interface{} {
action := bot.ChooseAction(state.ToClientGameState(1))
fmt.Println("Action chosen by bot:", action)

err := state.RunAction(action)
if err != nil {
panic(err)
panic(fmt.Errorf("running action: %w", err))
}
nbs, err := json.Marshal(state.ToClientGameState(0))
if err != nil {
panic(err)
panic(fmt.Errorf("marshalling game state: %w", err))
}

buffer := js.Global().Get("Uint8Array").New(len(nbs))
Expand Down
30 changes: 22 additions & 8 deletions truco/action_any_quiero.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func (a ActionRevealEnvidoScore) IsPossible(g GameState) bool {
if !g.EnvidoSequence.WasAccepted() {
return false
}
if g.EnvidoSequence.EnvidoPointsAwarded {
return false
}
roundLog := g.RoundsLog[g.RoundNumber]
if roundLog.EnvidoWinnerPlayerID != a.PlayerID {
return false
Expand All @@ -67,10 +70,14 @@ func (a ActionSayTrucoQuiero) IsPossible(g GameState) bool {
}
// Edge case: Truco -> Envido -> ???
// In this case, until envido is resolved, truco cannot continue
actionEnvidoQuiero := ActionSayEnvidoQuiero{act: act{Name: SAY_ENVIDO_QUIERO}}
actionSonBuenas := ActionSaySonBuenas{act: act{Name: SAY_SON_BUENAS}}
actionSonMejores := ActionSaySonMejores{act: act{Name: SAY_SON_MEJORES}}
if actionEnvidoQuiero.IsPossible(g) || actionSonBuenas.IsPossible(g) || actionSonMejores.IsPossible(g) {
var (
me = a.PlayerID
isEnvidoQuieroPossible = NewActionSayEnvidoQuiero(me).IsPossible(g)
isSonBuenasPossible = NewActionSaySonBuenas(me).IsPossible(g)
isSonMejoresPossible = NewActionSaySonMejores(0, me).IsPossible(g)
isSayEnvidoScorePossible = NewActionSayEnvidoScore(0, me).IsPossible(g)
)
if isEnvidoQuieroPossible || isSonBuenasPossible || isSonMejoresPossible || isSayEnvidoScorePossible {
return false
}

Expand All @@ -83,10 +90,14 @@ func (a ActionSayTrucoNoQuiero) IsPossible(g GameState) bool {
}
// Edge case: Truco -> Envido -> ???
// In this case, until envido is resolved, truco cannot continue
actionEnvidoQuiero := ActionSayEnvidoQuiero{act: act{Name: SAY_ENVIDO_QUIERO}}
actionSonBuenas := ActionSaySonBuenas{act: act{Name: SAY_SON_BUENAS}}
actionSonMejores := ActionSaySonMejores{act: act{Name: SAY_SON_MEJORES}}
if actionEnvidoQuiero.IsPossible(g) || actionSonBuenas.IsPossible(g) || actionSonMejores.IsPossible(g) {
var (
me = a.PlayerID
isEnvidoQuieroPossible = NewActionSayEnvidoQuiero(me).IsPossible(g)
isSonBuenasPossible = NewActionSaySonBuenas(me).IsPossible(g)
isSonMejoresPossible = NewActionSaySonMejores(0, me).IsPossible(g)
isSayEnvidoScorePossible = NewActionSayEnvidoScore(0, me).IsPossible(g)
)
if isEnvidoQuieroPossible || isSonBuenasPossible || isSonMejoresPossible || isSayEnvidoScorePossible {
return false
}

Expand Down Expand Up @@ -165,6 +176,9 @@ func (a ActionRevealEnvidoScore) Run(g *GameState) error {
}
// replace hand with our satisfactory candidate hand
g.Players[a.PlayerID].Hand = &candidateHand
if !g.tryAwardEnvidoPoints() {
return fmt.Errorf("couldn't award envido score after running reveal envido score action due to a bug, this code should be unreachable")
}
return nil
}
}
Expand Down
11 changes: 9 additions & 2 deletions truco/action_reveal_card.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package truco

type ActionRevealCard struct {
act
Card Card `json:"card"`
Card Card `json:"card"`
EnMesa bool `json:"en_mesa"`
Score int `json:"score"`
}

func (a ActionRevealCard) IsPossible(g GameState) bool {
Expand All @@ -27,7 +29,7 @@ func (a ActionRevealCard) IsPossible(g GameState) bool {
return g.CardRevealSequence.CanAddStep(step, g)
}

func (a ActionRevealCard) Run(g *GameState) error {
func (a *ActionRevealCard) Run(g *GameState) error {
if !a.IsPossible(*g) {
return errActionNotPossible
}
Expand Down Expand Up @@ -64,6 +66,11 @@ func (a ActionRevealCard) Run(g *GameState) error {
if !g.IsEnvidoFinished && len(g.Players[g.TurnPlayerID].Hand.Revealed) >= 1 && len(g.Players[g.TurnOpponentPlayerID].Hand.Revealed) >= 1 {
g.IsEnvidoFinished = true
}
// Revealing a card may cause the envido score to be revealed
if g.tryAwardEnvidoPoints() {
a.EnMesa = true
a.Score = g.Players[a.PlayerID].Hand.EnvidoScore() // it must be the action's player
}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion truco/action_son_buenas.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (a ActionSaySonBuenas) Run(g *GameState) error {
g.RoundsLog[g.RoundNumber].EnvidoPoints = cost
g.RoundsLog[g.RoundNumber].EnvidoWinnerPlayerID = g.TurnOpponentPlayerID
g.IsEnvidoFinished = true
g.Players[g.TurnOpponentPlayerID].Score += cost
g.tryAwardEnvidoPoints()
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion truco/action_son_mejores.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (a ActionSaySonMejores) Run(g *GameState) error {
g.RoundsLog[g.RoundNumber].EnvidoPoints = cost
g.RoundsLog[g.RoundNumber].EnvidoWinnerPlayerID = g.TurnPlayerID
g.IsEnvidoFinished = true
g.Players[g.TurnPlayerID].Score += cost
g.tryAwardEnvidoPoints()
return nil
}

Expand Down
34 changes: 17 additions & 17 deletions truco/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,69 +26,69 @@ func (a act) YieldsTurn(g GameState) bool {
}

func NewActionSayEnvido(playerID int) Action {
return ActionSayEnvido{act: act{Name: SAY_ENVIDO, PlayerID: playerID}}
return &ActionSayEnvido{act: act{Name: SAY_ENVIDO, PlayerID: playerID}}
}

func NewActionSayRealEnvido(playerID int) Action {
return ActionSayRealEnvido{act: act{Name: SAY_REAL_ENVIDO, PlayerID: playerID}}
return &ActionSayRealEnvido{act: act{Name: SAY_REAL_ENVIDO, PlayerID: playerID}}
}

func NewActionSayFaltaEnvido(playerID int) Action {
return ActionSayFaltaEnvido{act: act{Name: SAY_FALTA_ENVIDO, PlayerID: playerID}}
return &ActionSayFaltaEnvido{act: act{Name: SAY_FALTA_ENVIDO, PlayerID: playerID}}
}

func NewActionSayEnvidoNoQuiero(playerID int) Action {
return ActionSayEnvidoNoQuiero{act: act{Name: SAY_ENVIDO_NO_QUIERO, PlayerID: playerID}}
return &ActionSayEnvidoNoQuiero{act: act{Name: SAY_ENVIDO_NO_QUIERO, PlayerID: playerID}}
}

func NewActionSayEnvidoQuiero(playerID int) Action {
return ActionSayEnvidoQuiero{act: act{Name: SAY_ENVIDO_QUIERO, PlayerID: playerID}}
return &ActionSayEnvidoQuiero{act: act{Name: SAY_ENVIDO_QUIERO, PlayerID: playerID}}
}

func NewActionSayEnvidoScore(score int, playerID int) Action {
return ActionSayEnvidoScore{act: act{Name: SAY_ENVIDO_SCORE, PlayerID: playerID}, Score: score}
return &ActionSayEnvidoScore{act: act{Name: SAY_ENVIDO_SCORE, PlayerID: playerID}, Score: score}
}

func NewActionSayTrucoQuiero(playerID int) Action {
return ActionSayTrucoQuiero{act: act{Name: SAY_TRUCO_QUIERO, PlayerID: playerID}}
return &ActionSayTrucoQuiero{act: act{Name: SAY_TRUCO_QUIERO, PlayerID: playerID}}
}

func NewActionSayTrucoNoQuiero(playerID int) Action {
return ActionSayTrucoNoQuiero{act: act{Name: SAY_TRUCO_NO_QUIERO, PlayerID: playerID}}
return &ActionSayTrucoNoQuiero{act: act{Name: SAY_TRUCO_NO_QUIERO, PlayerID: playerID}}
}

func NewActionSayTruco(playerID int) Action {
return ActionSayTruco{act: act{Name: SAY_TRUCO, PlayerID: playerID}}
return &ActionSayTruco{act: act{Name: SAY_TRUCO, PlayerID: playerID}}
}

func NewActionSayQuieroRetruco(playerID int) Action {
return ActionSayQuieroRetruco{act: act{Name: SAY_QUIERO_RETRUCO, PlayerID: playerID}}
return &ActionSayQuieroRetruco{act: act{Name: SAY_QUIERO_RETRUCO, PlayerID: playerID}}
}

func NewActionSayQuieroValeCuatro(playerID int) Action {
return ActionSayQuieroValeCuatro{act: act{Name: SAY_QUIERO_VALE_CUATRO, PlayerID: playerID}}
return &ActionSayQuieroValeCuatro{act: act{Name: SAY_QUIERO_VALE_CUATRO, PlayerID: playerID}}
}

func NewActionSaySonBuenas(playerID int) Action {
return ActionSaySonBuenas{act: act{Name: SAY_SON_BUENAS, PlayerID: playerID}}
return &ActionSaySonBuenas{act: act{Name: SAY_SON_BUENAS, PlayerID: playerID}}
}

func NewActionSaySonMejores(score int, playerID int) Action {
return ActionSaySonMejores{act: act{Name: SAY_SON_MEJORES, PlayerID: playerID}, Score: score}
return &ActionSaySonMejores{act: act{Name: SAY_SON_MEJORES, PlayerID: playerID}, Score: score}
}

func NewActionRevealCard(card Card, playerID int) Action {
return ActionRevealCard{act: act{Name: REVEAL_CARD, PlayerID: playerID}, Card: card}
return &ActionRevealCard{act: act{Name: REVEAL_CARD, PlayerID: playerID}, Card: card}
}

func NewActionSayMeVoyAlMazo(playerID int) Action {
return ActionSayMeVoyAlMazo{act: act{Name: SAY_ME_VOY_AL_MAZO, PlayerID: playerID}}
return &ActionSayMeVoyAlMazo{act: act{Name: SAY_ME_VOY_AL_MAZO, PlayerID: playerID}}
}

func NewActionConfirmRoundFinished(playerID int) Action {
return ActionConfirmRoundFinished{act: act{Name: CONFIRM_ROUND_FINISHED, PlayerID: playerID}}
return &ActionConfirmRoundFinished{act: act{Name: CONFIRM_ROUND_FINISHED, PlayerID: playerID}}
}

func NewActionRevealEnvidoScore(playerID int, score int) Action {
return ActionRevealEnvidoScore{act: act{Name: REVEAL_ENVIDO_SCORE, PlayerID: playerID}, Score: score}
return &ActionRevealEnvidoScore{act: act{Name: REVEAL_ENVIDO_SCORE, PlayerID: playerID}, Score: score}
}
7 changes: 7 additions & 0 deletions truco/envido_sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ type EnvidoSequence struct {
// This is necessary because when son_buenas/son_mejores/no_quiero is said,
// the turn goes to whoever started the envido sequence (i.e. affects YieldsTurn)
StartingPlayerID int `json:"startingPlayerID"`

// EnvidoPointsAwarded is used to determine if the points have already been awarded.
//
// When an envido is won, points are not automatically awarded. They are when the
// winning score is revealed. This could be at the time it is won, but normally
// it is revealed later.
EnvidoPointsAwarded bool `json:"envidoPointsAwarded"`
}

func (es EnvidoSequence) String() string {
Expand Down
33 changes: 32 additions & 1 deletion truco/truco.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,31 @@ func (g *GameState) PrettyPrint() (string, error) {
return string(prettyJSON), nil
}

func (g *GameState) canAwardEnvidoPoints(revealedHand Hand) bool {
wonBy := g.RoundsLog[g.RoundNumber].EnvidoWinnerPlayerID
if wonBy == -1 {
return false
}
if g.EnvidoSequence.EnvidoPointsAwarded {
return false
}
if revealedHand.EnvidoScore() != g.Players[wonBy].Hand.EnvidoScore() {
return false
}
return true
}

func (g *GameState) tryAwardEnvidoPoints() bool {
if !g.canAwardEnvidoPoints(Hand{Revealed: g.Players[g.TurnPlayerID].Hand.Revealed}) {
return false
}
wonBy := g.RoundsLog[g.RoundNumber].EnvidoWinnerPlayerID
score := g.RoundsLog[g.RoundNumber].EnvidoPoints
g.Players[wonBy].Score += score
g.EnvidoSequence.EnvidoPointsAwarded = true
return true
}

type Action interface {
IsPossible(g GameState) bool
Run(g *GameState) error
Expand All @@ -290,7 +315,13 @@ func (g GameState) CalculatePossibleActions() []Action {
allActions := []Action{}

for _, card := range g.Players[g.TurnPlayerID].Hand.Unrevealed {
allActions = append(allActions, NewActionRevealCard(card, g.TurnPlayerID))
revealCard := NewActionRevealCard(card, g.TurnPlayerID).(*ActionRevealCard)
// If revealing a card would award envido points, then set the score in the action
if g.canAwardEnvidoPoints(Hand{Revealed: append(g.Players[g.TurnPlayerID].Hand.Revealed, card)}) {
revealCard.EnMesa = true
revealCard.Score = g.Players[g.TurnPlayerID].Hand.EnvidoScore()
}
allActions = append(allActions, revealCard)
}

allActions = append(allActions,
Expand Down

0 comments on commit 9034e13

Please sign in to comment.