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)
示例#2
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))
示例#3
0
    def test_um_pin(self):
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        board = np.empty(shape, dtype=np.int32)

        # ここではすべて有効に設定
        available_board = np.ones(shape, dtype=np.bool)

        ph = tf.placeholder(tf.int32, shape=shape)
        um_effect = BlackUmEffectLayer(data_format=self.data_format,
                                       use_cudnn=self.use_cudnn)(
                                           ph, available_board)
        # 余計な方向がないことを確認する
        self.assertEqual(8, len(um_effect))
        # 利用しやすいように次元を下げる
        um_effect = {
            direction: tf.squeeze(effect)
            for direction, effect in um_effect.items()
        }
        # 効きが長い方向のみ8種類の距離を一つにまとめる
        diagonal_directions = get_diagonal_directions()
        um_effect = {
            direction: tf.reduce_any(um_effect[direction], axis=0)
            if direction in diagonal_directions else effect
            for direction, effect in um_effect.items()
        }

        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

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

                    effect = sess.run(um_effect, feed_dict={ph: board})
                    for direction, e in effect.items():
                        with self.subTest(i=i, j=j, direction=direction):
                            s, t = self._get_range(i=i,
                                                   j=j,
                                                   direction=direction)

                            for x, y in zip(s, t):
                                if x not in range(9) or y not in range(9):
                                    # 盤の外に到達した
                                    break

                                if (pin_direction == PinDirection[
                                        direction.name]):
                                    self.assertTrue(e[x, y])
                                    # 利きをリセット
                                    e[x, y] = False
                            # 最後にまとめて一つも利きがないことを確認する
                            self.assertFalse(np.all(e))
示例#4
0
    def test_effect1_short(self):
        """
        RYの短い利きをテスト

        :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]):
            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:
                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_RY
                        else:
                            board[0, i, j, 0] = Piece.WHITE_RY

                        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

                        if direction == Direction.RIGHT_UP:
                            u, v = i - 1, j - 1
                        elif direction == Direction.RIGHT_DOWN:
                            u, v = i - 1, j + 1
                        elif direction == Direction.LEFT_UP:
                            u, v = i + 1, j - 1
                        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))
示例#5
0
    def test_ka_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_KA + offset
                    else:
                        board[0, i, j, 0] = Piece.WHITE_KA + 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_diagonal_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):
                                self.assertEqual(count[x, y], 1)
                                c += 1
                        self.assertEqual(np.sum(count), c)
示例#6
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))
示例#7
0
    def test_effect2(self):
        """
        KAの利きのある4方向にそれぞれ駒をおいて利きを遮った場合のテスト

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

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

        ph = tf.placeholder(tf.int32, shape=shape)
        for direction in get_diagonal_directions():
            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, k, l in product(range(9), range(9), range(9),
                                          [-1, 1]):
                    # KAを(i, j)に、遮る駒を(x, k)に置く
                    if j == k:
                        continue

                    # 利きを遮る駒を置く位置を計算
                    x = i + (k - j) * l
                    if x < 0 or x >= 9:
                        continue

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

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

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

                        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

                        if k - j < 0:
                            if l > 0:
                                block = direction == Direction.RIGHT_UP
                            else:
                                block = direction == Direction.LEFT_UP
                        else:
                            if l > 0:
                                block = direction == Direction.LEFT_DOWN
                            else:
                                block = direction == Direction.RIGHT_DOWN

                        if block:
                            # (i, j)から(x, k)までの距離を計算
                            margin = min(i - x if right else x - i,
                                         j - k if up else k - j)
                        else:
                            # 盤の端まで利きが伸びている
                            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))
示例#8
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))
示例#9
0
    def test_gi_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 chain(get_diagonal_directions(), [Direction.UP])
        }

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

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

        feed_dict = {
            placeholder: effect[direction]
            for direction, placeholder in gi_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, p = sess.run([non_promoting, promoting],
                                feed_dict=feed_dict)

                b = np.squeeze(board)

                for direction in effect.keys():
                    n_move = n[direction]
                    p_move = p[direction]

                    if j == 0 and direction in (Direction.RIGHT_DOWN,
                                                Direction.LEFT_DOWN):
                        continue

                    with self.subTest(i=i, j=j, direction=direction):
                        self.assertTupleEqual((9, 9), n_move.shape)
                        self.assertTupleEqual((9, 9), p_move.shape)

                        if b[i, j] < Piece.WHITE_FU:
                            # 自身の駒があって動けない
                            self.assertFalse(np.all(n_move))
                            self.assertFalse(np.all(p_move))
                        else:
                            self.assertTrue(n_move[i, j])
                            n_move[i, j] = False
                            self.assertFalse(np.all(n_move))

                            if (j < 3 or j == 3 and direction in
                                (Direction.RIGHT_DOWN, Direction.LEFT_DOWN)):
                                self.assertTrue(p_move[i, j])
                                p_move[i, j] = False
                            self.assertFalse(np.all(p_move))
示例#10
0
    def test_um_move(self):
        """
        UMについて成り、成らずの判定のテスト
        利きが通るかどうかは別のところで判定しているので、ここでは考えない
        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        # 移動距離ごとに用意
        effect = {
            direction: [np.empty(shape, dtype=np.bool) for _ in range(8)]
            for direction in get_diagonal_directions()
        }
        effect.update({
            direction: np.empty(shape, dtype=np.bool)
            for direction in get_cross_directions()
        })

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

        ph_board = tf.placeholder(tf.int32, shape=shape)
        um_effect = {
            direction:
            [tf.placeholder(tf.bool, shape=shape) for _ in range(8)]
            for direction in get_diagonal_directions()
        }
        um_effect.update({
            direction: tf.placeholder(tf.bool, shape=shape)
            for direction in get_cross_directions()
        })
        non_promoting = BlackUmMoveLayer()(ph_board, um_effect)
        # アクセスしやすいように次元を下げる
        non_promoting = {
            key: tf.squeeze(value)
            for key, value in non_promoting.items()
        }

        feed_dict = {}
        for direction, ph_list in um_effect.items():
            if direction in get_diagonal_directions():
                for ph, e in zip(ph_list, effect[direction]):
                    feed_dict[ph] = e
            else:
                feed_dict[ph_list] = effect[direction]
        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 direction, effect_list in effect.items():
                    if direction in get_diagonal_directions():
                        for e in effect_list:
                            e[:] = False
                            if self.data_format == 'NCHW':
                                e[0, 0, i, j] = True
                            else:
                                e[0, i, j, 0] = True
                    else:
                        effect_list[:] = False
                        if self.data_format == 'NCHW':
                            effect_list[0, 0, i, j] = True
                        else:
                            effect_list[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, distance in product(effect.keys(), range(8)):
                    if direction in get_cross_directions():
                        if distance > 0:
                            continue

                        if direction == Direction.UP and j == 8:
                            continue
                        elif direction == Direction.DOWN and j == 0:
                            continue
                        elif direction == Direction.RIGHT and i == 8:
                            continue
                        elif direction == Direction.LEFT and i == 0:
                            continue

                    if direction in (Direction.RIGHT_UP, Direction.LEFT_UP):
                        if j + distance >= 8:
                            continue
                    elif direction in (Direction.RIGHT_DOWN,
                                       Direction.LEFT_DOWN):
                        if j - distance <= 0:
                            continue

                    if direction in (Direction.RIGHT_UP, Direction.RIGHT_DOWN):
                        if i + distance >= 8:
                            continue
                    elif direction in (Direction.LEFT_UP, Direction.LEFT_DOWN):
                        if i - distance <= 0:
                            continue

                    n_move = n[direction]

                    if direction in get_diagonal_directions():
                        with self.subTest(i=i,
                                          j=j,
                                          piece=piece,
                                          direction=direction,
                                          distance=distance):
                            self.assertTupleEqual((8, 9, 9), n_move.shape)

                            if b[i, j] < Piece.WHITE_FU:
                                # 自身の駒があって動けない
                                self.assertFalse(np.all(n_move[distance]))
                            else:
                                self.assertTrue(n_move[distance, i, j])
                                n_move[distance, i, j] = False
                                self.assertFalse(np.all(n_move[distance]))
                    else:
                        with self.subTest(i=i,
                                          j=j,
                                          piece=piece,
                                          direction=direction):
                            self.assertTupleEqual((9, 9), n_move.shape)

                            if b[i, j] < Piece.WHITE_FU:
                                # 自身の駒があって動けない
                                self.assertFalse(np.all(n_move))
                            else:
                                self.assertTrue(n_move[i, j])
                                n_move[i, j] = False
                                self.assertFalse(np.all(n_move))
示例#11
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))
    def test_ka_move(self):
        """
        KAについて成り、成らずの判定のテスト
        利きが通るかどうかは別のところで判定しているので、ここでは考えない
        :return:
        """
        shape = (1, 1, 9, 9) if self.data_format == 'NCHW' else (1, 9, 9, 1)
        # 移動距離ごとに用意
        effect = {
            direction: [np.empty(shape, dtype=np.bool) for _ in range(8)]
            for direction in get_diagonal_directions()
        }

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

        ph_board = tf.placeholder(tf.int32, shape=shape)
        ka_effect = {
            direction:
            [tf.placeholder(tf.bool, shape=shape) for _ in range(8)]
            for direction in effect.keys()
        }
        non_promoting, promoting = BlackKaMoveLayer(
            data_format=self.data_format)(ph_board, ka_effect)
        # アクセスしやすいように次元を下げる
        non_promoting = {
            key: tf.squeeze(value)
            for key, value in non_promoting.items()
        }
        promoting = {
            key: tf.squeeze(value)
            for key, value in promoting.items()
        }

        feed_dict = {}
        for direction, ph_list in ka_effect.items():
            for ph, e in zip(ph_list, effect[direction]):
                feed_dict[ph] = e
        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 effect_list in effect.values():
                    for e in effect_list:
                        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, p = sess.run([non_promoting, promoting],
                                feed_dict=feed_dict)

                b = np.squeeze(board)

                for direction, distance in product(effect.keys(), range(8)):
                    if direction in (Direction.RIGHT_UP, Direction.LEFT_UP):
                        if j + distance >= 8:
                            continue
                    elif direction in (Direction.RIGHT_DOWN,
                                       Direction.LEFT_DOWN):
                        if j - distance <= 0:
                            continue

                    if direction in (Direction.RIGHT_UP, Direction.RIGHT_DOWN):
                        if i + distance >= 8:
                            continue
                    elif direction in (Direction.LEFT_UP, Direction.LEFT_DOWN):
                        if i - distance <= 0:
                            continue

                    n_move = n[direction]
                    p_move = p[direction]

                    if j < 3:
                        # 方向に依らず成れる
                        promotable = True
                    elif direction in (Direction.RIGHT_DOWN,
                                       Direction.LEFT_DOWN):
                        promotable = distance + 1 < j < distance + 4
                    else:
                        promotable = False

                    with self.subTest(i=i,
                                      j=j,
                                      piece=piece,
                                      direction=direction,
                                      distance=distance):
                        self.assertTupleEqual((8, 9, 9), n_move.shape)
                        self.assertTupleEqual((8, 9, 9), p_move.shape)

                        if b[i, j] < Piece.WHITE_FU:
                            # 自身の駒があって動けない
                            self.assertFalse(np.all(n_move[distance]))
                            self.assertFalse(np.all(p_move[distance]))
                        else:
                            self.assertTrue(n_move[distance, i, j])
                            n_move[distance, i, j] = False
                            self.assertFalse(np.all(n_move[distance]))

                            if promotable:
                                self.assertTrue(p_move[distance, i, j])
                                p_move[distance, i, j] = False
                            self.assertFalse(np.all(p_move[distance]))