Skip to content

Catalogues

tilttek/wargame-army

A Catalogue is the data of a game, apart from the engine that reads it. The application provides its catalogues; the library ships none.

Units

A UnitEntry is a unit the catalogue offers:

ValueMeaningBy default
code, nameThe unit's code and the name shown to peopleRequired
categoriesUp to 20 categories, each once, from the one that fills a detachment's slot firstNone
pointsThe points of the unit with its fewest models, 0 to 100 0000
minModels, maxModelsThe fewest and the most models, 1 to 1 0001, and the fewest
pointsPerModelThe points of each model beyond the fewest, 0 to 100 0000
optionGroupsUp to 50 option groups; each option code once in the unitNone

Options

An OptionGroup is a choice among 1 to 100 options: the fewest and the most selections a unit makes in it, each option counted as many times as it is taken — min: 1, max: 1 for one weapon, max: 2 for up to two upgrades. An Option has its points each time it is taken, 0 to 100 000, the most times one unit takes it, 1 to 1 000, and whether its points count once for each model of the unit (perModel).

The points of a unit are its own, plus those of each model beyond the fewest, plus those of each option taken.

Detachments

A DetachmentType has 1 to 50 Slots, each for a category with the fewest and the most units of it, and the most detachments of the type an army takes. A unit fills the slot of its first category the detachment takes; a unit of no such category is not allowed in it. The catalogue says how many detachments an army takes, 0 to 20, and 1 at least as its most.

Constraints

A catalogue declares up to 200 constraints — counts of units and shares of points —, which Constraints describes. A constraint that names a unit names one the catalogue holds.

Shapes and bounds

ValueShape
The code of a catalogue, a unit, an option, a group, a detachment type or a category1 to 64 lower-case letters, digits, _, . or -, starting with a letter or a digit
The version of a catalogue1 to 32 ASCII letters, digits, _, ., + or -, starting with a letter or a digit
A name1 to 200 characters of UTF-8, without control characters or surrounding spaces

A catalogue holds 1 to 2 000 units and 1 to 50 detachment types, each code once.

Reading a catalogue

Catalogue::fromArray() reads the array toArray() writes, and fromJson() reads JSON of at most 4 MiB, nested at most 15 levels deep. Both refuse an unknown key, a missing key and a value of the wrong type with InvalidCatalogue, never another exception. An invented catalogue, in the shape toJson() writes:

{
    "code": "ember-vale",
    "name": "Ember Vale Skirmish",
    "version": "2026.1",
    "units": [
        {"code": "captain", "name": "Captain", "categories": ["hero", "leader"], "points": 60, "option_groups": [
            {"code": "weapon", "name": "Weapon", "min": 1, "max": 1, "options": [
                {"code": "sword", "name": "Sword"},
                {"code": "bow", "name": "Bow", "points": 5}
            ]}
        ]},
        {"code": "scouts", "name": "Scouts", "categories": ["troops"], "points": 50,
         "min_models": 5, "max_models": 10, "points_per_model": 10, "option_groups": [
            {"code": "kit", "name": "Kit", "options": [
                {"code": "long-rifle", "name": "Long rifle", "points": 2, "per_model": true}
            ]}
        ]}
    ],
    "detachment_types": [
        {"code": "vanguard", "name": "Vanguard", "max": 1, "slots": [
            {"category": "hero", "min": 1, "max": 1},
            {"category": "troops", "min": 1, "max": 3}
        ]}
    ],
    "min_detachments": 1,
    "max_detachments": 2,
    "constraints": [
        {"type": "count", "category": "leader", "min": 1},
        {"type": "points-share", "category": "hero", "max_percent": 25}
    ]
}

A changed catalogue takes a new version: a list records the version it was built with, and the validator says when the catalogue has moved on.