robot_cleaning_game/CLAUDE.md
2026-05-09 19:39:31 +02:00

4.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a two-player cooperative cleaning game built with LÖVE2D using Fennel (a Lisp dialect that compiles to Lua).

Fennel docs are available locally at .claude/API_DOCs/fennel.md

Key Architecture

Fennel + LÖVE2D Setup

Fennel is a Lisp-like language that compiles to Lua at runtime. The project uses symlinked bootstrap files:

  • fennel-1.5.3.lua (root): The Fennel compiler itself
  • fennel_bootstrap.lua (root): Sets up Fennel module loading and compiles .fnl files on-the-fly

The two_player_cleaning_game directory contains:

  • main.fnl: The Fennel source code (user-editable)
  • main.lua → symlink to ../fennel_bootstrap.lua: Entry point that Lua/LÖVE2D loads
  • fennel.lua → symlink to ../fennel-1.5.3.lua: Fennel compiler reference

How It Works

  1. LÖVE2D loads main.lua (the bootstrap file)
  2. Bootstrap loads the Fennel compiler and sets up a custom module loader
  3. Module loader intercepts require("main.fnl") and compiles it via Fennel at runtime
  4. Compiled Fennel code executes with full LÖVE2D API access

LÖVE2D Lifecycle

Games define lifecycle callbacks (all optional):

  • love.load(): Called once at startup
  • love.update(): Called every frame (~60fps by default)
  • love.draw(): Called every frame after update, render graphics here
  • love.keypressed(key): Keyboard input handler
  • love.handlers.stdin(line): REPL input for live evaluation (used for debug/live coding)

Development Workflow

Running the Game

love ./game

LÖVE2D must be installed and in your PATH. See Getting Started for installation.

Live Coding / REPL

To enable stdin REPL support for live evaluation, add this to love.load():

(: (love.thread.newThread "require('love.event')
while 1 do love.event.push('stdin', io.read('*line')) end") :start)

(fn love.handlers.stdin [line]
  (let [(ok val) (pcall fennel.eval line)]
    (print (if ok (fennel.view val) val))))

While the game is running, type Fennel code at the terminal and it will be evaluated live.

Fennel Language Basics

Syntax Patterns

; Variables
(local name "value")
(var counter 0)

; Functions
(fn my-func [arg1 arg2]
  (+ arg1 arg2))

; Tables/Objects
(local person {
  :name "Alice"
  :age 30
  :greet (fn [self] (print (.. self.name " says hello")))
})

; Common control flow
(when condition
  (do-something))

(if condition
  (then-branch)
  (else-branch))

(match value
  "a" (handle-a)
  "b" (handle-b))

; Iteration
(each [k v (pairs table)]
  (print k v))

(for [i 1 10]
  (print i))

Interop with Lua

Call Lua functions naturally:

(love.graphics.setColor 1 0 0) ; red
(love.window.getMode)          ; returns width, height, flags table

Access nested Lua objects with colon : syntax:

(: canvas-obj :setFilter "nearest" "nearest")  ; equivalent to canvas_obj:setFilter(...)

Common Development Tasks

Adding a new module/file

  1. Create my_module.fnl in the two_player_cleaning_game directory
  2. Require it: (local my-module (require "my_module"))
  3. The bootstrap module loader will auto-compile it

Debugging

  • Use (print (fennel.view value)) to inspect tables and complex values
  • Enable stdin REPL (see above) for quick live tests
  • LÖVE2D console output is visible in the terminal where you ran love

Working with Graphics

LÖVE2D graphics API examples:

(love.graphics.setColor 1 0 0)               ; set color to red
(love.graphics.rectangle "fill" x y w h)    ; draw filled rectangle
(love.graphics.circle "line" x y radius)    ; draw circle outline
(love.graphics.print text x y)               ; draw text
(love.graphics.draw drawable x y)           ; draw canvas/image

Code Guidelines

Do not modify symlinked files (main.lua, fennel.lua) — modify main.fnl instead. If adding new modules, create them as separate .fnl files in the project directory.

References