Update app.py
Browse files
app.py
CHANGED
|
@@ -105,6 +105,7 @@ if 'game' not in st.session_state:
|
|
| 105 |
st.session_state.current_player = 1
|
| 106 |
st.session_state.show_winner_popup = False
|
| 107 |
st.session_state.move_count = 0
|
|
|
|
| 108 |
|
| 109 |
# Title
|
| 110 |
col_title1, col_title2 = st.columns([3, 1])
|
|
@@ -138,34 +139,32 @@ if game_mode != st.session_state.game_mode:
|
|
| 138 |
st.session_state.move_count = 0
|
| 139 |
st.rerun()
|
| 140 |
|
| 141 |
-
# AI Mode
|
| 142 |
if st.session_state.game_mode == "vs AI":
|
| 143 |
st.sidebar.markdown("---")
|
| 144 |
-
st.sidebar.subheader("๐ค AI
|
| 145 |
ai_mode = st.sidebar.radio("Select AI Mode", ["Ultra-Fast โก", "Balanced ๐ฏ"],
|
| 146 |
index=0 if st.session_state.ai_mode == "Ultra-Fast" else 1,
|
| 147 |
help="Ultra-Fast: ~200ms | Balanced: ~400ms, deeper analysis",
|
| 148 |
key="ai_mode_radio")
|
| 149 |
|
| 150 |
-
# Update mode without resetting game
|
| 151 |
new_mode = "Ultra-Fast" if "Ultra-Fast" in ai_mode else "Balanced"
|
| 152 |
if new_mode != st.session_state.ai_mode:
|
| 153 |
st.session_state.ai_mode = new_mode
|
| 154 |
-
# Don't reset - just update the AI reference
|
| 155 |
|
| 156 |
st.session_state.current_ai = st.session_state.ai_ultra if st.session_state.ai_mode == "Ultra-Fast" else st.session_state.ai_balanced
|
| 157 |
|
| 158 |
-
# Depth slider
|
| 159 |
st.sidebar.markdown("---")
|
| 160 |
st.sidebar.subheader("๐๏ธ Search Depth")
|
| 161 |
if st.session_state.ai_mode == "Ultra-Fast":
|
| 162 |
-
depth = st.sidebar.slider("Depth (Ultra-Fast)", 3, 8, 5,
|
| 163 |
-
help="Lower = faster, Higher = stronger")
|
| 164 |
st.session_state.ai_ultra.depth = depth
|
|
|
|
| 165 |
else:
|
| 166 |
-
depth = st.sidebar.slider("Depth (Balanced)", 4, 8, 6,
|
| 167 |
-
help="Lower = faster, Higher = stronger")
|
| 168 |
st.session_state.ai_balanced.depth = depth
|
|
|
|
| 169 |
|
| 170 |
st.sidebar.markdown("---")
|
| 171 |
|
|
@@ -270,12 +269,10 @@ with col1:
|
|
| 270 |
st.session_state.move_history.append(human_move)
|
| 271 |
st.session_state.move_count += 1
|
| 272 |
|
| 273 |
-
# Get AI analysis
|
| 274 |
if st.session_state.game_mode == "Two Player":
|
| 275 |
-
# For two player, use balanced for analysis
|
| 276 |
analysis_ai = st.session_state.ai_balanced
|
| 277 |
else:
|
| 278 |
-
# For vs AI, use whichever mode is selected
|
| 279 |
analysis_ai = st.session_state.current_ai
|
| 280 |
|
| 281 |
ai_analysis = analysis_ai.get_best_move()
|
|
@@ -354,7 +351,6 @@ with col2:
|
|
| 354 |
if st.session_state.game_mode == "vs AI" and hasattr(st.session_state, 'latest_ai_move'):
|
| 355 |
ai_move = st.session_state.latest_ai_move
|
| 356 |
|
| 357 |
-
# Get FULL explanation
|
| 358 |
if st.session_state.explainer:
|
| 359 |
explanation = st.session_state.explainer.explain_move(ai_move)
|
| 360 |
has_llm = explanation.get('success', False)
|
|
@@ -375,7 +371,6 @@ with col2:
|
|
| 375 |
</div>
|
| 376 |
''', unsafe_allow_html=True)
|
| 377 |
|
| 378 |
-
# FULL analysis display
|
| 379 |
st.success(f"๐ก **Why This Move:**\n{explanation['explanation']}")
|
| 380 |
|
| 381 |
if explanation.get('threat_analysis'):
|
|
@@ -384,7 +379,6 @@ with col2:
|
|
| 384 |
if explanation.get('key_insight'):
|
| 385 |
st.info(f"๐ **Strategic Insight:**\n{explanation['key_insight']}")
|
| 386 |
|
| 387 |
-
# Complete 5 metrics
|
| 388 |
st.markdown("### ๐ Algorithm Performance")
|
| 389 |
|
| 390 |
stat_col1, stat_col2, stat_col3 = st.columns(3)
|
|
@@ -426,12 +420,10 @@ with col2:
|
|
| 426 |
</div>
|
| 427 |
''', unsafe_allow_html=True)
|
| 428 |
|
| 429 |
-
# Only show fallback message if LLM actually failed
|
| 430 |
if not has_llm:
|
| 431 |
st.info("โน๏ธ Using fallback explanation (HF API unavailable)")
|
| 432 |
|
| 433 |
elif st.session_state.game_mode == "Two Player":
|
| 434 |
-
# Separate player sections
|
| 435 |
if st.session_state.player1_analyses:
|
| 436 |
st.markdown("### ๐ด Player 1 Analysis")
|
| 437 |
latest_p1 = st.session_state.player1_analyses[-1]
|
|
@@ -444,6 +436,27 @@ with col2:
|
|
| 444 |
|
| 445 |
if latest_p1['analysis']['threats']:
|
| 446 |
st.info(f"โ๏ธ **Threats:** {', '.join(latest_p1['analysis']['threats'])}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 448 |
|
| 449 |
if st.session_state.player2_analyses:
|
|
@@ -458,6 +471,27 @@ with col2:
|
|
| 458 |
|
| 459 |
if latest_p2['analysis']['threats']:
|
| 460 |
st.info(f"โ๏ธ **Threats:** {', '.join(latest_p2['analysis']['threats'])}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 462 |
|
| 463 |
# Winner popup
|
|
@@ -479,14 +513,15 @@ if st.session_state.show_winner_popup and st.session_state.game_over:
|
|
| 479 |
if st.session_state.game_over:
|
| 480 |
st.markdown("---")
|
| 481 |
st.markdown("### ๐ Download Match Report")
|
| 482 |
-
st.info("๐ฅ Get a detailed analysis
|
| 483 |
|
| 484 |
report = generate_match_report(
|
| 485 |
st.session_state.game_mode,
|
| 486 |
st.session_state.ai_mode,
|
| 487 |
st.session_state.winner,
|
| 488 |
st.session_state.move_history_detailed,
|
| 489 |
-
st.session_state.game.board_to_string()
|
|
|
|
| 490 |
)
|
| 491 |
|
| 492 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
|
|
| 105 |
st.session_state.current_player = 1
|
| 106 |
st.session_state.show_winner_popup = False
|
| 107 |
st.session_state.move_count = 0
|
| 108 |
+
st.session_state.current_depth = 5
|
| 109 |
|
| 110 |
# Title
|
| 111 |
col_title1, col_title2 = st.columns([3, 1])
|
|
|
|
| 139 |
st.session_state.move_count = 0
|
| 140 |
st.rerun()
|
| 141 |
|
| 142 |
+
# AI Mode
|
| 143 |
if st.session_state.game_mode == "vs AI":
|
| 144 |
st.sidebar.markdown("---")
|
| 145 |
+
st.sidebar.subheader("๐ค AI Difficulty")
|
| 146 |
ai_mode = st.sidebar.radio("Select AI Mode", ["Ultra-Fast โก", "Balanced ๐ฏ"],
|
| 147 |
index=0 if st.session_state.ai_mode == "Ultra-Fast" else 1,
|
| 148 |
help="Ultra-Fast: ~200ms | Balanced: ~400ms, deeper analysis",
|
| 149 |
key="ai_mode_radio")
|
| 150 |
|
|
|
|
| 151 |
new_mode = "Ultra-Fast" if "Ultra-Fast" in ai_mode else "Balanced"
|
| 152 |
if new_mode != st.session_state.ai_mode:
|
| 153 |
st.session_state.ai_mode = new_mode
|
|
|
|
| 154 |
|
| 155 |
st.session_state.current_ai = st.session_state.ai_ultra if st.session_state.ai_mode == "Ultra-Fast" else st.session_state.ai_balanced
|
| 156 |
|
| 157 |
+
# Depth slider
|
| 158 |
st.sidebar.markdown("---")
|
| 159 |
st.sidebar.subheader("๐๏ธ Search Depth")
|
| 160 |
if st.session_state.ai_mode == "Ultra-Fast":
|
| 161 |
+
depth = st.sidebar.slider("Depth (Ultra-Fast)", 3, 8, 5, help="Lower = faster, Higher = stronger")
|
|
|
|
| 162 |
st.session_state.ai_ultra.depth = depth
|
| 163 |
+
st.session_state.current_depth = depth
|
| 164 |
else:
|
| 165 |
+
depth = st.sidebar.slider("Depth (Balanced)", 4, 8, 6, help="Lower = faster, Higher = stronger")
|
|
|
|
| 166 |
st.session_state.ai_balanced.depth = depth
|
| 167 |
+
st.session_state.current_depth = depth
|
| 168 |
|
| 169 |
st.sidebar.markdown("---")
|
| 170 |
|
|
|
|
| 269 |
st.session_state.move_history.append(human_move)
|
| 270 |
st.session_state.move_count += 1
|
| 271 |
|
| 272 |
+
# Get AI analysis
|
| 273 |
if st.session_state.game_mode == "Two Player":
|
|
|
|
| 274 |
analysis_ai = st.session_state.ai_balanced
|
| 275 |
else:
|
|
|
|
| 276 |
analysis_ai = st.session_state.current_ai
|
| 277 |
|
| 278 |
ai_analysis = analysis_ai.get_best_move()
|
|
|
|
| 351 |
if st.session_state.game_mode == "vs AI" and hasattr(st.session_state, 'latest_ai_move'):
|
| 352 |
ai_move = st.session_state.latest_ai_move
|
| 353 |
|
|
|
|
| 354 |
if st.session_state.explainer:
|
| 355 |
explanation = st.session_state.explainer.explain_move(ai_move)
|
| 356 |
has_llm = explanation.get('success', False)
|
|
|
|
| 371 |
</div>
|
| 372 |
''', unsafe_allow_html=True)
|
| 373 |
|
|
|
|
| 374 |
st.success(f"๐ก **Why This Move:**\n{explanation['explanation']}")
|
| 375 |
|
| 376 |
if explanation.get('threat_analysis'):
|
|
|
|
| 379 |
if explanation.get('key_insight'):
|
| 380 |
st.info(f"๐ **Strategic Insight:**\n{explanation['key_insight']}")
|
| 381 |
|
|
|
|
| 382 |
st.markdown("### ๐ Algorithm Performance")
|
| 383 |
|
| 384 |
stat_col1, stat_col2, stat_col3 = st.columns(3)
|
|
|
|
| 420 |
</div>
|
| 421 |
''', unsafe_allow_html=True)
|
| 422 |
|
|
|
|
| 423 |
if not has_llm:
|
| 424 |
st.info("โน๏ธ Using fallback explanation (HF API unavailable)")
|
| 425 |
|
| 426 |
elif st.session_state.game_mode == "Two Player":
|
|
|
|
| 427 |
if st.session_state.player1_analyses:
|
| 428 |
st.markdown("### ๐ด Player 1 Analysis")
|
| 429 |
latest_p1 = st.session_state.player1_analyses[-1]
|
|
|
|
| 436 |
|
| 437 |
if latest_p1['analysis']['threats']:
|
| 438 |
st.info(f"โ๏ธ **Threats:** {', '.join(latest_p1['analysis']['threats'])}")
|
| 439 |
+
|
| 440 |
+
# Algorithm Performance for Two Player
|
| 441 |
+
st.markdown("**Algorithm Analysis:**")
|
| 442 |
+
perf_col1, perf_col2 = st.columns(2)
|
| 443 |
+
|
| 444 |
+
with perf_col1:
|
| 445 |
+
st.markdown(f'''
|
| 446 |
+
<div class="stats-card">
|
| 447 |
+
<div class="stat-number">{latest_p1['analysis']['nodes_explored']:,}</div>
|
| 448 |
+
<div class="stat-label">Nodes Explored</div>
|
| 449 |
+
</div>
|
| 450 |
+
''', unsafe_allow_html=True)
|
| 451 |
+
|
| 452 |
+
with perf_col2:
|
| 453 |
+
st.markdown(f'''
|
| 454 |
+
<div class="stats-card">
|
| 455 |
+
<div class="stat-number">{latest_p1['analysis']['nodes_pruned']:,}</div>
|
| 456 |
+
<div class="stat-label">Nodes Pruned</div>
|
| 457 |
+
</div>
|
| 458 |
+
''', unsafe_allow_html=True)
|
| 459 |
+
|
| 460 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 461 |
|
| 462 |
if st.session_state.player2_analyses:
|
|
|
|
| 471 |
|
| 472 |
if latest_p2['analysis']['threats']:
|
| 473 |
st.info(f"โ๏ธ **Threats:** {', '.join(latest_p2['analysis']['threats'])}")
|
| 474 |
+
|
| 475 |
+
# Algorithm Performance for Two Player
|
| 476 |
+
st.markdown("**Algorithm Analysis:**")
|
| 477 |
+
perf_col1, perf_col2 = st.columns(2)
|
| 478 |
+
|
| 479 |
+
with perf_col1:
|
| 480 |
+
st.markdown(f'''
|
| 481 |
+
<div class="stats-card">
|
| 482 |
+
<div class="stat-number">{latest_p2['analysis']['nodes_explored']:,}</div>
|
| 483 |
+
<div class="stat-label">Nodes Explored</div>
|
| 484 |
+
</div>
|
| 485 |
+
''', unsafe_allow_html=True)
|
| 486 |
+
|
| 487 |
+
with perf_col2:
|
| 488 |
+
st.markdown(f'''
|
| 489 |
+
<div class="stats-card">
|
| 490 |
+
<div class="stat-number">{latest_p2['analysis']['nodes_pruned']:,}</div>
|
| 491 |
+
<div class="stat-label">Nodes Pruned</div>
|
| 492 |
+
</div>
|
| 493 |
+
''', unsafe_allow_html=True)
|
| 494 |
+
|
| 495 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 496 |
|
| 497 |
# Winner popup
|
|
|
|
| 513 |
if st.session_state.game_over:
|
| 514 |
st.markdown("---")
|
| 515 |
st.markdown("### ๐ Download Match Report")
|
| 516 |
+
st.info("๐ฅ Get a detailed analysis with algorithm metrics and search depth")
|
| 517 |
|
| 518 |
report = generate_match_report(
|
| 519 |
st.session_state.game_mode,
|
| 520 |
st.session_state.ai_mode,
|
| 521 |
st.session_state.winner,
|
| 522 |
st.session_state.move_history_detailed,
|
| 523 |
+
st.session_state.game.board_to_string(),
|
| 524 |
+
search_depth=st.session_state.current_depth if st.session_state.game_mode == "vs AI" else None
|
| 525 |
)
|
| 526 |
|
| 527 |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|