Docs: Tutorial: build a game in the workshop

Tutorial: build a game in the workshop

In half an hour you turn the workshop's small starting game into a game of your own, check it, play it, let the computer play it a thousand times and share it by link. You need no code: the rules are written as data, and the workshop's tabs let you edit the cards, the flow and the table as tables, trees and chips. Where a line of text is needed, this page gives it.

The workshop keeps your games in your own browser; nothing is uploaded until you share a link or a package yourself.

1. Start from Fifteen

Open the workshop. The first visit shows Fifteen, a complete two-player card game: play a number card from your hand onto your pile and draw one; reach exactly 15 to win, go over and you lose. The left side holds the game in tabs, the right side looks at it:

Left: the gameRight: what the workshop makes of it
Model – the rules, as YAML textCheck – errors, warnings, how much of the model the engine can run, 20 random test games
View – how the table looks (optional)Rules – the rules as a track, as people read them
Tactic – how the computer plays (optional)Table – the table, in 2D or 3D, with a slider through a computer game
Flow, Cards, Layout – the flow, the content and the table layout as a tree, tables and chipsPlay – play it yourself
Images – your own picturesSimulate – many games at once, and experiments

Press Check: No errors, 100% executable, 20/20 test games end. Press Play and play a round against the computer to see the game. Then New › A small card game to change (Fifteen), name it Twenty-one, Create. We make three changes: a higher target, a new card and a new choice.

2. A constant: the target

Open the Model tab. Near the top:

constants:
  TARGET: 15
  HAND: 3

Change 15 into 21. The three green badges stay green: every rule that mentions the target (total[current] == TARGET) follows. Texts for people do not: the summary and the end conditions still say 15; change the summary a few lines above (summary:) and the two end conditions at the bottom (if: "the current player has exactly 15") to 21. The Rules pane shows the words you write there.

3. A card: the Cards tab

Open Cards. The group cards shows the seven number cards as a table: id, label, value, suit, status. Press + card: a new row appears with a placeholder id and label. Make it id eight, label Eight, value 8, suit sun, status verified. Every cell you leave goes straight into the model text (look at the Model tab: the new line is there, in the same style as the others). Add a nine the same way.

The deck is built from the cards (init_x: "[c for c in content['cards'] for i in range(2)]": two copies of each), so the new cards are in the game at once. Table shows them on the table; Check still says 20/20.

4. A choice: the Flow tab

In Fifteen a turn is one step, Play a card. We add a second thing a player may do: stand, play nothing and keep the total. Open Flow: the game as a tree (Deal, then the loop Turns with the step Play a card). Tap Play a card. Under What can be done the model's actions are listed with a checkbox, deal and play_card; type stand in the field + new action… and press Enter. Two things happen: the step now offers play_card and stand (the player chooses between them), and an action stand is created in the model with an empty effect.

Open Model and find it at the end of actions::

  stand:
    label: stand
    effect: []

Give it a meaning: standing ends your part of the game. Replace it with

  stand:
    label: Stand
    pre: you have at least 16
    pre_x: "total[actor] >= 16"
    effect:
      - {op: set, var: "standing[actor]", value: true}

pre_x says when the action is legal: below 16 you must play. The variable does not exist yet: Check says so (the test games stop with name 'standing' is not defined). Add it under state.vars, next to total:

    standing: {scope: player, type: bool, init: false}

Now stop a standing player from playing: give play_card the extra condition pre_x: "len(hand[actor]) > 0 and not standing[actor]", and end the game when both stand. Add to end:, before cards_out:

  - id: both_stand
    if: both players stand: the one closest to 21 wins
    if_x: "all(standing[p] for p in players)"
    result: score
    returns_x: "[0, 0] if abs(TARGET - total[0]) == abs(TARGET - total[1]) else [1, -1] if abs(TARGET - total[0]) < abs(TARGET - total[1]) else [-1, 1]"

A line ending in _x is an expression the engine runs; the line before it without _x is the same thing in words for people. Put the cursor in an _x and the panel under the text reads it out, shows its value on the table and, for a condition, lets you Build it from rows (Rules in words). The quick reference lists the operations (set, add, move, draw, choose, if…) and the names you can use.

Check is green again? Press Play: at 16 or more you get the choice Play a card or Stand. A player who has no legal action is skipped, so a standing player's turns pass by themselves.

5. The table: the Layout tab

Open Table: the deck on the table, per player a dial for total, the hand and the pile; that comes from Fifteen's small view (the View tab). To arrange it yourself, open Layout: the rows of the table as chips. Drag deck into a row of each player and back, move the dial to the right of the hand; tap a chip for its options: a name, wide, small cards, the maximum of a dial. The dial still runs to 15: tap total, set Max to 21. The Table pane follows every change, and the View tab shows the text it writes. (A game without a view gets an automatic layout; the Layout tab then offers to start from it.)

The palette Not placed yet lists what the model has that is not on the table yet. Numbers become dials; standing is a yes/no and gets no chip: the options a player has (Play a card or Stand, or nothing) tell the story, and the Details view of the player shows every value.

6. Let the computer play it: Simulate

Open Simulate: 1000 games with random players, in a few seconds. The result: how often each player wins, with a 95% interval, how the games ended (both_stand, bust, cards_out…) and a histogram of the game length. Does player 1 win too often? Tick Experiment: vary a constant, choose TARGET, from 15 to 25, step 2: a chart of the win rates and the game length for every target. That is where you balance a rule: pick the value that gives both players a fair chance and games that last the length you like.

The computer players so far move at random. Tactic gives them rules of thumb: which card to play, when to stand; see tactics. With a tactic, Compare with other players plays the same games (same seeds) with and without it, so the difference is the tactic, not luck.

7. Share it

Share link puts the whole game into a link: whoever opens it gets a copy in their own workshop and can play it in the player. Download package gives a zip with the model, the view, the tactic and your images, for a backup or for a repository; Import reads one back. Your game also appears in the player's Game box, for playing against the computer, in 3D, with the rules in words.

Where to go from here

  • The guide builds a game from a rulebook step by step and has the patterns for everything Fifteen does not need: dice, boards, triggers, modifiers, hidden information, campaigns.
  • The reference has every key; the quick reference fits on one page.
  • Views for your own card art, backs, boards and pieces, also in 3D.
  • Authoring with an AI agent when you would rather have a rulebook turned into a model for you.

This page as Markdown