Zaytun Handbook

When the compiler complains

Errors are file:line: message with a nonzero exit code, so an editor or a build script can parse them:

$ ./zaytunc/zaytunc broken.zaytun
zaytunc: broken.zaytun:7: expected "}" but found "exit"

Every id a program names is checked as well, so a typo in a branch nobody has played yet is a build failure rather than a crash halfway through someone's playthrough:

zaytunc: rooms/cellar.zaytun:31: refers to undeclared item "lantrn"

One compile tells you everything it can see, in the order you wrote it, rather than stopping at the first thing it dislikes — so a fresh chapter with four mistakes in it is one round of fixing, not four:

$ ./zaytunc/zaytunc mygame.zaytun
zaytunc: mygame.zaytun:2: start room "gatehouse" was never declared
zaytunc: rooms/cellar.zaytun:31: refers to undeclared item "lantrn"
zaytunc: rooms/cellar.zaytun:44: room "cellar" has an exit to undeclared room "stiar"
zaytunc: rooms/tower.zaytun:9: room "tower" is declared more than once

Two details worth knowing. Past twenty errors it stops and says so, so a long list is a floor and not a total. And a syntax error costs its own declaration and nothing else: the compiler skips to the next declaration and carries on, so the rest of that file and every other file is still checked in the same run. The one thing it cannot check is the inside of the declaration that failed.

The checks that catch the most common mistakes:

MessageWhat happened
refers to undeclared item / enemy / room / scene "x"a typo, or you forgot to declare it
item "x" has "on equip" but is neither a weapon nor armor, so it can never be equippedonly a weapon or a piece of armor can be in a hand — see On equip and on unequip
"attack" is read-onlychange it by equipping a weapon, not by assigning to it
"hp" is a reserved identifier and cannot be used as a flag namepick another flag name
"quit" leaves the program rather than the storyquit and exit are the only two words a verb may not take — see A verb of your own owns its word
"x" is defined by more than one verbtwo verbs, or a verb and an alias, answer to one word
enemy "x" can only be spawned or removed "in room"enemies do not go in the inventory
room / item / enemy / scene "x" is declared more than oncetwo declarations share an id
anything undeclared "x", when you can see the declaration right thereit is local to another file — that is what local means; drop the local if two files need to share it
"a.zaytun" and "b.zaytun" have the same file namelocal names are tagged with the file's name, so two files called the same thing cannot both have them; rename one

Warnings

A warning is the compiler saying this is almost certainly not what you meant about something it will not refuse. It is file:line: warning: message, it is printed with the errors, and a game whose only diagnostics are warnings compiles and exits 0. There are two.

A way out named after a word the player's line is read for first — exit take, exit look, a verb of your own. The exit is listed and cannot be walked by its name; GO TAKE still walks it. The whole rule, and the two ways to answer it, are under Naming an exit moves you.

A field the player reads, given true or false. Every field in the language takes an expression and a boolean is an expression, so this compiles, and the room's description is the word true:

room r "R" { description: true }
enemy wolf "a wolf" { hp: 4  attack: 1  defense: 0  ambush: true }

The compiler names the field, what it was given, and what the player will read:

zaytunc: g.zaytun:3: warning: "description:" on room "r" is read out to the player, and it
was given true — so what they read is the word "true"; put it in quotes to mean the word
itself, or write a sentence to mean a sentence

ambush: is the one that gets written by mistake, because it sits in the same declaration as hostile: and retaliates:, which are booleans — see Hostile enemies. The warning covers every field whose value ends up in front of the player: description:, examine:, dialogue:, ambush:, plural:, text:, empty:, a scene's lines, and the message half of every guard — opens if ... else, takes if ... else, an exit's else, and a hull's boards if ... else, moves if ... else and reaches out if ... else.

The condition half is never warned about, because a condition is supposed to be a boolean: opens if true else "Locked." and description when true: are an author saying so, and the compiler does not argue with a correct game. Neither are hostile:, retaliates:, dark if, fixed:, weapon:, armor:, open: or a verb's free:, which hold booleans by definition.

If you want the literal word, write it as a string: examine: "true".