Conditions
One grammar, used everywhere a condition can appear: fragment and choice
*requires:, block
*if/*elseif, conditional
navigation inside an *if block, and inline
{if cond} text.
| Term | Meaning |
|---|---|
INT >= 60 | Stat comparison. Operators: >= <= > < = |
age >= 17 | Age comparison |
has_pet | Variable is truthy (true, or a positive integer) |
!has_pet | Variable is falsy - false, 0, negative, or never set |
has_pet = true | The same as has_pet, spelled the way *set: spells it |
has_pet = false | The same as !has_pet, never-set included |
dog_debt >= 2 | Integer variable comparison |
random(20) + VIT >= 70 | Dice check - a fresh 1..20 roll plus the stat, against the threshold |
VIT + WIL >= 120 | Summed comparison - stats, int variables, and age can be added |
played:some_id | The fragment with that id has been played this life |
pronouns = she_her | The character’s pronouns, one of he_him, she_her, they_them |
All values are integers; > 40 is exactly >= 41.
Comparison is a single =. There is no assignment inside a condition to tell it apart
from - writing happens in *set: - so == is a build error that names the fix rather than
a second spelling of the same operator.
has_pet = false and !has_pet are one condition: a variable that was never set satisfies
both. Whether it was never set or set and undone is a question the
Life panel answers, not a condition.
Dice checks
Section titled “Dice checks”random(N) contributes a fresh roll of 1..N every time the condition is evaluated.
The natural home is an *if block - the attempt happens when the body runs:
> Climb the wall *if random(20) + VIT >= 70 You make it up, somehow. *else You slip on the second hold. *effects: VIT-1 *endifThree rules keep rolls predictable:
- Not allowed in inline
{if}- inline text re-renders while the player reads, and the roll would flicker. The build rejects it and points you to the pattern below. - Each evaluation rolls fresh. An
*elseifchain rolls separate dice per branch; a*requires:with a roll re-rolls each time its scene is entered. - To roll once and reuse the result, assign it and branch on the variable:
*set: fate = random(6)*if fate >= 5 A very good day.*elseif fate >= 3 An ordinary day.*else One of those days.*endifCombining
Section titled “Combining”pronouns is read off the character rather than out of the variable store, so no
fragment declares it and none can set it. It compares with = and != only, like any
other set of names with no order. It is not a gender: the game knows which words to
write and nothing else, and a character’s gender, if a fragment needs one, is an ordinary
shared variable that some scene establishes.
&& is AND, || is OR; && binds tighter, and parentheses group however you
like:
requires: CHA >= 70 || INT >= 70*if VIT >= 30 && !injured || has_medkit*if (CHA >= 70 || INT >= 70) && WIL >= 40*if ((random(6) >= 4 || lucky_charm) && VIT >= 30) || played:big_breakWithout parentheses, VIT >= 30 && !injured || has_medkit reads as
(VIT >= 30 && !injured) || has_medkit. With them, you decide. Unbalanced or
misplaced parentheses are build errors; random(N)’s own parentheses never
interfere with grouping.
Any term the parser doesn’t recognize is a build error - a typo like VIT => 70
or HPA >= 60 can never silently turn a gate into “always true.”
Effective state
Section titled “Effective state”Conditions evaluated mid-fragment see the effective state: the character’s base
stats plus every effect and assignment accumulated so far in this fragment. If a
choice applies *effects: HAP+4 and an *if HAP >= 52 follows it, the +4 already
counts. Stats commit permanently only when the fragment ends.