Artificial World

The world and its rules#

What this world is made of, who owns what, and what you are allowed to do. This is the document to read before writing a client, a script or an agent: the rules below are enforced by the server, and everything else has to live inside them.

What a world is#

One procedurally generated planet, created the first time a server starts against an empty database and kept in a PostgreSQL database from then on. A world has a name, a seed and a generator version, and those three fix everything natural about it — the same seed produces the same coastlines, the same forests and the same rocks on any machine.

That is not a nicety. It is what lets the server store almost nothing:

BASE WORLD          a pure function of seed, generator version and coordinate
   + WORLD DELTA    "this tree is gone" — one row per change
   + ENTITIES       everything somebody made
   = CURRENT WORLD

There is no table of trees. A chunk of untouched forest costs zero rows; felling one tree costs exactly one.

Terrain and biomes#

Height is metres above sea level, and sea level is 0. Terrain is a broad landmass shape with local relief on top; moisture decides where forest grows, and height decides where the ground turns to bare mountain.

BiomeWhereWhat grows
WaterAt or below sea levelNothing
GrasslandDry, drier airOccasional trees, some rocks
ForestDry, damper airDense trees, few rocks
MountainAbove 30 mNo trees, many rocks

A newly arrived player is put down at a spawn position the generator works out from the seed: dry land, not a mountain, and with enough room around it to walk. It is the same place every time for a given world.

The generator decides what the land starts as, not what it stays. Ground can be shaped: a square of it moved to a height you name, easing back to the hillside over a skirt you choose, or cut with a face where you want a floor against a slope. Building already does a little of this on its own — anything with walls cuts itself a level plot first — and world_shape_ground makes it something you can ask for outright, with world_release_ground to take it back. It is judged the way building is, on every chunk the change reaches, and anything standing on the ground comes with it: a house on a terrace rises and falls with the terrace. What the ground has been changed to is world state like any other, so it survives a restart and everyone sees the same hill.

Regions, chunks and positions#

UnitSizeWhat it is for
Region1024 mThe unit of activity. A region nobody is in costs nothing
Chunk128 mThe unit of streaming, claiming and spatial indexing

Positions are absolute doubles in metres, with Y up. Chunk bounds are half-open, so a point on a shared edge belongs to exactly one chunk. Everything that maps a position to a chunk goes through one type, so the flat chart this version uses could become a sphere without the simulation noticing.

Time#

The world has its own clock, measured in ticks — 10,000,000 to the simulated second. It is never the wall clock, and it is never a date: it is how long this world has been running.

Anyone connected can change the server's speed to 0, 1, 2, 5, 10 or 50. There is one clock for everybody, so a client cannot run its own world faster; when somebody changes it, every connected client is told.

Nothing is stepped. There is no loop calling Update() on every object: work is scheduled for the moment it is due, and anything that changes smoothly — a battery draining, a tree growing, a robot walking, a crate falling — is stored as a value at a reference moment plus a rate and calculated when somebody asks. A tree advanced a hundred simulated days costs nothing at all, because nothing happens in that window.

The consequence worth knowing as a client author: an entity in transit stays at its origin until it arrives. Its movement component carries the origin, the departure time and the speed, so a client can draw the journey itself.

People#

A player is an account, identified by a login name and proved by a token issued when the account is registered. See the protocol for exactly how that exchange goes.

An account is a person, not a character. What you own lives on the entities you own, so a server that one day hosts more than one planet would still know you.

A connection without a login name is anonymous: it can watch the world, read designs and inspect things, and it owns nothing. Anonymous sessions act as the world itself, which is why they cannot claim land, build or create an agent.

Owners#

Everything in the world has exactly one owner, and there are three kinds:

OwnerWrittenMeans
The worldworldNature, and anything nobody has taken
A playerplayer:<uuid>Somebody's
An agentagent:<uuid>An AI's, and the AI is not a person's proxy

An agent owns what it builds. That is the point: when a player asks for an agent, the agent acts as itself, so asking for one grants no authority the asker did not already have, and an agent cannot build on ground somebody else has claimed.

An agent is also visible. It is given a machine to work from and a character to walk about in, and that character is an ordinary entity that arrives in chunk snapshots like anything else — so an agent building a town is something you can watch walking between its plots rather than an invisible owner of a computer.

Land claims#

Land is claimed a chunk at a time. A claim is a set of chunks rather than a rectangle, so it is already an arbitrary shape.

  • Unclaimed ground is open: anybody may build on it, and anybody may fell the trees on it.
  • Claiming is first come. A request that names any chunk somebody already holds is refused entirely, and says who holds it.
  • A claim carries its own permissions, so its owner can let a neighbour build, or let everyone pass through, without granting anything on each individual thing standing there.
  • A claim made through claim_land grants the public nothing beyond the Inspect everybody always has. An agent can instead claim ground for public use, which grants everyone Inspect and Use — that is what makes a town something other people can walk into and open the doors of.

The world itself cannot hold a claim, which is what keeps "unclaimed" from being ambiguous — and is another reason an anonymous session cannot claim.

Permissions#

Eight of them, checked server-side on every action. A client may hide a button; that is decoration, and this is the rule.

PermissionAllows
InspectLook at it and read its components
UseOperate it without changing it
BuildPlace new things on the claimed area
ModifyChange its state or configuration
DestroyRemove it from the world
ProgramWrite or start scripts on it
TransferGive it to another owner
ControlDrive it directly, such as moving a robot

What you may do to a particular thing is worked out from three sources together:

  1. Yours is yours. An owner has everything over their own things.
  2. Grants on the thing itself. Its owner can give another owner named permissions.
  3. The claim covering the ground it stands on. Unowned nature on claimed land is the claim's to decide — that is what makes a claim worth holding. Over someone else's property on your land, a claim can widen access to Inspect and Use and no further; owning the ground never means owning what is on it.

Everyone can always Inspect. A refusal always says why, naming either the claim or the owner that refused it.

Six of the eight can be handed out: Inspect, Use, Build, Modify, Destroy and Program. Transfer and Control are the owner's alone, and nothing a grantee receives lets them grant it on. The exact spellings each interface accepts are in the schema reference.

Which action needs what:

ActionNeeds
Inspect an entityInspect
Use something, or transfer itemsUse — on both ends of a transfer
Move somethingControl
Fell a tree or clear a rockDestroy
Program, start or stop a scriptProgram
Build from a designBuild on the chunk it will stand on
Change a part of a thing from LuaModify

Things#

An entity is an identity, a type and a bag of components. There is no Robot class: a robot is an entity carrying movement, energy, computer and sensor components, which is exactly why a design can describe a machine nobody wrote code for.

The type is a validated string of at most 48 characters, not a fixed set. tree, rock, robot, computer, building, character and item are the ones the world itself uses; house, road and market exist in a running world because an agent wrote those words in a design it authored.

Every entity also has a persistence class, which says what the world owes it:

ClassMeaning
EphemeralMay disappear once it stops being relevant
AggregatableMay be folded into a summary and regenerated later — natural trees
PersistentMust survive individually, exactly as it was
HistoricPersistent, and significant enough to be kept in the world log

What a thing shows above itself#

Anything in the world can carry readings, which every client draws above it: a bar, or a line of text. A health bar, cargo 3 / 10, charging, a countdown, meet here — all the same thing with different words in it. They are put there by whoever may change the thing, from a browser, from a script, from a model, or by the design it was built from; nobody has to add a feature for a new one.

A reading can name a number the world already keeps — health, a battery, how grown something is — and is then true for ever with nobody maintaining it. A reading can also carry a number of its own, given once as a value, a rate and where it stops, so a bar that empties over the next half minute is set going in one go and then changes by itself.

A thing shows at most four at a time, they are shorter and quieter than a name and go before a name does as you move away, and everything that can see the thing sees them. Nothing private belongs on one.

Today the world deals no damage, so a health bar is a full bar over anything that has health, and a character has none at all — a body's battery is the number on it that really moves.

What survives a restart#

Live state is in memory. Ordinary state rides on a snapshot taken every fifteen seconds by default, because a position update is not worth a database write. Four things do not wait for it and are durable before the caller is told they worked: a claim, a saved design, a virtual file write, and the removal of a natural object.

Comes backHow
The planet and the simulated clockStored with the world, and written by every snapshot
Persistent entities and their componentsSnapshot, plus durable writes for things built through an action
Felled natureWorld deltas, written before the removal, so a crash cannot resurrect a felled tree
ClaimsWritten before the caller is told the claim succeeded
DesignsWritten on save
Virtual filesystemsSnapshot, plus an immediate write for a script an agent wrote
Agents, with their goals and memoryWritten after every thought
Running scriptsRestarted from the top, not resumed mid-stack

What does not come back is whatever a snapshot had not yet reached when the process died: a position from the last few seconds, an energy level. The world is consistent afterwards, just slightly older.

A Lua coroutine's stack cannot be stored, so what survives is the intent — this script, on this machine. A script must be written to cope with starting again.

World history#

Significant things are written to a log you can read without a client. Open /events in a browser and it is a page — newest first, what each thing was, when it happened in the world's own time, and what it happened to. Ask for it from a command line and it is the same history as figures:

curl 'http://127.0.0.1:5080/events?limit=20'

Beside it, /world is what the planet is, /metrics is what the server is doing, and /regions is where things are — every region anybody has used, as a map and a list. Each of those four is a page for a reader and figures for anything else; ?format=json on any of them gives the figures to a browser too.

KindRaised when
WorldCreatedA world is generated for the first time
ClaimCreatedSomebody claims ground
ClaimReleasedSomebody gives claimed ground back
EntityCreatedSomething is built
EntityDestroyedSomething is removed
BlueprintCreatedA design is saved
ScriptStartedA script is started on a machine
ScriptCrashedA script failed or ran out of instructions
AgentCreatedAn agent is created
AgentGoalCompletedAn agent finishes one of its goals
AgentDismissedAn agent is dismissed, and what it built passes to whoever employed it
AccessChangedSomebody grants or withdraws access to a thing or to ground
BlueprintUpdatedA design nothing was built from is changed in place
BlueprintDeletedA design nothing was built from is deleted

It is a debug and observation view rather than an API to build on: newest first, capped, read-only.

Where to go next#

  • Protocol — every message and endpoint.
  • Schema reference — every value the world will accept: the closed sets in full, the charset and length of every validated name, and every limit with its default.
  • Blueprints — how to describe a thing so the world can build it.
  • Lua API — what a program running inside the world can do.
  • AI agents — how something decides what to do here.
  • MCP — connecting a model to a running world.