public Node GetBestMove(BitBoard b, int color) { var board = b.Copy(); Node root = new Node(null, 0, color.Opp(), 0); root.Bits = board; for (int iteration = 0; iteration < 100; iteration++) { Node current = Selection(root, color); int value = Rollout(current, color); Update(current, value); } //root.Save($"{DateTime.Now.ToString("yyyy-MM-dd")}.json");// DrawTree(); var bestNode = root.FindBestNode(); return(bestNode); //BestChildUCB(root, 0).action; }
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; 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 depth = 0; var sw = Stopwatch.StartNew(); var searchResult = engines[turn].Search(board.Copy(), depth); sw.Stop(); timespans[turn] += sw.Elapsed; Console.WriteLine($"[{engines[turn].Name}][{board.EmptyPiecesCount()}] {searchResult}"); if (engines[turn].Name == "EdaxEngine" && board.EmptyPiecesCount() <= EdaxEngine.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 }); }
private FightResult Fight(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 depth = 8; var sw = Stopwatch.StartNew(); var searchResult = engines[turn].Search(board.Copy(), depth); sw.Stop(); timespans[turn] += sw.Elapsed; Console.Title = $"[{board.EmptyPiecesCount()}][{depth}] [{engines[turn].Name}] {board.PlayerPiecesCount()}:{board.OpponentPiecesCount()}"; Console.Title += $" {searchResult.Score}"; Console.WriteLine($"[{engines[turn].Name}][{board.EmptyPiecesCount()}] {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!"); //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 }); }