# Wrdler: Implementation Requirements **Version:** 0.1.1 **Status:** Production Ready - AI Enhanced **Last Updated:** 2025-01-31 This document breaks down the implementation tasks for Wrdler using the game rules described in `specs.md`. Wrdler is based on BattleWords but with a simplified 8x6 grid, horizontal-only words, and free letter guesses at the start. **Current Status:** ✅ All Phase 1 requirements complete, 100% tested (25/25 tests passing), AI word generation enhanced in v0.1.1 ## Key Differences from BattleWords - 8x6 grid instead of 12x12 - One word per row (6 total) instead of flexible placement - Horizontal words only (no vertical) - No radar/scope visualization - 2 free letter guesses at game start ## Implementation Details (v0.1.1) - **Tech Stack:** Python 3.12.8, Streamlit 1.51.0, Gradio 5.50, numpy, matplotlib, transformers, gradio_client - **Architecture:** Single-player, local state in Streamlit session state or Gradio gr.State - **Grid:** 8 columns × 6 rows (48 cells) with exactly six words - **Word Placement:** Horizontal-only, one word per row, no overlaps - **AI Generation:** Topic-based word lists with intelligent saving and retry logic - **Entry Points:** - Streamlit: `app.py` - Gradio: `wrdler/gradio_ui.py` or `python -m wrdler.gradio_ui` - **Testing:** pytest with 25/25 tests passing (100%) - **Development Time:** ~12.75 hours across 7 sprints (Phase 1) + AI enhancements - **Gradio Implementation:** Modern API compatible with Gradio 5.50+ - Reference: [Gradio 6 Migration Guide](https://www.gradio.app/guides/gradio-6-migration-guide) - Uses gr.State for game persistence - Event handlers with modern `.click()`, `.change()`, `.submit()` methods - Custom CSS styling via external file ## Streamlit Components (Implemented in v0.0.2) - State & caching ✅ - `st.session_state` for `puzzle`, `grid_rows`, `grid_cols`, `revealed`, `guessed`, `score`, `last_action`, `can_guess` - `st.session_state.points_by_word` for per-word score breakdown - `st.session_state.letter_map` derived from puzzle - `st.session_state.selected_wordlist` for sidebar picker - `st.session_state.show_incorrect_guesses` toggle - `st.session_state.show_challenge_share_links` toggle (default OFF) - `st.session_state.free_letters` and `free_letters_used` for free letter tracking - Layout & structure ✅ - `st.title`, `st.subheader`, `st.markdown` for headers - `st.columns(8)` to render the 8×6 grid (6 rows) - `st.sidebar` for secondary controls - `st.expander` for high scores and stats - Widgets (interaction) ✅ - `st.button` for each grid cell (48 total) with unique `key` - Circular green gradient free letter choice buttons (2 at game start) - `st.form` + `st.text_input` + `st.form_submit_button("OK")` for word guessing - `st.button("New Game")` to reset state - Sidebar `selectbox` for wordlist selection (classic, fourth_grade, wordlist) - Visualization ✅ - Ocean-themed gradient background - No animated radar (removed in Sprint 3) - Responsive 8×6 grid layout - Cell state indicators (unrevealed, letter, empty, completed) - Control flow ✅ - App reruns on interaction using `st.rerun()` - Game over dialog with final score and tier display ## Gradio Components (Implemented in v0.1.1) - State management ✅ - `gr.State(value=create_new_game_state)` for game persistence - State updates use `copy.deepcopy()` to trigger reactivity - Serializable state dict (no complex objects in state) - Layout & structure ✅ - `gr.Blocks()` with custom theme (`theme="Surn/beeuty"`) - `gr.Tabs()` for Game and Settings sections - `gr.Row()` and `gr.Column()` for responsive layout - `gr.Modal()` for share challenge dialog - Widgets (interaction) ✅ - 48 `gr.Button` components for grid cells with dynamic updates - 26 `gr.Button` components for letter selection (only puzzle letters visible) - `gr.Textbox` for word guessing with `.submit()` handler - `gr.Button` for actions (New Game, Guess, Share Challenge) - `gr.Dropdown` for settings (wordlist, game mode) - `gr.Checkbox` for toggles (audio, display options) - `gr.Slider` for volume controls - Visualization ✅ - `gr.HTML()` for score panel with custom styling - `gr.HTML()` for audio player (sound effects) - `gr.HTML()` for game over display - Custom CSS via `style_wrdler.css` file - Responsive grid layout with CSS Grid - Control flow ✅ - Event handlers return component update tuples - `.click()`, `.change()`, `.submit()` for events - `gr.update()` for conditional component updates - State mutations trigger UI updates - Reference ✅ - [Gradio 6 Migration Guide](https://www.gradio.app/guides/gradio-6-migration-guide) - Compatible with Gradio 5.50+ API ## Folder Structure (Implemented) - `app.py` – Streamlit entry point ✅ - `wrdler/` – Python package ✅ - `__init__.py` (version 0.1.0) - `models.py` – data models and types (rectangular grid support) - `word_loader.py` – load/validate/cached word lists - `generator.py` – word placement (8x6, horizontal only, one per row) - `logic.py` – game mechanics (reveal, guess, scoring, tiers, free letters) - `ui.py` – Streamlit UI composition (8×6 grid rendering) - `audio.py` – background music system - `sounds.py` – sound effects management - `game_storage.py` – HF storage wrapper for Challenge Mode - `modules/` – shared utilities (storage, constants, file_utils) - `words/` – word list files (classic.txt, fourth_grade.txt, wordlist.txt) - `specs/` – documentation (specs.md, requirements.md, sprint reports) - `tests/` – unit tests (test_sprint6_integration.py with 7 comprehensive tests) - `static/` – PWA assets (manifest.json, service-worker.js, icons) ## Phase 1: Wrdler v0.0.2 (Complete) ✅ **Goal:** A playable 8x6 grid game with free letter guesses, horizontal-only words, and Challenge Mode support. **Status:** ✅ All requirements complete, 7/7 sprints finished, 100% test pass rate ### 1) Data Models ✅ (Sprint 1) - ✅ `Coord(x:int, y:int)` with `in_bounds_rect()` for rectangular grid validation - ✅ `Word(text:str, start:Coord, direction:str{"H"}, cells:list[Coord])` (H only) - ✅ `Puzzle(words:list[Word], grid_rows:int, grid_cols:int, uid:str)` - ✅ `GameState(grid_rows:int, grid_cols:int, puzzle:Puzzle, revealed:set[Coord], guessed:set[str], score:int, free_letters:set[str], free_letters_used:int, ...)` **Acceptance:** ✅ Types implemented and fully integrated (13/13 tests passing) ### 2) Word List Management ✅ (Sprint 1, Enhanced in v0.1.0-0.1.1) - ✅ English word list filtered to alphabetic uppercase, lengths in {4,5,6} - ✅ Loader centralized in `word_loader.py` with caching - ✅ Three word lists: classic, fourth_grade, wordlist - ✅ **AI word generation** support via `word_loader_ai.py`: - Generates 75 words per topic (25 each of lengths 4, 5, 6) - **Dual generation modes** (v0.1.0+): - HF Space API (primary): Uses Hugging Face Space when `USE_HF_WORDS=true` - Local transformers (fallback): Falls back to local models if HF unavailable - **Intelligent word saving** (v0.1.1): - Smart detection separates existing dictionary words from new AI-generated words - Only saves new words to prevent duplicates - Automatic retry mechanism (up to 3 attempts) if insufficient words generated - 1000-word file size limit prevents dictionary bloat - Auto-sorted by length then alphabetically - **Additional word generation**: Automatically generates more words when MIN_REQUIRED threshold not met - **Enhanced logging**: Detailed pipeline visibility for debugging - ✅ Unified loader (`load_word_list_or_ai`) routes between file-based and AI-generated words - ✅ Saves new AI-generated words to local files for expansion **Acceptance:** ✅ Loading function returns lists by length with >= 25 words per length; AI generation produces valid words with intelligent saving and retry logic ### 3) Puzzle Generation (8x6 Horizontal) ✅ (Sprint 2) - ✅ Randomly place 6 words on 8x6 grid, one per row - ✅ **Word length requirement:** Each puzzle must have exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words - ✅ Constraints: - Horizontal (left→right) only - One word per row (no stacking) - No overlapping letters - ✅ Retry strategy with max attempts - ✅ Deterministic seeding support **Acceptance:** ✅ Generator returns valid `Puzzle` with 6 words, no collisions, in-bounds (5/5 tests passing) ### 4) Free Letter Guesses ✅ (Sprint 4) - ✅ At game start, show 2 circular green gradient buttons for letter selection - ✅ On selection, reveal all instances of that letter in the grid - ✅ Mark as used; disable buttons after 2 uses - ✅ Sound effects play on reveal (hit/miss) - ✅ Set `can_guess=True` after revealing letters **Acceptance:** ✅ Both free letters properly reveal all matching cells; buttons disabled appropriately; UI renders correctly ### 5) Game Mechanics ✅ (Sprint 1, 6) - ✅ Reveal: Click a covered cell to reveal letter or mark empty - ✅ Guess: After revealing, guess word (4-6 letters) - ✅ Scoring: Base + bonus for unrevealed cells - ✅ End: All words guessed or all word letters revealed - ✅ Incorrect guess limit: 10 per game - ✅ Auto-mark completed words when all letters revealed **Acceptance:** ✅ Unit tests cover reveal, guess gating, scoring, tiers, auto-completion (7/7 integration tests passing) ### 6) UI (Streamlit) ✅ (Sprint 5) - ✅ Layout: - Title and instructions - Left: 8×6 grid using `st.columns(8)` with 6 rows - Right: Score panel, guess form, incorrect guess history - Sidebar: New Game, wordlist select, game mode, settings - ✅ Visuals: - Ocean gradient background - Covered vs revealed cell styles (40px buttons) - Completed word highlighting - Free letter selection UI with circular buttons **Acceptance:** ✅ Users can play end-to-end; all features functional; responsive design ### 7) Challenge Mode ✅ (Inherited from BattleWords) - ✅ Parse `game_id` from query params - ✅ Load game settings from HF repo - ✅ Share button generates shareable URL - ✅ Display top 5 leaderboard in Challenge Mode banner - ✅ "Show Challenge Share Links" toggle (default OFF) **Acceptance:** ✅ URL with `game_id` loads correctly; share button works; leaderboard displays properly ### 8) Utility Modules ✅ (Sprint 1) - ✅ Shared utility modules from OpenBadge project - ✅ `modules/__init__.py` exports storage, constants, file_utils - ✅ HuggingFace storage & URL shortener - ✅ File handling and utility functions **Acceptance:** ✅ Modules integrated and functional for Challenge Mode storage ### 9) Comprehensive Tests ✅ (Sprint 6) - ✅ Placement validity (bounds, no overlaps, correct counts) - ✅ Scoring logic and bonuses - ✅ Free letter reveal behavior (2-letter limit) - ✅ Guess gating and word validation - ✅ Game completion detection - ✅ Auto-mark completed words - ✅ State consistency validation **Test Results:** ✅ 25/25 tests passing (100%) ## Sprint Completion Summary (v0.0.2) | Sprint | Description | Time | Tests | Status | |--------|-------------|------|-------|--------| | Sprint 1 | Core Data Models | 3h | 13/13 ✅ | Complete | | Sprint 2 | Puzzle Generator | 3h | 5/5 ✅ | Complete | | Sprint 3 | Remove Radar | 0.5h | N/A | Complete | | Sprint 4 | Free Letters UI | 2h | Manual ✅ | Complete | | Sprint 5 | Grid UI Updates | 1.25h | Syntax ✅ | Complete | | Sprint 6 | Integration Testing | 2h | 7/7 ✅ | Complete | | Sprint 7 | Documentation | 1h | N/A | Complete | | **Total** | **All Features** | **12.75h** | **25/25** | **Complete ✅** | **All known issues resolved. All TODO items completed.** ## Future Roadmap ### v0.3.0 (Next Phase) - 📋 Local persistent storage in `~/.wrdler/data/` - 📋 High score tracking and display - 📋 Player statistics - 📋 Enhanced UI animations ### v0.4.0 (AI Expansion) - 📋 AI difficulty tuning based on player performance - 📋 Custom topic suggestions - 📋 Multi-language word generation - 📋 Word difficulty analysis and visualization ### v1.0.0 (Long Term) - 📋 Multiple difficulty levels - 📋 Daily puzzle mode - 📋 Internationalization (i18n) - 📋 Performance optimizations ## Deployment Targets ✅ ### Supported Platforms (v0.0.2) - ✅ **Hugging Face Spaces** (primary) - Dockerfile deployment - ✅ **Docker** - Containerization with provided Dockerfile - ✅ **Local Development** - Run with `streamlit run app.py` - ✅ **PWA** - Installable as Progressive Web App on desktop and mobile ### Deployment Status **Ready for production deployment!** All features tested and documented. --- **Last Updated:** 2025-01-31 **Version:** 0.1.1 **Status:** Production Ready - AI Enhanced 🚀 ## AI Word Generation Pipeline (v0.1.1) ### Architecture ``` User Input (Topic) ↓ Check USE_HF_WORDS flag ↓ ┌─────────────────────────────────────┐ │ HF Space API (Primary) │ │ - gradio_client integration │ │ - Temperature: 0.95 │ │ - Max tokens: 512 │ └─────────────────────────────────────┘ ↓ (if fails or USE_HF_WORDS=false) ┌─────────────────────────────────────┐ │ Local Transformers (Fallback) │ │ - Auto model selection │ │ - Device auto-detection │ │ - Temperature: 0.7 │ └─────────────────────────────────────┘ ↓ Parse & Filter Words ↓ Identify New vs Existing ↓ Check MIN_REQUIRED threshold ↓ (if insufficient) Generate Additional Words (up to 3 retries) ↓ Save New Words to File ↓ Validate & Sort File ↓ Return 75 Words for Game ``` ### Word Saving Strategy 1. **Detection Phase**: Separate new AI words from existing dictionary words 2. **Validation Phase**: Check if file meets MIN_REQUIRED (25 words per length) 3. **Retry Phase**: If insufficient, generate additional words (up to 3 attempts) 4. **Save Phase**: Write only new words to topic-based file 5. **Sort Phase**: Auto-sort by length then alphabetically 6. **Limit Phase**: Stop adding if file reaches 1000 words ### Error Handling - **HF Space API failure**: Graceful fallback to local model - **Model loading failure**: Try multiple models in priority order - **Device compatibility**: Retry pipeline without device parameter on error 422 - **Insufficient words**: Automatic retry with targeted prompts - **File operations**: Detailed logging and error recovery ## Test File Location All test files must be placed in the `/tests` folder. This ensures a clean project structure and makes it easy to discover and run all tests. ## Gradio 5.50 Implementation Reference ### Migration from Gradio 4.x to 5.x The Gradio UI implementation follows modern Gradio 5.50+ patterns, compatible with the upcoming Gradio 6 release: **Official Reference:** [Gradio 6 Migration Guide](https://www.gradio.app/guides/gradio-6-migration-guide) ### Key Gradio Patterns Used 1. **State Management** ```python game_state = gr.State(value=create_new_game_state) # Updates use deep copy to trigger reactivity new_state = copy.deepcopy(state) new_state["score"] = 42 return new_state ``` 2. **Component Updates** ```python # Dynamic button updates gr.Button(value="X", variant="primary", interactive=True) # Conditional visibility gr.update(visible=True) ``` 3. **Event Handlers** ```python button.click( fn=handler_function, inputs=[input1, input2, state], outputs=[output1, output2, state] ) ``` 4. **Modal Dialogs** ```python with gr.Modal(visible=False, elem_id="modal-id") as modal: gr.Markdown("Modal content") ``` 5. **Custom CSS** ```python with gr.Blocks(css=css_content, theme="Surn/beeuty") as demo: # Components ``` ### Component Compatibility - ✅ `gr.Button` - Modern button API with variant, size, interactive params - ✅ `gr.Textbox` - Text input with submit handler support - ✅ `gr.HTML` - Custom HTML rendering for score panels and audio - ✅ `gr.State` - Serializable state management - ✅ `gr.Dropdown` - Selection widgets for settings - ✅ `gr.Checkbox` - Boolean toggles - ✅ `gr.Slider` - Numeric value controls - ✅ `gr.Tabs` - Multi-section layout - ✅ `gr.Modal` - Dialog overlays - ✅ `gr.Row` / `gr.Column` - Responsive layout containers ### Best Practices 1. **State must be JSON-serializable** - Use dicts/lists, not complex objects 2. **Deep copy for updates** - `copy.deepcopy(state)` triggers reactivity 3. **Return tuples matching outputs** - Order matters for component updates 4. **Use elem_id for CSS targeting** - Consistent IDs for custom styling 5. **Handle None/undefined gracefully** - Check state initialization 6. **Batch updates efficiently** - Return all component changes together ### File Structure - `wrdler/gradio_ui.py` - Main Gradio interface implementation - `style_wrdler.css` - Custom CSS for Gradio components - Both files use Gradio 5.50+ compatible patterns