Current source: curriculum/arrowfall/checkpoints/01-scene · Flecha 0.3.0 · 1/7.
The program at this checkpoint
Previously: You start with an installed Flecha v0.3.0 toolchain and an empty program.
Arrowfall begins with the smallest useful result: a terminal program that can already be recognized as a game. There is no state or input yet. The current program only establishes the title, the room boundary, the archer, the floor, and the exit.
This static frame is intentional. Before rules can move a symbol, the symbols need a stable meaning. The same four characters will remain visible as later checkpoints replace literal text with state, collision, enemies, and rendering logic.
Current limitation
There is nothing to play or recognize yet.
Required next behavior: Make one unmistakable terminal frame before adding state or rules.
Model and invariants
Print the title and a tiny room directly. The symbols establish the visual contract: # wall, . floor, @ archer, and > exit.
Plain functions and stdout are sufficient for this version. Adding a state model now would add structure without supporting any behavior.
The terminal is a grid of characters, so one printed line represents one row. Calling stdoutln once per row makes the spatial layout visible directly in source: the outer # characters are walls, @ is the archer, . is traversable floor, and > is the exit.
At this stage the source text is also the scene data. That is acceptable only because nothing can change. It gives us a precise baseline without introducing a structure whose responsibilities are still unknown.
The important invariant is visual rather than dynamic: every row has the same width and the room remains enclosed. Movement and collision are deliberately out of scope until the program has state to modify.
Implementation
The implementation is split into the changes below. Each excerpt is taken verbatim from the qualified checkpoint and is explained in the part of the data flow where it is used. The excerpts are not standalone programs; the complete compiled source is available after the run.
- Create the Longbow program manifest.
- Add the first complete main module.
- Record exact input, stdout, text, and SVG frames.
The complete first program
The complete program fits in one module. The module declaration gives Longbow an entry module, while main writes the four-line frame in display order.
Excerpt: src/main.fl:1–8. The complete file appears in the source section below.
module main;
void main() { stdoutln("ARROWFALL"); stdoutln("#####"); stdoutln("#@.>#"); stdoutln("#####");}Each call ends its row with a newline. Keeping the title separate from the room means later renderers can redraw the map without treating the title as a map cell.
There is no loop because there is no repeated rule yet. A loop would hide the only information this checkpoint needs to teach: the exact first frame.
Run and inspect the result
The command uses the checkpoint’s recorded input, so the behavior described above can be reproduced without manual timing.
longbow run tutorial/checkpoints/01-scene < tutorial/checkpoints/01-scene/tests/input.txtThe recorded run has no standard input. Its frame should contain the same four rows as the source, with the archer at the only floor cell before the exit.
This output becomes the first visual contract. If one character changes, the frame fixture changes with it; later checkpoints can therefore show which visible behavior came from a code change.
Accessible frame transcript
ARROWFALL######@.>######Complete recorded stdout
ARROWFALL######@.>######What this checkpoint establishes
We now have a compilable Longbow program and an exact terminal baseline, but the archer is still part of a string. There is no value that represents its location.
The next checkpoint introduces that value and makes rendering consult it. Only then can movement mean changing data instead of editing text.
Exercise
Change one floor dot to a wall. Exactly one frame character must change; restore it before continuing.
Complete source and verification
The sections below preserve the complete qualified source, the exact predecessor diff, and the command sequence used by CI. They are supporting evidence for the implementation explained above.
Complete tested source (3 files)
longbow.toml
[package]name = "arrowfall-step-01"version = "0.1.0"kind = "program"flecha = ">=0.3.0, <0.4.0"
[dependencies]longbow.lock
{ "schema": 1, "root": "root", "packages": [ { "id": "root", "identity": "local/arrowfall_step_01", "source": { "kind": "workspace", "path": "." }, "version": "0.1.0", "flecha": ">=0.3.0, <0.4.0", "dependencies": { "std": "toolchain-std" } }, { "id": "toolchain-std", "identity": "flecha/std", "source": { "kind": "toolchain" }, "dependencies": {} } ]}src/main.fl
module main;
void main() { stdoutln("ARROWFALL"); stdoutln("#####"); stdoutln("#@.>#"); stdoutln("#####");}Exact diff from the preceding version
--- /dev/null+++ tutorial/checkpoints/01-scene/README.md@@ -0,0 +1,50 @@+# 01 — A room appears++## Starting point++There is no previous checkpoint: we begin with an empty Flecha program.++## Why now?++A terminal game first needs something recognisable on screen. Before state,+input, or rules, a static room gives the project a visible identity.++## New behaviour++Running the program prints Arrowfall's title and a tiny room containing the+player (`@`), floor (`.`), walls (`#`), and exit (`>`).++## Files changed++- `README.md`+- `longbow.lock`+- `longbow.toml`+- `src/main.fl`+- `tests/input.txt`+- `tests/output.txt`+- `tests/frame.txt`+- `tests/frame.svg`++The exact source diff is `../../diffs/01-scene.patch`. This directory contains+the complete current code, not a fragment.++## Verify++```sh+longbow check tutorial/checkpoints/01-scene+longbow test tutorial/checkpoints/01-scene+longbow build tutorial/checkpoints/01-scene+longbow run tutorial/checkpoints/01-scene < tutorial/checkpoints/01-scene/tests/input.txt+```++Expected stdout is `tests/output.txt`; the representative frame is+`tests/frame.txt` and `tests/frame.svg`.++## Timeline++1. **A room appears** — a static scene establishes the game's visual goal.++## Challenge / acceptance++Change one floor dot to a wall, rebuild, and verify exactly one character in+the frame changes. Restore it before moving on.--- /dev/null+++ tutorial/checkpoints/01-scene/longbow.lock@@ -0,0 +1,27 @@+{+ "schema": 1,+ "root": "root",+ "packages": [+ {+ "id": "root",+ "identity": "local/arrowfall_step_01",+ "source": {+ "kind": "workspace",+ "path": "."+ },+ "version": "0.1.0",+ "flecha": ">=0.3.0, <0.4.0",+ "dependencies": {+ "std": "toolchain-std"+ }+ },+ {+ "id": "toolchain-std",+ "identity": "flecha/std",+ "source": {+ "kind": "toolchain"+ },+ "dependencies": {}+ }+ ]+}--- /dev/null+++ tutorial/checkpoints/01-scene/longbow.toml@@ -0,0 +1,7 @@+[package]+name = "arrowfall-step-01"+version = "0.1.0"+kind = "program"+flecha = ">=0.3.0, <0.4.0"++[dependencies]--- /dev/null+++ tutorial/checkpoints/01-scene/src/main.fl@@ -0,0 +1,8 @@+module main;++void main() {+ stdoutln("ARROWFALL");+ stdoutln("#####");+ stdoutln("#@.>#");+ stdoutln("#####");+}--- /dev/null+++ tutorial/checkpoints/01-scene/tests/frame.svg@@ -0,0 +1,10 @@+<?xml version="1.0" encoding="UTF-8"?>+<svg xmlns="http://www.w3.org/2000/svg" width="360" height="124" viewBox="0 0 360 124" role="img">+ <title>01-scene representative frame</title>+ <rect width="100%" height="100%" rx="12" fill="#10151c"/>+ <style>.terminal { fill: #d7f9e9; font: 15px monospace; white-space: pre; }</style>+ <text x="24" y="37" class="terminal">ARROWFALL</text>+ <text x="24" y="56" class="terminal">#####</text>+ <text x="24" y="75" class="terminal">#@.>#</text>+ <text x="24" y="94" class="terminal">#####</text>+</svg>--- /dev/null+++ tutorial/checkpoints/01-scene/tests/frame.txt@@ -0,0 +1,4 @@+ARROWFALL+#####+#@.>#+#####--- /dev/null+++ tutorial/checkpoints/01-scene/tests/output.txt@@ -0,0 +1,4 @@+ARROWFALL+#####+#@.>#+#####Check, test, build, and run commands
longbow check tutorial/checkpoints/01-scenelongbow test tutorial/checkpoints/01-scenelongbow build tutorial/checkpoints/01-scenelongbow run tutorial/checkpoints/01-scene < tutorial/checkpoints/01-scene/tests/input.txtVersions in this tutorial
- 1. Render the first room
Next version
The room is currently one fixed string. The next version derives the player position from owned game state.
References
Source: Arrowfall commit 56bb003, verified with official Flecha 0.3.0. The source, input, output, diff, and frame on this page are read from that committed snapshot.