Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 19 additions & 40 deletions astar.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,46 +23,24 @@ type node struct {
cost float64
rank float64
parent *node
open bool
closed bool
index int
}

// nodeMap is a collection of nodes keyed by Pather nodes for quick reference.
type nodeMap map[Pather]*node

// get gets the Pather object wrapped in a node, instantiating if required.
func (nm nodeMap) get(p Pather) *node {
n, ok := nm[p]
if !ok {
n = &node{
pather: p,
}
nm[p] = n
}
return n
}

// Path calculates a short path and the distance between the two Pather nodes.
//
// If no path is found, found will be false.
func Path(from, to Pather) (path []Pather, distance float64, found bool) {
nm := nodeMap{}
nq := &priorityQueue{}
heap.Init(nq)
fromNode := nm.get(from)
fromNode.open = true
heap.Push(nq, fromNode)
for {
if nq.Len() == 0 {
// There's no path, return found false.
return
}
current := heap.Pop(nq).(*node)
current.open = false
current.closed = true
fromNode := &node{pather: from}
closeset := nodeMap{from: fromNode}
openset := &priorityQueue{fromNode}
heap.Init(openset)
for openset.Len() > 0 {
current := heap.Pop(openset).(*node)

if current == nm.get(to) {
if current.pather == to {
// Found a path to the goal.
p := []Pather{}
curr := current
Expand All @@ -74,22 +52,23 @@ func Path(from, to Pather) (path []Pather, distance float64, found bool) {
}

for _, neighbor := range current.pather.PathNeighbors() {
cost := current.cost + current.pather.PathNeighborCost(neighbor)
neighborNode := nm.get(neighbor)
if cost < neighborNode.cost {
if neighborNode.open {
heap.Remove(nq, neighborNode.index)
}
neighborNode.open = false
neighborNode.closed = false
neighborNode, exists := closeset[neighbor]
if !exists {
neighborNode = &node{pather: neighbor}
closeset[neighbor] = neighborNode
}
if !neighborNode.open && !neighborNode.closed {
cost := current.cost + current.pather.PathNeighborCost(neighbor)
if !exists || cost < neighborNode.cost {
neighborNode.cost = cost
neighborNode.open = true
neighborNode.rank = cost + neighbor.PathEstimatedCost(to)
neighborNode.parent = current
heap.Push(nq, neighborNode)
if exists {
heap.Fix(openset, neighborNode.index)
} else {
heap.Push(openset, neighborNode)
}
}
}
}
return
}