private void CheckDeadend(List <IReadOnlyList <BoardPoint> > bestRoutes, GameBoard gameBoard) { var toExclude = new ConcurrentBag <IReadOnlyList <BoardPoint> >(); Parallel.ForEach(bestRoutes, route => { try { var goal = route.Last(); var otherTargets = NiceTargets(gameBoard).Except(new[] { goal }); foreach (var target in otherTargets) { var path = FindPath(goal, target, gameBoard); if (path.Count > 0) { return; } } toExclude.Add(route); Console.WriteLine($"DEADEND {goal} {gameBoard.GetElementAt(goal)}"); } catch (Exception e) { Console.WriteLine(e); } }); foreach (var deadend in toExclude) { bestRoutes.Remove(deadend); } }
private void Report(BoardPoint start, BoardPoint next, IReadOnlyList <BoardPoint> best, GameBoard gameBoard, string name = "GOTO") { var last = best.Last(); Console.WriteLine($"{name} {gameBoard.GetElementAt(last)} at {last}\t{start} -> {next}"); }
private static bool IsAcceptablePath(GameBoard board, BoardPoint leftPoint) { var left = board.GetElementAt(leftPoint); return(left == BoardElement.None || left == BoardElement.FuryPill || left == BoardElement.Apple || left == BoardElement.Gold); }
public IReadOnlyList <Route> FindRoutes(BoardPoint start, IsGoal isGoal, bool stopOnFirstGoal = false, int?maxLength = null) { var result = new List <Route>(); var frontier = new Queue <BoardPoint>(); frontier.Enqueue(start); var cameFrom = new Dictionary <BoardPoint, BoardPoint> { [start] = new BoardPoint() }; while (frontier.Count > 0) { var current = frontier.Dequeue(); var currentElement = _board.GetElementAt(current); var lazyRouteLength = new Lazy <int>(() => GetRouteLength(cameFrom, start, current)); if (isGoal(currentElement, current, () => lazyRouteLength.Value)) { result.Add(CreateRoute(cameFrom, start, current, currentElement)); if (stopOnFirstGoal) { break; } } if (maxLength.HasValue && lazyRouteLength.Value > maxLength) { break; } foreach (var next in GetNeighbors(current)) { if (!cameFrom.ContainsKey(next)) { frontier.Enqueue(next); cameFrom[next] = current; } } } return(result); }
private SnakeAction Think(GameBoard gameBoard, Stopwatch stopwatch) { var start = gameBoard.GetMyHead(); if (start == null) { return(new SnakeAction(false, Direction.Stop)); } var startElement = gameBoard.GetElementAt(start.Value); if (startElement == HeadSleep || startElement == HeadDead) { return(new SnakeAction(false, Direction.Stop)); } var isFury = gameBoard.AmIEvil(); var pathFinder = new PathFinder(gameBoard, isFury); // find all apples/coins var routes = pathFinder.FindRoutes(start.Value, (elem, point, requestRoute) => ConsiderGoal(elem, point, requestRoute, isFury)); // find weighted routes var max = routes.OrderByDescending(r => r.Length).First(); Console.WriteLine($"Max: {max.Length}"); var weighted = FindWeightedRoutes(routes, pathFinder, gameBoard, max); // avoid deadend var possible = weighted.Where(w => !w.Properties.IsDeadEnd).ToList(); if (possible.Count == 0) { Console.WriteLine("DEADEND!!!!"); // choose the longest: in the future it will be changed return(RouteToAction(weighted.OrderByDescending(r => r.Route.Length).First(), start.Value)); } // make a decision var best = Decide(possible, max, isFury, start.Value, pathFinder); return(RouteToAction(best, start.Value)); }