Cards & generation
StableThe Card block, and the rows × loops × count math that builds a deck.
A Card: block is a card type. It binds a sheet, a physical size, a coordinate
grid, and the templates that draw each face.
Card: Monster
sheet: Monsters # required — which data feeds it
size: poker # required — the physical card
x_units: 20 # required — the coordinate grid width
y_units: auto # required — auto keeps units square
loop: Suit as current_suit # optional — multiplies the deck
count: [count] # optional — copies per card (default 1)
Front: MonsterFront # required
edition: CardEdition.Black # required when MonsterFront declares this param
Back: PlainBack # optional — omitted means a plain white back
sheet:, a physical size, x_units:, y_units:, and Front: are required;
everything else has a default.
Instead of a size: preset, a Card may declare an exact width_mm: +
height_mm: pair — see custom sizes.
Indented lines below Front: and Back: pass explicit arguments to that Template;
see Template parameters.
How many cards you get#
For each Card block:
for each non-empty row of the bound sheet
for each combination of loop cases
emit `count` copies
Those copies are identical unless a face reads a per-instance generation binding such
as [copy], [deck_card], or [project_card]. Then each copy
resolves on its own, since its number is genuinely different content.
So the deck is rows × loop options × count. With the demo's two rows, three suits, and counts of 2 and 1:
- 2 rows × 3 suits = 6 distinct faces
- 2+2+2 + 1+1+1 = 9 physical cards
Multiple loop: lines nest in declaration order — rows × suits × elements × … Cases
come out in the order you declared them in the enum.
Every card generated this way can reference its row, copy, deck, deck-relative position, and project-wide position; see generation identity.
count:#
count: is an expression, so it can come from data (count: [count]) or be computed
(count: if [rare] then 1 else 3). It must evaluate to a whole number of at least 0 —
a 0 simply produces no cards for that row.
All generation built-ins are legal in count:. Because copies do not exist yet, count
uses the prospective first copy of that row × loop combination: [copy] is 1,
[card]/[deck_card] are the next deck position, and [project_card] is the next
project position. A legal count: 0 consumes no deck or project position.
Limits#
A single Card block generates at most 2,000 physical cards. A typo'd count of
999999 triggers D007 and truncates that Card block with a note in the status bar
instead of freezing the editor.
Separately, each card instance has a budget of 500 Repeat expansions per card.
Every iteration of every Repeat counts, including the outer and inner iterations
of nested repeats. Crossing that budget is D004: the affected card becomes an error
placeholder rather than keeping a partially truncated face. Other cards continue to
generate normally.
Several Card blocks#
A project can have as many Card: blocks as you like, and they can share sheets and
templates. Each becomes its own group in the preview, and in
PDF export each deck starts on its own page — decks never share a
sheet of paper.
[card] intentionally restarts for every Card block; [deck_card] is its more explicit
alias. Use [project_card] only when you want one running ordinal across every block,
and [deck] when the Card declaration name itself is meaningful.
Card: Monster
sheet: Monsters
size: poker
...
Card: Token
sheet: Tokens
size: square
...