Renamed files: constanten→constants, adt-positie→adt-position, adt-doolhof→adt-maze, adt-sleutel→adt-key, adt-tijdslimiet→adt-timer, adt-teken→adt-draw, adt-spel→adt-game. All message names, variables, comments, and tests converted to English. Also fixed counter location bug (time-label x/y were swapped). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
119 lines
5.4 KiB
Racket
119 lines
5.4 KiB
Racket
#lang r7rs
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Maze ADT ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; The maze contains the logical grid with cells. Each cell has a type
|
|
;; (wall, coin, empty, key, door). This ADT contains NO graphics code.
|
|
|
|
(define-library (pacman-project adt-maze)
|
|
(import (scheme base)
|
|
(pacman-project constants))
|
|
(export make-maze)
|
|
|
|
(begin
|
|
|
|
;; make-maze :: -> maze
|
|
;; Creates a new maze object with the full grid.
|
|
(define (make-maze)
|
|
|
|
;; The maze grid: 31 rows x 28 columns.
|
|
;; vector is used because it is mutable (unlike #()).
|
|
(define grid
|
|
(vector (vector 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
|
|
(vector 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1)
|
|
(vector 1 0 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 1 0 0 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 1 4 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
|
|
(vector 1 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 1)
|
|
(vector 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1)
|
|
(vector 2 2 2 2 2 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 2 2 2 2 2)
|
|
(vector 2 2 2 2 2 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 2 2 2 2 2)
|
|
(vector 2 2 2 2 2 1 0 1 1 0 1 1 1 4 4 1 1 1 0 1 1 0 1 2 2 2 2 2)
|
|
(vector 1 1 1 1 1 1 0 1 1 0 1 2 2 2 2 2 2 1 0 1 1 0 1 1 1 1 1 1)
|
|
(vector 2 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 2)
|
|
(vector 1 1 1 1 1 1 0 1 1 0 1 2 2 2 2 2 2 1 0 1 1 0 1 1 1 1 1 1)
|
|
(vector 2 2 2 2 2 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 2 2 2 2 2)
|
|
(vector 2 2 2 2 2 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 2 2 2 2 2)
|
|
(vector 2 2 2 2 2 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 2 2 2 2 2)
|
|
(vector 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1)
|
|
(vector 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1)
|
|
(vector 1 0 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 0 1)
|
|
(vector 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1)
|
|
(vector 1 1 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 1 0 1 1 1)
|
|
(vector 1 1 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 0 1 1 0 1 1 1)
|
|
(vector 1 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 4 1 0 0 0 0 0 0 1)
|
|
(vector 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1)
|
|
(vector 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1)
|
|
(vector 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)
|
|
(vector 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)))
|
|
|
|
(define num-rows (vector-length grid))
|
|
(define num-cols (vector-length (vector-ref grid 0)))
|
|
|
|
;; cell-ref :: number, number -> number
|
|
;; Returns the cell type at the given position.
|
|
(define (cell-ref row col)
|
|
(vector-ref (vector-ref grid row) col))
|
|
|
|
;; cell-set! :: number, number, number -> /
|
|
;; Sets the cell type at the given position.
|
|
(define (cell-set! row col value)
|
|
(vector-set! (vector-ref grid row) col value))
|
|
|
|
;; wall? :: number, number -> boolean
|
|
(define (wall? row col)
|
|
(= (cell-ref row col) cell-type-wall))
|
|
|
|
;; coin? :: number, number -> boolean
|
|
(define (coin? row col)
|
|
(= (cell-ref row col) cell-type-coin))
|
|
|
|
;; empty? :: number, number -> boolean
|
|
(define (empty? row col)
|
|
(= (cell-ref row col) cell-type-empty))
|
|
|
|
;; key? :: number, number -> boolean
|
|
(define (key? row col)
|
|
(= (cell-ref row col) cell-type-key))
|
|
|
|
;; door? :: number, number -> boolean
|
|
(define (door? row col)
|
|
(= (cell-ref row col) cell-type-door))
|
|
|
|
;; remove-door! :: number, number -> /
|
|
;; Removes a door from the grid (makes the cell empty).
|
|
(define (remove-door! row col)
|
|
(cell-set! row col cell-type-empty))
|
|
|
|
;; for-each-cell :: (number, number, number -> /) -> /
|
|
;; Iterates over all cells, calling callback with row, col, cell-type.
|
|
(define (for-each-cell callback)
|
|
(do ((row 0 (+ row 1)))
|
|
((= row num-rows))
|
|
(do ((col 0 (+ col 1)))
|
|
((= col num-cols))
|
|
(callback row col (cell-ref row col)))))
|
|
|
|
;; dispatch-maze :: symbol -> any
|
|
(define (dispatch-maze msg)
|
|
(cond ((eq? msg 'rows) num-rows)
|
|
((eq? msg 'cols) num-cols)
|
|
((eq? msg 'cell-ref) cell-ref)
|
|
((eq? msg 'cell-set!) cell-set!)
|
|
((eq? msg 'wall?) wall?)
|
|
((eq? msg 'coin?) coin?)
|
|
((eq? msg 'empty?) empty?)
|
|
((eq? msg 'key?) key?)
|
|
((eq? msg 'door?) door?)
|
|
((eq? msg 'remove-door!) remove-door!)
|
|
((eq? msg 'for-each-cell) for-each-cell)
|
|
(else (error "Maze ADT -- Unknown message:" msg))))
|
|
|
|
dispatch-maze)))
|