コード例 #1
0
    def test_effect(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
            white_effect = BlackNaiveShortEffectLayer(
                direction=direction, data_format=self.data_format,
                use_cudnn=self.use_cudnn
            )(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.BLACK_OU
                        else:
                            board[0, i, j, 0] = Piece.BLACK_OU

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction not in get_eight_directions():
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        if direction == Direction.RIGHT_UP:
                            u, v = i - 1, j - 1
                        elif direction == Direction.RIGHT:
                            u, v = i - 1, j
                        elif direction == Direction.RIGHT_DOWN:
                            u, v = i - 1, j + 1
                        elif direction == Direction.UP:
                            u, v = i, j - 1
                        elif direction == Direction.DOWN:
                            u, v = i, j + 1
                        elif direction == Direction.LEFT_UP:
                            u, v = i + 1, j - 1
                        elif direction == Direction.LEFT:
                            u, v = i + 1, j
                        elif direction == Direction.LEFT_DOWN:
                            u, v = i + 1, j + 1
                        else:
                            # ここには到達しないはず
                            raise ValueError()
                        if u not in range(9) or v not in range(9):
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                            continue

                        self.assertTrue(effect[u, v])
                        # 利きがあるのは1か所だけのはず
                        effect[u, v] = False
                        self.assertFalse(np.any(effect))
コード例 #2
0
    def test_ou_effect_with_long_check(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        # 利きはない状態に設定
        white_effect_mask = np.zeros_like(board, dtype=np.bool)

        white_long_check = {direction: tf.placeholder(tf.bool, shape=[])
                            for direction in get_eight_directions()}

        ph = tf.placeholder(tf.int32, shape=shape)
        ou_effect = BlackOuEffectLayer(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(ph, white_effect_mask, white_long_check)
        # 余計な方向がないことを確認する
        self.assertEqual(8, len(ou_effect))
        # 利用しやすいように次元を下げる
        ou_effect = {key: tf.squeeze(value)
                     for key, value in ou_effect.items()}

        feed_dict = {value: False for value in white_long_check.values()}
        feed_dict[ph] = board

        with self.test_session() as sess:
            for check_direction in get_eight_directions():
                feed_dict[white_long_check[check_direction]] = True
                # check_directionの方向に駒があるので、逃げるときに問題になるのは反対方向
                opposite_direction = get_opposite_direction(
                    direction=check_direction
                )

                for i, j in product(range(9), repeat=2):
                    # (i, j)に駒を置く

                    board[:] = Piece.EMPTY
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.BLACK_OU
                    else:
                        board[0, i, j, 0] = Piece.BLACK_OU

                    effect = sess.run(ou_effect, feed_dict=feed_dict)
                    for key, value in effect.items():
                        x, y = self.get_square(i=i, j=j, direction=key)

                        with self.subTest(i=i, j=j, direction=key,
                                          check_direction=check_direction):
                            if (x in range(9) and y in range(9) and
                                    key != opposite_direction):
                                self.assertTrue(value[x, y])
                                value[x, y] = False
                                self.assertFalse(np.all(value))
                            else:
                                self.assertFalse(np.all(value))

                feed_dict[white_long_check[check_direction]] = False
コード例 #3
0
    def test_long_check(self):
        """
        長い利きで王手されている場合に王以外の駒が動ける場所の判定のテスト
        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        pseudo_effect = BlackPseudoOuEffect(data_format=self.data_format,
                                            use_cudnn=self.use_cudnn)(ph)
        all_check, long_check = WhiteAllCheckLayer()(ph, pseudo_effect)
        available_square = CheckAvailableSquareLayer()(pseudo_effect,
                                                       all_check)
        available_square = tf.squeeze(available_square)

        long_piece_list = [
            Piece.WHITE_KY, Piece.WHITE_KA, Piece.WHITE_HI, Piece.WHITE_UM,
            Piece.WHITE_RY
        ]

        with self.test_session() as sess:
            for tmp in product(get_eight_directions(), range(9), range(9),
                               range(1, 9), long_piece_list):
                direction, i, j, k, piece = tmp

                # 短い利きは含めない
                if (piece == Piece.WHITE_UM
                        and direction in get_cross_directions()):
                    continue
                elif (piece == Piece.WHITE_RY
                      and direction == get_diagonal_directions()):
                    continue

                x, y = self._get_position(direction=direction, i=i, j=j, k=k)
                if x not in range(9) or y not in range(9):
                    continue

                board[:] = Piece.EMPTY
                if self.data_format == 'NCHW':
                    board[0, 0, i, j] = Piece.BLACK_OU
                    board[0, 0, x, y] = piece
                else:
                    board[0, i, j, 0] = Piece.BLACK_OU
                    board[0, x, y, 0] = piece

                with self.subTest(direction=direction, i=i, j=j, piece=piece):
                    square, check = sess.run(
                        [available_square, long_check[direction]],
                        feed_dict={ph: board})

                    self.assertTupleEqual(square.shape, (9, 9))

                    if check:
                        for u, v in zip(*self._get_range(i=i, j=j, x=x, y=y)):
                            self.assertTrue(square[u, v])
                            square[u, v] = False
                        self.assertFalse(np.any(square))
                    else:
                        self.assertTrue(np.all(square))
コード例 #4
0
    def test_check(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        pseudo_effect = BlackPseudoOuEffect(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(ph)
        long_check = WhiteLongCheckLayer()(ph, pseudo_effect)

        # 利きの長い駒のみに限定する
        # UM,RYの長い利きのみで、短い利きは対象に含めない
        white_pieces = [Piece.WHITE_KY, Piece.WHITE_KA, Piece.WHITE_HI,
                        Piece.WHITE_UM, Piece.WHITE_RY]

        for direction in get_eight_directions():
            with self.test_session() as sess:
                for i, j, k, piece in product(range(9), range(9), range(1, 9),
                                              white_pieces):
                    x, y = self._get_position(
                        direction=direction, i=i, j=j, k=k
                    )
                    if x not in range(9) or y not in range(9):
                        continue

                    # OUから見てdirectionの方向に相手の駒を配置
                    board[:] = Piece.EMPTY
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.BLACK_OU
                        board[0, 0, x, y] = piece
                    else:
                        board[0, i, j, 0] = Piece.BLACK_OU
                        board[0, x, y, 0] = piece

                    with self.subTest(direction=direction, i=i, j=j, k=k,
                                      piece=piece):
                        check = sess.run(long_check, feed_dict={ph: board})

                        for key, value in check.items():
                            # ブロードキャストが正しく行われるために4次元が必要
                            self.assertTupleEqual((1, 1, 1, 1), value.shape)

                            if key == direction:
                                d = get_opposite_direction(direction=direction)
                                if piece == Piece.WHITE_KY:
                                    self.assertEqual(value,
                                                     d == Direction.DOWN)
                                elif piece in (Piece.WHITE_KA, Piece.WHITE_UM):
                                    self.assertEqual(
                                        value, d in get_diagonal_directions()
                                    )
                                elif piece in (Piece.WHITE_HI, Piece.WHITE_RY):
                                    self.assertEqual(
                                        value, d in get_cross_directions()
                                    )
                                else:
                                    # ここには到達しないはず
                                    raise ValueError()
                            else:
                                self.assertFalse(value)
コード例 #5
0
    def test_check(self):
        """
        短い利きでの王手があるかの判定のテスト

        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        pseudo_effect = BlackPseudoOuEffect(data_format=self.data_format,
                                            use_cudnn=self.use_cudnn)(ph)
        short_check = WhiteShortCheckLayer()(ph, pseudo_effect)

        # 利きの短い駒のみに限定する
        # UM,RYの短い利きのみで、長い利きは対象に含めない
        white_pieces = [
            Piece.WHITE_FU, Piece.WHITE_KE, Piece.WHITE_GI, Piece.WHITE_KI,
            Piece.WHITE_TO, Piece.WHITE_NY, Piece.WHITE_NK, Piece.WHITE_NG,
            Piece.WHITE_UM, Piece.WHITE_RY
        ]
        direction_table = make_base_table()

        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
            with self.test_session() as sess:
                for i, j, piece in product(range(9), range(9), white_pieces):
                    x, y = self._get_position(direction=direction, i=i, j=j)
                    if x not in range(9) or y not in range(9):
                        continue

                    # OUから見てdirectionの方向に相手の駒を配置
                    board[:] = Piece.EMPTY
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.BLACK_OU
                        board[0, 0, x, y] = piece
                    else:
                        board[0, i, j, 0] = Piece.BLACK_OU
                        board[0, x, y, 0] = piece

                    with self.subTest(direction=direction,
                                      i=i,
                                      j=j,
                                      piece=piece):
                        check = sess.run(short_check, feed_dict={ph: board})

                        for key, value in check.items():
                            # ブロードキャストが正しく行われるために4次元が必要
                            self.assertTupleEqual((1, 1, 1, 1), value.shape)

                            if key == direction:
                                d = get_opposite_direction(direction=direction)
                                index = piece - Piece.WHITE_FU
                                flag = direction_table[d][index]
                                self.assertEqual(value, bool(flag))
                            else:
                                self.assertFalse(value)
            pass
コード例 #6
0
    def test_effect1(self):
        """
        KYの利きがあるかを確認するテスト
        他の駒が利きを遮る場合は考えない

        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_DOWN_DOWN,
                                Direction.LEFT_DOWN_DOWN]):
            if direction in (Direction.RIGHT_DOWN_DOWN,
                             Direction.LEFT_DOWN_DOWN):
                # 桂馬の方向の長い利きはあり得ないのでエラー
                with self.assertRaises(ValueError):
                    WhiteNaiveLongEffectLayer(
                        direction=direction, data_format=self.data_format,
                        use_cudnn=self.use_cudnn
                    )(ph)
                continue

            white_effect = WhiteNaiveLongEffectLayer(
                direction=direction, data_format=self.data_format,
                use_cudnn=self.use_cudnn
            )(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                # 9段目にはKYを置けないけど、気にしない
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.WHITE_KY
                        else:
                            board[0, i, j, 0] = Piece.WHITE_KY

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction != Direction.DOWN:
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        if j == 8:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                        else:
                            self.assertTrue(np.all(effect[i, j + 1:]))
                            # 利きがあるはずの場所の利きを消す
                            effect[i, j + 1:] = False
                            self.assertFalse(np.any(effect))
コード例 #7
0
    def test_ki_move(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        effect = {
            direction: np.empty(shape, dtype=np.bool)
            for direction in get_eight_directions()
        }

        board = np.empty(shape, dtype=np.int32)

        ph_board = tf.placeholder(tf.int32, shape=shape)
        ki_effect = {
            direction: tf.placeholder(tf.bool, shape=shape)
            for direction in effect.keys()
        }
        non_promoting = BlackOuMoveLayer()(ph_board, ki_effect)
        # アクセスしやすいように次元を下げる
        non_promoting = {
            key: tf.squeeze(value)
            for key, value in non_promoting.items()
        }

        feed_dict = {
            placeholder: effect[direction]
            for direction, placeholder in ki_effect.items()
        }
        feed_dict[ph_board] = board

        with self.test_session() as sess:
            for i, j, piece in product(range(9), range(9), range(Piece.SIZE)):
                for e in effect.values():
                    e[:] = False
                    if self.data_format == 'NCHW':
                        e[0, 0, i, j] = True
                    else:
                        e[0, i, j, 0] = True

                piece = Piece(piece)
                board[:] = piece

                n = sess.run(non_promoting, feed_dict=feed_dict)

                b = np.squeeze(board)

                for direction, move in n.items():
                    with self.subTest(i=i, j=j, direction=direction):
                        self.assertTupleEqual((9, 9), move.shape)

                        if b[i, j] < Piece.WHITE_FU:
                            # 自身の駒があって動けない
                            self.assertFalse(np.all(move))
                        else:
                            self.assertTrue(move[i, j])
                            move[i, j] = False
                            self.assertFalse(np.all(move))
コード例 #8
0
    def test_ry_pin(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        # ここでは相手の利きがない設定
        black_effect_mask = np.zeros(shape, dtype=np.bool)

        ph = tf.placeholder(tf.int32, shape=shape)
        short_effect = WhiteShortEffectLayer(data_format=self.data_format,
                                             use_cudnn=self.use_cudnn)(ph)
        long_effect = WhiteLongEffectLayer(data_format=self.data_format,
                                           use_cudnn=self.use_cudnn)(ph)
        ou_effect = WhiteOuEffectLayer(data_format=self.data_format,
                                       use_cudnn=self.use_cudnn)(
                                           ph, black_effect_mask)
        effect_count = WhiteEffectCountLayer()(short_effect, long_effect,
                                               ou_effect)
        effect_count = tf.squeeze(effect_count)

        with self.test_session() as sess:
            for i, j in product(range(9), repeat=2):
                # (i, j)に駒を置く

                board[:] = Piece.EMPTY
                for pin_direction in PinDirection:
                    if pin_direction == PinDirection.SIZE:
                        continue

                    offset = Piece.SIZE - Piece.WHITE_FU + pin_direction * 14
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.WHITE_RY + offset
                    else:
                        board[0, i, j, 0] = Piece.WHITE_RY + offset

                    count = sess.run(effect_count, feed_dict={ph: board})
                    with self.subTest(i=i, j=j, pin_direction=pin_direction):
                        c = 0
                        for direction in get_eight_directions():
                            if pin_direction != PinDirection[direction.name]:
                                continue

                            s, t = self._get_range(i=i,
                                                   j=j,
                                                   direction=direction)
                            for x, y in zip(s, t):
                                if x in range(9) and y in range(9):
                                    self.assertEqual(count[x, y],
                                                     1,
                                                     msg=(x, y))
                                    c += 1
                        self.assertEqual(np.sum(count), c)
コード例 #9
0
    def test_effect(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(
                get_eight_directions(),
            [Direction.RIGHT_DOWN_DOWN, Direction.LEFT_DOWN_DOWN]):
            white_effect = WhiteNaiveShortEffectLayer(
                direction=direction,
                data_format=self.data_format,
                use_cudnn=self.use_cudnn)(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                # 8,9段目にはKEを置けないけど、気にしない
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.WHITE_KE
                        else:
                            board[0, i, j, 0] = Piece.WHITE_KE

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction not in (Direction.RIGHT_DOWN_DOWN,
                                             Direction.LEFT_DOWN_DOWN):
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        if direction == Direction.RIGHT_DOWN_DOWN:
                            k = i - 1
                        elif direction == Direction.LEFT_DOWN_DOWN:
                            k = i + 1
                        else:
                            # ここには到達しないはず
                            raise ValueError()
                        if k < 0 or k >= 9 or j >= 7:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                            continue

                        self.assertTrue(effect[k, j + 2])
                        # 利きがあるのは1か所だけのはず
                        effect[k, j + 2] = False
                        self.assertFalse(np.any(effect))
コード例 #10
0
    def test_ou_effect_without_long_check(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        # 適当なマスクを設定
        white_effect_mask = np.zeros(81, dtype=np.bool)
        white_effect_mask[::2] = True
        white_effect_mask = np.reshape(white_effect_mask, shape)

        white_long_check = {direction: False
                            for direction in get_eight_directions()}

        ph = tf.placeholder(tf.int32, shape=shape)
        ou_effect = BlackOuEffectLayer(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(ph, white_effect_mask, white_long_check)
        # 余計な方向がないことを確認する
        self.assertEqual(8, len(ou_effect))
        # 利用しやすいように次元を下げる
        ou_effect = {key: tf.squeeze(value)
                     for key, value in ou_effect.items()}

        # Layerに渡したので、変更しても大丈夫
        # アクセスしやすいように次元を下げる
        white_effect_mask = np.squeeze(white_effect_mask)

        with self.test_session() as sess:
            for i, j in product(range(9), repeat=2):
                # (i, j)に駒を置く

                board[:] = Piece.EMPTY
                if self.data_format == 'NCHW':
                    board[0, 0, i, j] = Piece.BLACK_OU
                else:
                    board[0, i, j, 0] = Piece.BLACK_OU

                effect = sess.run(ou_effect, feed_dict={ph: board})
                for key, value in effect.items():
                    x, y = self.get_square(i=i, j=j, direction=key)

                    with self.subTest(i=i, j=j, direction=key):
                        if (x in range(9) and y in range(9) and
                                not white_effect_mask[x, y]):
                            self.assertTrue(value[x, y])
                            value[x, y] = False
                            self.assertFalse(np.all(value))
                        else:
                            self.assertFalse(np.all(value))
コード例 #11
0
    def test_effect(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
            white_effect = BlackNaiveShortEffectLayer(
                direction=direction,
                data_format=self.data_format,
                use_cudnn=self.use_cudnn)(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                # 9段目にはFUを置けないけど、気にしない
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.BLACK_FU
                        else:
                            board[0, i, j, 0] = Piece.BLACK_FU

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction != Direction.UP:
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        if j == 0:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                        else:
                            self.assertTrue(effect[i, j - 1])
                            # 利きがあるのは1か所だけのはず
                            effect[i, j - 1] = False
                            self.assertFalse(np.any(effect))
コード例 #12
0
def get_effects(direction, pieces, effects):
    """
    駒の種類ごとに計算した利きを方向ごとにまとめる

    :param direction:
    :param pieces:
    :param effects:
    :return:
    """
    short_effects = []
    long_effects = []
    for piece in pieces:
        effect = effects[piece][direction]
        if isinstance(effect, list):
            long_effects.append(effect)
        else:
            short_effects.append(effect)

    if direction not in get_eight_directions():
        # 桂馬の動き
        # dictを作りやすくするために方向と一緒に返す
        return direction, combine_or(*short_effects)

    long_merged = [
        tf.logical_or(v1, v2)
        for v1, v2 in zip(long_effects[0], long_effects[1])
    ]
    if len(long_effects):
        long_merged = [
            tf.logical_or(v1, v2)
            for v1, v2 in zip(long_effects[2], long_merged)
        ]

    short_effects.append(long_merged[0])
    short_merged = combine_or(*short_effects)
    long_merged[0] = short_merged

    # dictを作りやすくするために方向と一緒に返す
    return direction, long_merged
コード例 #13
0
    def test_effect_case3(self):
        # 非手番側のナイーブな利きを求める
        black_all_effect, black_long_effect = BlackNaiveAllEffect(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(self.board)

        pseudo_effect = WhitePseudoOuEffect(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(self.board)

        # ピンされているかを判定
        pinned_board = WhitePinLayer(
            data_format=self.data_format
        )(self.board, pseudo_effect, black_long_effect)

        # 長い利きを計算
        white_long_effect = WhiteLongEffectLayer(
            data_format=self.data_format, use_cudnn=self.use_cudnn
        )(pinned_board)
        white_long_effect = [tf.squeeze(value) for value in white_long_effect]

        with self.test_session() as sess:
            pin = sess.run(tf.squeeze(pinned_board))
            self.assertEqual(pin[5, 3],
                             Piece.WHITE_KA + 15 + PinDirection.DIAGONAL1)
            effect = sess.run(white_long_effect)

        for direction in get_eight_directions():
            with self.subTest(direction=direction):
                if direction in (Direction.RIGHT_DOWN, Direction.LEFT_UP):
                    self.assertEqual(PinDirection.DIAGONAL2,
                                     PinDirection[direction.name])
                    # pin
                    self.assertTrue(np.all(effect[direction] == 0))
                else:
                    # 縦と横はHIが2枚あるので、それらで必ずある
                    self.assertTrue(np.any(effect[direction]))
コード例 #14
0
    def test_short_check(self):
        """
        短い利きで王手されている場合に王以外の駒が動ける場所の判定をテスト
        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        pseudo_effect = BlackPseudoOuEffect(data_format=self.data_format,
                                            use_cudnn=self.use_cudnn)(ph)
        all_check, _ = WhiteAllCheckLayer()(ph, pseudo_effect)
        available_square = CheckAvailableSquareLayer()(pseudo_effect,
                                                       all_check)
        available_square = tf.squeeze(available_square)
        short_check = WhiteShortCheckLayer()(ph, pseudo_effect)

        with self.test_session() as sess:
            for direction in chain(
                    get_eight_directions(),
                [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
                for i, j, piece in product(range(9), range(9),
                                           range(Piece.WHITE_FU, Piece.EMPTY)):
                    piece = Piece(piece)

                    if piece == Piece.WHITE_OU:
                        # OUで王手はない
                        continue
                    # 長い利きはここではテストしない
                    if piece == Piece.WHITE_KY and direction == Direction.UP:
                        continue
                    elif (piece in (Piece.WHITE_KA, Piece.WHITE_UM)
                          and direction in get_diagonal_directions()):
                        continue
                    elif (direction in get_cross_directions()
                          and piece in (Piece.WHITE_HI, Piece.WHITE_RY)):
                        continue

                    x, y = self._get_position(direction=direction, i=i, j=j)
                    if x not in range(9) or y not in range(9):
                        continue

                    board[:] = Piece.EMPTY
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.BLACK_OU
                        board[0, 0, x, y] = piece
                    else:
                        board[0, i, j, 0] = Piece.BLACK_OU
                        board[0, x, y, 0] = piece

                    with self.subTest(direction=direction,
                                      i=i,
                                      j=j,
                                      piece=piece):
                        square, check = sess.run(
                            [available_square, short_check[direction]],
                            feed_dict={ph: board})

                        self.assertTupleEqual(square.shape, (9, 9))

                        if check:
                            self.assertTrue(square[x, y])
                            square[x, y] = False
                            self.assertFalse(np.any(square))
                        else:
                            self.assertTrue(np.all(square))
コード例 #15
0
    def test_effect2(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_DOWN_DOWN,
                                Direction.LEFT_DOWN_DOWN]):
            if direction in (Direction.RIGHT_DOWN_DOWN,
                             Direction.LEFT_DOWN_DOWN):
                # 桂馬の方向の長い利きはあり得ないのでエラー
                with self.assertRaises(ValueError):
                    WhiteNaiveLongEffectLayer(
                        direction=direction, data_format=self.data_format,
                        use_cudnn=self.use_cudnn
                    )(ph)
                continue

            white_effect = WhiteNaiveLongEffectLayer(
                direction=direction, data_format=self.data_format,
                use_cudnn=self.use_cudnn
            )(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            # 利きを遮る駒の候補を作成
            # 各方向についてテストするので、利きの長い駒以外が候補
            block_piece_list = [
                p for p in Piece if p not in (Piece.WHITE_KY, Piece.WHITE_KA,
                                              Piece.WHITE_HI, Piece.WHITE_UM,
                                              Piece.WHITE_RY, Piece.EMPTY,
                                              Piece.SIZE)
            ]

            with self.test_session() as sess:
                # 9段目にはKYを置けないけど、気にしない
                for i, j, k in product(range(9), repeat=3):
                    # KYを(i, j)に、遮る駒を(i, k)に置く
                    if j == k:
                        continue

                    with self.subTest(direction=direction, i=i, j=j, k=k):
                        board[:] = Piece.EMPTY
                        block_piece = np.random.choice(block_piece_list)
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.WHITE_KY
                            board[0, 0, i, k] = block_piece
                        else:
                            board[0, i, j, 0] = Piece.WHITE_KY
                            board[0, i, k, 0] = block_piece

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction != Direction.DOWN:
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect), msg=block_piece)
                            continue

                        if j == 8:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                        else:
                            if j < k:
                                # 駒が利きを遮っている
                                self.assertTrue(np.all(effect[i, j + 1:k + 1]))
                                # 利きがあるはずの場所の利きを消す
                                effect[i, j + 1:k + 1] = False
                            else:
                                # KYの後ろにあるので、遮っていない
                                self.assertTrue(np.all(effect[i, j + 1:]))
                                # 利きがあるはずの場所の利きを消す
                                effect[i, j + 1:] = False
                            self.assertFalse(np.any(effect), msg=effect)
コード例 #16
0
    def test_effect1(self):
        """
        KAの利きがあるかを確認するテスト
        他の駒が利きを遮る場合は考えない

        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
            if direction in (Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP):
                # 桂馬の方向の長い利きはあり得ないのでエラー
                with self.assertRaises(ValueError):
                    BlackNaiveLongEffectLayer(
                        direction=direction, data_format=self.data_format,
                        use_cudnn=self.use_cudnn
                    )(ph)
                continue

            white_effect = BlackNaiveLongEffectLayer(
                direction=direction, data_format=self.data_format,
                use_cudnn=self.use_cudnn
            )(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.BLACK_KA
                        else:
                            board[0, i, j, 0] = Piece.BLACK_KA

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction not in get_diagonal_directions():
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        right, up = self.get_direction_flag(
                            direction=direction
                        )
                        edge1, op1 = self.get_edge_flag(n=i, flag=right)
                        edge2, op2 = self.get_edge_flag(n=j, flag=up)

                        if edge1 or edge2:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                            continue

                        margin = min(i if right else 8 - i,
                                     j if up else 8 - j)
                        for n in range(1, margin + 1):
                            u, v = op1(i, n), op2(j, n)
                            self.assertTrue(effect[u, v])
                            effect[u, v] = False
                        self.assertFalse(np.any(effect))
コード例 #17
0
    def test_effect1(self):
        """
        HIの利きがあるかを確認するテスト
        他の駒が利きを遮る場合は考えない

        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in chain(get_eight_directions(),
                               [Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP]):
            if direction in (Direction.RIGHT_UP_UP, Direction.LEFT_UP_UP):
                # 桂馬の方向の長い利きはあり得ないのでエラー
                with self.assertRaises(ValueError):
                    BlackNaiveLongEffectLayer(direction=direction,
                                              data_format=self.data_format,
                                              use_cudnn=self.use_cudnn)(ph)
                continue

            white_effect = BlackNaiveLongEffectLayer(
                direction=direction,
                data_format=self.data_format,
                use_cudnn=self.use_cudnn)(ph)
            # チャネルの処理が面倒なので、次元を下げる
            white_effect = tf.squeeze(white_effect)

            with self.test_session() as sess:
                for i, j in product(range(9), repeat=2):
                    with self.subTest(direction=direction, i=i, j=j):
                        board[:] = Piece.EMPTY
                        if self.data_format == 'NCHW':
                            board[0, 0, i, j] = Piece.BLACK_HI
                        else:
                            board[0, i, j, 0] = Piece.BLACK_HI

                        effect = sess.run(white_effect, feed_dict={ph: board})

                        self.assertTupleEqual(effect.shape, (9, 9))

                        if direction not in get_cross_directions():
                            # 利きがあるマスはない
                            self.assertFalse(np.any(effect))
                            continue

                        if direction == Direction.RIGHT:
                            edge = i == 0
                        elif direction == Direction.LEFT:
                            edge = i == 8
                        elif direction == Direction.UP:
                            edge = j == 0
                        elif direction == Direction.DOWN:
                            edge = j == 8
                        else:
                            raise ValueError(direction)

                        if edge:
                            # 盤の端に駒があるので、盤の中に利きはない
                            self.assertFalse(np.any(effect))
                            continue

                        if direction == Direction.RIGHT:
                            self.assertTrue(np.all(effect[:i, j]))
                            effect[:i, j] = False
                        elif direction == Direction.LEFT:
                            self.assertTrue(np.all(effect[i + 1:, j]))
                            effect[i + 1:, j] = False
                        elif direction == Direction.UP:
                            self.assertTrue(np.all(effect[i, :j]))
                            effect[i, :j] = False
                        elif direction == Direction.DOWN:
                            self.assertTrue(np.all(effect[i, j + 1:]))
                            effect[i, j + 1:] = False
                        else:
                            raise ValueError(direction)
                        self.assertFalse(np.any(effect))
コード例 #18
0
    def test_pin1(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        ph = tf.placeholder(tf.int32, shape=shape)
        pseudo_effect = BlackPseudoOuEffect(data_format=self.data_format,
                                            use_cudnn=self.use_cudnn)(ph)
        long_effect = {
            direction: WhiteNaiveLongEffectLayer(direction=direction,
                                                 data_format=self.data_format,
                                                 use_cudnn=self.use_cudnn)(ph)
            for direction in get_eight_directions()
        }
        pinned_board = BlackPinLayer(data_format=self.data_format)(
            ph, pseudo_effect, long_effect)
        offset = tf.squeeze(pinned_board - ph)

        long_piece_list = (Piece.WHITE_KY, Piece.WHITE_KA, Piece.WHITE_HI,
                           Piece.WHITE_UM, Piece.WHITE_RY)
        pinned_piece_list = [
            Piece(p) for p in range(Piece.BLACK_FU, Piece.WHITE_FU)
            if p != Piece.BLACK_OU
        ]

        with self.test_session() as sess:
            for tmp in product(get_eight_directions(), range(9), range(9),
                               range(1, 8)):
                direction, i, j, k = tmp

                offset_value = Piece.SIZE + PinDirection[direction.name] * 14

                # ピンされる駒の移動
                x, y = self._get_position(direction=direction, i=i, j=j, k=k)
                if x not in range(9) or y not in range(9):
                    continue

                for l in range(k + 1, 9):
                    # 利きの長い駒の位置
                    u, v = self._get_position(direction=direction,
                                              i=i,
                                              j=j,
                                              k=l)
                    if u not in range(9) or v not in range(9):
                        continue

                    board[:] = Piece.EMPTY
                    if self.data_format == 'NCHW':
                        board[0, 0, i, j] = Piece.BLACK_OU
                    else:
                        board[0, i, j, 0] = Piece.BLACK_OU

                    for long_piece in long_piece_list:
                        pinned_piece = np.random.choice(pinned_piece_list)
                        if self.data_format == 'NCHW':
                            board[0, 0, x, y] = pinned_piece
                            board[0, 0, u, v] = long_piece
                        else:
                            board[0, x, y, 0] = pinned_piece
                            board[0, u, v, 0] = long_piece

                        if long_piece == Piece.WHITE_KY:
                            pin = direction == Direction.UP
                        elif long_piece in (Piece.WHITE_KA, Piece.WHITE_UM):
                            pin = direction in get_diagonal_directions()
                        elif long_piece in (Piece.WHITE_HI, Piece.WHITE_RY):
                            pin = direction in get_cross_directions()
                        else:
                            # ここには到達しないはず
                            raise ValueError(direction)

                        with self.subTest(direction=direction,
                                          i=i,
                                          j=j,
                                          k=k,
                                          l=l,
                                          pinned_piece=pinned_piece,
                                          long_piece=long_piece):
                            o = sess.run(offset, feed_dict={ph: board})

                            if pin:
                                self.assertEqual(o[x, y], offset_value)
                                # 他がすべて0であることを確認
                                o[x, y] = 0
                                self.assertTrue(np.all(o == 0))
                            else:
                                self.assertTrue(np.all(o == 0))