Metadata-Version: 2.4
Name: ttt-gauntlet
Version: 0.2.0
Summary: A Tic-Tac-Toe gauntlet CLI that gets harder the more you win, with DuckDB event streaming.
Project-URL: Homepage, https://github.com/cmacdonald0514/tictactoe
Project-URL: Repository, https://github.com/cmacdonald0514/tictactoe
Project-URL: Issues, https://github.com/cmacdonald0514/tictactoe/issues
Author: Christian Macdonald
License-Expression: MIT
License-File: LICENSE
Keywords: cli,duckdb,game,textual,tic-tac-toe,tui
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Games/Entertainment :: Board Games
Requires-Python: >=3.11
Requires-Dist: duckdb>=1.0
Requires-Dist: pydantic>=2.6
Requires-Dist: rich>=13
Requires-Dist: textual>=0.60
Requires-Dist: typer>=0.12
Description-Content-Type: text/markdown

# Tic-Tac-Toe Gauntlet

A terminal tic-tac-toe game that gets **harder the more you win**. Beat the
random Rookie to unlock the rule-based Contender, then the unbeatable Minimax
Champion. Every game and move is streamed into a local DuckDB database.

Built with **Python + uv + Pydantic + Textual + DuckDB**.

## Quickstart

No clone, no database setup — the database is created on first run.

```bash
uvx ttt-gauntlet play        # try it without installing anything
```

Or install it:

```bash
pip install ttt-gauntlet
ttt-gauntlet play            # play the gauntlet (interactive TUI)
ttt-gauntlet stats           # see your record
```

(`uvx` ships with [uv](https://docs.astral.sh/uv/); `pipx run ttt-gauntlet play`
works the same way.)

## How it plays

- You are **X** and always move first.
- **Win** to advance to the next tier. **Lose or draw** to replay the tier.
- Progress is remembered across sessions — `ttt-gauntlet play` resumes just past
  your best win. Force a tier with `ttt-gauntlet play --level 3`.
- A **live stats panel** sits to the right of the board — record, current/best
  win streak, average moves per win, win rate per tier, and a trend of your
  recent results — refreshed after every game.

Controls: click a square (or navigate with the keyboard), `N` to continue after
a game, `Q` to quit.

### The difficulty ladder

| Level | Tier      | Engine                                             |
| ----- | --------- | -------------------------------------------------- |
| 1     | Rookie    | Random legal move                                  |
| 2     | Contender | Heuristic: win → block → center → corner → edge    |
| 3     | Champion  | Minimax — optimal, cannot be beaten                |

## Architecture

The rules engine and the AI are pure and UI-agnostic, so the same logic backs
the game, the opponents, and the tests.

```
src/ttt/
  models.py        # Pydantic models (Board, GameEvent, …)
  engine/game.py   # pure tic-tac-toe rules (single source of truth)
  opponents/       # Opponent abstraction + random / heuristic / minimax + ladder
  data/db.py       # DuckDB connection + GameRepository
  tui/app.py       # Textual UI (thin: renders + dispatches only)
  cli.py           # Typer commands: play / stats
```

### Data model

`game_events` is an **append-only event stream** — the source of truth for
everything that happens (`game_started` / `move_made` / `game_ended`). The
`games` and `moves` tables are projections written alongside it to keep common
queries simple.

The database lives at `$XDG_DATA_HOME/ttt/ttt.duckdb` (or
`~/.local/share/ttt/ttt.duckdb`). Override with `TTT_DB_PATH`.

## Roadmap

Planned features are written up as one-file specs — these are the units of work
fed to the OpenHands PR automation.

## Development

Requires [uv](https://docs.astral.sh/uv/).

```bash
git clone https://github.com/cmacdonald0514/tictactoe.git
cd tictactoe
uv sync                     # install dependencies
uv run ttt-gauntlet play    # run from the working tree
```

```bash
uv run pytest          # unit tests (engine, opponents, persistence)
uv run ruff check      # lint
uv run ruff format     # format
```

### Releasing

Bump `version` in `pyproject.toml` and merge to `master`. The release workflow
compares that version against the previous commit and publishes to PyPI via
[Trusted Publishing](https://docs.pypi.org/trusted-publishers/) when it changes;
merges that leave the version alone publish nothing.
