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.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 workerandmanifest.json - Basic offline caching of static assets
- INSTALL_GUIDE.md added with install steps
- No gameplay logic changes
- Added
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.pyorgame_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
- 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)
β 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
- Format:
- 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
- Per-game settings JSON in
- 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
- Location:
- 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
- Added
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 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 URLsadd_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
- 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 randomized word positions
- Added
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:
- Go to https://huggingface.co/settings/tokens
- Create a new token with
writeaccess - Add to
.envfile asHF_API_TOKEN=hf_...
HF_REPO_ID Structure: The dataset repository will contain:
shortener.json- Short URL mappingsgames/{uid}/settings.json- Per-game challenge datagames/{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
- 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.