-
Notifications
You must be signed in to change notification settings - Fork 0
/
pathfinding.scm
124 lines (116 loc) · 3.31 KB
/
pathfinding.scm
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
(define (standard-transition state from to seed)
(passable? state from to))
(define (make-standard-heuristic goal)
(lambda (start)
(min-distance start goal)))
(define (standard-cost state from to)
(let ((dir (map - to from)))
(cond ((door? to) 3)
((bad-trap? to) 30)
((and (boulder? to)
(valid-coord? (map + to dir))
(not (seen? (map + to dir))))
; explore other areas first if we don't know where we're pushing
; towards
15)
(else 1))))
(define (find-path-to state start goal)
(find-path state
start
(specialize equal? goal)
(make-standard-heuristic goal)
standard-transition
#f
standard-cost))
(define (find-path-hard state start goal)
(find-path state
start
(specialize equal? goal)
(make-standard-heuristic goal)
(lambda x #t)
#f
(lambda (state from to)
(if (passable? state from to)
(standard-cost state from to)
10))))
; include dark squares
(define (find-path-towards state start goal)
(find-path state
start
(specialize equal? goal)
(make-standard-heuristic goal)
(lambda (state from to seed)
(or (passable? state from to)
(and (not (and (door? from)
(diagonal? (map - to from))))
(not (seen? to))
(char=? (square-char to) #\space))))
#f
(lambda (state from to)
(if (char=? (square-char to) #\space)
1.5
(standard-cost state from to)))))
(define (find-path state start pred heuristic transition transition-seed cost)
(define (make-node parent seed sq)
(let ((g-val (if parent (+ (g parent) (cost state (coord parent) sq)) 0))
(h-val (heuristic sq)))
(list sq parent seed (+ g-val h-val) g-val h-val)))
(define (make-start-node sq)
(make-node #f transition-seed sq))
(define (coord node) (list-ref node 0))
(define (parent node) (list-ref node 1))
(define (seed node) (list-ref node 2))
(define (f node) (list-ref node 3))
(define (g node) (list-ref node 4))
(define (h node) (list-ref node 5))
(define (path-to node)
(define (acc n)
(if (not (parent n))
(list (coord n))
(cons (coord n) (acc (parent n)))))
(reverse (acc node)))
(let loop ((open (list (make-start-node start)))
(closed '()))
(cond
((null? open) #f)
((pred (coord (car open)))
(path-to (car open)))
(else
; (display "examining ")
; (write (car open))
; (newline)
(let* ((current (car open))
(neighbors
(let loop ((ls '())
(squares (neighbor-squares (coord current))))
(cond
((null? squares) ls)
((member (car squares) closed)
(loop ls (cdr squares)))
(else
(let ((s (transition state
(coord current)
(car squares)
(seed current))))
(if s
(loop (cons (make-node current s (car squares))
ls)
(cdr squares))
(loop ls (cdr squares))))))))
(to-add
(filter
(lambda (node)
(or (not (member (coord node) (map coord open)))
(< (g node)
(g (any (lambda (n)
(and (equal? (coord n) (coord node))
n))
open)))))
neighbors)))
(loop
(list-merge (lambda (a b) (< (f a) (f b)))
(filter (lambda (node)
(not (member (coord node) (map coord to-add))))
(cdr open))
to-add)
(cons (coord current) closed)))))))