Spaces:
Running
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.17 (Stable) Next Version: 0.3.0 (In Development - Storage & Sharing Features) Repository: https://github.com/Oncorporation/BattleWords.git Live Demo: https://huggingface.co/spaces/Surn/BattleWords
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 revealed
- Incorrect guess history with optional display (enabled by default)
- 10 incorrect guess limit per game
- PLANNED (v0.3.0): Game sharing via unique game IDs
- PLANNED (v0.3.0): Local persistent storage for 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.50.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
- Classic Mode: Allows consecutive guessing after correct answers
- 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)
PLANNED: Storage & Sharing (v0.3.0)
- Game ID System: 8-character deterministic IDs based on word combinations
- Format:
?game_id=ABC123in URL - Same words, different positions for each replay
- Enables fair challenges between players
- Format:
- Local Storage:
- Location:
~/.battlewords/data/ - Files:
game_results.json,highscores.json - Privacy-first: no cloud dependency
- Location:
- High Scores:
- Top 100 scores tracked automatically
- Filterable by wordlist and game mode
- Optional player names (defaults to "Anonymous")
- Player Statistics:
- Games played, average score, best score
- Fastest completion time
- Per-player history
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
- v0.3.0: Game ID system planned (not yet integrated into Puzzle model)
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
- PLANNED (v0.3.0): High scores expander in sidebar
- PLANNED (v0.3.0): Share challenge button in game over dialog
- PLANNED (v0.3.0): Game ID display during gameplay
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
- Added
In Progress (v0.3.0 on cc-01):
- β
Imported storage modules from OpenBadge project:
battlewords/modules/storage.py(v0.1.5) - HuggingFace storage & URL shortenerbattlewords/modules/constants.py(trimmed) - Storage-related constantsbattlewords/modules/file_utils.py- File utility functionsbattlewords/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 URLload_game_from_sid()- Load game from short IDgenerate_uid()- Generate unique game identifiersserialize_game_settings()- Convert game data to JSONget_shareable_url()- Generate shareable URLs
- β
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 showing target score and time
- Share button in game over dialog with "Generate Share Link"
- Copy-to-clipboard functionality for share URLs
- Automatic save to HuggingFace on game completion
- Query parameter parsing for
- β
Generator updates (
battlewords/generator.py):- Added
target_wordsparameter for loading specific words - Added
may_overlapparameter (for future crossword mode) - Support for shared game replay with same words, different positions
- Added
- β³ High score tracking infrastructure (backend ready, UI pending)
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/
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
- ONCORP (origin): https://github.com/Oncorporation/BattleWords.git (main repository)
- Hugging: https://huggingface.co/spaces/Surn/BattleWords (live deployment)
Known Issues
- Word list loading bug: App may not select proper word lists in some environments
- Investigation needed in
word_loader.get_wordlist_files()andload_word_list() - Sidebar selection persistence needs verification
- Investigation needed in
v0.3.0 Development Status (cc-01 branch)
Completed β
battlewords/storage.pymodule created with:GameStorageclass for JSON-based local storageGameResultandHighScoreEntrydataclasses- 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_wordsparameter (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
uidfolder. - A shortened URL (sid) referencing the settings JSON is generated and used as
game_idin 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.pyupload_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 documentHF_API_TOKEN) HF_REPO_ID,SPACE_NAME,SHORTENER_JSON_FILE
- Uses HF token from env (expects
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
- 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 obtainsid - Share link: https:///?game_id=
- Build unique
- 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
- Call
- 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.pyas 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, renamebattlewords/storage.pytolocal_storage.pyin 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
usersarray in the remote JSON.