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 } }