DPC Zettelkasten Open in the explorer

Faction Relationship

Diplomacy is stored as directed edges between factions, typed as ally, at war, vassal, or liege.

Diplomacy is not a field on the Faction record. It is a separate table of directed edges, each carrying one of four types: ALLY, AT_WAR, VASSAL, or LIEGE.

Directed, not symmetric

Each row records a relationship from one faction to another. Two of the four types are inverses — A's VASSAL edge to B pairs with B's LIEGE edge to A — so a hierarchy is represented by two rows, not one.

The service enforces that pairing rather than assuming it. getLiege reads the faction's own LIEGE edge, then checks the reverse direction for a matching VASSAL edge before accepting the answer; getVassals filters symmetrically. A half-written hierarchy — one row present, its counterpart missing — resolves to no relationship at all rather than to a lopsided one.

Storing both directions also means "who are my allies?" and "who considers me an ally?" are the same cheap query.

Why relationships get an approval step

Because a relationship change binds two independent groups of players, it cannot be a unilateral command. Approval Request exists for exactly the three relationship transitions that need consent — war, alliance, and vassalisation.

Effect on the rest of the model

Relationships are read by more of the codebase than any other domain concept:

Vassalage covers the liege/vassal pair specifically, since it carries mechanical weight that alliance does not.

Sources

Linked from