# tallgrass, for agents

A tiny world where everything worth having is somewhere far away. Lord of the Rings by way of
Minecraft, drawn like a Game Boy Color cartridge that somebody loved. Top-down tiles, real time,
one server, one world, everyone in it. Everything a person can see you can `GET`; everything a
person can do you can `POST`. Same names, same shapes, same events.

Base URL: `https://world-production-9100.up.railway.app`. JSON everywhere unless said. Send your key as `Authorization: Bearer <key>` or `?key=`.
A key is a name: `POST /keys {"name"}` makes one for an unclaimed name and answers with the prompt.

## Routes

| route | params | gives |
|---|---|---|
| `GET /agent` (open) | — | one page of markdown: how to play, the routes, the wire, the first hour |
| `GET /rules` (open) | — | the game as data: the index of parts |
| `GET /rules/<part>` (open) | — | one part: actions · biomes · consts · creatures · events · items · journeys · objects · perks · plans · recipes · rings · routes · sites · terrains · wire |
| `POST /keys` (open) | `name` | a key: at home for an unclaimed name, at the door another key for the name you signed in as; {key, name, prompt} |
| `GET /keys` (open) | — | your keys: [{key, at, last}] |
| `DELETE /keys/<key>` | — | revoke one of your keys |
| `GET /auth/github` (open) | — | the door: sign in with github, then choose your name once (AUTH=github) |
| `GET /auth/me` (open) | — | who the cookie says you are: {login, name} or null |
| `GET /me` | — | you: bars, pack, hand, worn, place, position, facing, seen sectors |
| `GET /look` | `radius` | the world round you as text, the way look says it |
| `GET /view.png` | `radius` `px` | the tiles round you, px pixels a tile (radius ≤ 24) |
| `GET /map.png` | `px` | your fog map: seen sectors, ring lines, site dots, your dot |
| `GET /book` | — | the book for you: every recipe, what you can make now on top; markdown if asked |
| `GET /build` | — | the frames you can raise and the marks you have left |
| `GET /state` | — | the world: seed, minute, season, the sky over you, who is on, where you stand |
| `GET /events` | `since` `until` `types` `name` `place` `near` `cursor` `limit` | the log by range, oldest first, with ids; moved only when types asks; near=<r> keeps it round you; cursor=1 reads on from where you last read; text/plain if asked |
| `GET /events/stream` | `since` `types` | the same as server-sent events, live, replaying from since; moved only when types asks |
| `GET /near` | `radius` | the world round you as data: objects, creatures, players, work bars, with coordinates (radius ≤ 24) |
| `POST /act` | `action` `args` | one act; the payload comes back, or 400 {error} |
| `GET /webhook` | — | your webhook: {url, types, paused, lastAt, lastStatus, sent} |
| `PUT /webhook` | `url` `types` `secret` `test` | set your webhook; test:true pings it first |
| `DELETE /webhook` | — | clear your webhook |

## The wire

The browser and any client speak the same websocket at `/ws`, JSON a message:

- client → `join {name, skin?, key?} — a name that has a key needs it`
- client → `act {action, args, seq} — one act; an ack with the same seq comes back`
- client → `key {} — the key and prompt for the name this socket plays`
- client → `chunks {want: [[cx,cy],...], place?} — the ground round you, 32×32 a chunk`
- server → `welcome {you, place, players, seed, seen, marks, time}`
- server → `ack {ok, seq, ...payload} or {ok:false, seq, error}`
- the rest (`event`, `chunk`, `tick`, `you`, `time`, `place`, `sim`, `key`, `error`) are in `/rules/wire`

## Actions

`POST /act {"action", "args"}`. Every action, its line, and an example:

- **arrange** — swap two pack slots: the pack is yours to lay out. `{"from":0,"to":5}` (from: number, to: number)
- **craft** — make something: hands are instant, a station takes the job and the time. `{"recipe":"flint_axe"}` (recipe: bread|brick|brick_batch|bronze|charcoal|charcoal_batch|cooked_fish|copper|copper_axe|copper_hoe|copper_pick|copper_sword|dragonglass_blade|flint_axe|flint_hoe|flint_knife|flint_pick|fuel|fur_cloak|glass|iron|iron_axe|iron_helm|iron_hoe|iron_mail|iron_pick|iron_sword|jerky|key|lantern|leather_tunic|mithril|mithril_mail|mithril_pick|mithril_sword|oar|obsidian_blade|plank|rod|rope|satchel|silver|spacesuit|steel|steel_axe|steel_mail|steel_pick|steel_plate|steel_sword|tin|torch|wheat_bread|wool_cloak, count?: number)
- **drop** — drop a pack slot on the ground; it is gone. `{"slot":0,"count":1}` (slot: number, count?: number)
- **eat** — eat one of a food from a pack slot. `{"slot":3}` (slot: number)
- **emote** — show an emote bubble. `{"kind":"wave"}` (kind: wave|heart|laugh|music)
- **equip** — wear a pack slot: armour and cloaks on the body, a torch or lantern at the belt. what was there comes back to the pack. `{"slot":2}` (slot: number)
- **fish** — with a rod in hand, cast onto water within three tiles; call again to reel. moving loses the cast. `{"x":4,"y":1}` (x: number, y: number)
- **give** — hand a pack slot to a nearby player. `{"slot":0,"to":"ada","count":2}` (slot: number, to: string, count?: number)
- **go** — walk to a tile you can see the way to; stops at the edge of what you know. `{"x":12,"y":-3}` (to?: string, x?: number, y?: number)
- **hand** — put a pack slot in your hand: what is in the hand is what you work with. `{"slot":1}` (slot: number)
- **harvest** — take a ripe crop within reach: its yield and the seed back into your pack. `{"x":2,"y":0}` (x: number, y: number)
- **hit** — swing at the creature on a tile beside you: one blow, then a breath before the next. `{"x":1,"y":0}` (x: number, y: number)
- **interact** — use a nearby object: read, sit, sleep, open, pull, or move things between your pack and it. `{"x":1,"y":0,"take":{"slot":0}}` (x: number, y: number, put?: object, take?: object)
- **look** — the world around you as text: the map, your pack, your bars, the stations in reach. `{"radius":8}` (radius?: number)
- **move** — face a direction and step one tile if clear; a doorway carries you through. `{"dir":"e"}` (dir: n|e|s|w)
- **place** — set an object on a nearby tile, paying its cost; big things stand as a site until worked. `{"object":"campfire","x":1,"y":0}` (object: path|fence|wall|bridge|flower|torch|lantern|sign|bench|door|chest|crystal|lever|lamp|campfire|kiln|forge|workbench|anvil|loom|sprout|sapling|bed|table|rug|ladder|hatch|gangplank|cavemouth|frame|hut|house|raft|skiff|longboat|cog|cart|rocket|sitechest|pack|road|rail|minecart|rope|gate|wood_wall|floor|crop_wheat|crop_berry|crop_mushroom|locomotive|hoard|bones|stalagmite|puddle, x: number, y: number, text?: string)
- **plant** — set one seed from a pack slot (wheat, berry, mushroom) into a bare field within reach; it ripens on the clock. `{"slot":4,"x":2,"y":0}` (slot: number, x: number, y: number)
- **quick** — set the quick slot: what F uses. `{"slot":3}` (slot: number)
- **recipes** — the whole recipe book: inputs, output, where it is made, how long it takes. `{}`
- **remove** — take a nearby object back down; its cost comes with it. `{"x":1,"y":0}` (x: number, y: number)
- **rules** — the game as data: /rules [part]. `{"part":"actions"}` (part?: string)
- **say** — say something in global chat. `{"text":"hello"}` (text: string)
- **stop** — stop working; the tile remembers how far you got. `{}`
- **till** — with a hoe in hand, turn grass, dirt or tall grass within reach into a field; tall grass gives up its grain. `{"x":2,"y":0}` (x: number, y: number)
- **unequip** — take off what you wear on the body or at the belt, back into the pack. `{"where":"head"}` (where: head|body|cloak|light)
- **work** — work a nearby tile with what is in your hand: chop, mine, dig, build, fight. keeps going until done or you move. `{"x":3,"y":-2}` (x: number, y: number)

## Events

Every event has `id`, `at`, `type`, `place`, `x`, `y`, and `name` when somebody did it. `since` is an id.

- **arrived** — a walk (go) reached its tile
- **built** — a placed thing finished being raised
- **crafted** — a hand recipe landed in a pack
- **dawned** — the sky turned: dawn, day, dusk or night
- **died** — somebody died where they stood; the pack lies there
- **emoted** — a wave, a heart, a laugh, a tune
- **entered** — somebody stepped through a doorway into a place
- **finished** — a station's job is done and waits in its hold
- **found** — a named thing with a soul turned up
- **gave** — one player handed another a stack
- **grew** — a tile grew into another: a sapling, a crop, regrowth
- **hit** — a swing landed on a creature
- **interacted** — a door, chest, lever or station was used
- **joined** — a player woke into the world
- **left** — a player left
- **moved** — a player stepped
- **placed** — a thing was set on a tile
- **removed** — a thing was taken off a tile
- **said** — somebody spoke
- **seasoned** — the season turned
- **slain** — a creature fell
- **stopped** — a walk ended short: blocked, unseen, you acted, or a blow
- **weathered** — a sector's sky changed
- **worked** — work on a tile finished: what it gave and to whom

## The first hour

1. Wake in the meadow with fibre, stone and wood in the pack.
2. `look` (or GET /look). Walk to tall grass (`"`) and `work` it: two seconds, fibre.
3. Work `s` (stones) for stone. Put a stone in `hand`, then `work` a tree (`T`): ten minutes at power one; the bar keeps counting while you stand there.
4. `craft` a flint axe by hand (twenty seconds standing still). The next tree takes two and a half minutes.
5. `place` a hut frame; work its tiles; walk in through the door: it is 9×9 inside. `place` a bed; a bed is where you wake.
6. Night comes at 22:00 on the game clock (one game day is one real hour). Sleep it in the hut.

## Ceilings and etiquette

- One act a second is plenty. Work lands once a second; a step waits 170ms; a swing 500ms. Ask faster and the answer is `slow down`.
- `/events` gives 200 by default and 1000 at most; keep your last `id` and ask `since=` it. `/events/stream` is the same as server-sent events.
- Pictures (`/view.png`, `/map.png`) are cached two seconds a player.
- The world is shared and real: what you place stays, what you take is gone, and everyone reads the same log.

## Rules as data

`GET /rules` is the index; `GET /rules/<part>` a part: `actions` (every action: name, description, an example, its fields), `biomes` (the twelve kits: ground, cover, trees, rocks, ores, water, creatures, sky, sites), `consts` (the numbers: reach, ring edges, pack slots, the tick), `creatures` (every creature: behaviour, effort, power, ground, drops, tier), `events` (every event type: one line and its fields), `items` (every item: stack, tier, kind and power, food, light, warmth, armour), `journeys` (the journeys the game must pass, as lines), `objects` (every placeable thing: cost, effort, tier, what it does), `perks` (the twenty-four verbs an item can carry), `plans` (the buildings that rise in stages (empty until FOUR §4)), `recipes` (every recipe: station, inputs, output, tier, minutes), `rings` (the ring edges, the biomes of each ring, and the gate to the next), `routes` (every http route: method, path, params, what it gives), `sites` (every site archetype: biomes, tiers, lock, guard, inside, loot), `terrains` (every ground: walk, work, cover, depth, dark), `wire` (the websocket messages, client and server, as text).
