File size: 8,598 Bytes
6829252
 
 
 
4f625d4
 
 
 
6829252
 
4f625d4
 
 
 
 
 
 
 
 
 
 
5f8a848
4f625d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6829252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4f625d4
 
 
 
 
 
6829252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4f625d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f8a848
4f625d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6829252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4f625d4
 
5f8a848
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# Wrdler Game Specifications (specs.md)
**Version:** 0.0.2
**Status:** All Features Complete - Ready for Deployment
**Last Updated:** 2025-01-31

## Overview
Wrdler is a simplified vocabulary puzzle game based on BattleWords, but with key differences. The objective is to discover hidden words on a grid by making strategic guesses and using free letter reveals at the game start.

**Current Status:** All 7 sprints complete, 100% tested, fully documented

## Key Differences from BattleWords
- **8x6 grid** (instead of 12x12)
- **One word per row** (instead of 6 words placed anywhere)
- **Horizontal words only** (no vertical placement)
- **No scope/radar visualization**
- **2 free letter guesses at game start** (all instances of chosen letters are revealed)

## Game Board
- 8 x 6 grid
- Six hidden words:
  - One word per row (row 0-5)
  - **Word composition:** Exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
  - All placed horizontally (left-right)
  - No vertical placement
  - No diagonal placement
  - Words do not overlap
- Entry point is `app.py`
- **Supports Dockerfile-based deployment for Hugging Face Spaces and other container platforms**

## Gameplay (Core)
- Players start by choosing 2 letters; all instances of those letters are revealed in the grid
- 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
- 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**

## Core Rules (v0.0.2 - Implemented)
- βœ… 8x6 grid with one word per row
- βœ… Horizontal words only; no vertical placement
- βœ… No overlaps: words do not overlap or share letters
- βœ… No radar/scope visualization (removed in Sprint 3)
- βœ… 2 free letter guesses at game start (implemented in Sprint 4)
- βœ… Incorrect guess history with optional display
- βœ… 10 incorrect guess limit per game
- βœ… Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal)

## Implemented Features (v0.0.2)

### Challenge Mode
- βœ… **Game ID Sharing:** Each puzzle generates a shareable link with `?game_id=<sid>` to challenge others with the same word list
- βœ… **Remote Storage:** Game results and leaderboards stored in Hugging Face dataset repos
- βœ… **Leaderboards:** Multi-user leaderboards sorted by score (descending) then time (ascending)
- βœ… **Word List Difficulty:** Calculated and displayed for each challenge
- βœ… **Top 5 Display:** Leaderboard banner shows top 5 players
- βœ… **Optional Sharing:** "Show Challenge Share Links" toggle (default OFF) controls URL visibility

### PWA Support
- βœ… **PWA Installation:** 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

## Storage

### Current (v0.0.2)
- βœ… Challenge Mode uses remote storage via Hugging Face datasets
- βœ… Game ID is generated from the word list for replay/sharing

### Planned (v0.3.0)
- πŸ“‹ Local persistent storage for game results and high scores (JSON files)
- πŸ“‹ Local storage location: `~/.wrdler/data/`
- πŸ“‹ Privacy-first offline access

## UI Elements (v0.0.2 - Implemented)
- βœ… 8x6 grid (48 cells total)
- βœ… Free letter guess buttons (2 at game start) - circular green gradient design
- βœ… Text box for word guesses
- βœ… Score display (shows word, base points, bonus points, total score)
- βœ… Guess status indicator (Correct/Try Again)
- βœ… Incorrect guess history display (toggleable)
- βœ… Game ID display and share button in game over dialog
- βœ… Challenge Mode banner with leaderboard (top 5)
- βœ… High score expander in sidebar
- βœ… Player name input in sidebar
- βœ… Checkbox: "Show Challenge Share Links" (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"

## Word List
- External list at `wrdler/words/wordlist.txt`
- Loaded by `wrdler.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
- Horizontal-only word placement
- One word per row in 8x6 grid
- **Word length distribution:** Each puzzle must contain exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
- No word spacing configuration (fixed one word per row)

## 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/Wrdler         # 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/WrdlerStorage`)
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

## Development Status

### Completed (v0.0.2) βœ…
All 7 sprints complete, 100% test coverage (25/25 tests passing):
- **Sprint 1:** Core data models (rectangular grid support)
- **Sprint 2:** Puzzle generator (horizontal-only, one-per-row)
- **Sprint 3:** Radar visualization removal
- **Sprint 4:** Free letter selection UI
- **Sprint 5:** Grid UI updates for 8Γ—6 display
- **Sprint 6:** Integration testing
- **Sprint 7:** Documentation finalization

**Development Time:** ~12.75 hours
**Test Pass Rate:** 100% (25/25 tests)
**Status:** Ready for deployment! πŸš€

### Future Roadmap
- **v0.3.0:** Local persistent storage, high score tracking, player statistics
- **v1.0.0:** Enhanced UX, multiple difficulty levels, daily puzzle mode

## Copyright
Wrdler is based on BattleWords. BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.

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