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