crowns/game.go

155 lines
3.1 KiB
Go

package main
import (
"fmt"
"math/rand"
)
func PlayGame(numPlayers int, entropy *rand.Rand) {
currentPlayer := 0
runningScores := make([]int, numPlayers)
for round := 3; round < 14; round++ {
r := NewRound(round, numPlayers, entropy)
nextPlayer, roundScores := r.Play(currentPlayer)
currentPlayer = nextPlayer
for p := 0; p < numPlayers; p++ {
runningScores[p] += roundScores[p]
}
fmt.Printf("The round has ended\n")
fmt.Printf("Running total scores: %v\n", runningScores)
}
fmt.Printf("The game has ended\n")
}
type Round struct {
d []Card
discard []Card
round int
numPlayers int
hands [][]Card
}
func NewRound(round, numPlayers int, entropy *rand.Rand) *Round {
r := Round{
round: round,
numPlayers: numPlayers,
}
r.d = Deck()
Shuffle(r.d, entropy)
r.discard = []Card{}
fmt.Printf("# Round %d\n\n", r.round)
// Deal starting cards
r.hands = make([][]Card, numPlayers)
for p := 0; p < numPlayers; p++ {
r.hands[p] = r.d[0:round] // Deal from the bottom (0)
r.d = r.d[round:]
fmt.Printf("P%d starting hand: %v\n", p, r.hands[p])
}
// Deal one into the discard pile
r.discard = append(r.discard, r.d[0])
r.d = r.d[1:]
// Done
return &r
}
func FormatHandGroupings(hand []Card, groupings [][]int) string {
tmp := forkHand(hand)
cgroups := [][]Card{}
for _, group := range groupings {
cgroup := []Card{}
for _, cidx := range group {
cgroup = append(cgroup, hand[cidx])
tmp[cidx] = Card(-1)
}
cgroups = append(cgroups, cgroup)
}
leftover := []Card{}
for _, cv := range tmp {
if cv != Card(-1) {
leftover = append(leftover, cv)
}
}
return fmt.Sprintf("[ %v leftover %v ]", cgroups, leftover)
}
func (r *Round) Play(startingPlayer int) (nextPlayer int, roundScores []int) {
currentPlayer := startingPlayer
fmt.Printf("Discard stack: %v\n", r.discard)
fmt.Printf("Deck has %d cards remaining\n", len(r.d))
roundEndsWhenPlayerIs := -1
for {
if roundEndsWhenPlayerIs == currentPlayer {
break
}
// Play the strategy for the current player
r.PlayDefaultStrategy(currentPlayer)
// Check, one more time, if we have a winning hand
currentBestGrouping, currentScore := FindBestGrouping(r.hands[currentPlayer], r.round)
if currentScore == 0 {
// Declare victory
fmt.Printf("P%d declares victory\n- Hand: %v\n- Groupings: %v\n", currentPlayer, r.hands[currentPlayer], currentBestGrouping)
if roundEndsWhenPlayerIs == -1 {
roundEndsWhenPlayerIs = currentPlayer
} // Otherwise, the round is already ending anyway
}
// Move to the next player
currentPlayer = (currentPlayer + 1) % r.numPlayers
}
// The round has ended
// Figure out what each player scored
roundScores = make([]int, r.numPlayers)
for p := 0; p < r.numPlayers; p++ {
gr, score := FindBestGrouping(r.hands[p], r.round)
fmt.Printf("P%d has %v (score: %d)\n", p, FormatHandGroupings(r.hands[p], gr) /*r.hands[p], gr,*/, score)
roundScores[p] = score
}
// Check stack alignment
if len(r.discard)+len(r.d)+(r.numPlayers*len(r.hands[0])) != DeckSize {
panic("Cards on the floor")
}
// Done
return currentPlayer, roundScores
}