DarshanScripts commited on
Commit
bfb0d96
ยท
verified ยท
1 Parent(s): b236051

Upload stratego\web\app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. stratego//web//app.py +341 -0
stratego//web//app.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Main Streamlit application for Stratego Human vs AI"""
2
+
3
+ import streamlit as st
4
+ from stratego.web.config import session_manager, agent_builder, game_config
5
+ from stratego.web.game_controller import GameController
6
+ from stratego.web.components import game_history, status_panel
7
+ from stratego.web.components.interactive_board import render_interactive_board
8
+ from stratego.web.utils.validators import normalize_move
9
+
10
+
11
+ def screen_welcome():
12
+ """Screen 0: Welcome and game mode selection"""
13
+ st.title("โš”๏ธ STRATEGO - Human vs AI")
14
+ st.markdown("*Challenge an intelligent AI opponent in the classic strategy game!*")
15
+
16
+ st.divider()
17
+
18
+ col1, col2 = st.columns([2, 1])
19
+
20
+ with col1:
21
+ st.subheader("๐ŸŽฎ How to Play")
22
+ st.write("""
23
+ **Objective:** Capture the enemy flag or eliminate all movable pieces
24
+
25
+ **Your Setup:**
26
+ - ๐Ÿ”ต Your army positioned at the **BOTTOM** of the board
27
+ - Arrange your pieces strategically before the game starts
28
+ - Each piece has a rank that determines its strength
29
+
30
+ **Your Turn:**
31
+ 1. **Click on one of your pieces** (blue area at bottom)
32
+ 2. **Available destination squares will be highlighted** in green with a dot (โ—)
33
+ 3. **Click the destination** to move your piece there
34
+ 4. **Battles resolve automatically** when pieces meet
35
+
36
+ **AI Opponent:**
37
+ - ๐Ÿ”ด Enemy forces at the **TOP** of the board
38
+ - Uses Mistral 7B LLM to make strategic decisions
39
+ - Plays immediately after your move
40
+ """)
41
+
42
+ st.markdown("---")
43
+ st.markdown("### โš™๏ธ Setup Requirements")
44
+ with st.expander("๐Ÿ“ฆ Ollama Installation", expanded=False):
45
+ st.code(
46
+ """# Make sure you have Ollama running locally:
47
+ ollama serve
48
+
49
+ # In a new terminal, pull Mistral:
50
+ ollama pull mistral:7b
51
+
52
+ # Verify it's installed:
53
+ ollama list""",
54
+ language="bash"
55
+ )
56
+ st.caption(
57
+ "๐Ÿ’ก Ollama provides local LLM inference. "
58
+ "Download: https://ollama.ai"
59
+ )
60
+
61
+ with col2:
62
+ st.subheader("๐Ÿ“Š Game Info")
63
+ selected_config = game_config.get_game_config(
64
+ "Standard (10x10)"
65
+ )
66
+ st.metric("Board Size", "10 ร— 10")
67
+ st.metric("Players", "2 (You vs AI)")
68
+ st.metric("AI Model", "Mistral 7B")
69
+ st.metric("Time/Move", "~2-5 sec")
70
+
71
+ st.divider()
72
+
73
+ st.subheader("๐ŸŽฏ Piece Legend")
74
+ legend_data = {
75
+ "๐Ÿšฉ": "Flag (0โ˜…) - Must protect!",
76
+ "๐Ÿ’ฃ": "Bomb (0โ˜…) - Immovable",
77
+ "๐Ÿ‘‘": "Marshal (10โ˜…) - Strongest",
78
+ "โญ": "General (9โ˜…) - Second strongest",
79
+ "๐Ÿƒ": "Scout (2โ˜…) - Can move multi-square",
80
+ "๐Ÿ•ต๏ธ": "Spy (1โ˜…) - Defeats Marshal",
81
+ "๐Ÿช–": "Sergeant (3โ˜…)",
82
+ "๐Ÿ“": "Lieutenant (4โ˜…)",
83
+ "๐ŸŽ–๏ธ": "Captain (6โ˜…)",
84
+ }
85
+ for emoji, desc in legend_data.items():
86
+ st.caption(f"{emoji} {desc}")
87
+
88
+ st.divider()
89
+
90
+ # Game mode selection
91
+ st.markdown("### ๐Ÿ•น๏ธ Start Your Battle")
92
+
93
+ col1, col2 = st.columns([3, 1])
94
+
95
+ with col1:
96
+ st.markdown(
97
+ "**Standard 10ร—10 with lakes**\n"
98
+ "Classic Stratego rules. Your pieces at bottom, AI at top."
99
+ )
100
+
101
+ with col2:
102
+ if st.button("Start Game โ†’", type="primary", use_container_width=True, key="start_game_btn"):
103
+ session_manager.SessionManager.set_game_mode("Standard (10x10)")
104
+ session_manager.SessionManager.set_screen(1)
105
+ st.rerun()
106
+
107
+
108
+ def screen_ai_config():
109
+ """Screen 1: AI agent configuration - Real Ollama setup"""
110
+ st.title("โš™๏ธ Configure AI Opponent")
111
+
112
+ col1, col2 = st.columns(2)
113
+
114
+ with col1:
115
+ st.subheader("๐Ÿš€ Ollama AI Model")
116
+
117
+ # Ollama configuration
118
+ backend = "ollama"
119
+ st.success("โœ… Using Ollama Backend")
120
+
121
+ available_models = game_config.get_available_models(backend)
122
+ model = st.selectbox(
123
+ "Select Model:",
124
+ available_models,
125
+ index=0,
126
+ help="Choose from available Ollama models (make sure it's pulled: ollama pull mistral:7b)"
127
+ )
128
+
129
+ ollama_url = st.text_input(
130
+ "๐Ÿ”— Ollama Server URL:",
131
+ value="http://localhost:11434",
132
+ help="Local: http://localhost:11434 | Remote: your_server_ip:11434"
133
+ )
134
+
135
+ # Test connection button
136
+ if st.button("๐Ÿงช Test Connection", help="Check if Ollama is running"):
137
+ try:
138
+ import requests
139
+ response = requests.get(f"{ollama_url}/api/tags", timeout=3)
140
+ if response.status_code == 200:
141
+ st.success("โœ… Connected to Ollama!")
142
+ st.caption(f"(Available models: {len(response.json().get('models', []))})")
143
+ else:
144
+ st.error(f"โŒ Ollama responded with status {response.status_code}")
145
+ except Exception as e:
146
+ st.error(f"โŒ Cannot connect to Ollama: {str(e)}")
147
+ st.caption(f"Make sure Ollama is running at {ollama_url}")
148
+
149
+ with col2:
150
+ st.subheader("๐Ÿ“– Strategy & Settings")
151
+
152
+ prompt = st.selectbox(
153
+ "Prompt Style:",
154
+ game_config.PROMPT_PRESETS,
155
+ index=0,
156
+ help="base=minimal | concise=focused on winning | adaptive=strategic analysis"
157
+ )
158
+
159
+ st.info("๐Ÿ’ก Tip: Start with Mistral 7B for good balance of speed and quality")
160
+
161
+ st.divider()
162
+
163
+ col1, col2, col3 = st.columns(3)
164
+ with col1:
165
+ if st.button("< Back", use_container_width=True):
166
+ session_manager.SessionManager.set_screen(0)
167
+ st.rerun()
168
+
169
+ with col3:
170
+ if st.button("๐ŸŽฎ Start Game", type="primary", use_container_width=True):
171
+ # Build real OllamaAgent
172
+ try:
173
+ from stratego.models.ollama_model import OllamaAgent
174
+
175
+ st.session_state.ollama_url = ollama_url
176
+ agent = OllamaAgent(
177
+ model_name=model,
178
+ prompt_pack=prompt,
179
+ host=ollama_url
180
+ )
181
+
182
+ # Initialize game
183
+ mode = session_manager.SessionManager.get_game_mode()
184
+ env_id = game_config.get_env_id(mode)
185
+ size = game_config.get_board_size(mode)
186
+
187
+ game_ctrl = GameController(env_id, size, agent, prompt)
188
+ game_ctrl.reset()
189
+
190
+ session_manager.SessionManager.set_game_controller(game_ctrl)
191
+ session_manager.SessionManager.set_ai_config(backend, model, prompt)
192
+ session_manager.SessionManager.set_screen(2)
193
+ st.rerun()
194
+
195
+ except Exception as e:
196
+ st.error(f"โŒ Failed to create AI: {str(e)}")
197
+ st.code(f"Error details:\n{str(e)}")
198
+ st.warning(
199
+ f"Make sure:\n"
200
+ f"1. Ollama is running: `ollama serve`\n"
201
+ f"2. Model is pulled: `ollama pull {model}`\n"
202
+ f"3. Server URL is correct: {ollama_url}"
203
+ )
204
+
205
+
206
+ def screen_active_game():
207
+ """Screen 2: Active game with interactive chess-like board"""
208
+ game_ctrl = session_manager.SessionManager.get_game_controller()
209
+
210
+ if not game_ctrl:
211
+ st.error("Game not initialized!")
212
+ return
213
+
214
+ st.title("โš”๏ธ STRATEGO - Battle Arena")
215
+
216
+ # Top controls
217
+ col1, col2, col3 = st.columns([1, 2, 1])
218
+ with col1:
219
+ if st.button("๐Ÿ”„ Reset", help="Start a new game"):
220
+ session_manager.SessionManager.reset_all()
221
+ st.rerun()
222
+
223
+ with col2:
224
+ # Game stats in header
225
+ col2a, col2b, col2c = st.columns(3)
226
+ with col2a:
227
+ st.metric("Moves", game_ctrl.get_turn_count())
228
+ with col2b:
229
+ current = "๐Ÿ‘ค You" if game_ctrl.is_human_turn() else "๐Ÿค– AI"
230
+ st.metric("Current", current)
231
+ with col2c:
232
+ st.metric("Status", "๐ŸŽฎ Active" if not game_ctrl.game_done else "๐Ÿ Ended")
233
+
234
+ with col3:
235
+ if st.button("๐Ÿ“‹ Menu", help="Return to main menu"):
236
+ session_manager.SessionManager.reset_all()
237
+ st.rerun()
238
+
239
+ st.divider()
240
+
241
+ # Main game area
242
+ left, right = st.columns([2.5, 1.5])
243
+
244
+ with left:
245
+ # Interactive board
246
+ player_move = render_interactive_board(game_ctrl)
247
+
248
+ if player_move:
249
+ # Execute human move
250
+ done, info = game_ctrl.execute_move(player_move)
251
+
252
+ if done:
253
+ st.session_state.game_ended = True
254
+ st.rerun()
255
+
256
+ # Trigger AI turn
257
+ player_id, obs = game_ctrl.get_current_player()
258
+ st.rerun()
259
+
260
+ # AI's turn
261
+ if game_ctrl.is_ai_turn():
262
+ st.divider()
263
+ st.markdown("## ๐Ÿค– AI is thinking...")
264
+
265
+ with st.spinner("AI calculating move..."):
266
+ try:
267
+ move, error = game_ctrl.get_ai_move()
268
+
269
+ if error:
270
+ st.warning(f"โš ๏ธ {error}")
271
+
272
+ done, info = game_ctrl.execute_move(move)
273
+ st.success(f"โœ… AI played: {move}")
274
+
275
+ if done:
276
+ st.session_state.game_ended = True
277
+ else:
278
+ # Update to human turn
279
+ player_id, obs = game_ctrl.get_current_player()
280
+
281
+ st.rerun()
282
+
283
+ except Exception as e:
284
+ st.error(f"โŒ AI Error: {str(e)}")
285
+ st.code(str(e))
286
+
287
+ with right:
288
+ st.subheader("๐Ÿ“Š Game Info")
289
+
290
+ # Status panel with beautiful styling
291
+ status_panel.render_status_panel(game_ctrl)
292
+
293
+ st.divider()
294
+
295
+ # Move history
296
+ st.subheader("๐Ÿ“œ Move History")
297
+ game_history.render_game_history(game_ctrl)
298
+
299
+ # Game end screen
300
+ if game_ctrl.game_done:
301
+ st.divider()
302
+ st.error("๐Ÿ GAME ENDED!")
303
+ col1, col2 = st.columns(2)
304
+ with col1:
305
+ if st.button("๐Ÿ”„ Play Again", use_container_width=True):
306
+ session_manager.SessionManager.reset_all()
307
+ st.rerun()
308
+ with col2:
309
+ if st.button("๐Ÿ  Main Menu", use_container_width=True):
310
+ session_manager.SessionManager.reset_all()
311
+ st.rerun()
312
+
313
+
314
+ def main():
315
+ """Main application entry point"""
316
+ # Configure page
317
+ st.set_page_config(
318
+ page_title="Stratego - Human vs AI",
319
+ page_icon="chess",
320
+ layout="wide",
321
+ initial_sidebar_state="collapsed"
322
+ )
323
+
324
+ # Initialize session
325
+ session_manager.SessionManager.init()
326
+
327
+ # Route to correct screen
328
+ screen = session_manager.SessionManager.get_screen()
329
+
330
+ if screen == 0:
331
+ screen_welcome()
332
+ elif screen == 1:
333
+ screen_ai_config()
334
+ elif screen == 2:
335
+ screen_active_game()
336
+ else:
337
+ st.error(f"Unknown screen: {screen}")
338
+
339
+
340
+ if __name__ == "__main__":
341
+ main()