private int bestScore(HandState state) { int ret; if (mem.TryGetValue(state, out ret)) { return(ret); } if (state.Turns == 0) { return(0); } ret = 0; for (int c = 0; c < 4; c++) { if (c < 3 && state.InitialCards > 0) { continue; } if (c == 3 && state.InitialCards == 0) { continue; } if (c < 3 && state.Scores[c].Count == 0) { continue; } HandState newState = state.Clone(); int score = 0; int carddraws = state.InitialCards; newState.InitialCards = 0; if (c < 3) { score = newState.Scores[c][newState.Scores[c].Count - 1]; carddraws += c; newState.Turns--; newState.Scores[c].RemoveAt(newState.Scores[c].Count - 1); } while (carddraws > 0 && newState.DeckTopIdx < this.deckCards.Length) { carddraws--; string newcard = deckCards[newState.DeckTopIdx++]; int newcardc = int.Parse(newcard.Split(' ')[0]); int newcards = int.Parse(newcard.Split(' ')[1]); int newcardt = int.Parse(newcard.Split(' ')[2]); if (newcardt > 0 && newState.Turns > 0) { // immediately play this, don't add it to state score += newcards; carddraws += newcardc; newState.Turns += newcardt - 1; } else { newState.Scores[newcardc].Add(newcards); } } // We have finished drawing, or the deck has run out if (newState.DeckTopIdx == this.deckCards.Length) { // card draws are irrelevant newState.Scores[0].AddRange(newState.Scores[1]); newState.Scores[0].AddRange(newState.Scores[2]); newState.Scores[1] = new List <int>(); newState.Scores[2] = new List <int>(); } for (int i = 0; i < 3; i++) { newState.Scores[i].Sort(); } score += bestScore(newState); ret = Math.Max(ret, score); } mem[state] = ret; return(ret); }