Пример #1
0
        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
            });
        }