Zaytun Handbook

Splitting a game across files

include "items.zaytun"

include pulls another .zaytun file into the game at the point the line appears. Its declarations land where the include stood, and — unless they are marked local, below — they are visible to the whole game. It's a top-level declaration — it can't go inside a room or item block — and the included file holds ordinary declarations, so there's no header/body split to maintain. A game of any size can be laid out however suits it:

include "rooms/cellar.zaytun"
include "rooms/catacombs.zaytun"
include "items.zaytun"

title: "The Cellar Key"
start: entrance

Two rules worth knowing:

#include "...". A file in rooms/ that includes "shared.zaytun" gets rooms/shared.zaytun, so a subdirectory stays self-contained no matter who pulls it in.

Every name is checked before a byte is emitted — rooms, items, npcs, scenes, enemies, procs, and flags. A misspelled flag is a compile error rather than a silent false:

$ ./zaytunc/zaytunc mygame.zaytun
zaytunc: mygame.zaytun:31: refers to undeclared flag "lantern_lt"

That matters most in a large game, where a typo in one branch means that branch quietly never runs and nothing tells you until a player finds it.

Errors name the file they're in, so a mistake in an included file points at that file:

$ ./zaytunc/zaytunc dawnstone/dawnstone.zaytun
zaytunc: dawnstone/items.zaytun:14: expected "}" but found "on"

Note the spelling: it's include, not #include. In Zaytun a # starts a line comment, so a leading # would make the whole line vanish before the compiler ever saw it.

Keeping a name inside its file

Every name is normally visible to the whole game, which is what you want almost all of the time — a flag set in one room and read in another is the whole point of a flag.

What it costs is short names. An area wants to call its rooms gate, hall, steps, and so does the next area, so you end up prefixing by hand: angband_gate and doriath_gate, archive_step and church_step. Put local in front of a declaration and the name belongs to its file:

# angband.zaytun
local room gate "The Gate of Angband" { ... }

# doriath.zaytun
local room gate "The Gate of Menegroth" { ... }

Both compile, and they are two different rooms. Another file cannot name either of them — that is what local means — so anything two files need to share stays as it was, with no local on it.

local goes on room, item, npc, enemy, scene, proc, flag and stat. Not on a verb: a verb is a word the player types, and they aren't in any file when they type it.

A local item, person or creature still answers to its own name. The player can type TAKE LAMP for item lamp whether or not it is local — two files may each have a lamp and the one in the room is the one you get, exactly as when two items share an alias. Scope is about names in your source, not about what the player is allowed to say.

Two other things worth knowing: