# 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](https://tabletwin.com/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 game | Right: what the workshop makes of it |
|---|---|
| **Model** – the rules, as YAML text | **Check** – 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 chips | **Play** – play it yourself |
| **Images** – your own pictures | **Simulate** – 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:

```yaml
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:`:

```yaml
  stand:
    label: stand
    effect: []
```

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

```yaml
  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`:

```yaml
    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`:

```yaml
  - 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](https://tabletwin.com/docs/workshop/#rules-in-words)). The [quick reference](https://tabletwin.com/docs/cheatsheet/) 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](https://tabletwin.com/docs/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](https://tabletwin.com/docs/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](https://tabletwin.com/docs/reference/) has every key; the [quick reference](https://tabletwin.com/docs/cheatsheet/) fits on one page.
- [Views](https://tabletwin.com/docs/views/) for your own card art, backs, boards and pieces, also in 3D.
- [Authoring with an AI agent](https://tabletwin.com/docs/authoring-with-ai/) when you would rather have a rulebook turned
  into a model for you.
