Files
Pacman-Project/pacman-project/tests/test-ghost.rkt
joren 9028dd031c Add ghost CPUs with original Pac-Man AI targeting
Implement four ghosts (Blinky, Pinky, Inky, Clyde) with authentic
Pac-Man AI: Blinky chases directly, Pinky targets 2 tiles ahead
(with original up-direction bug), Inky uses vector doubling from
Blinky, Clyde switches to scatter within 8-tile radius.

Includes chase/scatter mode cycling, ghost house exit with staggered
delays, directional sprite rendering with animation, and ghost-pacman
collision detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:42:34 +01:00

98 lines
4.1 KiB
Racket

#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"))))