2020幻影围棋 围棋规则模块(二)

气追踪器的编写

气追踪器类用于更新和记录棋盘上每颗棋子的气,以及群的信息。下面是其追踪器的几个属性:

def __init__(self, groupIndexMap=None, groups=None, librtyCacheMap=None, maxGroupId=1):
        """
        一个"自由度追踪器"类,
        :param groupIndexMap: 一个棋盘(群的索引, 二维数组),上面用不同的数字(ID)标明不同的群 例如
                                1 1 1 1
                                1 2 2 1
                                1 2 1 1
        :param groups: 一个字典, 根据群的ID返回群
        :param librtyCacheMap: 记录每个群的自由度(周围相邻且为EMPTY的点的数量, 二维数组)
        :param maxGroupId: 记录ID最大的群的ID
        """
        self.groupIndexMap = groupIndexMap if groupIndexMap is not None else -np.ones([SIZE, SIZE], dtype=np.int16)
        self.groups = groups or {}
        self.libertyCacheMap = librtyCacheMap if librtyCacheMap is not None else np.zeros([SIZE, SIZE], dtype=np.uint8)
        self.maxGroupId = maxGroupId

气追踪器通过一个工厂方法生成对象,这个工厂方法会从棋盘上的局势来设置groupIndexMap和libertyCacheMap的值。

@staticmethod
    def newTrackerFromBaseBoard(board=gf.Board.getStaticBaseBoard()):
        """
        :param board 默认为基础棋盘。
        从基础棋盘上创建自由度追踪器
        :return: LibertyTracker
        """
        baseBoard = np.copy(board)
        curGroupId = 0
        libTracker = LibertyTracker()
        for color in (WHITE, BLACK):
            while color in baseBoard:
                curGroupId += 1
                foundColor = np.where(baseBoard == color)
                # point的值为第一个点
                point = foundColor[0][0], foundColor[1][0]
                chain, reached = findReached(point=point, baseBoard=baseBoard)
                # 相邻且为EMPTY的点的集合
                liberties = set(r for r in reached if baseBoard[r] == EMPTY)
                newGroup = Group(curGroupId, chain, liberties, color)
                libTracker.groups[curGroupId] = newGroup
                for c in chain:
                    libTracker.groupIndexMap[c] = curGroupId
                #在另一张图上标注这里已经有棋子了
                placeStones(baseBoard, FILL, chain)
        libTracker.maxGroupId = curGroupId

        libertyCounts = np.zeros([SIZE, SIZE], dtype=np.uint8)
        for group in libTracker.groups.values():
            # 一个群的自由度
            libNum = len(group.liberties)
            for s in group.stones:
                libertyCounts[s] = libNum
        libTracker.libertyCacheMap = libertyCounts

        return libTracker

气追踪器的deepcopy函数:

def __deepcopy__(self, memodict={}):
        """
        深层拷贝
        :param memodict:
        :return: LibertyTracker
        """
        newGroupIndexMap = np.copy(self.groupIndexMap)
        newLibertyCacheMap = np.copy(self.libertyCacheMap)
        newGroups = {
            group.id: Group(group.id, set(group.stones), set(group.liberties), group.color)
            for group in self.groups.values()
        }
        return LibertyTracker(newGroupIndexMap, newGroups, newLibertyCacheMap, maxGroupId=self.maxGroupId)

气追踪器还有其它的方法没有在这里介绍,可以用于普通围棋的行棋,这里贴上Gitee地址感兴趣的可以看看:
go_rules.py

Condition类的编写

"""
    对棋面进行分析的类
    baseBoard: 基础棋盘, 这里直接为我们的基础棋盘

    """
    def __init__(self, baseBoard=None, libTracker=None, ourColor=None, opponentColor=None):
        self.baseBoard = baseBoard if baseBoard is not None else gf.Board.getStaticBaseBoard()
        self.libTracker = libTracker if libTracker is not None else LibertyTracker.newTrackerFromBaseBoard(self.baseBoard)
        self.ourColor = ourColor if ourColor is not None else gf.GameStatus.ourColor
        self.opponentColor = opponentColor if opponentColor is not None else gf.GameStatus.opponentColor


    def __deepcopy__(self, memodict={}):
        condition = Condition()
        condition.baseBoard = np.copy(self.baseBoard)
        condition.libTracker = copy.deepcopy(self.libTracker)
        condition.ourColor = copy.copy(self.ourColor)
        condition.opponentColor = copy.copy(self.opponentColor)
        return condition

Condition类只有两个方法,用于判断是否为禁着点:

 def isMoveSuicidal(self, move):
        """
        判断该行棋点是否为禁着点
        :param move: 行棋的位置(元组对象,或者Point对象)
        :return: 如果是禁着点, 返回True, 否则返回False
        """
        if isinstance(move, gf.Point):
            move = move.toTuple()
        potentialLibs = set()
        for p in NEIGHBORS[move]:
            neighborGroupId = self.libTracker.groupIndexMap[p]
            if neighborGroupId == MISSING_GROUP_ID:
                return False
            neighborGroup = self.libTracker.groups[neighborGroupId]
            if neighborGroup.color == self.ourColor:
                potentialLibs |= neighborGroup.liberties
            elif len(neighborGroup.liberties) == 1:
                return False
        potentialLibs -= set([move])
        return not potentialLibs

isMoveSuicidal方法会计算下棋点的潜在气,也就是如果该点下了后能够提子,虽然该点本身气为0,但是可以下。

 def isMoveLegal(self, move):
        """
        判断下棋点是否合法
        :param move: 下棋点(元组对象, 或者point对象)
        :return:如果该下棋点合法,则返回True, 否则返回False
        """
        if isinstance(move, gf.Point):
            move = move.toTuple()
        if move is None:
            return True
        if self.baseBoard[move] != EMPTY:
            return False
        # if move == self.ko:
        #     if self.koTimes >= gf.GameStatus.koTimes:
        #         return False
        #     else:
        #         return True

        if self.isMoveSuicidal(move):
            return False
        return True

isMoveLegal是对isMoveSuicidal的进一步封装。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值