Skip to content

JasperBlank/1DChess

Repository files navigation

1D Chess — Full State Graph

A solver and interactive 3D visualization of every legal position reachable from the starting position of rowan441's 1D chess variant: an 8-square board with King, Knight, and Rook per side.

Live viewers:


The game

rowan441's 1D chess places the White king, knight, and rook on squares 0–2 and their Black counterparts on squares 5–7 of a 1×8 board.

  • King moves one square in either direction.
  • Knight jumps exactly two squares in either direction, over intervening pieces.
  • Rook slides any number of squares until blocked.

Mate, stalemate, insufficient material (lone kings), and threefold repetition end the game. There are no pawns, no promotion, no castling.

The state space is small enough that full retrograde analysis is instantaneous, yet the interplay between the three asymmetric pieces — pins along the single file, knight forks, king tempo — is rich enough that the optimal line is far from obvious.

White has a forced win from the start.

What the graph shows

Starting from KNR..rnk and enumerating every legal move (avoiding only positions that are self-check for the moving side), the reachable state space contains 1,237 unique (position, side-to-move) tuples connected by 2,672 directed edges. Each state is solved via fixed-point retrograde analysis:

  • 303 are wins for White with perfect play
  • 331 are wins for Black
  • 603 are draws (stalemate, insufficient material, or forced repetition)

In the visualization, internal nodes are colored by their solved value: blue (White wins), red (Black wins), grey (draw). Terminal positions override this: filled white for checkmates where White delivers mate, black-with-white-ring where Black does, yellow for stalemate or insufficient material.

Clicking a node highlights every position reachable downstream from there, with direct replies drawn in red. This is less of a search tool than a way to sit with the structure — to trace, visually, the funnel from a drawn position into a forced loss.

Approach

Unlike a runtime-queryable solver (minimax with a transposition table, consulted each time you ask about a position), this project materializes the entire game graph up front and then reasons on top of it.

  1. Enumerate. BFS from the start; positions are (board_tuple, turn_to_move). Every legal non-self-checking move is a directed edge. Transpositions merge — the graph is a DAG with cycles from repetition.
  2. Seed terminals. Any node with no legal moves is either mate (side-to-move loses) or stalemate (draw). Lone-kings positions are drawn by material.
  3. Retrograde analysis. A node becomes a win for its side-to-move as soon as any child resolves to a loss for the opponent. It becomes a loss only when every child resolves to a win for the opponent. Anything that never settles — the remnant cycles after the fixed point — is a draw. This correctly handles repetition without needing explicit history.
  4. Lay out. The full graph is too large to force-simulate in the browser without freezing the tab, so the 3D force-directed layout is computed once in Python with numpy (vectorized O(n²) repulsion + spring forces over the edge list, 400 iterations). The resulting coordinates are embedded in the HTML; the browser only projects and renders.

No piece of this is algorithmically novel — it's retrograde analysis on a small game graph. The value is in having it as an object you can look at.

Why bother

Connect 4 was the original target: 2swap's WeakC4 visualizes the winning subtree of Connect 4 with roughly 10,000 nodes, most of them leaves representing "steady state" cheat-sheets for the endgame. That level of compression is only possible because Connect 4's endgames admit pattern-based reasoning.

1D chess, by contrast, has no meaningful endgame pattern. Every position is near enough to the start that you can reasonably hold the whole graph in view. That makes it an interesting limit case — the game at which exhaustive visualization and minimal strategic abstraction meet in the same diagram.

It's also just small enough to fit: the winning subtree alone is 73 nodes. You can zoom in and read each board.

Files

solve.py             # engine + retrograde solver, emits winning subtree
solve_full.py        # emits the full reachable graph with solved values
layout_full.py       # numpy 3D force-directed layout
build_html.py        # builds index.html (winning subtree viewer)
build_full_html.py   # builds index_full.html (full graph viewer)
pieces/              # sliced piece sprites, transparent PNGs
pieces.json          # base64-encoded sprites for inline embedding
graph.json           # winning subtree (73 nodes)
graph_full.json      # full reachable graph, no layout (1237 nodes)
graph_full_laid.json # full graph with embedded xyz positions
index.html           # winning subtree viewer (standalone)
index_full.html      # full graph viewer (standalone)

Regenerating

python solve.py          # → graph.json
python solve_full.py     # → graph_full.json
python layout_full.py    # → graph_full_laid.json  (needs numpy)
python build_html.py     # → index.html
python build_full_html.py # → index_full.html

The HTMLs are single-file: layout, data, and piece sprites are all inlined. They work offline, with no CDN and no server.

Caveats

The retrograde solver treats any cycle after fixed-point convergence as drawn. This matches standard chess practice (threefold can be claimed, so forced cycles are drawn) but differs from variants that score the side unable to force progress as the loser. The engine generates pseudo-legal moves and filters by king-safety after the fact — functionally correct for this piece set but not a template for bigger boards.

The layout is force-directed, which means "similar distance in the graph" maps roughly to "similar distance in the image" — but only roughly. Long-range edges create visual noise. A structurally mirror-symmetric embedding (like 2swap's) would be more readable; it's not implemented here.

I do not claim the graph is minimal, most readable, or pedagogically optimal. It is complete.

Credits

  • Piece sprites: adapted from public-domain Chess_pieces.png
  • Variant rules and original interactive board: rowan441/1dchess
  • Visualization approach inspired by: 2swap/WeakC4

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors