Documentation

Game logic

v3 · Preview

Framework v3 is an opt-in preview available to everyone. New games use the stable framework by default.

Decisions, drafts, and Undo

Intents

Intent Means Bots
Choice Adds new information to the open decision and moves it forward. take it
Confirm Ends the decision and sends it. take it
Cancel Changes or takes back something already chosen in the open decision. ignore it

Two rules follow, and a game must keep both:

  1. Every state inside an open decision offers at least one Choice or Confirm. A bot ignores Cancel, so it must always have something else to take.
  2. A Choice never returns the decision to a state it had before. A bot taking only Choice and Confirm must always reach the end.

Worked example: a draft of 12 cards

The seat stages one card, may switch to another, and then takes the staged card.

  • Nothing staged: each of the 12 cards is a Choice.
  • One card staged: the other 11 cards are still offered, so the seat can switch, but as Cancel. The take command is a Confirm.
#[derive(Default, Serialize, Deserialize)]
#[serde(crate = "boardweaver_sdk::serde", default)]
struct Pick {
    staged: Option<usize>,
}

fn offers(table: &Table, player_id: PlayerId) -> Vec<Offer> {
    let pick: Pick = table.state().read(StateOf::PlayerPrivate(player_id));
    let switch = if pick.staged.is_some() { Intent::Cancel } else { Intent::Choice };
    let mut offers: Vec<Offer> = (0..table.state().space("market").pieces.len())
        .filter(|&index| pick.staged != Some(index))
        .map(|index| {
            Offer::new(Action::PieceClick { space_id: "market".into(), index }, switch)
                .label(msg!("offer.stage", card = index))
        })
        .collect();
    if pick.staged.is_some() {
        offers.push(Offer::new(Action::command("take"), Intent::Confirm).label(msg!("offer.take-staged")));
    }
    offers
}

The common mistake is to tag the 11 switches as Choice. Then staging card A, then card B, then card A again returns the decision to a state it had, and a bot can switch between cards forever.

What ends a decision

A decision stays open, as the seat's draft, until a step ends it. The first rule that applies decides:

  1. The step drew from Rng: the decision ends, whatever the step's intent.
  2. The step is a reveal: the decision ends.
  3. The step's intent is Confirm: the decision ends.
  4. Otherwise the decision stays open.

So only the last step of a decision can draw randomness or reveal. Plan multi-step moves so the random or revealing part comes last.

Undo

Undo is not an intent and not an action: it is the platform's, and the client shows its button. The game logic allows it with table.allow_undo() (Changing the state).

Need a hand with this?

Join our Discord