crowns/strategy.go

104 lines
3.3 KiB
Go

package main
import (
"fmt"
)
func (r *Round) PlayDefaultStrategy() {
currentPlayer := r.currentPlayer
// Score our hand as if we pick up the discard and discard it immediately
_, score := FindBestGrouping(r.hands[r.currentPlayer], r.round)
baseScore := score
bestDiscardBasedIdx := -1
bestDiscardBasedScore := score
if score != 0 {
// Score our hand as if we pick up the discard card and discard each other card
for cidx := 0; cidx < r.round; cidx++ {
// Pick up the last discard card, and discard card@cidx
theoretically := forkHand(r.hands[r.currentPlayer])
theoretically[cidx] = r.discard[len(r.discard)-1]
_, score := FindBestGrouping(theoretically, r.round)
if score < bestDiscardBasedScore {
// TODO if the points are equal or near-equal, prefer not to discard a wild for the next player
bestDiscardBasedIdx = cidx
bestDiscardBasedScore = score
}
}
}
// If taking the discard would let us win, or reduce our score by >5, take it
if bestDiscardBasedScore == 0 || (baseScore-bestDiscardBasedScore) > 5 {
fmt.Printf("P%d taking %v from the discard pile\n", r.currentPlayer, r.discard[len(r.discard)-1])
// We're going to win
if bestDiscardBasedIdx == -1 {
// Take the discard card + put it back again i.e. no change
fmt.Printf("P%d discards %v immediately\n", r.currentPlayer, r.discard[len(r.discard)-1])
} else {
// Take the discard card and discard cidx
newCard := r.discard[len(r.discard)-1]
r.discard = r.discard[0 : len(r.discard)-1]
unwantedCard := r.hands[r.currentPlayer][bestDiscardBasedIdx]
r.hands[r.currentPlayer][bestDiscardBasedIdx] = newCard
r.discard = append(r.discard, unwantedCard) // On top = available for next player
fmt.Printf("P%d discards %v (position %d)\n", currentPlayer, unwantedCard, bestDiscardBasedIdx)
}
} else {
// The discard card is not going to make us win or significantly lower our
// score
// Take from the deck
newCard := r.d[0]
r.d = r.d[1:]
r.hands[r.currentPlayer] = append(r.hands[r.currentPlayer], newCard)
fmt.Printf("P%d taking %v from the deck\n", r.currentPlayer, newCard)
bestRandomBasedIdx := -1
bestRandomBasedScore := (r.round * 50) + 51 // Worse than the worst possible score
// Look at what we can now drop (hand size + 1 new card). We have to drop something
for cidx := 0; cidx < r.round+1; cidx++ {
// Assume we discard that card,
theoretically := forkHand(r.hands[currentPlayer])
theoretically[cidx] = Card(-1) // Never matches + worth 0 points
_, score := FindBestGrouping(theoretically, r.round)
if score < bestRandomBasedScore {
// TODO if the points are equal or near-equal, prefer not to discard a wild for the next player
bestRandomBasedIdx = cidx
bestRandomBasedScore = score
}
}
// Discard our chosen card
// Slice tricks: Copy end card into this slot and reslice bounds
unwantedCard := r.hands[r.currentPlayer][bestRandomBasedIdx]
fmt.Printf("P%d discards %v (position %d)\n", currentPlayer, unwantedCard, bestRandomBasedIdx)
r.hands[r.currentPlayer][bestRandomBasedIdx] = r.hands[r.currentPlayer][len(r.hands[r.currentPlayer])-1]
r.hands[r.currentPlayer] = r.hands[r.currentPlayer][0 : len(r.hands[r.currentPlayer])-1]
r.discard = append(r.discard, unwantedCard) // On top = available for next player
}
}