Skip to content

Commit

Permalink
Merge pull request #7 from marianogappa/calculate-all-actions
Browse files Browse the repository at this point in the history
Calculate all actions, not just one per type.
  • Loading branch information
marianogappa authored Jun 25, 2024
2 parents 805658e + a7d3ab3 commit 91c4cab
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 94 deletions.
80 changes: 22 additions & 58 deletions exampleclient/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ func (u *ui) Close() {
}

func (u *ui) play(playerID int, gameState truco.GameState) (truco.Action, error) {
err := u.render(playerID, gameState, PRINT_MODE_NORMAL)
if err != nil {
if err := u.render(playerID, gameState, PRINT_MODE_NORMAL); err != nil {
return nil, err
}

Expand All @@ -45,65 +44,24 @@ func (u *ui) play(playerID int, gameState truco.GameState) (truco.Action, error)
}

var (
action truco.Action
input string
action truco.Action
possibleActions = _deserializeActions(gameState.PossibleActions)
)
for {
num := u.pressAnyNumber()
var actionName string
var err error
actionName, input, err = numToAction(num, gameState)
if err != nil {
continue
}
if actionName == truco.SAY_ENVIDO_QUIERO || actionName == truco.SAY_SON_BUENAS || actionName == truco.SAY_SON_MEJORES {
input = fmt.Sprintf(`{"name":"%v","score":%d}`, actionName, gameState.Hands[gameState.TurnPlayerID].EnvidoScore())
}
if actionName == "reveal_card" {
err := u.render(playerID, gameState, PRINT_MODE_WHICH_CARD_REVEAL)
if err != nil {
return nil, err
}
var card truco.Card
for {
which := u.pressAnyNumber()
if which > len(gameState.Hands[gameState.TurnPlayerID].Unrevealed) {
continue
}
if which == 0 {
return u.play(playerID, gameState)
}
card = gameState.Hands[gameState.TurnPlayerID].Unrevealed[which-1]
break
}
jsonCard, _ := json.Marshal(card)
input = fmt.Sprintf(`{"name":"reveal_card","card":%v}`, string(jsonCard))
}

action, err = truco.DeserializeAction([]byte(input))
if err != nil {
fmt.Printf("Invalid action: %v\n", err)
if num > len(possibleActions) {
continue
}
action = possibleActions[num-1]
break
}
return action, nil
}

func numToAction(num int, state truco.GameState) (string, string, error) {
actions := state.CalculatePossibleActions()
if num > len(actions) {
return "", "", fmt.Errorf("Invalid action")
}

return actions[num-1], fmt.Sprintf(`{"name":"%v"}`, actions[num-1]), nil
}

type printMode int

const (
PRINT_MODE_NORMAL printMode = iota
PRINT_MODE_WHICH_CARD_REVEAL
PRINT_MODE_SHOW_ROUND_RESULT
PRINT_MODE_END
)
Expand Down Expand Up @@ -159,7 +117,7 @@ func (u *ui) render(playerID int, state truco.GameState, mode printMode) error {
printAt(0, my-4, unrevealed)

switch mode {
case PRINT_MODE_NORMAL, PRINT_MODE_WHICH_CARD_REVEAL:
case PRINT_MODE_NORMAL:
lastActionString, err := getLastActionString(you, state)
if err != nil {
return err
Expand Down Expand Up @@ -223,15 +181,11 @@ func (u *ui) render(playerID int, state truco.GameState, mode printMode) error {
if state.TurnPlayerID == playerID {
if mode == PRINT_MODE_NORMAL {
actionsString := ""
for i, action := range state.PossibleActions {
for i, action := range _deserializeActions(state.PossibleActions) {
action := spanishAction(action, state)
actionsString += fmt.Sprintf("%d. %s ", i+1, action)
}
printAt(0, my-2, actionsString)
} else if mode == PRINT_MODE_WHICH_CARD_REVEAL {
printAt(0, my-2, "¿Cuál carta querés tirar?")
unrevealed = getCardsString(hand.Unrevealed, true, true)
printAt(0, my-1, unrevealed)
}
} else {
_, my := termbox.Size()
Expand Down Expand Up @@ -416,10 +370,11 @@ func spanishScore(score int) string {
return fmt.Sprintf("%d buenas", score-14)
}

func spanishAction(action string, state truco.GameState) string {
switch action {
func spanishAction(action truco.Action, state truco.GameState) string {
switch action.GetName() {
case truco.REVEAL_CARD:
return "tirar carta"
_action := action.(*truco.ActionRevealCard)
return getCardString(_action.Card)
case truco.SAY_ENVIDO:
return "envido"
case truco.SAY_REAL_ENVIDO:
Expand All @@ -443,11 +398,20 @@ func spanishAction(action string, state truco.GameState) string {
case truco.SAY_SON_BUENAS:
return "son buenas"
case truco.SAY_SON_MEJORES:
score := state.Hands[state.TurnPlayerID].EnvidoScore()
return fmt.Sprintf("%v son mejores", score)
_action := action.(*truco.ActionSaySonMejores)
return fmt.Sprintf("%v son mejores", _action.Score)
case truco.SAY_ME_VOY_AL_MAZO:
return "me voy al mazo"
default:
return "???"
}
}

func _deserializeActions(as []json.RawMessage) []truco.Action {
_as := []truco.Action{}
for _, a := range as {
_a, _ := truco.DeserializeAction(a)
_as = append(_as, _a)
}
return _as
}
11 changes: 0 additions & 11 deletions truco/action_reveal_card.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,6 @@ func (a ActionRevealCard) IsPossible(g GameState) bool {
playerID: g.CurrentPlayerID(),
}

// Note that CalculatePossibleActions will call this without arguments
// in this case, let's try all unrevealed cards
if a.Card == (Card{}) {
result := false
for _, card := range g.Hands[g.CurrentPlayerID()].Unrevealed {
step.card = card
result = result || g.CardRevealSequence.CanAddStep(step, g)
}
return result
}

return g.CardRevealSequence.CanAddStep(step, g)
}

Expand Down
15 changes: 12 additions & 3 deletions truco/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ func (a act) GetName() string {
}

func (a act) YieldsTurn(g GameState) bool {
// if a.Name == SAY_ENVIDO_NO_QUIERO {
// log.Printf("Player %d started the envido sequence, player %v just said no quiero, yields should return: %v but I'm returning true\n", g.EnvidoSequence.StartingPlayerID, g.TurnPlayerID, g.TurnPlayerID != g.EnvidoSequence.StartingPlayerID)
// }
return true
}

func newActionSayEnvido() Action {
return ActionSayEnvido{act: act{Name: SAY_ENVIDO}}
}

func newActionSayRealEnvido() Action {
return ActionSayRealEnvido{act: act{Name: SAY_REAL_ENVIDO}}
}

func newActionSayFaltaEnvido() Action {
return ActionSayFaltaEnvido{act: act{Name: SAY_FALTA_ENVIDO}}
}

func newActionSayEnvidoNoQuiero() Action {
return ActionSayEnvidoNoQuiero{act: act{Name: SAY_ENVIDO_NO_QUIERO}}
}
Expand Down Expand Up @@ -58,3 +63,7 @@ func newActionSaySonMejores(score int) Action {
func newActionRevealCard(card Card) Action {
return ActionRevealCard{act: act{Name: REVEAL_CARD}, Card: card}
}

func newActionSayMeVoyAlMazo() Action {
return ActionSayMeVoyAlMazo{act: act{Name: SAY_ME_VOY_AL_MAZO}}
}
60 changes: 38 additions & 22 deletions truco/truco.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type GameState struct {
// each action is run (i.e. GameState.RunAction).
// The actions are strings, which are the names of the actions. In the case of REVEAL_CARD,
// the card is not specified.
PossibleActions []string `json:"possibleActionTypes"`
PossibleActions []json.RawMessage `json:"possibleActions"`

// EnvidoSequence is the sequence of envido actions that have been taken in the current round.
// Example sequence is: [SAY_ENVIDO, SAY_REAL_ENVIDO, SAY_ENVIDO_QUIERO]
Expand Down Expand Up @@ -171,7 +171,7 @@ func (g *GameState) startNewRound() {
g.EnvidoFinished = false
g.RoundFinished = false
g.TrucoQuieroOwnerPlayerId = -1
g.PossibleActions = g.CalculatePossibleActions()
g.PossibleActions = _serializeActions(g.CalculatePossibleActions())
}

func (g *GameState) RunAction(action Action) error {
Expand Down Expand Up @@ -215,7 +215,7 @@ func (g *GameState) RunAction(action Action) error {
}
}

g.PossibleActions = g.CalculatePossibleActions()
g.PossibleActions = _serializeActions(g.CalculatePossibleActions())
return nil
}

Expand Down Expand Up @@ -280,30 +280,38 @@ var (
errGameIsEnded = errors.New("game is ended")
)

func (g GameState) CalculatePossibleActions() []string {
allActions := []Action{
ActionRevealCard{act: act{Name: "reveal_card"}},
ActionSayEnvido{act: act{Name: "say_envido"}},
ActionSayRealEnvido{act: act{Name: "say_real_envido"}},
ActionSayFaltaEnvido{act: act{Name: "say_falta_envido"}},
ActionSayEnvidoQuiero{act: act{Name: "say_envido_quiero"}},
ActionSayEnvidoNoQuiero{act: act{Name: "say_envido_no_quiero"}},
ActionSayTruco{act: act{Name: "say_truco"}},
ActionSayTrucoQuiero{act: act{Name: "say_truco_quiero"}},
ActionSayTrucoNoQuiero{act: act{Name: "say_truco_no_quiero"}},
ActionSayQuieroRetruco{act: act{Name: "say_quiero_retruco"}},
ActionSayQuieroValeCuatro{act: act{Name: "say_quiero_vale_cuatro"}},
ActionSaySonBuenas{act: act{Name: "say_son_buenas"}},
ActionSaySonMejores{act: act{Name: "say_son_mejores"}},
ActionSayMeVoyAlMazo{act: act{Name: "say_me_voy_al_mazo"}},
func (g GameState) CalculatePossibleActions() []Action {
envidoScore := g.Hands[g.TurnPlayerID].EnvidoScore()

allActions := []Action{}

for _, card := range g.Hands[g.TurnPlayerID].Unrevealed {
allActions = append(allActions, newActionRevealCard(card))
}
actions := []string{}

allActions = append(allActions,
newActionSayEnvido(),
newActionSayRealEnvido(),
newActionSayFaltaEnvido(),
newActionSayEnvidoQuiero(envidoScore),
newActionSayEnvidoNoQuiero(),
newActionSayTruco(),
newActionSayTrucoQuiero(),
newActionSayTrucoNoQuiero(),
newActionSayQuieroRetruco(),
newActionSayQuieroValeCuatro(),
newActionSaySonBuenas(),
newActionSaySonMejores(envidoScore),
newActionSayMeVoyAlMazo(),
)

possibleActions := []Action{}
for _, action := range allActions {
if action.IsPossible(g) {
actions = append(actions, action.GetName())
possibleActions = append(possibleActions, action)
}
}
return actions
return possibleActions
}

func SerializeAction(action Action) []byte {
Expand Down Expand Up @@ -369,3 +377,11 @@ type RoundResult struct {
TrucoWinnerPlayerID int `json:"trucoWinnerPlayerID"`
TrucoPoints int `json:"trucoPoints"`
}

func _serializeActions(as []Action) []json.RawMessage {
_as := []json.RawMessage{}
for _, a := range as {
_as = append(_as, json.RawMessage(SerializeAction(a)))
}
return _as
}

0 comments on commit 91c4cab

Please sign in to comment.