// JPSPath returns a path from a position to another, including these
// positions, in the path order. It uses the given path slice to avoid
// allocations unless its capacity is not enough. The passable function
// controls which positions can be passed. If diags is false, only movements in
// straight cardinal directions are allowed.
//
// The function returns nil if no path was found.
//
// In most situations, JPSPath has significantly better performance than
// AstarPath. The algorithm's limitation is that it only handles uniform costs
// and natural neighbors in grid geometry.
JPSPath returns a path from a position to another, including these
positions, in the path order. It uses the given path slice to avoid
allocations unless its capacity is not enough. The passable function
controls which positions can be passed. If diags is false, only movements in
straight cardinal directions are allowed.

The function returns nil if no path was found.

In most situations, JPSPath has significantly better performance than
AstarPath. The algorithm's limitation is that it only handles uniform costs
and natural neighbors in grid geometry.
// JPSPath returns a path from a position to another including these // positions in the path order . It uses the given path slice to avoid // allocations unless its capacity is not enough . The passable function // controls which positions can be passed . If diags is false only movements in // straight cardinal directions are allowed . // // The function returns nil if no path was found . // // In most situations JPSPath has significantly better performance than // AstarPath . The algorithm ' s limitation is that it only handles uniform costs // and natural neighbors in grid geometry .
func (pr *PathRange) JPSPath(path []gruid.Point, from, to gruid.Point, passable func(gruid.Point) bool, diags bool) []gruid.Point {
	if !from.In(pr.Rg) || !to.In(pr.Rg) {
		return nil
	}
	if from == to {
		return append(path, from)
	}
	pr.passable = passable
	pr.diags = diags
	path = path[:0]
	pr.initAstar()
	nm := pr.AstarNodes
	nm.Idx++
	defer checkNodesIdx(nm)
	pr.AstarQueue = pr.AstarQueue[:0]
	pqInit(&pr.AstarQueue)
	fromNode := nm.get(pr, from)
	fromNode.Closed = true
	fromNode.Open = false
	neighbors := make([]gruid.Point, 0, 8)
	pr.expandOrigin(from, to)
	)
	for {
		if (&pr.AstarQueue).Len() == 0 {
			return nil
		}
		n := pqPop(&pr.AstarQueue)
		n.Open = false
		n.Closed = true
		if n.P == to {
			path = pr.path(path, from, n)
			return path
		}
		neighbors = pr.neighbors(neighbors[:0], n, to)
		for _, p := range neighbors {
			dir := p.Sub(n.P)
			var q gruid.Point
			var i int
			if pr.diags {
				q, i = pr.jump(p, dir, to, n.Cost)
			} else {
				q, i = pr.jumpNoDiags(p, dir, to, n.Cost)
			}
			if i > 0 {
				pr.addSuccessor(q, n.P, to, n.Cost+i)
			}
		}
	}
}
func ( pr * PathRange ) JPSPath ( path [ ] gruid . Point , from , to gruid . Point , passable func ( gruid . Point ) bool , diags bool ) [ ] gruid . Point { if ! from . In ( pr . Rg ) || ! to . In ( pr . Rg ) { return nil } if from == to { return append ( path , from ) } pr . passable = passable pr . diags = diags path = path [ : 0 ] pr . initAstar ( ) nm := pr . AstarNodes nm . Idx ++ defer checkNodesIdx ( nm ) pr . AstarQueue = pr . AstarQueue [ : 0 ] pqInit ( & pr . AstarQueue ) fromNode := nm . get ( pr , from ) fromNode . Closed = true fromNode . Open = false neighbors := make ( [ ] gruid . Point , 0 , 8 ) pr . expandOrigin ( from , to ) for { if ( & pr . AstarQueue ) . Len ( ) == 0 { return nil } n := pqPop ( & pr . AstarQueue ) n . Open = false n . Closed = true if n . P == to { path = pr . path ( path , from , n ) return path } neighbors = pr . neighbors ( neighbors [ : 0 ] , n , to ) for _ , p := range neighbors { dir := p . Sub ( n . P ) var q gruid . Point var i int if pr . diags { q , i = pr . jump ( p , dir , to , n . Cost ) } else { q , i = pr . jumpNoDiags ( p , dir , to , n . Cost ) } if i > 0 { pr . addSuccessor ( q , n . P , to , n . Cost + i ) } } } }
JPSPath returns a path from a position to another, including these
positions, in the path order.
JPSPath returns a path from a position to another including these positions in the path order .
//logrid.Map(func(p gruid.Point, c gruid.Cell) gruid.Cell { //if passable(p) { //return gruid.Cell{Rune: '.'} //} //return gruid.Cell{Rune: '#'} //}) //logrid.Set(from, gruid.Cell{Rune: 'O'}) //logrid.Set(to, gruid.Cell{Rune: 'G'}) // There's no path. //if pr.passable(to) && pr.passable(from) { //log.Printf("\n%v\n", logrid) //} //if n.P != from && n.P != to { //logrid.Set(n.P, gruid.Cell{Rune: 'X'}) //} //logPath(path) //log.Printf("\n%v\n", logrid)