Surn commited on
Commit
032159d
·
1 Parent(s): 78346c3

Specification Update

Browse files
Files changed (3) hide show
  1. README.md +142 -1
  2. specs/requirements.md +50 -25
  3. specs/specs.md +36 -9
README.md CHANGED
@@ -1,2 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # BattleWords
2
- Old battleship style game to teach vocabulary
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: BattleWords
3
+ emoji: 🎲
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: streamlit
7
+ sdk_version: 1.25.0
8
+ python_version: 3.10
9
+ app_file: app.py
10
+ tags:
11
+ - game
12
+ - vocabulary
13
+ - streamlit
14
+ - education
15
+ ---
16
+
17
  # BattleWords
18
+
19
+ > **This project is used by [huggingface.co](https://huggingface.co/spaces/Surn/BattleWords) as a demonstration of interactive word games in Python.**
20
+
21
+ BattleWords is a vocabulary learning game inspired by classic Battleship mechanics. The objective is to discover hidden words on a grid, earning points for strategic guessing before all letters are revealed.
22
+
23
+ ## Features
24
+
25
+ - 12x12 grid with six hidden words (2x4-letter, 2x5-letter, 2x6-letter)
26
+ - Words placed horizontally or vertically
27
+ - Radar visualization to help locate word boundaries
28
+ - Reveal grid cells and guess words for points
29
+ - Scoring tiers: Good (34–37), Great (38–41), Fantastic (42+)
30
+ - Responsive UI built with Streamlit
31
+ - Deterministic seed support (Beta/Full)
32
+ - Keyboard navigation and guessing (Beta/Full)
33
+ - Overlapping words on shared letters (Beta)
34
+ - Daily and practice modes (Full)
35
+ - Leaderboards, persistence, and advanced features (Full)
36
+
37
+ ## Installation
38
+ 1. Clone the repository:
39
+ ```
40
+ git clone
41
+ cd battlewords
42
+ ```
43
+ 2. (Optional) Create and activate a virtual environment:
44
+ ```
45
+ python -m venv venv
46
+ source venv/bin/activate # On Windows use `venv\Scripts\activate`
47
+ ```
48
+ 3. Install dependencies:
49
+ ```
50
+ pip install -r specs/requirements.md
51
+ ```
52
+
53
+
54
+ ## Running BattleWords
55
+
56
+ You can run the app locally using either [uv](https://github.com/astral-sh/uv) or Streamlit directly:
57
+
58
+ ```
59
+ uv run streamlit run app.py
60
+ ```
61
+
62
+ or
63
+ ```
64
+ streamlit run app.py
65
+ ```
66
+
67
+ ## Folder Structure
68
+
69
+ - `app.py` – Streamlit entry point
70
+ - `battlewords/` – Python package
71
+ - `models.py` – data models and types
72
+ - `word_loader.py` – word list loading and validation
73
+ - `generator.py` – word placement logic
74
+ - `logic.py` – game mechanics (reveal, guess, scoring)
75
+ - `ui.py` – Streamlit UI composition
76
+ - `words/wordlist.txt` – candidate words
77
+ - `specs/` – documentation (`specs.md`, `requirements.md`)
78
+ - `tests/` – unit tests
79
+
80
+ ## How to Play
81
+
82
+ 1. Click grid squares to reveal letters or empty spaces.
83
+ 2. After revealing a letter, enter a guess for a word in the text box.
84
+ 3. Earn points for correct guesses and bonus points for unrevealed letters.
85
+ 4. The game ends when all six words are found. Your score tier is displayed.
86
+
87
+ ## Development Phases
88
+
89
+ - **Proof of Concept (0.1.0):** No overlaps, basic UI, single session.
90
+ - **Beta (0.5.0):** Overlaps allowed on shared letters, responsive layout, keyboard support, deterministic seed.
91
+ - **Full (1.0.0):** Enhanced UX, persistence, leaderboards, daily/practice modes, advanced features.
92
+
93
+ See `specs/requirements.md` and `specs/specs.md` for full details and roadmap.
94
+
95
+ ## License
96
+
97
+ BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.
98
+
99
+ ## Hugging Face Spaces Configuration
100
+
101
+ BattleWords is deployable as a Hugging Face Space. To configure your Space, add a YAML block at the top of your `README.md`:
102
+
103
+ ```yaml
104
+ ---
105
+ title: BattleWords
106
+ emoji: 🎲
107
+ colorFrom: blue
108
+ colorTo: indigo
109
+ sdk: streamlit
110
+ sdk_version: 1.25.0
111
+ python_version: 3.10
112
+ app_file: app.py
113
+ tags:
114
+ - game
115
+ - vocabulary
116
+ - streamlit
117
+ - education
118
+ ---
119
+ ```
120
+
121
+ **Key parameters:**
122
+ - `title`, `emoji`, `colorFrom`, `colorTo`: Visuals for your Space.
123
+ - `sdk`: Use `streamlit` for Streamlit apps.
124
+ - `sdk_version`: Latest supported Streamlit version.
125
+ - `python_version`: Python version (default is 3.10).
126
+ - `app_file`: Entry point for your app.
127
+ - `tags`: List of descriptive tags.
128
+
129
+ **Dependencies:**
130
+ Add a `requirements.txt` with your Python dependencies (e.g., `streamlit`, etc.).
131
+
132
+ **Port:**
133
+ Streamlit Spaces use port `8501` by default.
134
+
135
+ **Embedding:**
136
+ Spaces can be embedded in other sites using an `<iframe>`:
137
+
138
+ ```html
139
+ <iframe src="https://Surn-BattleWords.hf.space?embed=true" title="BattleWords"></iframe>
140
+ ```
141
+
142
+ For full configuration options, see [Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference) and [Streamlit SDK Guide](https://huggingface.co/docs/hub/spaces-sdks-streamlit).
143
+
specs/requirements.md CHANGED
@@ -1,11 +1,12 @@
1
  # Battlewords: Implementation Requirements
2
 
3
- This document breaks down the tasks to build Battlewords using the game rules described in `specs.md`. It is organized in phases: a minimal Proof of Concept (POC) and a Full Version with all features and polish.
4
 
5
  Assumptions
6
- - Tech stack: Python 3.10+, Streamlit for UI, standard library only for POC.
7
  - Single-player, local state stored in Streamlit session state for POC.
8
- - Grid is always 12x12 with exactly six words: two 4-letter, two 5-letter, two 6-letter words; horizontal/vertical only; no shared letters or overlaps.
 
9
 
10
  Streamlit key components (API usage plan)
11
  - State & caching
@@ -22,22 +23,24 @@ Streamlit key components (API usage plan)
22
  - `st.metric` to show score; `st.checkbox`/`st.toggle` for optional settings (e.g., show radar).
23
  - Visualization
24
  - `st.pyplot` for the radar mini-grid (scatter on a 12×12 axes) or `st.plotly_chart` if interactive.
 
25
  - Control flow
26
- - App reruns on interaction; optionally use `st.rerun()` after state resets; `st.stop()` after game over summary to freeze UI.
27
 
28
  Folder Structure
29
  - `app.py` – Streamlit entry point
30
  - `battlewords/` – Python package
31
  - `__init__.py`
32
  - `models.py` – data models and types
33
- - `generator.py` – word placement and puzzle generation
34
- - `logic.py` – game mechanics (reveal, guess, scoring)
35
- - `ui.py` – Streamlit UI composition
 
36
  - `words/wordlist.txt` – candidate words
37
- - `specs/` – documentation (existing)
38
- - `tests/` – unit tests
39
 
40
- Phase 1: Proof of Concept Version
41
  Goal: A playable, single-session game demonstrating core rules, scoring, and radar without persistence or advanced UX.
42
 
43
  1) Data Models
@@ -52,32 +55,32 @@ Acceptance: Types exist and are consumed by generator/logic; simple constructors
52
  - Add an English word list filtered to alphabetic uppercase, lengths in {4,5,6}.
53
  - Ensure words contain no special characters; maintain reasonable difficulty.
54
  - Streamlit: `st.cache_data` to memoize loading/filtering.
 
55
 
56
  Acceptance: Loading function returns lists by length with >= 500 words per length or fallback minimal lists.
57
 
58
  3) Puzzle Generation (Placement)
59
  - Randomly place 2×4, 2×5, 2×6 letter words on a 12×12 grid.
60
- - Constraints:
61
  - Horizontal (left→right) or Vertical (top→down) only.
62
- - No overlapping letters.
63
- - No shared letters between different words (cells must be unique; letters adjacent orthogonally are allowed).
64
  - Compute radar pulses as the last cell of each word.
65
  - Retry strategy with max attempts; raise a controlled error if generation fails.
66
 
67
- Acceptance: Generator returns a valid `Puzzle` passing validation checks (no collisions, in-bounds, correct counts).
68
 
69
  4) Game Mechanics
70
  - Reveal:
71
- - Click a covered cell to reveal; if the cell is part of a word, show the letter; else mark empty.
72
  - After a reveal action, set `can_guess=True`.
73
- - Streamlit: 12×12 `st.columns` + `st.button(label, key=f"cell_{r}_{c}")` per cell; on click, update `st.session_state` and optionally `st.rerun()`.
74
  - Guess:
75
  - Accept a guess only if `can_guess` is True and input length ∈ {4,5,6}.
76
  - Match guess case-insensitively against unguessed words in puzzle.
77
  - If correct: add base points = word length; bonus points = count of unrevealed cells in that word at guess time; mark all cells of the word as revealed; add to `guessed`.
78
  - If incorrect: no points awarded.
79
  - After any guess, set `can_guess=False` and require another reveal before next guess.
80
- - Streamlit: `with st.form("guess"):` + `st.text_input("Your guess", key="guess_text")` + `st.form_submit_button("OK", disabled=not st.session_state.can_guess)`.
81
  - End of game when all 6 words are guessed; display summary and tier, then `st.stop()`.
82
 
83
  Acceptance: Unit tests cover scoring, guess gating, and reveal behavior.
@@ -89,11 +92,11 @@ Acceptance: Unit tests cover scoring, guess gating, and reveal behavior.
89
  - Right: Radar mini-grid via `st.pyplot` (matplotlib scatter) or `st.plotly_chart`.
90
  - Bottom/right: Guess form using `st.form`, `st.text_input`, `st.form_submit_button`.
91
  - Score panel showing current score using `st.metric` and `st.markdown` for last action.
92
- - Optional `st.sidebar` to host reset/new game and settings.
93
  - Visuals:
94
- - Covered cell vs revealed styles: use button labels/emojis and background color hints; if needed, small custom `st.html`/CSS for color.
95
 
96
- Acceptance: Users can play end-to-end in one session; UI updates consistently; radar shows exactly 6 pulses.
97
 
98
  6) Scoring Tiers
99
  - After game ends, compute tier:
@@ -107,13 +110,37 @@ Acceptance: Tier text shown at game end; manual test with mocked states.
107
 
108
  7) Basic Tests
109
  - Unit tests for:
110
- - Placement validity (bounds, overlap, counts).
111
  - Scoring logic and bonus calculation.
112
  - Guess gating (must reveal before next guess).
113
 
114
  Acceptance: Tests run and pass locally.
115
 
116
- Phase 2: Full Version (All Features and Polish)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  Goal: Robust app with polish, persistence, test coverage, and optional advanced features.
118
 
119
  A) UX and Visual Polish
@@ -185,9 +212,7 @@ J) Deployment
185
 
186
  Milestones and Estimates (High-level)
187
  - Phase 1 (POC): 2–4 days
188
- - Models + generator + logic: 1–2 days
189
- - UI + scoring + radar: 1 day
190
- - Tests and polish: 0.5–1 day
191
  - Phase 2 (Full): 1–2 weeks depending on features selected
192
 
193
  Definitions of Done (per task)
 
1
  # Battlewords: Implementation Requirements
2
 
3
+ This document breaks down the tasks to build Battlewords using the game rules described in `specs.md`. It is organized in phases: a minimal Proof of Concept (POC), a Beta Version (0.5.0), and a Full Version (1.0.0).
4
 
5
  Assumptions
6
+ - Tech stack: Python 3.10+, Streamlit for UI, matplotlib for radar, numpy for tick helpers.
7
  - Single-player, local state stored in Streamlit session state for POC.
8
+ - Grid is always 12x12 with exactly six words: two 4-letter, two 5-letter, two 6-letter words; horizontal/vertical only; no shared letters or overlaps in POC; shared-letter overlaps allowed in Beta; no overlaps in Full.
9
+ - Entry point is `app.py`.
10
 
11
  Streamlit key components (API usage plan)
12
  - State & caching
 
23
  - `st.metric` to show score; `st.checkbox`/`st.toggle` for optional settings (e.g., show radar).
24
  - Visualization
25
  - `st.pyplot` for the radar mini-grid (scatter on a 12×12 axes) or `st.plotly_chart` if interactive.
26
+ - Radar plot uses `ax.set_ylim(size, 0)` to invert Y so (0,0) is top-left.
27
  - Control flow
28
+ - App reruns on interaction; uses `st.rerun()` after state changes (reveal, guess); `st.stop()` after game over summary to freeze UI.
29
 
30
  Folder Structure
31
  - `app.py` – Streamlit entry point
32
  - `battlewords/` – Python package
33
  - `__init__.py`
34
  - `models.py` – data models and types
35
+ - `word_loader.py` – load/validate/cached word lists (uses `battlewords/words/wordlist.txt` with fallback)
36
+ - `generator.py` – word placement; imports from `word_loader`; avoids duplicate words
37
+ - `logic.py` – game mechanics (reveal, guess, scoring, tiers)
38
+ - `ui.py` – Streamlit UI composition; immediate rerender on reveal/guess via `st.rerun()`; inverted radar Y
39
  - `words/wordlist.txt` – candidate words
40
+ - `specs/` – documentation (this file and `specs.md`)
41
+ - `tests/` – unit tests (optional for now)
42
 
43
+ Phase 1: Proof of Concept (0.1.0)
44
  Goal: A playable, single-session game demonstrating core rules, scoring, and radar without persistence or advanced UX.
45
 
46
  1) Data Models
 
55
  - Add an English word list filtered to alphabetic uppercase, lengths in {4,5,6}.
56
  - Ensure words contain no special characters; maintain reasonable difficulty.
57
  - Streamlit: `st.cache_data` to memoize loading/filtering.
58
+ - Loader is centralized in `word_loader.py` and used by generator and UI.
59
 
60
  Acceptance: Loading function returns lists by length with >= 500 words per length or fallback minimal lists.
61
 
62
  3) Puzzle Generation (Placement)
63
  - Randomly place 2×4, 2×5, 2×6 letter words on a 12×12 grid.
64
+ - Constraints (POC):
65
  - Horizontal (left→right) or Vertical (top→down) only.
66
+ - No overlapping letters between different words (cells must be unique).
 
67
  - Compute radar pulses as the last cell of each word.
68
  - Retry strategy with max attempts; raise a controlled error if generation fails.
69
 
70
+ Acceptance: Generator returns a valid `Puzzle` passing validation checks (no collisions, in-bounds, correct counts, no duplicates).
71
 
72
  4) Game Mechanics
73
  - Reveal:
74
+ - Click a covered cell to reveal; if the cell is part of a word, show the letter; else mark empty (CSS class `empty`).
75
  - After a reveal action, set `can_guess=True`.
76
+ - Streamlit: 12×12 `st.columns` + `st.button(label, key=f"cell_{r}_{c}")` per cell; on click, update `st.session_state` and call `st.rerun()`.
77
  - Guess:
78
  - Accept a guess only if `can_guess` is True and input length ∈ {4,5,6}.
79
  - Match guess case-insensitively against unguessed words in puzzle.
80
  - If correct: add base points = word length; bonus points = count of unrevealed cells in that word at guess time; mark all cells of the word as revealed; add to `guessed`.
81
  - If incorrect: no points awarded.
82
  - After any guess, set `can_guess=False` and require another reveal before next guess.
83
+ - Streamlit: `with st.form("guess"):` + `st.text_input("Your guess", key="guess_text")` + `st.form_submit_button("OK", disabled=not st.session_state.can_guess)`; after guess, call `st.rerun()`.
84
  - End of game when all 6 words are guessed; display summary and tier, then `st.stop()`.
85
 
86
  Acceptance: Unit tests cover scoring, guess gating, and reveal behavior.
 
92
  - Right: Radar mini-grid via `st.pyplot` (matplotlib scatter) or `st.plotly_chart`.
93
  - Bottom/right: Guess form using `st.form`, `st.text_input`, `st.form_submit_button`.
94
  - Score panel showing current score using `st.metric` and `st.markdown` for last action.
95
+ - Optional `st.sidebar` to host reset/new game and settings; shows word list source/counts.
96
  - Visuals:
97
+ - Covered cell vs revealed styles: use button labels/emojis and background color hints; revealed empty cells use CSS class `empty` for background.
98
 
99
+ Acceptance: Users can play end-to-end in one session; UI updates consistently; radar shows exactly 6 pulses; single-click reveal and guess update via rerun.
100
 
101
  6) Scoring Tiers
102
  - After game ends, compute tier:
 
110
 
111
  7) Basic Tests
112
  - Unit tests for:
113
+ - Placement validity (bounds, overlap, counts, no duplicate words).
114
  - Scoring logic and bonus calculation.
115
  - Guess gating (must reveal before next guess).
116
 
117
  Acceptance: Tests run and pass locally.
118
 
119
+ Beta Version (0.5.0)
120
+ Goal: Introduce overlapping words on shared letters, improve UX responsiveness and input options, and add deterministic seeding.
121
+
122
+ A) Generator and Validation
123
+ - Allow shared-letter overlaps: words may cross on the same letter; still disallow conflicting letters on the same cell.
124
+ - Optional validation pass to detect and avoid unintended adjacent partial words (content curation rule).
125
+ - Deterministic seed support to reproduce puzzles (e.g., daily seed derived from date).
126
+ Acceptance:
127
+ - Placement permits shared-letter crossings only when letters match.
128
+ - With a fixed seed/date, the same puzzle is produced.
129
+
130
+ B) UI and Interaction
131
+ - Cell rendering with consistent sizing and responsive layout (desktop/mobile).
132
+ - Keyboard support for grid navigation and guessing (custom JS via `st.html` or component).
133
+ - Maintain radar behavior and scoring rules.
134
+ Acceptance:
135
+ - Grid scales cleanly across typical desktop and mobile widths.
136
+ - Users can enter guesses and move focus via keyboard.
137
+
138
+ C) Tests
139
+ - Property checks for overlap validity (only same letters may share a cell).
140
+ - Seed reproducibility tests (same seed → identical placements).
141
+ - Optional validation tests for adjacency curation (when enabled).
142
+
143
+ Phase 2: Full Version (1.0.0)
144
  Goal: Robust app with polish, persistence, test coverage, and optional advanced features.
145
 
146
  A) UX and Visual Polish
 
212
 
213
  Milestones and Estimates (High-level)
214
  - Phase 1 (POC): 2–4 days
215
+ - Beta (0.5.0): 3–5 days (overlaps, responsive UI, keyboard, deterministic seed)
 
 
216
  - Phase 2 (Full): 1–2 weeks depending on features selected
217
 
218
  Definitions of Done (per task)
specs/specs.md CHANGED
@@ -10,14 +10,15 @@ Battlewords is inspired by the classic Battleship game, but uses words instead o
10
  - Two five-letter words
11
  - Two six-letter words
12
  - Words are placed horizontally (left-right) or vertically (top-down), not diagonally.
13
- - Words do not overlap or share letters.
14
- - Radar screen indicates the location of the last letter of each word.
15
 
16
- ## Gameplay
17
  - Players click grid squares to reveal letters or empty spaces.
18
- - Blue squares turn black if empty; otherwise, a letter is revealed.
 
19
  - Use radar pulses to locate word boundaries (first and last letters).
20
  - After revealing a letter, players may guess a word by entering it in a text box.
 
21
  - Only one guess per letter reveal; must uncover another letter before guessing again.
22
 
23
  ## Scoring
@@ -29,16 +30,42 @@ Battlewords is inspired by the classic Battleship game, but uses words instead o
29
  - Great: 38-41
30
  - Fantastic: 42+
31
 
32
- ## Strategy
33
- - Focus on finding word boundaries using radar.
34
- - Guess words with hidden letters for higher scores.
35
- - The game rewards strategy over speed.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  ## UI Elements
38
  - 12x12 grid
39
- - Radar screen (shows last letter locations)
40
  - Text box for word guesses
41
  - Score display (shows word, base points, bonus points, total score)
42
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  ## Copyright
44
  BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.
 
10
  - Two five-letter words
11
  - Two six-letter words
12
  - Words are placed horizontally (left-right) or vertically (top-down), not diagonally.
13
+ - Entry point is `app.py`.
 
14
 
15
+ ## Gameplay (Common)
16
  - Players click grid squares to reveal letters or empty spaces.
17
+ - Empty revealed squares are styled with CSS class `empty`.
18
+ - After any reveal, the app immediately reruns (`st.rerun`) to show the change.
19
  - Use radar pulses to locate word boundaries (first and last letters).
20
  - After revealing a letter, players may guess a word by entering it in a text box.
21
+ - Guess submission triggers an immediate rerun to reflect results.
22
  - Only one guess per letter reveal; must uncover another letter before guessing again.
23
 
24
  ## Scoring
 
30
  - Great: 38-41
31
  - Fantastic: 42+
32
 
33
+ ## POC (0.1.0) Rules
34
+ - No overlaps: words do not overlap or share letters.
35
+ - UI: basic grid, radar, and guess form.
36
+ - No keyboard interaction requirement.
37
+ - Seed is optional and not standardized.
38
+
39
+ ## Beta (0.5.0) Additions
40
+ - Overlaps allowed on shared letters: words may cross only where letters match; still forbid conflicting letters in the same cell.
41
+ - Optional validation pass to avoid unintended adjacent partial words (content curation rule).
42
+ - Cell rendering with consistent sizing and responsive layout (desktop/mobile).
43
+ - Keyboard support for navigation and guessing (custom JS via `st.html` or a component).
44
+ - Deterministic seed support to reproduce puzzles (e.g., daily seed derived from date).
45
+
46
+ ## Full (1.0.0) Rules
47
+ - No overlaps: words do not overlap or share letters.
48
+ - Enhanced UX polish (animations, accessibility, themes).
49
+ - Persistence, leaderboards, and additional modes as specified in requirements.
50
+ - Deterministic daily mode and practice mode supported.
51
 
52
  ## UI Elements
53
  - 12x12 grid
54
+ - Radar screen (shows last letter locations); y-axis inverted so (0,0) is top-left
55
  - Text box for word guesses
56
  - Score display (shows word, base points, bonus points, total score)
57
 
58
+ ## Word List
59
+ - External list at `battlewords/words/wordlist.txt`.
60
+ - Loaded by `battlewords.word_loader.load_word_list()` with caching.
61
+ - Filtered to uppercase A�Z, lengths in {4,5,6}; falls back if < 500 per length.
62
+
63
+ ## Generator
64
+ - Centralized word loader.
65
+ - No duplicate word texts are selected.
66
+
67
+ ## Entry Point
68
+ - The Streamlit entry point is `app.py`.
69
+
70
  ## Copyright
71
  BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.