> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eucaengine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The world as a table

> Euca's world is a flat table: each row is an entity, each column a typed component. An agent reads and edits it as plain data — no opaque object graph, no GUI required.

In Euca the entire game world is a **flat table**. Each row is an **entity** — a stable id.
Each column is a **component** — a group of typed fields. An entity "has" a component when
its row has a value in that column. There is no object graph to walk and no scene tree to
reverse-engineer: an agent reads the world by reading the table, and changes the world by
writing to it.

This is the **Entity–Component–System (ECS)** model. Entities are ids, components are the
data, and **systems** are the logic that runs over the table each tick — physics, combat,
and [rules](/concepts/rules-as-data).

```mermaid theme={null}
flowchart LR
    Read["observe<br/>read the table"] --> Write["spawn · patch · add rule<br/>write the table"]
    Write --> Step["step<br/>advance N ticks"]
    Step --> Run["systems run over every row<br/>physics · rules · combat"]
    Run --> Read
```

## Reading the table

`POST /observe` returns the whole table as JSON: a tick, an entity count, and one object
per entity carrying its components.

```bash theme={null}
# Build a tiny world: reset, spawn a Kinematic mover on team 1 and a stationary
# target on team 2, step 5 ticks, then read the table back.
curl -s -X POST http://localhost:3917/observe
```

```json theme={null}
{
  "tick": 5,
  "entity_count": 2,
  "entities": [
    {
      "id": 0, "generation": 1,
      "transform": { "position": [0.083333336, 1.0, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "scale": [1.0, 1.0, 1.0] },
      "velocity": { "linear": [1.0, 0.0, 0.0], "angular": [0.0, 0.0, 0.0] },
      "physics_body": "Kinematic",
      "health": [100.0, 100.0],
      "team": 1
    },
    {
      "id": 1, "generation": 0,
      "transform": { "position": [5.0, 1.0, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "scale": [1.0, 1.0, 1.0] },
      "health": [60.0, 60.0],
      "team": 2
    }
  ]
}
```

Read literally as a table, that is two rows and a handful of typed columns:

| entity      | `transform.position`      | `velocity.linear` | `physics_body` | `health` `[cur,max]` | `team` |
| ----------- | ------------------------- | ----------------- | -------------- | -------------------- | ------ |
| `0` (gen 1) | `[0.083333336, 1.0, 0.0]` | `[1.0, 0.0, 0.0]` | `Kinematic`    | `[100, 100]`         | `1`    |
| `1` (gen 0) | `[5.0, 1.0, 0.0]`         | —                 | —              | `[60, 60]`           | `2`    |

Entity 0 has a `velocity` and a `physics_body`, so a system moved it along +x; entity 1 has
neither, so it stayed put. Nothing about the world is hidden behind accessors — what you read
is the state.

## Entities are generational ids

An entity id has two parts: an **index** and a **generation**. When an entity is despawned its
index can be reused, but the generation bumps — so a stale reference to the old occupant is
detected rather than silently pointing at a new one. Thread the `id` *and* `generation`
returned by `/spawn` through later calls.

<Note>
  The `/observe` view is a **flattened, readable projection** of the underlying components —
  for example `health` is reported as `[current, max]`. It is built from explicit typed reads,
  not reflection: the agent gets plain data, not an opaque handle.
</Note>

## Editing the table

Because the world is data, every change is a plain write — no editor or scripting host *required*
(though the visual editor can make the same edits by hand):

<CardGroup cols={2}>
  <Card title="Add a row" icon="plus">
    `POST /spawn` creates an entity with the components you give it.
  </Card>

  <Card title="Edit a cell" icon="pen">
    `POST /entities/{id}/components` adds or updates components on an existing entity.
  </Card>

  <Card title="Remove a row" icon="trash">
    `POST /despawn` removes an entity by id + generation.
  </Card>

  <Card title="Add logic" icon="gear">
    `POST /rule/create` adds a [rule](/concepts/rules-as-data) — logic is data too.
  </Card>
</CardGroup>

## The same table, forked and replayed

Because the world is a self-contained table of plain data, the engine can **copy it** to run
a [counterfactual](/concepts/forks), and **hash it** into a stable digest to verify a
[replay](/concepts/determinism) is exact. The canonical, fully-typed form of this table — used
by the [evaluation track](/evaluation/overview) as the answer key — sorts entities by id and
components by name so two runs can be compared byte for byte.

<Card title="Run the loop yourself" icon="rocket" href="/quickstart" horizontal>
  Build this table, step it, and fork it in the Quickstart.
</Card>
