65 lines
2.9 KiB
Markdown
65 lines
2.9 KiB
Markdown
# Wizard online
|
||
|
||
An online version of the card game Wizard (rules: `wizard_instructions/`).
|
||
|
||
| Component | Path | Tech |
|
||
|-----------|------|------|
|
||
| Frontend | `wizard_website/` | React + TypeScript + Vite, CSS modules, served by nginx |
|
||
| Game server | `wizard_server/` | Python, FastAPI, websockets |
|
||
| Game logic | `wizard_server/game_logic/` | Pure Python package `wizard_game` (no dependencies) |
|
||
| AI player | `wizard_ai/` | Python; RL training skeleton + websocket service |
|
||
|
||
```
|
||
browser ──wss /api/ws──▶ Caddy ──▶ wizard_server ◀──ws /internal/ai── wizard_ai
|
||
──https /──────▶ Caddy ──▶ wizard_website (network wizard_internal)
|
||
```
|
||
|
||
## How it works
|
||
|
||
1. A player opens the website, enters a name and creates a lobby (and joins it).
|
||
2. The lobby shows a code (and an invite link, `?lobby=CODE`) others use to join.
|
||
3. The host can add AI players, toggle the *not equal* / *hidden bids* rules, and start the game (3–6 players).
|
||
4. The server runs the game with `wizard_game` and sends every player a personal view
|
||
(`Observation`) after each move. Reloading the page reconnects to the same seat.
|
||
A player who leaves a running game is replaced by an AI player.
|
||
5. When an AI seat has to act, the server sends its `Observation` to the AI service over the
|
||
internal websocket and applies the answered action. If the AI service is unavailable or
|
||
too slow, a random legal move is played so games never get stuck.
|
||
|
||
The `Observation` / action JSON format is defined once in `wizard_game` and shared by the
|
||
frontend, the server and the AI, so AI models see exactly the same data in training and in
|
||
production.
|
||
|
||
## Deployment
|
||
|
||
```bash
|
||
cp .env.example .env # set AI_SHARED_SECRET
|
||
docker network create wizard_website # if they don't exist yet
|
||
docker network create wizard_api
|
||
docker compose up -d --build
|
||
```
|
||
|
||
- `wizard_website` joins the external network `wizard_website` (port 8082).
|
||
- `wizard_server` joins the external network `wizard_api` (port 8083) and `wizard_internal`.
|
||
- `wizard_ai` joins only `wizard_internal`, created by compose as an internal network.
|
||
|
||
Add a site block like `Caddyfile.example` to the existing Caddy container: `/api/*` goes to
|
||
`wizard_server:8083`, everything else to `wizard_website:8082`.
|
||
|
||
Trained AI checkpoints go into `wizard_ai/models/latest/` (mounted read-only). Until one exists
|
||
the AI service uses the built-in heuristic player.
|
||
|
||
## Development
|
||
|
||
```bash
|
||
python -m venv .venv && . .venv/bin/activate
|
||
pip install -r wizard_server/requirements-dev.txt -r wizard_ai/requirements-dev.txt
|
||
|
||
(cd wizard_server && uvicorn app.main:app --reload) # :8000
|
||
(cd wizard_ai && python -m wizard_ai serve) # connects to :8000
|
||
(cd wizard_website && npm install && npm run dev) # :5173
|
||
|
||
(cd wizard_server && pytest) # game logic + server tests
|
||
(cd wizard_ai && pytest)
|
||
```
|