Surn commited on
Commit
1a984ea
·
1 Parent(s): ea6f44a

v0.2.4 - Add wordlist filters

Browse files

Add word list filtering and update to v0.2.4

Introduced a "Filter Wordlist" feature to remove unwanted words using a blocklist (`assets/filter.txt`). Added a sidebar button and dialog to display filtering results. Enhanced word list management with new filtering logic in `generator.py` and UI updates in `ui.py`.

Updated documentation (`README.md`, `CLAUDE.md`, `requirements.md`, `specs.md`) to reflect the new version and features. Modified word lists to include placeholders and additional content. Added `filter.txt` for blocklist management.

Refactored `generator.py` to include `filter_word_file` and improved `sort_word_file`. Updated CSS styles for the new button. Incremented version to `0.2.4` and updated changelog. Ensured compatibility with `/tests` folder structure.

CLAUDE.md CHANGED
@@ -8,11 +8,11 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords:
8
  - **2 free letter guesses at game start** (all instances revealed)
9
  - **Word composition:** 2 four-letter, 2 five-letter, 2 six-letter words per puzzle
10
 
11
- **Current Version:** 0.2.1
12
  **Repository:** https://github.com/Oncorporation/Wrdler.git
13
  **Branch:** AI (working branch)
14
 
15
- ## Current Features (v0.2.1)
16
 
17
  ### Core Gameplay
18
  - 8x6 grid with 6 hidden words (one per row, horizontal only)
@@ -34,6 +34,11 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords:
34
  - **Good:** 35-38 points
35
  - **Keep practicing:** < 35 points
36
 
 
 
 
 
 
37
  ### Challenge Mode & Remote Storage
38
  - Short URL-based challenge sharing via `?game_id=<sid>`
39
  - Each player gets different random words from same wordlist
 
8
  - **2 free letter guesses at game start** (all instances revealed)
9
  - **Word composition:** 2 four-letter, 2 five-letter, 2 six-letter words per puzzle
10
 
11
+ **Current Version:** 0.2.4
12
  **Repository:** https://github.com/Oncorporation/Wrdler.git
13
  **Branch:** AI (working branch)
14
 
15
+ ## Current Features (v0.2.4)
16
 
17
  ### Core Gameplay
18
  - 8x6 grid with 6 hidden words (one per row, horizontal only)
 
34
  - **Good:** 35-38 points
35
  - **Keep practicing:** < 35 points
36
 
37
+ ### Word List Management
38
+ - Sidebar controls for sorting and filtering word lists
39
+ - Filter capability using `assets/filter.txt` blocklist to remove unwanted words
40
+ - Dialog display of removed words after filtering
41
+
42
  ### Challenge Mode & Remote Storage
43
  - Short URL-based challenge sharing via `?game_id=<sid>`
44
  - Each player gets different random words from same wordlist
README.md CHANGED
@@ -25,7 +25,7 @@ thumbnail: >-
25
 
26
  Wrdler is a vocabulary learning game with a simplified grid and strategic letter guessing. The objective is to discover hidden words on a grid by making smart guesses before all letters are revealed.
27
 
28
- **Current Version:** v0.2.1
29
 
30
  ## Key Differences from BattleWords
31
 
@@ -69,7 +69,7 @@ Wrdler is a vocabulary learning game with a simplified grid and strategic letter
69
 
70
  ### Customization
71
  - Multiple word lists (classic, fourth_grade, wordlist)
72
- - Wordlist sidebar controls (picker + one-click sort)
73
  - Audio volume controls (music and effects separate)
74
 
75
  ### ✅ Challenge Mode
@@ -241,7 +241,13 @@ All test files must be placed in the `/tests` folder. This ensures a clean proje
241
 
242
  ## Changelog
243
 
244
- ### v0.2.1 (Current) ✅
 
 
 
 
 
 
245
  **Daily and Weekly Leaderboards Improved**
246
  - ✅ Settings-based leaderboard separation (unique leaderboards per settings combo)
247
  - ✅ Folder-based discovery system (no index.json)
 
25
 
26
  Wrdler is a vocabulary learning game with a simplified grid and strategic letter guessing. The objective is to discover hidden words on a grid by making smart guesses before all letters are revealed.
27
 
28
+ **Current Version:** v0.2.4
29
 
30
  ## Key Differences from BattleWords
31
 
 
69
 
70
  ### Customization
71
  - Multiple word lists (classic, fourth_grade, wordlist)
72
+ - Wordlist sidebar controls (picker + one-click sort + filter)
73
  - Audio volume controls (music and effects separate)
74
 
75
  ### ✅ Challenge Mode
 
241
 
242
  ## Changelog
243
 
244
+ ### v0.2.4 (Current) ✅
245
+ **Word List Filtering**
246
+ - ✅ Added "Filter Wordlist" button to sidebar
247
+ - ✅ Filters words against `assets/filter.txt` blocklist
248
+ - ✅ Displays dialog with count and list of removed words
249
+
250
+ ### v0.2.1
251
  **Daily and Weekly Leaderboards Improved**
252
  - ✅ Settings-based leaderboard separation (unique leaderboards per settings combo)
253
  - ✅ Folder-based discovery system (no index.json)
specs/requirements.md CHANGED
@@ -1,5 +1,5 @@
1
  # Wrdler: Implementation Requirements
2
- **Version:** 0.2.1
3
  **Status:** Production Ready - Leaderboards Implemented
4
  **Last Updated:** 2025-12-08
5
 
@@ -47,6 +47,7 @@ This document breaks down the implementation tasks for Wrdler using the game rul
47
  - `st.form` + `st.text_input` + `st.form_submit_button("OK")` for word guessing
48
  - `st.button("New Game")` to reset state
49
  - Sidebar `selectbox` for wordlist selection (classic, fourth_grade, wordlist)
 
50
 
51
  - Visualization ✅
52
  - Ocean-themed gradient background
@@ -95,10 +96,14 @@ This document breaks down the implementation tasks for Wrdler using the game rul
95
 
96
  **Acceptance:** ✅ Types implemented and fully integrated (13/13 tests passing)
97
 
98
- ### 2) Word List Management ✅ (Sprint 1, Enhanced in v0.1.0-0.1.1)
99
  - ✅ English word list filtered to alphabetic uppercase, lengths in {4,5,6}
100
  - ✅ Loader centralized in `word_loader.py` with caching
101
  - ✅ Three word lists: classic, fourth_grade, wordlist
 
 
 
 
102
  - ✅ **AI word generation** support via `word_loader_ai.py`:
103
  - Generates 75 words per topic (25 each of lengths 4, 5, 6)
104
  - **Dual generation modes** (v0.1.0+):
 
1
  # Wrdler: Implementation Requirements
2
+ **Version:** 0.2.4
3
  **Status:** Production Ready - Leaderboards Implemented
4
  **Last Updated:** 2025-12-08
5
 
 
47
  - `st.form` + `st.text_input` + `st.form_submit_button("OK")` for word guessing
48
  - `st.button("New Game")` to reset state
49
  - Sidebar `selectbox` for wordlist selection (classic, fourth_grade, wordlist)
50
+ - Sidebar buttons for "Sort Wordlist" and "Filter Wordlist"
51
 
52
  - Visualization ✅
53
  - Ocean-themed gradient background
 
96
 
97
  **Acceptance:** ✅ Types implemented and fully integrated (13/13 tests passing)
98
 
99
+ ### 2) Word List Management ✅ (Sprint 1, Enhanced in v0.1.0-0.1.1, v0.2.4)
100
  - ✅ English word list filtered to alphabetic uppercase, lengths in {4,5,6}
101
  - ✅ Loader centralized in `word_loader.py` with caching
102
  - ✅ Three word lists: classic, fourth_grade, wordlist
103
+ - ✅ **Filter functionality** (v0.2.4):
104
+ - Filter word lists against blocklist (`assets/filter.txt`)
105
+ - Return count and list of removed words
106
+ - Display results in UI dialog
107
  - ✅ **AI word generation** support via `word_loader_ai.py`:
108
  - Generates 75 words per topic (25 each of lengths 4, 5, 6)
109
  - **Dual generation modes** (v0.1.0+):
specs/specs.md CHANGED
@@ -1,5 +1,5 @@
1
  # Wrdler Game Specifications (specs.md)
2
- **Version:** 0.2.1
3
  **Status:** Production Ready - Leaderboards Implemented
4
  **Last Updated:** 2025-12-08
5
 
@@ -61,7 +61,12 @@ Wrdler is a Python/Streamlit vocabulary puzzle game based on BattleWords, but wi
61
  - ✅ 10 incorrect guess limit per game
62
  - ✅ Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal)
63
 
64
- ## Implemented Features (v0.2.1)
 
 
 
 
 
65
 
66
  ### AI Word Generation (v0.1.0+)
67
  - ✅ **Topic-Based Generation:** Create custom word lists for any theme using AI
@@ -268,9 +273,14 @@ HF_REPO_ID/
268
 
269
  ## Development Status
270
 
271
- **Current Version:** 0.2.1 (Production Ready - Leaderboards Implemented)
272
 
273
  ### Completed ✅
 
 
 
 
 
274
  - **v0.2.1:** Daily and Weekly Leaderboards
275
  - Settings-based leaderboard separation
276
  - Folder-based discovery (no index.json)
 
1
  # Wrdler Game Specifications (specs.md)
2
+ **Version:** 0.2.4
3
  **Status:** Production Ready - Leaderboards Implemented
4
  **Last Updated:** 2025-12-08
5
 
 
61
  - ✅ 10 incorrect guess limit per game
62
  - ✅ Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal)
63
 
64
+ ## Implemented Features (v0.2.4)
65
+
66
+ ### Word List Management (v0.2.4)
67
+ - ✅ **Filter Wordlist:** Remove words found in `assets/filter.txt` from the selected word list
68
+ - ✅ **Sort Wordlist:** Sort words by length and alphabetically
69
+ - ✅ **Feedback:** Dialog showing count and list of removed words
70
 
71
  ### AI Word Generation (v0.1.0+)
72
  - ✅ **Topic-Based Generation:** Create custom word lists for any theme using AI
 
273
 
274
  ## Development Status
275
 
276
+ **Current Version:** 0.2.4 (Production Ready - Leaderboards Implemented)
277
 
278
  ### Completed ✅
279
+ - **v0.2.4:** Word List Filtering
280
+ - Added "Filter Wordlist" button to sidebar
281
+ - Implemented blocklist filtering via `assets/filter.txt`
282
+ - Added results dialog showing removed words
283
+
284
  - **v0.2.1:** Daily and Weekly Leaderboards
285
  - Settings-based leaderboard separation
286
  - Folder-based discovery (no index.json)
wrdler/__init__.py CHANGED
@@ -9,5 +9,5 @@ Key differences from BattleWords:
9
  - Daily and weekly leaderboards
10
  """
11
 
12
- __version__ = "0.2.3"
13
  __all__ = ["models", "generator", "logic", "ui", "word_loader", "leaderboard", "leaderboard_page"]
 
9
  - Daily and weekly leaderboards
10
  """
11
 
12
+ __version__ = "0.2.4"
13
  __all__ = ["models", "generator", "logic", "ui", "word_loader", "leaderboard", "leaderboard_page"]
wrdler/assets/filter.txt ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ END
2
+ RAN
3
+ SAW
4
+ WIN
5
+ BUYS
6
+ CALV
7
+ DANS
8
+ ELMY
9
+ ENDS
10
+ FLTE
11
+ FRYD
12
+ GETS
13
+ HARV
14
+ MANU
15
+ NUNC
16
+ OARE
17
+ OPEX
18
+ PAYS
19
+ PUTS
20
+ RADE
21
+ RECT
22
+ ROPS
23
+ RUNS
24
+ SAID
25
+ SAYS
26
+ SEES
27
+ SENT
28
+ SERV
29
+ SIMP
30
+ SITS
31
+ SKIL
32
+ STAM
33
+ SWAM
34
+ TOLD
35
+ TURK
36
+ USED
37
+ USES
38
+ WINS
39
+ ADJAR
40
+ ASKED
41
+ BALLS
42
+ BLTIG
43
+ BOATS
44
+ BOILD
45
+ BOOKS
46
+ BURNS
47
+ BUTTI
48
+ CALLS
49
+ CUEPS
50
+ DEPTS
51
+ DRIED
52
+ FEELS
53
+ FINDS
54
+ FIXED
55
+ FLOWE
56
+ FOMIT
57
+ FOULE
58
+ FRAPS
59
+ FRAZE
60
+ FROWS
61
+ GAMEY
62
+ GIVES
63
+ HARVE
64
+ HELPS
65
+ JABBY
66
+ JOTTY
67
+ JUMPS
68
+ KEEPS
69
+ KICKS
70
+ KITCH
71
+ LIKED
72
+ LISTO
73
+ LOOKS
74
+ LOREY
75
+ LOVED
76
+ LURKY
77
+ MAKES
78
+ MANTO
79
+ MARIN
80
+ MASTO
81
+ MEETS
82
+ MOVES
83
+ OPENS
84
+ PLAYS
85
+ PLOOM
86
+ PREPS
87
+ PUNGY
88
+ PURTY
89
+ READS
90
+ REELD
91
+ REPLA
92
+ REPOS
93
+ RESTS
94
+ RINGS
95
+ ROBSO
96
+ RODER
97
+ RODIN
98
+ ROODY
99
+ ROSEY
100
+ ROUPS
101
+ ROWLS
102
+ RUBED
103
+ RUPES
104
+ RUPTS
105
+ RUYSY
106
+ SAVAN
107
+ SELLS
108
+ SENDS
109
+ SHOWS
110
+ SHRIL
111
+ SINGS
112
+ SKIPS
113
+ SMAKE
114
+ STIRD
115
+ STIRP
116
+ STOPS
117
+ TAKES
118
+ TAXIS
119
+ TELLS
120
+ TEMPP
121
+ TRIED
122
+ TRIES
123
+ TRIMM
124
+ TURNS
125
+ VEGET
126
+ WAITS
127
+ WALKS
128
+ WANTS
129
+ WORKS
130
+ BAROBA
131
+ BAUGHT
132
+ BRAINS
133
+ BREADS
134
+ BROWNS
135
+ BROWNY
136
+ BURSTS
137
+ CALLED
138
+ CHAIRS
139
+ CLOSED
140
+ CLOUDS
141
+ COLORS
142
+ COOKED
143
+ COOKIN
144
+ DANCED
145
+ DANCES
146
+ DREAMS
147
+ DRINKS
148
+ DRIVED
149
+ DRIVES
150
+ EAGLES
151
+ EARTHS
152
+ ELBOWS
153
+ FANATE
154
+ FANOUT
155
+ FLOURD
156
+ GRILLD
157
+ HELPED
158
+ JUMPED
159
+ KNEADD
160
+ KNITWE
161
+ KNOWED
162
+ LEAVES
163
+ LOOKED
164
+ OPENED
165
+ PLAYED
166
+ PULLED
167
+ PUSHED
168
+ REYLES
169
+ ROLLED
170
+ SHOWED
171
+ SINGED
172
+ STANDS
173
+ STARTS
174
+ STUNED
175
+ TAUGHT
176
+ THINKS
177
+ TOUCHS
178
+ TURNED
179
+ WAITED
180
+ WALKED
181
+ WANTED
182
+ WORKED
183
+ WRITES
184
+ ZIPPER
185
+ BUNCHES
186
+ CANDIES
187
+ CARROTS
188
+ CHALKES
189
+ CIRCLES
190
+ CLEANED
191
+ COOKIES
192
+ CORNERS
193
+ COTTONS
194
+ COUSINS
195
+ CRASHED
196
+ CRAYONS
197
+ DANGERS
198
+ DESERTS
199
+ DINNERS
200
+ DOCTORS
201
+ DOLLARS
202
+ DRAGONS
203
+ DRAWERS
204
+ DRESSED
205
+ DRILLED
206
+ DRINKED
207
+ ENGINES
208
+ FARMERS
209
+ FINGERS
210
+ FORESTS
211
+ FRIENDS
212
+ GARDENS
213
+ GLIDERS
214
+ HAMMERS
215
+ HAPPENS
216
+ HOCKEYS
217
+ INSECTS
218
+ ISLANDS
219
+ JACKETS
220
+ JUNGLES
221
+ KITTENS
222
+ LADDERS
223
+ LAUGHED
224
+ LETTERS
225
+ LIZARDS
226
+ MARKETS
227
+ MIRRORS
228
+ MONKEYS
229
+ MOTHERS
230
+ MUFFINS
231
+ NUMBERS
232
+ ORANGES
233
+ PENCILS
234
+ PEPPERS
235
+ PERSONS
236
+ PICNICS
237
+ PILLOWS
238
+ PIRATES
239
+ PLANETS
240
+ POCKETS
241
+ PUZZLES
242
+ RABBITS
243
+ RECORDS
244
+ ROCKETS
245
+ SADDLES
246
+ SEASONS
247
+ SHADOWS
248
+ SILVERS
249
+ SISTERS
250
+ SKATERS
251
+ SOCCERS
252
+ SPIDERS
253
+ SPRINGS
254
+ SQUARES
255
+ STARTED
256
+ STOPPED
257
+ STRINGS
258
+ STUDIED
259
+ SUMMERS
260
+ SUNSETS
261
+ TICKETS
262
+ TISSUES
263
+ TURTLES
264
+ VALLEYS
265
+ WATCHED
266
+ WATCHES
267
+ WINDOWS
268
+ WINTERS
269
+ CHERRIES
270
+ CHICKENS
271
+ FAMILIES
272
+ LISTENED
273
+ POTATOES
274
+ STITCHES
275
+ STOMACHS
wrdler/generator.py CHANGED
@@ -295,4 +295,49 @@ def sort_word_file(filepath: str) -> List[str]:
295
  words = [line.strip() for line in lines if line.strip() and not line.strip().startswith("#")]
296
  # Sort by length, then alphabetically
297
  sorted_words = sorted(words, key=lambda w: (len(w), w))
298
- return sorted_words
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  words = [line.strip() for line in lines if line.strip() and not line.strip().startswith("#")]
296
  # Sort by length, then alphabetically
297
  sorted_words = sorted(words, key=lambda w: (len(w), w))
298
+ return sorted_words
299
+
300
+
301
+ def filter_word_file(filter_filepath: str, target_filepath: str) -> tuple[int, List[str]]:
302
+ """
303
+ Removes words found in filter_filepath from target_filepath.
304
+ Overwrites target_filepath with the filtered content.
305
+ Returns (number of words removed, list of removed words).
306
+ """
307
+ # Read filter words
308
+ try:
309
+ with open(filter_filepath, "r", encoding="utf-8") as f:
310
+ filter_words = {
311
+ line.strip().upper()
312
+ for line in f
313
+ if line.strip() and not line.strip().startswith("#")
314
+ }
315
+ except FileNotFoundError:
316
+ return 0, []
317
+
318
+ # Read target file lines
319
+ with open(target_filepath, "r", encoding="utf-8") as f:
320
+ lines = f.readlines()
321
+
322
+ new_lines = []
323
+ removed_words = []
324
+
325
+ for line in lines:
326
+ stripped = line.strip()
327
+ # Preserve comments and empty lines
328
+ if not stripped or stripped.startswith("#"):
329
+ new_lines.append(line)
330
+ continue
331
+
332
+ # Check if word is in filter list
333
+ if stripped.upper() in filter_words:
334
+ removed_words.append(stripped)
335
+ else:
336
+ new_lines.append(line)
337
+
338
+ # Write back if changes were made
339
+ if removed_words:
340
+ with open(target_filepath, "w", encoding="utf-8") as f:
341
+ f.writelines(new_lines)
342
+
343
+ return len(removed_words), removed_words
wrdler/ui.py CHANGED
@@ -14,7 +14,7 @@ import numpy as np
14
  import time
15
  from datetime import datetime
16
 
17
- from .generator import generate_puzzle, sort_word_file
18
  from .logic import build_letter_map, reveal_cell, reveal_free_letter, guess_word, is_game_over, compute_tier, auto_mark_completed_words, hidden_word_display
19
  from .models import Coord, GameState, Puzzle
20
  from .word_loader import get_wordlist_files, load_word_list, load_word_list_or_ai, compute_word_difficulties, get_wordlist_info
@@ -527,8 +527,8 @@ border-radius: 50% !important;
527
  text-align: center;
528
  }
529
  div[data-testid="stButton"] button { max-width: 100%; aspect-ratio: 16 / 11; border-radius: 0; background: #1d64c8; color: #ffffff; font-weight: 700; padding: 0.5rem 0.75rem; min-height: 2.5rem; min-width: 1.75rem;}
530
- .st-key-new_game_btn, .st-key-sort_wordlist_btn { margin: 0 auto; aspect-ratio: unset; z-index:9999;}
531
- .st-key-new_game_btn > div[data-testid="stButton"] button, .st-key-sort_wordlist_btn > div[data-testid="stButton"] button { aspect-ratio: unset; text-align:center; height: auto;}
532
 
533
  div[data-testid="column"], .st-emotion-cache-zh2fnc { width: auto !important; flex: 1 1 auto !important; min-width: 100% !important; max-width: 100% !important; }
534
  .st-emotion-cache-1permvm, .st-emotion-cache-1n6tfoc { gap:0.25rem !important; min-height: 2.5rem; min-width: 2.5rem;}
@@ -545,7 +545,7 @@ border-radius: 50% !important;
545
  position:relative;
546
  z-index: 1200;
547
  }
548
- .username_input id[="text_input"], .st-key-username_input id[="text_input"] { color: #fff;}
549
  .st-emotion-cache-18kf3ut, .stColumn.st-emotion-cache-116javk {padding-bottom:3px;}
550
 
551
  /* grid adjustments */
@@ -557,7 +557,7 @@ border-radius: 50% !important;
557
  # }
558
  @media (min-width: 560px){
559
  div[data-testid="stButton"] button { max-width: 100%; aspect-ratio: 16 / 11; min-height: 1.75rem; display: flex;}
560
- .st-key-new_game_btn > div[data-testid="stButton"] button, .st-key-sort_wordlist_btn > div[data-testid="stButton"] button { min-height: calc(100% + 20px) !important;}
561
  .st-emotion-cache-ckafi0 { gap:0.1rem !important; min-height: calc(100% + 20px) !important; aspect-ratio: 16 / 11; width: auto !important; flex: 1 1 auto !important; min-width: 100% !important; max-width: 100% !important;}
562
  /*.st-emotion-cache-1n6tfoc { aspect-ratio: 16 / 11; min-height: calc(100% + 20px) !important;}*/
563
  .st-emotion-cache-1n6tfoc::before { min-height: calc(100% + 20px) !important; }
@@ -788,7 +788,7 @@ def _new_game() -> None:
788
  if st.session_state.get("enable_free_letters", False):
789
  st.session_state.last_action = "Welcome to Wrdler! Choose 2 free letters to start."
790
  else:
791
- st.session_state.last_action = "Welcome to Wrdler! Reveal cells and guess words on each line!"
792
  st.session_state.can_guess = False
793
  st.session_state.points_by_word = {}
794
  st.session_state.letter_map = build_letter_map(puzzle)
@@ -1111,6 +1111,8 @@ def _render_sidebar():
1111
  if not st.session_state.use_ai_wordlist:
1112
  if st.button("Sort Wordlist", width=125, key="sort_wordlist_btn"):
1113
  _sort_wordlist(st.session_state.selected_wordlist)
 
 
1114
  else:
1115
  st.info("No word lists found in words/ directory. Using AI or built-in fallback.")
1116
  # Force AI mode if no files available
@@ -1508,6 +1510,21 @@ def _sort_wordlist(filename):
1508
  time.sleep(5) # 5 second delay before starting new game
1509
  _new_game()
1510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1511
  def _render_hit_miss(state: GameState):
1512
  # Determine last reveal outcome from last_action string
1513
  action = (state.last_action or "").strip()
@@ -2233,7 +2250,7 @@ def _game_over_content(state: GameState) -> None:
2233
  else:
2234
  # Do not display the share URL, but confirm it's saved/submitted
2235
  st.success("✅ Your result has been saved.")
2236
-
2237
  # Show leaderboard submission status if already submitted
2238
  if st.session_state.get("leaderboard_submitted", False):
2239
  lb_results = st.session_state.get("leaderboard_results", {})
@@ -2285,12 +2302,24 @@ def _game_over_content(state: GameState) -> None:
2285
  st.rerun()
2286
 
2287
 
 
 
 
 
 
 
 
 
2288
  # Prefer st.dialog/experimental_dialog; fallback to st.modal if unavailable
2289
  _Dialog = getattr(st, "dialog", getattr(st, "experimental_dialog", None))
2290
  if _Dialog:
2291
  @_Dialog("Game Over")
2292
  def _game_over_dialog(state: GameState):
2293
  _game_over_content(state)
 
 
 
 
2294
  else:
2295
  def _game_over_dialog(state: GameState):
2296
  modal_ctx = getattr(st, "modal", None)
@@ -2302,6 +2331,15 @@ else:
2302
  st.subheader("Game Over")
2303
  _game_over_content(state)
2304
 
 
 
 
 
 
 
 
 
 
2305
  def _render_game_over(state: GameState):
2306
  # Use hide_gameover_overlay (same key as run_app) with inverted logic
2307
  visible = not st.session_state.get("hide_gameover_overlay", False) and is_game_over(state)
 
14
  import time
15
  from datetime import datetime
16
 
17
+ from .generator import generate_puzzle, sort_word_file, filter_word_file
18
  from .logic import build_letter_map, reveal_cell, reveal_free_letter, guess_word, is_game_over, compute_tier, auto_mark_completed_words, hidden_word_display
19
  from .models import Coord, GameState, Puzzle
20
  from .word_loader import get_wordlist_files, load_word_list, load_word_list_or_ai, compute_word_difficulties, get_wordlist_info
 
527
  text-align: center;
528
  }
529
  div[data-testid="stButton"] button { max-width: 100%; aspect-ratio: 16 / 11; border-radius: 0; background: #1d64c8; color: #ffffff; font-weight: 700; padding: 0.5rem 0.75rem; min-height: 2.5rem; min-width: 1.75rem;}
530
+ .st-key-new_game_btn, .st-key-sort_wordlist_btn, .st-key-filter_wordlist_btn { margin: 0 auto; aspect-ratio: unset; z-index:9999;}
531
+ .st-key-new_game_btn > div[data-testid="stButton"] button, .st-key-sort_wordlist_btn > div[data-testid="stButton"] button, .st-key-filter_wordlist_btn > div[data-testid="stButton"] button { aspect-ratio: unset; text-align:center; height: auto;}
532
 
533
  div[data-testid="column"], .st-emotion-cache-zh2fnc { width: auto !important; flex: 1 1 auto !important; min-width: 100% !important; max-width: 100% !important; }
534
  .st-emotion-cache-1permvm, .st-emotion-cache-1n6tfoc { gap:0.25rem !important; min-height: 2.5rem; min-width: 2.5rem;}
 
545
  position:relative;
546
  z-index: 1200;
547
  }
548
+ .username_input [id^="text_input"], .st-key-username_input [id^="text_input"] { color: #fff;}
549
  .st-emotion-cache-18kf3ut, .stColumn.st-emotion-cache-116javk {padding-bottom:3px;}
550
 
551
  /* grid adjustments */
 
557
  # }
558
  @media (min-width: 560px){
559
  div[data-testid="stButton"] button { max-width: 100%; aspect-ratio: 16 / 11; min-height: 1.75rem; display: flex;}
560
+ .st-key-new_game_btn > div[data-testid="stButton"] button, .st-key-sort_wordlist_btn > div[data-testid="stButton"] button, .st-key-filter_wordlist_btn > div[data-testid="stButton"] button { min-height: calc(100% + 20px) !important;}
561
  .st-emotion-cache-ckafi0 { gap:0.1rem !important; min-height: calc(100% + 20px) !important; aspect-ratio: 16 / 11; width: auto !important; flex: 1 1 auto !important; min-width: 100% !important; max-width: 100% !important;}
562
  /*.st-emotion-cache-1n6tfoc { aspect-ratio: 16 / 11; min-height: calc(100% + 20px) !important;}*/
563
  .st-emotion-cache-1n6tfoc::before { min-height: calc(100% + 20px) !important; }
 
788
  if st.session_state.get("enable_free_letters", False):
789
  st.session_state.last_action = "Welcome to Wrdler! Choose 2 free letters to start."
790
  else:
791
+ st.session_state.last_action = "Welcome to Wrdler! Reveal cells and guess the words on each line!"
792
  st.session_state.can_guess = False
793
  st.session_state.points_by_word = {}
794
  st.session_state.letter_map = build_letter_map(puzzle)
 
1111
  if not st.session_state.use_ai_wordlist:
1112
  if st.button("Sort Wordlist", width=125, key="sort_wordlist_btn"):
1113
  _sort_wordlist(st.session_state.selected_wordlist)
1114
+ if st.button("Filter Wordlist", width=125, key="filter_wordlist_btn"):
1115
+ _filter_wordlist(st.session_state.selected_wordlist)
1116
  else:
1117
  st.info("No word lists found in words/ directory. Using AI or built-in fallback.")
1118
  # Force AI mode if no files available
 
1510
  time.sleep(5) # 5 second delay before starting new game
1511
  _new_game()
1512
 
1513
+ def _filter_wordlist(filename):
1514
+ filter_path = os.path.join(os.path.dirname(__file__), "assets", "filter.txt")
1515
+ words_path = os.path.join(os.path.dirname(__file__), "words", filename)
1516
+
1517
+ if not os.path.exists(filter_path):
1518
+ st.error("Filter file not found (wrdler/assets/filter.txt).")
1519
+ return
1520
+
1521
+ count, removed_words = filter_word_file(filter_path, words_path)
1522
+
1523
+ if count > 0:
1524
+ _filter_results_dialog(count, removed_words, filename)
1525
+ else:
1526
+ st.info(f"No words removed from {filename}.")
1527
+
1528
  def _render_hit_miss(state: GameState):
1529
  # Determine last reveal outcome from last_action string
1530
  action = (state.last_action or "").strip()
 
2250
  else:
2251
  # Do not display the share URL, but confirm it's saved/submitted
2252
  st.success("✅ Your result has been saved.")
2253
+
2254
  # Show leaderboard submission status if already submitted
2255
  if st.session_state.get("leaderboard_submitted", False):
2256
  lb_results = st.session_state.get("leaderboard_results", {})
 
2302
  st.rerun()
2303
 
2304
 
2305
+ def _filter_results_content(count: int, words: list[str], filename: str):
2306
+ st.success(f"Removed {count} words from {filename}")
2307
+ st.markdown("### Removed Words")
2308
+ st.text_area("List", value="\n".join(words), height=200, disabled=True)
2309
+ if st.button("Close", key="close_filter_dialog"):
2310
+ st.rerun()
2311
+
2312
+
2313
  # Prefer st.dialog/experimental_dialog; fallback to st.modal if unavailable
2314
  _Dialog = getattr(st, "dialog", getattr(st, "experimental_dialog", None))
2315
  if _Dialog:
2316
  @_Dialog("Game Over")
2317
  def _game_over_dialog(state: GameState):
2318
  _game_over_content(state)
2319
+
2320
+ @_Dialog("Filter Results")
2321
+ def _filter_results_dialog(count, words, filename):
2322
+ _filter_results_content(count, words, filename)
2323
  else:
2324
  def _game_over_dialog(state: GameState):
2325
  modal_ctx = getattr(st, "modal", None)
 
2331
  st.subheader("Game Over")
2332
  _game_over_content(state)
2333
 
2334
+ def _filter_results_dialog(count, words, filename):
2335
+ modal_ctx = getattr(st, "modal", None)
2336
+ if callable(modal_ctx):
2337
+ with modal_ctx("Filter Results"):
2338
+ _filter_results_content(count, words, filename)
2339
+ else:
2340
+ st.info(f"Removed {count} words from {filename}")
2341
+ st.text_area("Removed Words", value="\n".join(words), height=200)
2342
+
2343
  def _render_game_over(state: GameState):
2344
  # Use hide_gameover_overlay (same key as run_app) with inverted logic
2345
  visible = not st.session_state.get("hide_gameover_overlay", False) and is_game_over(state)
wrdler/words/cooking.txt CHANGED
@@ -1,16 +1,11 @@
1
- # AI-generated word list
2
- # Topic: COOKing
3
- # Last updated: 2025-11-28 12:16:45
4
- # Total words: 174
5
- # Format: one word per line, sorted by length then alphabetically
6
- #
7
  BAKE
8
  BEEN
9
  BLUE
10
  BOIL
11
  BUFF
12
  CAKE
13
- CALV
14
  CARD
15
  COOK
16
  FARM
@@ -20,15 +15,12 @@ FIRE
20
  FISH
21
  FIZZ
22
  FOOD
23
- FRYD
24
- HARV
25
  HERB
26
  JUST
27
  KEEN
28
  KERN
29
  KING
30
  MAKE
31
- MANU
32
  MASH
33
  MEAT
34
  MINI
@@ -39,13 +31,10 @@ POUR
39
  PREP
40
  PUFF
41
  RACK
42
- RECT
43
  ROLL
44
  SEAR
45
  SEEK
46
  SIFT
47
- SIMP
48
- SKIL
49
  SKIP
50
  SLOW
51
  SOFT
@@ -54,7 +43,6 @@ STEW
54
  STIR
55
  TAKE
56
  THAW
57
- TURK
58
  VEAL
59
  WARM
60
  WASH
@@ -66,12 +54,8 @@ BAKED
66
  BASTE
67
  BLANK
68
  BLEND
69
- BLTIG
70
- BOATS
71
- BOILD
72
  BREAD
73
  BROWN
74
- BUTTI
75
  CANDY
76
  CARBS
77
  CHICK
@@ -79,7 +63,6 @@ CHILL
79
  CLEAN
80
  CRUMB
81
  CRUST
82
- DRIED
83
  FLAKY
84
  FRIED
85
  FRUIT
@@ -88,50 +71,38 @@ GLAZE
88
  GRAIN
89
  GRASS
90
  GRILL
91
- HARVE
92
  HERBS
93
  HOUSE
94
- KITCH
95
  KNEAD
96
- MARIN
97
  MIXED
98
  MIXER
99
  PASTA
100
  PLATE
101
- PREPS
102
  PUREE
103
  QUICK
104
  ROAST
105
- RUBED
106
  SALAD
107
  SALTY
108
  SAUTE
109
  SCONE
110
  SHAVE
111
- SHRIL
112
  SLICE
113
  SLICK
114
- SMAKE
115
  SPICE
116
  SPICY
117
  SPIRE
118
  START
119
  STEAK
120
  STICK
121
- STIRD
122
- STIRP
123
  STOVE
124
  SWEET
125
  TASTE
126
  TASTY
127
- TEMPP
128
  THINK
129
  TOAST
130
  TREAT
131
- TRIMM
132
  TWIST
133
  UNDER
134
- VEGET
135
  WHISK
136
  WIELD
137
  YIELD
@@ -139,27 +110,19 @@ ZESTY
139
  ASSERT
140
  BARELY
141
  BARKED
142
- BAROBA
143
  BATTER
144
- BAUGHT
145
  BAZAAR
146
  BITTER
147
  BOILED
148
- BROWNY
149
  CARROT
150
  CHEESE
151
- COOKED
152
  COOKER
153
- COOKIN
154
  DETAIL
155
  DILUTE
156
  EATING
157
- FLOURD
158
  FLYING
159
  FROZEN
160
  GRATED
161
- GRILLD
162
- KNEADD
163
  LITTLE
164
  MARINA
165
  MASHED
@@ -176,5 +139,4 @@ SMOOTH
176
  SNAKES
177
  SPICED
178
  TASTES
179
- TOUCHS
180
  VEGGIE
 
1
+ # Optional: place a large A–Z word list here (one word per line).
2
+ # The app falls back to built-in pools if fewer than 500 words per length are found.
 
 
 
 
3
  BAKE
4
  BEEN
5
  BLUE
6
  BOIL
7
  BUFF
8
  CAKE
 
9
  CARD
10
  COOK
11
  FARM
 
15
  FISH
16
  FIZZ
17
  FOOD
 
 
18
  HERB
19
  JUST
20
  KEEN
21
  KERN
22
  KING
23
  MAKE
 
24
  MASH
25
  MEAT
26
  MINI
 
31
  PREP
32
  PUFF
33
  RACK
 
34
  ROLL
35
  SEAR
36
  SEEK
37
  SIFT
 
 
38
  SKIP
39
  SLOW
40
  SOFT
 
43
  STIR
44
  TAKE
45
  THAW
 
46
  VEAL
47
  WARM
48
  WASH
 
54
  BASTE
55
  BLANK
56
  BLEND
 
 
 
57
  BREAD
58
  BROWN
 
59
  CANDY
60
  CARBS
61
  CHICK
 
63
  CLEAN
64
  CRUMB
65
  CRUST
 
66
  FLAKY
67
  FRIED
68
  FRUIT
 
71
  GRAIN
72
  GRASS
73
  GRILL
 
74
  HERBS
75
  HOUSE
 
76
  KNEAD
 
77
  MIXED
78
  MIXER
79
  PASTA
80
  PLATE
 
81
  PUREE
82
  QUICK
83
  ROAST
 
84
  SALAD
85
  SALTY
86
  SAUTE
87
  SCONE
88
  SHAVE
 
89
  SLICE
90
  SLICK
 
91
  SPICE
92
  SPICY
93
  SPIRE
94
  START
95
  STEAK
96
  STICK
 
 
97
  STOVE
98
  SWEET
99
  TASTE
100
  TASTY
 
101
  THINK
102
  TOAST
103
  TREAT
 
104
  TWIST
105
  UNDER
 
106
  WHISK
107
  WIELD
108
  YIELD
 
110
  ASSERT
111
  BARELY
112
  BARKED
 
113
  BATTER
 
114
  BAZAAR
115
  BITTER
116
  BOILED
 
117
  CARROT
118
  CHEESE
 
119
  COOKER
 
120
  DETAIL
121
  DILUTE
122
  EATING
 
123
  FLYING
124
  FROZEN
125
  GRATED
 
 
126
  LITTLE
127
  MARINA
128
  MASHED
 
139
  SNAKES
140
  SPICED
141
  TASTES
 
142
  VEGGIE
wrdler/words/english.txt CHANGED
@@ -1,9 +1,5 @@
1
- # AI-generated word list
2
- # Topic: English
3
- # Last updated: 2025-12-04 10:32:04
4
- # Total words: 601
5
- # Format: one word per line, sorted by length then alphabetically
6
- #
7
  ALES
8
  ALMS
9
  ARMY
 
1
+ # Optional: place a large A–Z word list here (one word per line).
2
+ # The app falls back to built-in pools if fewer than 500 words per length are found.
 
 
 
 
3
  ALES
4
  ALMS
5
  ARMY
wrdler/words/fourth_grade.txt CHANGED
@@ -1,3 +1,5 @@
 
 
1
  area
2
  ball
3
  band
@@ -94,6 +96,9 @@ stay
94
  step
95
  stop
96
  tail
 
 
 
97
  team
98
  tent
99
  test
@@ -118,6 +123,8 @@ board
118
  brain
119
  bread
120
  brush
 
 
121
  candy
122
  chair
123
  chalk
@@ -130,23 +137,44 @@ clean
130
  clock
131
  cloud
132
  color
 
 
 
 
133
  count
134
  cover
135
  crash
136
  cross
137
  dance
 
 
 
138
  dress
 
 
139
  drink
 
 
140
  drive
 
 
141
  eagle
 
 
 
 
142
  earth
 
 
143
  elbow
 
 
 
144
  empty
145
  fence
146
  field
147
  flash
148
  floor
149
- flower
150
  frame
151
  fruit
152
  glass
@@ -180,7 +208,6 @@ queen
180
  radio
181
  river
182
  salty
183
- school
184
  shape
185
  shark
186
  sheep
@@ -221,374 +248,347 @@ white
221
  witch
222
  world
223
  write
224
- yellow
225
- animal
226
- answer
227
- autumn
228
- bamboo
229
- banana
230
- basket
231
- battle
232
- beaver
233
- bellow
234
- bottle
235
- bridge
236
- bubble
237
- butter
238
- button
239
- cactus
240
- camera
241
- candle
242
- canyon
243
- carrot
244
- castle
245
- circle
246
- circus
247
- cotton
248
- cousin
249
- crayon
250
- desert
251
- dinner
252
- doctor
253
- dollar
254
- dragon
255
- drawer
256
- engine
257
- family
258
- farmer
259
- finger
260
- forest
261
- friend
262
- garden
263
- glider
264
- hammer
265
- happen
266
- hockey
267
- insect
268
- island
269
- jacket
270
- jungle
271
- kitten
272
- ladder
273
- letter
274
- lizard
275
- market
276
- mirror
277
- monkey
278
- mother
279
- muffin
280
- number
281
- orange
282
- pencil
283
- pepper
284
- person
285
- picnic
286
- pillow
287
- pirate
288
- planet
289
- pocket
290
- potato
291
- puzzle
292
- rabbit
293
- record
294
- rocket
295
- saddle
296
- season
297
- shadow
298
- silver
299
- sister
300
- skater
301
- soccer
302
- spider
303
- spring
304
- square
305
- stitch
306
- stomach
307
- string
308
- summer
309
- sunset
310
- taxi
311
- ticket
312
- tissue
313
- turtle
314
- valley
315
- window
316
- winter
317
- zipper
318
  accept
 
 
319
  across
320
  action
 
 
321
  active
322
  anchor
 
 
 
 
323
  arrive
324
  artist
 
 
325
  asleep
326
  attack
 
 
 
327
  awaken
328
  baking
329
- balloon
 
 
 
330
  barrel
 
 
331
  beauty
 
 
332
  behave
 
 
333
  behind
334
  belief
 
 
335
  belong
 
 
336
  better
337
  bitter
338
- blanket
 
339
  border
 
 
340
  bottom
341
  breeze
 
 
342
  bright
 
 
343
  broken
 
344
  bucket
345
- bunny
 
346
  burrow
 
 
347
  button
 
 
348
  cactus
 
 
349
  camera
350
  candle
 
 
 
 
351
  canyon
352
  carrot
 
 
 
 
353
  castle
354
  cement
 
 
355
  center
356
  chance
 
 
357
  change
358
  charge
 
 
359
  cheese
360
  cherry
361
- chicken
 
362
  circle
 
 
363
  circus
 
 
364
  closer
365
  cloudy
 
 
366
  coffee
367
  collar
368
- color
 
369
  comedy
370
- comic
371
  common
 
 
372
  corner
373
  cotton
 
 
374
  cousin
 
 
 
 
375
  crayon
376
  create
 
 
377
  danger
378
  decide
 
 
379
  degree
380
  desert
 
 
 
 
381
  dinner
382
  doctor
 
 
 
383
  dollar
 
 
 
384
  dragon
385
  drawer
386
- dream
387
- dress
388
- drink
389
- drive
390
- eagle
391
- early
392
- earth
393
- elbow
394
- empty
395
  engine
 
 
396
  family
 
 
397
  farmer
 
 
398
  finger
 
 
399
  forest
 
 
 
 
400
  friend
401
  garden
 
 
 
402
  glider
 
 
403
  hammer
 
 
404
  happen
 
 
405
  hockey
 
 
406
  insect
 
 
407
  island
 
 
408
  jacket
 
 
409
  jungle
 
 
410
  kitten
 
 
411
  ladder
 
 
412
  letter
 
 
413
  lizard
 
 
414
  market
 
 
415
  mirror
 
 
416
  monkey
 
 
 
417
  mother
418
  muffin
 
 
 
 
419
  number
420
  orange
 
 
 
 
421
  pencil
422
  pepper
 
 
 
 
423
  person
424
  picnic
 
 
 
 
425
  pillow
426
  pirate
 
 
 
 
427
  planet
428
  pocket
 
 
 
 
429
  potato
430
  puzzle
 
 
 
 
431
  rabbit
432
  record
 
 
 
433
  rocket
 
 
434
  saddle
 
 
435
  season
 
 
 
 
436
  shadow
437
  silver
 
 
 
 
438
  sister
439
  skater
 
 
 
 
440
  soccer
441
  spider
 
 
 
 
442
  spring
443
  square
 
 
444
  stitch
445
- stomach
 
 
446
  string
 
 
 
447
  summer
448
  sunset
449
- taxi
 
 
450
  ticket
 
 
451
  tissue
 
 
452
  turtle
 
 
453
  valley
 
 
454
  window
 
 
455
  winter
 
 
456
  zipper
457
- accept
458
- across
459
- action
460
- active
461
- anchor
462
- arrive
463
- artist
464
- asleep
465
- attack
466
- awaken
467
- baking
468
  balloon
469
- barrel
470
- beauty
471
- behave
472
- behind
473
- belief
474
- belong
475
- better
476
- bitter
477
  blanket
478
- border
479
- bottom
480
- breeze
481
- bright
482
- broken
483
- bucket
484
- bunny
485
- burrow
486
- button
487
- cactus
488
- candle
489
- canyon
490
- carrot
491
- castle
492
- cement
493
- center
494
- chance
495
- change
496
- charge
497
- cheese
498
- cherry
499
  chicken
500
- circle
501
- circus
502
- closer
503
- cloudy
504
- coffee
505
- collar
506
- color
507
- comedy
508
- comic
509
- common
510
- corner
511
- cotton
512
- cousin
513
- crayon
514
- create
515
- danger
516
- decide
517
- degree
518
- desert
519
- dinner
520
- doctor
521
- dollar
522
- dragon
523
- drawer
524
- dream
525
- dress
526
- drink
527
- drive
528
- eagle
529
- early
530
- earth
531
- elbow
532
- empty
533
- engine
534
- family
535
- farmer
536
- finger
537
- forest
538
- friend
539
- garden
540
- glider
541
- hammer
542
- happen
543
- hockey
544
- insect
545
- island
546
- jacket
547
- jungle
548
- kitten
549
- ladder
550
- letter
551
- lizard
552
- market
553
- mirror
554
- monkey
555
- mother
556
- muffin
557
- number
558
- orange
559
- pencil
560
- pepper
561
- person
562
- picnic
563
- pillow
564
- pirate
565
- planet
566
- pocket
567
- potato
568
- puzzle
569
- rabbit
570
- record
571
- rocket
572
- saddle
573
- season
574
- shadow
575
- silver
576
- sister
577
- skater
578
- soccer
579
- spider
580
- spring
581
- square
582
- stitch
583
  stomach
584
- string
585
- summer
586
- sunset
587
- taxi
588
- ticket
589
- tissue
590
- turtle
591
- valley
592
- window
593
- winter
594
- zipper
 
1
+ # Optional: place a large A–Z word list here (one word per line).
2
+ # The app falls back to built-in pools if fewer than 500 words per length are found.
3
  area
4
  ball
5
  band
 
96
  step
97
  stop
98
  tail
99
+ taxi
100
+ taxi
101
+ taxi
102
  team
103
  tent
104
  test
 
123
  brain
124
  bread
125
  brush
126
+ bunny
127
+ bunny
128
  candy
129
  chair
130
  chalk
 
137
  clock
138
  cloud
139
  color
140
+ color
141
+ color
142
+ comic
143
+ comic
144
  count
145
  cover
146
  crash
147
  cross
148
  dance
149
+ dream
150
+ dream
151
+ dress
152
  dress
153
+ dress
154
+ drink
155
  drink
156
+ drink
157
+ drive
158
  drive
159
+ drive
160
+ eagle
161
  eagle
162
+ eagle
163
+ early
164
+ early
165
+ earth
166
  earth
167
+ earth
168
+ elbow
169
  elbow
170
+ elbow
171
+ empty
172
+ empty
173
  empty
174
  fence
175
  field
176
  flash
177
  floor
 
178
  frame
179
  fruit
180
  glass
 
208
  radio
209
  river
210
  salty
 
211
  shape
212
  shark
213
  sheep
 
248
  witch
249
  world
250
  write
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  accept
252
+ accept
253
+ across
254
  across
255
  action
256
+ action
257
+ active
258
  active
259
  anchor
260
+ anchor
261
+ animal
262
+ answer
263
+ arrive
264
  arrive
265
  artist
266
+ artist
267
+ asleep
268
  asleep
269
  attack
270
+ attack
271
+ autumn
272
+ awaken
273
  awaken
274
  baking
275
+ baking
276
+ bamboo
277
+ banana
278
+ barrel
279
  barrel
280
+ basket
281
+ battle
282
  beauty
283
+ beauty
284
+ beaver
285
  behave
286
+ behave
287
+ behind
288
  behind
289
  belief
290
+ belief
291
+ bellow
292
  belong
293
+ belong
294
+ better
295
  better
296
  bitter
297
+ bitter
298
+ border
299
  border
300
+ bottle
301
+ bottom
302
  bottom
303
  breeze
304
+ breeze
305
+ bridge
306
  bright
307
+ bright
308
+ broken
309
  broken
310
+ bubble
311
  bucket
312
+ bucket
313
+ burrow
314
  burrow
315
+ butter
316
+ button
317
  button
318
+ button
319
+ cactus
320
  cactus
321
+ cactus
322
+ camera
323
  camera
324
  candle
325
+ candle
326
+ candle
327
+ canyon
328
+ canyon
329
  canyon
330
  carrot
331
+ carrot
332
+ carrot
333
+ castle
334
+ castle
335
  castle
336
  cement
337
+ cement
338
+ center
339
  center
340
  chance
341
+ chance
342
+ change
343
  change
344
  charge
345
+ charge
346
+ cheese
347
  cheese
348
  cherry
349
+ cherry
350
+ circle
351
  circle
352
+ circle
353
+ circus
354
  circus
355
+ circus
356
+ closer
357
  closer
358
  cloudy
359
+ cloudy
360
+ coffee
361
  coffee
362
  collar
363
+ collar
364
+ comedy
365
  comedy
 
366
  common
367
+ common
368
+ corner
369
  corner
370
  cotton
371
+ cotton
372
+ cotton
373
  cousin
374
+ cousin
375
+ cousin
376
+ crayon
377
+ crayon
378
  crayon
379
  create
380
+ create
381
+ danger
382
  danger
383
  decide
384
+ decide
385
+ degree
386
  degree
387
  desert
388
+ desert
389
+ desert
390
+ dinner
391
+ dinner
392
  dinner
393
  doctor
394
+ doctor
395
+ doctor
396
+ dollar
397
  dollar
398
+ dollar
399
+ dragon
400
+ dragon
401
  dragon
402
  drawer
403
+ drawer
404
+ drawer
405
+ engine
 
 
 
 
 
 
406
  engine
407
+ engine
408
+ family
409
  family
410
+ family
411
+ farmer
412
  farmer
413
+ farmer
414
+ finger
415
  finger
416
+ finger
417
+ flower
418
  forest
419
+ forest
420
+ forest
421
+ friend
422
+ friend
423
  friend
424
  garden
425
+ garden
426
+ garden
427
+ glider
428
  glider
429
+ glider
430
+ hammer
431
  hammer
432
+ hammer
433
+ happen
434
  happen
435
+ happen
436
+ hockey
437
  hockey
438
+ hockey
439
+ insect
440
  insect
441
+ insect
442
+ island
443
  island
444
+ island
445
+ jacket
446
  jacket
447
+ jacket
448
+ jungle
449
  jungle
450
+ jungle
451
+ kitten
452
  kitten
453
+ kitten
454
+ ladder
455
  ladder
456
+ ladder
457
+ letter
458
  letter
459
+ letter
460
+ lizard
461
  lizard
462
+ lizard
463
+ market
464
  market
465
+ market
466
+ mirror
467
  mirror
468
+ mirror
469
+ monkey
470
  monkey
471
+ monkey
472
+ mother
473
+ mother
474
  mother
475
  muffin
476
+ muffin
477
+ muffin
478
+ number
479
+ number
480
  number
481
  orange
482
+ orange
483
+ orange
484
+ pencil
485
+ pencil
486
  pencil
487
  pepper
488
+ pepper
489
+ pepper
490
+ person
491
+ person
492
  person
493
  picnic
494
+ picnic
495
+ picnic
496
+ pillow
497
+ pillow
498
  pillow
499
  pirate
500
+ pirate
501
+ pirate
502
+ planet
503
+ planet
504
  planet
505
  pocket
506
+ pocket
507
+ pocket
508
+ potato
509
+ potato
510
  potato
511
  puzzle
512
+ puzzle
513
+ puzzle
514
+ rabbit
515
+ rabbit
516
  rabbit
517
  record
518
+ record
519
+ record
520
+ rocket
521
  rocket
522
+ rocket
523
+ saddle
524
  saddle
525
+ saddle
526
+ school
527
  season
528
+ season
529
+ season
530
+ shadow
531
+ shadow
532
  shadow
533
  silver
534
+ silver
535
+ silver
536
+ sister
537
+ sister
538
  sister
539
  skater
540
+ skater
541
+ skater
542
+ soccer
543
+ soccer
544
  soccer
545
  spider
546
+ spider
547
+ spider
548
+ spring
549
+ spring
550
  spring
551
  square
552
+ square
553
+ square
554
  stitch
555
+ stitch
556
+ stitch
557
+ string
558
  string
559
+ string
560
+ summer
561
+ summer
562
  summer
563
  sunset
564
+ sunset
565
+ sunset
566
+ ticket
567
  ticket
568
+ ticket
569
+ tissue
570
  tissue
571
+ tissue
572
+ turtle
573
  turtle
574
+ turtle
575
+ valley
576
  valley
577
+ valley
578
+ window
579
  window
580
+ window
581
+ winter
582
  winter
583
+ winter
584
+ yellow
585
  zipper
 
 
 
 
 
 
 
 
 
 
 
586
  balloon
587
+ balloon
588
+ blanket
 
 
 
 
 
 
589
  blanket
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
590
  chicken
591
+ chicken
592
+ stomach
593
+ stomach
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  stomach
 
 
 
 
 
 
 
 
 
 
 
wrdler/words/sports.txt CHANGED
@@ -1,12 +1,9 @@
1
- # AI-generated word list
2
- # Topic: sporTS
3
- # Last updated: 2025-12-04 10:41:42
4
- # Total words: 164
5
- # Format: one word per line, sorted by length then alphabetically
6
- #
7
  ARMS
8
  BALL
9
  BASK
 
10
  BOWS
11
  BULL
12
  DART
@@ -21,6 +18,7 @@ GAIN
21
  GALE
22
  GENT
23
  GILD
 
24
  HALE
25
  HARE
26
  HINT
@@ -29,6 +27,7 @@ HOOP
29
  HOPS
30
  HUES
31
  JAWS
 
32
  JUMP
33
  KICK
34
  LANE
@@ -47,15 +46,14 @@ SHIP
47
  SHOE
48
  SOAR
49
  SOFA
 
50
  SPAN
51
  SWIM
52
  TALK
53
  WING
54
  BAILS
55
- BALLS
56
  BENCH
57
  BENDS
58
- BOWL
59
  CHAMP
60
  CLUBS
61
  CURLS
@@ -71,8 +69,8 @@ FLARE
71
  FLAWS
72
  FLICK
73
  FLINT
74
- FLUTE
75
  FLUKE
 
76
  GAINS
77
  GAMER
78
  GAMES
@@ -82,14 +80,12 @@ GOLFS
82
  GOUTS
83
  GRAFT
84
  GROAN
85
- GUNS
86
  HAILS
87
  HEATS
88
  HEELS
89
  HOOPS
90
  HORNS
91
  HORSE
92
- JINX
93
  JOLTS
94
  KNITS
95
  LANCE
@@ -120,7 +116,6 @@ SLIDE
120
  SLIPS
121
  SLOPE
122
  SOLES
123
- SOLO
124
  SPITE
125
  SPOKE
126
  SPOON
@@ -137,7 +132,6 @@ TABLE
137
  TEAMS
138
  TRACK
139
  TRAMP
140
- TURNS
141
  WREST
142
  BASKET
143
  BIKERS
@@ -167,4 +161,4 @@ STITCH
167
  SURFER
168
  SURVEY
169
  TAILOR
170
- WINNER
 
1
+ # Optional: place a large A–Z word list here (one word per line).
2
+ # The app falls back to built-in pools if fewer than 500 words per length are found.
 
 
 
 
3
  ARMS
4
  BALL
5
  BASK
6
+ BOWL
7
  BOWS
8
  BULL
9
  DART
 
18
  GALE
19
  GENT
20
  GILD
21
+ GUNS
22
  HALE
23
  HARE
24
  HINT
 
27
  HOPS
28
  HUES
29
  JAWS
30
+ JINX
31
  JUMP
32
  KICK
33
  LANE
 
46
  SHOE
47
  SOAR
48
  SOFA
49
+ SOLO
50
  SPAN
51
  SWIM
52
  TALK
53
  WING
54
  BAILS
 
55
  BENCH
56
  BENDS
 
57
  CHAMP
58
  CLUBS
59
  CURLS
 
69
  FLAWS
70
  FLICK
71
  FLINT
 
72
  FLUKE
73
+ FLUTE
74
  GAINS
75
  GAMER
76
  GAMES
 
80
  GOUTS
81
  GRAFT
82
  GROAN
 
83
  HAILS
84
  HEATS
85
  HEELS
86
  HOOPS
87
  HORNS
88
  HORSE
 
89
  JOLTS
90
  KNITS
91
  LANCE
 
116
  SLIPS
117
  SLOPE
118
  SOLES
 
119
  SPITE
120
  SPOKE
121
  SPOON
 
132
  TEAMS
133
  TRACK
134
  TRAMP
 
135
  WREST
136
  BASKET
137
  BIKERS
 
161
  SURFER
162
  SURVEY
163
  TAILOR
164
+ WINNER
wrdler/words/wordlist.txt CHANGED
@@ -1,9 +1,5 @@
1
- # AI-generated word list
2
- # Topic: wordlisT
3
- # Last updated: 2025-11-28 12:18:24
4
- # Total words: 581
5
- # Format: one word per line, sorted by length then alphabetically
6
- #
7
  ABLE
8
  ACID
9
  AGED
@@ -137,7 +133,6 @@ FISH
137
  FIVE
138
  FLAT
139
  FLOW
140
- FLTE
141
  FOAM
142
  FOOD
143
  FOOT
@@ -290,7 +285,6 @@ NICK
290
  NINE
291
  NOSE
292
  NOTE
293
- NUNC
294
  OBEY
295
  ODDS
296
  OILY
@@ -358,7 +352,6 @@ ROSE
358
  RULE
359
  RUSH
360
  SAFE
361
- SAID
362
  SAKE
363
  SALE
364
  SALT
@@ -374,8 +367,6 @@ SEEN
374
  SELF
375
  SELL
376
  SEND
377
- SENT
378
- SERV
379
  SETT
380
  SEXY
381
  SHED
@@ -438,7 +429,6 @@ THIN
438
  THIS
439
  TIME
440
  TINY
441
- TOLD
442
  TOLL
443
  TONE
444
  TOOL
@@ -453,7 +443,6 @@ TWIN
453
  TYPE
454
  UNIT
455
  UPON
456
- USED
457
  USER
458
  VARY
459
  VAST
@@ -501,7 +490,6 @@ YELL
501
  YOGA
502
  ZERO
503
  ZONE
504
- ADJAR
505
  APPLE
506
  BLAST
507
  BOARD
 
1
+ # Optional: place a large A–Z word list here (one word per line).
2
+ # The app falls back to built-in pools if fewer than 500 words per length are found.
 
 
 
 
3
  ABLE
4
  ACID
5
  AGED
 
133
  FIVE
134
  FLAT
135
  FLOW
 
136
  FOAM
137
  FOOD
138
  FOOT
 
285
  NINE
286
  NOSE
287
  NOTE
 
288
  OBEY
289
  ODDS
290
  OILY
 
352
  RULE
353
  RUSH
354
  SAFE
 
355
  SAKE
356
  SALE
357
  SALT
 
367
  SELF
368
  SELL
369
  SEND
 
 
370
  SETT
371
  SEXY
372
  SHED
 
429
  THIS
430
  TIME
431
  TINY
 
432
  TOLL
433
  TONE
434
  TOOL
 
443
  TYPE
444
  UNIT
445
  UPON
 
446
  USER
447
  VARY
448
  VAST
 
490
  YOGA
491
  ZERO
492
  ZONE
 
493
  APPLE
494
  BLAST
495
  BOARD