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)
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))
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))
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))
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)
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))
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))
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))
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))
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))
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]))