How Petri works

Petri is Conway’s Game of Life on one shared dish, kept by a NEAR contract. Every live cell belongs to a colony. Colonies buy PETRI from the dish with NEAR, spend it to plant, and are fed PETRI for the cells that stay alive. Every hour 5% of the tide vault, which holds the NEAR players attached, goes back out, split by what each colony earned that hour; free play is paid the same way in credit. A colony can also fix a patch of its living cells as a specimen slide, an NFT the contract draws itself and, from 12 cells up, a licence: anyone may plant its pattern for less, paying its holder a royalty. This page is the whole rulebook, with the numbers read live from the contract; the long tables open on request.

  1. Buy in

    Pay NEAR to the agar and get PETRI back, at a price that rises as the agar empties. Past the storage it pays for, the NEAR goes to the tide vault, not to anyone running the dish.

  2. Plant cells that last

    Spend PETRI to plant a pattern; half is burned, half returns to the agar. Life decides what survives, and your living cells earn PETRI every 15 s, up to 8 paid cells per cell of stake.

  3. Collect at the tide

    Every 240 generations 5% of the vault is paid out in NEAR (as credit on free play), split by the PETRI each colony earned since the last tide. Claim it, or sell PETRI back to the agar.

cells, with edges that wrap
128 × 128
between generations
15 s
most living cells a colony is paid for, per cell of stake
× 8
the price of planting within 3 cells of a rival
× 3
PETRI to plant one cell right now
—
NEAR for one PETRI from the agar right now
—

A small world on a clock

The dish is 128 by 128 cells, 16,384 in all, and it has no walls. A new generation is due every 15 seconds, 5,760 times a day, counted from the block in which the contract was created.

Nothing stops at the edge. The right side touches the left and the top touches the bottom, so this glider and light spaceship leave one side of a 36 by 20 dish and come back on the other. The big dish works the same way.

Generation 0

The contract only moves when asked

A NEAR contract cannot run on a timer. Petri’s contract stores the board at the last generation someone advanced to. Every join, buy, sell, plant, claim, mint_slide and advance call first steps that board through the generations the clock says are due, up to 120 in one call, and stops early once the call has used 110 TGas (or its prepaid gas less 40) less what is still to be written, so no backlog can push a call past NEAR’s gas limit; it always steps at least one. A planting is refused if the dish is still behind after that. If nobody touches the dish for more than 480 generations, the next call skips the clock ahead to 120 behind instead of replaying the quiet stretch, and writes a Skip entry to the ledger.

A keeper pot pays for the steps

Each generation sets 2% of its feed aside in a keeper pot. Whoever’s call catches the dish up (advance, or a join, purchase, sale, planting, claim or slide mint) takes the whole pot, but only if that call ran at least one generation and the account can hold PETRI (a colony, or an account registered with storage_deposit) and is neither one of the house’s (a house strain or a keeper) nor a guest (a colony that has never attached NEAR): for those the pot keeps waiting. A call on a dish that is already current pays nothing. Whoever’s call runs an hourly tide also gets a small bounty, in NEAR, or as credit to a colony that has never attached NEAR (see the tides); a house colony or a keeper gets none, and it stays in the vault. The project’s keeper, petri-keeper.testnet, is listed in rules.keepers, so it takes neither the pot nor a bounty. On testnet it advances once the stored board is 20 generations behind, or when the pot holds more than 50 PETRI (which then waits for the next caller outside the house); on mainnet, only once someone outside the house plays, and only when the board is 400 generations behind, before the clock would skip. It also unwraps wNEAR that arrived with too little gas to unwrap. It has no powers anyone else lacks: any account may call advance.

Your browser runs ahead

The site downloads the stored board, loads it into petri-core, the same Rust crate the contract runs, compiled to WebAssembly, and steps it to the generation that is due. That is the dish you see. It also works out the feed every colony is owed since the stored board. The contract adds it to each colony’s unclaimed earnings the next time anyone advances the dish.

Due by the clock
—
Stored on chain
—
Your browser is ahead by
—
Next generation in
—

The dish page runs the contract’s own placement check, check_plant, on the board your browser holds before you sign, so it can show why a planting would be refused before you send it.

Life, with owners

Every generation each cell counts its eight neighbours, all at once, from the board as it was. The first two rules are Conway’s Life exactly. Ownership adds the other two.

  • Survive with two or three

    A live cell with two or three live neighbours stays alive and keeps its owner. Whose neighbours they are does not matter.

  • Otherwise die

    With fewer than two neighbours, or more than three, a live cell dies and its square is empty agar again.

  • Births join the majority

    An empty square with exactly three live neighbours comes alive. It joins the colony that owns at least two of those three parents.

  • Three owners, no birth

    If the three parents belong to three different colonies, the birth is contested and nothing grows there. This is the only place Petri differs from Life.

One owner. The corner square has three red parents, so a red cell is born and the L becomes a block, a still life.

Two owners. Two red parents and one green: the birth is red. The green cell survives and keeps its colour.

Three owners. Red, green and violet parents. The corner is contested, every cell keeps two neighbours, and the L never changes.

Generation 0Births contested this generation 0

One owner: plain Life

The same three gliders, all owned by one colony, so every birth happens. The crash leaves debris that is still active when the loop restarts at generation 72.

Generation 0Live cells 0

Three owners

Red, green and violet gliders. One birth, at generation 13, has three different parents and does not happen. That single missing cell changes the whole crash: the wreck burns out by generation 41.

Generation 0Red 0Green 0Violet 0Contested 0

These dishes run petri-core compiled to WebAssembly, the code the contract runs. The scenes were chosen by simulating them; nothing is drawn by hand. On the real dish the trios would be sieges, since each cell sits inside a rival’s three-cell buffer and would cost three times the price. The three gliders start outside each other’s buffers, so they would pay the normal price.

Planting new life

A colony grows by planting: naming up to 64 empty cells and paying for them in PETRI, with a little NEAR for storage. Any shape is allowed. The site’s stamps, from a block to a glider gun, are only a convenience; the contract sees a list of cells.

  • Up to 64 cells, once a generation

    One planting brings at most 64 cells to life (a glider gun is 36), and each colony plants at most once per generation, every 15 seconds.

  • Empty cells only

    Every target cell must be dead. You cannot plant over anyone’s cells, including your own.

  • Near a rival costs 3×

    If another colony has a live cell within 3 cells of any planted cell, counting diagonals and across the wrapped edges, the planting is a siege and costs 3 times the price. It is never refused for being close, so no colony can close the dish to newcomers by spreading cells everywhere. Your own cells do not count.

  • A slide’s pattern costs 25% less

    A specimen slide that captured at least 12 cells is a pattern licence (a smaller one is a keepsake). Plant exactly a slide’s cells, moved anywhere on the dish but not turned or flipped, and name the slide: the planting costs 25% less, for anyone. A planter that does not hold the slide also pays its holder 10% of that discounted cost in PETRI, or the agar, if the planter has never attached NEAR. The siege surcharge still applies in full, so a licence never makes a rival’s ground cheap.

  • A lab note, if you like

    Up to 140 characters and 280 bytes, stored on chain with the planting and shown in the dish’s log. Notes may not contain control, direction, invisible or tag characters, and colony names are plain ASCII letters, digits and a little punctuation, so nothing can hide in either.

×3×1

Green’s block and its 3-cell buffer. Red’s cell inside the hatched square is a siege and pays 3 times the price; the one just outside pays the normal price. The buffer is checked only when planting, so a glider sent from outside gets in for the normal price.

A cell costs what a cell earns in 480 generations

feed per cell = agar × 3 ÷ 1,000,000 × (1 − 2%) ÷ max(counted cells, 1,000)
price of a cell = max(feed per cell × 480, 0.5 PETRI)
cost = price of a cell × cells × (3 for a siege, else 1)
under a slide's licence: cost × (1 − 25%), plus 10% of that to the holder if you are not it

An average cell, left alone, earns back its price in 480 generations, about 2 hours. Counted cells are the living cells of fed colonies, each colony capped by its reach. The price counts at least 1,000 of them, and below that the agar releases only that fraction of its ration, so on a nearly empty dish a cell still earns exactly what its price assumes. The price never falls below 0.5 PETRI a cell, and falls as the agar shrinks and as more than 1,000 cells are counted. The contract computes it after the planting’s own catch-up, in millionths of a PETRI, rounding down at every step. Of every cost, 50% is burned and 50% goes back into the agar; a royalty is a transfer to the slide’s holder, neither burned nor returned. Planting first claims the colony’s waiting earnings, so they count towards the price.

A beehive, right now

Agar at your browser’s generation
—
This generation’s feed, 3 ppm of it, less the keeper’s 2%
—
Divided by — counted cells
—
Times 480
—
Six cells
—
The same six cells as a siege
—

Burned: —. Back to the agar: —.

Using the — counted cells your browser has at generation —.

The NEAR a planting carries

The player pays for what their planting stores: the ledger entry, its cells and its note. On top of that every planted cell carries a fee of 0.0001 NEAR. The contract measures the storage the planting actually used and keeps it; everything above that goes to the tide vault, or to the credit pool when it was paid in credit. A wallet attaches the NEAR; a guest spends it from the credit the site sponsored for it.

bring = (257 + 4 × cells + (note bytes + 64, if there is a note)
         + (26 + the holder's account length, under a slide's licence)
         + (125, if that holder has no PETRI registration)
         + (82, if no colony is playing at all)) bytes × 0.00001 NEAR
      + 0.0001 NEAR × cells

The plant_deposit(cells, note_bytes, slide) view returns that sum and the site sends it for you. It allows for the colony’s row in the table of playing colonies, which a colony’s first planting since it last played creates (the table holds at most 10,000 rows; while it is full and none can leave, a colony without a row waits for the next tide); storage not used goes to the vault or the credit pool with the fee. A royalty to a holder with no PETRI registration registers it at the planter’s expense. A refused planting changes nothing: attached NEAR comes back and credit is not spent.

What plant_deposit returns now 5 plantings
PlantingBringOf which fee
A block, no note—0.0004
A beehive, no note—0.0006
A beehive with a 60-byte note—0.0006
A glider gun, no note—0.0036
64 cells with a full 280-byte note—0.0064

Read from the contract when this page loaded.

One cell at different crowding today’s agar and half of it
Counted cellsToday’s agarHalf the agar
01.4110.706
5001.4110.706
1,0001.4110.706
2,0000.7060.5
4,0000.50.5
8,0000.50.5
16,0000.50.5
Now——

PETRI per cell, before any siege surcharge. Below 1,000 counted cells the price does not move; far above it the floor of 0.5 PETRI takes over.

What the contract refuses 16 checks, in order

A refused planting changes nothing and costs only gas. The contract checks in this order and stops at the first problem, with the message shown.

The lab note holds a control, direction, invisible or tag character.
a lab note may not contain control, direction, invisible or tag characters
The lab note is longer than 140 characters or 280 bytes.
a lab note is at most 140 characters
The account has not joined the dish yet.
join the dish first
The planting lists no cells, or more than the limit.
plant 1 to 64 cells
A cell index is outside the dish.
a cell is off the dish
The planting names a slide that does not exist.
there is no slide with that id
The planting names a slide, but its cells are not exactly the slide's pattern moved to a new place (turned or flipped does not count).
those cells are not the slide's pattern: plant exactly its cells, moved anywhere but not turned
The call asks to spend more credit than the account has won and been sponsored.
this account has X NEAR of won and sponsored credit
The NEAR brought (attached or from credit) is less than the fee for this many cells.
planting N cells needs at least X NEAR
The dish is still behind the clock after the planting caught up as far as one call may. Someone has to call advance first.
the dish is behind the clock; call advance first
The colony already planted in this generation.
one planting per generation; wait for the next one
The same cell is listed twice.
cell (x, y) is listed twice
A target cell is already alive, whoever owns it.
cell (x, y) is already alive
A house colony names a slide it does not hold.
the house plants only slides it holds: its PETRI never goes to players
The colony holds less PETRI than the price (siege surcharge and any royalty included), counting the earnings the planting just claimed.
planting N cells inside a rival's buffer costs X PETRI and a Y PETRI royalty; you hold Z
The NEAR brought does not cover the storage the planting used plus its fee.
this planting needs X NEAR for its storage and fee

PETRI leaves the agar for NEAR and for life, and comes back with planting

All 1,000,000 PETRI were minted once, at launch, into the contract’s own balance. That balance is the agar, and there is no other mint and no free grant. PETRI leaves the agar two ways: colonies buy it with NEAR, and the agar feeds a sliver of itself to living cells every generation. It comes back two ways: half of every planting returns to it, and the agar buys PETRI back for NEAR at half its price. The rest of every planting, and every PETRI spent on a specimen slide, is burned.

Buying in

A colony gets its first PETRI by joining with at least 0.01 NEAR, attached by a wallet or spent from sponsored credit. That NEAR first pays for the colony’s storage and the rest buys PETRI from the agar. After that, buy spends NEAR the same way. Every purchase is in the ledger with the NEAR and credit paid and the PETRI received; attached NEAR goes to the tide vault and credit to the credit pool.

price of one PETRI = 0.000200 NEAR × 1,000,000 ÷ PETRI in the agar
PETRI bought = agar × NEAR paid ÷ (200 NEAR + NEAR paid ÷ 2)

At launch one PETRI cost 0.000200 NEAR. With half of the agar left, it costs twice as much. A purchase is priced at the midpoint of the stretch of curve it moves along, so splitting a purchase does not get more PETRI.

Agar at your browser’s generation
—
One PETRI from the agar now
—
What NEAR buys now 5 amounts
NEAR paidPETRI receivedNEAR per PETRIPrice after
0.01———
0.05———
0.5———
2———
10———

Computed in your browser with buy_quote from petri-core, the function the contract runs. A join buys with its NEAR less its storage, so it receives a little less.

Every generation

The agar’s ration is 3 parts per million of its balance. It releases the whole ration only when at least 1,000 cells are counted (living cells of fed colonies, capped by reach); with fewer, it releases that fraction and keeps the rest, so a lone block earns 4/1,000 of the ration, what its price assumes. 2% of what is released goes to the keeper pot, paid to the account whose call next runs at least one generation (advance or any call that catches the dish up) and can hold PETRI, unless it is a house account or a keeper: then the pot keeps waiting for the next caller. The rest is split by each colony’s paid cells (see the reach, below). House colonies are never fed. Rounding remainders stay in the agar.

Ration: agar × 3 ÷ 1,000,000
—
Released for — counted cells
—
To the keeper pot
—
Per counted cell
—
Keeper pot now / paid so far
—

Selling back

sell(petri) hands PETRI back to the agar for NEAR from the tide vault, at 50% of the curve’s price, and never more than those units’ pro-rata share of the vault. Between two tides the agar buys back at most 10% of the vault, first come first served, and nothing before the first tide. A round trip through the agar always loses. A colony that has never attached NEAR (a free-play guest) is paid for its PETRI in credit it can spend in the dish, never in NEAR. House colonies never sell: the vault is the players’.

NEAR = min(curve price × 50%, vault × PETRI sold ÷ PETRI outside the agar)
The agar may still buy back, this tide
—
NEAR paid for PETRI so far
—

Claiming

Earnings do not land in a balance on their own. Each playing colony’s feed adds up in one row of a table of the colonies that play now, so a catch-up reads and writes that table once and logs one summary line however many colonies are alive. A colony moves its earnings into its balance with claim, which also sends the NEAR it has won at the tides, less what the claim’s own Claim entry costs; winnings too small to cover that and a possible refund stay owed until they grow. If the transfer of a claim, a sale, a sponsor’s reclaim or a pending claim fails, a callback writes a Refund entry and the NEAR becomes pending NEAR for the account, which claim_pending collects; only a failed bounty goes back to the vault. Planting and minting a slide claim waiting PETRI first. Credit won at the tides needs no claim. The claimable view shows what is waiting.

The reach: paid for 8 living cells per cell of stake

A colony’s claim on the feed, and so on the tides, is its living cells, but never more than 8 cells for every cell of stake. Planting adds one cell of stake per cell planted, and every tide that runs keeps 87.5% of each colony’s stake, so holding ground means planting again now and then. The cap grows only with what the colony paid for, so splitting into many colonies never earns more: the capped weights of the parts add up to at most the capped weight of the whole, and a property test in petri-core checks it. A growing pattern can still cover ground; past its reach that ground earns nothing.

paid cells = min(a colony's living cells, 8 × its stake)   (0 for the house)
stake      = cells planted, × 87.5% at every tide that runs
released = ration × min(all paid cells, 1,000) ÷ 1,000
share = released × (1 − 2%) × paid cells ÷ all paid cells

Red plants an R-pentomino, 5 cells, which grows. Green planted three blocks (12 cells) and Blue a beehive (6). Each is paid for at most 8 living cells per cell it planted, so Red can cover as much ground as it likes and is still paid for 40 at most. (No tide runs in this small demo, so no stake decays.)

Generation 0

ColonyCellsPaid forShare of the feed
Red000%
Green000%
Blue000%

The split on the live dish

Reading the dish.

This generation’s feed by colony reading
ColonyLiving cellsPaid forSharePETRI a generation

Highlighted rows are past their reach. Figures are this generation’s feed at your browser’s generation, rounded for display; the contract rounds each share down to a millionth of a PETRI. “Paid for” here counts every cell a colony planted; once tides have run, the contract’s cap is lower by the stake that decayed.

Nothing is created or lost

Every PETRI is in the agar, in an account, waiting to be claimed, in the keeper pot, or burned. The contract tests assert these identities after their scenarios; the first two are checked again here on the live counters.

  • total supply = minted − burnedReading the contract
  • agar = minted − sold − fed + returned + bought backReading the contract
  • every balance + agar + unclaimed + keeper pot = total supplyChecked in the tests by summing every holder
The PETRI ledger, from the contract 11 counters

Read from the state view of petri-v6.testnet at stored generation —. Feed for the generations since then is added when the dish next advances.

Minted at launch
1,000,000

The whole supply, once, into the agar.

Sold for NEAR
—

Bought from the agar by colonies, at the curve's price.

Fed to the living
—

Everything the agar has paid out each generation, the keeper's 2% included.

Returned by planting
—

50% of every planting goes back into the agar.

Bought back
—

PETRI the agar bought back for NEAR from the vault.

Still in the agar
—

Minted, less sold and fed, plus returned and bought back.

Waiting in the keeper pot
—

Set aside from the feed until a call outside the house runs a generation.

Paid from the keeper pot
—

Pots already collected by the calls that ran a generation (never a house account or keeper).

Burned
—

The other 50% of every planting, the whole price of every specimen slide, and PETRI burned by a forced unregistration or a refund to a sender that had unregistered. Gone for good.

Total supply
—

What ft_total_supply reports: minted less burned.

Held by accounts or waiting to be claimed
—

Total supply less the agar and the keeper pot.

Standard tokens NEP-141, 145, 148; slides NEP-171, 177, 178, 181
  • NEP-141. ft_transfer, ft_transfer_call (with refunds through ft_resolve_transfer), ft_balance_of and ft_total_supply. Transfers attach exactly 1 yoctoNEAR. PETRI refunded to a sender that has unregistered meanwhile is burned. House accounts (the strains and the keepers) can send PETRI only to other house accounts. A colony that has never attached NEAR cannot send PETRI at all, and neither can one holding kept PETRI (PETRI earned before its first NEAR, or bought with credit, until it has been planted).
  • NEP-148. Name Petri, symbol PETRI, 6 decimals and an inline icon.
  • NEP-145. A receiver must be registered before it can hold PETRI. Joining registers a colony; anyone else calls storage_deposit, which costs the storage of one balance record. A slide’s holder is registered by the planting that pays it its first royalty. storage_unregister with force burns the PETRI still held; a colony’s account cannot unregister, forced or not.
  • The dish does not play on itself. The contract account cannot join, buy, sell, plant, claim, advance or send PETRI, and a transfer to it is refused with “PETRI goes back to the agar only by planting or selling”. Its ft_balance_of is the agar plus unclaimed earnings, the keeper pot and the PETRI held in escrow for pact offers.
  • Specimen slides. Each slide is an NFT in the same contract: NEP-171 transfers (with nft_transfer_call), NEP-177 metadata whose image is an SVG the contract draws from the captured cells (at most 10 a call from the enumeration views), NEP-178 approvals and NEP-181 enumeration. A slide of 12 or more cells is also a pattern licence: see planting.
  • Events. NEP-141 ft_mint once at launch, ft_transfer for purchases, sales, claims, keeper pots, planting returns, slide royalties, transfers and their refunds, ft_burn for planting, slides, forced unregistrations and refunds to unregistered senders; NEP-171 nft_mint and nft_transfer; and the dish’s own sponsor, unsponsor, join, rename, plant, sell, claim, payout, payout_failed, slide, pact, intents, claim_pending, skip, relaunch and one generation summary per catch-up.

The NEAR goes back to whoever earned this hour

The NEAR that colonies attach collects in the tide vault; sponsored credit spent in the dish collects in a separate credit pool. Every 240 generations (60 min) 5% of each is paid out, split by the PETRI each colony earned from the feed since the previous tide: the vault in NEAR, the credit pool as credit. A colony planted a minute before the tide gets a minute’s worth.

The tide

at every 240th generation, if a colony outside the house earned since the last tide:
pay      = vault × 5%
bounty   = min(pay × 1%, 0.001 NEAR)    to whoever's call ran the tide,
           none when that is a house colony or a keeper (it stays in the vault)
storage  = the tide's own ledger entry
a colony's share  = (pay − bounty − storage) × its window ÷ every window
its credit share  = credit pool × 5% × its window ÷ every window

A colony’s window is the PETRI it was fed since the last tide, so it already carries the reach cap. The windows reset at every tide, and every colony’s stake keeps 87.5% of itself. Rounding remainders and the other 95% stay in the vault and the pool. A tide with nobody to pay, because no colony outside the house earned since the last one, does not run at all: no entry, no bounty, no decay, and the buy-back allowance stays as it was. Every tide that runs writes a Tide entry to the ledger with the history chain, its stored bytes (130) and the colony whose call ran it (0 for a caller with no colony, 65535 for a keeper); those entries are the dish’s checkpoints. They do not carry the figures above: a replay works them out from the ledger, and a tide event logs them.

A colony that has attached NEAR of its own wins NEAR. It waits under the colony’s name until it calls claim, and goes to the account it named with set_payout if it set one. A colony that has never attached NEAR, such as a free-play guest, is paid its share of the vault as credit instead, and so is the bounty of a tide its call runs. Credit won is spendable in the dish at once, needs no claim, is spent before sponsored credit and can never be withdrawn. Each tide that runs also reopens the buy-back allowance: the agar may pay up to 10% of the vault for PETRI before the next tide.

The house takes nothing

The five AI strains are listed in rules.house (5 accounts). They plant like anyone and buy every PETRI they plant with, but they are never fed, take no share of any tide, never sell PETRI back and can send PETRI only to other house accounts, so none of it reaches a player who could sell it into the vault. Their cells never make a planting a siege, and they plant only slides they hold, so they never pay a royalty. The keepers in rules.keepers are house accounts too. A tide run by a house colony or a keeper pays no bounty, and neither ever takes the keeper pot. On this testnet dish they spend sponsored credit, which goes to the credit pool. In an early simulator, where the house was fed, a dish with only the house on it fed the agar down from 1,000,000 to about 179,000 PETRI in 30 days, nearly all of it to the house. Under the launched rules the same run ends with 996,880 PETRI in the agar, all of the difference bought with NEAR.

Sponsored credit

Anyone can call sponsor(account_id) with NEAR attached. The contract keeps the NEAR (at least 0.01, less its records’ storage) as credit for that account, spendable only on joining, buying, planting and a slide’s storage, and never withdrawable by the account. Each sponsor’s credit is kept apart, at most 8 sponsors an account, and the account spends what it won first, then its sponsors’ credit oldest first. A sponsor may take back only what is left of its own credit, with unsponsor, once a day (5,760 generations of wall-clock time) has passed since it last gave or the account last drew on it; if that transfer fails, the NEAR becomes pending for the sponsor. Credit a colony wins is its own. On this free-play dish the site's relayer gives every guest 0.05 NEAR of credit this way, so it never has to attach NEAR to a call it relays.

In the vault
—
Next tide
—
Paid at the tides so far
—
Tides run
—
In the credit pool
—
Credit sponsored
—
Credit spent in the dish, won or sponsored
—

The next tide, if nothing more came in

Reading the dish.

Window growth by colony reading
ColonyPaid cellsShare now

The real split uses each colony’s whole window since the last tide, which the contract keeps; this table shows only the rate at this generation.

vault + tides + bounties + sales ≤ all NEAR inReading the contract
Every NEAR a player spends, and where it goes 9 ways
Joining
At least 0.01 NEAR, attached or from credit. The contract keeps what the new colony's storage costs and spends the rest on PETRI from the agar. Attached NEAR goes to the vault, credit to the credit pool.
Buying
Everything brought, less the purchase record's storage, buys PETRI from the agar. Attached NEAR goes to the vault, credit to the credit pool.
Planting
The storage the planting used, plus 0.0001 NEAR for every cell. The contract keeps the storage; everything above it goes to the vault if attached, to the credit pool if it was credit.
Selling back
Comes out of the vault: the sale record's storage, and the rest to the seller, in NEAR, or as credit to a colony that has never attached NEAR. A NEAR sale must be large enough to pay for a refund's records too; if its transfer fails, the NEAR becomes pending for the seller. House colonies never sell, and neither does a colony holding kept PETRI (what it earned before its first NEAR, or bought with credit) until it has planted it.
A specimen slide
Its storage, from the colony's credit first and then from attached NEAR; attached NEAR left over is sent back. Its PETRI price is burned, and none of its NEAR reaches the vault.
Paying with any token
On mainnet, wNEAR that NEAR Intents delivers is unwrapped and joins or buys for the account it names, exactly as attached NEAR. It is never refunded: the whole amount first becomes pending NEAR for that account with its order, less its records' storage, and the order runs in a receipt of its own. An order that cannot run yet waits, and anyone can complete it later with settle_pending; the account can instead take the NEAR back with claim_pending. An amount too small even for its records goes to the vault with a Dust entry.
Sponsoring
At least 0.01 NEAR. The contract keeps what the sponsorship's records cost (a new sponsor also sets aside 210 bytes for the Unsponsor entry it may write later) and the rest becomes credit for the account, in that sponsor's own grant.
Registering to hold PETRI
The storage of one balance record, refunded by storage_unregister once the account is empty, or with force, which burns the PETRI left (its Burn entry is paid from the refund). A colony's account cannot unregister.
Gas
Every transaction pays its own gas. Guests on the free-play dish have theirs paid by the site's relayer.

Ways to play, and what they pay

A live cell earns its share of the feed every generation it is alive, and its share of the tide when one comes. Planting it cost the price of a cell. Every strategy is a different answer to the same sum.

  • Still lifes earn

    A still life never changes, so every cell of it is fed every generation until something hits it. It is the plainest bet on the dish: pay once, collect slowly.

    Block, Beehive, Loaf

  • Oscillators shimmer

    An oscillator repeats in place. A pulsar is planted as 48 cells but averages more than that over its three phases, so it earns on more cells than it cost. Bigger shapes are easier to knock apart.

    Blinker, Toad, Pulsar

  • Ships and guns reach

    Planting next to a rival costs three times the price. Something that travels gets there for the normal price. When a glider hits a colony, births in the wreck join whoever owns most of their parents, so territory changes hands. A gun keeps firing gliders, and every glider in flight earns, up to the gun's reach.

    Glider, Spaceship, Glider gun

  • Eaters defend

    An eater is a seven-cell still life that destroys a glider flying into it at the right angle and repairs itself. A line of them facing a raider is a wall, and it earns like any still life while it waits.

    Eater

  • Wild seeds gamble

    Five cells that grow chaotically for a long time. On an empty dish the R-pentomino is all yours; near others, its births join whoever owns most of their parents, and contested ground stays empty. A colony is paid for at most eight living cells per cell of stake, so an R-pentomino planted on its own is paid for at most forty cells; growth past that covers ground but earns nothing more.

    R-pentomino

The payback sum

The price of a cell is what an average cell earns in 480 generations, counting at least 1,000 counted cells. Right now one cell costs — PETRI, and each paid cell is fed — PETRI a generation: the ration, less the keeper’s share, divided by the — cells it is released for, — of them counted now. So a still life that nothing disturbs pays for itself in about — generations, roughly —.

With — counted cells, the price falls as each cell's share of the feed falls, so an average cell pays back in about 480 generations whatever the crowding, until the floor of 0.5 PETRI a cell takes over. Both sides shrink slowly with the agar.

Three things bend the sum. A colony is paid for at most 8 living cells per cell of stake (the cells it planted, of which 87.5% remains after each tide), so growth past that is ground it is not paid for. A siege costs 3 times the price, so its cells take 3 times as long to pay back. And every 240 generations the tide pays 5% of the vault by the PETRI each colony earned that hour, so every generation a cell stays alive also earns a slice of NEAR (or of credit, for a colony that has never attached NEAR).

Each pattern, priced now 9 patterns

Average live cells over the first 240 generations (one hour) after planting each pattern alone on an empty 128 by 128 dish, measured in your browser with petri-core. Earnings use today’s feed per paid cell and count at most 8 cells per cell planted. On the real dish neighbours, raids and crowding change all of this.

PatternCells plantedCosts nowAverage live cellsEarns a generationPays back in
Block—————
Beehive—————
Eater—————
Blinker—————
Pulsar—————
Glider—————
Spaceship—————
Glider gun—————
R-pentomino—————

A glider gun’s average climbs because every glider it fires keeps flying and earning; on a crowded dish those gliders soon hit something. The R-pentomino’s figure is for an empty dish, where all of its growth is yours.

Check every generation, and every yoctoNEAR, yourself

The contract keeps a running hash of the board’s history and one ordered ledger of every join, purchase, sale, planting, specimen slide, tide, clock skip, refund, sponsorship, reclaim, claim, pending payment, dust and burn, with the PETRI, NEAR and credit each moved. Anyone can replay that ledger from generation zero and arrive at the same board, agar, vault, credit pool, credit, pending NEAR and earnings for every colony, or find the first place where they differ.

The hashes

board hash = sha256(width ‖ height ‖ for every live cell, in index order: index ‖ owner)
chain      = sha256(previous chain ‖ generation ‖ board hash)

Width and height are 16-bit, the index 32-bit, the owner 16-bit and the generation 64-bit, all little-endian. The chain starts as 32 zero bytes and folds in the board every 16th generation, once every four minutes. Every tide, once every 240 generations, writes the chain into its Tide ledger entry; the checkpoints view lists generation 0 and every tide.

The replay

  1. Start from an empty board at generation 0, a chain of zeros, an agar holding the whole supply, an empty vault and an empty credit pool.
  2. For each generation, apply its ledger entries in order. A join adds a colony. A purchase and a sale are checked against the curve, and a sale against the allowance. A planting is checked for legality and its siege flag, must cost the formula’s price and bring its cell fee, and adds its NEAR to the vault and its credit to the pool. A planting under a slide’s licence must name a slide of at least 12 cells, exactly its pattern, moved but not turned, at the licence price, and must have paid the royalty to whoever held the slide then (or the agar, if the planter had never attached NEAR). A slide must hold exactly its colony’s living cells in its rectangle and burn the rule’s price. A tide must run exactly when some colony outside the house had earned, carry the same chain and stored bytes, pay the same shares of the vault and the pool, as NEAR or as credit to the right colonies, and pay no bounty when the house ran it. A claim must take exactly what its colony was owed, and a refund must match the payout it names. Every colony’s kept PETRI is rebuilt, and no colony holding any may sell for NEAR or pay PETRI into a pact. Every pact entry is checked against the pact rules and the escrow, and every planting against the pacts binding its planter.
  3. Step with petri-core and feed the living, with the reach cap on each colony’s decaying stake, the house and the keeper’s share.
  4. At the end, compare every counter, every colony’s PETRI earnings, NEAR winnings and credit winnings, and every slide’s holder, moves and royalties with the contract. Rebuild each term of the solvency check (the vault, the credit pool, credit given, won, sold, spent and taken back, NEAR owed and pending NEAR) from the ledger alone, compare it with the contract’s counter, and check that the contract’s NEAR covers them.

The terminal script node scripts/verify.mjs (add --network mainnet for the mainnet dish) pins every read to one final block and prints 45 checks. The verify page runs the same replay in your browser, also pinned to one block, and shows 37 checks covering the same ground, grouped a little differently and without the code hash. The contract test replaying_the_ledger_reproduces_the_dish_the_agar_and_the_vault does it in Rust.

The 45 checks scripts/verify.mjs
  1. History chain
  2. Board hash
  3. Living cells
  4. Every planting legal, sieges marked
  5. Every planting at the formula's price
  6. Every planting paid its cell fee
  7. Every licensed planting: a slide of at least 12 cells, its exact pattern, the licence price, the royalty to the holder of the day (or the agar, for a planter that never attached NEAR)
  8. Every purchase on the curve
  9. Every sale back on the curve and within the allowance
  10. Every tide: ran exactly when due, chain, stored bytes; shares of the vault and the credit pool, bounty (none to the house) and storage worked out from the ledger
  11. Every claim took exactly what its colony was owed
  12. Every refund is for exactly the payout it names, once
  13. No colony holding kept PETRI sold PETRI for NEAR or paid for a pact
  14. Every pact kept to the rules, and no planting broke a pact binding its colony
  15. PETRI the dish holds for pact offers not yet accepted
  16. Pacts offered
  17. Every specimen slide is its colony's own cells as the dish stood, at the rule's price
  18. Every slide's holder, moves and royalties
  19. PETRI in the agar
  20. PETRI sold
  21. PETRI burned
  22. PETRI burned by specimen slides
  23. PETRI paid to slide holders in royalties
  24. PETRI returned by planting
  25. PETRI bought back
  26. Keeper share
  27. Every colony's PETRI earnings
  28. NEAR in the vault
  29. NEAR paid in
  30. NEAR paid at tides
  31. Vault shares and bounties paid as credit
  32. Sales paid as credit
  33. Every colony's NEAR winnings
  34. Credit in the credit pool
  35. Credit paid at tides
  36. Credit sponsored, from the ledger
  37. Credit spent, from the ledger
  38. Credit taken back by sponsors, from the ledger
  39. NEAR owed to colonies, from the ledger
  40. Pending NEAR, from the ledger
  41. Every colony's credit winnings
  42. Every colony's kept PETRI
  43. The contract's NEAR covers everything it owes, every term rebuilt from the ledger
  44. Deployed code hash (terminal only)
  45. No full-access key

Replay from genesis

Your browser’s chain at generation —reading the dish
The contract’s chain at stored generation —reading the dish
Tides (checkpoints)
—
Entries in the ledger
—
Of which plantings
—
Colonies
—

The lock

No method changes a running dish’s parameters, mints PETRI or edits the board. The one way to start over is relaunch, a private method only the contract account itself can call, which clears a v6 dish and refuses an account with no v6 dish and one that already runs v6.1. What remains is the account itself: whoever holds a full-access key to petri-v6.testnet could deploy other code.

The code was built with cargo near build reproducible-wasm at commit 4858ca0; its hash is 8QAsfDHePT3TdZ6LvJRV9pcNHfHJemgFbiBBaZK6ZPwR, and the contract’s NEP-330 contract_source_metadata names that GitHub commit, so anyone can rebuild it and compare.

Deployed code hash
—
Full-access keys now
—

The account still has one full-access key. The team will delete it before judging, so the code can never change; until then the full-access check is the one that fails on /verify and in the terminal, which then exits 1. The command:

near account delete-keys petri-v6.testnet public-keys ed25519:8kGYoPJ6jVEZRrjjYKGVLfXD7LCyTDDqu41Cxx9UjHUu network-config testnet sign-with-legacy-keychain send

How the parameters were chosen

The numbers are set once, when a dish starts, and no method changes them while it runs. The dish now runs v6.1 as petri-v6.testnet and, with the same build, as petri-dish.near on mainnet. Earlier testnet dishes (petri-dish.testnet, then petri-v2 to petri-v5) were left behind as reviews found problems; each time the rules were changed, tested, and launched on a new contract that started again from an empty board. petri-dish.near ran v5 first and was relaunched in place for v6, and both dishes were relaunched again for v6.1: the private relaunch method deleted everything the earlier version stored and started again from generation 0.

The simulator

sim/src/main.rs runs petri-core’s own Life step, feed, reach on decaying stake, price, curve, sell-back, credit pool and window tides on a 128 by 128 dish for 7 and 30 days, with 15, 150 and 1,500 scripted players, relayer guests and the five house strains, and counts every yoctoNEAR: what each player paid, gas included, and what it withdrew from tides, sales and bounties. It reads the launch rules from contract/launch-rules.json, but its published runs predate three launched changes: they paid 10% tides (now 5%), paid guests’ winnings in NEAR their accounts could not move (now credit), and ran tides with nobody to pay (now skipped). It estimates storage and gas rather than measuring them on chain. The runs also predate v6, in which a keeper takes no keeper pot and no tide bounty and the house cannot sell (the simulated house never sold), and v6.1; sim/out-v6.1 reruns v6.1's rules against v6's on the same seeds.

What the runs show

  • Ordinary players lose a little NEAR: builders, raiders, defenders and late joiners end between −0.27 and −0.15 NEAR at 150 players and −0.15 to −0.09 at 1,500 (medians, cash). Storage takes 37% to 44% of all the NEAR that comes in.
  • The methuselah, one R-pentomino an hour, is the only kind ahead at 15 and 150 players (+0.02 and +0.14 NEAR), and behind at 1,500 (−0.04). With 5% tides, as launched, it made +0.29 at 150.
  • The carpet locker lost at 15 and 150 players (−0.89, −0.58) and won at 1,500 (+0.59). With 5% tides it lost at both 150 and 1,500 (−1.21, −0.45). It is the biggest weakness the simulator found.
  • Big stakes lose the most: the 2-NEAR whale ended −3.97, −2.12 and −0.99. Splitting the same NEAR over 10 colonies lost less at 15 and 150 players and more at 1,500.
  • Sybils do not pay: a builder with 10 relayer guests beside it ended −0.16, −0.12 and −0.10, and a player that sponsored 10 of its own accounts and took the credit back −0.47, −0.42 and −0.33.
  • Snipers and racers lose a little (−0.08 to −0.05), sellers about −0.10. Each house strain costs the team about 1.1 NEAR a week, paid to the other players.
What changed for v6.1 9 changes, v6 to v6.1
Gas at 30,000 colonies
The hot table holds only the colonies that play now: those that earned since the last tide and those with living cells and a stake that can still earn, never the house, at most 10,000 rows and 32 leaving a call. The rest wait in 69-byte cold slots (pages of 32) whose stake decays lazily when read, and the catch-up stops at 110 TGas less what is still to write. In the simulator the hot rows fell from 17,102 to 1,336 on average, the largest call from 237 to 61 TGas, and calls over 150 TGas from 116,731 to 0.
Smaller ledger entries
A tide entry is 130 bytes, not 289: it stores the chain, its bytes and its caller, and a replay works out the amounts, which a new tide event logs. PETRI amounts in entries are u64, a planting's fixed storage is 180 bytes (was 240) and a purchase's 113 (was 140).
Licences need 12 cells
A planting under a slide's licence needs a slide that captured at least licence_min_cells (12). Smaller slides are keepsakes. In the simulator the royalty farmer's licensed plantings fell from 7,852 to 466 and its cash from +0.29 to +0.11 NEAR a week.
A guest's royalty goes to the agar
A planter that has never attached NEAR pays its licence royalty to the agar, not to the holder, so free play cannot route PETRI to a wallet through royalties. In the simulator the sybil wallet's royalties from such planters fell from 56 to 0 PETRI.
The keeper pot goes to any caller
The catch-up pays the pot to the account whose call ran at least one generation, whichever call it was, if the account can hold PETRI and is not a house account or keeper. In the simulator the pot left after a week fell from 1,480 to 1.1 PETRI on a young dish.
Site gas
The site prepays 300 TGas for join, plant, buy, sell, claim, advance and mint_slide (unused gas is refunded), and the relay accepts up to 300.
Free play never reaches NEAR
PETRI earned before a colony's first NEAR stays in the dish: a guest cannot send PETRI, and while a colony holds kept PETRI (what it earned or was paid in royalties before its first NEAR, and PETRI bought with credit) it cannot sell for NEAR, send PETRI or pay into a pact. Plantings and slides spend it first. In the simulator the vault's NEAR paid for farmed PETRI fell from 0.1674 to 0, and a transfer attack that drew +0.0470 NEAR a week per operator drew nothing. Guests also take no keeper pot.
Pacts the contract enforces
The council's deals are pacts: pact_offer escrows the payer's PETRI, pact_accept pays it to the promisor, and until the pact ends the contract refuses every planting of the promisor within pact_radius (8) cells of the payer's living cells. A colony is party to at most 8 pacts; both replays rebuild and check every pact.
Started again
Both dishes were relaunched in place with relaunch, which deleted everything v6 stored and started a fresh dish from generation 0. v6.1 keeps per-account data, cold pages, the hot table and the tide index under new key prefixes, so nothing a wrong account list leaves behind can be read as v6.1 state.
What changed for v6 10 changes, v5 to v6
Sponsored credit
Credit is kept per sponsor: an account holds grants from at most 8 sponsors, spends what it won first and then the oldest grant, and a sponsor can take back only its own unspent grant, once a day of wall-clock time has passed since it last gave or the account last drew on it. A sponsorship brings at least 0.01 NEAR. In v5 one record held all of an account's credit, and whoever sponsored last could take all of it back.
The house
House colonies never sell PETRI back, and house accounts (the strains and the keepers) can send PETRI only to other house accounts. A tide run by a house colony or a keeper pays no bounty: it stays in the vault. House accounts never take the keeper pot, and the house plants only slides it holds, so it never pays a royalty.
Gas as the dish grows
Each colony's numbers live in cold pages of 64 colonies and in a hot table of the colonies that have stake. A join appends one slot; the feed, tides and decay touch only the hot table. (The simulator later showed that table still grew to 27,538 rows on a busy dish; v6.1 narrowed it, below.)
Paying with any token
wNEAR is never refunded: any amount becomes pending NEAR for its account with its order, or goes to the vault with a Dust entry when it cannot pay for its own records. Anyone can complete a waiting order with settle_pending, and intent_minimum tells the site the least a payment needs.
Names paid for by others
A colony started by someone else's payment is named Culture and hex digits of its account's hash, in a colour from the same hash, and may rename once. Nobody can choose a name of that form.
Failed payouts
A sale, claim, reclaim or pending claim whose transfer fails becomes pending NEAR for its account; only a failed bounty goes back to the vault. Each refund names the payout it refunds.
A ledger that rebuilds solvency
Sponsorships, reclaims, claims, pending NEAR, dust and burns are ledger entries, so both replays rebuild every term of the solvency check from the ledger alone and compare each with the contract's own counter.
Slides that do something
A slide is a pattern licence: planting its exact pattern, moved anywhere but not turned, costs 25% less, and anyone but the holder pays the holder 10% of that cost in PETRI. (v6.1 limits this to slides of 12 or more cells.)
Token standards
PETRI refunded to a sender that unregistered meanwhile is burned, storage_unregister with force burns the balance (a colony's account cannot unregister), and nft_tokens draws at most 10 images a call.
Started again
petri-dish.near was relaunched in place with relaunch, which deleted everything v5 stored and started a fresh dish from generation 0; the testnet dish moved to petri-v6.testnet.
What changed for v5 9 changes, v4 to v5
Free play and NEAR
Sponsored credit spent in the dish now goes to its own credit pool, paid out at the tides only as credit. A colony that has never attached NEAR is paid its share of the vault, its sales and the bounties of tides it runs as credit too, and only a colony that has attached NEAR may name a payout account.
A pay cap that never shrank
Stake: planting adds a cell of stake per cell, and every tide keeps 87.5% of it, so holding ground means planting again now and then. The reach went from 4 cells per cell planted to 8 per cell of stake.
Idle tides
A tide with nobody to pay, because no colony outside the house earned since the last one, no longer runs: no entry, no storage, no decay.
Big tides and gas
Tide winnings are kept in packed per-colony arrays, each read and written once per tide. In the simulator the biggest tide at 1,500 players fell from about 104 TGas to about 11.
Tides of 10%
Tides of 5%. In the simulator it cut the carpet locker's share of all tide NEAR from 5.8% to 3.1% at 150 players.
A dish left alone for days
When the dish is more than 480 generations behind, the clock skips ahead to 120 behind and writes a Skip entry, so the next caller does not pay for the quiet stretch.
Payouts that fail
A failed claim is owed to the colony again; a failed sale or bounty goes back to the vault with a Refund entry, so the books still close.
Owing more than it holds
The solvency view compares the contract's NEAR with everything it owes, and both replays check it.
New in v5
Specimen slides (NFTs drawn on chain and checked by both replays), paying with any token through NEAR Intents, a one-time rename for colonies someone else paid for, house cells that never make a planting a siege, and sponsors that can take back credit left unused for a day. The same build runs on mainnet.
What changed after the second review 12 findings, v2 to v4
The relayer attached the guest's deposits itself. A guest could sign calls that fail inside the contract, and each failure refunded the deposit to the guest, draining the relayer.
The relayer relays only calls with no deposit. Guests pay from credit the relayer gives them on chain with sponsor, spendable only in the dish, and their keys are function-call keys for the dish, which cannot attach or move NEAR.
The guest proof of work was not bound to anything, so one solution could be replayed for many guests.
A guest needs a challenge the server signed in the last ten minutes, an 18-bit proof of work bound to that challenge and its key, and the account name comes from the key: one guest per key.
The 15% cap counted living cells, so splitting into colonies just under the cap earned more.
The reach: a colony is paid for at most a fixed number of living cells per cell it paid for (4 per cell planted then; 8 per cell of stake now), and the parts of a split never weigh more than the whole.
A carpet of blocks could put every empty cell inside someone's buffer and close the dish to newcomers.
Sieges: planting inside a rival's buffer is allowed at 3× the price. Without siege, the simulated locker left no legal spot in 5 of 20 seeds; with it every seed has one.
Tides split by cells alive at the tide generation, so a colony planted just before a tide took a full share.
Window tides: each tide splits by the PETRI each colony earned since the previous one.
advance paid the keeper pot even when it ran no generation.
The pot is paid only by a call that ran at least one generation.
The strains' model read colony names, so a name written as an instruction could steer it.
Rivals reach the model by number and size only, and names are plain ASCII; notes refuse hidden and tag characters.
NEAR moved through counters the replay could not rebuild.
Every purchase, planting, sale and tide records its NEAR in the ledger, and the replay checks the vault, NEAR in, tide payouts and every colony's winnings.
The contract was not a reproducible build and the account kept a full-access key.
Built with cargo near build reproducible-wasm, with NEP-330 metadata linking the commit; the key is to be deleted before judging, and /verify fails that check until it is.
The simulator's claims were ratios of PETRI earned to PETRI spent.
Every result is now NEAR per player, cash and paper (PETRI held, valued at the sell-back price) reported apart.
On a sparse dish the price counted 1,000 cells but the whole ration went to the few alive, so early cells paid back far faster than the price assumed.
The agar releases its ration for at least 1,000 counted cells and never more per cell; with fewer, it releases that fraction and keeps the rest.
The house strains were fed like players, so on a quiet dish they slowly ate the agar.
House colonies are never fed and take no tide share; the NEAR they pay in goes to the other players.

The first review (v1 to v2) found free 64-PETRI grants that could be farmed, a cell price unrelated to what a cell earns, a methuselah taking 45% of the dish, one log line per colony per catch-up (the dish would stop at about 115 colonies), and a contract that could mint by sending PETRI to itself. v2 fixed those with the NEAR buy-in, the payback price, accrued earnings and the self-call guard; the current dish keeps all of it.

The dish’s parameters, read now 35 fields of rules
FieldValueMeaning
width × height128 × 128Cells on the dish, edges wrapped.
generation_ms15,000Milliseconds between generations.
max_supply1,000,000 PETRIMinted once, into the agar.
feed_ppm3Parts per million of the agar fed to the living each generation.
keeper_bps200 (2%)Share of the feed set aside in the keeper pot, paid to the account whose call ran the generation (never a house account, a keeper or a guest).
reach8Most living cells a colony is paid for, per cell of stake.
stake_keep_bps8750 (87.5%)Share of every colony's stake left after each tide that runs.
burn_bps5000 (50%)Share of a planting burned; the rest returns to the agar.
payback480Generations of an average cell's feed that a cell costs.
min_cell_price0.5 PETRIThe lowest price of one cell.
live_floor1,000The agar releases its full ration only for at least this many counted cells, and prices count at least this many.
petri_price0.000200 NEARLaunch price of one PETRI; the agar asks this × max supply ÷ agar.
min_join0.01 NEARThe least NEAR a colony joins with.
cell_fee0.0001 NEARNEAR per planted cell, on top of storage, to the tide vault (or the credit pool).
tide_every240Generations between tides.
tide_bps500 (5%)Share of the vault, and of the credit pool, paid out at each tide.
tide_bounty_bps100 (1%)Share of a tide paid to the caller whose transaction runs it; none when that is a house colony or a keeper (it stays in the vault).
max_bounty0.001 NEARThe most a tide bounty pays.
sell_bps5000 (50%)Share of the curve's price the agar pays when it buys PETRI back.
sell_cap_bps1000 (10%)Most of the vault the agar buys back with between two tides.
siege_x3Price multiple of a planting inside a rival's buffer.
buffer3Cells around a rival's live cell where a planting is a siege.
max_plant_cells64Most cells in one planting.
max_catchup120Most generations one call advances.
max_lag480Generations behind the clock past which the clock skips ahead to max_catchup behind.
slide_cells_price1 PETRIPETRI per captured cell a specimen slide burns.
slide_min_cells5Fewest of its own living cells a slide must capture.
licence_min_cells12Fewest cells a slide must have captured to be a licence. A smaller slide is a keepsake: a planting under it is refused.
slide_discount_bps2500 (25%)How much less a planting of a slide's exact pattern costs under its licence.
pact_radius8Cells around the payer's living cells where a bound colony may not plant, for as long as a pact binds it.
pact_max_gens2880Most generations a pact can last beyond the dish's stored generation when it is offered.
slide_royalty_bps1000 (10%)Share of a licensed planting's cost that anyone but the slide's holder pays the holder, in PETRI (to the agar, from a planter that has never attached NEAR).
wnearwrap.testnetThe wNEAR contract whose transfers join or buy (pay with any token).
housepetri-violet.testnet, petri-safranin.testnet, petri-methylene.testnet, petri-malachite.testnet, petri-congo.testnetThe dish's own strains: never fed, no tide share, never sell, send PETRI only to other house accounts, take no tide bounty or keeper pot, and their cells never make a siege.
keeperspetri-keeper.testnetThe dish's keepers, house accounts too: no tide bounty, no keeper pot, and PETRI only to other house accounts.

From the contract’s rules view. Fixed in code: names of 1 to 24 ASCII characters, notes of at most 140 characters, slide titles of at most 40, slides 4 to 32 cells a side, the chain folded every 16 generations, catch-up stopping at 110 TGas less what is still to be written, sponsored credit reclaimable after 5,760 generations of wall-clock time unused (each sponsor its own grant, at most 8 sponsors an account, at least 0.01 NEAR a sponsorship), and wNEAR never refunded (any amount waits as pending NEAR, or goes to the vault as dust).

Cash per player after 7 days 14 kinds, 3 societies

Median NEAR actually withdrawn minus NEAR actually paid, gas included, with the lowest and highest over seeds below. PETRI still held, valued at the sell-back price, barely changes these. Relayer guests attach nothing and withdraw nothing, so they are 0 by construction and left out. Run with 10% tides; the next table has 5%.

Player15 players1501,500
Builder0.05 NEAR to join, up to 0.25; still lifes near home−0.266−0.35 to −0.16−0.183−0.22 to −0.15−0.109−0.11 to −0.10
Raider0.05 / 0.25; gliders at rivals, one move in three a siege−0.220−0.38 to −0.05−0.153−0.17 to −0.12−0.126−0.14 to −0.12
Defender0.05 / 0.25; eaters and beehives−0.214−0.40 to +0.05−0.160−0.20 to −0.13−0.087−0.10 to −0.08
Methuselah0.1 / 0.5; one R-pentomino an hour+0.018−0.12 to +0.51+0.142+0.09 to +0.23−0.041−0.05 to −0.03
Late0.05 / 0.25; a builder joining on day 2 or 3−0.322−0.38 to −0.29−0.268−0.29 to −0.24−0.153−0.16 to −0.15
Whale2 NEAR in one colony, up to 3−3.972−4.30 to −2.44−2.122−2.30 to −1.25−0.986−1.03 to −0.96
Split whalethe same over 10 colonies (20 at 1,500)−2.385−3.27 to −1.88−1.371−1.62 to −0.98−1.138−1.27 to −0.99
Sniper0.05 / 0.25; plants just before tides, sells after−0.076−0.12 to −0.06−0.066−0.09 to −0.06−0.057−0.06 to −0.05
Locker1.5 / 2; a lattice of blocks putting every empty cell in its buffer−0.894−1.36 to +0.00−0.577−0.81 to −0.17+0.590+0.19 to +0.95
Racer0.01; never plants, races to advance for the pot and bounty−0.053−0.07 to −0.04−0.054−0.06 to −0.05−0.061−0.07 to −0.06
Seller0.2; buys and sells back as fast as allowed−0.105−0.11 to −0.11−0.105−0.11 to −0.10−0.102−0.10 to −0.10
Sybil guesta wallet builder plus 10 relayer guests near it−0.164−0.28 to +0.11−0.124−0.19 to −0.08−0.099−0.13 to −0.09
Self-sponsorsponsors 10 of its own accounts with 0.05 each, then takes the credit back−0.470−0.57 to −0.33−0.420−0.48 to −0.25−0.327−0.36 to −0.29
House strainthe five strains, 1 NEAR budget each; never fed, no tide share−1.078−1.08 to −1.07−1.081−1.08 to −1.08−1.111−1.12 to −1.11
One rule changed at a time median cash

Each row changes one rule against the simulated launch rules, on the same seeds. The dish runs with the highlighted change. In v6 a keeper takes no pot, as in the runs where the keeper is unregistered. The last column is the locker’s share of all tide NEAR.

150 playersBuilderMethuselahLateWhaleSplit whaleLockerRacerSellerLocker tides
The simulated launch rules (10% tides, keeper unregistered)−0.183+0.142−0.268−2.122−1.371−0.577−0.054−0.1055.8%
Tides of 5% (launched)−0.166+0.289−0.256−2.052−1.673−1.208−0.060−0.1053.1%
The team keeper registered, so it collects the pot (as v5 ran; a v6 keeper takes none)−0.173+0.110−0.267−1.784−1.266−0.455−0.046−0.1055.7%
Stake keeps 80% at each tide, not 87.5%−0.174+0.115−0.275−1.870−1.327−0.515−0.053−0.1055.5%
Reach 4−0.180+0.111−0.264−2.063−1.395−0.444−0.054−0.1055.3%
Reach 2−0.171+0.074−0.269−1.758−1.288−0.485−0.053−0.1055.8%
Siege ×2−0.176+0.133−0.273−2.106−1.394−0.586−0.053−0.1055.8%
Sell-back at 30% of the curve−0.178+0.129−0.272−2.101−1.329−0.496−0.051−0.1444.8%
1,500 playersBuilderMethuselahLateWhaleSplit whaleLockerRacerSellerLocker tides
The simulated launch rules (10% tides, keeper unregistered)−0.109−0.041−0.153−0.986−1.138+0.590−0.061−0.1021.4%
Tides of 5% (launched)−0.110−0.044−0.100−1.190−1.539−0.451−0.070−0.1020.7%
The team keeper registered, so it collects the pot (as v5 ran; a v6 keeper takes none)−0.109−0.036−0.153−0.997−1.155+0.590−0.019−0.1021.4%
Stake keeps 80% at each tide, not 87.5%−0.109−0.038−0.153−0.997−1.082+0.638−0.061−0.1021.4%
Reach 4−0.110−0.037−0.151−0.988−1.102+0.703−0.060−0.1021.4%
Reach 2−0.106−0.040−0.153−0.970−1.177+0.622−0.061−0.1021.4%
Siege ×2−0.119−0.044−0.157−0.976−1.152+0.613−0.060−0.1021.4%
Sell-back at 30% of the curve−0.099−0.050−0.154−1.175−1.065+0.389−0.046−0.1431.2%
A newcomer beside the carpet locker its first block

The locker lays a lattice of blocks 8 cells apart at launch so every empty cell is inside its buffer. Free cells and free 2 × 2 spots are where a newcomer could plant at the normal price (median, range); with none free, its cheapest block is a siege. Without the locker, 94.8% of 2 × 2 spots are free after 1 h at 15 players.

15 players, 20 seedsFree cells %Free 2 × 2 spots %Cheapest block, mNEARSiege block, mNEAR
1 h0.3 (0.0–1.8)0.2 (0.0–1.1)3.866.03
6 h25.6 (2.2–40.5)19.5 (1.3–32.3)3.725.64
day 132.3 (24.8–50.4)24.6 (18.3–41.6)3.625.33
day 758.8 (46.5–63.8)51.4 (39.1–57.0)3.896.15
150 players, 12 seedsFree cells %Free 2 × 2 spots %Cheapest block, mNEARSiege block, mNEAR
1 h2.5 (0.9–10.3)1.4 (0.4–6.5)3.715.61
6 h28.0 (16.6–36.1)20.5 (11.1–28.2)3.525.05
day 121.7 (15.3–28.3)15.2 (9.5–21.0)3.414.71
day 748.8 (39.5–60.6)41.5 (32.1–53.7)3.896.15

After the first hour at 15 players, 9 of 20 seeds had no free 2 × 2 spot at all, but a siege block is always legal, so no seed is ever without somewhere to plant.

A dish with no players, 30 days 4 runs
RunAgar after 30 days, PETRIVault, NEARWhat happened
Nobody at all, the team keeper advancing1,000,0000The keeper spent 3.18 NEAR of gas in 30 days.
Nobody at all, and nobody calls for 30 days1,000,0000One visit at day 30 skips 172,680 generations in a single Skip entry.
Only the five house strains, 1 NEAR each996,8800.27The house paid 5.39 NEAR; it is never fed, so no PETRI left the agar except what it bought.
Only the house, with no budget limit957,38329.22The house paid 75.59 NEAR, gas included; with nobody else to win it, the vault grew to 29.22.

From sim/out-v5/summary.txt. In these runs the simulator still wrote a tide entry with nobody to pay, which the launched contract skips. The scripted players follow fixed habits and do not adapt to prices, so the runs show how NEAR moves under each rule set, not how people would change their play.

Known limits

Where the design is weaker than it looks, or where you are trusting something other than the code. The full specification is in RULES.md.

It runs on testnet
This dish lives on NEAR testnet. PETRI there is a real token on a real chain, but testnet NEAR and PETRI have no market, and guests play with credit the site sponsors. The same contract runs with real NEAR on mainnet.
The lock is a plan until the key is gone
No method changes a running dish’s parameters, mints PETRI or edits the board. The one way to start over, relaunch, is private (only the contract account itself can call it), clears a v6 dish and refuses an account with no v6 dish and one that already runs v6.1. But petri-v6.testnet still has one full-access key that could deploy other code or relaunch. The team will delete it before judging; until then the full-access check fails on /verify and in the terminal.
The methuselah edge
In the simulator (sim/out-v5, run with 10% tides) a player planting one R-pentomino an hour was the only kind ahead in cash at 15 and 150 players: +0.02 and +0.14 NEAR median after a week, while builders, raiders and defenders lost 0.15 to 0.27. With 5% tides, as launched, the fix experiment put it at +0.29 at 150 players.
PETRI is paper until it is sold back
The agar buys back at half the curve's price, never more than the units' share of the vault, at most 10% of the vault between tides, and nothing before the first tide. That price holds for one seller at a time: all holders together could not exit at it.
A carpet locker can still earn at scale
Sieges keep the dish open, but a 1.5-NEAR lattice of blocks lost at 15 and 150 simulated players (−0.89 and −0.58 NEAR median) and won +0.59 at 1,500, with 10% tides. With 5% tides, as launched, the fix experiment put it at −1.21 and −0.45 NEAR at 150 and 1,500 players.
Early colonies have an edge
The agar is fullest at the start, so the first colonies are fed the most PETRI, and PETRI is cheapest in NEAR while the agar is full. On a sparse dish the agar releases only part of its ration, which narrows but does not remove the edge.
Ordering within a generation
Entries in the same generation apply in the order the chain executes them. An earlier planting can fill a cell a later one wanted, or turn it into a siege.
Large licensed patterns earn royalties, by design
A slide is a licence only from 12 captured cells, which stops the small common patterns, but whoever mints the first slide of a large pattern others plant (the pulsar, 48 cells; the Gosper gun, 36) collects 10% of every licensed planting of it: in the v6.1 simulator +0.11 NEAR a week at 150 players, down from +0.29. Only planters that choose the licence pay it, and they still come out ahead of planting without it (whales −1.97 with the farmer, −2.01 with none, −2.05 with no licence at all); the vault's totals hardly move with the royalty. The launch rules keep 12; 49 or no royalty would make the farmer lose about 0.16.
A full hot table makes newcomers wait
At most 10,000 colonies can play at once. Past that, a colony with no row in the hot table cannot plant until the next tide pays rows out; the simulator's busiest 30,000-colony dish never passed 2,390. Filling the table would take about 10,000 earning plantings an hour, roughly 50 NEAR an hour.
The house is a subsidy
The five strains are run by the team and buy every PETRI they plant with. They are never fed, win no tides, never sell PETRI back, can send PETRI only to other house accounts, and take no tide bounty or keeper pot, so what they pay in, about 1.1 NEAR a strain a week in the simulator, goes to the other players. On mainnet that is the team's real NEAR; on testnet it is sponsored credit.
Somebody has to advance it
The stored board moves only when a transaction touches it. Each call catches up at most 120 generations and stops at 110 TGas less what is still to be written; plantings are refused until the dish is current. Feed and tides for missed generations are worked out late, but a dish left alone for more than 480 generations skips the quiet stretch, and nothing is fed for the skipped generations.
Races for the pot and the bounty
The keeper pot goes to whoever's call first runs a generation, and a tide's bounty to whoever's call runs it, unless that caller is a house account or a keeper: then the pot waits for the next caller and the bounty stays in the vault. A simulated racer that only advanced lost 0.05 to 0.06 NEAR a week after gas in the v5 runs and 0.0055 in the v6.1 runs, where every call that runs a generation shares the pot; the bounty is capped at 0.001 NEAR a tide.
The simulator is a model
It estimates storage and gas instead of measuring them, and its players follow fixed habits. Its main runs predate three launched changes: they paid 10% tides (now 5%), paid guests' shares in NEAR their accounts could not move (now credit), and ran tides with nobody to pay (now skipped). They also predate v6, in which a keeper takes no pot and no bounty, and v6.1, which the simulator was rerun on (sim/out-v6.1).
Gas at scale is measured in a unit test
Each colony's numbers live in cold pages of 32 colonies and a hot table of the colonies that play now (at most 10,000), so a join costs the same however many colonies came before, and a catch-up costs what the playing colonies cost. The contract's gas tests scale the unit runtime's host calls to the real price per byte and add an estimate of the wasm, which the unit runtime does not charge: with 30,000 colonies, 1,500 of them playing, the largest call is 67.5 TGas; with a full table, 9,999 playing, 125.7, under the 150 TGas they assert and the 300 one transaction can buy. In the simulator's 30,000-colony dish no call passed 60 TGas.
Views come in pages
earnings and tide_winnings return at most 500 colonies a call, stakes 2,000, colonies and slides 500, the ledger 1,000 entries, and nft_tokens and nft_tokens_for_owner 10 slides, each drawn as an SVG. A reader pages through with from and limit.
The strains need a model to answer
Code proposes legal moves and forecasts them 240 generations ahead on a copy of the dish (as many as a two-second budget allows); a model picks one and writes the note, and at the council each tide window it offers and answers the house's pacts, which the contract enforces. Petri is integrated with both Claude Haiku (claude-haiku-5-5, within a fixed dollar budget) and NEAR AI Cloud (z-ai/glm-5.3-flash, used when Claude does not answer and NEAR AI has credits). When neither answers, the strains take their first proposal, and every move in the public log says which decided it.
Small rounding
Feed shares round down to a millionth of a PETRI and tide shares to a yoctoNEAR. The remainders stay in the agar and the vault.

Now plant something

Start a colony as a guest or with your own NEAR wallet, and put your first pattern on the dish. The rules above are the only ones there are.