amanmoon commited on
Commit
5ca3e02
·
verified ·
1 Parent(s): e772345

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +212 -0
app.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import numpy as np
4
+ import torch
5
+ import time
6
+
7
+ from Games.ConnectFour.ConnectFour import ConnectFour
8
+ from Games.ConnectFour.ConnectFourNN import ResNet as ConnectFourResNet
9
+ from Games.TicTacToe.TicTacToe import TicTacToe
10
+ from Games.TicTacToe.TicTacToeNN import ResNet as TicTacToeResNet
11
+ from Alpha_MCTS import Alpha_MCTS
12
+ torch.backends.cudnn.enabled = False
13
+
14
+ st.set_page_config(page_title="AlphaZero UI", layout="centered", page_icon="🎮")
15
+
16
+ st.markdown("""
17
+ <style>
18
+ div.stButton > button {
19
+ height: 80px;
20
+ font-size: 30px;
21
+ font-weight: bold;
22
+ border-radius: 12px;
23
+ transition: all 0.3s ease;
24
+ }
25
+ div.stButton > button:hover {
26
+ transform: translateY(-2px);
27
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
28
+ }
29
+ .main-header {
30
+ text-align: center;
31
+ margin-bottom: 2rem;
32
+ font-size: 3rem;
33
+ font-weight: 800;
34
+ background: -webkit-linear-gradient(45deg, #FF4B4B, #FF9090);
35
+ -webkit-background-clip: text;
36
+ -webkit-text-fill-color: transparent;
37
+ }
38
+ </style>
39
+ """, unsafe_allow_html=True)
40
+
41
+ @st.cache_resource
42
+ def load_model(game_name):
43
+ print("running load_model")
44
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
45
+ if game_name == "ConnectFour":
46
+ game = ConnectFour()
47
+ model = ConnectFourResNet(game, 9, 128, device)
48
+ else:
49
+ game = TicTacToe()
50
+ model = TicTacToeResNet(game, 9, 128, device)
51
+
52
+ model.eval()
53
+ model_path = os.path.join(os.getcwd(), "Games", game_name, "models_n_optimizers", "model.pt")
54
+
55
+ if os.path.exists(model_path):
56
+ try:
57
+ model.load_state_dict(torch.load(model_path, map_location=device))
58
+ except Exception as e:
59
+ st.warning(f"Failed to load model from {model_path}: {e}")
60
+ print(f"Failed to load model from {model_path}: {e}")
61
+ else:
62
+ st.warning(f"Model path does not exist: {model_path}")
63
+ print(f"Model path does not exist: {model_path}")
64
+
65
+ return game, model
66
+
67
+ def init_state(game_name):
68
+ st.session_state.game_name = game_name
69
+ st.session_state.board_state = None
70
+ st.session_state.player = 1
71
+ st.session_state.game_over = False
72
+ st.session_state.winner = None
73
+
74
+ st.sidebar.title("AlphaZero Play")
75
+ game_selection = st.sidebar.selectbox("Select Game", ["ConnectFour", "TicTacToe"])
76
+
77
+ st.sidebar.markdown("### Hyperparameters")
78
+ no_of_searches = st.sidebar.slider("Number of MCTS Searches", min_value=10, max_value=20000, value=600, step=10, help="More searches = stronger but slower AI.")
79
+ exploration_constant = st.sidebar.slider("Exploration Constant (C)", min_value=0.1, max_value=5.0, value=1.0, step=0.1, help="Higher values favor exploration.")
80
+ temperature = st.sidebar.slider("Temperature", min_value=0.1, max_value=2.0, value=1.0, step=0.1, help="Controls exploration during policy evaluation.")
81
+ adversarial = st.sidebar.checkbox("Adversarial (Zero-Sum)", value=True)
82
+ root_randomness = st.sidebar.checkbox("Root Randomness (Dirichlet Noise)", value=False)
83
+
84
+ mcts_args = {
85
+ "ADVERSARIAL": adversarial,
86
+ "ROOT_RANDOMNESS": root_randomness,
87
+ "TEMPERATURE": temperature,
88
+ "NO_OF_SEARCHES": no_of_searches,
89
+ "EXPLORATION_CONSTANT": exploration_constant,
90
+ }
91
+
92
+ if root_randomness:
93
+ mcts_args["DIRICHLET_EPSILON"] = st.sidebar.slider("Dirichlet Epsilon", 0.0, 1.0, 0.25)
94
+ mcts_args["DIRICHLET_ALPHA"] = st.sidebar.slider("Dirichlet Alpha", 0.01, 1.0, 0.3)
95
+
96
+ if "game_name" not in st.session_state or st.session_state.game_name != game_selection:
97
+ init_state(game_selection)
98
+
99
+ game, model = load_model(game_selection)
100
+ mcts = Alpha_MCTS(game, mcts_args, model)
101
+
102
+ if st.session_state.board_state is None:
103
+ st.session_state.board_state = game.initialise_state()
104
+
105
+ st.sidebar.markdown("---")
106
+ if st.sidebar.button("Reset Game"):
107
+ init_state(game_selection)
108
+ st.session_state.board_state = game.initialise_state()
109
+ st.rerun()
110
+
111
+ st.sidebar.markdown("### Rules")
112
+ st.sidebar.info(
113
+ "You are Player 1 (playing first).\n"
114
+ "AlphaZero is Player -1.\n\n"
115
+ "For **Tic Tac Toe**: Click on a cell to place your X.\n"
116
+ "\n"
117
+ "For **Connect Four**: Click the ⬇️ button above a column to drop your piece."
118
+ )
119
+
120
+ st.markdown(f"<h1 class='main-header'>{game_selection} vs AlphaZero</h1>", unsafe_allow_html=True)
121
+
122
+ if st.session_state.game_over:
123
+ if st.session_state.winner == 1:
124
+ st.success("You Won! Amazing job playing against AlphaZero!")
125
+ elif st.session_state.winner == -1:
126
+ st.error("AlphaZero Won! Better luck next time!")
127
+ else:
128
+ st.info("It's a Draw! Well played.")
129
+
130
+ def trigger_rerun():
131
+ time.sleep(0.1)
132
+ st.rerun()
133
+
134
+ def check_ai_move():
135
+ if not st.session_state.game_over and st.session_state.player == -1:
136
+ with st.spinner(f"AlphaZero is thinking ({no_of_searches} searches)..."):
137
+ neutral_state = game.change_perspective(st.session_state.board_state, st.session_state.player)
138
+ mcts_probs = mcts.search(neutral_state)
139
+ action = np.argmax(mcts_probs)
140
+
141
+ st.session_state.board_state = game.make_move(
142
+ st.session_state.board_state.copy(), action, st.session_state.player
143
+ )
144
+
145
+ # Check terminal
146
+ is_terminal, value = game.know_terminal_value(st.session_state.board_state, action)
147
+ if is_terminal:
148
+ st.session_state.game_over = True
149
+ st.session_state.winner = st.session_state.player if value == 1 else 0
150
+ else:
151
+ st.session_state.player = game.get_opponent(st.session_state.player)
152
+ trigger_rerun()
153
+
154
+ def make_move(action):
155
+ if not st.session_state.game_over and st.session_state.player == 1:
156
+ valid_moves = game.get_valid_moves(st.session_state.board_state)
157
+
158
+ if isinstance(valid_moves, np.ndarray) and valid_moves.ndim > 1:
159
+ valid_moves = valid_moves.reshape(-1)
160
+
161
+ if valid_moves[action] == 1:
162
+ st.session_state.board_state = game.make_move(
163
+ st.session_state.board_state.copy(), action, st.session_state.player
164
+ )
165
+
166
+ is_terminal, value = game.know_terminal_value(st.session_state.board_state, action)
167
+ if is_terminal:
168
+ st.session_state.game_over = True
169
+ st.session_state.winner = st.session_state.player if value == 1 else 0
170
+ else:
171
+ st.session_state.player = game.get_opponent(st.session_state.player)
172
+ trigger_rerun()
173
+
174
+ container = st.container()
175
+
176
+ with container:
177
+ if game_selection == "TicTacToe":
178
+ state = st.session_state.board_state
179
+ for row in range(3):
180
+ cols = st.columns([1, 1, 1, 1, 1])
181
+ for col in range(3):
182
+ val = state[row, col]
183
+ display_str = "❌" if val == 1 else "⭕" if val == -1 else " "
184
+
185
+ action = row * 3 + col
186
+
187
+ with cols[col + 1]:
188
+ if st.button(display_str, key=f"btn_{action}", disabled=st.session_state.game_over or val != 0 or st.session_state.player != 1, use_container_width=True):
189
+ make_move(action)
190
+
191
+ elif game_selection == "ConnectFour":
192
+ state = st.session_state.board_state
193
+
194
+ cols = st.columns(7)
195
+ valid_moves = game.get_valid_moves(state)
196
+ for col in range(7):
197
+ with cols[col]:
198
+ if st.button("⬇️", key=f"drop_{col}", disabled=st.session_state.game_over or valid_moves[col] == 0 or st.session_state.player != 1, use_container_width=True):
199
+ make_move(col)
200
+
201
+ st.markdown("---")
202
+
203
+ colors = {1: "🔴", -1: "🟡", 0: "⚫"}
204
+ for row in range(6):
205
+ cols = st.columns(7)
206
+ for col in range(7):
207
+ val = state[row, col]
208
+ with cols[col]:
209
+ st.markdown(f"<div style='text-align:center; font-size:40px;'>{colors[val]}</div>", unsafe_allow_html=True)
210
+
211
+ if not st.session_state.game_over and st.session_state.player == -1:
212
+ check_ai_move()