Contracts

Optional

A contract is a short list of questions about one game mechanic, such as what a backpack does with a pile of items that will not fit. Answer the questions and the mechanic is defined well enough to build and test. A contract with the answers filled in is an adoption. To use one, start from the Contracts pages. The files below are what they produce.

The adoption file#

contracts/backpack.json, part of a filled-in Container adoption

{
  "contract": "container",
  "version": 1,
  …
  "answers": {
    "capacity-limit": "slot-count",
    "partial-acceptance": "fill-what-fits",
    "leftover-destination": "left-where-it-is",
    …
  },
  "values": {
    "slot-count": 12,
    …
  },
  …
}

This backpack has twelve slots. It takes the part of a delivery that fits and leaves the rest where the delivery arrived. The adoption file also carries a copy of the contract's definition, left out above: the questions, their options and the rules. In this excerpt, … marks fields left out. Each option has a meaning: the promise you choose, in plain words. An option can also carry semantics: exact wording for the builder and the tests. The definition's mechanism text says what every game that uses this contract must do.

Put it in your game#

The adoption is a file in contracts/. It holds the copied definition, the answers, the values, any content rows, and any inputs the tests need. Some questions and settings apply only after a particular answer. Two adoptions can use the same contract with different answers.

The example writes its slot count directly. A contract can also let a setting cite a number you have already named: a number in the values part of tuning.json, with or without a range, or another setting of the same adoption. The contract says which forms it allows. The setting uses the number written in your package, even when the builder chooses another value for a cited number that has a range. A setting cannot cite an open number, one you have not decided yet, and it cannot cite a setting of another adoption.

Content rows can list things such as the item types a container accepts. Some rows cite a rule by its chapter file and heading, such as 02-mechanics.md#recovery. The citation must match exactly one heading in that file. The section under that heading must be Fixed (the builder follows it exactly), so no > DELEGATED: or > PERSONALIZATION: tag may cover any part of it.

The filename gives the adoption its address: contracts.backpack. contracts.backpack.slot-count names its slot count. The authoring tool can update references when you rename an adoption, and validation reports references that no longer point at anything.

Adding a contract does not supply the rest of a game's rules. The chapters still say how the mechanic is used in play.

Check the promise#

Package validation checks the adoption's form, required answers, declared values and rows, citations and numeric rules. It does not run your finished game.

The contract's acceptance tests are in a separate file, the verification pack. With the matching pack next to it in contracts/, an adoption is checked: the tests are part of the design you give the builder. Without the pack, the adoption is promised: you have stated the behavior, and the builder must still implement it, but no tests come with it. Checked never means a game has passed the tests.

Keep the exact matching pack next to the adoption. The copied definition names the pack's SHA-256 fingerprint, and validation compares it with the file. A pack for another version of the contract does not match. The command npx opengdd render-contract-tests <package-dir> shows the tests that apply to your answers. It does not run them or add them to your build plan.

Change or remove it#

Changing an answer changes what the builder must implement. Review the resulting tests and your ordinary game rules together. Updating to a newer version of a contract can keep your answers while changing what they mean. It does not update your game rules or saved games for you.

When you remove an adoption, review the tuning and prose that used it. Update references that used its address, and remove its pack only when no other adoption needs it. You can also use a contract as a checklist without adopting it, by recording your decisions in ordinary prose.

A contract records design promises. The builder chooses how to implement them. Only evidence from running the game shows that the promises are kept.

Full rules: OpenGDD specification, §10.

← Personalization questions · All chapters · What validation proves →