private FightResult DoFight(IEngine engineA, IEngine engineB, BitBoard board) { var clock = new Clock(); clock.Start(); var engines = new IEngine[] { engineA, engineB }; var timespans = new TimeSpan[] { TimeSpan.Zero, TimeSpan.Zero }; var colors = new[] { "Black", "White" }; int turn = 0; Console.WriteLine(board.Draw(colors[turn])); while (!board.IsFull) { var empties = board.EmptyPiecesCount(); if (empties <= TrainDepth + 1) { var moves = Rule.FindMoves(board); if (moves.Length > 0) { var bestScore = -64 - 1; var bestMove = -1; foreach (var move in moves) { var oppboard = Rule.MoveSwitch(board, move); var own = false; if (!Rule.CanMove(oppboard)) { oppboard = oppboard.Switch(); own = true; } var sr = AnalyzeEndGame(oppboard, turn); var eval = own ? sr.Score : -sr.Score;//opp's score if (eval > bestScore) { bestScore = eval; bestMove = move; } Console.WriteLine($"color:{turn} move:{move}, score:{eval}"); } var winIndex = bestScore >= 0 ? turn : 1 - turn; return(new FightResult { WinnerName = engines[winIndex].Name, LoserName = engines[1 - winIndex].Name, WinnerStoneType = colors[winIndex], Score = Math.Abs(bestScore), TimeSpan = clock.Elapsed }); } } var sw = Stopwatch.StartNew(); var currentEngine = engines[turn]; var searchResult = currentEngine.Search(board.Copy(), MidGameDepth); if (searchResult.IsTimeout) { Console.WriteLine("time out, switch to 'BackupEngine' on this time"); currentEngine = new RandomEngine("BackupEngine"); searchResult = currentEngine.Search(board.Copy(), MidGameDepth); } sw.Stop(); timespans[turn] += sw.Elapsed; Console.WriteLine($"[{currentEngine.Name}][{board.EmptyPiecesCount()}] {searchResult}"); if (currentEngine.Name == EndEngine.Name && board.EmptyPiecesCount() <= EndGameDepth) { SaveResult(board, searchResult); } if (searchResult.Move < 0 || searchResult.Move >= Constants.StonesCount || !Rule.FindMoves(board).Contains(searchResult.Move)) { clock.Stop(); //error Console.WriteLine("----------------Error Move----------------------"); Console.WriteLine(board.Draw(colors[turn])); return(new FightResult() { WinnerName = engines[1 - turn].Name, LoserName = engines[turn].Name, WinnerStoneType = colors[turn], Score = 1, TimeSpan = clock.Elapsed }); } else { board = Rule.MoveSwitch(board, searchResult.Move); Console.WriteLine(board.Draw(colors[turn])); } turn = 1 ^ turn; var canFlip = Rule.CanMove(board); if (!canFlip) { //pass Console.WriteLine($"{engines[turn].Name} pass"); turn = 1 ^ turn; board = board.Switch(); canFlip = Rule.CanMove(board); if (!canFlip) { Console.WriteLine($"{engines[turn].Name} pass, game over!"); AnalyzeEndGame(board, turn); //both pass break; } } } clock.Stop(); Console.WriteLine("################### Game Over #######################"); for (var i = 0; i < 2; i++) { Console.WriteLine($"Total spent time({engines[i].Name}): {timespans[i]}"); } return(new FightResult(board, engines, turn) { TimeSpan = clock.Elapsed }); }