Files
yarn-ng/README.md
T

102 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Y.A.R.N. HTML5
A browser remake of **Y.A.R.N.** (Yet Another Random Narrative), the collaborative
story-writing parlor game from GameSpy Arcade, with optional LLM-driven bots.
Players take turns adding one sentence to a shared story, vote for their favourite
entry each round, and score points. The finished story is saved to disk.
## Quick start
```bash
npm install
npm start
# open http://localhost:3000
```
Create or pick a room on the menu, share the `/game/<room>` URL, and the host
can start once at least 3 players (humans + bots) are present.
## Configuration
| Variable | Default | Purpose |
| --- | --- | --- |
| `PORT` | `3000` | HTTP port |
| `YARN_STORIES_DIR` | `./stories` | Where finished stories are written |
| `OPENAI_API_KEY` | – | Enables LLM bots (any OpenAI-compatible endpoint) |
| `OPENAI_MODEL` | `meta-llama/Llama-3.2-3B-Instruct-Turbo` | Default model |
Bots can also be configured with `bots/llm_config.json` (same shape as the
OpenAI JS client's options, e.g. `{ "apiKey": "...", "baseURL": "...", "model": "..." }`).
Copy `bots/llm_config.example.json` to get started. This file is gitignored.
**If the LLM client cannot be created (no key/config), bots automatically fall
back to `RandomBot`**, so a game always starts. A bot request that fails or
times out degrades to a fallback sentence (or an empty entry) and the game
continues.
## Game rules
- The host picks the round limit, score limit, time per round, bot count and
starting text. Settings sync live to everyone in the lobby.
- Writing phase: each player submits one sentence (max 280 chars).
- Voting phase: 10 seconds per entry (minimum 15s). You cannot vote for your
own entry, and empty entries are not voteable.
- Scoring: 1 point per vote received. The single most-voted entry gets +3
bonus points. On a tie the longest tied entry gets +2 and the others +1.
**The final round is worth double points.**
- The game ends when a player reaches the score limit, or when the round limit
is reached (highest score wins). The story is saved automatically.
- The host can skip a stalled writing/voting phase and remove idle players.
If a player drops, the round advances immediately when everyone remaining
has submitted/voted.
## Project layout
```
server.js Express + Socket.IO server and the YarnGame state machine
bots/BotFactory.js Bot construction (LLM with RandomBot fallback) + unique names
bots/LLMBot.js OpenAI-compatible bot (write/vote/banter, optional config)
bots/RandomBot.js Deterministic offline bot
public/menu.html Room browser, past-story archive, about
public/game.html Game client (lobby, writing, voting, results, game over)
tests/ node:test unit + socket integration tests
stories/ Saved stories (gitignored, created on demand)
```
## Tests
```bash
npm test
```
The suite (`node --test tests/*.test.js`) covers:
- `tests/yarn-game.test.js` – scoring (incl. final-round doubling and tie
breaks), vote validation, phase transitions/timers, reconnection, story
assembly and persistence.
- `tests/bots.test.js` – factory fallback, unique names, concurrent bot
writing/voting, invalid bot votes, banter wiring.
- `tests/validation.test.js` – room/player-id sanitisation, settings clamping,
text cleaning.
- `tests/socket-flow.test.js` – full end-to-end game over real Socket.IO:
two humans + one bot, writing → voting → results → game over, story saved,
plus immediate phase advance when the last unsubmitted player disconnects.
- `tests/client-ui.test.js` – loads `game.html` and `menu.html` in jsdom and
drives the real client code: input preservation, score-limit `0`, refresh
resync, HUD, own-vote blocking, results table, game-over controls, host
skip/kick, room list and past-story archive.
### Manual verification checklist
The jsdom suite covers the client logic; a few visual/browser checks are still
worth doing by hand:
1. Open two browser windows on the same room and confirm the live chat, player
highlight colours and host ★ marker look right.
2. Hover a story segment and confirm the author name appears.
3. On game over, use Download/Copy Story and check the file/clipboard contents.
4. Confirm the results table is readable on a narrow (mobile) viewport.
5. Start a game with 2 humans and 4 bots and confirm the round flow feels right
(LLM latency, banter in chat, no stalled rounds).