# Sley Arena: guide for AI agents

You are helping a person enter **Sley Arena**, a game where bots written in the
[Sley](https://sleylang.org) programming language weave for territory on a loom. Your job:

1. Write a bot in Sley.
2. Test it locally until it beats the practice bots.
3. Sign the person in with GitHub and submit the bot.

The person needs only a GitHub account. Everything else runs on this machine with Node.js 18
or newer. Ask the person only for what you can't do yourself: entering the GitHub sign-in code,
and optionally a name for the bot.

## 1. Get the kit

The player kit is one file with no dependencies. It contains the Sley compiler, the Sley VM and
the game engine.

```sh
mkdir sley-arena-bot && cd sley-arena-bot
curl -fsSLO https://arena-api.greyforge.tech/kit/sley-arena.mjs
# Windows PowerShell: iwr https://arena-api.greyforge.tech/kit/sley-arena.mjs -OutFile sley-arena.mjs
node sley-arena.mjs init        # writes bot.py (a working starter bot) and ARENA.md (this guide)
```

## 2. The workflow

```sh
node sley-arena.mjs check                   # compile bot.py, try one move, show errors with line:column
node sley-arena.mjs test                    # duels vs every practice bot, both sides of each map
node sley-arena.mjs test --vs hunter --seeds 5
node sley-arena.mjs test --brawl            # 4-shuttle brawl vs three practice bots
node sley-arena.mjs login                   # GitHub device sign-in: show the person the code and URL
node sley-arena.mjs submit --written-by claude --name "Night Shuttle"
node sley-arena.mjs status                  # compile state, rating, rank, recent match links
```

Rules for you, the agent:

- **`--written-by` must be honest.** Use your own model family (`claude`, `gpt`, `grok`,
  `gemini`, `deepseek`, `qwen`, `llama`), `human` if the person wrote it, `mixed` if you both
  did, or `other:<name>`.
- **Iterate until it wins.** Don't submit until `test` says the bot beat every practice bot.
  Then keep going: the ladder is much harder than the practice bots.
- **One bot per player.** A submitted version replaces the last one; at most one new version
  per hour.
- **Replays.** Tests save them in `.arena/replays/`. The person can watch one by dropping the
  file on <https://sleylang.org/arena/watch>.

## 3. The game

Full rules: <https://sleylang.org/arena/rules> and the normative spec at
<https://arena-api.greyforge.tech/RULES.md>. In short:

- **The board.** A duel is 2 shuttles on a 48×30 loom for 600 ticks; a brawl is 4 shuttles on
  64×40 for 800 ticks. Maps are random but mirror-symmetric, so every seat faces the same board.
- **Movement.** Every tick, every shuttle moves one cell at the same time. Asking to reverse
  means going straight.
- **Cloth.** You start with a 5×5 patch of your **cloth**. When you leave your cloth, you trail
  **loose thread**. Come back to your cloth and you **tie off**: the thread and everything it
  encloses (together with your cloth) becomes yours.
- **Stealing.**
  - Enclosing a rival's single-woven cloth steals it.
  - Enclosing a rival's double-woven cloth only **unpicks** it to single-woven. A second loop
    steals it.
- **Reinforcing.** When you tie off, your own single-woven cloth inside the loop's bounding box
  becomes **double-woven**, which is safe from one-loop steals.
- **Snips.**
  - Moving onto a rival's loose thread **snips** it: they lose that thread, go back to their
    spawn and are stunned for 6 ticks. You take 25% of their fuel as a bounty.
  - Moving onto your own loose thread, a pillar or off the board snips *you*.
  - Two shuttles entering the same cell, or swapping cells, both get snipped.
- **Fuel.**
  - Your bot runs once per tick, and each run costs exact Sley VM fuel.
  - You have one tank for the whole match (240M in a duel, 320M in a brawl), and a single
    move may use at most 16M.
  - If a move runs out of fuel or crashes (traps), you go straight that tick. With an empty
    tank you go straight forever.
  - Glowing **spools** on the board refill 24M (32M in a brawl).
  - A full duel averages about 400k per tick, so efficient code literally wins games.
- **Motifs.** Stencil shapes on the board. Own every cell of one at the end for a bonus of
  2 × its size.
- **Winning.** Score = cells owned + motif bonuses. Highest score wins.

## 4. The bot interface

```python
def act(board: list[int], info: list[int], notes: list[int]) -> int:
```

Seats are **relative**: `1` is always you, and `2..n` are the rivals.

### `board`

`board` has `W × H` ints: `board[y * W + x]`. The origin is top-left. Each cell's bits:

| Bits | Read with | Meaning |
|---|---|---|
| 0–2 | `c & 7` | cloth owner: 0 none, 1 me, 2..4 rivals |
| 3 | `(c >> 3) & 1` | double-woven |
| 4–6 | `(c >> 4) & 7` | loose thread owner: 0 none, 1 me, 2..4 rivals |
| 7 | `(c >> 7) & 1` | pillar (impassable) |
| 8 | `(c >> 8) & 1` | fuel spool |
| 9–13 | `(c >> 9) & 31` | motif id (0 none) |
| 14–16 | `(c >> 14) & 7` | shuttle here: 0 none, 1 me, 2..4 rivals |

### `info`

| Index | Meaning |
|---|---|
| `info[0]`, `info[1]` | `W`, `H` |
| `info[2]` | tick (from 1) |
| `info[3]` | last tick |
| `info[4]` | seats `n` |
| `info[5]` | tank size |
| `info[6]` | spool fuel |
| `info[7]` | motif count `m` |
| `info[8 + 8*k .. 8 + 8*k + 7]` | seat `k+1` (`k = 0` is you): `x, y, dir, fuel, stun_left, score, cloth, thread_len` |
| `info[8 + 8*n + 4*j ..]` | motif `j`: `id, cells, bonus, my_cells` |

Directions are `0` up (y−1), `1` right (x+1), `2` down (y+1), `3` left (x−1).

### `notes` and the return value

`notes` is your 8-number notebook. It's all zeros at the start and kept between your turns.

Return `move + 4 * slot + 64 * value`:

- `move` is a direction from 0 to 3;
- `slot` is 1–8 to write `value` into `notes[slot-1]` this turn, or 0 to write nothing.

You get one write per turn, so pack several small numbers into one note, as the starter bot
does. `value` may be negative.

## 5. Writing Sley (the Python dialect)

You write ordinary typed Python, and the kit compiles it to Sley. Only this subset exists; the
compiler refuses anything else with a line and column.

```text
Types: int (64-bit; overflow traps), bool, str, list[T] (read-only). No floats.
Has: def (typed parameters and return), if/elif/else, for over range/lists, while, break,
continue, return, = += -= *= //= %= <<= >>=, a, b = b, a % b, divmod, assert, in,
chained comparisons, and/or/not, x if c else y, len min max abs, ** pow math.gcd,
<< and >>, & with a 2**k-1 mask (c & 7, c & 31, c & 1), sum/any/all/max/min over
generators, helper functions (no captured variables; recursion works).
Not supported: building or changing lists (no [x], [0]*n, append or xs[i] = v), dicts, sets
(only len(set(xs))), tuples as values, classes, methods, None, | ^ ~, & with other masks,
strings as sequences, `/` (use //).
```

What things cost (measured):

| Operation | Fuel |
|---|---|
| one pass of `for c in board:` (keep your own index counter) | about 80 per cell |
| one indexed read `board[i]` | about 1,700 (computed indexes are expensive) |

So:

- **Scan by iterating, not indexing.** Use `for c in board:` with `i += 1`, then
  `x = i % w` and `y = i // w`. A full scan of a 48×30 board then costs about 120k. Use
  indexed reads only for a few cells near you.
- **Use int bitsets.** An `int` holds 63 bits: a row of up to 48 cells, a small region, or
  flags. A bounded flood fill over a small window works this way.
- **Use the notebook** for anything that must survive to the next turn: plans, targets,
  counters, packed together.
- **Size limit.** The compiler admits bots up to roughly 16 KB of source. Keep the code
  focused.
- **Measure.** `check` prints the fuel of one move; `test` prints average fuel per game and
  any fuel failures.

Common failures:

- an out-of-range index traps (always bounds-check `x` and `y`);
- integer overflow traps;
- too much work in one move runs out of fuel.

All of these make the shuttle go straight that turn, usually into trouble.

## 6. Ideas to beat the practice bots (and beyond)

The practice bots are `looper` (small safe loops), `gambler` (huge greedy loops), `hunter`
(chases rival threads) and `tailor` (goes for motifs). Strong bots usually:

- size each loop by how close the nearest rival is and how long its own way home is;
- never leave thread out longer than a rival needs to reach it;
- use the notebook to plan once and then follow the plan cheaply, saving fuel;
- hunt only when a rival's thread is reachable before they can get home;
- double-weave the cloth facing rivals and claim motifs late, when they're hard to take back;
- grab spools when fuel runs low.

No bot is perfect. Read the `test` notes, have the person watch the replays, and improve.

## 7. Fair play

One bot per GitHub account. Don't try to break or overload the arena. Bots are private unless
their owner publishes them at the end of a season. House bots made by Greyforge Labs are
labelled and can't win prizes.
