#lang r7rs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Tests: Ghost ADT ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-library (pacman-project tests test-ghost) (import (scheme base) (pp1 tests) (pacman-project adt ghost)) (export test) (begin ;; Test creation and initial state (define (test-creation) (define g (make-ghost 'blinky 11 14 0 27 0)) (define pos (g 'position)) (check-eq? (pos 'row) 11 "Start row should be 11") (check-eq? (pos 'col) 14 "Start col should be 14") (check-eq? (g 'type) 'blinky "Type should be blinky") (check-eq? (g 'direction) 'left "Default direction should be left")) ;; Test that exit-delay 0 means ghost starts outside (scatter mode) (define (test-blinky-starts-active) (define g (make-ghost 'blinky 11 14 0 27 0)) (check-eq? (g 'in-house?) #f "Blinky should start outside") (check-eq? (g 'mode) 'scatter "Blinky should start in scatter")) ;; Test that non-zero exit-delay means ghost starts in house (define (test-pinky-starts-in-house) (define g (make-ghost 'pinky 14 13 0 0 2000)) (check-eq? (g 'in-house?) #t "Pinky should start in house") (check-eq? (g 'mode) 'in-house "Pinky mode should be in-house")) ;; Test direction change (define (test-direction) (define g (make-ghost 'blinky 11 14 0 27 0)) ((g 'direction!) 'right) (check-eq? (g 'direction) 'right "Direction should be right")) ;; Test mode change and reverse queuing (define (test-mode-change-queues-reverse) (define g (make-ghost 'blinky 11 14 0 27 0)) ((g 'mode!) 'chase) (check-eq? (g 'mode) 'chase "Mode should be chase") (check-eq? ((g 'consume-reverse!)) #t "Reverse should be queued after mode change")) ;; Test reverse consumed only once (define (test-consume-reverse-once) (define g (make-ghost 'blinky 11 14 0 27 0)) ((g 'mode!) 'chase) ((g 'consume-reverse!)) (check-eq? ((g 'consume-reverse!)) #f "Reverse should be consumed after first call")) ;; Test move (define (test-move) (define g (make-ghost 'blinky 11 14 0 27 0)) ((g 'move!) 0 -1) (define pos (g 'position)) (check-eq? (pos 'col) 13 "Col should be 13 after move left")) ;; Test scatter target (define (test-scatter-target) (define g (make-ghost 'blinky 11 14 0 27 0)) (define st (g 'scatter-target)) (check-eq? (st 'row) 0 "Scatter target row should be 0") (check-eq? (st 'col) 27 "Scatter target col should be 27")) ;; Test house timer expiry (define (test-house-exit) (define g (make-ghost 'pinky 14 13 0 0 2000)) ((g 'update-house-timer!) 1000) (check-eq? (g 'in-house?) #t "Still in house after 1000ms") ((g 'update-house-timer!) 1000) (check-eq? (g 'in-house?) #f "Should exit house after 2000ms") (check-eq? (g 'mode) 'scatter "Should be in scatter after exiting")) ;; Test movement timer (define (test-movement-timer) (define g (make-ghost 'blinky 11 14 0 27 0)) (check-eq? ((g 'advance-movement-timer!) 100) 100 "Timer should be 100") (check-eq? ((g 'advance-movement-timer!) 120) 220 "Timer should be 220") ((g 'reset-movement-timer!)) (check-eq? (g 'movement-timer) 0 "Timer should reset to 0")) (define (test) (run-test test-creation "Ghost: creation and initial state") (run-test test-blinky-starts-active "Ghost: Blinky starts active") (run-test test-pinky-starts-in-house "Ghost: Pinky starts in house") (run-test test-direction "Ghost: direction change") (run-test test-mode-change-queues-reverse "Ghost: mode change queues reverse") (run-test test-consume-reverse-once "Ghost: consume reverse only once") (run-test test-move "Ghost: move") (run-test test-scatter-target "Ghost: scatter target") (run-test test-house-exit "Ghost: house timer exit") (run-test test-movement-timer "Ghost: movement timer"))))