public virtual Move FindBestMove(Board board, out int nMoveRating) { bool bSimpleMinMax = true; m_timer.tic(); Move best_move = null; Node node = new Node(); m_nMinMaxCount = 0; m_nMinMaxDepth = m_nDepth; if (m_bPerfectFinish && board.CountPieces(enPiece.Empty) <= 11) { m_nMinMaxDepth = 12; } int nBestMoveRating; //Simple minimax interface if (bSimpleMinMax) { node.depth = 0; node.max = (m_piece == enPiece.White); node.board = (Board)board.Clone(); nBestMoveRating = minimax_ab(node, Int32.MinValue, Int32.MaxValue, ref best_move); } else { //Move advanced interface that allows to analyse all moves nBestMoveRating = (m_piece == enPiece.White) ? Int32.MinValue : Int32.MaxValue; node.depth = 1; node.max = !(m_piece == enPiece.White); List <Move> vMoves = board.GetAvailableMoves(m_piece); //Cycle over ALL moves foreach (Move move in vMoves) { node.board = (Board)board.Clone(); node.board.MakeBlindMove(move); nMoveRating = minimax_ab_advanced(node, Int32.MinValue, Int32.MaxValue); Console.WriteLine("Move {0} {1}", move, nMoveRating); if ((m_piece == enPiece.White) && nMoveRating > nBestMoveRating) { nBestMoveRating = nMoveRating; best_move = move; } else if ((m_piece == enPiece.Black) && nMoveRating < nBestMoveRating) { nBestMoveRating = nMoveRating; best_move = move; } } } nMoveRating = nBestMoveRating; //Print log message before returning double time = m_timer.toc(); string log_message = String.Format("Rating: {0} depth {1} in {2:F4} sec, total nodes: {3} ( {4:F0} nodes/sec) {5}", nBestMoveRating, m_nMinMaxDepth, time, m_nMinMaxCount, m_nMinMaxCount / time, best_move); Console.WriteLine(log_message); #if PERFORMANCE_LOG using (StreamWriter sr = new StreamWriter("perf.log.txt", true)) { sr.Write(DateTime.Now); sr.WriteLine(log_message); } #endif return(best_move); }