Surn commited on
Commit
581c2fc
·
1 Parent(s): b66ffa9

debug reveal

Browse files
.gitignore CHANGED
@@ -342,6 +342,9 @@ paket-files/
342
  # Python Tools for Visual Studio (PTVS)
343
  **/__pycache__/
344
  *.pyc
 
 
 
345
 
346
  # Cake - Uncomment if you are using it
347
  #tools/**
 
342
  # Python Tools for Visual Studio (PTVS)
343
  **/__pycache__/
344
  *.pyc
345
+ **/**/__pycache__/
346
+ **/*.pyc
347
+
348
 
349
  # Cake - Uncomment if you are using it
350
  #tools/**
app.py CHANGED
@@ -1,6 +1,14 @@
1
  import streamlit as st
2
 
3
  from battlewords.ui import run_app
 
 
 
 
 
 
 
 
4
  def main():
5
  st.set_page_config(page_title="Battlewords (POC)", layout="wide")
6
  run_app()
 
1
  import streamlit as st
2
 
3
  from battlewords.ui import run_app
4
+
5
+
6
+ def _new_game() -> None:
7
+ st.session_state.clear()
8
+ _init_session()
9
+ st.rerun()
10
+
11
+
12
  def main():
13
  st.set_page_config(page_title="Battlewords (POC)", layout="wide")
14
  run_app()
battlewords/__init__.py CHANGED
@@ -1 +1,2 @@
 
1
  __all__ = ["models", "generator", "logic", "ui"]
 
1
+ __version__ = "0.1.0"
2
  __all__ = ["models", "generator", "logic", "ui"]
battlewords/logic.py CHANGED
@@ -19,8 +19,8 @@ def reveal_cell(state: GameState, letter_map: Dict[Coord, str], coord: Coord) ->
19
  return
20
  state.revealed.add(coord)
21
  state.can_guess = True
22
- ch = letter_map.get(coord, "")
23
- if ch == "":
24
  state.last_action = f"Revealed empty at ({coord.x+1},{coord.y+1})."
25
  else:
26
  state.last_action = f"Revealed '{ch}' at ({coord.x+1},{coord.y+1})."
@@ -32,7 +32,7 @@ def guess_word(state: GameState, guess_text: str) -> Tuple[bool, int]:
32
  return False, 0
33
  guess = (guess_text or "").strip().upper()
34
  if not (len(guess) in (4, 5, 6) and guess.isalpha()):
35
- state.last_action = "Guess must be AZ and length 4, 5, or 6."
36
  state.can_guess = False
37
  return False, 0
38
  if guess in state.guessed:
 
19
  return
20
  state.revealed.add(coord)
21
  state.can_guess = True
22
+ ch = letter_map.get(coord, "·")
23
+ if ch == "·":
24
  state.last_action = f"Revealed empty at ({coord.x+1},{coord.y+1})."
25
  else:
26
  state.last_action = f"Revealed '{ch}' at ({coord.x+1},{coord.y+1})."
 
32
  return False, 0
33
  guess = (guess_text or "").strip().upper()
34
  if not (len(guess) in (4, 5, 6) and guess.isalpha()):
35
+ state.last_action = "Guess must be AZ and length 4, 5, or 6."
36
  state.can_guess = False
37
  return False, 0
38
  if guess in state.guessed:
battlewords/models.py CHANGED
@@ -28,7 +28,7 @@ class Word:
28
  if self.direction not in ("H", "V"):
29
  raise ValueError("direction must be 'H' or 'V'")
30
  if not self.text.isalpha():
31
- raise ValueError("word must be alphabetic AZ only")
32
  # compute cells based on start and direction
33
  length = len(self.text)
34
  cells: List[Coord] = []
 
28
  if self.direction not in ("H", "V"):
29
  raise ValueError("direction must be 'H' or 'V'")
30
  if not self.text.isalpha():
31
+ raise ValueError("word must be alphabetic AZ only")
32
  # compute cells based on start and direction
33
  length = len(self.text)
34
  cells: List[Coord] = []
battlewords/ui.py CHANGED
@@ -32,7 +32,6 @@ def _init_session() -> None:
32
  def _new_game() -> None:
33
  st.session_state.clear()
34
  _init_session()
35
- st.rerun()
36
 
37
 
38
  def _to_state() -> GameState:
@@ -63,13 +62,13 @@ def _render_header():
63
  st.markdown(
64
  "- Grid is 12×12 with 6 words (two 4-letter, two 5-letter, two 6-letter).\n"
65
  "- After each reveal, you may submit one guess.\n"
66
- "- Scoring: length + unrevealed letters of that word at guess time."
67
- )
68
 
69
  def _render_sidebar():
70
  with st.sidebar:
71
  st.header("Controls")
72
- st.button("New Game", use_container_width=True, on_click=_new_game)
73
  st.markdown("Radar pulses show the last letter position of each hidden word.")
74
 
75
 
@@ -84,7 +83,7 @@ def _render_radar(puzzle: Puzzle, size: int):
84
  ax.set_yticks(range(1, size + 1))
85
  ax.grid(True, which="both", linestyle="--", alpha=0.3)
86
  ax.set_title("Radar")
87
- st.pyplot(fig, use_container_width=True)
88
  plt.close(fig)
89
 
90
 
@@ -92,6 +91,30 @@ def _render_grid(state: GameState, letter_map):
92
  size = state.grid_size
93
  clicked: Optional[Coord] = None
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  grid_container = st.container()
96
  with grid_container:
97
  for r in range(size):
@@ -101,20 +124,20 @@ def _render_grid(state: GameState, letter_map):
101
  revealed = coord in state.revealed
102
  label = letter_map.get(coord, " ") if revealed else " "
103
  key = f"cell_{r}_{c}"
104
- # Make revealed cells look disabled via help text; but still keep them clickable for UX feedback
105
  if cols[c].button(label, key=key, help=f"({r+1},{c+1})"):
106
- clicked = coord
 
107
 
108
  if clicked is not None:
109
  reveal_cell(state, letter_map, clicked)
 
110
  _sync_back(state)
111
- # No need to st.rerun(); Streamlit will rerun after button click
112
 
113
 
114
  def _render_guess_form(state: GameState):
115
  with st.form("guess_form"):
116
  guess_text = st.text_input("Your guess", value="", max_chars=12)
117
- submitted = st.form_submit_button("OK", disabled=not state.can_guess, use_container_width=True)
118
  if submitted:
119
  correct, _ = guess_word(state, guess_text)
120
  _sync_back(state)
 
32
  def _new_game() -> None:
33
  st.session_state.clear()
34
  _init_session()
 
35
 
36
 
37
  def _to_state() -> GameState:
 
62
  st.markdown(
63
  "- Grid is 12×12 with 6 words (two 4-letter, two 5-letter, two 6-letter).\n"
64
  "- After each reveal, you may submit one guess.\n"
65
+ "- Scoring: length + unrevealed letters of that word at guess time.")
66
+
67
 
68
  def _render_sidebar():
69
  with st.sidebar:
70
  st.header("Controls")
71
+ st.button("New Game", width="stretch", on_click=_new_game)
72
  st.markdown("Radar pulses show the last letter position of each hidden word.")
73
 
74
 
 
83
  ax.set_yticks(range(1, size + 1))
84
  ax.grid(True, which="both", linestyle="--", alpha=0.3)
85
  ax.set_title("Radar")
86
+ st.pyplot(fig, width="stretch")
87
  plt.close(fig)
88
 
89
 
 
91
  size = state.grid_size
92
  clicked: Optional[Coord] = None
93
 
94
+ # Inject CSS for grid lines and button styling
95
+ st.markdown(
96
+ """
97
+ <style>
98
+ div[data-testid="column"] {
99
+ padding: 0 !important;
100
+ }
101
+ button[data-testid="stButton"] {
102
+ width: 32px !important;
103
+ height: 32px !important;
104
+ min-width: 32px !important;
105
+ min-height: 32px !important;
106
+ padding: 0 !important;
107
+ margin: 0 !important;
108
+ border: 1px solid #888 !important;
109
+ background: #fff !important;
110
+ font-weight: bold;
111
+ font-size: 1rem;
112
+ }
113
+ </style>
114
+ """,
115
+ unsafe_allow_html=True,
116
+ )
117
+
118
  grid_container = st.container()
119
  with grid_container:
120
  for r in range(size):
 
124
  revealed = coord in state.revealed
125
  label = letter_map.get(coord, " ") if revealed else " "
126
  key = f"cell_{r}_{c}"
 
127
  if cols[c].button(label, key=key, help=f"({r+1},{c+1})"):
128
+ if not revealed:
129
+ clicked = coord
130
 
131
  if clicked is not None:
132
  reveal_cell(state, letter_map, clicked)
133
+ st.session_state.letter_map = build_letter_map(st.session_state.puzzle)
134
  _sync_back(state)
 
135
 
136
 
137
  def _render_guess_form(state: GameState):
138
  with st.form("guess_form"):
139
  guess_text = st.text_input("Your guess", value="", max_chars=12)
140
+ submitted = st.form_submit_button("OK", disabled=not state.can_guess, width="stretch")
141
  if submitted:
142
  correct, _ = guess_word(state, guess_text)
143
  _sync_back(state)