ShubhanshuBansod commited on
Commit
fc6af73
ยท
verified ยท
1 Parent(s): 5871b1f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -59
app.py CHANGED
@@ -1,7 +1,5 @@
1
- # app.py - Final Polished Version
2
  import streamlit as st
3
  import os
4
- import time
5
  from datetime import datetime
6
  from connect_four_game import ConnectFour
7
  from minimax_ai import MinimaxAI
@@ -15,7 +13,7 @@ st.set_page_config(
15
  initial_sidebar_state="expanded"
16
  )
17
 
18
- # Enhanced CSS with animations and better styling
19
  st.markdown('''
20
  <style>
21
  .board-display {
@@ -84,32 +82,6 @@ st.markdown('''
84
  .ultra-fast { background: #10b981; color: white; }
85
  .balanced { background: #3b82f6; color: white; }
86
  .two-player { background: #f59e0b; color: white; }
87
-
88
- /* Winner popup animation */
89
- @keyframes confetti {
90
- 0% { transform: translateY(0) rotate(0deg); opacity: 1; }
91
- 100% { transform: translateY(1000px) rotate(720deg); opacity: 0; }
92
- }
93
- @keyframes slideDown {
94
- from { transform: translateY(-100%); opacity: 0; }
95
- to { transform: translateY(0); opacity: 1; }
96
- }
97
- .winner-popup {
98
- position: fixed;
99
- top: 50%;
100
- left: 50%;
101
- transform: translate(-50%, -50%);
102
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
103
- color: white;
104
- padding: 40px 60px;
105
- border-radius: 20px;
106
- box-shadow: 0 20px 60px rgba(0,0,0,0.3);
107
- z-index: 9999;
108
- animation: slideDown 0.5s ease-out;
109
- text-align: center;
110
- font-size: 32px;
111
- font-weight: bold;
112
- }
113
  </style>
114
  ''', unsafe_allow_html=True)
115
 
@@ -166,17 +138,18 @@ if game_mode != st.session_state.game_mode:
166
  st.session_state.move_count = 0
167
  st.rerun()
168
 
169
- # AI Mode (vs AI only)
170
  if st.session_state.game_mode == "vs AI":
171
  st.sidebar.markdown("---")
172
  st.sidebar.subheader("๐Ÿค– AI Difficulty")
173
  ai_mode = st.sidebar.radio("Select AI Mode", ["Ultra-Fast โšก", "Balanced ๐ŸŽฏ"],
174
- index=0 if st.session_state.ai_mode == "Ultra-Fast" else 1)
 
175
 
176
  st.session_state.ai_mode = "Ultra-Fast" if "Ultra-Fast" in ai_mode else "Balanced"
177
  st.session_state.current_ai = st.session_state.ai_ultra if st.session_state.ai_mode == "Ultra-Fast" else st.session_state.ai_balanced
178
 
179
- # Depth slider for AI mode
180
  st.sidebar.markdown("---")
181
  st.sidebar.subheader("๐ŸŽš๏ธ Search Depth")
182
  if st.session_state.ai_mode == "Ultra-Fast":
@@ -227,14 +200,12 @@ with col2:
227
 
228
  st.sidebar.markdown("---")
229
 
230
- # Additional features
231
  st.sidebar.subheader("๐Ÿ“Š Game Stats")
232
  st.sidebar.write(f"**Moves Played:** {st.session_state.move_count}")
233
  if st.session_state.game_mode == "Two Player":
234
- p1_moves = len(st.session_state.player1_analyses)
235
- p2_moves = len(st.session_state.player2_analyses)
236
- st.sidebar.write(f"**Player 1 Moves:** {p1_moves}")
237
- st.sidebar.write(f"**Player 2 Moves:** {p2_moves}")
238
 
239
  st.sidebar.markdown("---")
240
 
@@ -250,12 +221,24 @@ with st.sidebar.expander("๐Ÿ“‹ Rules"):
250
  st.markdown('''
251
  **Objective:** Get 4 in a row!
252
 
253
- **Patterns:** โ†โ†’ โ†•๏ธ โ†—๏ธ โ†–๏ธ
254
 
255
  **Players:** ๐Ÿ”ด Red, ๐ŸŸก Yellow
256
  ''')
257
 
258
- # Main game area
 
 
 
 
 
 
 
 
 
 
 
 
259
  col1, col2 = st.columns([2, 3])
260
 
261
  with col1:
@@ -353,47 +336,98 @@ with col1:
353
  st.rerun()
354
 
355
  with col2:
356
- st.subheader("๐Ÿค– Analysis & Insights")
357
 
358
  if st.session_state.game_mode == "vs AI" and hasattr(st.session_state, 'latest_ai_move'):
359
  ai_move = st.session_state.latest_ai_move
360
 
 
361
  if st.session_state.explainer:
362
  explanation = st.session_state.explainer.explain_move(ai_move)
363
  else:
364
  explanation = {
365
  'explanation': f"Column {ai_move['move']} scores {ai_move['score']} points.",
366
- 'threat_analysis': "; ".join(ai_move['threats']) if ai_move['threats'] else "Strategic"
 
 
367
  }
368
 
369
- st.markdown(f'<div class="move-card"><h3>๐ŸŽฏ AI Played: Column {ai_move["move"]}</h3>'
370
- f'<p><strong>Score:</strong> {ai_move["score"]} points</p></div>',
371
- unsafe_allow_html=True)
372
- st.success(f"๐Ÿ’ก **Strategy:** {explanation['explanation']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
 
374
- st.markdown("### ๐Ÿ“Š Performance Metrics")
375
  stat_col1, stat_col2, stat_col3 = st.columns(3)
376
  with stat_col1:
377
- st.markdown(f'<div class="stats-card"><div class="stat-number">{ai_move["nodes_explored"]:,}</div>'
378
- f'<div class="stat-label">Explored</div></div>', unsafe_allow_html=True)
 
 
 
 
379
  with stat_col2:
380
- st.markdown(f'<div class="stats-card"><div class="stat-number">{ai_move["nodes_pruned"]:,}</div>'
381
- f'<div class="stat-label">Pruned</div></div>', unsafe_allow_html=True)
 
 
 
 
382
  with stat_col3:
383
- st.markdown(f'<div class="stats-card"><div class="stat-number">{ai_move["time_ms"]:.0f}ms</div>'
384
- f'<div class="stat-label">Time</div></div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
 
386
  elif st.session_state.game_mode == "Two Player":
387
- # Separate sections for each player
388
  if st.session_state.player1_analyses:
389
  st.markdown("### ๐Ÿ”ด Player 1 Analysis")
390
  latest_p1 = st.session_state.player1_analyses[-1]
391
  st.markdown('<div class="player-section player1-section">', unsafe_allow_html=True)
392
  st.write(f"**Last Move:** Column {latest_p1['column']}")
393
  if latest_p1['recommendation']['is_optimal']:
394
- st.success("โœ… Excellent Move!")
395
  else:
396
- st.warning(f"๐Ÿค” AI suggests Column {latest_p1['recommendation']['suggested_column']}")
 
 
 
397
  st.markdown('</div>', unsafe_allow_html=True)
398
 
399
  if st.session_state.player2_analyses:
@@ -402,9 +436,12 @@ with col2:
402
  st.markdown('<div class="player-section player2-section">', unsafe_allow_html=True)
403
  st.write(f"**Last Move:** Column {latest_p2['column']}")
404
  if latest_p2['recommendation']['is_optimal']:
405
- st.success("โœ… Excellent Move!")
406
  else:
407
- st.warning(f"๐Ÿค” AI suggests Column {latest_p2['recommendation']['suggested_column']}")
 
 
 
408
  st.markdown('</div>', unsafe_allow_html=True)
409
 
410
  # Winner popup
@@ -422,11 +459,11 @@ if st.session_state.show_winner_popup and st.session_state.game_over:
422
 
423
  st.session_state.show_winner_popup = False
424
 
425
- # Game over - show report download
426
  if st.session_state.game_over:
427
  st.markdown("---")
428
  st.markdown("### ๐Ÿ“„ Download Match Report")
429
- st.info("๐Ÿ“ฅ Get a detailed analysis of this match")
430
 
431
  report = generate_match_report(
432
  st.session_state.game_mode,
 
 
1
  import streamlit as st
2
  import os
 
3
  from datetime import datetime
4
  from connect_four_game import ConnectFour
5
  from minimax_ai import MinimaxAI
 
13
  initial_sidebar_state="expanded"
14
  )
15
 
16
+ # Enhanced CSS
17
  st.markdown('''
18
  <style>
19
  .board-display {
 
82
  .ultra-fast { background: #10b981; color: white; }
83
  .balanced { background: #3b82f6; color: white; }
84
  .two-player { background: #f59e0b; color: white; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  </style>
86
  ''', unsafe_allow_html=True)
87
 
 
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 Difficulty")
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
 
149
  st.session_state.ai_mode = "Ultra-Fast" if "Ultra-Fast" in ai_mode else "Balanced"
150
  st.session_state.current_ai = st.session_state.ai_ultra if st.session_state.ai_mode == "Ultra-Fast" else st.session_state.ai_balanced
151
 
152
+ # Depth slider
153
  st.sidebar.markdown("---")
154
  st.sidebar.subheader("๐ŸŽš๏ธ Search Depth")
155
  if st.session_state.ai_mode == "Ultra-Fast":
 
200
 
201
  st.sidebar.markdown("---")
202
 
203
+ # Game Stats
204
  st.sidebar.subheader("๐Ÿ“Š Game Stats")
205
  st.sidebar.write(f"**Moves Played:** {st.session_state.move_count}")
206
  if st.session_state.game_mode == "Two Player":
207
+ st.sidebar.write(f"**Player 1:** {len(st.session_state.player1_analyses)}")
208
+ st.sidebar.write(f"**Player 2:** {len(st.session_state.player2_analyses)}")
 
 
209
 
210
  st.sidebar.markdown("---")
211
 
 
221
  st.markdown('''
222
  **Objective:** Get 4 in a row!
223
 
224
+ **Patterns:** Horizontal โ†โ†’, Vertical โ†•๏ธ, Diagonal โ†—๏ธ โ†–๏ธ
225
 
226
  **Players:** ๐Ÿ”ด Red, ๐ŸŸก Yellow
227
  ''')
228
 
229
+ # AI Concepts
230
+ with st.sidebar.expander("๐Ÿง  AI Concepts"):
231
+ st.markdown('''
232
+ **Minimax:** AI evaluates all possible moves
233
+
234
+ **Alpha-Beta:** Prunes bad branches (saves 80%+ time)
235
+
236
+ **Heuristic:** Scores positions intelligently
237
+
238
+ **Search Depth:** Moves ahead AI thinks
239
+ ''')
240
+
241
+ # Main area
242
  col1, col2 = st.columns([2, 3])
243
 
244
  with col1:
 
336
  st.rerun()
337
 
338
  with col2:
339
+ st.subheader("๐Ÿค– AI Analysis & Insights")
340
 
341
  if st.session_state.game_mode == "vs AI" and hasattr(st.session_state, 'latest_ai_move'):
342
  ai_move = st.session_state.latest_ai_move
343
 
344
+ # Get FULL explanation
345
  if st.session_state.explainer:
346
  explanation = st.session_state.explainer.explain_move(ai_move)
347
  else:
348
  explanation = {
349
  'explanation': f"Column {ai_move['move']} scores {ai_move['score']} points.",
350
+ 'threat_analysis': "; ".join(ai_move['threats']) if ai_move['threats'] else "Strategic move",
351
+ 'key_insight': "Good positioning",
352
+ 'success': False
353
  }
354
 
355
+ st.markdown(f'''
356
+ <div class="move-card">
357
+ <h3>๐ŸŽฏ AI Played: Column {ai_move['move']}</h3>
358
+ <p><strong>Evaluation Score:</strong> {ai_move['score']} points</p>
359
+ <p><strong>Mode:</strong> {st.session_state.ai_mode}</p>
360
+ </div>
361
+ ''', unsafe_allow_html=True)
362
+
363
+ # FULL analysis display (like before)
364
+ st.success(f"๐Ÿ’ก **Why This Move:**\n{explanation['explanation']}")
365
+
366
+ if explanation.get('threat_analysis'):
367
+ st.warning(f"โš”๏ธ **Threat Analysis:**\n{explanation['threat_analysis']}")
368
+
369
+ if explanation.get('key_insight'):
370
+ st.info(f"๐Ÿ”‘ **Strategic Insight:**\n{explanation['key_insight']}")
371
+
372
+ # Complete 5 metrics
373
+ st.markdown("### ๐Ÿ“Š Algorithm Performance")
374
 
 
375
  stat_col1, stat_col2, stat_col3 = st.columns(3)
376
  with stat_col1:
377
+ st.markdown(f'''
378
+ <div class="stats-card">
379
+ <div class="stat-number">{ai_move["nodes_explored"]:,}</div>
380
+ <div class="stat-label">Nodes Explored</div>
381
+ </div>
382
+ ''', unsafe_allow_html=True)
383
  with stat_col2:
384
+ st.markdown(f'''
385
+ <div class="stats-card">
386
+ <div class="stat-number">{ai_move["nodes_pruned"]:,}</div>
387
+ <div class="stat-label">Nodes Pruned</div>
388
+ </div>
389
+ ''', unsafe_allow_html=True)
390
  with stat_col3:
391
+ st.markdown(f'''
392
+ <div class="stats-card">
393
+ <div class="stat-number">{ai_move["pruning_efficiency"]:.1f}%</div>
394
+ <div class="stat-label">Efficiency</div>
395
+ </div>
396
+ ''', unsafe_allow_html=True)
397
+
398
+ stat_col4, stat_col5 = st.columns(2)
399
+ with stat_col4:
400
+ st.markdown(f'''
401
+ <div class="stats-card">
402
+ <div class="stat-number">{ai_move["depth"]}</div>
403
+ <div class="stat-label">Search Depth</div>
404
+ </div>
405
+ ''', unsafe_allow_html=True)
406
+ with stat_col5:
407
+ st.markdown(f'''
408
+ <div class="stats-card">
409
+ <div class="stat-number">{ai_move["time_ms"]:.0f}ms</div>
410
+ <div class="stat-label">Response Time</div>
411
+ </div>
412
+ ''', unsafe_allow_html=True)
413
+
414
+ if not explanation.get('success', True):
415
+ st.info("โ„น๏ธ Using fallback explanation (HF API unavailable)")
416
 
417
  elif st.session_state.game_mode == "Two Player":
418
+ # Separate player sections
419
  if st.session_state.player1_analyses:
420
  st.markdown("### ๐Ÿ”ด Player 1 Analysis")
421
  latest_p1 = st.session_state.player1_analyses[-1]
422
  st.markdown('<div class="player-section player1-section">', unsafe_allow_html=True)
423
  st.write(f"**Last Move:** Column {latest_p1['column']}")
424
  if latest_p1['recommendation']['is_optimal']:
425
+ st.success("โœ… Excellent Move! Matches AI recommendation")
426
  else:
427
+ st.warning(f"๐Ÿค” AI suggests Column {latest_p1['recommendation']['suggested_column']} (Score difference: {latest_p1['recommendation']['score_diff']})")
428
+
429
+ if latest_p1['analysis']['threats']:
430
+ st.info(f"โš”๏ธ **Threats:** {', '.join(latest_p1['analysis']['threats'])}")
431
  st.markdown('</div>', unsafe_allow_html=True)
432
 
433
  if st.session_state.player2_analyses:
 
436
  st.markdown('<div class="player-section player2-section">', unsafe_allow_html=True)
437
  st.write(f"**Last Move:** Column {latest_p2['column']}")
438
  if latest_p2['recommendation']['is_optimal']:
439
+ st.success("โœ… Excellent Move! Matches AI recommendation")
440
  else:
441
+ st.warning(f"๐Ÿค” AI suggests Column {latest_p2['recommendation']['suggested_column']} (Score difference: {latest_p2['recommendation']['score_diff']})")
442
+
443
+ if latest_p2['analysis']['threats']:
444
+ st.info(f"โš”๏ธ **Threats:** {', '.join(latest_p2['analysis']['threats'])}")
445
  st.markdown('</div>', unsafe_allow_html=True)
446
 
447
  # Winner popup
 
459
 
460
  st.session_state.show_winner_popup = False
461
 
462
+ # Game over - report download
463
  if st.session_state.game_over:
464
  st.markdown("---")
465
  st.markdown("### ๐Ÿ“„ Download Match Report")
466
+ st.info("๐Ÿ“ฅ Get a detailed analysis of this match including move-by-move breakdown")
467
 
468
  report = generate_match_report(
469
  st.session_state.game_mode,