Skip to content

Commit

Permalink
Added more levels, modified algorithm.
Browse files Browse the repository at this point in the history
I added a few new pre-defined levels (with more to come) and changed the
A* algorithm so that it will no longer move through corners.
  • Loading branch information
packetpirate committed Apr 27, 2015
1 parent 6ccc453 commit 15de2d3
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 33 deletions.
76 changes: 46 additions & 30 deletions constants.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
(define F_WIDTH 600)
(define F_HEIGHT 600)
(define GRID_SIZE 15)
(define NEIGHBORS '((0 -1) (1 -1) (1 0) (1 1) (0 1) (-1 1) (-1 0) (-1 -1)))
(define NEIGHBORS '((0 -1) (1 -1) (1 0) (1 1) (0 1) (-1 1) (-1 0) (-1 -1))) ; Allow for horizontal, vertical and diagonal movements.
;(define NEIGHBORS '((0 -1) (1 0) (0 1) (-1 0))) ; Allow for only vertical and horizontal movement.
(define nil '())

; Globals
Expand Down Expand Up @@ -108,6 +109,30 @@
(list-ref li (+ (* row GRID_SIZE) col)))
h)

; Check if the neighbor being examed is next to a neighbor that is unwalkable.
(define (noNeighborWalls GRID t p)
(cond ([and (= (car p) -1) (= (cadr p) -1)] ; Upper-left neighbor. Check tiles above and to the left of t.
(if (or (not (send ((get (+ (cadr p) (send t getRow)) (+ (car p) 1 (send t getCol))) GRID) isWalkable))
(not (send ((get (+ (cadr p) 1 (send t getRow)) (+ (car p) (send t getCol))) GRID) isWalkable)))
#f
#t))
([and (= (car p) 1) (= (cadr p) -1)] ; Upper-right neighbor. Check tiles above and to the right of t.
(if (or (not (send ((get (+ (cadr p) (send t getRow)) (+ (- (car p) 1) (send t getCol))) GRID) isWalkable))
(not (send ((get (+ (cadr p) 1 (send t getRow)) (+ (car p) (send t getCol))) GRID) isWalkable)))
#f
#t))
([and (= (car p) -1) (= (cadr p) 1)] ; Bottom-left neighbor. Check tiles below and to the left of t.
(if (or (not (send ((get (+ (- (cadr p) 1) (send t getRow)) (+ (car p) (send t getCol))) GRID) isWalkable))
(not (send ((get (+ (cadr p) (send t getRow)) (+ (car p) 1 (send t getCol))) GRID) isWalkable)))
#f
#t))
([and (= (car p) 1) (= (cadr p) 1)] ; Bottom-right neighbor. Check tiles below and to the right of t.
(if (or (not (send ((get (+ (cadr p) (send t getRow)) (+ (- (car p) 1) (send t getCol))) GRID) isWalkable))
(not (send ((get (+ (- (cadr p) 1) (send t getRow)) (+ (car p) (send t getCol))) GRID) isWalkable)))
#f
#t))
(else #t)))

; Get the neighbors of the given tile.
(define (getNeighbors GRID t)
(let ([ne '()])
Expand All @@ -116,16 +141,21 @@
(let ([a (cons (+ (send t getRow) (car p)) (+ (send t getCol) (cadr p)))])
; Only get the walkable tiles.
(when (and (validRowCol? (car a) (cdr a))
(send ((get (car a) (cdr a)) GRID) isWalkable))
(send ((get (car a) (cdr a)) GRID) isWalkable)
(noNeighborWalls GRID t p) ; Comment out to allow walking through corners.
)
(set! ne (append ne (list ((get (car a) (cdr a)) GRID)))))))
NEIGHBORS)
ne))

; Find the tile in the open list with the lowest F score.
(define (lowestF open)
; Recurse through the entire open list. Each time it encounters a
; tile with a lower F score, it overrides the current "lowest F tile".
(define (lowestF-help open t)
(cond ([empty? open] t)
([< (send (car open) getF) (send t getF)] (lowestF-help (cdr open) (car open)))
([< (send (car open) getF) (send t getF)]
(lowestF-help (cdr open) (car open)))
(else (lowestF-help (cdr open) t))))
(lowestF-help open (car open)))

Expand All @@ -146,23 +176,17 @@
(set! PATH (append PATH (list current)))
(retrace-help))))
(retrace-help)
(set! PATH (reverse PATH))))

; Look through parents to find start.
;(define (parent-ception C n)
; (if (= n 0)
; (begin (display "Row of Current Parent: ")
; (pretty-print (send C getRow))
; (display "Col of Current Parent: ")
; (pretty-print (send C getCol)))
; (parent-ception (send C getParent) (- n 1))))
(if (not (sameTile? (list-ref PATH 0) ((get (cdr goal) (car goal)) GRID)))
(begin (set! PATH '())
(display "No path could be found."))
(set! PATH (reverse PATH)))))

; Define the A* search function.
(define (search GRID A B)
(let ([open nil]
[closed nil]
[current nil]
[neighbors nil])
(let ([open nil] ; The open list, which contains tiles for the algorithm to consider as it walks through the "maze".
[closed nil] ; The closed list, which contains tiles that have already been considered (traversed) and can be ignored.
[current nil] ; The current tile.
[neighbors nil]) ; A list containing the neighbors of the current tile.
(set! open (append open (list A))) ; Add the start tile to the open list.
(define (searchLoop)
(begin (set! current (lowestF open)) ; Find the tile in the open list with the lowest F score.
Expand All @@ -172,24 +196,16 @@
(begin (set! neighbors (getNeighbors GRID current)) ; Retrieve the 8 neighbor tiles surrounding the current tile. Un-walkable tiles excluded.
(map (lambda (t) ; Map over each neighbor tile...
(unless (member t closed) ; Ignore tiles that are on the closed list... we've already "explored" them.
; (if (not (member t open)) ; If the tile is not yet on the open list, add it to the open list and compute its F score.
; (begin (send t setG (compG current t)) ; Compute the G score of the neighbor.
; (send t setH (compH t B)) ; Compute the H score of the neighbor.
; (send t setF (compF (send t getG) (send t getH))) ; Compute the F score of the neighbor.
; (send t setParent current) ; Set the parent of the neighbor to the current tile.
; (set! open (append open (list t)))) ; Add the neighbor to the open list.
; ; If it's on the open list, but not the closed list, see if it's a better path than the current tile.
; ())
(when (not (member t open))
(begin (send t setG (compG current t)) ; Compute the G score of the neighbor.
(when (not (member t open)) ; If the neighbor is not in the open list...
(begin (send t setG (compG current t)) ; Compute the G score of the neighbor.
(send t setH (compH t B)) ; Compute the H score of the neighbor.
(send t setF (compF (send t getG) (send t getH))) ; Compute the F score of the neighbor.
(send t setParent current) ; Set the parent of the neighbor to the current tile.
(set! open (append open (list t)))))))
(set! open (append open (list t))))))) ; Add the neighbor to the open list.
neighbors)
(unless (empty? open) (searchLoop)))))) ; If there are no more tiles in the open list, we're done searching.
(searchLoop)
(retrace GRID A current)))
(searchLoop) ; Call the search procedure's main loop.
(retrace GRID A current))) ; Retrace the steps from goal to start to find the path that the "player" takes.

; Used to move the player around the grid.
(define (move rOff cOff)
Expand Down
4 changes: 3 additions & 1 deletion levels.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
(require "constants.rkt")

(define maps (list (file->lines "levels/level1.txt")
(file->lines "levels/level2.txt")))
(file->lines "levels/level2.txt")
(file->lines "levels/level3.txt")
(file->lines "levels/level4.txt")))

; Checks to make sure the map in the file is a 15x15 grid.
(define (validMap? m)
Expand Down
15 changes: 15 additions & 0 deletions levels/level3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
111111111111111
1000000000000S1
101111111111111
100000000000001
111111111111101
100000001000101
101111101010101
100000101010101
111110101010101
111110101010101
100000100010001
101111111111111
100000000000001
1000000000000E1
111111111111111
15 changes: 15 additions & 0 deletions levels/level4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
111111111111111
1000000S0000001
100000000000001
100000000000001
100000000000001
100000000000001
100000000000001
111111111111111
100000000000001
100000000000001
100000000000001
100000000000001
100000000000001
1000000E0000001
111111111111111
8 changes: 6 additions & 2 deletions tune_traveler.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
(define GRID (createGrid GRID_SIZE GRID_SIZE))

; Define the level to use for the algorithm.
(buildMap GRID (list-ref maps 1))
(buildMap GRID (list-ref maps 0))

; Reset the player position. (weird bug, player will appear at (0,0) elsewise)
(movePlayer (cdr start) (car start))

; Call the search algorithm to generate the path.
(search GRID ((get (cdr start) (car start)) GRID) ((get (cdr goal) (car goal)) GRID))

Expand Down Expand Up @@ -62,7 +66,7 @@
(define r (cdr player))
(define c (car player))
(define s (/ TILE_SIZE 4))
(glColor3f 0.0 0.0 1.0)
(glColor3f 0.0 1.0 1.0)
(glVertex3f (+ (* c TILE_SIZE) GRID_OFF s) (+ (* r TILE_SIZE) s) 0.0)
(glVertex3f (+ (* c TILE_SIZE) GRID_OFF TILE_SIZE (- s)) (+ (* r TILE_SIZE) s) 0.0)
(glVertex3f (+ (* c TILE_SIZE) GRID_OFF TILE_SIZE (- s)) (+ (* r TILE_SIZE) TILE_SIZE (- s)) 0.0)
Expand Down

0 comments on commit 15de2d3

Please sign in to comment.