Chapter 3
Tags & the ontology
Tags are how a node says what it's like. Last chapter used them freely; this one is about what they are. A tag has a name and a leading sigil, and the sigil marks which facet of a thing the tag describes — for the reader and the engine alike. Five come up constantly.
+ | property | what a thing is — a role, a kind, an attribute. [+Grifter], [+Cursed] |
# | state | how it is right now — a mutable condition. [#Grieving], [#Wounded] |
& | verb | what happens, usually on an evt. [&Betrays(agent=…)] |
@ | relation | a bond between nodes. [@Rival_Of(other=…)] |
% | register | an engine-/world-level modifier. [%Status_Berserk] |
char vale [+Grifter] [#Suspicious]
evt the_switch [&Deceives(agent=vale, target=renn)]
char renn [@Rival_Of(other=vale)]
Tags can carry parameters in parentheses — [&Deceives(agent=vale, target=renn)] — which
bind roles so recognition can match "who did what to whom." A handful of parameter keys are reserved and
meaningful: hidden=true keeps a tag active in the engine but out of what's surfaced to a
player (that's how information asymmetry is built), and source, target, and
others anchor provenance and intent.
The leading character also carries a dynamic: + plays the trope straight (the
default), while - subverts, ? averts, and ! invokes it. These can
wait — the grammar reference has the full set; the five facets above are the
part to learn first.
imply: one tag, many
Vocabulary in TropeLang is layered. Tags form an ontology, and the connective is imply:
declaring that one tag pulls in others. When vale is tagged [+Grifter] and the
ontology says a grifter is deceptive and cunning, those component tags come along automatically.
imply Grifter -> [Deceptive, Cunning]
char vale [+Grifter]
This matters more than it looks. Implication is transitive (if grifter implies deceiver, and deceiver
implies something else, you get all of it) and it's reference-counted, so removing [+Grifter]
only removes the components nothing else still requires. The point is that a story can use rich,
specific words — grifter, con artist, sharper — while the engine sees the common structural facts
underneath. That shared substrate is exactly what lets a trope match across stories that use completely
different surface vocabulary (Chapter 4).
exclusive: mutually exclusive tags
Where imply says tags travel together, exclusive says they can't co-occur. It
declares a partition — a named set of tags of which an entity may carry at most one:
exclusive Allegiance -> [Loyalist, Traitor, Neutral]
char mole [+Traitor]
A character has one allegiance, not several. Declaring the partition tells the engine so, and a trailing
! on the name (exclusive Allegiance! -> […]) tightens "at most one" to
exactly one. Like imply, it's a vocabulary-level statement, not a fact about any
particular entity — the partition name is a label, never asserted on a character.
The point is what it does for recognition. A partition is a constraint: when a trope needs a
character to be [+Loyalist] and the story marks that character [+Traitor], that
partition sibling doesn't just leave the anchor unmet — it actively refutes it. The engine can
then tell "this trope is ruled out" apart from "we haven't seen evidence yet," which is the difference
between absence of evidence and evidence of absence (recognition makes
that distinction; the planning tools build on it).
A partition earns two more moves. In an exactly-one partition (Allegiance!),
eliminating members determines the rest: mark a character [-Loyalist] where only
Traitor remains and the engine derives [+Traitor] — the last candidate
standing. And a rule can demand resolution by anchoring the partition label itself
(when: char $p [+Allegiance!]), matching only once the character is settled on some member —
the difference between "we haven't placed them" and "they're placed, whichever way." Both need
engine ≥ 0.33.
Taxonomy: specific and general
Where imply pulls in companion tags, taxonomy says one tag is a kind
of another. A braced axis after a tag name — [+Warrior{Archetype}] —
declares a subsumption edge: a swordsman is a warrior. Recognition then reads the
specific tag as the general one, so a story that only ever says [+Swordsman] still satisfies
a trope gated on [+Warrior].
concept Archetype
prop Warrior
prop Swordsman [+Warrior{Archetype}]
char kael [+Swordsman]
The direction is is-a, one way: a swordsman counts as a warrior, never the reverse. The axis
(Archetype) groups related edges, and a tag can sit under several parents at once — the graph
is a DAG, not a tree. The brace is what makes it structural: a plain [+Warrior] stays
ordinary annotation, so no vocabulary written before taxonomy landed changes meaning. It is recognition's
alone — expanding what a trope will match while staying out of eval and the
drams coverage count, where folding in vocabulary structure would only inflate
the numbers. Needs engine ≥ 0.32.0.
The prelude
All of this rests on the prelude: the base vocabulary and its implications, computed
once and always in scope. It's why [+Protagonist] means something without you defining it,
and why two authors who never coordinated still write tags that the same engine understands. The full,
living list of what the prelude and corpus define is the
vocabulary glossary — generated straight from the core, so it never
drifts from the language.