1.前文总结
存在的问题与改进方向
-
性能瓶颈:
- MCTS的每次迭代需要神经网络推理,速度较慢。
- 解决方案:实现批量推理(Batch Inference)。
-
训练不稳定:
- 自我对弈初期策略随机,生成数据质量低。
- 解决方案:先用人类棋谱进行预训练。
-
规则缺失:
- 未实现打劫、眼、禁着点等规则。
- 解决方案:完善
GoBoard
类中的合法性检查。
通过以上简化模拟,可以看到程序的基本流程,但实际开发中需逐步完善细节和优化性能。
2.规则改进
实现围棋中的打劫、眼、禁着点等规则是围棋AI开发中的关键部分。以下是这些规则的详细解释和代码实现。
1. 禁着点(自杀规则)
禁着点是指落子后导致自己的棋子没有气的点。根据围棋规则,禁止在禁着点落子。
实现逻辑
- 检查落子后是否会导致自己的棋子没有气。
- 如果有气,则允许落子;否则禁止。
class GoBoard:
def is_suicide(self, x, y, player):
# 检查落子后是否会导致自己的棋子没有气
self.board[x][y] = player
if self.count_liberties(x, y) == 0:
self.board[x][y] = 0 # 恢复棋盘状态
return True
self.board[x][y] = 0
return False
def count_liberties(self, x, y):
# 计算(x,y)处棋子的气
if self.board[x][y] == 0:
return 0
liberties = 0
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == 0:
liberties += 1
return liberties
2. 眼(真眼与假眼)
眼是指被同一方棋子完全包围的空点。真眼是活棋的关键,假眼则可能被对方破坏。
实现逻辑
- 检查某个空点是否被同一方棋子完全包围。
- 如果是,则认为是眼。
class GoBoard:
def is_eye(self, x, y, player):
# 检查(x,y)是否是player的眼
if self.board[x][y] != 0:
return False
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] != player:
return False
return True
3. 打劫(劫争规则)
打劫是指双方反复争夺同一个点的规则。为了防止无限循环,围棋规定不能立即回提同一个点。
实现逻辑
- 记录上一步的落子位置。
- 检查当前落子是否是回提上一步的落子。
- 如果是,则禁止落子。
class GoBoard:
def __init__(self, size=19):
self.size = size
self.board = [[0] * size for _ in range(size)]
self.last_move = None # 记录上一步的落子
self.ko = None # 劫争点
def place_stone(self, x, y, player):
if self.is_suicide(x, y, player):
return False # 禁着点
if (x, y) == self.ko:
return False # 打劫禁止
self.board[x][y] = player
self.last_move = (x, y)
self.ko = None
self.remove_dead_stones(x, y, player)
return True
def remove_dead_stones(self, x, y, player):
# 移除被提掉的棋子
opponent = 3 - player
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == opponent and self.count_liberties(nx, ny) == 0:
self.capture_group(nx, ny)
if self.count_liberties(x, y) == 1:
self.ko = (nx, ny) # 设置劫争点
def capture_group(self, x, y):
# 捕获一组棋子
if self.board[x][y] == 0:
return
player = self.board[x][y]
stack = [(x, y)]
while stack:
cx, cy = stack.pop()
self.board[cx][cy] = 0
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = cx + dx, cy + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == player:
stack.append((nx, ny))
4. 整合规则
将以上规则整合到GoBoard
类中,确保每次落子都符合围棋规则。
class GoBoard:
def __init__(self, size=19):
self.size = size
self.board = [[0] * size for _ in range(size)]
self.last_move = None
self.ko = None
def place_stone(self, x, y, player):
if self.board[x][y] != 0:
return False # 已有棋子
if self.is_suicide(x, y, player):
return False # 禁着点
if (x, y) == self.ko:
return False # 打劫禁止
self.board[x][y] = player
self.last_move = (x, y)
self.ko = None
self.remove_dead_stones(x, y, player)
return True
def is_suicide(self, x, y, player):
self.board[x][y] = player
if self.count_liberties(x, y) == 0:
self.board[x][y] = 0
return True
self.board[x][y] = 0
return False
def count_liberties(self, x, y):
if self.board[x][y] == 0:
return 0
liberties = 0
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == 0:
liberties += 1
return liberties
def remove_dead_stones(self, x, y, player):
opponent = 3 - player
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = x + dx, y + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == opponent and self.count_liberties(nx, ny) == 0:
self.capture_group(nx, ny)
if self.count_liberties(x, y) == 1:
self.ko = (nx, ny)
def capture_group(self, x, y):
if self.board[x][y] == 0:
return
player = self.board[x][y]
stack = [(x, y)]
while stack:
cx, cy = stack.pop()
self.board[cx][cy] = 0
for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nx, ny = cx + dx, cy + dy
if 0 <= nx < self.size and 0 <= ny < self.size:
if self.board[nx][ny] == player:
stack.append((nx, ny))
3.总结
通过以上代码,我们实现了围棋中的禁着点、眼、打劫等规则。这些规则是围棋AI的基础,确保AI能够合法、合理地落子。接下来,可以将这些规则整合到MCTS和神经网络中,进一步提升AI的棋力。