(local pi (math.pi))

; Define map (0 is empty space, 1 is wall)
(var map [[1 1 1 1 1]
          [1 0 0 0 1]
          [1 0 1 0 1]
          [1 0 0 0 1]
          [1 1 1 1 1]])

; Map size
(var map-width (length map))
(var map-height (length (first map)))

; Player position and direction
(var player {:x 2.5 :y 2.5 :dir 0 :fov (/ pi 3)})

; Screen size
(var screen-width 640)
(var screen-height 480)

; Ray-casting function
(fn cast-ray [ray-angle]
  (local dx (math.cos ray-angle))
  (local dy (math.sin ray-angle))
  
  (var distance 0)
  (while true
    (var ray-x (+ player.x (* dx distance)))
    (var ray-y (+ player.y (* dy distance)))
    
    ; Check if ray hits a wall (1) on the map
    (when (or (>= (math.floor ray-x) map-width)
              (>= (math.floor ray-y) map-height)
              (<= ray-x 0)
              (<= ray-y 0)
              (= (nth (nth map (math.floor ray-y)) (math.floor ray-x)) 1))
      (return distance))
    
    ; Increment distance
    (set distance (+ distance 0.01))))

; Draw function for rendering
(fn love.draw []
  (love.graphics.clear)
  
  ; For each vertical slice of the screen
  (for [i 0 (- screen-width 1)]
    ; Calculate angle of ray relative to player direction
    (local ray-angle (+ player.dir
                        (- (* (/ i screen-width) player.fov) (/ player.fov 2))))
    
    ; Cast the ray to find distance to the nearest wall
    (local distance (cast-ray ray-angle))
    
    ; Calculate height of the wall slice
    (local wall-height (math.floor (/ screen-height distance)))
    
    ; Draw the wall slice (centered vertically)
    (love.graphics.line i (/ (- screen-height wall-height) 2)
                        i (/ (+ screen-height wall-height) 2))))

