public AStarState Create(Board board, AStarState previousState) { int currentScore = wrongPlacesHeuristicScoreComputer.Compute(board); int previousScore = previousState?.TotalHeuristicScore ?? 0; int totalScore = previousScore + currentScore; return(new AStarState(board, previousState, currentScore, totalScore)); }
public AStarState(AStarState <Node> copy) { open = new HashSet <Node>(copy.open); closed = new HashSet <Node>(copy.closed); gs = new Dictionary <Node, float>(copy.gs); fs = new Dictionary <Node, float>(copy.fs); previous = new Dictionary <Node, Node>(copy.previous); current = copy.current; finished = copy.finished; }
public void AStarPathSync() { AStarState <Point> state = new AStarState <Point>(); state.Start = new Point(4, 2); state.EndPoints.Add(new Point(5, 15)); var astar = new AStar <Point>(new FakeMap()); astar.FindPathSync(state); // two steps to the left to get to (2, 2) // 13 steps down to get to (2, 15) // 3 steps to the right to get to (5, 15) // that's 18 steps, plus the start point makes 19. state.Path.Count.Should().Be(19); }
public IEnumerable <Point> GetAvailableSteps(AStarState <Point> task, Point location) { for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { if (i == j || i == -j) { continue; } Point trial = new Point(location.X + i, location.Y + j); if (IsAvailable(trial)) { yield return(trial); } } } }
static void DebugGoap(AStarState <Node> state) { var candidate = state.current; U.Log("OPEN SET " + state.open.Aggregate("", (a, x) => a + x.ToString() + "\n\n")); U.Log("CLOSED SET " + state.closed.Aggregate("", (a, x) => a + x.ToString() + "\n\n")); U.Log("CHOSEN CANDIDATE COST " + state.fs[candidate] + ":" + candidate.ToString()); if (state is AStarState <GOAPState> ) { U.Log("SEQUENCE FOR CANDIDATE" + U.Generate(state.current, n => state.previous[n]) .TakeWhile(x => x != null) .Reverse() .Select(x => x as GOAPState) .Where(x => x != null && x.generatingAction != null) .Aggregate("", (a, x) => a + "-->" + x.generatingAction.name) ); var prevs = state.previous as Dictionary <GOAPState, GOAPState>; U.Log("Other candidate chains:\n" + prevs .Select(kv => kv.Key) .Where(y => !prevs.ContainsValue(y)) .Aggregate("", (a, y) => a + U.Generate(y, n => prevs[n]) .TakeWhile(x => x != null) .Reverse() .Select(x => x as GOAPState) .Where(x => x != null && x.generatingAction != null) .Aggregate("", (a2, x) => a2 + "-->" + x.generatingAction.name + "(" + x.step + ")") + " (COST: g" + (state.gs)[y as Node] + " f" + state.fs[y as Node] + ")" + "\n" ) ); } }
//expand can return null as "no neighbours" public static IEnumerable <Node> Run ( Node from, Node to, Func <Node, Node, float> h, //Current, Goal -> Heuristic cost Func <Node, bool> satisfies, //Current -> Satisfies Func <Node, IEnumerable <Arc> > expand //Current -> (Endpoint, Cost)[] ) { var initialState = new AStarState <Node>(); initialState.open.Add(from); initialState.gs[from] = 0; initialState.fs[from] = h(from, to); initialState.previous[from] = null; initialState.current = from; var state = initialState; while (state.open.Count > 0 && !state.finished) { //Debugger gets buggy af with this, can't watch variable: state = state.Clone(); var candidate = state.open.OrderBy(x => state.fs[x]).First(); state.current = candidate; //DebugGoap(state); if (satisfies(candidate)) { U.Log("SATISFIED"); state.finished = true; } else { state.open.Remove(candidate); state.closed.Add(candidate); var neighbours = expand(candidate); if (neighbours == null || !neighbours.Any()) { continue; } var gCandidate = state.gs[candidate]; foreach (var ne in neighbours) { if (ne.endpoint.In(state.closed)) { continue; } var gNeighbour = gCandidate + ne.cost; state.open.Add(ne.endpoint); if (gNeighbour > state.gs.DefaultGet(ne.endpoint, () => gNeighbour)) { continue; } state.previous[ne.endpoint] = candidate; state.gs[ne.endpoint] = gNeighbour; state.fs[ne.endpoint] = gNeighbour + h(ne.endpoint, to); } } } if (!state.finished) { return(null); } //Climb reversed tree. var seq = U.Generate(state.current, n => state.previous[n]) .TakeWhile(n => n != null) .Reverse(); return(seq); }
public void ReportProgress(AStarState <Point> task) { }
public static IEnumerator Run ( Node start, Func <Node, float> heuristic, Func <Node, bool> satisfies, Func <Node, IEnumerable <NodeCost> > expand, Action <IEnumerable <Node> > callback ) { var initialState = new AStarState <Node>(); initialState.open.Add(start); initialState.gs[start] = 0; initialState.fs[start] = heuristic(start); initialState.previous[start] = null; initialState.current = start; var state = initialState; while (state.open.Count > 0 && !state.finished) { state = state.Clone(); var candidate = state.open.OrderBy(x => state.fs[x]).First(); state.current = candidate; if (satisfies(candidate)) { state.finished = true; } else { state.open.Remove(candidate); state.closed.Add(candidate); var neighbours = expand(candidate); if (neighbours == null || !neighbours.Any()) { continue; } var gCandidate = state.gs[candidate]; foreach (var neighbour in neighbours) { if (neighbour.endpoint.In(state.closed)) { continue; } var gNeighbour = gCandidate + neighbour.cost; state.open.Add(neighbour.endpoint); if (gNeighbour > state.gs.DefaultGet(neighbour.endpoint, () => gNeighbour)) { continue; } state.previous[neighbour.endpoint] = candidate; state.gs[neighbour.endpoint] = gNeighbour; state.fs[neighbour.endpoint] = gNeighbour + heuristic(neighbour.endpoint); } } yield return(null); } if (!state.finished) { callback(null); } else { var seq = AStarUtility.Generate(state.current, n => state.previous[n]) .TakeWhile(n => n != null) .Reverse(); callback(seq); } }