DarshanScripts's picture
Upload stratego/web/app.py with huggingface_hub
ad372ca verified
"""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()