Surn commited on
Commit
85779ec
1 Parent(s): 0c74398

add background
naming update
version info in settings

app.py CHANGED
@@ -11,7 +11,7 @@ def _new_game() -> None:
11
 
12
  def main(opened=False):
13
  st.set_page_config(
14
- page_title="Battlewords (Proof Of Concept)",
15
  layout="wide",
16
  initial_sidebar_state="expanded" if opened else "collapsed"
17
  )
 
11
 
12
  def main(opened=False):
13
  st.set_page_config(
14
+ page_title="Battlewords",
15
  layout="wide",
16
  initial_sidebar_state="expanded" if opened else "collapsed"
17
  )
battlewords/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.1.8"
2
  __all__ = ["models", "generator", "logic", "ui"]
 
1
+ __version__ = "0.1.9"
2
  __all__ = ["models", "generator", "logic", "ui"]
battlewords/logic.py CHANGED
@@ -18,8 +18,10 @@ def reveal_cell(state: GameState, letter_map: Dict[Coord, str], coord: Coord) ->
18
  state.last_action = "Already revealed."
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:
 
18
  state.last_action = "Already revealed."
19
  return
20
  state.revealed.add(coord)
21
+ # Determine if this reveal uncovered a letter or an empty cell
22
  ch = letter_map.get(coord, "路")
23
+ # Only allow guessing if a letter was revealed; preserve existing True (e.g., after a correct guess)
24
+ state.can_guess = state.can_guess or (ch != "路")
25
  if ch == "路":
26
  state.last_action = f"Revealed empty at ({coord.x+1},{coord.y+1})."
27
  else:
battlewords/ui.py CHANGED
@@ -15,6 +15,7 @@ from .generator import generate_puzzle, sort_word_file
15
  from .logic import build_letter_map, reveal_cell, guess_word, is_game_over, compute_tier
16
  from .models import Coord, GameState, Puzzle
17
  from .word_loader import get_wordlist_files, load_word_list # use loader directly
 
18
 
19
 
20
  CoordLike = Tuple[int, int]
@@ -50,11 +51,53 @@ def _build_letter_map(puzzle) -> dict[CoordLike, str]:
50
  letters[xy] = text[i]
51
  return letters
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  def inject_styles() -> None:
55
  st.markdown(
56
  """
57
  <style>
 
 
 
 
58
  .stMainBlockContainer {
59
  max-width: 1100px;
60
  }
@@ -297,7 +340,7 @@ def _sync_back(state: GameState) -> None:
297
 
298
 
299
  def _render_header():
300
- st.title(f"Battlewords (Proof Of Concept) v {version}")
301
  st.subheader("Reveal cells, then guess the hidden words.")
302
  st.markdown(
303
  "- Grid is 12脳12 with 6 words (two 4-letter, two 5-letter, two 6-letter).\n"
@@ -349,6 +392,7 @@ def _render_sidebar():
349
  _sort_wordlist(st.session_state.selected_wordlist)
350
  else:
351
  st.info("No word lists found in words/ directory. Using built-in fallback.")
 
352
 
353
  def get_scope_image(size=4, bgcolor="none", scope_color="green", img_name="scope.gif"):
354
  scope_path = os.path.join(os.path.dirname(__file__), img_name)
@@ -750,6 +794,9 @@ def _render_game_over(state: GameState):
750
  row_cols[2].markdown(f"{extra_display}")
751
  st.markdown(f"**Total**: {state.score}")
752
 
 
 
 
753
  st.stop()
754
 
755
 
@@ -775,6 +822,7 @@ def _sort_wordlist(filename):
775
 
776
  def run_app():
777
  _init_session()
 
778
  _render_header()
779
  _render_sidebar()
780
 
@@ -802,4 +850,5 @@ def run_app():
802
  # End condition
803
  state = _to_state()
804
  if is_game_over(state):
805
- _render_game_over(state)
 
 
15
  from .logic import build_letter_map, reveal_cell, guess_word, is_game_over, compute_tier
16
  from .models import Coord, GameState, Puzzle
17
  from .word_loader import get_wordlist_files, load_word_list # use loader directly
18
+ from .version_info import versions_html # version info footer
19
 
20
 
21
  CoordLike = Tuple[int, int]
 
51
  letters[xy] = text[i]
52
  return letters
53
 
54
+ ocean_background_css = """
55
+ <style>
56
+ .stApp {
57
+ margin: 0;
58
+ height: 100vh;
59
+ background: linear-gradient(
60
+ 45deg,
61
+ rgba(29, 100, 200, 0.6) 0%,
62
+ rgba(50, 120, 220, 0.8) 25%,
63
+ rgba(20, 80, 180, 0.95) 50%,
64
+ rgba(50, 120, 220, 0.8) 75%,
65
+ rgba(29, 100, 200, 0.6) 100%
66
+ );
67
+ background-size: 200% 200%;
68
+ animation: oceanFlow 12s ease-in-out infinite;
69
+ overflow: hidden;
70
+ }
71
+
72
+ /* Animation for rolling water effect */
73
+ @keyframes oceanFlow {
74
+ 0% {
75
+ background-position: 0% 50%;
76
+ }
77
+ 50% {
78
+ background-position: 100% 50%;
79
+ }
80
+ 100% {
81
+ background-position: 0% 50%;
82
+ }
83
+ }
84
+
85
+ /* Ensure Streamlit content is visible above the background */
86
+ .stApp > div {
87
+ position: relative;
88
+ z-index: 1;
89
+ }
90
+ </style>
91
+ """
92
 
93
  def inject_styles() -> None:
94
  st.markdown(
95
  """
96
  <style>
97
+ /* Center main content and limit width */
98
+ # .stApp, body {
99
+ # background: rgba(29, 100, 200, 0.5);
100
+ # }
101
  .stMainBlockContainer {
102
  max-width: 1100px;
103
  }
 
340
 
341
 
342
  def _render_header():
343
+ st.title(f"Battlewords v{version}")
344
  st.subheader("Reveal cells, then guess the hidden words.")
345
  st.markdown(
346
  "- Grid is 12脳12 with 6 words (two 4-letter, two 5-letter, two 6-letter).\n"
 
392
  _sort_wordlist(st.session_state.selected_wordlist)
393
  else:
394
  st.info("No word lists found in words/ directory. Using built-in fallback.")
395
+ st.markdown(versions_html(), unsafe_allow_html=True)
396
 
397
  def get_scope_image(size=4, bgcolor="none", scope_color="green", img_name="scope.gif"):
398
  scope_path = os.path.join(os.path.dirname(__file__), img_name)
 
794
  row_cols[2].markdown(f"{extra_display}")
795
  st.markdown(f"**Total**: {state.score}")
796
 
797
+ # footer version info on game over as well
798
+ st.markdown(versions_html(), unsafe_allow_html=True)
799
+
800
  st.stop()
801
 
802
 
 
822
 
823
  def run_app():
824
  _init_session()
825
+ st.markdown(ocean_background_css, unsafe_allow_html=True)
826
  _render_header()
827
  _render_sidebar()
828
 
 
850
  # End condition
851
  state = _to_state()
852
  if is_game_over(state):
853
+ _render_game_over(state)
854
+
battlewords/version_info.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import subprocess
3
+
4
+ try:
5
+ import streamlit as st
6
+ except Exception: # pragma: no cover
7
+ st = None
8
+
9
+
10
+ def commit_hash() -> str:
11
+ """Return current git commit hash or '<none>' if unavailable."""
12
+ try:
13
+ return subprocess.check_output(["git", "rev-parse", "HEAD"], shell=False, encoding="utf-8").strip()
14
+ except Exception:
15
+ return "<none>"
16
+
17
+
18
+ def versions_html() -> str:
19
+ """Return a small HTML snippet with runtime and app environment info.
20
+
21
+ Includes: git commit, Python version, and Streamlit version.
22
+ """
23
+ python_version = ".".join(str(x) for x in sys.version_info[:3])
24
+ full_python = sys.version.replace("\n", " ")
25
+ commit = commit_hash()
26
+ streamlit_version = getattr(st, "__version__", "not installed")
27
+
28
+ html = f"""
29
+ <div style="font-size: 0.85rem; color: #b7c3d0; margin-top: 1.5rem; padding-top: 0.5rem; border-top: 1px solid rgba(255,255,255,0.15);">
30
+ <span>commit: <code>{commit}</code></span>
31
+ &nbsp;|&nbsp;
32
+ <span>python: <span title="{full_python}">{python_version}</span></span>
33
+ &nbsp;|&nbsp;
34
+ <span>streamlit: {streamlit_version}</span>
35
+ </div>
36
+ """
37
+ return html