# Battlewords Game Requirements (specs.md) ## Overview Battlewords is inspired by the classic Battleship game, but uses words instead of ships. The objective is to discover hidden words on a grid, earning points for strategic guessing before all letters are revealed. ## Game Board - 12 x 12 grid. - Six hidden words: - Two four-letter words - Two five-letter words - Two six-letter words - Words are placed horizontally (left-right) or vertically (top-down), not diagonally. - Words may touch edges or corners but do not overlap unless a future mode allows shared letters. - Entry point is `app.py`. - **Supports Dockerfile-based deployment for Hugging Face Spaces and other container platforms.** ## Gameplay (Common) - Players click grid squares to reveal letters or empty spaces. - Empty revealed squares are styled with CSS class `empty`. - After any reveal, the app immediately reruns (`st.rerun`) to show the change. - Use radar pulses to locate word boundaries (first and last letters). - After revealing a letter, players may guess a word by entering it in a text box. - Guess submission triggers an immediate rerun to reflect results. - Only one guess per letter reveal; must uncover another letter before guessing again. - In the default mode, a correct guess allows chaining an additional guess without another reveal. - **The game ends when all six words are guessed or all word letters are revealed.** ## Scoring - Each correct word guess awards points: - 1 point per letter in the word - Bonus points for each hidden letter at the time of guessing - Score tiers: - Good: 34-37 - Great: 38-41 - Fantastic: 42+ - **Game over is triggered by either all words being guessed or all word letters being revealed.** ## POC (0.1.0) Rules - No overlaps: words do not overlap or share letters. - UI: basic grid, radar, and guess form. - No keyboard interaction requirement. - Seed is optional and not standardized. ## Beta (0.5.0) Additions - Optional validation pass to avoid unintended adjacent partial words (content curation rule). - Cell rendering with consistent sizing and responsive layout (desktop/mobile). - Keyboard support for navigation and guessing (custom JS via `st.html` or a component). - Deterministic seed support to reproduce puzzles (e.g., daily seed derived from date). ## Full (1.0.0) Rules - No overlaps: words do not overlap or share letters. - Enhanced UX polish (animations, accessibility, themes). - Persistence, leaderboards, and additional modes as specified in requirements. - Deterministic daily mode and practice mode supported. ## New Features (v0.3.0) - **Game ID Sharing:** Each puzzle generates a deterministic game ID based on the word list. Players can share URLs with `?game_id=ABC123` to challenge others with the same words. - **Persistent Storage:** Game results and high scores are saved locally in `~/.battlewords/data/`. - **High Scores:** Top scores are tracked and displayed in the sidebar, filterable by wordlist and game mode. - **Player Name:** Optional player name is saved with results. ## New Features (v0.2.28) - **PWA Support:** App is installable as a Progressive Web App on desktop and mobile. - Added `service worker` and `manifest.json`. - Basic offline caching of static assets. - INSTALL_GUIDE.md added with platform-specific install steps. - No gameplay logic changes. ## New Features (v0.2.24) - **UI Improvements:** More compact layout, improved tooltip for incorrect guesses, and updated final score screen. - **Word Difficulty:** Added a word difficulty formula and display for each game/challenge, visible in the final score and leaderboard. - **Challenge Mode:** Enhanced leaderboard with difficulty display, improved result submission, and clearer challenge sharing. - **Documentation:** Updated to reflect new features and UI changes. ## Storage - Game results and high scores are stored in JSON files for privacy and offline access. - Game ID is generated from the sorted word list for replay/sharing. ## UI Elements - 12x12 grid - Radar screen (shows last letter locations); y-axis inverted so (0,0) is top-left - Text box for word guesses - Score display (shows word, base points, bonus points, total score) - Guess status indicator (Correct/Try Again) - Game ID display and share button in game over dialog. - High score expander in sidebar. - Player name input in sidebar. - Checkbox: "Show Challenge Share Links" (v0.2.27, default OFF) - When OFF: - Challenge Mode header hides the Share Challenge link - Game Over dialog still supports submitting/creating challenges, but does not display the generated share URL - Persisted in session state and preserved across "New Game" ## New Features (v0.2.27) - Added "Show Challenge Share Links" visibility toggle for Challenge Mode sharing UI - Purely a UI change; gameplay logic and storage behavior unchanged ## Word List - External list at `battlewords/words/wordlist.txt`. - Loaded by `battlewords.word_loader.load_word_list()` with caching. - Filtered to uppercase A�Z, lengths in {4,5,6}; falls back if < 25 per length. ## Generator - Centralized word loader. - No duplicate word texts are selected. ## Entry Point - The Streamlit entry point is `app.py`. - **A `Dockerfile` can be used for containerized deployment (recommended for Hugging Face Spaces).** ## Deployment Requirements ### Basic Deployment (Offline Mode) No special configuration needed. The app will run with all core gameplay features. Optional: Install as PWA from the browser menu (Add to Home Screen/Install app). ### Challenge Mode Deployment (Remote Storage) Requires HuggingFace Hub integration for challenge sharing and leaderboards. **Required Environment Variables:** ```bash HF_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxx # or HF_TOKEN (write access required) HF_REPO_ID=YourUsername/YourRepo # Target HF dataset repository SPACE_NAME=YourUsername/BattleWords # Your HF Space name for URL generation ``` **Optional Environment Variables:** ```bash CRYPTO_PK= # Reserved for future challenge signing ``` **Setup Steps:** 1. Create a HuggingFace account at https://huggingface.co 2. Create a dataset repository (e.g., `YourUsername/BattleWordsStorage`) 3. Generate an access token with `write` permissions: - Go to https://huggingface.co/settings/tokens - Click "New token" - Select "Write" access - Copy the token (starts with `hf_`) 4. Create a `.env` file in project root with the variables above 5. For Hugging Face Spaces deployment, add these as Space secrets **Repository Structure (automatically created):** ``` HF_REPO_ID/ ├── shortener.json # Short URL mappings (sid -> full URL) └── games/ └── {uid}/ └── settings.json # Challenge data with users array ``` **Data Privacy:** - Challenge Mode stores: word lists, scores, times, game modes, player names - No PII beyond optional player name (defaults to "Anonymous") - Players control URL visibility via "Show Challenge Share Links" setting - App functions fully offline when HF credentials not configured **Deployment Platforms:** - Local development: Run with `streamlit run app.py` - Docker: Use provided `Dockerfile` - Hugging Face Spaces: Dockerfile deployment (recommended) - Any Python 3.10+ hosting with Streamlit support ## Copyright BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner. ## v0.2.20: Remote Storage and Shortened game_id URL Game Sharing - Each puzzle can be shared via a link containing a `game_id` querystring (short id / sid) - `game_id` resolves to a settings JSON on the storage server (HF repo) - JSON fields: - word_list (list of 6 uppercase words) - score (int), time (int seconds) [metadata only] - game_mode (e.g., classic, too easy) - grid_size (e.g., 12) - puzzle_options (e.g., { spacer, may_overlap }) - On load with `game_id`, fetch and apply: word_list, game_mode, grid_size, puzzle_options High Scores - Repository maintains `highscores/highscores.json` for top scores - Local highscores remain supported for offline use UI/UX - Show the current `game_id` (sid) and a �Share Challenge� link - When loading with a `game_id`, indicate the puzzle is a shared challenge Security/Privacy - Only game configuration and scores are stored; no personal data is required - `game_id` is a short reference; full URL is stored in a repo JSON shortener index ## Challenge Mode & Leaderboard - When loading a shared challenge via `game_id`, the leaderboard displays all user results for that challenge. - **Sorting:** The leaderboard is sorted by highest score (descending), then by fastest time (ascending). - **Difficulty:** Each result now displays a computed word list difficulty value. - Results are stored remotely in a Hugging Face dataset repo and updated via the app.