protected int[] GetOptimalThrow(ThrowingStrategy strategy) { //This is the AI, automatically chooses which cards to throw away //DESCRIPTION: //THERE ARE TWO THINGS THE AI NEEDS TO CONSIDER: //1) Having the statistically best hand possible (given random cut-up card) //2) Giving the opponent the statistically best/worst cards possible (given 3 random cards) //What Optimal means depends on your strategy //This array will hold the best 4 indices to keep var best = new int[4]; //Stores the best score so far to find max with double score = double.MinValue, bestScore = 0; //Looks at every possible throwing possible (there should be 15, since 6C4 is 15) foreach (var combo in HelperFunctions.GetKCombination(_size, FinalHandSize)) { //Finds hand that best satisfies chosen strategy score = AnalyzeThrow(combo, strategy); { //Better hand found, replace original if (score > bestScore) { bestScore = score; best = combo; } } } return(best); }
//METHODS protected void ThrowAway(ThrowingStrategy strategy) { //Figures out the best way to throw away var best = GetOptimalThrow(strategy); foreach (var throwIndex in HelperFunctions.GetIndexComplement(_size, best)) { //Mark the indices from the optimal throw as thrown MarkThrown(throwIndex); } }
protected double AnalyzeThrow(int[] keep, ThrowingStrategy strategy) { //Get weighted average of both sides of this option double handScore = AnalyzeHand(keep); double cribScore; double score; //STRATEGY PATTERN - CHANGE THIS LATER! //score = strategy(keep) //There is no point to have all these algorithms here //Switch statement takes the AI's strategy switch (strategy) { case ThrowingStrategy.OptimizeCrib: cribScore = AnalyzeCrib(keep); //Optimize hand AND crib at the same time score = cribScore + handScore; break; case ThrowingStrategy.DeoptimizeCrib: cribScore = AnalyzeCrib(keep); //Otherwise, deoptimize crib. The better the crib, the worse this throw score = handScore - cribScore; break; case ThrowingStrategy.IgnoreCrib: //There are only 15 ways to throw away, ignoring will only give a bad throw every once in a while //It's MUCH MUCH faster than optimize and deoptimize score = handScore; break; case ThrowingStrategy.Random: //Randomly assigns quality values to each throw var r = new Random(); score = 29 * r.NextDouble(); break; default: //This strategy doesn't exist throw new ArgumentException("No strategy provided!"); } return(score); }
public ThrowingHandAITest(Deck deck, ThrowingStrategy strategy) : base(deck, strategy) { }
//CONSTRUCTOR public ThrowingHandAI(Deck deck, ThrowingStrategy strategy, int DefaultStartingHandSize = 6) : base(deck, DefaultStartingHandSize) { _strategy = strategy; //Automatically creates (somewhat) ideal hand //ThrowAway(_strategy); }