World space & grids

Grid and direction

grid-and-direction-1

Tests included

This contract defines the behaviour of square grids: a tile map, a chess board, or a dungeon map.

It decides how your grid is numbered, which cells are neighbours, how distance works, and how a rule breaks a tie.

Use in your game

Opens the authoring tool with this contract added and its questions unanswered. Or download the ZIP and add it later.

What is in the ZIP

The ZIP holds the contract and its acceptance tests. In the authoring tool, choose Add contract and pick this ZIP. If you keep your design as files, put them in contracts/ and fill in the answers there.

Questions

Up to 10 questions. Some appear only after earlier answers.

  1. Where is this grid's first cell, and which way do its row and column numbers grow?
  2. When you write a cell with two numbers, does the row or column come first?
  3. Do the first row and column use zero or one?
  4. A point lies exactly on the line between two cells. Which cell owns it?
  5. When your rules say nearest or within some distance, how do they measure between cells?
  6. From one cell, which other cells can a thing reach in one step?
  7. When a rule says two cells are next to each other, do corners count?
  8. In what order does an authored layout list its cells?
  9. A rule rates two cells equally and must pick one. How does it decide?
  10. When your rules turn a facing by an amount, which way does the amount go on the grid?

Try the answers

Pick answers to see which rules and tests apply. Nothing is saved here: the ZIP and the authoring tool start unanswered.

Where is this grid's first cell, and which way do its row and column numbers grow?

Choices for Where is this grid's first cell, and which way do its row and column numbers grow?
The first cell is the top-left corner. Column numbers grow right, and row numbers grow down.
The first cell is the bottom-left corner. Column numbers grow right, and row numbers grow up.
There is no first cell or corner. The grid continues through negative and positive numbers. Columns grow right, and rows grow down from the cell your game calls zero.
There is no first cell or corner. The grid continues through negative and positive numbers. Columns grow right, and rows grow up from the cell your game calls zero.
Why this is asked

Every later rule needs one shared reading of row and column numbers. This contract only carries columns that grow right; state a left-growing grid in your own prose.

When you write a cell with two numbers, does the row or column come first?

Choices for When you write a cell with two numbers, does the row or column come first?
The column comes first. The pair (3, 5) means column 3, row 5.
The row comes first. The pair (3, 5) means row 3, column 5.
The game never names a cell with a pair of numbers. It uses a layout, cell contents, or another name instead.
Why this is asked

Swapping the two numbers turns rows into columns. A square grid can hide that mistake, so the order must be clear.

Do the first row and column use zero or one?

Asked when
Origin and axes is Top left or Bottom left.
Choices for Do the first row and column use zero or one?
The first row and column are numbered zero. A ten-cell row runs from zero through nine.
The first row and column are numbered one. A ten-cell row runs from one through ten.
Why this is asked

Starting at zero or one changes every written cell address. Naming it prevents an off-by-one shift between the design and the build.

A point lies exactly on the line between two cells. Which cell owns it?

Choices for A point lies exactly on the line between two cells. Which cell owns it?
The cell with the larger number owns the line. The line where cell five ends and cell six begins belongs to cell six, on either side of zero.

Divide the position by cell-size and round down, then add one when counting-starts-at is one. A boundary position belongs to the cell with the larger coordinate.

The cell farther from zero owns the line. The zero cell reaches one cell-size to each side, so it is twice as wide as the others.

Divide the position by cell-size and truncate toward zero, then add one when counting-starts-at is one. Coordinate zero spans one cell-size on each side.

Whole numbers mark cell centres. A point halfway between two centres belongs to the cell with the larger number.

Cell coordinates name centres. Divide the position by cell-size and round to the nearest whole coordinate, taking an exact half toward the larger coordinate, then add one when counting-starts-at is one.

Your rules only use whole cells, never positions between them. No boundary choice is needed.
Why this is asked

A boundary point needs one owner. Different rounding rules can place the same point in different cells, especially beside zero.

When your rules say nearest or within some distance, how do they measure between cells?

Choices for When your rules say nearest or within some distance, how do they measure between cells?
Add the steps across and down the grid (Manhattan). A cell two across and one up is three steps away.
Count the larger of the across and down steps (Chebyshev). A cell two across and one up is two steps away.
Straight steps cost one, and diagonal steps cost the square root of two (octile). The distance is the cheapest mix of those steps. Your game's comparison rule decides when two distances count as equal.

For absolute coordinate differences dx and dy, multiply the smaller difference by the square root of two minus one (about 0.414), then add the result to the larger difference. Equal means equal at whatever precision this game compares its distances with. For straight-line and octile distance, the adoption must state that comparison rule in the distance test's verification scope.

Measure a straight line between the cell centres (Euclidean). Use position units when positions exist; otherwise use cells. Your game's comparison rule decides when two distances count as equal.

Equal means equal at whatever precision this game compares its distances with. For straight-line and octile distance, the adoption must state that comparison rule in the distance test's verification scope.

No rule measures distance between cells. Rules may still use neighbours, named shapes, or links.
Why this is asked

Games often use several distance rules. This answer only controls what your written rules mean by nearest or within a distance.

From one cell, which other cells can a thing reach in one step?

Choices for From one cell, which other cells can a thing reach in one step?
Only the four cells sharing an edge are one step away. A diagonal cell cannot be reached in one step.
All eight surrounding cells are one step away. A thing may move across an edge or diagonally across a corner.
Nothing moves one cell at a time. Things are placed directly or move freely while the grid only reads their final cell.
Why this is asked

Movement neighbours do not follow automatically from distance or effect range. A game can use different cells for each.

When a rule says two cells are next to each other, do corners count?

Choices for When a rule says two cells are next to each other, do corners count?
Only cells sharing an edge count as neighbours. Two cells touching only at a corner are not next to each other.
All eight surrounding cells count as neighbours. Cells touching only at a corner are still next to each other.
No rule uses next to by itself. Each rule names the cells it means, or no rule asks whether cells are neighbours.
Why this is asked

Movement and effects can count neighbours differently. This answer keeps words such as next to from changing meaning between rules.

In what order does an authored layout list its cells?

Choices for In what order does an authored layout list its cells?
List every cell in one row before starting the next row. Start with the smallest row and column numbers. A text map with one line per row already uses this order.
List every cell in one column before starting the next column. Start with the smallest row and column numbers.
List cells inside blocks such as chunks, regions, or screens. Your game's prose states block size, block order, and the order inside each block.
No authored layout lists the grid's cells. No order is needed for the material designers write and read.
Why this is asked

Drawing, updates, and save files may use different orders. This answer covers only layouts designers write and read.

A rule rates two cells equally and must pick one. How does it decide?

Choices for A rule rates two cells equally and must pick one. How does it decide?
The cell with the smaller column number wins. Between a cell in column 2 and a cell in column 4, the column-2 cell wins and the column-4 cell loses. If columns match, the smaller row number wins.
The cell with the smaller row number wins. Between a cell in row 2 and a cell in row 4, the row-2 cell wins and the row-4 cell loses. If rows match, the smaller column number wins.
Walk the grid-fixed direction words in their chosen order. The first direction that points to a tied neighbour wins. Use another answer when tied cells are not neighbours.
The candidate that arrived first wins. Your game names whether arrival means creation, placement, storage, or entering play. The same run repeats the choice, but save and reload follow your persistence rules. The validator (the checking tool) cannot check this; a reviewer does.
The candidate kind listed first in your game's priority order wins. Cell position never decides.
Either candidate may win, and players must not depend on which one. Replaying the same run repeats the choice, but loading a save may not.
Draw one candidate from a random stream declared by your game. The same run and replay draw the same candidate. The validator cannot check this; a reviewer does.
The player chooses the candidate. If the game cannot ask, the rule does nothing instead of guessing. The validator cannot check this; a reviewer does.
No rule ever chooses one of two equal candidates. The situation cannot happen, or the rule affects every tied candidate.
Why this is asked

Equal choices are common and rarely written down. A fixed answer stops two builds from choosing different cells.

When your rules turn a facing by an amount, which way does the amount go on the grid?

Choices for When your rules turn a facing by an amount, which way does the amount go on the grid?
A positive turn goes clockwise on the grid. A rotated view may show it differently, but the grid rule stays the same.
A positive turn goes counter-clockwise on the grid. A rotated view may show it differently, but the grid rule stays the same.
No rule turns a facing by an amount. A piece may still snap directly toward movement or a target.
Why this is asked

Axis direction does not decide turn direction. Naming clockwise or counter-clockwise prevents equivalent formulas from reading as opposite rules.

Numbers and rules1 number, 1 rule

Numbers

Each setting takes a number, or a reference to a named value in your tuning. Stay inside any range shown.

Cell size

cell-size

The length of one cell in your position units. For centre-based cells, measure from one centre to the next. Use a positive size when rules read positions. Use zero when they only read whole cells. Changing this number changes which cell holds a position.

Rules

  • cell-size >= 0
Lists1 list

Some settings are lists of rows.

Directions

directions

List every direction word your game uses. Each row says whether it follows the grid or a piece. A grid direction also says where it points. An empty list means the game names no directions. If ties use this order, list every grid-fixed neighbour that can tie. The validator cannot check this; a reviewer does.

Each row is: id, frame, points, order.

Every field
FieldKindWhen it appearsMeaning
id string Required The direction word your game uses, such as north, forward, or starboard. Write it in lowercase with hyphens between words.
frame choice: grid, piece Required Whether the direction follows the grid or a piece. A grid direction always points the same way: north stays north. A piece direction changes when that piece turns: forward, left, and behind turn with it.
points choice: up, down, left, right, up-left, up-right, down-left, down-right Present when row frame is Grid. Where this grid-fixed direction points on the grid. Omit it for a direction that follows a piece. This does not decide whether movement is allowed that way.
order integer Present when Tie break between cells is Direction order and row frame is Grid. This direction's place in the tie-breaking walk. One is tried first. Give each grid-fixed direction a different number. Use it only when ties follow direction order.

For builders

Exact mechanism wording and 22 pack tests

Exact mechanism wording

The mechanism is one grid of equal square cells. A row runs across it, and a column runs down it. When a game names a cell with two whole numbers, coordinate-order says which one comes first; a layout may name cells by their contents instead. The grid may be a bounded rectangle with a first cell in one corner, or run on in every direction with signed numbers and no first cell; the first question says which.

The grid's own frame. Every answer below is read against the grid as this package declares it: the layout your content writes out, or your own chapter's sentence about which way the numbers grow. Up, down, left and right mean those directions on the declared grid. On a bounded grid where content writes the grid out row by row, the first written row is nearest the declared origin corner: the top row for top-left, and the bottom row for bottom-left. These directions never follow the finished picture, which a build may draw any way its presentation chapter allows. A Delegated view can never change a Fixed answer.

Where a game also has positions — things resting between cells rather than on them — zero is the same place for cells and for positions, and where a cell-ownership option makes the cell at zero a different width, that option says so. Two neighbouring cells share a line, and cell-ownership says which cell the line belongs to. Every conversion below divides by the cell size and, where the grid counts from 1, adds 1. Each cell-ownership option that uses positions states how position zero and shared lines are treated.

Several nearby decisions are deliberately not here — the grid's edge, sharing a cell, corner-cutting, pathfinding, a third axis, cells that are not squares, whether a sweep sees its own changes. The note at the end says where each lives.

Verification pack

sha256:b17529b6bce460ee83f7c460f2e73c39d5c32051637613867e42ef85b6e0996a

The format calls an adoption with its matching pack Checked: the tests travel with it, but a game has not necessarily passed them. Without the pack the adoption is Promised: the builder still owes the chosen behavior.

22 pack tests

Placeholders are filled from the adoption's answers, values, rows, and verification inputs.

the numbers grow one way

axes-grow

scenarioonce

Applies for every adoption

In Instance the two numbers grow Bind growth phrase, one per cell. The layout this is read against is the one this package declares, not the finished picture: a build may draw the grid any way its presentation chapter allows and still has to number it this way.

Given

Instance as this package lays it out, with at least two rows and at least two columns

When
  • a cell is located in the layout
  • the cells one step from it across and down are located
Then
  • the numbers grow Bind growth phrase
  • moving one cell that way raises exactly one of the two numbers by one and lowers neither
  • moving one cell the opposite way lowers exactly one of them by one
Diagnostics
  • Instance-cell-addresses
  • Instance-declared-layout
the grid has a first cell, in one named corner

the-first-cell-is-in-one-corner

scenarioonce

Applies when Origin and axes is Top left or Bottom left.

Instance is a bounded rectangle whose first cell — the one whose two numbers are both smallest — is Bind corner phrase. A build that numbers from the opposite corner fails this test even when every layout still loads.

Given

Instance as this package lays it out

When
  • the cell whose two numbers are both the smallest on the grid is located in the layout
Then
  • that cell is Bind corner phrase
  • no other corner of Instance holds a smaller pair of numbers
  • the grid is bounded: every cell of it lies inside the declared number of rows and columns
Diagnostics
  • Instance-cell-addresses
  • Instance-declared-layout
the grid runs on in every direction

the-grid-has-no-first-cell

scenarioonce

Applies when Origin and axes is Unbounded right and down or Unbounded right and up.

Instance has no first cell. Its numbers are signed and it runs on in every direction, so a cell at a negative number is as ordinary as any other and no rule may assume a corner to count from. Six of thirteen externally surveyed grids are this shape, including two of the four format specifications, which is why it is an answer here rather than an omission.

Given

Instance and the cell this package puts at zero on both axes

When
  • cells are addressed on every side of that cell, including at negative numbers on each axis
  • a rule of this game reads or writes one of those cells
Then
  • every one of those cells is a legal address and is handled the same way as any other
  • no rule of this game assumes a first cell, a last cell, or a corner
  • nothing shifts the numbers to make them positive before a rule of this game reads them
Diagnostics
  • Instance-cell-addresses
  • Instance-negative-coordinate-trace
a written pair names the cell this package means

coordinate-reading

scenarioonce

Applies when Coordinate order is Column first or Row first.

In Instance, Bind pair phrase, and Bind start phrase. The test asks for a grid whose rows and columns differ in number on purpose: on a square grid a build that reads the pair backwards passes every test anyone would think to write, and ships transposed. One surveyed game numbers its authored map files from one and its engine from zero, and records that nowhere but a source comment. The numbers this test is about are the ones this package's own material writes.

Given

Instance with a different number of rows and columns, so that reading a pair the wrong way round cannot land on a real cell by luck, or a stated reason why no such grid exists in this game

When
  • the build resolves a cell that this package's own material writes as a pair of numbers
Then
  • Bind pair phrase
  • Bind start phrase
  • the cell the build resolves is the cell this package's material means
  • the same pair with its two numbers swapped resolves to a different cell, or to no cell at all
Diagnostics
  • Instance-resolved-cell
  • Instance-source-reference
every position belongs to exactly one cell

every-position-has-one-cell

generalonce

Applies when Cell ownership is Next cell along or Truncate toward zero or Cell centres are whole numbers.

Within this adoption's verification scope — Inputs scope — every position of Instance lands in exactly one cell, never in two and never in none, and the cell is found by Bind conversion phrase. Converting back and forth closes the loop. The scope and seeds are this game's, supplied through this adoption's verification inputs; the check and its oracle are the contract's. Rounding down and cutting the fraction off agree everywhere the numbers are positive and part company on the other side of zero, which is why the scope should reach both sides wherever this game has them.

Diagnostics
  • Instance-position-to-cell-trace
  • first-position-owned-twice
Holds

the position belongs to exactly one cell of Instance, found by Bind conversion phrase; and converting that cell back to a position inside it and converting again returns the same cell

Seeds

Inputs seeds

Scope

Inputs scope

a position on a shared line belongs to one cell

boundary-belongs-to-one-cell

scenarioonce

Applies when Cell ownership is Next cell along or Truncate toward zero or Cell centres are whole numbers.

In Instance, a position exactly on the line between cells 5 and 6 is in Bind positive case phrase, and a position on a line below zero is in Bind negative case phrase. Real cell numbers are named here on purpose: this is the decision in the definition whose answers are easiest to state backwards, so the test states the winning one as a worked case rather than as a label. Cells 5 and 6 exist whether this grid counts from 0 or from 1, and where counting starts at 1 the conversion adds its one step and this case is unchanged. The second clause asks about positions below zero rather than about cells at negative numbers, and the difference is not pedantry: a bounded board numbered from zero has no negative cells, yet where the cell numbers name centres the outer half-cell band of that same board sits at negative positions — which is exactly where two of the three conversions part company. Where no rule of this game ever reads a position below zero on either axis, the clause has nothing to check. The last clause is worth reading twice: one answer, everywhere in the build, rather than one answer per system that happens to ask.

Given

the cells numbered 5 and 6 on one axis of Instance, and any position your rules read that lies below zero on either axis

When
  • a position is placed exactly on the line between cells 5 and 6
  • a position below zero is placed exactly on a line between two cells
  • a position is placed exactly where four cells meet
Then
  • the position between cells 5 and 6 is in Bind positive case phrase
  • wherever a position your rules read lies below zero, the position on the line there is in Bind negative case phrase
  • neither of those positions is in any other cell
  • the position where four cells meet is in the single cell picked by applying that same rule on both axes at once
  • every rule in the build that asks which cell any of those positions is in gets the same answer
Diagnostics
  • Instance-boundary-owner-report
distance between two cells is measured one way

distance-is-measured

generalonce

Applies when Distance metric is No diagonals or Diagonals count the same or Octile or Straight line.

Where a rule of Instance says nearest, in range, or within, the distance it means is Bind metric phrase. It is zero from a cell to itself, it does not depend on which cell is asked about first, and — the clause that matters most — every such rule returns the same number for the same pair. One worked case pins the arithmetic where a near-enough value would pass unnoticed: measured from one cell, Bind worked case phrase. Seven of nine externally surveyed games measure distance more than one way, and one carries five measures at once. This test does not forbid that: a route planner's own estimate is craft and is outside Inputs scope. What it forbids is two rules telling a player two different things about the same two cells.

Diagnostics
  • Instance-distance-trace
  • first-disagreeing-rule
Holds

the distance the rule uses between the two cells is Bind metric phrase; the distance from a cell to itself is zero; it is the same whichever cell is asked about first; every rule in Inputs scope returns the same number for the same pair; and the worked case holds — measured from one cell, Bind worked case phrase

Seeds

Inputs seeds

Scope

Inputs scope

two distances count as equal by a declared rule

equal-distance-is-decided

scenarioonce

Applies when Distance metric is Straight line or Octile.

Instance measures distance with a rule that does not come out in whole cells, so two distances being the same is itself a decision, and this game declares how: Inputs scope That rule decides which pairs reach the tie-break question and which are settled before it, and it is the only comparison the build may use. Asking for it out loud is worth one line of an adoption. In a blind two-build experiment on this definition, one builder met exactly this gap, invented a tolerance of sixteen times the smallest representable step, got the right answer, and did not record the decision — the one number in that build the package had not supplied, sitting directly under a scored check.

Given
  • the rule this game declares for deciding that two distances are the same: Inputs scope
  • two candidates whose distances from one cell are the same under that rule, and two more whose distances that rule tells apart
When
  • a rule of this game ranks each pair by distance
  • the same two pairs are ranked again with the two distances worked out in the opposite order
Then
  • the first pair reaches the tie-break and the second does not
  • the rule supplied in this adoption's verification scope is the only comparison used: no other tolerance, rounding or nearly-equal test appears anywhere in the build
  • both rankings come out the same, whichever order the two distances were worked out in
Diagnostics
  • Instance-distance-trace
  • Instance-tie-break-report
one step reaches exactly the neighbouring cells

one-step-moves

generalonce

Applies when Adjacency for movement is Four neighbours or Eight neighbours.

From any cell of Instance, one step reaches exactly Bind movement neighbours phrase, with nothing standing in the way. What happens when a step would leave the grid, and whether something in the way blocks it, are settled elsewhere in this package; this test fixes only which cells a step can reach at all.

Diagnostics
  • Instance-reachable-in-one-step
  • first-unexpected-destination
Holds

of the cells on the grid, the ones a thing can move to from this cell in one step, with nothing standing in the way, are exactly Bind movement neighbours phrase — no more and no fewer

Seeds

Inputs seeds

Scope

Inputs scope

next to means the same cells in every rule

next-to-means

generalonce

Applies when Adjacency for effects is Four neighbours or Eight neighbours.

Wherever a rule of Instance says one cell is next to another, it means Bind effect neighbours phrase — and it means the same thing in every rule that says it. This is asked apart from movement because games answer the two differently, sometimes without noticing: one surveyed game plans routes over four neighbours while targeting by straight line, and one engine hands back four surrounding cells while its own direction list carries sixteen.

Diagnostics
  • Instance-neighbour-set-per-rule
  • first-disagreeing-rule
Holds

wherever a rule of this game treats one cell as next to another, the cells it means are exactly Bind effect neighbours phrase, and the answer is the same in every such rule

Seeds

Inputs seeds

Scope

Inputs scope

this package's own material lists every cell once

authored-order-lists-every-cell

generalonce

Applies when Enumeration order is Rows then columns or Columns then rows or Block tiled.

An authored layout of Instance lists every cell exactly once, Bind order phrase, and reading that layout back gives the same cells in the same places. This does not set save-file order, drawing order, update order, or the order in which rules visit cells. Naming the authored order stops a rule from quietly depending on one of those other orders.

Scope

an authored layout of Instance, with every cell distinguishable from every other, read from the first cell to the last as designers write it

Holds

the material lists every cell of Instance exactly once, Bind order phrase, and a board written out and read back arrives cell for cell the same

Diagnostics
  • Instance-authored-order-sequence
  • first-cell-out-of-order
  • cells-listed-twice-or-never
the blocks this material is written in are declared

block-layout-is-declared

scenarioonce

Applies when Enumeration order is Block tiled.

Instance is written in blocks, so three things have to be readable before the material can be read at all: how big a block is, what order the blocks come in, and what order the cells inside a block come in. They are set out at Inputs scope, and this test reads the material against that place. The three worlds in the external tally that store their grids this way are all too large to hold at once, and none of them states these three things in an authored artifact. The pointer is what this contract can carry; following it is a reviewer's job.

Given

an authored layout of Instance, and the block size and the two orders as Inputs scope sets them out

When
  • the material is read back cell by cell
Then
  • the blocks come in the order that place sets out, and the cells inside each block come in the order it sets out
  • every block holds the number of cells that place states, apart from any partial block it also describes
  • reading the same material twice gives the same sequence
Diagnostics
  • Instance-authored-order-sequence
  • Instance-block-boundaries
a tie between two cells settles the same way every time

tie-break-settles

scenarioonce

Applies when Tie break between cells is Lower column wins or Lower row wins or Direction order or Named priority list.

When a rule of Instance must pick between two candidates it ranks equally, it picks Bind tie phrase. The adoption demonstrates that answer with this worked case: Inputs scope. The test repeats the case after reversing creation and drawing order. A choice that changed would be a different answer to this question.

Given

a rule of this game that must pick one cell, and the worked pair of equally ranked candidates described here: Inputs scope

When
  • the rule runs
  • the same situation is set up again, with the two candidates created in the opposite order and drawn in the opposite order
Then
  • the rule picks Bind tie phrase
  • it picks the same candidate both times
  • the order the candidates were created in, the order they are drawn in, where the pointer is, and how the animation runs change nothing
Diagnostics
  • Instance-tie-break-report
  • Instance-candidate-set
a tie between two cells goes to whichever came first

tie-break-follows-arrival

scenarioonce

Applies when Tie break between cells is Arrival order.

A tie in Instance goes to whichever candidate came first, by the moment Inputs scope names — one moment, chosen and written down, rather than whichever of created, placed and stored happens to be handy at the call site. This is the plurality answer in the wild: five of nine externally surveyed games settle ties this way. The test holds a build to the part it can be held to — a run replayed from a fresh start makes the same choice. Whether these ranks survive a save and reload is this game's own persistence rule, stated where that pointer leads, and this contract records the pointer rather than checking what it says.

Given

a rule of this game that must pick one cell, and two candidates the rule ranks equally, one of which came first by the moment Inputs scope names

When
  • the rule runs
  • the same run is played again from a fresh start with the same inputs
Then
  • the rule picks the candidate that came first by that moment, and not by any other moment in the two candidates' histories
  • the replayed run picks the same candidate, because it builds the two candidates in the same order
  • nothing about where the candidates sit on the grid changes the choice
Diagnostics
  • Instance-tie-break-report
  • Instance-arrival-order-log
a tie between two cells comes out the same way in a replay

tie-break-is-arbitrary

scenarioonce

Applies when Tie break between cells is Deliberately arbitrary.

Instance promises no order between two candidates it ranks equally: the choice may come out either way. That is a decision rather than a shrug — two surveyed sources choose it on purpose, one of them deliberately mixing the choices so the leftmost candidate is not always favoured. This test checks only what a build can be held to: one run, replayed from a fresh start with the same inputs, picks the same candidate. The design's real claim — that nothing a player sees depends on which one was taken — is recorded in the answer itself and cannot be tested here, because nothing can rerun a moment with the tie settled the other way. Nothing further is promised either: a save and reload may choose differently.

Given

a rule of this game that must pick one cell, and two candidates the rule ranks equally

When
  • the rule runs
  • the same run is played again from a fresh start with the same inputs
Then
  • one of the two candidates is picked, and the run carries on
  • the replayed run picks the same candidate
  • no rule of this game reports which candidate was picked as a promise a player or another rule may rely on
Diagnostics
  • Instance-tie-break-report
  • Instance-tie-occurrence-log
a tie between two cells is drawn from a declared stream

tie-break-is-drawn

scenarioonce

Applies when Tie break between cells is Random from a declared seed.

A tie between two candidates in Instance is drawn at random from a stream this game declares, so the same seed and the same inputs pick the same candidate every time. Random here means reproducible: a draw from an undeclared source would make two faithful builds of this spec disagree, which is what a declared stream prevents.

Given

a rule of this game that must pick one cell, two candidates the rule ranks equally, and a run started from a named seed

When
  • the rule runs
  • the same run is replayed from the same seed with the same inputs
  • the same situation is reached in a run started from a different seed
Then
  • the candidate picked is drawn from the stream this game declares for it, and from no other source of randomness
  • the replay picks the same candidate
  • the draw consumes from that stream exactly as this game's own determinism rules say it does
Diagnostics
  • Instance-tie-break-report
  • Instance-stream-consumption-log
a tie between two cells is put to the player

tie-break-asks-the-player

scenarioonce

Applies when Tie break between cells is Player chooses.

Instance does not settle a tie between two equally ranked candidates by itself: the player is asked. Where a rule cannot ask — an automatic step, a replay, a resolution with nobody watching — it does not guess. It does not run, and nothing changes.

Given

a rule of this game that must pick one cell, and two candidates the rule ranks equally

When
  • the rule runs and the player can be asked
  • the rule runs where the player cannot be asked
Then
  • in the first case the player is asked which candidate they mean, and the game picks neither on its own
  • in the second case the rule does not run and nothing about the game state changes
  • no candidate is ever picked because of the order things were created in, the order they are drawn in, or where the pointer is
Diagnostics
  • Instance-tie-break-prompt-log
  • Instance-state-before-after
no rule ever faces a tie between two cells

no-tie-ever-arises

generalonce

Applies when Tie break between cells is Not applicable.

Instance answers the tie-break question with not-applicable, and this is that answer checked rather than assumed: across Inputs scope, no rule ever has to choose between two candidates it ranks equally. Where a rule does meet a tie, it affects both alike and picks neither. Three corpus packages state exactly this claim in their own prose, and all nine externally surveyed games face the tie instead. It has a real failure mode — a rule quietly taking whichever candidate happened to be first in some list — and that is what this test looks for.

Diagnostics
  • Instance-tie-occurrence-log
  • first-unresolved-tie
Holds

no rule of this game reaches a point where two candidates are ranked equally and one of them has to be chosen: either the situation cannot arise, or the rule affects every tied candidate alike

Seeds

Inputs seeds

Scope

Inputs scope

a positive turn goes one way

a-positive-turn-goes

scenarioonce

Applies when Turn direction is Clockwise or Counter clockwise.

In Instance, a positive turn moves a facing Bind turn phrase on the declared grid, and turning back by the same amount returns the facing exactly. Naming the turn on the grid is deliberate: two corpus packages describe this same turn in opposite words, one counting from an axis and one naming the clock, and a reader has to do arithmetic to find out they agree.

Given

something standing on Instance that has a facing, with that facing recorded

When
  • it turns by a positive amount
  • it then turns by the same amount the other way
Then
  • the first turn moves its facing Bind turn phrase on the grid as this package lays it out
  • the second turn brings the facing back exactly to where it started
  • every rule of this game that turns something turns it the same way for a positive amount
Diagnostics
  • Instance-facing-before-after
  • Instance-turn-log
Row.id points Bind points phrase

grid-direction-points

scenarioper directions row

Applies when row frame is Grid.

In Instance, the word Row.id means the direction Bind points phrase. It is fixed to the grid: it points the same way whoever uses it, and it never follows anything's facing. Naming it says nothing about whether anything may move that way — the movement question decides that, and a game whose pieces move to four neighbours may still name a diagonal for an effect or a line of sight. Writing the word down here is what stops a second document in this package using it for a different direction. One surveyed format ships eight named compass directions and never says where any of them points.

Given

a cell of Instance with a cell on every side of it

When
  • a rule of this game moves something, points something, or reads a cell Row.id of that cell
Then
  • the cell it uses is the one Bind points phrase
  • the word Row.id means that same direction in every rule of this package and never another
  • the direction does not change with whatever is using it
Diagnostics
  • Instance-direction-resolution
  • Instance-cell-addresses
Row.id takes place Row.order in the direction walk

direction-walk-order

scenarioper directions row

Applies when Tie break between cells is Direction order and row frame is Grid.

When Instance settles a tie by walking its directions, Row.id — the direction Bind points phrase — is tried at place Row.order. The number is on the row so that the walk is visible here rather than inferred from the order the rows happen to sit in.

Given

a rule of this game settling a tie by walking the directions, and a tied candidate lying Bind points phrase from whatever is choosing

When
  • the walk runs
Then
  • Row.id is tried at place Row.order in the walk, after every direction with a smaller number and before every direction with a larger one
  • the candidate lying that way is taken exactly when no direction tried earlier holds a tied candidate
  • the walk runs in this order every time, whatever built the situation up
Diagnostics
  • Instance-tie-break-report
  • Instance-direction-walk-trace
Row.id is read from the facing of whatever uses it

piece-direction-follows-facing

scenarioper directions row

Applies when row frame is Piece.

In Instance, the word Row.id is read from the facing of whatever uses it, so it points somewhere else after that thing turns, and it can mean two different directions for two things standing on the same cell. That is the whole difference from a word fixed to the grid, and it is worth stating in a package that uses both kinds.

Given

a thing standing on a cell of Instance, with a facing and a cell on every side of it

When
  • a rule of this game moves it, points it, or reads a cell Row.id of it
  • the thing turns, and the same rule runs again
Then
  • the direction the word Row.id names is read from that thing's own facing, not from the grid
  • after the turn, Row.id names a different direction on the grid, turned by exactly as much as the facing was
  • two things with different facings, standing on the same cell, resolve Row.id differently
Diagnostics
  • Instance-direction-resolution
  • Instance-facing-before-after

Use this contract in your game ↑