HANTAI — build opposites-game boards from the Linguabase antonyms table ======================================================================= A plain-text method file for an LLM (or a person) to build from. Companion script: linguabase-hantai-boards.py (same method, runnable). Game: word tiles on a grid; the player swaps tiles until no two opposites are orthogonally adjacent. No timer. TABLES (CC0, from the Linguabase mirrors — huggingface.co/datasets/ linguabase/linguabase, zenodo DOI 10.5281/zenodo.20788428, kaggle): vocabulary.core.parquet word, core_rank (1 = most familiar; the core download cuts at the recommended 400,000-rank threshold) antonyms.core.parquet word, axis, opposites — opposites is a list of "term:strength" strings, strength 1-7; 1,596,686 axis rows. A word usually opposes along SEVERAL axes (mother -> father on parental gender, child on generation). STEP 1 — HARVEST MUTUAL PAIRS (the step that matters most) Candidate pair {a, b}: both single lowercase alphabetic words, 3-9 chars, core_rank <= 20,000, not stopwords, and b listed as a bare-word opposite of a with strength >= 6 on some axis. THEN REQUIRE MUTUALITY: a must also appear as a bare-word opposite in some row headed by b (any axis, any strength; match headwords case-insensitively). Why: one-way listings are the table's stretches. Specimen: the row hot [freshness/recency] lists old:6, but OLD's rows list only the phrase "hot off the press:4" — so hot/old is one-way and players would revolt at the pairing. Measured on the June 2026 release: 47,140 one-way-eligible pairs -> 21,105 mutual. Sampled casualties (people:one, know:think, maybe:yes, sun:night) are all stretches. Strength floor is required in ONE direction only — mutual listing is the semantic test; asymmetric ratings are normal sense dominance. STEP 2 — GROW BOARDS Build the undirected pair graph over the mutual pool. A board is a dense connected patch: start at a seed word, repeatedly add the neighbor that opposes the most words already on the board (small random jitter for variety), until the grid (3x3 up to 4x5) is full. Block near-duplicate roots (5+ shared prefix chars: rainy/raining). Rules: every tile must have >= 1 opposite on the board (no "free parking" — see step 3), most should have >= 2. Verify SOLVABILITY by backtracking search (place cell by cell, prune on adjacency; give the search a node budget — dense unsolvable boards are exponential). Ship a shuffled start with >= 3 clashes. Keep one found solution. A teaching board (board 1) is built sparse instead: a 2-partner hub plus disjoint pairs, 4-7 pairs total. STEP 3 — GATE BY SIMULATED DIFFICULTY (the reusable principle: before shipping a puzzle, simulate the dumbest policy that could win) Policy A (dumbest): swap a random clashing tile with a random calm tile; 300-move cap. Policy B (greedy): try all swaps, take the one minimizing clashes, random tie-break; a STALL is when no swap strictly improves. Our free-parking first build: A solved every board, median 4-7 moves, 99-100% within 20. Shipped boards: A hits the 300-move cap (under 4% solve within 20), B stalls 28-64% of trials yet still wins 36-72% — hard, but a thinking player has a fair path. Gate numbers: hard boards need A_median >= ~0.8 * cap, B stall >= 25-30%, B solve >= 35%. Teach board: A_median 3-14, stalls <= 15%. STEP 4 — PACK Enforce: no two shipped boards share more than 2 pairs. Measured supply at this quality bar: a greedy packer produced 68 boards before exhausting (1,200 consecutive rejects) — hard boards cluster in the same high-degree semantic neighborhoods (temperature, emotion, open/closed). The disjointness envelope says ~530 boards at ~40 pairs/board (~1,400 at 3x3), so 68 is the generator's floor, not the table's ceiling. PRESENTATION RULES THAT MATTER - Never color-code tiles by pair: players would match colors instead of meanings. Tiles stay neutral; color belongs to chrome. - Clashes must be visible where they happen (a spark between the two adjacent tiles) — that is how the game teaches itself. - No timers.