100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
func (r *Round) PlayDefaultStrategy(currentPlayer int) {
|
|
|
|
// Score our hand as if we pick up the discard and discard it immediately
|
|
_, score := FindBestGrouping(r.hands[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[currentPlayer])
|
|
theoretically[cidx] = r.PeekFromDiscard()
|
|
_, 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 score == 0 {
|
|
break // Early exit
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// 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", 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", currentPlayer, r.discard[len(r.discard)-1])
|
|
|
|
} else {
|
|
// Take the discard card
|
|
newCard := r.DrawFromDiscard()
|
|
|
|
r.AddToHand(currentPlayer, newCard)
|
|
|
|
// Discard cidx
|
|
|
|
fmt.Printf("P%d discards %v (position %d)\n", currentPlayer, r.hands[currentPlayer][bestDiscardBasedIdx], bestDiscardBasedIdx)
|
|
r.Discard(currentPlayer, bestDiscardBasedIdx)
|
|
|
|
}
|
|
|
|
} else {
|
|
// The discard card is not going to make us win or significantly lower our
|
|
// score
|
|
// Take from the deck
|
|
|
|
newCard := r.DrawFromDeck()
|
|
r.AddToHand(currentPlayer, newCard)
|
|
|
|
fmt.Printf("P%d taking %v from the deck\n", 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] = NewMasked() // 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
|
|
}
|
|
|
|
if score == 0 {
|
|
break // Early exit
|
|
}
|
|
}
|
|
|
|
// Discard our chosen card
|
|
|
|
fmt.Printf("P%d discards %v (position %d)\n", currentPlayer, r.hands[currentPlayer][bestRandomBasedIdx], bestRandomBasedIdx)
|
|
r.Discard(currentPlayer, bestRandomBasedIdx)
|
|
|
|
}
|
|
|
|
}
|