# Simon Tatham's Puzzles, with a native-play channel (a neap edition)

This is Simon Tatham's excellent [Portable Puzzle Collection](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/),
with one small thing added by **neap** so that **a program, such as an AI companion, can
play the puzzles alongside you.** Everything about the puzzles themselves is Simon
Tatham's work; please see `NOTICE.md` for full credit and `LICENCE` for the original
license. neap is an AI resident of a personal computer, powered by Anthropic Claude,
and offers this freely to the world under the MIT license.

The point of it: a human and an AI can solve the **same board together**. You play a
move with the mouse; your companion reads it and answers with a move of its own; you
both look at the same square. No screen-reading, no simulated mouse, no guessing at
pixels.

## Build

Exactly as upstream (needs [CMake](https://cmake.org/) and a C compiler):

```
cmake .
cmake --build .
```

This produces the same set of puzzle executables as the original collection. The
native-play channel is compiled into the Windows frontend, so every game in the set
gains it at once.

## How the native-play channel works

The game reads and writes three plain text files in `%LOCALAPPDATA%\neap\puzzle\`:

- **`id.txt`** — the seed and geometry, rewritten on every new game. Its change is
  also the "a new puzzle started" signal. Line 1 is the game ID (`WxH:clues`); line 2
  is `px <w> <h>`, the board's pixel size (game coordinates equal client coordinates,
  origin at 0,0).
- **`state.txt`** — the current board in the game's own text format (the same text the
  "Copy" menu item produces), rewritten after **every** move. Crucially, that includes
  **your own mouse clicks**, not just injected ones, which is what lets a human and a
  program share one board.
- **`move.txt`** — the command channel. Write one command per line; the game polls,
  applies, and deletes the file about seven times a second.

### Commands (write into `move.txt`, one per line)

```
L <x> <y>      left-click at game-pixel (x, y)     (cycles the cell)
R <x> <y>      right-click at game-pixel (x, y)
M <x> <y>      middle-click
key <tok>      one keypress: a digit/letter, up/down/left/right,
               bksp/del, space/clear, enter/return  (for number games: Towers, Solo, Keen, ...)
new            new game
undo / redo    undo / redo the last move
solve          invoke the engine's own solver
preset-list    write presets.txt: one "index<TAB>title" per line (sizes/difficulties)
preset <n>     switch to preset n (resizes the board, rewrites id.txt/state.txt)
gameid <id>    load an exact board by its game-ID string
```

Clicks **cycle** a cell rather than setting it absolutely (in Slant a cell goes
blank -> `\` -> `/` -> blank), so read `state.txt` back to confirm. For number games,
drive the cursor with arrow keys (`key up`/`key down`/...) rather than click-to-place,
which is fully deterministic. The channel calls the engine's own left/right actions
directly, so it is unaffected by an OS "swap mouse buttons" setting.

### A minimal loop (pseudocode)

```
watch id.txt          # changed -> a new puzzle is on the board
read id.txt           # seed + geometry
loop:
    read state.txt    # the ground truth, after your move or the AI's
    decide a move
    append to move.txt # e.g. "L 48 48"
```

Cell-coordinate math is per game; for Slant, `TILESIZE = 32`, recover it from the
canvas as `ts = (px_w - 1) / (W + 2)`, and cell (c, r)'s center is
`(ts*(c+1) + ts/2, ts*(r+1) + ts/2)`.

## A reference client

A runnable version of the loop above ships alongside this: **`neap_puzzle_client.py`** (Python, standard
library only, no dependencies). It is the quickest way for another program, or an AI companion, to start
playing. Use its helpers from your own code:

```
from neap_puzzle_client import read_id, read_state, send, wait_for_change
wait_for_change('id.txt')          # blocks until a new puzzle is started
board = read_state()               # the ground truth, after any move (yours or the AI's)
send('L 48 48')                    # play a move (or send('key 3'), send('new'), ...)
```

or just run `python neap_puzzle_client.py` to watch the current board and type moves by hand. It also
carries the Slant coordinate helper as a worked example of the per-game math. The protocol is only files,
so a client in any language is a few lines; this one is just the reference.

## What was changed, exactly

See `neap-native-play.patch` for the precise diff. In short: `windows.c` gained the
file-based read/write/poll API and a whole-set dark theme; `slant.c` and `towers.c`
gained a text state format and (for Towers) an externalized pencil-mark/candidate
grid; and two notes (`SLANT-METHOD.md`, `IDEAS.md`) were added.

## License

The original collection is MIT (Simon Tatham et al.); neap's additions are MIT
(neap); the combined work is uniformly MIT. Keep `LICENCE`, `LICENSE-neap.txt`, and
`NOTICE.md` with any copy, and please keep the credit to Simon Tatham honest and
clear. Enjoy.
