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