The claim, and why it is wrong
tools/trim-factorio-oracle.py:139-151 says this:
def collect_directions(doc_dir):
"""defines.direction is the authoritative answer to 'what number means east'.
Factorio 2.0 widened this from 8 to 16 values, which silently reinterpreted every
direction in every blueprint."""
...
return {v["name"]: v["order"] for v in define.get("values", [])}
runtime-api.json does not publish the numeric value of any define. The fixture's
directions table is built from a documentation ordering index, not from the
game's actual numbers.
Verified against the installed 2.1.14 file
Measured directly on
.../Factorio/factorio.app/Contents/doc-html/runtime-api.json, application_version
2.1.14:
- 0 of 1,408 define values carry a
value key. The only keys present on a
define value are name, order and description. There is no value field
anywhere in the file.
order is always a dense 0..n-1 index. Checked across all 137 define
tables in the file: every one has orders that are exactly range(len(values)).
Not one has a gap, a duplicate or a non-zero start.
- Values are stored alphabetically by name.
defines.direction is stored as
east, eastnortheast, eastsoutheast, ... So order exists to restore
declaration order for display, which is what a documentation index is for.
- The HTML docs do not publish values either.
doc-html/defines.html contains
no numeric assignments for defines.inventory or anything else.
So there is no shipped file, JSON or HTML, that answers "what number is east".
Why the fixture is still correct today
Factorio declares directions clockwise starting at north = 0, and there are
exactly 16 of them with no gaps. For an enum like that, declaration order and
runtime value are the same number. The committed fixture holds exactly 0 through
15 with north=0, east=4, south=8, west=12, which is right.
So this is not a live defect in output. Nothing is currently wrong in a
blueprint. It is a wrong method that currently produces a right answer.
Why it is still worth fixing
Because order provably cannot represent a non-sequential enum. It is a dense
0..n-1 index by construction, so any define whose real values have a gap, a
duplicate, or a start other than zero would be read wrong and nothing here would
notice. Directions happen to be the friendly case.
Because the docstring makes a claim the file does not support. It says
defines.direction is "the authoritative answer". The authority is the running
game. What we read is a documentation artifact that agrees with the game by
coincidence of declaration order. Anyone extending collect_directions to a second
define - which is the obvious next step, and something the shared oracle CLI
proposal explicitly wants - would inherit a method that looks proven and is not.
Because of what this constant is. Direction encoding is the exact thing that
silently broke in 2.0, when 8-way widened to 16-way and every blueprint direction
was reinterpreted. #77 exists because of it. The oracle was built so that constant
would never again be taken on trust - and it is the one value in the fixture that
is inferred rather than read.
How to fix it
Read the values from the running game rather than from the docs. A probe mod dumps
them directly:
local out = {}
for name, value in pairs(defines.direction) do out[name] = value end
helpers.write_file("defines-dump.json", helpers.table_to_json(out))
That is the same throwaway-mod technique already used in this repo to establish the
direction table, the mirror field and the Version bit layout - see 975e344 and
the notes in CLAUDE.md. The catch is that the mod was written, run and thrown away,
so there is nothing to re-run. Rebuilding it from the prose in CLAUDE.md is the
work here.
Two smaller changes go with it:
- Correct the docstring. Say what the source actually is and what it can and
cannot answer.
- Add a guard while the current method stands. If
collect_directions keeps
reading order, assert that the resulting values are contiguous from zero and
that the count matches what the planner expects. That turns a silent wrong
answer into a failed capture for any future define that is not sequential.
Relationship to the shared oracle work
This is the strongest single argument for the probe-mod capability described in
#82, and it stands on its own regardless of whether that tool gets built. Filed
separately so it does not get lost inside a larger issue.
While in this file, CLAUDE.md also says the capture pulls four sources and lists
data/changelog.txt as one of them. It pulls three. There is no changelog handling
anywhere in tools/. Worth correcting in the same pass.
The claim, and why it is wrong
tools/trim-factorio-oracle.py:139-151says this:runtime-api.jsondoes not publish the numeric value of any define. The fixture'sdirectionstable is built from a documentation ordering index, not from thegame's actual numbers.
Verified against the installed 2.1.14 file
Measured directly on
.../Factorio/factorio.app/Contents/doc-html/runtime-api.json,application_version2.1.14:
valuekey. The only keys present on adefine value are
name,orderanddescription. There is no value fieldanywhere in the file.
orderis always a dense0..n-1index. Checked across all 137 definetables in the file: every one has orders that are exactly
range(len(values)).Not one has a gap, a duplicate or a non-zero start.
defines.directionis stored aseast,eastnortheast,eastsoutheast, ... Soorderexists to restoredeclaration order for display, which is what a documentation index is for.
doc-html/defines.htmlcontainsno numeric assignments for
defines.inventoryor anything else.So there is no shipped file, JSON or HTML, that answers "what number is east".
Why the fixture is still correct today
Factorio declares directions clockwise starting at
north = 0, and there areexactly 16 of them with no gaps. For an enum like that, declaration order and
runtime value are the same number. The committed fixture holds exactly
0through15withnorth=0,east=4,south=8,west=12, which is right.So this is not a live defect in output. Nothing is currently wrong in a
blueprint. It is a wrong method that currently produces a right answer.
Why it is still worth fixing
Because
orderprovably cannot represent a non-sequential enum. It is a dense0..n-1index by construction, so any define whose real values have a gap, aduplicate, or a start other than zero would be read wrong and nothing here would
notice. Directions happen to be the friendly case.
Because the docstring makes a claim the file does not support. It says
defines.directionis "the authoritative answer". The authority is the runninggame. What we read is a documentation artifact that agrees with the game by
coincidence of declaration order. Anyone extending
collect_directionsto a seconddefine - which is the obvious next step, and something the shared oracle CLI
proposal explicitly wants - would inherit a method that looks proven and is not.
Because of what this constant is. Direction encoding is the exact thing that
silently broke in 2.0, when 8-way widened to 16-way and every blueprint direction
was reinterpreted. #77 exists because of it. The oracle was built so that constant
would never again be taken on trust - and it is the one value in the fixture that
is inferred rather than read.
How to fix it
Read the values from the running game rather than from the docs. A probe mod dumps
them directly:
That is the same throwaway-mod technique already used in this repo to establish the
direction table, the
mirrorfield and theVersionbit layout - see 975e344 andthe notes in CLAUDE.md. The catch is that the mod was written, run and thrown away,
so there is nothing to re-run. Rebuilding it from the prose in CLAUDE.md is the
work here.
Two smaller changes go with it:
cannot answer.
collect_directionskeepsreading
order, assert that the resulting values are contiguous from zero andthat the count matches what the planner expects. That turns a silent wrong
answer into a failed capture for any future define that is not sequential.
Relationship to the shared oracle work
This is the strongest single argument for the probe-mod capability described in
#82, and it stands on its own regardless of whether that tool gets built. Filed
separately so it does not get lost inside a larger issue.
While in this file,
CLAUDE.mdalso says the capture pulls four sources and listsdata/changelog.txtas one of them. It pulls three. There is no changelog handlinganywhere in
tools/. Worth correcting in the same pass.