Views: how a game lies on the table
A game has three layers, each in its own file:
| Layer | File | Read by |
|---|---|---|
| Rules | the model | engine, validator, diagram, player |
| Players | a tactic | the engine, as a player (see tactics) |
| View | a view | the player: the Board tab of the table |
The engine never reads a view: it changes nothing about the rules or the results.
Using a view with your model. In the validator, paste the view into "View (optional YAML)" below the model and press Check. "Open in the player" then opens your model with that view. The validator only checks that the view is readable YAML ("The view cannot be read" otherwise); a slot that names a zone, variable or board the model does not have shows up in the player (for example "board x not found"). The built-in games of the player come with their own views; "Start from" in the validator loads an example together with its view.
Without a view the player lays out the table itself: shuffled or hidden zones as a deck, open
zones as a row, a meter for every per-player variable with a numeric init, and an area per
player for the zones with owner: player.
Cards are drawn as typographic cards (name, type, numbers, tokens), never as the original artwork. What a viewer sees follows the visibility in the model: in the player you can "view as player p", and hidden zones and other players' hands then show only card backs.
Structure
view: my-card-game # label only; the view belongs to the model it is used with
card:
lang: en # language of card names, for hyphenation (default en)
type_field: type # field with the card type (small text in the colour band)
type_names: {hero: Hero, ally: Ally} # optional: display names of the types
color: # colour band: the first entry that matches
- {field: sphere, values: {leadership: "#6d4c9f", tactics: "#a53a2c"}}
- {field: type, values: {enemy: "#6b4a32"}}
corner: [cost, threat] # number top right: the first of these fields the card has
stats: # numbers at the bottom, with an icon
- {field: willpower, icon: "✦", name: willpower}
- {field: hp, icon: "♥", name: hit points}
tokens: # numbers on the instance shown as tokens on the card
damage: {color: "#c0392b", name: damage}
sideways: exhausted # turn the card sideways while this property is true
table: # the middle of the table, row by row
- row:
- {zone: encounter_deck, as: deck}
- {zone: encounter_discard, as: discard} # top card face up
- {quest: {var: quest_card, catalogue: quests, progress: progress, goal: quest_points}}
- {zone: staging, name: staging area, wide: true}
player: # the area of every player (per-player zones show that player's part)
- row:
- {meter: {var: threat, max: 50, name: threat}}
- {zone: heroes, attachments: {zone: attachments, field: host}}
- {zone: hand, small: true, wide: true}
card
| Key | Type | Default | Meaning |
|---|---|---|---|
lang | text | en | Language of the card names (the lang attribute, for hyphenation) |
type_field | text | type | Field that holds the card type |
type_names | {type: name} | Display name per type; otherwise the type itself | |
color | list of {field, values} | Colour band: the first entry whose field value is in values. No match: a colour derived from the type | |
corner | list of fields | Number in the top right corner: the first listed field that holds a number | |
stats | list of {field, icon, name} | the first 4 numeric fields of the content item | Numbers along the bottom; name is the tooltip |
tokens | {property: {color, name}} | Numeric properties of the instance shown as coloured tokens. Without tokens, every positive number on the instance that the content item does not have is shown as a token | |
sideways | property | The card is turned sideways while this property is true |
A card's fields are the content item's fields (looked up by id) overlaid with the current
properties of the instance. Properties that are true (other than sideways) show as tags.
table and player
Both are lists of rows: - row: [slot, slot, ...]. table is drawn once; player once per
player, and a per-player zone in it shows that player's part.
| Slot | Key | Meaning |
|---|---|---|
| Zone | zone | Name of a zone in the model |
as | row (all cards side by side), deck (a face-down pile with a count) or discard (a pile with the top card face up, if the viewer may see it). Default: deck for shuffled or hidden zones, row otherwise | |
name | Heading; default the zone name | |
wide | Take the rest of the row | |
small | Smaller cards | |
attachments: {zone, field} | Cards from that zone whose field equals the uid of a card in this zone are shown under it | |
| Meter | meter: {var, max, name} | A dial for a numeric variable; for a per-player variable, that player's value. max default: the larger of 10 and the value |
| Quest | quest: {var, catalogue, progress, goal} | A landscape card: the item content[catalogue][<value of var>] (or the content item with that id), with the variable progress against goal (a derived value or variable; default the card's quest_points) |
| Grid | board: {zone | var, columns} | A grid of cells from a zone or a list variable, columns wide (default 3); None shows as empty |
| Board | board: {geometry, ...} | A board from the model's boards with pieces; see below |
Every slot may have a name. Cards that are new since the previous request get a highlight, and a
meter shows its change.
The smallest view, for a 3 × 3 grid kept in a zone board:
view: tictactoe
table:
- row:
- {board: {zone: board, columns: 3}, name: board}
Boards with geometry
A board from boards (see board geometry) is drawn with the same geometry as
the engine: square with coordinates, hex with gaps drawn as walls, walls between cells as lines.
Cells that changed since the previous request get a highlight (in chess: the from and to squares).
table:
- row:
- name: chessboard
board:
geometry: board # name in the model's boards
pieces: {var: pieces} # a dict cell → piece
checkered: true
flip: true
names: true
icons:
wK: {icon: "♚", color: white}
bK: {icon: "♚", color: black}
- name: dungeon
board:
geometry: map
pieces: {zone: figures, field: cell} # instances with a property cell
color: {field: side, values: {hero: "#2f6fb3", monster: "#a53a2c"}}
value: hp # number on the token
cells: # highlighted cells (with a legend)
- {const: OBSTACLES, color: "rgba(120, 100, 70, .65)", name: obstacle}
- {const: TERRAIN, color: "rgba(110, 160, 80, .42)", name: difficult terrain}
| Key | Meaning |
|---|---|
geometry | Name of the board in the model's boards. Unknown: a "board not found" notice |
pieces | {var}: a dict cell → piece (text, or a dict whose label or id names it). {zone, field}: the instances in a global zone, placed on the cell in their property field (default cell); fixed fields come from the content item, or from a dict with that id in constants |
icons | Piece label (or id) → icon text, or {icon, color} with color: white, black or a CSS colour. Without an icon: a round token with the first letters of the label |
color | {field, values}: token colour from a property of the piece |
value | Property shown as a number on the token |
cells | List of {const | var, color, name}: the cells in a constant or variable (a list of cell names, or a dict whose keys are cell names) get that colour; name goes into the legend |
checkered | Alternate light and dark squares (square boards) |
flip | Turn the board around when viewing as player 1 |
names | Show cell names (square: a–h and 1–8 for letters boards, else numbers; hex: the cell name in each cell) |
Clicking a piece or card shows its properties. Complete views, used by the player for the built-in games of the same name: chess, hex-skirmish and tictactoe.