Refactor(English): Rename all files and identifiers from Dutch to English

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>
This commit is contained in:
joren
2026-03-23 11:06:32 +01:00
parent c3c3c6e86c
commit cd70055bc7
45 changed files with 1936 additions and 1136 deletions

View File

@@ -1,118 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Doolhof ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Het doolhof bevat het logische grid met cellen. Elke cel heeft een type
;; (muur, muntje, leeg, sleutel, deur). Dit ADT bevat GEEN grafische code.
(define-library (pacman-project adt-doolhof)
(import (scheme base)
(pacman-project constanten))
(export maak-doolhof)
(begin
;; maak-doolhof :: -> doolhof
;; Maakt een nieuw doolhof-object aan met het volledige grid.
(define (maak-doolhof)
;; Het doolhof grid: 31 rijen x 28 kolommen.
;; vector wordt gebruikt omdat het mutable is (i.t.t. #()).
(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 aantal-rijen (vector-length grid))
(define aantal-kolommen (vector-length (vector-ref grid 0)))
;; cel-ref :: number, number -> number
;; Geeft het celtype terug op de opgegeven positie.
(define (cel-ref rij kolom)
(vector-ref (vector-ref grid rij) kolom))
;; cel-set! :: number, number, number -> /
;; Past het celtype aan op de opgegeven positie.
(define (cel-set! rij kolom waarde)
(vector-set! (vector-ref grid rij) kolom waarde))
;; muur? :: number, number -> boolean
(define (muur? rij kolom)
(= (cel-ref rij kolom) cel-type-muur))
;; muntje? :: number, number -> boolean
(define (muntje? rij kolom)
(= (cel-ref rij kolom) cel-type-muntje))
;; leeg? :: number, number -> boolean
(define (leeg? rij kolom)
(= (cel-ref rij kolom) cel-type-leeg))
;; sleutel? :: number, number -> boolean
(define (sleutel? rij kolom)
(= (cel-ref rij kolom) cel-type-sleutel))
;; deur? :: number, number -> boolean
(define (deur? rij kolom)
(= (cel-ref rij kolom) cel-type-deur))
;; verwijder-deur! :: number, number -> /
;; Verwijdert een deur uit het grid (maakt de cel leeg).
(define (verwijder-deur! rij kolom)
(cel-set! rij kolom cel-type-leeg))
;; voor-elke-cel :: (number, number, number -> /) -> /
;; Itereert over alle cellen en roept de callback op met rij, kolom en celtype.
(define (voor-elke-cel callback)
(do ((rij 0 (+ rij 1)))
((= rij aantal-rijen))
(do ((kolom 0 (+ kolom 1)))
((= kolom aantal-kolommen))
(callback rij kolom (cel-ref rij kolom)))))
;; dispatch-doolhof :: symbol -> any
(define (dispatch-doolhof msg)
(cond ((eq? msg 'rijen) aantal-rijen)
((eq? msg 'kolommen) aantal-kolommen)
((eq? msg 'cel-ref) cel-ref)
((eq? msg 'cel-set!) cel-set!)
((eq? msg 'muur?) muur?)
((eq? msg 'muntje?) muntje?)
((eq? msg 'leeg?) leeg?)
((eq? msg 'sleutel?) sleutel?)
((eq? msg 'deur?) deur?)
((eq? msg 'verwijder-deur!) verwijder-deur!)
((eq? msg 'voor-elke-cel) voor-elke-cel)
(else (error "Doolhof ADT -- Onbekend bericht:" msg))))
dispatch-doolhof)))

248
pacman-project/adt-draw.rkt Normal file
View File

@@ -0,0 +1,248 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Draw ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; All graphics logic is isolated in this ADT. Game logic knows nothing about
;; pixels, windows, or sprites. Grid-to-pixel conversion happens exclusively
;; here.
(define-library (pacman-project adt-draw)
(import (scheme base)
(pp1 graphics)
(pacman-project constants))
(export make-draw)
(begin
;; make-draw :: number, number -> draw
;; Creates the draw object that handles all rendering.
(define (make-draw width height)
(let ((window (make-window width height "Pacman")))
((window 'set-background!) "black")
;;
;; Layers (order determines draw order)
;;
(define maze-layer ((window 'new-layer!)))
(define coins-layer ((window 'new-layer!)))
(define key-layer ((window 'new-layer!)))
(define pacman-layer ((window 'new-layer!)))
(define ui-layer ((window 'new-layer!)))
(define pause-layer ((window 'new-layer!)))
;;
;; Maze tiles
;;
(define maze-tile (make-tile width height))
((maze-layer 'add-drawable!) maze-tile)
;;
;; Coins tile
;;
(define coins-tile (make-tile width height))
((coins-layer 'add-drawable!) coins-tile)
;;
;; Key sprite (in the maze)
;;
(define key-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((key-sprite 'set-scale!) sprite-scale-key)
((key-layer 'add-drawable!) key-sprite)
;; Key UI indicator (next to the score)
(define key-ui-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((key-ui-sprite 'set-scale!) sprite-scale-key-ui)
((key-ui-sprite 'set-x!) key-ui-x)
((key-ui-sprite 'set-y!) key-ui-y)
;;
;; Pac-Man sprite
;;
(define pacman-bitmap-tiles
(list (make-bitmap-tile "pacman-sprites/pacman-death-1.png")
(make-bitmap-tile "pacman-sprites/pacman-closed.png")
(make-bitmap-tile "pacman-sprites/pacman-open.png")))
(define pacman-sprite (make-tile-sequence pacman-bitmap-tiles))
((pacman-sprite 'set-scale!) sprite-scale-pacman)
((pacman-layer 'add-drawable!) pacman-sprite)
;; Animation state
(define time-since-last-animation 0)
;;
;; UI tiles
;;
(define ui-tile (make-tile width height))
((ui-layer 'add-drawable!) ui-tile)
;;
;; Coordinate conversion
;;
;; grid->pixel-x :: number -> number
(define (grid->pixel-x col)
(* cell-size-px col))
;; grid->pixel-y :: number -> number
(define (grid->pixel-y row)
(+ (* row cell-size-px) maze-offset-y))
;;
;; Draw functions
;;
;; draw-maze! :: maze -> /
;; Draws all walls and doors.
(define (draw-maze! maze)
((maze 'for-each-cell)
(lambda (row col cell-type)
(cond
((= cell-type cell-type-wall)
((maze-tile 'draw-rectangle!)
(grid->pixel-x col)
(grid->pixel-y row)
(- cell-size-px maze-wall-shrink)
(- cell-size-px maze-wall-shrink)
"blue"))
((= cell-type cell-type-door)
((maze-tile 'draw-rectangle!)
(grid->pixel-x col)
(grid->pixel-y row)
(- cell-size-px maze-wall-shrink)
(- cell-size-px maze-wall-shrink)
"pink"))))))
;; draw-coins! :: maze -> /
;; Draws all coins in the maze.
(define (draw-coins! maze)
((coins-tile 'clear!))
((maze 'for-each-cell)
(lambda (row col cell-type)
(when (= cell-type cell-type-coin)
((coins-tile 'draw-rectangle!)
(+ (grid->pixel-x col) coin-inset)
(+ (grid->pixel-y row) coin-inset)
(- cell-size-px (* 2 coin-inset) 6)
(- cell-size-px (* 2 coin-inset) 6)
"yellow")))))
;; draw-key! :: key -> /
;; Draws the key at its position, or shows it in UI if taken.
(define (draw-key! key-obj)
(if (key-obj 'taken?)
(begin
((key-layer 'remove-drawable!) key-sprite)
((key-layer 'add-drawable!) key-ui-sprite))
(let ((pos (key-obj 'position)))
((key-sprite 'set-x!) (grid->pixel-x (pos 'col)))
((key-sprite 'set-y!) (grid->pixel-y (pos 'row))))))
;; draw-pacman! :: pacman, number -> /
;; Draws Pac-Man at its current position with correct rotation.
(define (draw-pacman! pacman delta-time)
(let* ((pos (pacman 'position))
(direction (pacman 'direction)))
;; Set position
((pacman-sprite 'set-x!) (grid->pixel-x (pos 'col)))
((pacman-sprite 'set-y!) (grid->pixel-y (pos 'row)))
;; Set rotation based on direction
(cond ((eq? direction 'right) ((pacman-sprite 'rotate!) rotation-right))
((eq? direction 'left) ((pacman-sprite 'rotate!) rotation-left))
((eq? direction 'up) ((pacman-sprite 'rotate!) rotation-up))
((eq? direction 'down) ((pacman-sprite 'rotate!) rotation-down)))
;; Animation
(set! time-since-last-animation (+ time-since-last-animation delta-time))
(when (>= time-since-last-animation animation-interval-ms)
((pacman-sprite 'set-next!))
(set! time-since-last-animation 0))))
;; draw-ui! :: score, timer -> /
;; Draws the score and time limit on screen.
(define (draw-ui! score timer)
((ui-tile 'clear!))
;; Score
((ui-tile 'draw-text!)
(number->string (score 'points))
score-text-size score-text-x score-text-y "white")
;; Separator line
((ui-tile 'draw-rectangle!)
separator-x 0 separator-width height "white")
;; Time limit
((ui-tile 'draw-text!)
"Time remaining:" time-text-size time-label-x time-label-y "white")
((ui-tile 'draw-text!)
((timer 'format-time))
score-text-size time-value-x time-value-y "white"))
;; draw-pause! :: boolean -> /
;; Shows or hides the pause screen.
(define (draw-pause! paused?)
((pause-layer 'empty!))
(when paused?
(let ((pause-tile (make-tile width height)))
((pause-layer 'add-drawable!) pause-tile)
((pause-tile 'draw-rectangle!) 0 90 670 height "black")
((pause-tile 'draw-text!) "Game Paused" 40 200 400 "red"))))
;; redraw-maze! :: maze -> /
;; Redraws the maze (after door removal).
(define (redraw-maze! maze)
((maze-tile 'clear!))
(draw-maze! maze))
;;
;; Main draw function
;;
;; draw-game! :: game -> /
;; Draws the full game (registered as draw callback).
(define (draw-game! game)
(let ((level (game 'level)))
(draw-pacman! (level 'pacman) 0)
(draw-key! (level 'key))
(draw-coins! (level 'maze))
(draw-ui! (level 'score) (level 'timer))
(draw-pause! (level 'paused?))))
;;
;; Callback registration
;;
;; set-game-loop! :: (number -> /) -> /
(define (set-game-loop! fun)
((window 'set-update-callback!) fun))
;; set-key-callback! :: (symbol, any -> /) -> /
(define (set-key-callback! fun)
((window 'set-key-callback!) fun))
;; start-drawing! :: game -> /
;; Starts drawing by setting the draw callback.
(define (start-drawing! game)
;; Initial maze and coins draw (one-time)
(draw-maze! ((game 'level) 'maze))
(draw-coins! ((game 'level) 'maze))
((window 'set-draw-callback!)
(lambda () (draw-game! game))))
;;
;; Dispatch
;;
(define (dispatch-draw msg)
(cond ((eq? msg 'set-game-loop!) set-game-loop!)
((eq? msg 'set-key-callback!) set-key-callback!)
((eq? msg 'start-drawing!) start-drawing!)
(else (error "Draw ADT -- Unknown message:" msg))))
dispatch-draw))))

View File

@@ -0,0 +1,48 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Game ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Top-level game object that connects the level (logic) with the draw ADT
;; (graphics). Registers callbacks for the game loop, keys, and drawing.
(define-library (pacman-project adt-game)
(import (scheme base)
(pacman-project constants)
(pacman-project adt-level)
(pacman-project adt-draw))
(export make-game)
(begin
;; make-game :: -> game
(define (make-game)
(let ((level (make-level))
(draw (make-draw window-width-px window-height-px)))
;; key-handler :: symbol, any -> /
;; Processes key presses and forwards them to the level.
(define (key-handler status key)
(when (eq? status 'pressed)
((level 'key-press!) key)))
;; game-loop :: number -> /
;; Called each frame for game state updates.
(define (game-loop delta-time)
((level 'update!) delta-time))
;; start! :: -> /
;; Starts the game by registering all callbacks.
(define (start!)
((draw 'set-game-loop!) game-loop)
((draw 'set-key-callback!) key-handler)
((draw 'start-drawing!) dispatch-game))
;; dispatch-game :: symbol -> any
(define (dispatch-game msg)
(cond ((eq? msg 'start!) start!)
((eq? msg 'level) level)
(else (error "Game ADT -- Unknown message:" msg))))
dispatch-game))))

View File

@@ -0,0 +1,55 @@
#lang r7rs
(#%require (only racket/base random))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Key ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The key is placed at a random coin position in the maze. When Pac-Man
;; picks it up, doors can be opened. Contains NO graphics code.
(define-library (pacman-project adt-key)
(import (scheme base)
(pacman-project constants)
(pacman-project adt-position))
(export make-key)
(begin
;; make-key :: maze -> key
;; Creates a key and places it at a random coin position.
(define (make-key maze)
(let ((position #f)
(taken? #f))
;; place-random! :: -> /
;; Places the key on a random cell that contains a coin.
(define (place-random!)
(let loop ((attempts 0))
(if (>= attempts max-placement-attempts)
(error "No valid position found for key")
(let ((col (random 0 (maze 'cols)))
(row (random 0 (maze 'rows))))
(if ((maze 'coin?) row col)
(begin
(set! position (make-position row col))
((maze 'cell-set!) row col cell-type-key))
(loop (+ attempts 1)))))))
;; take! :: -> /
;; Marks the key as taken.
(define (take!)
(set! taken? #t))
;; Initialization: place the key immediately on creation.
(place-random!)
;; dispatch-key :: symbol -> any
(define (dispatch-key msg)
(cond ((eq? msg 'position) position)
((eq? msg 'taken?) taken?)
((eq? msg 'take!) take!)
(else (error "Key ADT -- Unknown message:" msg))))
dispatch-key))))

View File

@@ -4,172 +4,171 @@
;; Level ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Het level bevat alle spellogica: beweging van Pac-Man, botsingsdetectie,
;; muntjes eten, sleutel oppakken, deuren openen, teleportatie, pauze en
;; tijdsbeheer. Bevat GEEN grafische code.
;; Contains all game logic: Pac-Man movement, collision detection, coin/key
;; pickup, door opening, teleportation, pause, and time management.
;; Contains NO graphics code.
(define-library (pacman-project adt-level)
(import (scheme base)
(pacman-project constanten)
(pacman-project adt-positie)
(pacman-project adt-doolhof)
(pacman-project constants)
(pacman-project adt-position)
(pacman-project adt-maze)
(pacman-project adt-pacman)
(pacman-project adt-sleutel)
(pacman-project adt-key)
(pacman-project adt-score)
(pacman-project adt-tijdslimiet))
(export maak-level)
(pacman-project adt-timer))
(export make-level)
(begin
;; maak-level :: -> level
;; Maakt een nieuw level aan met alle spelobjecten.
(define (maak-level)
(let ((doolhof (maak-doolhof))
(pacman (maak-pacman 5 2))
(sleutel #f)
(score (maak-score))
(tijdslimiet (maak-tijdslimiet))
(gepauzeerd? #f))
;; make-level :: -> level
;; Creates a new level with all game objects.
(define (make-level)
(let ((maze (make-maze))
(pacman (make-pacman 5 2))
(key #f)
(score (make-score))
(timer (make-timer))
(paused? #f))
;; Initialiseer de sleutel nadat het doolhof is aangemaakt.
(set! sleutel (maak-sleutel doolhof))
;; Initialize key after maze is created.
(set! key (make-key maze))
;;
;; Richting helpers
;; Direction helpers
;;
;; richting->delta :: symbol -> (number . number)
;; Converteert een richting naar een (delta-rij . delta-kolom) paar.
(define (richting->delta richting)
(cond ((eq? richting 'rechts) (cons 0 1))
((eq? richting 'links) (cons 0 -1))
((eq? richting 'omhoog) (cons -1 0))
((eq? richting 'omlaag) (cons 1 0))
;; direction->delta :: symbol -> (number . number)
;; Converts a direction to a (delta-row . delta-col) pair.
(define (direction->delta direction)
(cond ((eq? direction 'right) (cons 0 1))
((eq? direction 'left) (cons 0 -1))
((eq? direction 'up) (cons -1 0))
((eq? direction 'down) (cons 1 0))
(else (cons 0 0))))
;;
;; Muntje logica
;; Coin logic
;;
;; eet-muntje! :: number, number -> /
;; Verwijdert het muntje op de cel en past score/tijd aan.
(define (eet-muntje! rij kolom)
((doolhof 'cel-set!) rij kolom cel-type-leeg)
((score 'verhoog!))
((tijdslimiet 'verhoog!)))
;; eat-coin! :: number, number -> /
;; Removes the coin at the cell and updates score/time.
(define (eat-coin! row col)
((maze 'cell-set!) row col cell-type-empty)
((score 'increase!))
((timer 'increase!)))
;;
;; Sleutel logica
;; Key logic
;;
;; pak-sleutel-op! :: number, number -> /
;; Pakt de sleutel op en maakt de cel leeg.
(define (pak-sleutel-op! rij kolom)
((doolhof 'cel-set!) rij kolom cel-type-leeg)
((sleutel 'pak-op!)))
;; pick-up-key! :: number, number -> /
;; Picks up the key and clears the cell.
(define (pick-up-key! row col)
((maze 'cell-set!) row col cell-type-empty)
((key 'take!)))
;;
;; Teleportatie logica
;; Teleportation logic
;;
;; teleporteer-horizontaal! :: number, number -> /
;; Teleporteert Pac-Man naar de andere kant van het doolhof.
(define (teleporteer-horizontaal! rij kolom)
(let ((pac-pos (pacman 'positie)))
(cond ((< kolom 0)
((pac-pos 'kolom!) (- (doolhof 'kolommen) 1))
((pac-pos 'rij!) rij))
((>= kolom (doolhof 'kolommen))
((pac-pos 'kolom!) 0)
((pac-pos 'rij!) rij)))))
;; teleport-horizontal! :: number, number -> /
;; Teleports Pac-Man to the other side of the maze.
(define (teleport-horizontal! row col)
(let ((pac-pos (pacman 'position)))
(cond ((< col 0)
((pac-pos 'col!) (- (maze 'cols) 1))
((pac-pos 'row!) row))
((>= col (maze 'cols))
((pac-pos 'col!) 0)
((pac-pos 'row!) row)))))
;;
;; Bewegingslogica
;; Movement logic
;;
;; beweeg-pacman! :: symbol -> /
;; Beweegt Pac-Man in de opgegeven richting met alle spelregels.
(define (beweeg-pacman! richting)
(when (not ((tijdslimiet 'tijd-op?)))
(let* ((delta (richting->delta richting))
(delta-rij (car delta))
(delta-kolom (cdr delta))
(huidige-pos (pacman 'positie))
(volgende-rij (+ (huidige-pos 'rij) delta-rij))
(volgende-kolom (+ (huidige-pos 'kolom) delta-kolom)))
;; move-pacman! :: symbol -> /
;; Moves Pac-Man in the given direction with all game rules.
(define (move-pacman! direction)
(when (not ((timer 'time-up?)))
(let* ((delta (direction->delta direction))
(delta-row (car delta))
(delta-col (cdr delta))
(current-pos (pacman 'position))
(next-row (+ (current-pos 'row) delta-row))
(next-col (+ (current-pos 'col) delta-col)))
;; Pas richting aan voor de teken-laag.
((pacman 'richting!) richting)
;; Update direction for the draw layer.
((pacman 'direction!) direction)
(cond
;; Teleportatie: buiten het grid horizontaal.
((or (< volgende-kolom 0) (>= volgende-kolom (doolhof 'kolommen)))
(teleporteer-horizontaal! volgende-rij volgende-kolom))
;; Teleportation: outside grid horizontally.
((or (< next-col 0) (>= next-col (maze 'cols)))
(teleport-horizontal! next-row next-col))
;; Deur: open alleen als de sleutel opgepakt is.
(((doolhof 'deur?) volgende-rij volgende-kolom)
(when (sleutel 'opgepakt?)
((doolhof 'verwijder-deur!) volgende-rij volgende-kolom)))
;; Door: only open if key has been taken.
(((maze 'door?) next-row next-col)
(when (key 'taken?)
((maze 'remove-door!) next-row next-col)))
;; Normale beweging: alleen als het geen muur is.
;; Normal movement: only if not a wall.
(else
(when (not ((doolhof 'muur?) volgende-rij volgende-kolom))
((pacman 'beweeg!) delta-rij delta-kolom)
;; Controleer wat er op de nieuwe positie staat.
(when (not ((maze 'wall?) next-row next-col))
((pacman 'move!) delta-row delta-col)
;; Check what's at the new position.
(cond
(((doolhof 'sleutel?) volgende-rij volgende-kolom)
(pak-sleutel-op! volgende-rij volgende-kolom))
(((doolhof 'muntje?) volgende-rij volgende-kolom)
(eet-muntje! volgende-rij volgende-kolom)))))))))
(((maze 'key?) next-row next-col)
(pick-up-key! next-row next-col))
(((maze 'coin?) next-row next-col)
(eat-coin! next-row next-col)))))))))
;;
;; Pauze logica
;; Pause logic
;;
;; wissel-pauze! :: -> /
;; Wisselt de pauzetoestand.
(define (wissel-pauze!)
(set! gepauzeerd? (not gepauzeerd?)))
;; toggle-pause! :: -> /
(define (toggle-pause!)
(set! paused? (not paused?)))
;;
;; Toets afhandeling
;; Key handling
;;
;; toets! :: symbol -> /
;; Verwerkt een toetsaanslag.
(define (toets! toets)
;; key-press! :: symbol -> /
;; Processes a key press.
(define (key-press! pressed-key)
(cond
((eq? toets 'escape) (wissel-pauze!))
((not gepauzeerd?)
((eq? pressed-key 'escape) (toggle-pause!))
((not paused?)
(cond
((eq? toets 'right) (beweeg-pacman! 'rechts))
((eq? toets 'left) (beweeg-pacman! 'links))
((eq? toets 'up) (beweeg-pacman! 'omhoog))
((eq? toets 'down) (beweeg-pacman! 'omlaag))))))
((eq? pressed-key 'right) (move-pacman! 'right))
((eq? pressed-key 'left) (move-pacman! 'left))
((eq? pressed-key 'up) (move-pacman! 'up))
((eq? pressed-key 'down) (move-pacman! 'down))))))
;;
;; Update (spellusfunctie)
;; Update (game loop function)
;;
;; update! :: number -> /
;; Wordt elk frame aangeroepen met het aantal verstreken milliseconden.
(define (update! delta-tijd)
(when (not gepauzeerd?)
((tijdslimiet 'verlaag!) delta-tijd)))
;; Called each frame with elapsed milliseconds.
(define (update! delta-time)
(when (not paused?)
((timer 'decrease!) delta-time)))
;;
;; Dispatch
;;
(define (dispatch-level msg)
(cond ((eq? msg 'doolhof) doolhof)
(cond ((eq? msg 'maze) maze)
((eq? msg 'pacman) pacman)
((eq? msg 'sleutel) sleutel)
((eq? msg 'key) key)
((eq? msg 'score) score)
((eq? msg 'tijdslimiet) tijdslimiet)
((eq? msg 'gepauzeerd?) gepauzeerd?)
((eq? msg 'toets!) toets!)
((eq? msg 'timer) timer)
((eq? msg 'paused?) paused?)
((eq? msg 'key-press!) key-press!)
((eq? msg 'update!) update!)
(else (error "Level ADT -- Onbekend bericht:" msg))))
(else (error "Level ADT -- Unknown message:" msg))))
dispatch-level))))

118
pacman-project/adt-maze.rkt Normal file
View File

@@ -0,0 +1,118 @@
#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)))

View File

@@ -4,45 +4,43 @@
;; Pac-Man ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Het Pac-Man ADT beheert de logische toestand van de speler: positie op het
;; grid en de huidige richting. Bevat GEEN grafische code.
;; Manages the logical state of the player: grid position and current
;; direction. Contains NO graphics code.
(define-library (pacman-project adt-pacman)
(import (scheme base)
(pacman-project adt-positie))
(export maak-pacman)
(pacman-project adt-position))
(export make-pacman)
(begin
;; maak-pacman :: number, number -> pacman
;; Maakt een Pac-Man object aan op de opgegeven startpositie (rij, kolom).
(define (maak-pacman start-rij start-kolom)
(let ((positie (maak-positie start-rij start-kolom))
(richting 'rechts))
;; make-pacman :: number, number -> pacman
;; Creates a Pac-Man object at the given start position (row, col).
(define (make-pacman start-row start-col)
(let ((position (make-position start-row start-col))
(direction 'right))
;; positie! :: positie -> /
;; Vervangt de huidige positie.
(define (positie! nieuwe-positie)
(set! positie nieuwe-positie))
;; position! :: position -> /
(define (position! new-position)
(set! position new-position))
;; richting! :: symbol -> /
;; Past de huidige richting aan.
(define (richting! nieuwe-richting)
(set! richting nieuwe-richting))
;; direction! :: symbol -> /
(define (direction! new-direction)
(set! direction new-direction))
;; beweeg! :: number, number -> /
;; Verplaatst Pac-Man met een delta op het grid.
(define (beweeg! delta-rij delta-kolom)
((positie 'rij!) (+ (positie 'rij) delta-rij))
((positie 'kolom!) (+ (positie 'kolom) delta-kolom)))
;; move! :: number, number -> /
;; Moves Pac-Man by a delta on the grid.
(define (move! delta-row delta-col)
((position 'row!) (+ (position 'row) delta-row))
((position 'col!) (+ (position 'col) delta-col)))
;; dispatch-pacman :: symbol -> any
(define (dispatch-pacman msg)
(cond ((eq? msg 'positie) positie)
((eq? msg 'positie!) positie!)
((eq? msg 'richting) richting)
((eq? msg 'richting!) richting!)
((eq? msg 'beweeg!) beweeg!)
(else (error "Pac-Man ADT -- Onbekend bericht:" msg))))
(cond ((eq? msg 'position) position)
((eq? msg 'position!) position!)
((eq? msg 'direction) direction)
((eq? msg 'direction!) direction!)
((eq? msg 'move!) move!)
(else (error "Pac-Man ADT -- Unknown message:" msg))))
dispatch-pacman))))

View File

@@ -1,52 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Positie ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Een positie stelt een locatie voor op het logische grid van het doolhof.
;; Coordinaten zijn in grid-eenheden (rij, kolom), NIET in pixels.
(define-library (pacman-project adt-positie)
(import (scheme base))
(export maak-positie)
(begin
;; maak-positie :: number, number -> positie
;; Maakt een nieuw positie-object aan met rij en kolom op het grid.
(define (maak-positie rij kolom)
;; rij! :: number -> /
;; Past de rij-coordinaat aan.
(define (rij! nieuwe-rij)
(set! rij nieuwe-rij))
;; kolom! :: number -> /
;; Past de kolom-coordinaat aan.
(define (kolom! nieuwe-kolom)
(set! kolom nieuwe-kolom))
;; vergelijk? :: positie -> boolean
;; Controleert of twee posities dezelfde coordinaten hebben.
(define (vergelijk? andere-positie)
(and (= rij (andere-positie 'rij))
(= kolom (andere-positie 'kolom))))
;; beweeg :: number, number -> positie
;; Geeft een nieuwe positie terug verschoven met delta-rij en delta-kolom.
(define (beweeg delta-rij delta-kolom)
(maak-positie (+ rij delta-rij)
(+ kolom delta-kolom)))
;; dispatch-positie :: symbol -> any
(define (dispatch-positie msg)
(cond ((eq? msg 'rij) rij)
((eq? msg 'kolom) kolom)
((eq? msg 'rij!) rij!)
((eq? msg 'kolom!) kolom!)
((eq? msg 'vergelijk?) vergelijk?)
((eq? msg 'beweeg) beweeg)
(else (error "Positie ADT -- Onbekend bericht:" msg))))
dispatch-positie)))

View File

@@ -0,0 +1,50 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Position ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; A position represents a location on the logical maze grid.
;; Coordinates are in grid units (row, col), NOT pixels.
(define-library (pacman-project adt-position)
(import (scheme base))
(export make-position)
(begin
;; make-position :: number, number -> position
;; Creates a new position object with row and column on the grid.
(define (make-position row col)
;; row! :: number -> /
(define (row! new-row)
(set! row new-row))
;; col! :: number -> /
(define (col! new-col)
(set! col new-col))
;; equal? :: position -> boolean
;; Checks whether two positions have the same coordinates.
(define (equal? other)
(and (= row (other 'row))
(= col (other 'col))))
;; move :: number, number -> position
;; Returns a new position shifted by delta-row and delta-col.
(define (move delta-row delta-col)
(make-position (+ row delta-row)
(+ col delta-col)))
;; dispatch-position :: symbol -> any
(define (dispatch-position msg)
(cond ((eq? msg 'row) row)
((eq? msg 'col) col)
((eq? msg 'row!) row!)
((eq? msg 'col!) col!)
((eq? msg 'equal?) equal?)
((eq? msg 'move) move)
(else (error "Position ADT -- Unknown message:" msg))))
dispatch-position)))

View File

@@ -4,29 +4,29 @@
;; Score ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Houdt de score bij. Bevat GEEN grafische code.
;; Tracks the player's score. Contains NO graphics code.
(define-library (pacman-project adt-score)
(import (scheme base)
(pacman-project constanten))
(export maak-score)
(pacman-project constants))
(export make-score)
(begin
;; maak-score :: -> score
;; Maakt een nieuw score-object aan, startend bij 0.
(define (maak-score)
(let ((punten 0))
;; make-score :: -> score
;; Creates a new score object, starting at 0.
(define (make-score)
(let ((points 0))
;; verhoog! :: -> /
;; Verhoogt de score met het aantal punten per muntje.
(define (verhoog!)
(set! punten (+ punten punten-per-muntje)))
;; increase! :: -> /
;; Increases the score by points-per-coin.
(define (increase!)
(set! points (+ points points-per-coin)))
;; dispatch-score :: symbol -> any
(define (dispatch-score msg)
(cond ((eq? msg 'punten) punten)
((eq? msg 'verhoog!) verhoog!)
(else (error "Score ADT -- Onbekend bericht:" msg))))
(cond ((eq? msg 'points) points)
((eq? msg 'increase!) increase!)
(else (error "Score ADT -- Unknown message:" msg))))
dispatch-score))))

View File

@@ -1,56 +0,0 @@
#lang r7rs
(#%require (only racket/base random))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Sleutel ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; De sleutel is een object dat op een willekeurige positie in het doolhof
;; geplaatst wordt. Wanneer Pac-Man de sleutel oppakt, worden deuren geopend.
;; Bevat GEEN grafische code.
(define-library (pacman-project adt-sleutel)
(import (scheme base)
(pacman-project constanten)
(pacman-project adt-positie))
(export maak-sleutel)
(begin
;; maak-sleutel :: doolhof -> sleutel
;; Maakt een sleutel aan en plaatst deze op een willekeurige muntje-positie.
(define (maak-sleutel doolhof)
(let ((positie #f)
(opgepakt? #f))
;; plaats-willekeurig! :: -> /
;; Plaatst de sleutel op een willekeurige cel waar een muntje staat.
(define (plaats-willekeurig!)
(let loop ((pogingen 0))
(if (>= pogingen max-plaatsing-pogingen)
(error "Geen geldige positie gevonden voor sleutel")
(let ((kolom (random 0 (doolhof 'kolommen)))
(rij (random 0 (doolhof 'rijen))))
(if ((doolhof 'muntje?) rij kolom)
(begin
(set! positie (maak-positie rij kolom))
((doolhof 'cel-set!) rij kolom cel-type-sleutel))
(loop (+ pogingen 1)))))))
;; pak-op! :: -> /
;; Markeert de sleutel als opgepakt.
(define (pak-op!)
(set! opgepakt? #t))
;; Initialisatie: plaats de sleutel direct bij aanmaak.
(plaats-willekeurig!)
;; dispatch-sleutel :: symbol -> any
(define (dispatch-sleutel msg)
(cond ((eq? msg 'positie) positie)
((eq? msg 'opgepakt?) opgepakt?)
((eq? msg 'pak-op!) pak-op!)
(else (error "Sleutel ADT -- Onbekend bericht:" msg))))
dispatch-sleutel))))

View File

@@ -1,49 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Spel ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Het top-level spel-object dat het level verbindt met het teken-ADT.
;; Registreert de callbacks voor de spellus, toetsen en tekenen.
(define-library (pacman-project adt-spel)
(import (scheme base)
(pacman-project constanten)
(pacman-project adt-level)
(pacman-project adt-teken))
(export maak-spel)
(begin
;; maak-spel :: -> spel
;; Maakt het spel-object aan.
(define (maak-spel)
(let ((level (maak-level))
(teken (maak-teken venster-breedte-px venster-hoogte-px)))
;; toets-procedure :: symbol, any -> /
;; Verwerkt toetsaanslagen en stuurt ze door naar het level.
(define (toets-procedure status toets)
(when (eq? status 'pressed)
((level 'toets!) toets)))
;; spel-lus-procedure :: number -> /
;; Wordt elk frame aangeroepen voor game-state updates.
(define (spel-lus-procedure delta-tijd)
((level 'update!) delta-tijd))
;; start! :: -> /
;; Start het spel door alle callbacks te registreren.
(define (start!)
((teken 'set-spel-lus-functie!) spel-lus-procedure)
((teken 'set-toets-functie!) toets-procedure)
((teken 'start-tekenen!) dispatch-spel))
;; dispatch-spel :: symbol -> any
(define (dispatch-spel msg)
(cond ((eq? msg 'start!) start!)
((eq? msg 'level) level)
(else (error "Spel ADT -- Onbekend bericht:" msg))))
dispatch-spel))))

View File

@@ -1,252 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Teken ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Alle grafische logica is geisoleerd in dit ADT. De spellogica kent niets
;; over pixels, vensters of sprites. De omzetting van grid-coordinaten naar
;; schermcoordinaten gebeurt uitsluitend hier.
(define-library (pacman-project adt-teken)
(import (scheme base)
(pp1 graphics)
(pacman-project constanten))
(export maak-teken)
(begin
;; maak-teken :: number, number -> teken
;; Maakt het teken-object aan dat alle grafische weergave verzorgt.
(define (maak-teken breedte hoogte)
(let ((venster (make-window breedte hoogte "Pacman")))
((venster 'set-background!) "black")
;;
;; Lagen aanmaken (volgorde bepaalt tekenvolgorde)
;;
(define doolhof-laag ((venster 'new-layer!)))
(define muntjes-laag ((venster 'new-layer!)))
(define sleutel-laag ((venster 'new-layer!)))
(define pacman-laag ((venster 'new-layer!)))
(define ui-laag ((venster 'new-layer!)))
(define pauze-laag ((venster 'new-layer!)))
;;
;; Doolhof tiles
;;
(define doolhof-tile (make-tile breedte hoogte))
((doolhof-laag 'add-drawable!) doolhof-tile)
;;
;; Muntjes tile
;;
(define muntjes-tile (make-tile breedte hoogte))
((muntjes-laag 'add-drawable!) muntjes-tile)
;;
;; Sleutel sprite (in het doolhof)
;;
(define sleutel-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((sleutel-sprite 'set-scale!) sprite-schaal-sleutel)
((sleutel-laag 'add-drawable!) sleutel-sprite)
;; Sleutel UI indicator (naast de score)
(define sleutel-ui-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((sleutel-ui-sprite 'set-scale!) sprite-schaal-sleutel-ui)
((sleutel-ui-sprite 'set-x!) sleutel-ui-x)
((sleutel-ui-sprite 'set-y!) sleutel-ui-y)
;;
;; Pac-Man sprite
;;
(define pacman-bitmap-tiles
(list (make-bitmap-tile "pacman-sprites/pacman-death-1.png")
(make-bitmap-tile "pacman-sprites/pacman-closed.png")
(make-bitmap-tile "pacman-sprites/pacman-open.png")))
(define pacman-sprite (make-tile-sequence pacman-bitmap-tiles))
((pacman-sprite 'set-scale!) sprite-schaal-pacman)
((pacman-laag 'add-drawable!) pacman-sprite)
;; Animatie state
(define tijd-sinds-laatste-animatie 0)
;;
;; UI tiles
;;
(define ui-tile (make-tile breedte hoogte))
((ui-laag 'add-drawable!) ui-tile)
;;
;; Coordinaat conversie
;;
;; grid->pixel-x :: number -> number
;; Converteert een grid kolom naar een pixel x-coordinaat.
(define (grid->pixel-x kolom)
(* cel-grootte-px kolom))
;; grid->pixel-y :: number -> number
;; Converteert een grid rij naar een pixel y-coordinaat.
(define (grid->pixel-y rij)
(+ (* rij cel-grootte-px) doolhof-offset-y))
;;
;; Teken functies
;;
;; teken-doolhof! :: doolhof -> /
;; Tekent alle muren en deuren van het doolhof.
(define (teken-doolhof! doolhof)
((doolhof 'voor-elke-cel)
(lambda (rij kolom celtype)
(cond
((= celtype cel-type-muur)
((doolhof-tile 'draw-rectangle!)
(grid->pixel-x kolom)
(grid->pixel-y rij)
(- cel-grootte-px doolhof-muur-krimp)
(- cel-grootte-px doolhof-muur-krimp)
"blue"))
((= celtype cel-type-deur)
((doolhof-tile 'draw-rectangle!)
(grid->pixel-x kolom)
(grid->pixel-y rij)
(- cel-grootte-px doolhof-muur-krimp)
(- cel-grootte-px doolhof-muur-krimp)
"pink"))))))
;; teken-muntjes! :: doolhof -> /
;; Tekent alle muntjes in het doolhof.
(define (teken-muntjes! doolhof)
((muntjes-tile 'clear!))
((doolhof 'voor-elke-cel)
(lambda (rij kolom celtype)
(when (= celtype cel-type-muntje)
((muntjes-tile 'draw-rectangle!)
(+ (grid->pixel-x kolom) muntje-inset)
(+ (grid->pixel-y rij) muntje-inset)
(- cel-grootte-px (* 2 muntje-inset) 6)
(- cel-grootte-px (* 2 muntje-inset) 6)
"yellow")))))
;; teken-sleutel! :: sleutel -> /
;; Tekent de sleutel op haar positie, of verbergt ze als opgepakt.
(define (teken-sleutel! sleutel)
(if (sleutel 'opgepakt?)
(begin
((sleutel-laag 'remove-drawable!) sleutel-sprite)
((sleutel-laag 'add-drawable!) sleutel-ui-sprite))
(let ((pos (sleutel 'positie)))
((sleutel-sprite 'set-x!) (grid->pixel-x (pos 'kolom)))
((sleutel-sprite 'set-y!) (grid->pixel-y (pos 'rij))))))
;; teken-pacman! :: pacman, number -> /
;; Tekent Pac-Man op zijn huidige positie met de juiste rotatie.
(define (teken-pacman! pacman delta-tijd)
(let* ((pos (pacman 'positie))
(richting (pacman 'richting)))
;; Positie instellen
((pacman-sprite 'set-x!) (grid->pixel-x (pos 'kolom)))
((pacman-sprite 'set-y!) (grid->pixel-y (pos 'rij)))
;; Rotatie instellen op basis van richting
(cond ((eq? richting 'rechts) ((pacman-sprite 'rotate!) rotatie-rechts))
((eq? richting 'links) ((pacman-sprite 'rotate!) rotatie-links))
((eq? richting 'omhoog) ((pacman-sprite 'rotate!) rotatie-omhoog))
((eq? richting 'omlaag) ((pacman-sprite 'rotate!) rotatie-omlaag)))
;; Animatie
(set! tijd-sinds-laatste-animatie (+ tijd-sinds-laatste-animatie delta-tijd))
(when (>= tijd-sinds-laatste-animatie animatie-interval-ms)
((pacman-sprite 'set-next!))
(set! tijd-sinds-laatste-animatie 0))))
;; teken-ui! :: score, tijdslimiet -> /
;; Tekent de score en de tijdslimiet op het scherm.
(define (teken-ui! score tijdslimiet)
((ui-tile 'clear!))
;; Score
((ui-tile 'draw-text!)
(number->string (score 'punten))
score-tekst-grootte score-tekst-x score-tekst-y "white")
;; Scheidingslijn
((ui-tile 'draw-rectangle!)
scheidingslijn-x 0 scheidingslijn-breedte hoogte "white")
;; Tijdslimiet
((ui-tile 'draw-text!)
"Time remaining:" tijd-tekst-grootte tijd-label-x tijd-label-y "white")
((ui-tile 'draw-text!)
((tijdslimiet 'formatteer-tijd))
score-tekst-grootte tijd-waarde-x tijd-waarde-y "white"))
;; teken-pauze! :: boolean -> /
;; Toont of verbergt het pauzescherm.
(define (teken-pauze! gepauzeerd?)
((pauze-laag 'empty!))
(when gepauzeerd?
(let ((pauze-tile (make-tile breedte hoogte)))
((pauze-laag 'add-drawable!) pauze-tile)
((pauze-tile 'draw-rectangle!) 0 90 670 hoogte "black")
((pauze-tile 'draw-text!) "Game Paused" 40 200 400 "red"))))
;; herteken-doolhof! :: doolhof -> /
;; Hertekent het doolhof (na deur verwijdering).
(define (herteken-doolhof! doolhof)
((doolhof-tile 'clear!))
(teken-doolhof! doolhof))
;;
;; Hoofdtekenfunctie
;;
;; teken-spel! :: spel -> /
;; Tekent het volledige spel (wordt als draw-callback geregistreerd).
(define (teken-spel! spel)
(let ((level (spel 'level)))
(teken-pacman! (level 'pacman) 0)
(teken-sleutel! (level 'sleutel))
(teken-muntjes! (level 'doolhof))
(teken-ui! (level 'score) (level 'tijdslimiet))
(teken-pauze! (level 'gepauzeerd?))))
;;
;; Callbacks instellen
;;
;; set-spel-lus-functie! :: (number -> /) -> /
;; Registreert de update-callback.
(define (set-spel-lus-functie! fun)
((venster 'set-update-callback!) fun))
;; set-toets-functie! :: (symbol, any -> /) -> /
;; Registreert de keyboard-callback.
(define (set-toets-functie! fun)
((venster 'set-key-callback!) fun))
;; start-tekenen! :: spel -> /
;; Start het tekenen door de draw-callback in te stellen.
(define (start-tekenen! spel)
;; Initieel doolhof en muntjes tekenen (eenmalig)
(teken-doolhof! ((spel 'level) 'doolhof))
(teken-muntjes! ((spel 'level) 'doolhof))
((venster 'set-draw-callback!)
(lambda () (teken-spel! spel))))
;;
;; Dispatch
;;
(define (dispatch-teken msg)
(cond ((eq? msg 'set-spel-lus-functie!) set-spel-lus-functie!)
((eq? msg 'set-toets-functie!) set-toets-functie!)
((eq? msg 'start-tekenen!) start-tekenen!)
(else (error "Teken ADT -- Onbekend bericht:" msg))))
dispatch-teken))))

View File

@@ -1,63 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tijdslimiet ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Beheert de aftellende tijdslimiet van het spel. Bevat GEEN grafische code.
(define-library (pacman-project adt-tijdslimiet)
(import (scheme base)
(pacman-project constanten))
(export maak-tijdslimiet)
(begin
;; maak-tijdslimiet :: -> tijdslimiet
;; Maakt een nieuw tijdslimiet-object aan.
(define (maak-tijdslimiet)
(let ((resterende-tijd start-tijd-seconden)
(tijd-sinds-laatste-tick 0))
;; verlaag! :: number -> /
;; Verlaagt de tijd op basis van het aantal verstreken milliseconden.
(define (verlaag! ms)
(set! tijd-sinds-laatste-tick (+ tijd-sinds-laatste-tick ms))
(when (>= tijd-sinds-laatste-tick ms-per-seconde)
(set! tijd-sinds-laatste-tick 0)
(when (> resterende-tijd 0)
(set! resterende-tijd (- resterende-tijd 1)))))
;; verhoog! :: -> /
;; Verhoogt de resterende tijd met een bonus (bij het eten van een muntje).
(define (verhoog!)
(set! resterende-tijd (+ resterende-tijd tijd-bonus-per-muntje)))
;; tijd-op? :: -> boolean
;; Controleert of de tijd verstreken is.
(define (tijd-op?)
(= resterende-tijd 0))
;; formatteer-tijd :: -> string
;; Geeft de resterende tijd terug als "m:ss" string.
(define (formatteer-tijd)
(let* ((minuten (quotient resterende-tijd 60))
(seconden (remainder resterende-tijd 60))
(min-str (number->string minuten))
(sec-str (number->string seconden)))
(string-append min-str
":"
(if (< seconden 10)
(string-append "0" sec-str)
sec-str))))
;; dispatch-tijdslimiet :: symbol -> any
(define (dispatch-tijdslimiet msg)
(cond ((eq? msg 'resterende-tijd) resterende-tijd)
((eq? msg 'verlaag!) verlaag!)
((eq? msg 'verhoog!) verhoog!)
((eq? msg 'tijd-op?) tijd-op?)
((eq? msg 'formatteer-tijd) formatteer-tijd)
(else (error "Tijdslimiet ADT -- Onbekend bericht:" msg))))
dispatch-tijdslimiet))))

View File

@@ -0,0 +1,62 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Timer ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Manages the countdown time limit. Contains NO graphics code.
(define-library (pacman-project adt-timer)
(import (scheme base)
(pacman-project constants))
(export make-timer)
(begin
;; make-timer :: -> timer
;; Creates a new timer object.
(define (make-timer)
(let ((remaining-time start-time-seconds)
(time-since-last-tick 0))
;; decrease! :: number -> /
;; Decreases time based on elapsed milliseconds.
(define (decrease! ms)
(set! time-since-last-tick (+ time-since-last-tick ms))
(when (>= time-since-last-tick ms-per-second)
(set! time-since-last-tick 0)
(when (> remaining-time 0)
(set! remaining-time (- remaining-time 1)))))
;; increase! :: -> /
;; Adds a time bonus (when eating a coin).
(define (increase!)
(set! remaining-time (+ remaining-time time-bonus-per-coin)))
;; time-up? :: -> boolean
(define (time-up?)
(= remaining-time 0))
;; format-time :: -> string
;; Returns remaining time as "m:ss" string.
(define (format-time)
(let* ((minutes (quotient remaining-time 60))
(seconds (remainder remaining-time 60))
(min-str (number->string minutes))
(sec-str (number->string seconds)))
(string-append min-str
":"
(if (< seconds 10)
(string-append "0" sec-str)
sec-str))))
;; dispatch-timer :: symbol -> any
(define (dispatch-timer msg)
(cond ((eq? msg 'remaining-time) remaining-time)
((eq? msg 'decrease!) decrease!)
((eq? msg 'increase!) increase!)
((eq? msg 'time-up?) time-up?)
((eq? msg 'format-time) format-time)
(else (error "Timer ADT -- Unknown message:" msg))))
dispatch-timer))))

View File

@@ -1,135 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constanten ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Alle configuratieconstanten voor het Pac-Man spel worden hier gedefinieerd.
;; Dit voorkomt "magic constants" doorheen de code en maakt het spel flexibel
;; aanpasbaar.
(define-library (pacman-project constanten)
(import (scheme base))
(export ;; Venster
venster-breedte-px
venster-hoogte-px
;; Doolhof grid
cel-grootte-px
doolhof-offset-y
doolhof-muur-krimp
;; Cel types
cel-type-muntje
cel-type-muur
cel-type-leeg
cel-type-sleutel
cel-type-deur
;; Muntje weergave
muntje-inset
;; Sprites
sprite-schaal-pacman
sprite-schaal-sleutel
sprite-schaal-sleutel-ui
;; Animatie
animatie-interval-ms
;; Score
punten-per-muntje
;; Tijdslimiet
start-tijd-seconden
ms-per-seconde
tijd-bonus-per-muntje
;; Sleutel plaatsing
max-plaatsing-pogingen
;; Rotatie hoeken
rotatie-rechts
rotatie-links
rotatie-omhoog
rotatie-omlaag
;; UI posities
score-tekst-grootte
score-tekst-x
score-tekst-y
tijd-tekst-grootte
tijd-label-x
tijd-label-y
tijd-waarde-x
tijd-waarde-y
scheidingslijn-x
scheidingslijn-breedte
sleutel-ui-x
sleutel-ui-y)
(begin
;; Venster dimensies
(define venster-breedte-px 1000)
(define venster-hoogte-px 830)
;; Doolhof grid configuratie
(define cel-grootte-px 24)
(define doolhof-offset-y 97)
(define doolhof-muur-krimp 6)
;; Cel type encodering voor het doolhof grid
(define cel-type-muntje 0)
(define cel-type-muur 1)
(define cel-type-leeg 2)
(define cel-type-sleutel 3)
(define cel-type-deur 4)
;; Muntje weergave: inset in pixels ten opzichte van cel rand
(define muntje-inset 7)
;; Sprite schaalfactoren
(define sprite-schaal-pacman 1.5)
(define sprite-schaal-sleutel 1.5)
(define sprite-schaal-sleutel-ui 3)
;; Animatie timing
(define animatie-interval-ms 100)
;; Score configuratie
(define punten-per-muntje 10)
;; Tijdslimiet configuratie
(define start-tijd-seconden 60)
(define ms-per-seconde 1000)
(define tijd-bonus-per-muntje 1)
;; Sleutel plaatsing
(define max-plaatsing-pogingen 1000)
;; Rotatie hoeken (graden)
(define rotatie-rechts 0)
(define rotatie-links 180)
(define rotatie-omhoog 90)
(define rotatie-omlaag -90)
;; UI posities voor score weergave
(define score-tekst-grootte 40)
(define score-tekst-x 560)
(define score-tekst-y 20)
;; UI posities voor tijd weergave
(define tijd-tekst-grootte 35)
(define tijd-label-x 300)
(define tijd-label-y 710)
(define tijd-waarde-x 400)
(define tijd-waarde-y 800)
;; Scheidingslijn tussen speelveld en UI
(define scheidingslijn-x 670)
(define scheidingslijn-breedte 24)
;; Sleutel UI positie (naast score)
(define sleutel-ui-x 20)
(define sleutel-ui-y 35)))

View File

@@ -0,0 +1,134 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; All configuration constants for the Pac-Man game. Prevents magic numbers
;; throughout the codebase and makes the game easily configurable.
(define-library (pacman-project constants)
(import (scheme base))
(export ;; Window
window-width-px
window-height-px
;; Maze grid
cell-size-px
maze-offset-y
maze-wall-shrink
;; Cell types
cell-type-coin
cell-type-wall
cell-type-empty
cell-type-key
cell-type-door
;; Coin rendering
coin-inset
;; Sprites
sprite-scale-pacman
sprite-scale-key
sprite-scale-key-ui
;; Animation
animation-interval-ms
;; Score
points-per-coin
;; Time limit
start-time-seconds
ms-per-second
time-bonus-per-coin
;; Key placement
max-placement-attempts
;; Rotation angles
rotation-right
rotation-left
rotation-up
rotation-down
;; UI positions
score-text-size
score-text-x
score-text-y
time-text-size
time-label-x
time-label-y
time-value-x
time-value-y
separator-x
separator-width
key-ui-x
key-ui-y)
(begin
;; Window dimensions
(define window-width-px 1000)
(define window-height-px 830)
;; Maze grid configuration
(define cell-size-px 24)
(define maze-offset-y 97)
(define maze-wall-shrink 6)
;; Cell type encoding for the maze grid
(define cell-type-coin 0)
(define cell-type-wall 1)
(define cell-type-empty 2)
(define cell-type-key 3)
(define cell-type-door 4)
;; Coin rendering: inset in pixels from cell edge
(define coin-inset 7)
;; Sprite scale factors
(define sprite-scale-pacman 1.5)
(define sprite-scale-key 1.5)
(define sprite-scale-key-ui 3)
;; Animation timing
(define animation-interval-ms 100)
;; Score configuration
(define points-per-coin 10)
;; Time limit configuration
(define start-time-seconds 60)
(define ms-per-second 1000)
(define time-bonus-per-coin 1)
;; Key placement
(define max-placement-attempts 1000)
;; Rotation angles (degrees)
(define rotation-right 0)
(define rotation-left 180)
(define rotation-up 90)
(define rotation-down -90)
;; UI positions for score display
(define score-text-size 40)
(define score-text-x 560)
(define score-text-y 20)
;; UI positions for time display (right side of separator)
(define time-text-size 35)
(define time-label-x 710)
(define time-label-y 300)
(define time-value-x 800)
(define time-value-y 400)
;; Separator line between play field and UI
(define separator-x 670)
(define separator-width 24)
;; Key UI position (next to score)
(define key-ui-x 20)
(define key-ui-y 35)))

View File

@@ -1,11 +1,11 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Spel Opstarten ;;
;; Start Game ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(import (scheme base)
(pacman-project adt-spel))
(pacman-project adt-game))
(define spel (maak-spel))
((spel 'start!))
(define game (make-game))
((game 'start!))

View File

@@ -0,0 +1,24 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; All Tests ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Runs all ADT tests. Open this file and evaluate to run everything.
(import (scheme base)
(pp1 tests)
(prefix (pacman-project tests test-position) position:)
(prefix (pacman-project tests test-maze) maze:)
(prefix (pacman-project tests test-pacman) pacman:)
(prefix (pacman-project tests test-score) score:)
(prefix (pacman-project tests test-timer) timer:))
(define (test-all)
(position:test)
(maze:test)
(pacman:test)
(score:test)
(timer:test))
(test-all)

View File

@@ -1,25 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Alle Testen ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Voert alle ADT-testen uit. Open dit bestand en evalueer om alle testen
;; tegelijkertijd te draaien.
(import (scheme base)
(pp1 tests)
(prefix (pacman-project tests test-positie) positie:)
(prefix (pacman-project tests test-doolhof) doolhof:)
(prefix (pacman-project tests test-pacman) pacman:)
(prefix (pacman-project tests test-score) score:)
(prefix (pacman-project tests test-tijdslimiet) tijdslimiet:))
(define (test-alles)
(positie:test)
(doolhof:test)
(pacman:test)
(score:test)
(tijdslimiet:test))
(test-alles)

View File

@@ -1,59 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Doolhof ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-doolhof)
(import (scheme base)
(pp1 tests)
(pacman-project constanten)
(pacman-project adt-doolhof))
(export test)
(begin
;; Test dimensies
(define (test-dimensies)
(define d (maak-doolhof))
(check-eq? (d 'rijen) 31 "Doolhof moet 31 rijen hebben")
(check-eq? (d 'kolommen) 28 "Doolhof moet 28 kolommen hebben"))
;; Test muur detectie (rij 0 is volledig muur)
(define (test-muur)
(define d (maak-doolhof))
(check ((d 'muur?) 0 0) "Cel (0,0) moet een muur zijn")
(check ((d 'muur?) 0 14) "Cel (0,14) moet een muur zijn"))
;; Test muntje detectie
(define (test-muntje)
(define d (maak-doolhof))
(check ((d 'muntje?) 1 1) "Cel (1,1) moet een muntje zijn")
(check (not ((d 'muntje?) 0 0)) "Cel (0,0) mag geen muntje zijn"))
;; Test deur detectie
(define (test-deur)
(define d (maak-doolhof))
(check ((d 'deur?) 4 3) "Cel (4,3) moet een deur zijn")
(check (not ((d 'deur?) 1 1)) "Cel (1,1) mag geen deur zijn"))
;; Test cel-set! en verwijder-deur!
(define (test-mutatie)
(define d (maak-doolhof))
((d 'verwijder-deur!) 4 3)
(check ((d 'leeg?) 4 3) "Cel (4,3) moet leeg zijn na verwijder-deur!")
(check (not ((d 'deur?) 4 3)) "Cel (4,3) mag geen deur meer zijn"))
;; Test dat Pac-Man niet door muur kan (muur blokkeert)
(define (test-muur-blokkade)
(define d (maak-doolhof))
;; Pac-Man staat op (1,1) en wil naar links (1,0) -> dat is een muur
(check ((d 'muur?) 1 0) "Cel (1,0) is een muur, Pac-Man kan niet door"))
(define (test)
(run-test test-dimensies "Doolhof: dimensies")
(run-test test-muur "Doolhof: muur detectie")
(run-test test-muntje "Doolhof: muntje detectie")
(run-test test-deur "Doolhof: deur detectie")
(run-test test-mutatie "Doolhof: cel mutatie")
(run-test test-muur-blokkade "Doolhof: muur blokkeert beweging"))))

View File

@@ -0,0 +1,58 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Maze ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-maze)
(import (scheme base)
(pp1 tests)
(pacman-project constants)
(pacman-project adt-maze))
(export test)
(begin
;; Test dimensions
(define (test-dimensions)
(define m (make-maze))
(check-eq? (m 'rows) 31 "Maze should have 31 rows")
(check-eq? (m 'cols) 28 "Maze should have 28 cols"))
;; Test wall detection (row 0 is all walls)
(define (test-wall)
(define m (make-maze))
(check ((m 'wall?) 0 0) "Cell (0,0) should be a wall")
(check ((m 'wall?) 0 14) "Cell (0,14) should be a wall"))
;; Test coin detection
(define (test-coin)
(define m (make-maze))
(check ((m 'coin?) 1 1) "Cell (1,1) should be a coin")
(check (not ((m 'coin?) 0 0)) "Cell (0,0) should not be a coin"))
;; Test door detection
(define (test-door)
(define m (make-maze))
(check ((m 'door?) 4 3) "Cell (4,3) should be a door")
(check (not ((m 'door?) 1 1)) "Cell (1,1) should not be a door"))
;; Test cell-set! and remove-door!
(define (test-mutation)
(define m (make-maze))
((m 'remove-door!) 4 3)
(check ((m 'empty?) 4 3) "Cell (4,3) should be empty after remove-door!")
(check (not ((m 'door?) 4 3)) "Cell (4,3) should no longer be a door"))
;; Test that wall blocks movement
(define (test-wall-blocks)
(define m (make-maze))
(check ((m 'wall?) 1 0) "Cell (1,0) is a wall, Pac-Man cannot pass"))
(define (test)
(run-test test-dimensions "Maze: dimensions")
(run-test test-wall "Maze: wall detection")
(run-test test-coin "Maze: coin detection")
(run-test test-door "Maze: door detection")
(run-test test-mutation "Maze: cell mutation")
(run-test test-wall-blocks "Maze: wall blocks movement"))))

View File

@@ -1,51 +1,51 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Pac-Man ADT ;;
;; Tests: Pac-Man ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-pacman)
(import (scheme base)
(pp1 tests)
(pacman-project adt-positie)
(pacman-project adt-position)
(pacman-project adt-pacman))
(export test)
(begin
;; Test aanmaak en startpositie
(define (test-aanmaak)
(define pac (maak-pacman 5 2))
(define pos (pac 'positie))
(check-eq? (pos 'rij) 5 "Start rij moet 5 zijn")
(check-eq? (pos 'kolom) 2 "Start kolom moet 2 zijn"))
;; Test creation and start position
(define (test-creation)
(define pac (make-pacman 5 2))
(define pos (pac 'position))
(check-eq? (pos 'row) 5 "Start row should be 5")
(check-eq? (pos 'col) 2 "Start col should be 2"))
;; Test richting
(define (test-richting)
(define pac (maak-pacman 5 2))
(check-eq? (pac 'richting) 'rechts "Startrichting moet rechts zijn")
((pac 'richting!) 'links)
(check-eq? (pac 'richting) 'links "Richting moet links zijn na richting!"))
;; Test direction
(define (test-direction)
(define pac (make-pacman 5 2))
(check-eq? (pac 'direction) 'right "Start direction should be right")
((pac 'direction!) 'left)
(check-eq? (pac 'direction) 'left "Direction should be left after direction!"))
;; Test beweeg!
(define (test-beweeg)
(define pac (maak-pacman 5 2))
((pac 'beweeg!) 0 1)
(define pos (pac 'positie))
(check-eq? (pos 'kolom) 3 "Kolom moet 3 zijn na 1 stap rechts")
(check-eq? (pos 'rij) 5 "Rij ongewijzigd na horizontale beweging"))
;; Test move!
(define (test-move)
(define pac (make-pacman 5 2))
((pac 'move!) 0 1)
(define pos (pac 'position))
(check-eq? (pos 'col) 3 "Col should be 3 after 1 step right")
(check-eq? (pos 'row) 5 "Row unchanged after horizontal move"))
;; Test meerdere bewegingen
(define (test-meerdere-bewegingen)
(define pac (maak-pacman 5 5))
((pac 'beweeg!) -1 0)
((pac 'beweeg!) 0 1)
(define pos (pac 'positie))
(check-eq? (pos 'rij) 4 "Rij moet 4 zijn na omhoog")
(check-eq? (pos 'kolom) 6 "Kolom moet 6 zijn na rechts"))
;; Test multiple moves
(define (test-multiple-moves)
(define pac (make-pacman 5 5))
((pac 'move!) -1 0)
((pac 'move!) 0 1)
(define pos (pac 'position))
(check-eq? (pos 'row) 4 "Row should be 4 after up")
(check-eq? (pos 'col) 6 "Col should be 6 after right"))
(define (test)
(run-test test-aanmaak "Pac-Man: aanmaak en startpositie")
(run-test test-richting "Pac-Man: richting")
(run-test test-beweeg "Pac-Man: beweeg!")
(run-test test-meerdere-bewegingen "Pac-Man: meerdere bewegingen"))))
(run-test test-creation "Pac-Man: creation and start position")
(run-test test-direction "Pac-Man: direction")
(run-test test-move "Pac-Man: move!")
(run-test test-multiple-moves "Pac-Man: multiple moves"))))

View File

@@ -1,57 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Positie ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-positie)
(import (scheme base)
(pp1 tests)
(pacman-project adt-positie))
(export test)
(begin
;; Test aanmaak en getters
(define (test-aanmaak)
(define pos (maak-positie 5 10))
(check-eq? (pos 'rij) 5 "Rij moet 5 zijn")
(check-eq? (pos 'kolom) 10 "Kolom moet 10 zijn"))
;; Test mutators
(define (test-mutators)
(define pos (maak-positie 0 0))
((pos 'rij!) 3)
((pos 'kolom!) 7)
(check-eq? (pos 'rij) 3 "Rij moet 3 zijn na rij!")
(check-eq? (pos 'kolom) 7 "Kolom moet 7 zijn na kolom!"))
;; Test vergelijk?
(define (test-vergelijk)
(define p1 (maak-positie 5 10))
(define p2 (maak-positie 5 10))
(define p3 (maak-positie 5 11))
(check ((p1 'vergelijk?) p2) "Gelijke posities moeten gelijk zijn")
(check (not ((p1 'vergelijk?) p3)) "Verschillende posities mogen niet gelijk zijn"))
;; Test beweeg
(define (test-beweeg)
(define pos (maak-positie 5 10))
(define nieuwe-pos ((pos 'beweeg) -1 0))
(check-eq? (nieuwe-pos 'rij) 4 "Rij moet 4 zijn na beweeg omhoog")
(check-eq? (nieuwe-pos 'kolom) 10 "Kolom ongewijzigd na beweeg omhoog")
;; Originele positie mag niet gewijzigd zijn
(check-eq? (pos 'rij) 5 "Originele rij mag niet wijzigen"))
;; Test dat twee objecten niet eq? zijn
(define (test-identiteit)
(define p1 (maak-positie 1 1))
(define p2 (maak-positie 1 1))
(check (not (eq? p1 p2)) "Twee positie-objecten mogen niet eq? zijn"))
(define (test)
(run-test test-aanmaak "Positie: aanmaak en getters")
(run-test test-mutators "Positie: mutators")
(run-test test-vergelijk "Positie: vergelijk?")
(run-test test-beweeg "Positie: beweeg")
(run-test test-identiteit "Positie: identiteit"))))

View File

@@ -0,0 +1,57 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Position ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-position)
(import (scheme base)
(pp1 tests)
(pacman-project adt-position))
(export test)
(begin
;; Test creation and getters
(define (test-creation)
(define pos (make-position 5 10))
(check-eq? (pos 'row) 5 "Row should be 5")
(check-eq? (pos 'col) 10 "Col should be 10"))
;; Test mutators
(define (test-mutators)
(define pos (make-position 0 0))
((pos 'row!) 3)
((pos 'col!) 7)
(check-eq? (pos 'row) 3 "Row should be 3 after row!")
(check-eq? (pos 'col) 7 "Col should be 7 after col!"))
;; Test equal?
(define (test-equal)
(define p1 (make-position 5 10))
(define p2 (make-position 5 10))
(define p3 (make-position 5 11))
(check ((p1 'equal?) p2) "Equal positions should match")
(check (not ((p1 'equal?) p3)) "Different positions should not match"))
;; Test move
(define (test-move)
(define pos (make-position 5 10))
(define new-pos ((pos 'move) -1 0))
(check-eq? (new-pos 'row) 4 "Row should be 4 after move up")
(check-eq? (new-pos 'col) 10 "Col unchanged after move up")
;; Original position must not change
(check-eq? (pos 'row) 5 "Original row must not change"))
;; Test that two objects are not eq?
(define (test-identity)
(define p1 (make-position 1 1))
(define p2 (make-position 1 1))
(check (not (eq? p1 p2)) "Two position objects must not be eq?"))
(define (test)
(run-test test-creation "Position: creation and getters")
(run-test test-mutators "Position: mutators")
(run-test test-equal "Position: equal?")
(run-test test-move "Position: move")
(run-test test-identity "Position: identity"))))

View File

@@ -1,30 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Score ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-score)
(import (scheme base)
(pp1 tests)
(pacman-project adt-score))
(export test)
(begin
;; Test startscore
(define (test-startscore)
(define s (maak-score))
(check-eq? (s 'punten) 0 "Startscore moet 0 zijn"))
;; Test score verhoging
(define (test-verhoog)
(define s (maak-score))
((s 'verhoog!))
(check-eq? (s 'punten) 10 "Score moet 10 zijn na 1 muntje")
((s 'verhoog!))
(check-eq? (s 'punten) 20 "Score moet 20 zijn na 2 muntjes"))
(define (test)
(run-test test-startscore "Score: startscore")
(run-test test-verhoog "Score: verhoging"))))

View File

@@ -1,55 +0,0 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Tijdslimiet ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-tijdslimiet)
(import (scheme base)
(pp1 tests)
(pacman-project adt-tijdslimiet))
(export test)
(begin
;; Test starttijd
(define (test-starttijd)
(define t (maak-tijdslimiet))
(check-eq? (t 'resterende-tijd) 60 "Starttijd moet 60 seconden zijn")
(check (not ((t 'tijd-op?))) "Tijd mag niet op zijn bij start"))
;; Test verlaag na 1 seconde
(define (test-verlaag)
(define t (maak-tijdslimiet))
((t 'verlaag!) 1000)
(check-eq? (t 'resterende-tijd) 59 "Tijd moet 59 zijn na 1 seconde"))
;; Test verhoog (muntje bonus)
(define (test-verhoog)
(define t (maak-tijdslimiet))
((t 'verlaag!) 1000)
((t 'verhoog!))
(check-eq? (t 'resterende-tijd) 60 "Tijd moet 60 zijn na verlaag + verhoog"))
;; Test formatteer-tijd
(define (test-formatteer)
(define t (maak-tijdslimiet))
(check-eq? ((t 'formatteer-tijd)) "1:00" "60 seconden = 1:00")
((t 'verlaag!) 1000)
(check-eq? ((t 'formatteer-tijd)) "0:59" "59 seconden = 0:59"))
;; Test tijd-op?
(define (test-tijd-op)
(define t (maak-tijdslimiet))
;; 60 keer verlagen met 1 seconde
(do ((i 0 (+ i 1)))
((= i 60))
((t 'verlaag!) 1000))
(check ((t 'tijd-op?)) "Tijd moet op zijn na 60 seconden"))
(define (test)
(run-test test-starttijd "Tijdslimiet: starttijd")
(run-test test-verlaag "Tijdslimiet: verlaag")
(run-test test-verhoog "Tijdslimiet: verhoog")
(run-test test-formatteer "Tijdslimiet: formatteer-tijd")
(run-test test-tijd-op "Tijdslimiet: tijd-op?"))))

View File

@@ -0,0 +1,55 @@
#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests: Timer ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-library (pacman-project tests test-timer)
(import (scheme base)
(pp1 tests)
(pacman-project adt-timer))
(export test)
(begin
;; Test initial time
(define (test-initial)
(define t (make-timer))
(check-eq? (t 'remaining-time) 60 "Initial time should be 60 seconds")
(check (not ((t 'time-up?))) "Time should not be up at start"))
;; Test decrease after 1 second
(define (test-decrease)
(define t (make-timer))
((t 'decrease!) 1000)
(check-eq? (t 'remaining-time) 59 "Time should be 59 after 1 second"))
;; Test increase (coin bonus)
(define (test-increase)
(define t (make-timer))
((t 'decrease!) 1000)
((t 'increase!))
(check-eq? (t 'remaining-time) 60 "Time should be 60 after decrease + increase"))
;; Test format-time
(define (test-format)
(define t (make-timer))
(check-eq? ((t 'format-time)) "1:00" "60 seconds = 1:00")
((t 'decrease!) 1000)
(check-eq? ((t 'format-time)) "0:59" "59 seconds = 0:59"))
;; Test time-up?
(define (test-time-up)
(define t (make-timer))
;; Decrease 60 times by 1 second
(do ((i 0 (+ i 1)))
((= i 60))
((t 'decrease!) 1000))
(check ((t 'time-up?)) "Time should be up after 60 seconds"))
(define (test)
(run-test test-initial "Timer: initial time")
(run-test test-decrease "Timer: decrease")
(run-test test-increase "Timer: increase")
(run-test test-format "Timer: format-time")
(run-test test-time-up "Timer: time-up?"))))