-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaStar.ts
103 lines (79 loc) · 2.25 KB
/
aStar.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import Node from '../utils/ObservableNode';
import Heap from 'heap-js';
import vm from 'vm';
/**
* aStar.pseudo implementation
*/
async function aStar(start: Node, goal: Node) {
const h = vm.runInNewContext(`(()=>${heuristicStr})()`);
const heuristic = (current) => h(current, goal);
function weightBetween(_nodeA: Node, nodeB: Node) {
return nodeB.weight;
}
const gScore = new Map([[start, 0]]);
const fScore = new Map([[start, heuristic(start)]]);
const openSet = new Heap<Node>((a, b) => {
const aValue = fScore.get(a) ?? Infinity;
const bValue = fScore.get(b) ?? Infinity;
switch (true) {
case aValue > bValue:
return 1;
case aValue < bValue:
return -1;
default:
return 0;
}
});
const cameFrom = new Map();
openSet.add(start);
while (openSet.length > 0) {
const current = openSet.pop()!;
if (current === goal) {
const path = [current];
let cur = cameFrom.get(current);
while (cur) {
path.unshift(cur);
cur = cameFrom.get(cur);
}
for (const p of path) {
await p.setAns();
}
return path;
}
await current.Visit();
const currentGScore = gScore.get(current) ?? Infinity;
const neighbors = current.getNeighbors();
for (const neighbor of neighbors) {
if (neighbor.isWall) {
continue;
}
await neighbor.setExplored();
const tentativeGScore = currentGScore + weightBetween(current, neighbor);
const neighborGScore = gScore.get(neighbor) ?? Infinity;
if (tentativeGScore < neighborGScore) {
openSet.remove(neighbor);
cameFrom.set(neighbor, current);
gScore.set(neighbor, tentativeGScore);
fScore.set(neighbor, tentativeGScore + heuristic(neighbor));
openSet.add(neighbor);
}
}
current.Leave();
}
}
export let heuristicStr = `/**
* current: { x: number; y: number; index: number }
* goal: { x: number; y: number; index: number }
*
* return number
*/
function heuristic(current, goal) {
const dx = Math.abs(current.x - goal.x);
const dy = Math.abs(current.y - goal.y);
return (dx + dy) * 2;
}
`;
export const setHeuristicStr = (str: string) => {
heuristicStr = str;
};
export default aStar;