Map-scale preview: show the pattern on a territory - #6
Merged
Conversation
OpenFront paints a pattern onto territory in absolute world coordinates, so what a player sees depends on where the territory sits on the map. The editor showed a 3x3 repeat of the bitmap, which cannot express that at all — patterns were being designed against a preview that did not model the thing they are for. tools/preview_prototype.py has verified the sampling rule since before the editor existed, and the suite has been running it on every commit without the app ever using it. It is ported now: floorMod and ofPrimaryAt, plus territoryMask, and a Map view that renders the pattern inside a territory shape at its real scale. Drag it and the pattern's phase moves, because the position is what decides which part of the pattern lands where. JS `%` is a remainder whose sign follows the dividend, so a naive `(x >> scale) % width` returns a negative index the moment the territory is dragged left of the origin, reading before the start of the bit array. That is the single likeliest way for this port to be wrong, so 661 of the 1,161 probes are at negative coordinates. Reintroducing the bare `%` fails 6 cases with the first disagreement at (-9,-9), so the suite is known to catch it rather than assumed to. tests/fixtures/sampler.json is the oracle: 56 patterns across all eight scales, each probed 1,161 times, generated against an independently written decoder. The committed corpus is 1,117 patterns at scale 0 and one or two at each of the rest — built for width, height and bit packing — so scale coverage is synthesised here. Nothing comes from the game's cosmetics.json; it is CC BY-SA 4.0 and not redistributed. Two things the port exposed: The map scale readout showed the slider position, so scale 3 read "3x" directly above a sentence saying "One pixel covers 8x8 map tiles". scale is an exponent; the readout is now the magnification. The brace-matching extractor had been copied into two suites and was about to be copied into a third, which is one edit from two suites disagreeing about what the editor's source says. It lives in tools/lib/extract.js now, and verify-codec.js uses it — 28 duplicated lines gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UCrKKTD2mwHx8Fm1EnJiQ3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of the v0.2.0 plan — OpenFront fidelity.
OpenFront paints a pattern onto territory in absolute world coordinates, so what a player sees depends on where the territory sits on the map. The editor showed a 3×3 repeat of the bitmap, which cannot express that — patterns were being designed against a preview that did not model the thing they are for.
tools/preview_prototype.pyhas verified the sampling rule since before the editor existed, and the suite has run it on every commit without the app ever using it. It is ported now, with a Map view that renders the pattern inside a territory shape at its real scale. Drag it and the pattern's phase moves with it.The trap, and proof the test catches it
JavaScript's
%is a remainder whose sign follows the dividend, so a naive(x >> scale) % widthreturns a negative index the moment the territory is dragged left of the origin — reading before the start of the bit array. That is the likeliest way for this port to be wrong, so 661 of the 1,161 probes are at negative coordinates.I reintroduced the bare
%to check the suite isn't vacuous. It failed 6 cases, first disagreement at(-9,-9). Driving the real app, a drag reaches world offset−48,−53and renders correctly.The oracle
tests/fixtures/sampler.json— 56 patterns across all eight scales, each probed 1,161 times, every expectation generated against an independently written decoder that unpacks bits a different way, so a self-consistent bug cannot hide.Scale coverage is synthesised: the committed corpus is 1,117 patterns at scale 0 and one or two at each of the rest, because it was built for width, height and bit packing. Nothing here comes from the game's
cosmetics.json— it is CC BY-SA 4.0 and deliberately not redistributed.Beyond per-probe agreement, the suite pins the property that makes this a map preview: a shift of one full scaled period must be invisible, and a shift of one world tile must not be. 15 of 28 structured patterns change under a one-tile shift; none change under a full period.
Two things the port exposed
scaleis an exponent; the readout is now the magnification.tools/lib/extract.js;verify-codec.jsuses it, 28 duplicated lines gone.Verification
./tools/verify-all.shgreen, now includingsampler oracleandeditor sampler vs oracle. Drove the real app: picked a duotone, set map scale, toggled Map, dragged into negative world space, and confirmed the territory renders the pattern clipped to its shape.🤖 Generated with Claude Code
https://claude.ai/code/session_01UCrKKTD2mwHx8Fm1EnJiQ3