コード例 #1
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            if (_useOpeningBook)
            {
                if (maxSeconds <= _book.Seconds)
                {
                    var bookMove = _book.GetMove(state.Transcript);

                    if (bookMove >= 0)
                    {
                        return(new SearchResult
                        {
                            BestMove = bookMove
                        });
                    }
                }
            }

            timer           = Stopwatch.StartNew();
            statusUpdate    = Stopwatch.StartNew();
            visitedNodes    = 0;
            simulationCount = 0;

            cancel = new EngineCancellationToken(() => token.Cancelled || timer.ElapsedMilliseconds >= maxSeconds * 1000L - bufferMilliseconds);

            int best = MonteCarloTreeSearch(state);

            return(new SearchResult
            {
                BestMove = best,
                Evaluations = visitedNodes,
                Simulations = simulationCount,
                Milliseconds = timer.ElapsedMilliseconds
            });
        }
コード例 #2
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            timer       = Stopwatch.StartNew();
            evaluations = 0;

            SearchResult result = new SearchResult();

            result.Score = int.MinValue;

            Player player = state.Player;

            // Get a list of all possible moves, randomly shuffled
            List <int> moves = Shuffle(state.GetMoves());

            foreach (int move in moves)
            {
                Board copy = new Board(state);
                copy.MakeMove(move);

                var eval = EvaluateLongestPath(copy, player, move);

                if (eval > result.Score)
                {
                    result.BestMove = move;
                    result.Score    = eval;
                }
            }

            result.Evaluations  = evaluations;
            result.Milliseconds = timer.ElapsedMilliseconds;

            return(result);
        }
コード例 #3
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            List <int> moves = state.GetMoves();

            return(new SearchResult
            {
                BestMove = moves[_random.Next(moves.Count)]
            });
        }
コード例 #4
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            Stopwatch timer = Stopwatch.StartNew();

            evaluations = 0;

            SearchResult result = AlphaBetaSearch(state, searchDepth, int.MinValue, int.MaxValue);

            result.Evaluations  = evaluations;
            result.Milliseconds = timer.ElapsedMilliseconds;

            return(result);
        }
コード例 #5
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            Stopwatch timer = Stopwatch.StartNew();

            evaluations = 0;

            cancellationToken = token;

            var result = MonteCarlo(state, _initialDepth, 0);

            result.Result.Evaluations  = evaluations;
            result.Result.Milliseconds = timer.ElapsedMilliseconds;

            return(result.Result);
        }
コード例 #6
0
ファイル: SkipTileEngine.cs プロジェクト: skotz/volcanoes
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            SearchResult result = new SearchResult();

            for (int i = 0; i < 80; i++)
            {
                // Start from a tile we don't own
                if (state.Tiles[i] == 0)
                {
                    List <int> neighbors = new List <int>();
                    foreach (int adjacent in Constants.AdjacentIndexes[i])
                    {
                        foreach (int twoStepsAway in Constants.AdjacentIndexes[adjacent])
                        {
                            // If the tile is exactly two steps away from a tile we own
                            if (twoStepsAway != i && !Constants.AdjacentIndexes[i].Contains(twoStepsAway) && ((state.Tiles[twoStepsAway] > 0 && state.Player == Player.One) || (state.Tiles[twoStepsAway] < 0 && state.Player == Player.Two)))
                            {
                                if (!neighbors.Contains(twoStepsAway))
                                {
                                    neighbors.Add(twoStepsAway);
                                }
                            }
                        }
                    }

                    result.BestMove = i;

                    // This tile is two steps away from one and only one of our other tiles, then it's an amazing move
                    if (neighbors.Count == 1)
                    {
                        return(result);
                    }
                }
            }

            if (result.BestMove >= 0)
            {
                return(result);
            }
            else
            {
                List <int> moves = state.GetMoves();
                result.BestMove = moves[random.Next(moves.Count)];

                return(result);
            }
        }
コード例 #7
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            Stopwatch timer = Stopwatch.StartNew();

            evaluations = 0;
            hashHits    = 0;
            hashMisses  = 0;

            cancellationToken = token;

            SearchResult result = AlphaBetaSearch(state, searchDepth, int.MinValue, int.MaxValue);

            result.Evaluations    = evaluations;
            result.Milliseconds   = timer.ElapsedMilliseconds;
            result.HashPercentage = hashHits + hashMisses > 0 ? hashHits / ((decimal)hashHits + hashMisses) : 0m;

            return(result);
        }
コード例 #8
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            Stopwatch timer = Stopwatch.StartNew();

            statusUpdate    = Stopwatch.StartNew();
            visitedNodes    = 0;
            simulationCount = 0;

            cancel = new EngineCancellationToken(() => token.Cancelled || timer.ElapsedMilliseconds >= maxSeconds * 1000 - bufferMilliseconds);

            int best = MonteCarloTreeSearch(state);

            return(new SearchResult
            {
                BestMove = best,
                Evaluations = visitedNodes,
                Simulations = simulationCount,
                Milliseconds = timer.ElapsedMilliseconds
            });
        }
コード例 #9
0
ファイル: AlphaEngine.cs プロジェクト: skotz/volcanoes
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            List <int> moves = state.GetMoves();

            // Use old tile names since the new system isn't named like this
            List <int> alphaMoves = moves.Where(x => Constants.OldTileNames[x].EndsWith("A")).ToList();

            if (alphaMoves.Count > 0)
            {
                return(new SearchResult
                {
                    BestMove = alphaMoves[random.Next(alphaMoves.Count)]
                });
            }
            else
            {
                return(new SearchResult
                {
                    BestMove = moves[random.Next(moves.Count)]
                });
            }
        }
コード例 #10
0
ファイル: BeeLineEngine.cs プロジェクト: skotz/volcanoes
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            List <int> moves = state.GetMoves();

            // If we've played at lest once, find a suggested antipode path and try that
            if (bestPathStart >= 0)
            {
                if ((state.Tiles[bestPathStart] > 0 && state.Player == Player.One) || (state.Tiles[bestPathStart] < 0 && state.Player == Player.Two))
                {
                    List <int> suggestedPath = GetSuggestedAntipodePath(state, bestPathStart);
                    suggestedPath = Shuffle(suggestedPath);

                    foreach (int tile in suggestedPath)
                    {
                        if (((state.Tiles[tile] > 0 && state.Player == Player.One) || (state.Tiles[tile] < 0 && state.Player == Player.Two)) || state.Tiles[tile] == 0)
                        {
                            if (moves.Any(x => x == tile && state.Tiles[x] == 0))
                            {
                                // Return the next move in the path to the antipode
                                return(new SearchResult(tile));
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            // If all else fails, pick a random move
            int best = moves[random.Next(moves.Count)];

            bestPathStart = best;
            return(new SearchResult(best));
        }
コード例 #11
0
ファイル: BarricadeEngine.cs プロジェクト: skotz/volcanoes
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            List <int> moves = state.GetMoves();
            int        best  = -3;

            // For each tile we own, figure out how long it'll take to get to it's antipode
            PathResult[] selfPaths  = new PathResult[80];
            PathResult[] enemyPaths = new PathResult[80];
            for (int i = 0; i < 80; i++)
            {
                if ((state.Tiles[i] > 0 && state.Player == Player.One) || (state.Tiles[i] < 0 && state.Player == Player.Two))
                {
                    selfPaths[i] = pathFinder.FindPath(state, i, Constants.Antipodes[i]);
                }
                else
                if (state.Tiles[i] != 0)
                {
                    enemyPaths[i] = pathFinder.FindPath(state, i, Constants.Antipodes[i]);
                }
            }

            // Of all the calculated paths, find the one that's fastest
            PathResult bestSelfPath  = selfPaths.Where(x => x != null && x.Distance != 0).OrderBy(x => x.Distance).FirstOrDefault();
            PathResult bestEnemyPath = enemyPaths.Where(x => x != null && x.Distance != 0).OrderBy(x => x.Distance).FirstOrDefault();

            if (bestSelfPath != null && bestEnemyPath != null)
            {
                if (bestSelfPath.Distance <= bestEnemyPath.Distance - 2)
                {
                    // If we're two moves ahead of our opponent, then run to the finish line
                    foreach (int tile in bestSelfPath.Path)
                    {
                        if (state.Tiles[tile] == 0 && moves.Contains(tile))
                        {
                            best = tile;
                            break;
                        }
                    }
                }
                else
                {
                    // Try to obstruct our opponent's path
                    foreach (int tile in bestEnemyPath.Path)
                    {
                        if (state.Tiles[tile] == 0 && moves.Contains(tile))
                        {
                            best = tile;
                            break;
                        }
                    }
                }
            }

            // When all else fails, pick a random move
            if (best < 0)
            {
                best = moves[random.Next(moves.Count)];
            }

            return(new SearchResult(best));
        }
コード例 #12
0
 public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
 {
     throw new Exception("Just making sure that an exception results in a resignation, not a crash!");
 }
コード例 #13
0
        public SearchResult GetBestMove(Board state, int maxSeconds, EngineCancellationToken token)
        {
            List <int> moves = state.GetMoves();

            // See if we have any pair of points that are antipodes connected by kitty corners
            List <int> antipodePath = new List <int>();

            for (int i = 0; i < 80; i++)
            {
                if ((state.Tiles[i] > 0 && state.Player == Player.One) || (state.Tiles[i] < 0 && state.Player == Player.Two))
                {
                    List <int> path = GetAntipodePath(state, i);
                    if (path.Count > 0)
                    {
                        antipodePath = path;
                        break;
                    }
                }
            }

            // If we have an antipode path, fill in tiles around the path
            if (antipodePath.Count > 0)
            {
                // Find a move in a tile adjacent to a tile in our antipode path
                List <int> adjacentAntipodePath = new List <int>();
                foreach (int i in antipodePath)
                {
                    adjacentAntipodePath.AddRange(Constants.AdjacentIndexes[i]);
                }

                List <int> antipodeSupport = moves.Where(x => adjacentAntipodePath.Contains(x) && state.Tiles[x] == 0).ToList();

                if (antipodeSupport.Count > 0)
                {
                    // There are no more antipode support tiles, so just buff the main path
                    antipodeSupport = moves.Where(x => adjacentAntipodePath.Contains(x)).ToList();
                }

                if (antipodeSupport.Count > 0)
                {
                    // Pick a random antipode path support tile
                    return(new SearchResult(antipodeSupport[random.Next(antipodeSupport.Count)]));
                }
            }
            else
            {
                // If we've played at lest once, find a suggested antipode path and try that
                if (bestPathStart >= 0)
                {
                    if ((state.Tiles[bestPathStart] > 0 && state.Player == Player.One) || (state.Tiles[bestPathStart] < 0 && state.Player == Player.Two))
                    {
                        List <int> suggestedPath = GetSuggestedAntipodePath(state, bestPathStart);
                        foreach (int tile in suggestedPath)
                        {
                            if (((state.Tiles[tile] > 0 && state.Player == Player.One) || (state.Tiles[tile] < 0 && state.Player == Player.Two)) || state.Tiles[tile] == 0)
                            {
                                if (moves.Any(x => x == tile && state.Tiles[x] == 0))
                                {
                                    // Return the next move in the path to the antipode
                                    return(new SearchResult(tile));
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }

                // If we don't have an antipode path, continue connecting A tiles kitty corner until we do
                // Use old tile names since new ones don't have As
                List <int> alphaMoves = moves.Where(x => Constants.OldTileNames[x].EndsWith("A")).ToList();

                if (alphaMoves.Count > 0)
                {
                    List <int> primaryKittyCornerMoves = new List <int>();
                    List <int> kittyCornerMoves        = new List <int>();
                    foreach (int move in alphaMoves)
                    {
                        if (state.Tiles[move] == 0)
                        {
                            int adjacentCount = 0;
                            foreach (int i in Constants.KittyCornerTiles[move])
                            {
                                if (state.Tiles[i] == 0)
                                {
                                    adjacentCount++;

                                    if (!kittyCornerMoves.Contains(move))
                                    {
                                        kittyCornerMoves.Add(move);
                                    }
                                }
                            }

                            if (adjacentCount == 1)
                            {
                                // Only one adjacent kitty corner, so this is good
                                primaryKittyCornerMoves.Add(move);
                            }
                        }
                    }

                    if (primaryKittyCornerMoves.Count > 0)
                    {
                        // Pick a random primary kitty corner move
                        int best = primaryKittyCornerMoves[random.Next(primaryKittyCornerMoves.Count)];
                        bestPathStart = best;
                        return(new SearchResult(best));
                    }
                    else if (kittyCornerMoves.Count > 0)
                    {
                        // Pick a random kitty corner move
                        int best = kittyCornerMoves[random.Next(kittyCornerMoves.Count)];
                        bestPathStart = best;
                        return(new SearchResult(best));
                    }
                    else
                    {
                        // Pick a random A tile
                        int best = alphaMoves[random.Next(alphaMoves.Count)];
                        bestPathStart = best;
                        return(new SearchResult(best));
                    }
                }
            }

            // If all else fails, pick a random move
            return(new SearchResult(moves[random.Next(moves.Count)]));
        }