SmokeyBandit commited on
Commit
88de4e7
·
verified ·
1 Parent(s): 4d70b4c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -129
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import numpy as np
3
  from enum import Enum
4
  import random
 
5
 
6
  class Difficulty(Enum):
7
  EASY = "Easy"
@@ -15,135 +16,62 @@ class GoGame:
15
  self.current_player = 1 # 1 for black, -1 for white
16
  self.last_move = None
17
  self.pass_count = 0
18
-
19
- def is_valid_move(self, x, y):
20
- if x < 0 or x >= self.size or y < 0 or y >= self.size:
21
- return False
22
- if self.board[x][y] != 0:
23
- return False
24
- # Make move temporarily to check for suicide rule
25
- self.board[x][y] = self.current_player
26
- has_liberties = self.has_liberties(x, y)
27
- self.board[x][y] = 0
28
- return has_liberties
29
-
30
- def get_neighbors(self, x, y):
31
- neighbors = []
32
- for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
33
- nx, ny = x + dx, y + dy
34
- if 0 <= nx < self.size and 0 <= ny < self.size:
35
- neighbors.append((nx, ny))
36
- return neighbors
37
-
38
- def has_liberties(self, x, y):
39
- color = self.board[x][y]
40
- checked = set()
41
-
42
- def check_group(x, y):
43
- if (x, y) in checked:
44
- return False
45
- checked.add((x, y))
46
-
47
- for nx, ny in self.get_neighbors(x, y):
48
- if self.board[nx][ny] == 0:
49
- return True
50
- if self.board[nx][ny] == color and check_group(nx, ny):
51
- return True
52
- return False
53
-
54
- return check_group(x, y)
55
-
56
- def make_move(self, x, y):
57
- if not self.is_valid_move(x, y):
58
- return False
59
-
60
- self.board[x][y] = self.current_player
61
- self.last_move = (x, y)
62
- self.pass_count = 0
63
- self.current_player *= -1
64
- return True
65
-
66
- def ai_move(self, difficulty):
67
- if difficulty == Difficulty.EASY:
68
- return self.random_move()
69
- elif difficulty == Difficulty.MEDIUM:
70
- return self.medium_move()
71
- else:
72
- return self.hard_move()
73
-
74
- def random_move(self):
75
- valid_moves = []
76
- for i in range(self.size):
77
- for j in range(self.size):
78
- if self.is_valid_move(i, j):
79
- valid_moves.append((i, j))
80
-
81
- if not valid_moves:
82
- return None
83
-
84
- move = random.choice(valid_moves)
85
- self.make_move(*move)
86
- return move
87
-
88
- def medium_move(self):
89
- # Medium difficulty tries to play near the last human move
90
- if self.last_move is None:
91
- return self.random_move()
92
-
93
- last_x, last_y = self.last_move
94
- for radius in range(1, self.size):
95
- valid_moves = []
96
- for dx in range(-radius, radius + 1):
97
- for dy in range(-radius, radius + 1):
98
- if abs(dx) + abs(dy) == radius:
99
- x, y = last_x + dx, last_y + dy
100
- if 0 <= x < self.size and 0 <= y < self.size and self.is_valid_move(x, y):
101
- valid_moves.append((x, y))
102
-
103
- if valid_moves:
104
- move = random.choice(valid_moves)
105
- self.make_move(*move)
106
- return move
107
-
108
- return self.random_move()
109
-
110
- def hard_move(self):
111
- # Hard difficulty tries to control the center and corners
112
- center = self.size // 2
113
- priority_moves = [
114
- (center, center),
115
- (1, 1), (1, self.size-2), (self.size-2, 1), (self.size-2, self.size-2),
116
- (center, 1), (1, center), (center, self.size-2), (self.size-2, center)
117
- ]
118
-
119
- for x, y in priority_moves:
120
- if self.is_valid_move(x, y):
121
- self.make_move(x, y)
122
- return (x, y)
123
-
124
- return self.medium_move()
125
 
126
  def create_board_image(board):
127
- # Convert board to RGB image
128
- image = np.zeros((board.shape[0], board.shape[1], 3), dtype=np.uint8)
129
- image.fill(222) # Wooden background color
 
 
 
 
130
 
131
  # Draw grid lines
132
  for i in range(board.shape[0]):
133
- image[i, :] = [150, 150, 150]
134
- image[:, i] = [150, 150, 150]
 
 
 
 
 
 
 
 
 
 
135
 
136
  # Draw stones
137
  for i in range(board.shape[0]):
138
  for j in range(board.shape[1]):
139
- if board[i, j] == 1: # Black stone
140
- image[i, j] = [0, 0, 0]
141
- elif board[i, j] == -1: # White stone
142
- image[i, j] = [255, 255, 255]
 
 
 
 
 
 
 
 
 
143
 
144
- # Scale the image up for better visibility
145
- scaled_image = np.repeat(np.repeat(image, 40, axis=0), 40, axis=1)
146
- return scaled_image
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  class GradioGoGame:
149
  def __init__(self):
@@ -154,7 +82,13 @@ class GradioGoGame:
154
  if x is None or y is None:
155
  return create_board_image(self.game.board), "Invalid move"
156
 
157
- x, y = int(x), int(y)
 
 
 
 
 
 
158
  self.difficulty = Difficulty(difficulty)
159
 
160
  if not self.game.make_move(x, y):
@@ -178,25 +112,25 @@ def create_interface():
178
  gr.Markdown("# Go Game vs AI")
179
 
180
  with gr.Row():
181
- with gr.Column():
182
  board_output = gr.Image(
183
  value=create_board_image(game.game.board),
184
  label="Go Board",
185
- height=360,
186
- width=360
187
  )
188
- msg_output = gr.Textbox(label="Message", value="Click on the board to make a move")
189
 
190
- with gr.Column():
191
- x_input = gr.Number(label="X coordinate (0-8)")
192
- y_input = gr.Number(label="Y coordinate (0-8)")
193
  difficulty = gr.Radio(
194
  choices=[d.value for d in Difficulty],
195
  value=Difficulty.EASY.value,
196
  label="Difficulty"
197
  )
198
- move_btn = gr.Button("Make Move")
199
- reset_btn = gr.Button("Reset Game")
200
 
201
  move_btn.click(
202
  game.make_move,
 
2
  import numpy as np
3
  from enum import Enum
4
  import random
5
+ import cv2
6
 
7
  class Difficulty(Enum):
8
  EASY = "Easy"
 
16
  self.current_player = 1 # 1 for black, -1 for white
17
  self.last_move = None
18
  self.pass_count = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  def create_board_image(board):
21
+ # Create a larger base image (19x19 cells, each 40 pixels)
22
+ cell_size = 40
23
+ margin = 30
24
+ total_size = board.shape[0] * cell_size + 2 * margin
25
+
26
+ # Create base image with wooden texture color
27
+ image = np.full((total_size, total_size, 3), [219, 179, 119], dtype=np.uint8)
28
 
29
  # Draw grid lines
30
  for i in range(board.shape[0]):
31
+ # Vertical lines
32
+ cv2.line(image,
33
+ (margin + i * cell_size, margin),
34
+ (margin + i * cell_size, total_size - margin),
35
+ (0, 0, 0),
36
+ 1)
37
+ # Horizontal lines
38
+ cv2.line(image,
39
+ (margin, margin + i * cell_size),
40
+ (total_size - margin, margin + i * cell_size),
41
+ (0, 0, 0),
42
+ 1)
43
 
44
  # Draw stones
45
  for i in range(board.shape[0]):
46
  for j in range(board.shape[1]):
47
+ if board[i, j] != 0:
48
+ center = (margin + j * cell_size, margin + i * cell_size)
49
+ color = (0, 0, 0) if board[i, j] == 1 else (255, 255, 255)
50
+ # Draw stone with anti-aliasing
51
+ cv2.circle(image, center, 15, color, -1, cv2.LINE_AA)
52
+ # Add a shine effect for 3D appearance
53
+ if board[i, j] == -1: # Only for white stones
54
+ cv2.circle(image,
55
+ (center[0] - 3, center[1] - 3),
56
+ 5,
57
+ (240, 240, 240),
58
+ -1,
59
+ cv2.LINE_AA)
60
 
61
+ # Draw star points (hoshi)
62
+ star_points = []
63
+ if board.shape[0] == 9:
64
+ star_points = [(2, 2), (2, 6), (4, 4), (6, 2), (6, 6)]
65
+
66
+ for point in star_points:
67
+ cv2.circle(image,
68
+ (margin + point[1] * cell_size, margin + point[0] * cell_size),
69
+ 3,
70
+ (0, 0, 0),
71
+ -1,
72
+ cv2.LINE_AA)
73
+
74
+ return image
75
 
76
  class GradioGoGame:
77
  def __init__(self):
 
82
  if x is None or y is None:
83
  return create_board_image(self.game.board), "Invalid move"
84
 
85
+ try:
86
+ x, y = int(x), int(y)
87
+ if x < 0 or x >= self.game.size or y < 0 or y >= self.game.size:
88
+ return create_board_image(self.game.board), "Invalid coordinates"
89
+ except:
90
+ return create_board_image(self.game.board), "Invalid input"
91
+
92
  self.difficulty = Difficulty(difficulty)
93
 
94
  if not self.game.make_move(x, y):
 
112
  gr.Markdown("# Go Game vs AI")
113
 
114
  with gr.Row():
115
+ with gr.Column(scale=2):
116
  board_output = gr.Image(
117
  value=create_board_image(game.game.board),
118
  label="Go Board",
119
+ height=500,
120
+ width=500
121
  )
122
+ msg_output = gr.Textbox(label="Message", value="Enter coordinates and click Make Move")
123
 
124
+ with gr.Column(scale=1):
125
+ x_input = gr.Number(label="X coordinate (0-8)", minimum=0, maximum=8)
126
+ y_input = gr.Number(label="Y coordinate (0-8)", minimum=0, maximum=8)
127
  difficulty = gr.Radio(
128
  choices=[d.value for d in Difficulty],
129
  value=Difficulty.EASY.value,
130
  label="Difficulty"
131
  )
132
+ move_btn = gr.Button("Make Move", variant="primary")
133
+ reset_btn = gr.Button("Reset Game", variant="secondary")
134
 
135
  move_btn.click(
136
  game.make_move,