//randomly picks a piece (used for random opponent) public Piece RandomPickPiece(Board b, AvailablePieces av) { Piece[] pieces = av.RemainingPieces; int count = av.GetRemainingCount(); int rng = rnd.Next(count - 1); int it = 0; foreach (Piece p in pieces) { if (rng == it) { if (p == null) { continue; } else { return(p); } } if (p != null) { it++; } } return(null); }
//original MinMax pick evaluation attempt, not used anymore public Dictionary <Piece, double> RecursivePickEvaluation(Board b, AvailablePieces av, int depth) { if (depth == 0) { Dictionary <Piece, double> evaluationDict = new Dictionary <Piece, double>(); foreach (Piece p in av.RemainingPieces) { if (p != null) { double value = StaticPickEvaluate(b, p, av); evaluationDict.Add(p, value); } } return(evaluationDict.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value)); } else { Dictionary <Piece, double> evaluationDict = new Dictionary <Piece, double>(); foreach (Piece p in av.RemainingPieces) { if (p != null) { Dictionary <int[], double> playDict = RecursivePlayEvaluation(b, p, av, depth - 1); double value = 0; foreach (KeyValuePair <int[], double> i in playDict) { value += i.Value; } evaluationDict.Add(p, value); } } return(evaluationDict.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value)); } }
//picks a random location to play a pieces (used for random opponent) public int[] RandomPlayPiece(Board b, Piece p, AvailablePieces a) { List <int[]> playableLocations = b.GetOpenSpots(); int rng = rnd.Next(playableLocations.Count - 1); return(playableLocations[rng]); }
//original attempt at MinMax pick, not used anymore public Piece RecursivePickPiece(Board b, AvailablePieces av) { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <Piece, double> evaluationDict = new Dictionary <Piece, double>(); int piecesLeft = av.GetRemainingCount(); /*foreach (Piece temp in av.RemainingPieces) * { * if (temp != null) { piecesLeft++; } * }*/ //int searchDepth = Convert.ToInt32(Math.Floor(Convert.ToDecimal(av.RemainingPieces.Length / piecesLeft))); int searchDepth = 2; foreach (Piece p in av.RemainingPieces) { if (p != null) { double value = 0; Dictionary <Piece, double> abc = RecursivePickEvaluation(b, av, searchDepth); foreach (KeyValuePair <Piece, double> i in abc) { value += i.Value; } evaluationDict.Add(p, value); } } List <Piece> sorted = evaluationDict.OrderBy(x => x.Value).ToDictionary(pair => pair.Key).Keys.ToList(); return(sorted[0]); }
//original attempt at MinMax evaluation, not used anymore public Dictionary <int[], double> RecursivePlayEvaluation(Board b, Piece p, AvailablePieces a, int depth) { if (depth == 0) { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <int[], double> evaluationDict = new Dictionary <int[], double>(); foreach (int[] coordinates in playableLocations) { evaluationDict.Add(coordinates, StaticPlayEvaluate(b, p, coordinates, a)); } evaluationDict = evaluationDict.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value); return(evaluationDict); } else { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <int[], double> evaluationDict = new Dictionary <int[], double>(); foreach (int[] i in playableLocations) { Board temp = b.Copy(); temp.SetPiece(p, i[0], i[1]); Dictionary <Piece, double> pickEvaluation = RecursivePickEvaluation(temp, a, depth - 1); double value = 0; foreach (KeyValuePair <Piece, double> pair in pickEvaluation) { value += pair.Value; } evaluationDict.Add(i, value); } return(evaluationDict.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value)); } }
public AvailablePieces Copy() { AvailablePieces av = new AvailablePieces(); for (int i = 0; i < RemainingPieces.Length; i++) { av.RemainingPieces[i] = RemainingPieces[i]; } return(av); }
//original attempt at MinMax play, no longer used public int[] RecursivePlayPiece(Board b, Piece p, AvailablePieces a) { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <int[], double> staticEval = new Dictionary <int[], double>(); List <int[]> playableSubset; foreach (int[] i in playableLocations) { staticEval.Add(i, StaticPlayEvaluate(b, p, i, a)); } int piecesLeft = a.GetRemainingCount(); int searchDepth; if (piecesLeft > 0) { searchDepth = Convert.ToInt32(Math.Floor(Convert.ToDecimal(a.RemainingPieces.Length / (piecesLeft)))); if (searchDepth > 4) { searchDepth = 4; } } else { searchDepth = 0; } playableSubset = staticEval.OrderByDescending(x => x.Value).ToDictionary(x => x.Key).Keys.ToList().Take(Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(a.GetRemainingCount() * 1 / (4 - searchDepth + 1))))).ToList(); Dictionary <int[], double> evaluationDict = new Dictionary <int[], double>(); /*foreach(Piece temp in a.RemainingPieces) * { * if (temp != null) { piecesLeft++; } * }*/ foreach (int[] coordinates in playableSubset) { double value = 0; Dictionary <int[], double> abc = RecursivePlayEvaluation(b, p, a, searchDepth); foreach (KeyValuePair <int[], double> i in abc) { value += i.Value; } evaluationDict.Add(coordinates, value); } List <int[]> sorted = evaluationDict.OrderByDescending(x => x.Value).ToDictionary(pair => pair.Key).Keys.ToList(); if (sorted.Count == 0) { return(PlayPiece(b, p, a)); } return(sorted[0]); }
//selects a location to play a piece by evaluating the board with a depth of 0 (used during training) public int[] PlayPiece(Board b, Piece p, AvailablePieces a) { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <int[], double> evaluationDict = new Dictionary <int[], double>(); foreach (int[] coordinates in playableLocations) { evaluationDict.Add(coordinates, StaticPlayEvaluate(b, p, coordinates, a)); } List <int[]> sorted = evaluationDict.OrderByDescending(x => x.Value).ToDictionary(pair => pair.Key).Keys.ToList(); return(sorted[0]); }
//picks a piece without evaluation future board states (depth 0) public Piece PickPiece(Board b, AvailablePieces av) { List <int[]> playableLocations = b.GetOpenSpots(); Dictionary <Piece, double> evaluationDict = new Dictionary <Piece, double>(); foreach (Piece p in av.RemainingPieces) { if (p != null) { evaluationDict.Add(p, StaticPickEvaluate(b, p, av)); } } List <Piece> sorted = evaluationDict.OrderBy(x => x.Value).ToDictionary(pair => pair.Key).Keys.ToList(); return(sorted[0]); }
//evaluation function for picking a piece (opposite of playing a piece) public double StaticPickEvaluate(Board b, Piece p, AvailablePieces a) { List <int[]> playableLocations = b.GetOpenSpots(); double value = 0; foreach (int[] i in playableLocations) { AvailablePieces temp = a.Copy(); temp.RemovePiece(p); if (StaticPlayEvaluate(b, p, i, temp) > value) { value = StaticPlayEvaluate(b, p, i, temp); } //value += StaticPlayEvaluate(b, p, i, temp); } return(value); }
//Evaluation Function for placing a piece public double StaticPlayEvaluate(Board b, Piece p, int[] coordinates, AvailablePieces a) { double v1 = Coefficients[0] * EvaluationFunctions.BinarySum(EvaluationFunctions.CommonProperties(EvaluationFunctions.EvaluationDirection.Row, b, coordinates[0], coordinates[1])); double v2 = Coefficients[1] * EvaluationFunctions.BinarySum(EvaluationFunctions.CommonProperties(EvaluationFunctions.EvaluationDirection.Column, b, coordinates[0], coordinates[1])); double v3 = Coefficients[2] * EvaluationFunctions.BinarySum(EvaluationFunctions.CommonProperties(EvaluationFunctions.EvaluationDirection.Diagonal, b, coordinates[0], coordinates[1])); double v4 = Coefficients[3] * EvaluationFunctions.SpotsRemaining(EvaluationFunctions.EvaluationDirection.Row, b, coordinates[0], coordinates[1]); double v5 = Coefficients[4] * EvaluationFunctions.SpotsRemaining(EvaluationFunctions.EvaluationDirection.Column, b, coordinates[0], coordinates[1]); double v6 = Coefficients[5] * EvaluationFunctions.SpotsRemaining(EvaluationFunctions.EvaluationDirection.Diagonal, b, coordinates[0], coordinates[1]); double v7 = Coefficients[6] * a.GetRemainingCount(); double v8 = Coefficients[7] * EvaluationFunctions.CommonPiecesRemaining(EvaluationFunctions.EvaluationDirection.Row, b, a.RemainingPieces, coordinates[0], coordinates[1]); double v9 = Coefficients[8] * EvaluationFunctions.CommonPiecesRemaining(EvaluationFunctions.EvaluationDirection.Column, b, a.RemainingPieces, coordinates[0], coordinates[1]); double v10 = Coefficients[9] * EvaluationFunctions.CommonPiecesRemaining(EvaluationFunctions.EvaluationDirection.Diagonal, b, a.RemainingPieces, coordinates[0], coordinates[1]); int v11 = EvaluationFunctions.Winnable(EvaluationFunctions.EvaluationDirection.Diagonal, b, coordinates[0], coordinates[1]); int v12 = EvaluationFunctions.WinningMoveAvailable(p, b, coordinates); //return v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10; return((v1 * v4 * v8) + (v2 * v5 * v9) + (v3 * v6 * v10 * v11) + v12); //return (v1 * v8 - v4) + (v2 * v9 - v5) + (v3 * v10 * v11 - v6); }
//MinMax pick algorithm //[piece, value] public object[] MinMaxPick(Board b, AvailablePieces av, int depth, double value, bool opponent) { Piece p = PickPiece(b, av); AvailablePieces copy = av.Copy(); value -= StaticPickEvaluate(b, p, av); if (depth == 0) { if (value == 0) { value = 0.0; } return(new object[] { p, value }); } else { copy.RemovePiece(p); object[] evaluation = MinMaxPlay(b, p, av, depth - 1, value, !opponent); return(new object[] { p, evaluation[2] }); } }
//MinMax play algorithm //[int[], piece, value] public object[] MinMaxPlay(Board b, Piece p, AvailablePieces av, int depth, double value, bool opponent) { int[] useless = p.GetBinary(); List <int[]> playableLocations = b.GetOpenSpots(); int evaluationCount = 0; if (playableLocations.Count < 4) { evaluationCount = playableLocations.Count; } else { evaluationCount = 4; } Dictionary <int[], double> evaluationDict = new Dictionary <int[], double>(); foreach (int[] coordinates in playableLocations) { evaluationDict.Add(coordinates, StaticPlayEvaluate(b, p, coordinates, av)); } List <int[]> sorted = evaluationDict.OrderByDescending(x => x.Value).ToDictionary(pair => pair.Key).Keys.ToList(); List <object[]> evaluationResults = new List <object[]>(); for (int i = 0; i < evaluationCount; i++) { Board temp = b.Copy(); temp.SetPiece(p, sorted[i][0], sorted[i][1]); if (temp.CheckWin()) { if (!opponent) { return(new object[] { sorted[i], p, 1000 }); } else { return(new object[] { sorted[i], p, -1000 }); } } if (evaluationCount == 1) { return(new object[] { sorted[0], p, 1 }); } if (!opponent) { object[] eval = MinMaxPick(temp, av, depth, evaluationDict[sorted[i]], opponent); evaluationResults.Add(new object[] { sorted[i], eval[0], eval[1] }); } else { object[] eval = MinMaxPick(temp, av, depth, -1 * evaluationDict[sorted[i]], opponent); evaluationResults.Add(new object[] { sorted[i], eval[0], eval[1] }); } } if (evaluationResults.Count == 0) { return(new object[] { playableLocations[0], null, 0 }); } object[] bestPlay = evaluationResults[0]; if (!opponent) { foreach (object[] o in evaluationResults) { try { if ((double)o[2] > (double)bestPlay[2]) { bestPlay = o; } } catch { } } //bestPlay = evaluationResults.OrderByDescending(x => x[1]).ToList<object[]>()[0]; } else { foreach (object[] o in evaluationResults) { try { if ((double)o[2] < (double)bestPlay[2]) { bestPlay = o; } } catch { } } //bestPlay = evaluationResults.OrderBy(x => x[1]).ToList<object[]>()[0]; } return(bestPlay); }