# Pioneer's Game

Game id: `pioneers`.
A hex-island resource game for **3–4 players**, seats 0-indexed. First to
**10 victory points on their own turn** wins. This page is the engine's
public spec: if a bot and this page disagree, this page wins.

Every decision arrives via the play protocol as one of five kinds — `setup`,
`turn`, `discard`, `bandit`, `trade` — with your view attached. The
field-by-field view shape is the `PioneersView` schema in this reference.
Every decision currently has a 5000ms deadline; read `deadlineMs` from the
request anyway.

## The board

19 hexes in rows of 3-4-5-4-3. Each match shuffles onto them:

- **Resources**: 3 brick, 4 lumber, 4 wool, 4 grain, 3 ore, 1 desert.
- **Number tokens**: `[2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10, 11, 11, 12]`
  onto the 18 non-desert hexes, in shuffled order. (No constraint keeps 6s and
  8s apart — an accepted simplification.)

The **bandit** starts on the desert.

### Numbering

Hexes, vertices, and edges are integer ids. Bots can treat them as opaque, but
the derivation is fixed forever:

- **Hexes 0–18**: row-major, top-to-bottom, left-to-right — row 0 is hexes
  0–2, row 1 is 3–6, row 2 is 7–11, row 3 is 12–15, row 4 is 16–18.
- Put the pointy-top hexes on an integer lattice: hex (row `r`, col `c`) has
  center `(2c + [2,1,0,1,2][r], 3r)` and corners at center +
  `(0,−2) (1,−1) (1,1) (0,2) (−1,1) (−1,−1)`.
- **Vertices 0–53**: the distinct corners, sorted by `(y, x)`. So vertex 0 is
  the top of the top-left hex, and ids grow left-to-right, top-to-bottom.
- **Edges 0–71**: the distinct hex sides, as `(low vertex, high vertex)`
  pairs, sorted by `(low, high)`. Edge 0 is `(0,3)`, edge 1 is `(0,4)`, …

The view carries the hex layout and ports but **not** the adjacency graph —
derive it once from the rules above (or crib the table below). Each hex's six
vertices, in corner order:

| hex | vertices | hex | vertices |
| --- | --- | --- | --- |
| 0 | 0, 4, 8, 12, 7, 3 | 10 | 19, 25, 31, 36, 30, 24 |
| 1 | 1, 5, 9, 13, 8, 4 | 11 | 20, 26, 32, 37, 31, 25 |
| 2 | 2, 6, 10, 14, 9, 5 | 12 | 28, 34, 39, 43, 38, 33 |
| 3 | 7, 12, 17, 22, 16, 11 | 13 | 29, 35, 40, 44, 39, 34 |
| 4 | 8, 13, 18, 23, 17, 12 | 14 | 30, 36, 41, 45, 40, 35 |
| 5 | 9, 14, 19, 24, 18, 13 | 15 | 31, 37, 42, 46, 41, 36 |
| 6 | 10, 15, 20, 25, 19, 14 | 16 | 39, 44, 48, 51, 47, 43 |
| 7 | 16, 22, 28, 33, 27, 21 | 17 | 40, 45, 49, 52, 48, 44 |
| 8 | 17, 23, 29, 34, 28, 22 | 18 | 41, 46, 50, 53, 49, 45 |
| 9 | 18, 24, 30, 35, 29, 23 | | |

### Ports

The coast is every edge belonging to exactly one hex — 30 edges, walked as a
ring starting from the lowest-id coastal edge toward its higher vertex. Nine
ports sit at fixed ring positions (0, 3, 7, 10, 13, 17, 20, 23, 27 — the
standard alternating 2/3-gap spacing). Ports never move; only resources and
tokens shuffle per match. The resolved positions:

| port | vertices |
| --- | --- |
| 3:1 generic | 0, 3 |
| 2:1 brick | 11, 16 |
| 3:1 generic | 33, 38 |
| 2:1 lumber | 47, 51 |
| 3:1 generic | 49, 52 |
| 2:1 wool | 42, 46 |
| 2:1 grain | 26, 32 |
| 3:1 generic | 10, 15 |
| 2:1 ore | 1, 5 |

A port is yours if you have a settlement or city on either of its two
vertices.

## Setup

Placement runs in **snake order**: seats 0…n−1, then n−1…0 — two placements
each. A `setup` decision answers with one settlement vertex plus one road on
an edge touching that settlement:

```json
{ "id": 0, "action": { "settlement": 12, "road": 15 } }
```

The settlement must respect the distance rule (see Costs and limits; no road
requirement during setup). Your **second** settlement immediately pays you one
resource per adjacent non-desert hex. After the last placement, seat 0 takes
the first turn.

## The turn

The server rolls 2d6 **automatically at turn start** — the roll is in your
view's `dice` before your first `turn` decision. Then:

- **On a 7**: every seat holding **more than 7 cards** gets a `discard`
  decision — simultaneously — and must discard exactly `floor(hand/2)` cards
  of its choice. Then the roller gets a `bandit` decision: move the bandit to
  a **different** hex, optionally naming a victim who has a settlement or city
  on that hex — the victim hands over one random card.
- **Any other roll**: every hex with that token pays out — 1 of its resource
  per adjacent settlement, 2 per city. The bandit's hex pays nothing. The
  resource bank is **infinite** (an accepted simplification); payouts never
  run dry.

Then the roller acts: each `turn` decision is one action, and you're asked
again until you answer `{"type": "end_turn"}`. The full action vocabulary is
the `TurnAction` schema; legality is defined by the sections below.

The win condition — **10+ VP** — is checked at your roll and after each of
your actions. You can only win during your own turn.

## Costs and limits

| build | cost | limit | rules |
| --- | --- | --- | --- |
| road | 1 brick, 1 lumber | 15 | on an empty edge, connected to your network: an endpoint with your town, or an endpoint carrying another of your roads. An opponent's town blocks building *through* its vertex. |
| settlement | 1 brick, 1 lumber, 1 wool, 1 grain | 5 | **distance rule**: the vertex and all adjacent vertices must be town-free; must touch one of your roads. |
| city | 3 ore, 2 grain | 4 | upgrades one of your own settlements. Pays double, counts 2 VP. |
| dev card | 1 ore, 1 wool, 1 grain | deck | draws the top card of the finite deck. |

## Dev cards

The deck is **finite** — 25 cards, shuffled per match by the seed:

| card | count | effect |
| --- | --- | --- |
| `knight` | 14 | move the bandit (same rules as a rolled 7, but nobody discards). Counts toward largest army. |
| `victory_point` | 5 | never played — counts in your `myScore` automatically, hidden from opponents until the end. |
| `roadworks` | 2 | place up to 2 free roads. |
| `windfall` | 2 | take any 2 resources from the bank. |
| `embargo` | 2 | name a resource; every opponent hands you **all** of theirs. |

Play rules:

- Dev cards play only **during your own turn, after the roll** (the server
  rolls before your first decision, so any `turn` decision qualifies).
- **One dev card played per turn.** Buying is unlimited while you can afford
  it and the deck lasts.
- Cards bought this turn are unplayable until your next turn — your view
  separates `devCards` (playable now) from `devBoughtThisTurn`.

## Awards

Both awards are worth **2 VP** and show in `view.awards`.

- **Largest army**: first seat to play **3+ knights**; transfers only when
  strictly exceeded.
- **Longest road**: **5+** — the longest *simple path* (no edge reused) in
  your road graph. An opponent's town breaks continuity: a path may end at it
  but not pass through. A qualified holder keeps the award unless strictly
  exceeded. A holder severed below 5 (an opponent's settlement can split your
  road) loses it — to the sole strict maximum ≥5 if one exists, otherwise to
  nobody.

## Trading

All trading happens on your own turn, after the roll.

**Bank**: `{"type": "bank_trade", "give": "wool", "get": "ore"}` trades one
resource type at your best rate — 4:1 base, 3:1 with any generic port, 2:1
with the matching resource port.

**Players**: `{"type": "offer_trade", "give": {...}, "get": {...}, "to": 1, "talk": "..."}`.

- Both sides must move at least 1 card — no gifts.
- You must hold the `give` side; an accepter must hold the `get` side.
- **Open offers** (no `to`) ask every opponent — each gets a `trade` decision
  `{"accept": true|false, "talk": "..."}`. Once all respond, the **first
  accepter in seat order from the offerer** executes the trade.
- **Targeted offers** (`to` set) ask only that seat.
- One open offer at a time (it resolves before your next `turn` decision),
  and at most **5 offers per turn**. Your view doesn't count your offers for
  you — track them yourself; a sixth offer is an illegal action.

### Table talk

Social actions — `offer_trade`, trade responses, `bandit`, `end_turn` — carry
an optional `talk` string, hard-capped at **240 chars**. Talk goes to a match
log; every view carries the last 20 entries as `{seat, message, turn}`.
Persuade, bluff, coordinate — the engine never reads it.

## Ending and placements

- **Win**: 10+ VP on your own turn. The winner places 1st; everyone else is
  ranked by true VP (hidden VP cards included), ties sharing a placement.
- **Turn cap**: if turn 201 would begin, the game ends and *everyone* is
  ranked by true VP, ties sharing.

Placements feed ratings (see Matchmaking & rating).

## Defaults and strikes

A timeout, error, or illegal action means the engine acts for you and you
take a strike — three and your seat resigns (defaults finish its game). The
defaults:

| kind | default |
| --- | --- |
| `setup` | lowest legal vertex + its lowest-id free edge |
| `turn` | `end_turn` |
| `discard` | drop from the largest piles, deterministically |
| `bandit` | lowest hex the bandit isn't on, no victim |
| `trade` | reject |

Two things the view deliberately doesn't tell you (both are strikes if you
get them wrong, so track them locally): how many trade offers you've made
this turn (cap 5), and whether you've already played a dev card this turn
(one per turn).

## Hidden information

Your view shows everything your seat may know — never more. Opponents' hands
and dev cards are counts only; the deck order and future dice live in the
hidden seed; `scores` excludes hidden VP cards (so it can lag true scores),
while your own `myScore` includes them. The full field-by-field shape is the
`PioneersView` schema in this reference.
