// POST: api/ChessAI public string Post(StringAux gameXml, int timeLimitInSecs) { if (gameXml == null) { return("WTF"); } XmlDocument doc = new XmlDocument(); doc.LoadXml(gameXml.Str); XmlNode gameXmlNode = doc.DocumentElement; ChessLibrary.Game g1 = new ChessLibrary.Game(); g1.XmlDeserialize(gameXmlNode); Player p = g1.BlackPlayer; if (g1.BlackTurn()) { p = g1.WhitePlayer; } ChessLibrary.Move m = p.GetBestMove(); string best_str = m.ToString2(); g1.NextPlayerTurn(); // need to do that because the player is opposite for some reason if (g1.DoMove(best_str.Substring(best_str.Length - 5, 2), best_str.Substring(best_str.Length - 2, 2)) == -1) { return("bad move"); } return(best_str); /*XmlDocument doc = new XmlDocument(); * doc.LoadXml(gameXml.Str); * XmlNode gameXmlNode = doc.DocumentElement; * * Move bestMove = ChessAPI.calculateBestMoveXmlNode(gameXmlNode, timeLimitInSecs);*/ /*System.Xml.Serialization.XmlSerializer writer = * new System.Xml.Serialization.XmlSerializer(typeof(Move)); * StringBuilder sb = new StringBuilder(); * StringWriter sw = new StringWriter(sb); * writer.Serialize(sw, bestMove);*/ //return bestMove.ToString(); // seralized move }
// Fire the computer thinking events to all the subscribers public void NotifyComputerThinking(int depth, int currentMove, int TotalMoves, int TotalAnalzyed, Move BestMove) { if (ComputerThinking != null) // There are some subscribers { ComputerThinking(depth, currentMove, TotalMoves, TotalAnalzyed, BestMove); } }
// Get the best move available to the player public Move GetBestMove() { int alpha, beta; int depth; // depth to which to do the search TimeSpan ElapsedTime = new TimeSpan(1); // Total elpased time Move BestMove = null; // The best move for the current position // Initialize constants const int MIN_SCORE = -10000000; // Minimum limit of negative for integer const int MAX_SCORE = 10000000; // Maximum limit of positive integer ArrayList TotalMoves = m_Rules.GenerateAllLegalMoves(m_Side); // Get all the legal moves for the current side // Now we use the Iterative deepening technique to search the best move // The idea is just simple, we will keep searching in the more and more depth // as long as we don't time out. // So, it means that when we have less moves, we can search more deeply and which means // better chess game. DateTime ThinkStartTime = DateTime.Now; int MoveCounter; Random RandGenerator = new Random(); // Game is near the end, or the current player is under check if (m_Rules.ChessBoard.GetSideCell(m_Side.type).Count <= 5 || TotalMoves.Count <= 5) { m_GameNearEnd = true; } // Game is near the end, or the Enemy player is under check Side EnemySide; if (m_Side.isBlack()) { EnemySide = m_Rules.ChessGame.WhitePlayer.PlayerSide; } else { EnemySide = m_Rules.ChessGame.BlackPlayer.PlayerSide; } if (m_Rules.ChessBoard.GetSideCell(m_Side.Enemy()).Count <= 5 || m_Rules.GenerateAllLegalMoves(EnemySide).Count <= 5) { m_GameNearEnd = true; } m_TotalMovesAnalyzed = 0; // Reset the total moves anazlye counter for (depth = 1;; depth++) // Keep doing a depth search { alpha = MIN_SCORE; // The famous Alpha & Beta are set to their initial values beta = MAX_SCORE; // at the start of each increasing search depth iteration MoveCounter = 0; // Initialize the move counter variable // Loop through all the legal moves and get the one with best score foreach (Move move in TotalMoves) { MoveCounter++; // Now to get the effect of this move; execute this move and analyze the board m_Rules.ExecuteMove(move); move.Score = -AlphaBeta(m_Rules.ChessGame.EnemyPlayer(m_Side).PlayerSide, depth - 1, -beta, -alpha); m_TotalMovesAnalyzed++; // Increment move counter m_Rules.UndoMove(move); // undo the move // If the score of the move we just tried is better than the score of the best move we had // so far, at this depth, then make this the best move. if (move.Score > alpha) { BestMove = move; alpha = move.Score; } m_Rules.ChessGame.NotifyComputerThinking(depth, MoveCounter, TotalMoves.Count, m_TotalMovesAnalyzed, BestMove); // Check if the user time has expired ElapsedTime = DateTime.Now - ThinkStartTime; if (ElapsedTime.Ticks > (m_MaxThinkTime.Ticks)) // More than 75 percent time is available { break; // Force break the loop } } // Check if the user time has expired ElapsedTime = DateTime.Now - ThinkStartTime; if (ElapsedTime.Ticks > (m_MaxThinkTime.Ticks * 0.25)) // More than 75 percent time is available { break; // Force break the loop } } m_Rules.ChessGame.NotifyComputerThinking(depth, MoveCounter, TotalMoves.Count, m_TotalMovesAnalyzed, BestMove); return(BestMove); }