Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .agents/skills/live-ffa-viewer-testing/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: live-ffa-viewer-testing
description: Boot a live CTF/FFA (battle-royale) server with bots and inspect the board visually in the browser viewer — for testing rendering/presentation changes (map art, palettes, HUD) end-to-end instead of only via unit tests.
description: Boot a live Battle Royale (FFA) or legacy CTF server with bots and inspect the board visually in the browser viewer — for testing rendering/presentation changes (map art, palettes, HUD) end-to-end instead of only via unit tests.
---

# Live FFA/CTF board testing in the browser viewer
# Live Battle Royale / CTF board testing in the browser viewer

## Build

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ players/modulabot/test/parity
/data/rig_real/*.png

# Local coworld package build output. CI builds the real package to build/ from
# the tracked coworld_manifest_paintbot.json; dist/ is a local convenience artifact.
# the tracked coworld_manifest_battleroyale.json; dist/ is a local convenience artifact.
/dist/
trench-demo.bitreplay
pool-preview/
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Agent operating guide — coworld-ctf
# Agent operating guide — coworld-battle-royale

Orientation for coding agents (Claude Code, Codex, etc.) working in this
repo. Gameplay rules live in [docs/RULES.md](docs/RULES.md); this file
Expand Down
69 changes: 52 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,66 @@
# Coworld CTF — AI Capture-the-Flag Shooter

Coworld CTF is a two-team capture-the-flag shooter for the Coworld platform. Two
teams (Red and Blue) start on opposite edges of a symmetric arena, each with its
own flag on a home pedestal. Players move, take cover behind obstacles, and
shoot. Steal the enemy flag and carry it home — or wipe the enemy team — to win.
# Coworld Battle Royale — AI Free-for-All Shooter

Coworld Battle Royale is a free-for-all shooter for the Coworld platform. The
shipped config (`config.br.json`, `mode: "ffa"`) seats **12 players**
(`numPlayers: 12`); the Coworld manifest
(`coworld_manifest_battleroyale.json`) ships the `br-12` and `br-16` variants.
Every seat is its own team and receives its own identity color, and each player
has a **single life**. Players spawn unarmed on an evenly spaced ring and fight
with their fists until they pick up a weapon — gun pickups form a permanent
upgrade ladder of tiers. A **shrinking ring** (`ringShrinkSec` 150 s, closing
to a floor of 3% of the arena) forces the survivors together, and an armed
victim drops their gun as a one-use pickup at the death site
(`dropWeaponOnDeath`, armed as of GV46). **Placements** decide the results.
Vision is fog-of-war: you observe the full map, but enemies only appear inside
your forward vision cone (walls block it) or your small omnidirectional bubble.

It is a fork of [Crewrift](https://github.com/Metta-AI/coworld-crewrift). It keeps
Crewrift's continuous 2D movement, line-of-sight, Sprite v1 protocol, websocket
server, and replay infrastructure, and replaces the social-deduction game layer
(roles, tasks, voting) with teams, guns, flags, and fog-of-war vision.
(roles, tasks, voting) with teams, guns, and fog-of-war vision.

The **full, authoritative ruleset lives in [`docs/RULES.md`](docs/RULES.md)**. The
summary below is just an orientation.

This repo publishes one `battleroyale` Coworld manifest with the `br-12` and
`br-16` variants. The battle-royale league is a free-for-all: every seat is its
own team and receives its own identity color. CTF compatibility remains in the
engine and tests, but is not the artifact published by this repository.

If docs, commands, runtime behavior, logs, or replays disagree while you are
building or submitting a CTF policy, preserve the evidence and file a GitHub issue
building or submitting a policy, preserve the evidence and file a GitHub issue
instead of silently working around it. Include the command, league/Coworld ids,
logs or replay links, and the smallest repro.

## Rules at a glance
## Battle Royale at a glance

- **Free-for-all, single life.** Every seat is its own team with its own
identity color. There is no respawn — death ends your episode, and
**placements** decide the result.
- **Unarmed start.** Everyone spawns on an evenly spaced ring with no gun; the
fallback attack is a **fist** — 70 px reach, 2 damage, twice the normal fire
cooldown, hitting the nearest living player inside the ±67.5° aim cone. A
punch always connects inside reach, cone, and line of sight, and is only
available while you hold no gun or spray can.
- **Weapon tiers are a permanent upgrade ladder.** Touching a higher-tier
pickup raises your tier for the rest of the episode: **low** (2 damage,
700 px reach), **mid** (3 damage, 1050 px), **heavy** (5 damage, 1050 px at
a faster cooldown). With the shipped config, no weapon has ammo, durability,
or a magazine (`finiteAmmo` is a dormant knob) — the only way to lose a gun
is to die.
- **Drop on death (GV46).** With `dropWeaponOnDeath` on — it is armed in the
shipped configs — a non-unarmed victim leaves their gun as a one-use pickup
at the death site, consumable only by a strictly lower-tier player. Grenades
and spray cans drop nothing.
- **The ring shrinks.** The safe zone closes over the match
(`ringShrinkSec` 150 s in `config.br.json`) down to a final floor of 3% of
the arena (`ringFloorAreaPct`).
- **Vision is fog-of-war**, as in the legacy mode: the map is always visible,
but enemies only appear inside your forward vision cone or your small
omnidirectional bubble.

See [`docs/RULES.md`](docs/RULES.md) for exact mechanics and tuning defaults.

## Legacy CTF mode — rules at a glance

The bullets below describe the two-team capture-the-heart mode that remains in
the engine and tests (`config.json`, `mode: "ctf"`); it is not the Coworld this
repo publishes. "Flag" below is the heart: the mode reskinned flags as hearts.

- **8 vs 8.** Red spawns on the **left** edge, Blue on the **right**. Each team's
flag sits on a pedestal inside its spawn pocket.
Expand Down Expand Up @@ -72,8 +107,8 @@ See [`docs/RULES.md`](docs/RULES.md) for exact mechanics and tuning defaults.

## Campaign mode (territory leagues)

Ctf and Paintbot also run **campaign leagues** (e.g. "CTF Campaign", "Paintbot
Campaign"): territory wars on a cell grid where an LLM strategist issues
The Coworld platform also runs **campaign leagues** (e.g. "CTF Campaign",
"Paintbot Campaign" — those are platform league names): territory wars on a cell grid where an LLM strategist issues
invasion orders for your player each round, guided by a standing **strategy
prompt** you control. Each contested cell is settled by the policies playing a
normal match on the cell's variant (which sets the battle mode — 1v1 duel,
Expand Down Expand Up @@ -161,7 +196,7 @@ docker run --rm -d \

## Policy starting points

CTF policies speak the shared Bitworld Sprite v1 protocol:
Policies speak the shared Bitworld Sprite v1 protocol:
<https://github.com/Metta-AI/bitworld/blob/master/docs/sprite_v1.md>

The runner starts every policy with a `COWORLD_PLAYER_WS_URL` environment
Expand Down
2 changes: 1 addition & 1 deletion REPLAY_BRIEF.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Ranked by drama:
## Tempo map

24 ticks/s (`ReplayFps`). `maxTicks 10000` ≈ 6:56 of game time (config.json:13 — but certification runs
`maxTicks 300` ≈ 12.5s in `coworld_manifest_paintbot.json` certification, so the clock derives from `sim.config.maxTicks`,
`maxTicks 300` ≈ 12.5s in `coworld_manifest_battleroyale.json` certification, so the clock derives from `sim.config.maxTicks`,
never a hardcode). Engine playback speeds `[1,2,3,4,8,16]` (replays.nim:40). Dead time = both flags
home, no contact — where speed collapses; contact windows and any beat hold their read time
(DEPTH_TARGET tempo levers).
Expand Down
2 changes: 1 addition & 1 deletion caos-tools/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ narrow)
# COMPILED in. Verified as the only top-level files any .nim actually reads
# (Dockerfile and AGENTS.md appear in comments only).
narrow_tree /cas/ws src tests tools players client data \
config.json coworld_manifest_paintbot.json
config.json coworld_manifest_battleroyale.json

deps=$(caos curry --base:@=/cas/args/base \
"--worker1:@=/cas/args/in/caos-tools/lib/deps.sh") || fail "currying deps"
Expand Down
4 changes: 2 additions & 2 deletions docs/MAPKIT.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# mapkit — LLM-authored, interesting-but-fair CTF maps
# mapkit — LLM-authored, interesting-but-fair maps

`tools/mapkit.nim` is a CLI for generating and hand-editing CTF maps in the
`tools/mapkit.nim` is a CLI for generating and hand-editing maps in the
native `mapSpec` format. It is a peer to the [map editor](designs/map-editor.md)
service: it never reimplements geometry, it drives the same sim procs
(`generateMapAttempt`, `mapSpecJson`/`mapFromSpecJson`, `validateGeneratedMap`,
Expand Down
6 changes: 3 additions & 3 deletions docs/PROTOCOL.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# CTF wire protocol — Sprite v1 plus CTF extensions
# Coworld Battle Royale wire protocol — Sprite v1 plus game extensions

Both the player endpoints (`/player`, POV observation streams) and the
global/spectator endpoint speak
[Sprite v1](https://github.com/Metta-AI/bitworld/blob/master/docs/sprite_v1.md).
This document lists everything CTF adds or changes relative to that base
This document lists everything the game adds or changes relative to that base
document; anything not mentioned here matches Sprite v1 exactly. Game
semantics — mechanics, sprite labels, tuning defaults — live in
[`RULES.md`](RULES.md).

## Player input: bit 7 is the C button

Sprite v1 reserves player-input bit `7` ("must be sent as 0"). CTF assigns it:
Sprite v1 reserves player-input bit `7` ("must be sent as 0"). The game assigns it:

| Bit | Value | Meaning |
| ---: | ---: | --- |
Expand Down
29 changes: 19 additions & 10 deletions docs/RULES.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Coworld CTF — Game Rules

Coworld CTF is a two-team capture-the-heart shooter for the Coworld platform. Two
teams start on opposite edges of a symmetric arena, each with its own heart on a
home pedestal. Players move, take cover behind obstacles, and shoot. Steal the
enemy heart and carry it home — or eliminate the enemy team — to win. Vision is
# Coworld Battle Royale — Game Rules

Coworld Battle Royale is a free-for-all shooter for the Coworld platform
(`config.br.json`, `mode: "ffa"`, 12 seats; the manifest ships the `br-12` and
`br-16` variants). Every seat is its own team and receives its own identity
color. Each player has a single life, spawns unarmed on an evenly spaced ring,
and fights with fists until they pick up a weapon tier. A shrinking ring
(`ringShrinkSec` 150 s, to a 3%-of-the-arena floor) forces the survivors
together, an armed victim drops a one-use gun at the death site
(`dropWeaponOnDeath`, GV46), and placements decide the results. Vision is
fog-of-war: the map is always visible, but enemies only appear inside your
forward vision cone or your small omnidirectional bubble.
forward vision cone or your small omnidirectional bubble. The engine also
retains the original two-team capture-the-heart (CTF) mode; sections below
that describe teams, hearts, and captures apply to that mode, and
Battle-Royale-specific rules are called out where they differ.

It is a fork of [Crewrift](https://github.com/Metta-AI/coworld-crewrift): it keeps
Crewrift's continuous 2D movement, line-of-sight, sprite protocol, server, and
Expand All @@ -16,6 +23,8 @@ tasks, voting) with teams, guns, hearts, and fog-of-war vision.

## Overview

The bullets below describe the legacy CTF mode.

- **16 players, 8 vs 8.** Red team spawns along the **left edge**, Blue along the
**right edge**.
- **Two team hearts**, one on each team's **home pedestal** inside its spawn
Expand Down Expand Up @@ -1276,13 +1285,13 @@ This section is a build plan, not player-facing rules.
image with walk/wall layers. Red/Blue spawn strips on the left/right edges,
heart pedestal at center, obstacles mirrored across the vertical axis, home-edge
capture zones at the leftmost/rightmost columns.
- New team-based `config.json` and `coworld_manifest_paintbot.json` (slots carry `team`
- New team-based `config.json` and `coworld_manifest_battleroyale.json` (slots carry `team`
instead of `role`; results schema reports team/kills/deaths/captures).
- A **baseline bot** (Crewrift's `notsus` equivalent) speaking Sprite v1.
- A **CTF grader** scoring episodes from wins.

**Resolved:** CTF needed team-based seating and win/loss ranking rather than
Crewrift's social-deduction scheme. This is no longer a per-game concern — both
the Ctf and Paintbot leagues run on the platform ladder service
Crewrift's social-deduction scheme. This is no longer a per-game concern —
the Battle Royale league runs on the platform ladder service
(`commissioner_key=platform`), which owns seating and ranking. This repo ships
the game and baseline player only; it declares no commissioner runnable.
2 changes: 1 addition & 1 deletion docs/designs/expand-replay-reporter.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ document gives the reasoning behind each.
`report_output` (an empty `[]` when there are no events); a missing /
unfetchable / undecodable replay, or a hash-validation failure, →
`report_failed`. (§5.4)
7. **Manifest: defer + document.** Leave `coworld_manifest_paintbot.json` untouched;
7. **Manifest: defer + document.** Leave `coworld_manifest_battleroyale.json` untouched;
document the intended `reporter[]` entry in the reporter README and wire it
when the platform runtime and the new manifest schema land here. (§5.5)
8. **Testing: unit tests + mock WS client.** The platform reporter runtime is
Expand Down
2 changes: 1 addition & 1 deletion docs/designs/map-editor.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Map Editor Design

A visual editor for CTF / Paintbot maps that reads and writes the existing
A visual editor for Battle Royale / CTF maps that reads and writes the existing
`mapSpec` JSON format, with the Nim sim as the single source of truth for all
geometry, derivation, and validation.

Expand Down
8 changes: 4 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
description = "Coworld CTF — Nim capture-the-flag game server, bots, and tooling";
description = "Coworld Battle Royale — Nim free-for-all shooter game server, bots, and tooling";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
Expand Down Expand Up @@ -62,7 +62,7 @@
'';

meta = {
description = "Nim package manager used by coworld-ctf (nimby.lock)";
description = "Nim package manager used by coworld-battle-royale (nimby.lock)";
homepage = "https://github.com/treeform/nimby";
license = pkgs.lib.licenses.mit;
mainProgram = "nimby";
Expand Down Expand Up @@ -135,7 +135,7 @@
in
{
default = pkgs.mkShell {
name = "coworld-ctf";
name = "coworld-battle-royale";

packages = [
# Nim toolchain. nixpkgs-unstable ships 2.2.10, the version the
Expand Down Expand Up @@ -174,7 +174,7 @@
# real interactive terminal.
shellHook = ''
if [ -t 1 ]; then
echo "coworld-ctf dev shell — nim $(nim --version | head -1 | cut -d' ' -f4), node $(node --version), python $(python3 --version | cut -d' ' -f2)"
echo "coworld-battle-royale dev shell — nim $(nim --version | head -1 | cut -d' ' -f4), node $(node --version), python $(python3 --version | cut -d' ' -f2)"
if [ ! -f nim.cfg ]; then
echo
echo " nim.cfg is missing — sync the pinned Nim deps first:"
Expand Down
2 changes: 1 addition & 1 deletion players/baseline/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# baseline — Coworld CTF bot (8v8, fog-of-war)
# baseline — Coworld Battle Royale bot (8v8/FFA, fog-of-war)

A capture-the-flag reference bot that speaks the Bitworld Sprite v1 protocol.
Its WebSocket disables Nagle buffering so separate input and chat messages
Expand Down
6 changes: 5 additions & 1 deletion tools/ladder/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Ladder assessment tools

Judge a submitted policy on the LIVE Elo ladder. Run everything with the
Judge a submitted policy on the LIVE Elo ladder. **This tooling is
CTF-league-only** (`ctfapi.py` hardcodes the CTF league id, and the named
tenures/rounds below are CTF league history); the Battle Royale league is a
separate league, so point these scripts at it only by passing its id
explicitly. Run everything with the
cogherence player's venv, which holds the working login:

```sh
Expand Down
Loading