wrdler / CLAUDE.md
Surn's picture
Initial Commit v0.0.1
4f625d4
|
raw
history blame
16.9 kB

Wrdler - Project Context

Project Overview

Wrdler is a simplified vocabulary puzzle game based on BattleWords, with these key differences:

  • 8x6 grid (instead of 12x12)
  • One word per row, horizontal only (no vertical words)
  • No scope/radar visualization
  • 2 free letter guesses at game start (all instances of chosen letters are revealed)

Current Version: 0.0.1 (Initial Wrdler release) Repository: https://github.com/Oncorporation/Wrdler.git Live Demo: [DEPLOYMENT_URL_HERE]

Recent Changes

Latest (v0.0.1):

  • Project renamed from BattleWords to Wrdler
  • Grid resized from 12x12 to 8x6
  • Removed vertical word placement (horizontal only)
  • Removed scope/radar visualization
  • Added 2 free letter guesses at game start
  • Version reset to 0.0.1
  • All documentation updated to reflect Wrdler specifications

Core Gameplay

  • 8x6 grid with 6 hidden words (one per row, horizontal only)
  • No scope/radar visualization
  • Players start by choosing 2 letters; all instances are revealed
  • 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: Challenge Mode with game sharing via short URLs
  • βœ… IMPLEMENTED: Remote storage via Hugging Face datasets
  • βœ… IMPLEMENTED: PWA install support
  • PLANNED: Local persistent storage for game 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
  • Package Manager: UV

Project Structure

wrdler/
β”œβ”€β”€ app.py                    # Streamlit entry point
β”œβ”€β”€ wrdler/                   # Main package
β”‚   β”œβ”€β”€ __init__.py          # Version: 0.0.1
β”‚   β”œβ”€β”€ 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
β”‚   β”œβ”€β”€ 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
β”‚   β”œβ”€β”€ version_info.py      # Version display
β”‚   β”œβ”€β”€ modules/             # Shared utility modules (from OpenBadge)
β”‚   β”‚   β”œβ”€β”€ __init__.py      # Module exports
β”‚   β”‚   β”œβ”€β”€ storage.py       # HuggingFace storage & URL shortener
β”‚   β”‚   β”œβ”€β”€ 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

  1. Classic Mode: Allows consecutive guessing after correct answers
  2. 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
  • 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
  • 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: ~/.wrdler/data/
    • Files: game_results.json, highscores.json
    • Privacy-first: no cloud dependency, offline-capable
  • 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)

  • Game Grid: Interactive 8x6 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

Completed (v0.2.20-0.2.27 - Challenge Mode):

  • βœ… Imported storage modules from OpenBadge project:
    • wrdler/modules/storage.py (v0.1.5) - HuggingFace storage & URL shortener
    • wrdler/modules/constants.py (trimmed) - Storage-related constants
    • wrdler/modules/file_utils.py - File utility functions
    • wrdler/modules/storage.md - Documentation
  • βœ… Created wrdler/game_storage.py (v0.1.0) - Wrdler storage wrapper:
    • save_game_to_hf() - Save game to HF repo and generate short URL
    • load_game_from_sid() - Load game from short ID
    • generate_uid() - Generate unique game identifiers
    • serialize_game_settings() - Convert game data to JSON
    • get_shareable_url() - Generate shareable URLs
    • add_user_result_to_game() - Append results to existing challenges
  • βœ… UI integration complete (wrdler/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
  • βœ… Generator updates (wrdler/generator.py):
    • Added target_words parameter for loading specific words
    • Added may_overlap parameter (for future crossword mode)
    • Support for shared game replay with randomized word positions

In Progress (v0.3.0 - Local Player History):

  • ⏳ Local storage module (wrdler/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 wrdler .
docker run -p 8501:8501 wrdler

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/Wrdler         # 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_...

HF_REPO_ID Structure: The dataset repository will contain:

  • shortener.json - Short URL mappings
  • games/{uid}/settings.json - Per-game challenge data
  • games/{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: main (or development branch) Purpose: Wrdler - vocabulary puzzle game with simplified 8x6 grid Main Branch: main

Remotes

Known Issues

  • Word list loading bug: App may not select proper word lists in some environments
    • Investigation needed in word_loader.get_wordlist_files() and load_word_list()
    • Sidebar selection persistence needs verification

v0.0.1 Development Status

Completed βœ…

  • Project renamed from BattleWords to Wrdler
  • Grid resized from 12x12 to 8x6
  • Removed vertical word placement (horizontal only)
  • Removed scope/radar visualization
  • Added 2 free letter guesses at game start
  • Updated version to 0.0.1
  • Updated all documentation

In Progress ⏳

  • Generator updates for 8x6 grid and horizontal-only placement
  • UI adjustments for new grid size and free letter guesses
  • Testing with new gameplay mechanics

Planned πŸ“‹

  • Local persistent storage module
  • High score tracking and display
  • Player statistics
  • Share results functionality

Future Roadmap

Phase 1.0 (v0.0.1) - Current βœ…

  • 8x6 grid with horizontal words only
  • Free letter guesses at start
  • Challenge Mode with remote storage
  • PWA support

Phase 2.0 (v0.1.0)

  • Local persistent storage (backend complete)
  • High score tracking and display
  • Player statistics

Phase 3.0 (v1.0.0)

  • Enhanced UX and animations
  • Multiple difficulty levels
  • Daily puzzle mode
  • 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 ~/.wrdler/data/

Notes for Claude

  • Project uses modern Python features (3.12+)
  • Heavy use of Streamlit session state for game state management
  • 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
  • Storage features are backward-compatible (game works without storage)
  • Game IDs are deterministic for consistent sharing
  • JSON storage chosen for simplicity and privacy
  • Generator needs updating to handle 8x6 grid and horizontal-only placement
  • Radar/scope visualization removed entirely

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+.

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 users array in the remote JSON.