aboutsummaryrefslogtreecommitdiff
path: root/tests/world-test.scm
diff options
context:
space:
mode:
Diffstat (limited to 'tests/world-test.scm')
-rw-r--r--tests/world-test.scm239
1 files changed, 239 insertions, 0 deletions
diff --git a/tests/world-test.scm b/tests/world-test.scm
new file mode 100644
index 0000000..c758d2a
--- /dev/null
+++ b/tests/world-test.scm
@@ -0,0 +1,239 @@
+;; Load dependencies first
+(import scheme
+ (chicken base)
+ (chicken keyword)
+ defstruct
+ srfi-64
+ (only srfi-1 every member make-list))
+
+;; Create a mock tilemap module to avoid SDL dependency
+(module tilemap *
+ (import scheme (chicken base) defstruct)
+
+ (defstruct tileset
+ tilewidth
+ tileheight
+ spacing
+ tilecount
+ columns
+ image-source
+ image)
+
+ (defstruct layer
+ name
+ width
+ height
+ map)
+
+ (defstruct tilemap
+ width
+ height
+ tilewidth
+ tileheight
+ tileset-source
+ tileset
+ layers
+ objects))
+
+(import tilemap)
+
+;; Load entity module first (since world now imports entity)
+(include "entity.scm")
+(import entity)
+
+;; Load the module source directly
+(include "world.scm")
+;; Now import it to access the exported functions
+(import world)
+
+;; Test suite for world module
+(test-begin "world-module")
+
+;; Test: tilemap-tile-at retrieves tile IDs
+(test-group "tilemap-tile-at"
+ (test-group "valid positions in a small 3x3 tilemap"
+ (let* ((layer1 (make-layer name: "test" width: 3 height: 3
+ map: '((1 2 3) (4 5 6) (7 8 9))))
+ (tm (make-tilemap width: 3 height: 3
+ tilewidth: 16 tileheight: 16
+ tileset-source: ""
+ tileset: #f
+ layers: (list layer1)
+ objects: '())))
+ (test-equal "top-left corner" 1 (tilemap-tile-at tm 0 0))
+ (test-equal "top-right corner" 3 (tilemap-tile-at tm 2 0))
+ (test-equal "bottom-left corner" 7 (tilemap-tile-at tm 0 2))
+ (test-equal "center" 5 (tilemap-tile-at tm 1 1))))
+
+ (test-group "out-of-bounds returns 0"
+ (let* ((layer1 (make-layer name: "test" width: 3 height: 3
+ map: '((1 2 3) (4 5 6) (7 8 9))))
+ (tm (make-tilemap width: 3 height: 3
+ tilewidth: 16 tileheight: 16
+ tileset-source: ""
+ tileset: #f
+ layers: (list layer1)
+ objects: '())))
+ (test-equal "negative col" 0 (tilemap-tile-at tm -1 0))
+ (test-equal "col beyond width" 0 (tilemap-tile-at tm 3 0))
+ (test-equal "negative row" 0 (tilemap-tile-at tm 0 -1))
+ (test-equal "row beyond height" 0 (tilemap-tile-at tm 0 3))))
+
+ (test-group "zero tiles are skipped to next layer"
+ (let* ((layer1 (make-layer name: "test1" width: 3 height: 3
+ map: '((0 0 0) (0 0 0) (0 0 0))))
+ (layer2 (make-layer name: "test2" width: 3 height: 3
+ map: '((1 2 3) (4 5 6) (7 8 9))))
+ (tm (make-tilemap width: 3 height: 3
+ tilewidth: 16 tileheight: 16
+ tileset-source: ""
+ tileset: #f
+ layers: (list layer1 layer2)
+ objects: '())))
+ (test-equal "skips zero in layer1, finds in layer2"
+ 5 (tilemap-tile-at tm 1 1)))))
+
+;; Test: scene record creation
+(test-group "scene-structure"
+ (let ((scene (make-scene entities: '() tilemap: #f)))
+ (test-assert "scene is a record" (scene? scene))
+ (test-equal "entities list is empty" '() (scene-entities scene))
+ (test-equal "tilemap is #f" #f (scene-tilemap scene))))
+
+;; Test: scene with entities and tilemap
+(test-group "scene-with-data"
+ (let* ((player (make-player-entity 100 100 16 16))
+ (enemy '(#:type enemy #:x 200 #:y 200))
+ (tilemap "mock-tilemap")
+ (scene (make-scene entities: (list player enemy)
+ tilemap: tilemap)))
+ (test-equal "scene has 2 entities"
+ 2
+ (length (scene-entities scene)))
+ (test-equal "first entity is player"
+ 'player
+ (entity-type (car (scene-entities scene))))
+ (test-equal "tilemap is set correctly"
+ "mock-tilemap"
+ (scene-tilemap scene))))
+
+;; Test: scene-add-entity adds entity to scene
+(test-group "scene-add-entity"
+ (let* ((player (make-player-entity 100 100 16 16))
+ (scene (make-scene entities: (list player) tilemap: #f))
+ (enemy '(#:type enemy #:x 200 #:y 200)))
+
+ (test-equal "initial entity count" 1 (length (scene-entities scene)))
+
+ (scene-add-entity scene enemy)
+
+ (test-equal "entity count after add" 2 (length (scene-entities scene)))
+ (test-equal "second entity is enemy"
+ 'enemy
+ (entity-type (cadr (scene-entities scene))))))
+
+;; Test: scene-add-entity appends to end
+(test-group "scene-add-entity-order"
+ (let* ((e1 '(#:type a #:x 1))
+ (e2 '(#:type b #:x 2))
+ (e3 '(#:type c #:x 3))
+ (scene (make-scene entities: (list e1) tilemap: #f)))
+
+ (scene-add-entity scene e2)
+ (scene-add-entity scene e3)
+
+ (test-equal "entities are in order"
+ '(a b c)
+ (map entity-type (scene-entities scene)))))
+
+;; Test: scene-update-entities applies function to all entities
+(test-group "scene-update-entities"
+ (let* ((e1 '(#:type player #:x 100 #:y 100))
+ (e2 '(#:type enemy #:x 200 #:y 200))
+ (scene (make-scene entities: (list e1 e2) tilemap: #f))
+ ;; Function that moves all entities right by 10
+ (move-right (lambda (entity)
+ (let ((x (entity-ref entity #:x))
+ (y (entity-ref entity #:y))
+ (type (entity-ref entity #:type)))
+ (list #:type type #:x (+ x 10) #:y y)))))
+
+ (scene-update-entities scene move-right)
+
+ (test-equal "first entity moved right"
+ 110
+ (entity-ref (car (scene-entities scene)) #:x))
+ (test-equal "second entity moved right"
+ 210
+ (entity-ref (cadr (scene-entities scene)) #:x))
+ (test-equal "y values unchanged"
+ 100
+ (entity-ref (car (scene-entities scene)) #:y))))
+
+;; Test: scene-update-entities with identity function
+(test-group "scene-update-entities-identity"
+ (let* ((e1 '(#:type player #:x 100))
+ (e2 '(#:type enemy #:x 200))
+ (scene (make-scene entities: (list e1 e2) tilemap: #f)))
+
+ (scene-update-entities scene (lambda (e) e))
+
+ (test-equal "entity count unchanged" 2 (length (scene-entities scene)))
+ (test-equal "first entity unchanged"
+ 100
+ (entity-ref (car (scene-entities scene)) #:x))))
+
+;; Test: scene mutation
+(test-group "scene-mutation"
+ (let* ((scene (make-scene entities: '() tilemap: #f))
+ (player (make-player-entity 10 20 16 16)))
+
+ ;; Add entity
+ (scene-add-entity scene player)
+ (test-equal "entity added" 1 (length (scene-entities scene)))
+
+ ;; Update entities
+ (scene-update-entities scene
+ (lambda (e)
+ (let ((x (entity-ref e #:x))
+ (y (entity-ref e #:y))
+ (type (entity-type e)))
+ (list #:type type #:x (* x 2) #:y (* y 2)
+ #:width 16 #:height 16))))
+
+ (test-equal "entity x doubled" 20 (entity-ref (car (scene-entities scene)) #:x))
+ (test-equal "entity y doubled" 40 (entity-ref (car (scene-entities scene)) #:y))))
+
+;; Test: scene-tilemap-set!
+(test-group "scene-tilemap-mutation"
+ (let ((scene (make-scene entities: '() tilemap: #f)))
+ (test-equal "tilemap initially #f" #f (scene-tilemap scene))
+
+ (scene-tilemap-set! scene "new-tilemap")
+ (test-equal "tilemap updated" "new-tilemap" (scene-tilemap scene))))
+
+;; Create a test tilemap for the filter test
+(define test-tilemap
+ (make-tilemap width: 3 height: 3
+ tilewidth: 16 tileheight: 16
+ tileset-source: ""
+ tileset: #f
+ layers: '()
+ objects: '()))
+
+;; Test: scene-filter-entities
+(test-group "scene-filter-entities"
+ (let* ((e1 (list #:type 'player #:x 0 #:y 0 #:width 16 #:height 16))
+ (e2 (list #:type 'enemy #:x 0 #:y 0 #:width 16 #:height 16))
+ (scene (make-scene entities: (list e1 e2)
+ tilemap: test-tilemap
+ camera: (make-camera x: 0 y: 0)
+ tileset-texture: #f)))
+ (scene-filter-entities scene
+ (lambda (e) (eq? (entity-ref e #:type #f) 'player)))
+ (test-equal "keeps matching entities" 1 (length (scene-entities scene)))
+ (test-equal "kept entity is player"
+ 'player
+ (entity-ref (car (scene-entities scene)) #:type #f))))
+
+(test-end "world-module")