Spaces:
Running
Running
| title: BattleWords | |
| emoji: 🎲 | |
| colorFrom: blue | |
| colorTo: indigo | |
| sdk: streamlit | |
| sdk_version: 1.51.0 | |
| python_version: 3.12.8 | |
| app_port: 8501 | |
| app_file: app.py | |
| tags: | |
| - game | |
| - vocabulary | |
| - streamlit | |
| - education | |
| # BattleWords | |
| > **This project is used by [huggingface.co](https://huggingface.co/spaces/Surn/BattleWords) as a demonstration of interactive word games in Python.** | |
| BattleWords is a vocabulary learning game inspired by classic Battleship mechanics. The objective is to discover hidden words on a grid, earning points for strategic guessing before all letters are revealed. | |
| ## Features | |
| ### Core Gameplay | |
| - 12x12 grid with six hidden words (2x4-letter, 2x5-letter, 2x6-letter) | |
| - Words placed horizontally or vertically | |
| - Animated radar visualization showing word boundaries | |
| - Reveal grid cells and guess words for points | |
| - Scoring tiers: Good (34–37), Great (38–41), Fantastic (42+) | |
| - Game ends when all words are guessed or all word letters are revealed | |
| - Incorrect guess history with tooltip and optional display (enabled by default) | |
| - 10 incorrect guess limit per game | |
| - Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal) | |
| ### Audio & Visuals | |
| - Ocean-themed gradient background with wave animations | |
| - Background music system (toggleable with volume control) | |
| - Sound effects for hits, misses, correct/incorrect guesses | |
| - Responsive UI built with Streamlit | |
| ### Customization | |
| - Multiple word lists (classic, fourth_grade, wordlist) | |
| - Wordlist sidebar controls (picker + one-click sort) | |
| - Configurable word spacing (0-2 cells between words) | |
| - Audio volume controls (music and effects separate) | |
| ### ✅ Challenge Mode (v0.2.20+) | |
| - **Shareable challenge links** via short URLs (`?game_id=<sid>`) | |
| - **Multi-user leaderboards** sorted by score and time | |
| - **Remote storage** via Hugging Face datasets | |
| - **Word list difficulty calculation** and display | |
| - **Submit results** to existing challenges or create new ones | |
| - **Top 5 leaderboard** display in Challenge Mode banner | |
| - **"Show Challenge Share Links" toggle** (default OFF) to control URL visibility | |
| - Each player gets different random words from the same wordlist | |
| ### Deployment & Technical | |
| - **Dockerfile-based deployment** supported for Hugging Face Spaces and other container platforms | |
| - **Environment variables** for Challenge Mode (HF_API_TOKEN, HF_REPO_ID, SPACE_NAME) | |
| - Works offline without HF credentials (Challenge Mode features disabled gracefully) | |
| ### Progressive Web App (PWA) - v0.2.28 | |
| - Installable on desktop and mobile from your browser: | |
| - Chrome/Edge: Menu → “Install app” | |
| - Android Chrome: “Add to Home screen” | |
| - iOS Safari: Share → “Add to Home Screen” | |
| - Includes `service worker` and `manifest.json` with basic offline caching of static assets | |
| - See `INSTALL_GUIDE.md` for platform-specific steps | |
| ### Planned (v0.3.0) | |
| - Local persistent storage for personal game history | |
| - Personal high scores sidebar (offline-capable) | |
| - Player statistics tracking | |
| - Deterministic seed UI for custom puzzles | |
| ### Beta (v0.5.0) | |
| - Word overlaps on shared letters (crossword-style) | |
| - Enhanced responsive layout for mobile/tablet | |
| - Keyboard navigation and guessing | |
| ### Full (v1.0.0) | |
| - Daily puzzle mode with global leaderboards | |
| - Practice mode with hints | |
| - Multiple difficulty levels | |
| - Internationalization (i18n) support | |
| ## Challenge Mode & Leaderboard | |
| When playing a shared challenge (via a `game_id` link), the leaderboard displays all submitted results for that challenge. The leaderboard is **sorted by highest score (descending), then by fastest time (ascending)**. This means players with the most points appear at the top, and ties are broken by the shortest completion time. | |
| ## Installation | |
| 1. Clone the repository: | |
| ``` | |
| git clone https://github.com/Oncorporation/BattleWords.git | |
| cd battlewords | |
| ``` | |
| 2. (Optional) Create and activate a virtual environment: | |
| ``` | |
| python -m venv venv | |
| source venv/bin/activate # On Windows use `venv\Scripts\activate` | |
| ``` | |
| 3. Install dependencies: ( add --system if not using a virutal environment) | |
| ``` | |
| uv pip install -r requirements.txt --link-mode=copy | |
| ``` | |
| ## Running BattleWords | |
| You can run the app locally using either [uv](https://github.com/astral-sh/uv) or Streamlit directly: | |
| ``` | |
| uv run streamlit run app.py | |
| ``` | |
| or | |
| ``` | |
| streamlit run app.py | |
| ``` | |
| ### Dockerfile Deployment (Hugging Face Spaces and more) | |
| BattleWords supports containerized deployment using a `Dockerfile`. This is the recommended method for deploying to [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces-sdks-docker) or any Docker-compatible environment. | |
| To deploy on Hugging Face Spaces: | |
| 1. Add a `Dockerfile` to your repository root (see [Spaces Dockerfile guide](https://huggingface.co/docs/hub/spaces-sdks-docker)). | |
| 2. Push your code to your Hugging Face Space. | |
| 3. The platform will build and run your app automatically. | |
| For local Docker runs: | |
| ```sh | |
| docker build -t battlewords . | |
| docker run -p8501:8501 battlewords | |
| ``` | |
| ### Environment Variables (for Challenge Mode) | |
| Challenge Mode requires a `.env` file in the project root with HuggingFace Hub credentials: | |
| ```bash | |
| # 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_...` | |
| **Note:** The app works without these variables, but Challenge Mode features (sharing, leaderboards) will be disabled. | |
| ## Folder Structure | |
| - `app.py` – Streamlit entry point | |
| - `battlewords/` – Python package | |
| - `models.py` – data models and types | |
| - `word_loader.py` – word list loading and validation | |
| - `generator.py` – word placement logic | |
| - `logic.py` – game mechanics (reveal, guess, scoring) | |
| - `ui.py` – Streamlit UI composition | |
| - `game_storage.py` – Hugging Face remote storage integration and challenge sharing | |
| - `local_storage.py` – local JSON storage for results and high scores | |
| - `storage.py` – (legacy) local storage and high scores | |
| - `words/wordlist.txt` – candidate words | |
| - `specs/` – documentation (`specs.md`, `requirements.md`) | |
| - `tests/` – unit tests | |
| ## How to Play | |
| 1. Click grid squares to reveal letters or empty spaces. | |
| 2. After revealing a letter, enter a guess for a word in the text box. | |
| 3. Earn points for correct guesses and bonus points for unrevealed letters. | |
| 4. **The game ends when all six words are found or all word letters are revealed. Your score tier is displayed.** | |
| 5. **To play a shared challenge, use a link with `?game_id=<sid>`. Your result will be added to the challenge leaderboard.** | |
| ## Changelog | |
| ### v0.3.0 (planned) | |
| - Local persistent storage for personal game history (offline-capable) | |
| - Personal high scores sidebar with filtering | |
| - Player statistics tracking (games played, averages, bests) | |
| -0.2.29 | |
| - change difficulty calculation | |
| - add test_compare_difficulty_functions | |
| - streamlit version update to 1.51.0 | |
| -0.2.28 | |
| - PWA INSTALL_GUIDE.md added | |
| - PWA implementation with service worker and manifest.json added | |
| -0.2.27 | |
| - Add "Show Challenge Share Links" setting (default: off) | |
| - When disabled: | |
| - Header Challenge Mode: hides the Share Challenge link | |
| - Game Over: allows submitting results but suppresses displaying the generated share URL | |
| - The setting is saved in session state and preserved across "New Game" | |
| - No changes to game logic or storage; only UI visibility behavior | |
| -0.2.26 | |
| - fix copy/share link button | |
| -0.2.25 | |
| - Share challenge from expander | |
| - fix incorrect guess overlap of guess box | |
| -0.2.24 | |
| - compress height | |
| - change incorrect guess tooltip location | |
| - update final screen layout | |
| - add word difficulty formula | |
| - update documentation | |
| -0.2.23 | |
| - Update miss and correct guess sound effects to new versions | |
| - allow iframe hosted version to pass url as a query string parameter (&iframe_host=https%3A%2F%2Fwww.battlewords.com%2Fplaynow.html) url encoding is required. | |
| - minimal security added to prevent users from changing the options in a challenge. | |
| -0.2.22 | |
| - fix challenge mode link | |
| - challenge mode UI improvements | |
| -0.2.21 | |
| - fix tests | |
| -0.2.20 | |
| - Remote Storage game_id: | |
| - Per-game JSON settings uploaded to a storage server (Hugging Face repo) under unique `games/{uid}/settings.json` | |
| - A shortened URL id (sid) is generated; shareable link: `?game_id=<sid>` | |
| - On load with `game_id`, the app resolves sid to the JSON and applies word_list, game_mode, grid_size, puzzle options | |
| - High Scores: add remote `highscores/highscores.json` (repo) alongside local highscores | |
| - Dependencies: add `huggingface_hub` and `python-dotenv` | |
| - Env: `.env` should include `HF_API_TOKEN` (or `HF_TOKEN`), `CRYPTO_PK`, `HF_REPO_ID`, `SPACE_NAME` | |
| ### Environment Variables | |
| - HF_API_TOKEN or HF_TOKEN: HF Hub access token | |
| - CRYPTO_PK: reserved for signing (optional) | |
| - HF_REPO_ID: e.g., Surn/Storage | |
| - SPACE_NAME: e.g., Surn/BattleWords | |
| ### Remote Storage Structure | |
| - shortener.json | |
| - games/{uid}/settings.json | |
| - highscores/highscores.json | |
| Note | |
| - `battlewords/storage.py` remains local-only storage; a separate HF integration wrapper is provided as `game_storage.py` for remote challenge mode. | |
| -0.2.19 | |
| - Fix music and sound effect volume issues | |
| - Update documentation for proposed new features | |
| -0.2.18 | |
| - Fix sound effect volume wiring and apply volume to all effects (hit/miss/correct/incorrect) | |
| - Respect "Enable music" and "Volume" when playing congratulations music and when resuming background music (uses selected track) | |
| - Add "Enable Sound Effects" checkbox (on by default) and honor it across the app | |
| - Save generated effects to `assets/audio/effects/` so they are picked up by the app | |
| - Add `requests` dependency for sound effect generation | |
| -0.2.17 | |
| - documentation updates and corrections | |
| - updated CLAUDE.md with accurate feature status and project structure | |
| - clarified v0.3.0 planned features vs current implementation | |
| -0.2.16 | |
| - replace question marks in score panel with underscores | |
| - add option to toggle incorrect guess history display in settings (enabled by default) | |
| - game over popup updated to ensure it is fully visible on screen | |
| -0.2.15 | |
| - fix music playing after game end | |
| - change incorrect guesses icon | |
| - fix sound effect and music volume issues | |
| -0.2.14 | |
| - bug fix on final score popup | |
| - score panel alignment centered | |
| - change incorrect guess history UI | |
| -0.2.13 | |
| - upgrade background ocean view | |
| - apply volume control to sound effects | |
| -0.2.12 | |
| - fix music looping on congratulations screen | |
| -0.2.11 | |
| - update timer to be live during gameplay, but reset with each action | |
| - compact design | |
| - remove fullscreen image tooltip | |
| -0.2.10 | |
| - reduce sonar graphic size | |
| - update music and special effects file locations | |
| - remove some music and sound effects | |
| - change Guess Text input color | |
| - incorrect guess UI update | |
| - scoreboard update | |
| -0.2.9 | |
| - fix sonar grid alignment issue on some browsers | |
| - When all letters of a word are revealed, it is automatically marked as found. | |
| -0.2.8 | |
| - Add10 incorrect guess limit per game | |
| -0.2.7 | |
| - fix background music playback issue on some browsers | |
| - add sound effects | |
| - enhance sonar grid visualization | |
| - add claude.md documentation | |
| -0.2.6 | |
| - fix sonar grid alignment | |
| - improve score summary layout and styling | |
| - Add timer to game display in sidebar | |
| -0.2.5 | |
| - fix finale pop up issue | |
| - make grid cells square on wider devices | |
| -0.2.4 | |
| - Add music files to repo | |
| - disable music by default | |
| -0.2.3 | |
| - Update version information display | |
| - adjust sonar grid alignment | |
| - fix settings scroll issue | |
| -0.2.2 | |
| - Add Musical background and settings to toggle sound on/off. | |
| -0.2.1 | |
| - Add Theme toggle (light/dark/custom) in sidebar. | |
| -0.2.0 | |
| - Added a loading screen when starting a new game. | |
| - Added a congratulations screen with your final score and tier when the game ends. | |
| -0.1.13 | |
| - Improved score summary layout for clarity and style. | |
| -0.1.12 | |
| - Improved score summary layout and styling. | |
| - Enhanced overall appearance and readability. | |
| -0.1.11 | |
| - Game now ends when all words are found or revealed. | |
| - Added word spacing logic and improved settings. | |
| -0.1.10 | |
| - Added game mode selector and improved UI feedback. | |
| -0.1.9 | |
| - Improved background and mobile layout. | |
| -0.1.8 | |
| - Updated to Python3.12. | |
| -0.1.5 | |
| - Added hit/miss indicator and improved grid feedback. | |
| -0.1.4 | |
| - Radar visualization improved and mobile layout enhanced. | |
| -0.1.3 | |
| - Added wordlist picker and sort feature. | |
| - Improved score panel and final score display. | |
| ## Known Issues / TODO | |
| - Word list loading bug: the app may not select the proper word lists in some environments. Investigate `word_loader.get_wordlist_files()` / `load_word_list()` and sidebar selection persistence to ensure the chosen file is correctly used by the generator. | |
| ## Development Phases | |
| - **Proof of Concept (0.1.0):** No overlaps, basic UI, single session. | |
| - **Beta (0.5.0):** Overlaps allowed on shared letters, responsive layout, keyboard support, deterministic seed. | |
| - **Full (1.0.0):** Enhanced UX, persistence, leaderboards, daily/practice modes, advanced features. | |
| See `specs/requirements.md` and `specs/specs.md` for full details and roadmap. | |
| ## License | |
| BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner. | |
| ## Hugging Face Spaces Configuration | |
| BattleWords is deployable as a Hugging Face Space. You can use either the YAML config block or a Dockerfile for advanced/custom deployments. | |
| To configure your Space with the YAML block, add it at the top of your `README.md`: | |
| ```yaml | |
| --- | |
| title: BattleWords | |
| emoji: 🎲 | |
| colorFrom: blue | |
| colorTo: indigo | |
| sdk: streamlit | |
| sdk_version:1.25.0 | |
| python_version:3.10 | |
| app_file: app.py | |
| tags: | |
| - game | |
| - vocabulary | |
| - streamlit | |
| - education | |
| --- | |
| ``` | |
| **Key parameters:** | |
| - `title`, `emoji`, `colorFrom`, `colorTo`: Visuals for your Space. | |
| - `sdk`: Use `streamlit` for Streamlit apps. | |
| - `sdk_version`: Latest supported Streamlit version. | |
| - `python_version`: Python version (default is3.10). | |
| - `app_file`: Entry point for your app. | |
| - `tags`: List of descriptive tags. | |
| **Dependencies:** | |
| Add a `requirements.txt` with your Python dependencies (e.g., `streamlit`, etc.). | |
| **Port:** | |
| Streamlit Spaces use port `8501` by default. | |
| **Embedding:** | |
| Spaces can be embedded in other sites using an `<iframe>`: | |
| ```html | |
| <iframe src="https://Surn-BattleWords.hf.space?embed=true" title="BattleWords"></iframe> | |
| ``` | |
| For full configuration options, see [Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference) and [Streamlit SDK Guide](https://huggingface.co/docs/hub/spaces-sdks-streamlit). | |
| # Assets Setup | |
| To fully experience BattleWords, especially the audio elements, ensure you set up the following assets: | |
| - Place your background music `.mp3` files in `battlewords/assets/audio/music/` to enable music. | |
| - Place your sound effect files (`.mp3` or `.wav`) in `battlewords/assets/audio/effects/` for sound effects. | |
| Refer to the documentation for guidance on compatible audio formats and common troubleshooting tips. | |
| # Sound Asset Generation | |
| To generate and save custom sound effects for BattleWords, you can use the `generate_sound_effect` function. | |
| ## Function: `generate_sound_effect` | |
| ```python | |
| def generate_sound_effect(effect: str, save_to_assets: bool = False, use_api: str = "huggingface") -> str: | |
| """ | |
| Generate a sound effect and save it as a file. | |
| Parameters: | |
| - `effect`: Name of the effect to generate. | |
| - `save_to_assets`: If `True`, saves the effect to the assets directory; | |
| if `False`, saves to a temporary location. Default is `False`. | |
| - `use_api`: API to use for generation. Options are "huggingface" or "replicate". Default is "huggingface". | |
| Returns: | |
| - File path to the saved sound effect. | |
| """ | |
| # ... [sound generation code] ... | |
| if save_to_assets: | |
| # Save to effects directory | |
| assets_dir = os.path.join(os.path.dirname(__file__), "assets", "audio", "effects") | |
| os.makedirs(assets_dir, exist_ok=True) | |
| filename = f"{effect}.wav" | |
| path = os.path.join(assets_dir, filename) | |
| with open(path, "wb") as f: | |
| f.write(audio_bytes) | |
| print(f" Saved to: {path}") | |
| else: | |
| # Save to temporary file | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: | |
| tmpfile.write(audio_bytes) | |
| path = tmpfile.name | |
| print(f" Saved to: {path}") | |
| return path | |
| ``` | |
| ## Parameters | |
| - `effect`: The name of the sound effect you want to generate (e.g., "explosion", "powerup"). | |
| - `save_to_assets` (optional): Set to `True` to save the generated sound effect to the game's assets directory. If `False`, the effect is saved to a temporary location. Default is `False`. | |
| - `use_api` (optional): The API to use for generating the sound. Options are `"huggingface"` or `"replicate"`. Default is `"huggingface"`. | |
| ## Returns | |
| - The function returns the file path to the saved sound effect, whether it's in the assets directory or a temporary location. | |
| ## Usage Example | |
| To generate a sound effect and save it to the assets directory: | |
| ```python | |
| generate_sound_effect("your_effect_name", save_to_assets=True) | |
| ``` | |
| To generate a sound effect and keep it in a temporary location: | |
| ```python | |
| temp_path = generate_sound_effect("your_effect_name", save_to_assets=False) | |
| ``` | |
| ## Note | |
| Ensure you have the necessary permissions and API access (if required) to use the sound generation service. Generated sounds are subject to the terms of use of the respective API. | |
| For any issues or enhancements, please refer to the project documentation or contact the project maintainer. | |
| Happy gaming and sound designing! | |
| ## What's New in v0.2.20-0.2.27: Challenge Mode 🎯 | |
| ### Remote Challenge Sharing 🔗 | |
| - Share challenges with friends via short URLs (`?game_id=<sid>`) | |
| - Each player gets different random words from the same wordlist | |
| - Multi-user leaderboards sorted by score and time | |
| - Word list difficulty calculation and display | |
| - Compare your performance against others! | |
| ### Leaderboards 🏆 | |
| - Top 5 players displayed in Challenge Mode banner | |
| - Results sorted by: highest score → fastest time → highest difficulty | |
| - Submit results to existing challenges or create new ones | |
| - Player names supported (optional, defaults to "Anonymous") | |
| ### Remote Storage 💾 | |
| - Challenge data stored in Hugging Face dataset repositories | |
| - Automatic save on game completion (with user consent) | |
| - "Show Challenge Share Links" toggle for privacy control (default OFF) | |
| - Works offline when HF credentials not configured | |
| ## What's Planned for v0.3.0 | |
| ### Local Player History (Coming Soon) | |
| - Personal game results saved locally in `~/.battlewords/data/` | |
| - Offline-capable high score tracking | |
| - Player statistics (games played, averages, bests) | |
| - Privacy-first: no cloud dependency for personal data | |
| - Easy data management (delete `~/.battlewords/data/` to reset) | |