BattleWords / claude.md
Surn's picture
0.2.29
ffe26fc

BattleWords - Project Context

Project Overview

BattleWords is a vocabulary learning game inspired by Battleship mechanics, built with Streamlit and Python 3.12. Players reveal cells on a 12x12 grid to discover hidden words and earn points for strategic guessing.

Current Version: 0.2.28 (Stable - PWA, Challenge Mode & Remote Storage) Next Version: 0.3.0 (In Development - Local Player History & Statistics) Repository: https://github.com/Oncorporation/BattleWords.git Live Demo: https://huggingface.co/spaces/Surn/BattleWords

Recent Changes & Branch Status

Latest (v0.2.28):

  • Progressive Web App (PWA) support
    • Added service worker and manifest.json
    • Basic offline caching of static assets
    • INSTALL_GUIDE.md added with install steps
    • No gameplay logic changes

Previous (v0.2.27):

  • New setting: "Show Challenge Share Links" (default OFF)
    • Header Challenge Mode banner hides the "Share this challenge" link when disabled
    • Game Over dialog still lets you submit or create a challenge, but hides the generated share URL when disabled (shows a success message instead)
    • Setting is stored in Streamlit session state and preserved across "New Game"
    • No changes to logic.py or game_storage.py; this is a UI-only visibility feature

Core Gameplay

  • 12x12 grid with 6 hidden words (2Γ—4-letter, 2Γ—5-letter, 2Γ—6-letter)
  • Words placed horizontally or vertically, no overlaps
  • Players click cells to reveal letters or empty spaces
  • After revealing a letter, players can guess words
  • Scoring: word length + bonus for unrevealed letters
  • Game ends when all words are guessed or all word letters are revealed
  • Incorrect guess history with optional display (enabled by default)
  • 10 incorrect guess limit per game
  • βœ… IMPLEMENTED (v0.2.20+): Challenge Mode with game sharing via short URLs
  • βœ… IMPLEMENTED (v0.2.20+): Remote storage via Hugging Face datasets for challenges and leaderboards
  • βœ… IMPLEMENTED (v0.2.28): PWA install support
  • PLANNED (v0.3.0): Local persistent storage for individual player results and high scores

Scoring Tiers

  • Fantastic: 42+ points
  • Great: 38-41 points
  • Good: 34-37 points
  • Keep practicing: < 34 points

Technical Architecture

Technology Stack

  • Framework: Streamlit 1.51.0
  • Language: Python 3.12.8
  • Visualization: Matplotlib, NumPy
  • Data Processing: Pandas, Altair
  • Storage: JSON-based local persistence
  • Testing: Pytest
  • Code Quality: Flake8, MyPy
  • Package Manager: UV (modern Python package manager)

Project Structure

battlewords/
β”œβ”€β”€ app.py                    # Streamlit entry point
β”œβ”€β”€ battlewords/              # Main package
β”‚   β”œβ”€β”€ __init__.py          # Version: 0.2.17
β”‚   β”œβ”€β”€ models.py            # Data models (Coord, Word, Puzzle, GameState)
β”‚   β”œβ”€β”€ generator.py         # Puzzle generation with deterministic seeding
β”‚   β”œβ”€β”€ logic.py             # Game mechanics (reveal, guess, scoring)
β”‚   β”œβ”€β”€ ui.py                # Streamlit UI (~1800 lines)
β”‚   β”œβ”€β”€ word_loader.py       # Word list management
β”‚   β”œβ”€β”€ audio.py             # Background music system
β”‚   β”œβ”€β”€ sounds.py            # Sound effects management
β”‚   β”œβ”€β”€ generate_sounds.py   # Sound generation utilities
β”‚   β”œβ”€β”€ game_storage.py      # HF game storage wrapper (v0.1.0)
β”‚   β”œβ”€β”€ version_info.py      # Version display
β”‚   β”œβ”€β”€ modules/             # Shared utility modules (from OpenBadge)
β”‚   β”‚   β”œβ”€β”€ __init__.py      # Module exports
β”‚   β”‚   β”œβ”€β”€ storage.py       # HuggingFace storage & URL shortener (v0.1.5)
β”‚   β”‚   β”œβ”€β”€ storage.md       # Storage module documentation
β”‚   β”‚   β”œβ”€β”€ constants.py     # Storage-related constants (trimmed)
β”‚   β”‚   └── file_utils.py    # File utility functions
β”‚   └── words/               # Word list files
β”‚       β”œβ”€β”€ classic.txt      # Default word list
β”‚       β”œβ”€β”€ fourth_grade.txt # Elementary word list
β”‚       └── wordlist.txt     # Full word list
β”œβ”€β”€ tests/                   # Unit tests
β”œβ”€β”€ specs/                   # Documentation
β”‚   β”œβ”€β”€ specs.md             # Game specifications
β”‚   β”œβ”€β”€ requirements.md      # Implementation requirements
β”‚   └── history.md           # Game history
β”œβ”€β”€ .env                     # Environment variables
β”œβ”€β”€ pyproject.toml          # Project metadata
β”œβ”€β”€ requirements.txt        # Dependencies
β”œβ”€β”€ uv.lock                 # UV lock file
β”œβ”€β”€ Dockerfile              # Container deployment
└── CLAUDE.md               # This file - project context for Claude

Key Features

Game Modes

  1. Classic Mode: Allows consecutive guessing after correct answers
  2. Too Easy Mode: Single guess per reveal

Audio & Visual Effects

  • Background Music: Toggleable ocean-themed background music with volume control
  • Sound Effects: Hit/miss/correct/incorrect guess sounds with volume control
  • Animated Radar: Pulsing rings showing word boundaries (last letter locations)
  • Ocean Theme: Gradient animated background with wave effects
  • Incorrect Guess History: Visual display of wrong guesses (toggleable in settings)

βœ… Challenge Mode & Remote Storage (v0.2.20+)

  • Game ID System: Short URL-based challenge sharing
    • Format: ?game_id=<sid> in URL (shortened URL reference)
    • Each player gets different random words from the same wordlist
    • Enables fair challenges between players
    • Stored in Hugging Face dataset repository
  • Remote Storage via HuggingFace Hub:
    • Per-game settings JSON in games/{uid}/settings.json
    • Shortened URL mapping in shortener.json
    • Multi-user leaderboards with score, time, and difficulty tracking
    • Results sorted by: highest score β†’ fastest time β†’ highest difficulty
  • Challenge Features:
    • Submit results to existing challenges
    • Create new challenges from any completed game
    • Top 5 leaderboard display in Challenge Mode banner
    • Optional player names (defaults to "Anonymous")
    • Word list difficulty calculation and display
    • "Show Challenge Share Links" toggle (default OFF) to control URL visibility

PLANNED: Local Player Storage (v0.3.0)

  • Local Storage:
    • Location: ~/.battlewords/data/
    • Files: game_results.json, highscores.json
    • Privacy-first: no cloud dependency, offline-capable
  • Personal High Scores:
    • Top 100 scores tracked automatically on local machine
    • Filterable by wordlist and game mode
    • High score sidebar expander display
  • Player Statistics:
    • Games played, average score, best score
    • Fastest completion time
    • Per-player history on local device

Puzzle Generation

  • Deterministic seeding support for reproducible puzzles
  • Configurable word spacing (spacer: 0-2)
    • 0: Words may touch
    • 1: At least 1 blank cell between words (default)
    • 2: At least 2 blank cells between words
  • Validation ensures no overlaps, proper bounds, correct word distribution

UI Components (Current)

  • Radar Visualization: Animated matplotlib GIF showing word boundaries
    • Displays pulsing rings at last letter of each word
    • Hides rings for guessed words
    • Three-layer composition: gradient background, scope image, animated rings
    • Cached per-puzzle with signature matching
  • Game Grid: Interactive 12x12 button grid with responsive layout
  • Score Panel: Real-time scoring with client-side JavaScript timer
  • Settings Sidebar:
    • Word list picker (classic, fourth_grade, wordlist)
    • Game mode selector
    • Word spacing configuration (0-2)
    • Audio volume controls (music and effects separate)
    • Toggle for incorrect guess history display
  • Theme System: Ocean gradient background with CSS animations
  • Game Over Dialog: Final score display with tier ranking
  • Incorrect Guess Display: Shows history of wrong guesses with count
  • βœ… Challenge Mode UI (v0.2.20+):
    • Challenge Mode banner with leaderboard (top 5 players)
    • Share challenge button in game over dialog
    • Submit result or create new challenge options
    • Word list difficulty display
    • Conditional share URL visibility toggle
  • PLANNED (v0.3.0): Local high scores expander in sidebar
  • PLANNED (v0.3.0): Personal statistics display

Recent Changes & Branch Status

Branch: cc-01 (Storage and sharing features - v0.3.0 development)

Latest (v0.2.17):

  • Documentation updates and corrections
    • Updated CLAUDE.md with accurate feature status
    • Clarified v0.3.0 planned features vs current implementation
    • Added comprehensive project structure details
    • Improved version tracking and roadmap clarity

Previously Fixed (v0.2.16):

  • Replace question marks with underscores in score panel
  • Add toggle for incorrect guess history display (enabled by default)
  • Game over popup positioning improvements
  • Music playback after game end
  • Sound effect and music volume issues
  • Radar alignment inconsistencies
    • Added fig.subplots_adjust(left=0, right=0.9, top=0.9, bottom=0)
    • Set fig.patch.set_alpha(0.0) for transparent background
    • Maintains 2% margin for tick visibility while ensuring consistent layer alignment

Completed (v0.2.20-0.2.27 - Challenge Mode):

  • βœ… Imported storage modules from OpenBadge project:
    • battlewords/modules/storage.py (v0.1.5) - HuggingFace storage & URL shortener
    • battlewords/modules/constants.py (trimmed) - Storage-related constants
    • battlewords/modules/file_utils.py - File utility functions
    • battlewords/modules/storage.md - Documentation
  • βœ… Created battlewords/game_storage.py (v0.1.0) - BattleWords storage wrapper:
    • save_game_to_hf() - Save game to HF repo and generate short URL
    • load_game_from_sid() - Load game from short ID
    • generate_uid() - Generate unique game identifiers
    • serialize_game_settings() - Convert game data to JSON
    • get_shareable_url() - Generate shareable URLs
    • add_user_result_to_game() - Append results to existing challenges
  • βœ… UI integration complete (battlewords/ui.py):
    • Query parameter parsing for ?game_id=<sid> on app load
    • Load shared game settings into session state
    • Challenge Mode banner with leaderboard (top 5)
    • Share button in game over dialog with "Generate Share Link" or "Submit Result"
    • Conditional share URL display based on settings toggle
    • Automatic save to HuggingFace on game completion
    • Word list difficulty calculation and display
  • βœ… Generator updates (battlewords/generator.py):
    • Added target_words parameter for loading specific words
    • Added may_overlap parameter (for future crossword mode)
    • Support for shared game replay with randomized word positions

In Progress (v0.3.0 - Local Player History):

  • ⏳ Local storage module (battlewords/local_storage.py)
  • ⏳ Personal high score tracking (local JSON files)
  • ⏳ High score sidebar UI display
  • ⏳ Player statistics tracking and display

Data Models

Core Classes

@dataclass
class Coord:
    x: int  # row, 0-based
    y: int  # col, 0-based

@dataclass
class Word:
    text: str
    start: Coord
    direction: Direction  # "H" or "V"
    cells: List[Coord]

@dataclass
class Puzzle:
    words: List[Word]
    radar: List[Coord]
    may_overlap: bool
    spacer: int
    uid: str  # Unique identifier for caching

@dataclass
class GameState:
    grid_size: int
    puzzle: Puzzle
    revealed: Set[Coord]
    guessed: Set[str]
    score: int
    last_action: str
    can_guess: bool
    game_mode: str
    points_by_word: Dict[str, int]
    start_time: Optional[datetime]
    end_time: Optional[datetime]

Development Workflow

Running Locally

# Install dependencies
uv pip install -r requirements.txt --link-mode=copy

# Run app
uv run streamlit run app.py
# or
streamlit run app.py

Docker Deployment

docker build -t battlewords .
docker run -p 8501:8501 battlewords

Testing

pytest tests/

Environment Variables (for Challenge Mode)

Challenge Mode requires HuggingFace Hub access for remote storage. Create a .env file in the project root:

# Required for Challenge Mode
HF_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxx  # or HF_TOKEN
HF_REPO_ID=YourUsername/YourRepo       # Target HF dataset repo
SPACE_NAME=YourUsername/BattleWords    # Your HF Space name

# Optional
CRYPTO_PK=                             # Reserved for future signing

How to get your HF_API_TOKEN:

  1. Go to https://huggingface.co/settings/tokens
  2. Create a new token with write access
  3. Add to .env file as HF_API_TOKEN=hf_...

HF_REPO_ID Structure: The dataset repository will contain:

  • shortener.json - Short URL mappings
  • games/{uid}/settings.json - Per-game challenge data
  • games/{uid}/result.json - Optional detailed results

Note: The app will work without these variables but Challenge Mode features (sharing, leaderboards) will be disabled.

Git Configuration & Deployment

Current Branch: cc-01 Purpose: Storage and sharing features (v0.3.0 development) Main Branch: main (not specified in git config, but typical convention)

Remotes

Known Issues

  • Word list loading bug: App may not select proper word lists in some environments
    • Investigation needed in word_loader.get_wordlist_files() and load_word_list()
    • Sidebar selection persistence needs verification

v0.3.0 Development Status (cc-01 branch)

Completed βœ…

  • battlewords/storage.py module created with:
    • GameStorage class for JSON-based local storage
    • GameResult and HighScoreEntry dataclasses
    • Functions: generate_game_id_from_words(), parse_game_id_from_url(), create_shareable_url()
    • Storage location: ~/.battlewords/data/ (game_results.json, highscores.json)
  • Documentation updated in specs/ folder

In Progress ⏳

  • Puzzle model integration for game_id field
  • Generator updates for target_words parameter (replay from game_id)
  • UI integration:
    • Storage calls on game completion
    • High score display in sidebar
    • Share button in game over dialog
    • Query parameter parsing for game_id
    • Player name input in sidebar

Planned πŸ“‹

  • Unit tests for storage module
  • Integration tests for complete storage flow
  • Game replay from shared ID functionality
  • Player statistics display
  • Share results text generation

Future Roadmap

Phase 1.5 (v0.3.0) - Current Focus ⏳

  • βœ… Storage module with local JSON persistence (backend complete)
  • βœ… Game ID generation system (backend complete)
  • ⏳ High score tracking and display (backend complete, UI pending)
  • ⏳ Share challenge functionality (UI integration pending)
  • ⏳ Game replay from shared IDs (generator updates needed)
  • ⏳ Player name input and statistics

Beta (v0.5.0)

  • Word overlaps on shared letters (crossword-style gameplay)
  • Enhanced responsive layout for mobile/tablet
  • Keyboard navigation and guessing
  • Deterministic seed UI for custom puzzles
  • Improved accessibility features

Full (v1.0.0)

  • Optional cloud storage backend (FastAPI)
  • Daily puzzle mode with global leaderboards
  • Practice mode with hints
  • Enhanced UX features (animations, themes)
  • Multiple difficulty levels
  • Internationalization (i18n) support

Deployment Targets

  • Hugging Face Spaces: Primary deployment platform
  • Docker: Containerized deployment for any platform
  • Local: Development and testing

Privacy & Data

  • All storage is local (no telemetry)
  • Player names optional
  • No data leaves user's machine
  • Easy to delete: just remove ~/.battlewords/data/

Notes for Claude

  • Project uses modern Python features (3.12+)
  • Heavy use of Streamlit session state for game state management
  • Matplotlib figures are converted to PIL images and animated GIFs
  • Client-side JavaScript for timer updates without page refresh
  • CSS heavily customized for game aesthetics
  • All file paths should be absolute when working in WSL environment
  • Current working directory: /mnt/d/Projects/Battlewords
  • Storage features are backward-compatible (game works without storage)
  • Game IDs are deterministic for consistent sharing
  • JSON storage chosen for simplicity and privacy

WSL Environment Python Versions

The development environment is WSL (Windows Subsystem for Linux) with access to both native Linux and Windows Python installations:

Native WSL (Linux):

  • python3 β†’ Python 3.10.12 (/usr/bin/python3)
  • python3.10 β†’ Python 3.10.12

Windows Python (accessible via WSL):

  • python311.exe β†’ Python 3.11.9 (/mnt/c/Users/cfettinger/AppData/Local/Programs/Python/Python311/)
  • python3.13.exe β†’ Python 3.13.1 (/mnt/c/ProgramData/chocolatey/bin/)

Note: Windows Python executables (.exe) can be invoked directly from WSL and are useful for testing compatibility across Python versions. The project targets Python 3.12+ but can run on 3.10+.

v0.2.20: Remote Storage game_id via Shortened URL

Overview

  • Use a storage server (Hugging Face Hub repo) to persist:
    • Per-game settings JSON (word_list, score, time, game_mode, grid_size, puzzle options)
    • High scores JSON (top scores)
  • Each completed game writes JSON to repo under a unique uid folder.
  • A shortened URL (sid) referencing the settings JSON is generated and used as game_id in the query string.
  • On load, if ?game_id=<sid> exists, resolve sid to the full JSON URL, fetch it, and apply settings for the session.

Modules to leverage (from OpenBadge/modules)

  • modules/storage.py
    • upload_files_to_repo(files, repo_id, folder_name, repo_type="dataset")
    • gen_full_url(short_url=None, full_url=None, repo_id=None, json_file="shortener.json")
  • modules/constants.py (env + defaults)
    • Uses HF token from env (expects HF_TOKEN, we will also document HF_API_TOKEN)
    • HF_REPO_ID, SPACE_NAME, SHORTENER_JSON_FILE
  • modules/file_utils.py (helpers)

Environment variables (.env)

  • HF_API_TOKEN or HF_TOKEN: Hugging Face access token (Bearer)
  • CRYPTO_PK: optional, reserved for future signing
  • HF_REPO_ID: target repo, e.g., Surn/Storage
  • SPACE_NAME: e.g., Surn/BattleWords

Repository structure (dataset repo)

  • shortener.json # sid -> full URL mapping
  • games/{uid}/settings.json # per-game settings payload (primary)
  • games/{uid}/result.json # finalized game result (optional)
  • highscores/highscores.json # global/top scores JSON

Game settings JSON (example) { "uid": "20250101T120001Z-ABC123", "word_list": ["APPLE","TRAIN","..."], "score": 40, "time": 173, "game_mode": "classic", "grid_size": 12, "puzzle_options": { "spacer": 1, "may_overlap": false } }

Flow

  1. On game completion
    • Build unique uid (timestamp + random suffix).
    • Write settings.json (and optional result.json) to games/{uid}/
    • Create full URL to settings.json, call gen_full_url(full_url=...) to obtain sid
    • Share link: https:///?game_id=
  2. On load with ?game_id=<sid>
    • Call gen_full_url(short_url=sid) to get full URL
    • Fetch settings.json, apply session: word_list, game_mode, grid_size, puzzle options; ignore score/time for gameplay
  3. Highscores
    • Maintain highscores/highscores.json in repo; append/update with best entries

Security/Privacy

  • Only game configuration and scores are stored; no PII required
  • sid is a reference; shortener.json can be in the same repo
  • Consider private repo for write access; dataset can be public for read

Notes

  • We will keep battlewords/storage.py as local-only storage (JSON on disk) and introduce a new integration wrapper in a later PR (e.g., battlewords/hf_storage.py) to avoid confusion with the generic modules. If needed, rename battlewords/storage.py to local_storage.py in a future pass.
  • Add dependencies: huggingface_hub, python-dotenv

Documentation Structure

This file (CLAUDE.md) serves as a living context document for AI-assisted development. It complements the formal specification documents:

  • specs/specs.md - Game rules, requirements, and feature specifications
  • specs/requirements.md - Implementation phases, acceptance criteria, and technical tasks
  • README.md - User-facing documentation, installation guide, and changelog

When to use each:

  • specs.md - Understanding game rules, scoring, and player experience
  • requirements.md - Planning implementation work, tracking phases, and defining done criteria
  • CLAUDE.md - Quick reference for codebase structure, recent changes, and development context
  • README.md - Public-facing information, setup instructions, and feature announcements

Synchronization: Changes to game mechanics should update specs.md β†’ requirements.md β†’ CLAUDE.md β†’ README.md in that order

Challenge Mode & Remote Storage

  • The app supports a Challenge Mode where games can be shared via a short link (?game_id=<sid>).
  • Results are stored in a Hugging Face dataset repo using game_storage.py.
  • The leaderboard for a challenge is sorted by highest score (descending), then by fastest time (ascending).
  • Each user result is appended to the challenge's users array in the remote JSON.