mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-29 23:58:34 +01:00
use dictionaries in favor of lists for AStar to speed up pathfinding
This commit is contained in:
parent
a5c1b6c2b4
commit
4f63770de0
1 changed files with 18 additions and 20 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MLEM.Pathfinding {
|
namespace MLEM.Pathfinding {
|
||||||
|
@ -91,25 +92,23 @@ namespace MLEM.Pathfinding {
|
||||||
var tries = maxTries ?? this.DefaultMaxTries;
|
var tries = maxTries ?? this.DefaultMaxTries;
|
||||||
var defCost = defaultCost ?? this.DefaultCost;
|
var defCost = defaultCost ?? this.DefaultCost;
|
||||||
|
|
||||||
var open = new List<PathPoint<T>>();
|
var open = new Dictionary<T, PathPoint<T>>();
|
||||||
var closed = new List<PathPoint<T>>();
|
var closed = new Dictionary<T, PathPoint<T>>();
|
||||||
open.Add(new PathPoint<T>(start, this.GetManhattanDistance(start, goal), null, 0, defCost));
|
open.Add(start, new PathPoint<T>(start, this.GetManhattanDistance(start, goal), null, 0, defCost));
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
Stack<T> ret = null;
|
Stack<T> ret = null;
|
||||||
while (open.Count > 0) {
|
while (open.Count > 0) {
|
||||||
PathPoint<T> current = null;
|
PathPoint<T> current = null;
|
||||||
var lowestF = float.MaxValue;
|
foreach (var point in open.Values) {
|
||||||
foreach (var point in open)
|
if (current == null || point.F < current.F)
|
||||||
if (point.F < lowestF) {
|
|
||||||
current = point;
|
current = point;
|
||||||
lowestF = point.F;
|
}
|
||||||
}
|
|
||||||
if (current == null)
|
if (current == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
open.Remove(current);
|
open.Remove(current.Pos);
|
||||||
closed.Add(current);
|
closed.Add(current.Pos, current);
|
||||||
|
|
||||||
if (current.Pos.Equals(goal)) {
|
if (current.Pos.Equals(goal)) {
|
||||||
ret = CompilePath(current);
|
ret = CompilePath(current);
|
||||||
|
@ -120,20 +119,19 @@ namespace MLEM.Pathfinding {
|
||||||
foreach (var dir in dirsUsed) {
|
foreach (var dir in dirsUsed) {
|
||||||
var neighborPos = this.AddPositions(current.Pos, dir);
|
var neighborPos = this.AddPositions(current.Pos, dir);
|
||||||
var cost = getCost(current.Pos, neighborPos);
|
var cost = getCost(current.Pos, neighborPos);
|
||||||
if (!float.IsInfinity(cost) && cost < float.MaxValue) {
|
if (!float.IsInfinity(cost) && cost < float.MaxValue && !closed.ContainsKey(neighborPos)) {
|
||||||
var neighbor = new PathPoint<T>(neighborPos, this.GetManhattanDistance(neighborPos, goal), current, cost, defCost);
|
var neighbor = new PathPoint<T>(neighborPos, this.GetManhattanDistance(neighborPos, goal), current, cost, defCost);
|
||||||
if (!closed.Contains(neighbor)) {
|
// check if we already have a waypoint at this location with a worse path
|
||||||
var alreadyIndex = open.IndexOf(neighbor);
|
if (open.TryGetValue(neighborPos, out var alreadyNeighbor)) {
|
||||||
if (alreadyIndex < 0) {
|
if (neighbor.G < alreadyNeighbor.G) {
|
||||||
open.Add(neighbor);
|
open.Remove(neighborPos);
|
||||||
} else {
|
} else {
|
||||||
var alreadyNeighbor = open[alreadyIndex];
|
// if the old waypoint is better, we don't add ours
|
||||||
if (neighbor.G < alreadyNeighbor.G) {
|
continue;
|
||||||
open.Remove(alreadyNeighbor);
|
|
||||||
open.Add(neighbor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add the new neighbor as a possible waypoint
|
||||||
|
open.Add(neighborPos, neighbor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue