private const int Randomness = 0; // Degree of randomness, random number between -val to +val is added to each rating private static void EvaluateAiMove(Dictionary <Square, AiChessPiece> board, float[,] strength, Player currentPlayer) { List <ChessMove> moves = GetMovesForPlayer(board, strength, currentPlayer); List <Task <float> > threads = new List <Task <float> >(); for (int i = 0; i < NumThreads; i++) { Player threadedPlayer = new Player(currentPlayer); List <ChessMove> threadedMoves = new List <ChessMove>(); int threadIndex = _turns.Count; // split up best moves for (int j = 0; j < moves.Count; j += NumThreads) { if (j + threadIndex >= moves.Count) { continue; } threadedMoves.Add(moves[j + threadIndex]); } // store new board for thread Dictionary <Square, AiChessPiece> threadedBoard = new Dictionary <Square, AiChessPiece>(); foreach (Square s in board.Keys) { AiChessPiece p = board[s]; threadedBoard.Add(s, new AiChessPiece(p.Name, p.Owner, p.Type, p.Position)); } // init new strength for thread float[,] threadedStrength = EvaluationValues.InitStrength(threadedBoard); _turns.Add(new List <ChessMove[]>()); _ratings.Add(new List <float>()); _boards.Add(threadedBoard); Task <float> thread = new Task <float>(() => Minimax(threadedMoves, threadedBoard, threadedStrength, new Stack <ChessMove>(), threadedPlayer, TurnSearchDepth, 3, threadIndex, 0)); threads.Add(thread); thread.Start(); } // Wait for all threads to join foreach (Task <float> t in threads) { t.Wait(); } }
public static void AiMoves(Dictionary <Square, AiChessPiece> board, Player currentPlayer) { Stopwatch watch = new Stopwatch(); watch.Start(); // Generate new environment for AI to simulate moves in float[,] strength = EvaluationValues.InitStrength(board); Game.AIMoves = null; _totalMovesSearched = 0; _turns = new List <List <ChessMove[]> >(); _ratings = new List <List <float> >(); Player player = new Player(currentPlayer); // Run evaluation EvaluateAiMove(board, strength, currentPlayer); // All combinations are now stored in _turns, and their corresponding ratings are in _ratings // Find the best depending on player float best; int index = 0; // Flatten lists Random random = new Random(); List <ChessMove[]> Moves = new List <ChessMove[]>(); List <float> Ratings = new List <float>(); for (var i = 0; i < _turns.Count; i++) { List <ChessMove[]> moveList = _turns[i]; List <float> ratingList = _ratings[i]; for (int j = 0; j < moveList.Count; j++) { Moves.Add(moveList[j]); Ratings.Add(ratingList[j]); Ratings[Ratings.Count - 1] += random.Next(-Randomness, Randomness); } } // add the ratings of the turns to the total rating for (int i = 0; i < Moves.Count; i++) { ChessMove[] moves = Moves[i]; Ratings[i] = 0; foreach (ChessMove move in moves) { if (move == null) { continue; } Ratings[i] += move.Rating; Ratings[i] += (currentPlayer.Name == "player1" ? 10000 : -10000); } } // find the min or max if (player.Name == "player1") { best = float.MinValue; for (int i = 0; i < Ratings.Count; i++) { if (!(Ratings[i] > best)) { continue; } best = Ratings[i]; index = i; } } else { best = float.MaxValue; for (int i = 0; i < Ratings.Count; i++) { if (!(Ratings[i] < best)) { continue; } best = Ratings[i]; index = i; } } // Set the ai's moves in Game Game.AIMoves = Moves[index]; Game.nextMove = Moves[index][0]; //Debug.Log(watch.ElapsedMilliseconds + " ms - " + _totalMovesSearched + // " moves searched. Best moves yielded eval of: " + Ratings[index]); }