One condition language for quests, dialogue and spawns

· 1 min read · game-dev, javascript, data-driven, lantern-valley, design

A quest board and lanterns in a cozy island village, the kind of place whose rules are written as plain data

In Lantern Valley, quests, dialogue rules and spawns are all written in one condition language made of plain data, evaluated by one pure function. That is what keeps content out of engine code.

What a condition looks like #

Combinators first:

{ all: [ ... ] }   { any: [ ... ] }   { not: c }   // a bare list means "all"

Then the questions you can ask:

{ flag: 'name' }                         { quest: 'id', state: 'done' }
{ questStep: ['id', 's2'] }              { has: { item: 'id', n: 1 } }
{ hasKind: { kind: 'fish', n: 2 } }      { entity: 'id', is: 'broken' }
{ time: [20, 5] }                        { weather: 'rain' }
{ island: 'atol' }                       { friend: { npc: 'id', min: 20 } }
{ caught: 'ebb_snook' }

Time ranges wrap past midnight. hasFamily counts whole fruit of one tree kind, and the bruised do not count. hasMix asks for n items out of a list of at least k different ones, which is how a cart asks for "six pies, two kinds".

The evaluator is pure #

evalCond(cond, ctx) takes a context that answers the questions: flags, quest state, counts, entities. It has no access to the world, so a test can build a fake context and check every rule.

Why one language #

The same sentences work in three places: a quest can be available, a dialogue line can be chosen, and a spawn can happen. A designer learns one vocabulary, and the cost of a new rule kind is paid once.

The same idea elsewhere #

The tide is a function of the hour, and the state this language reads is stored by the save system. For the quest guide on top of it, see the quest guide post. The project is on its project page.

Related projects