def test_get_sensibleness(self): gs, moves = parseboard.parse("x B . . W . . . .|" "B B W . . W . . .|" ". W B B W W . . .|" ". B y B W W . . .|" ". B B z B W . . .|" ". . B B B W . . .|" ". . . . . . . . W|" ". . . . . . . . W|" ". . . . . . . W s|") gs.set_current_player(go.BLACK) pp = Preprocess(["sensibleness"], size=9) feature = pp.state_to_tensor(gs)[0, 0] # 1D tensor; no need to transpose expectation = np.zeros((gs.get_size(), gs.get_size()), dtype=int) for (x, y) in gs.get_legal_moves(): expectation[x, y] = 1 # 'x', 'y', and 'z' are eyes - remove them from 'sensible' moves expectation[moves['x']] = 0 expectation[moves['y']] = 0 expectation[moves['z']] = 0 # 's' is suicide - should not be legal expectation[moves['s']] = 0 self.assertTrue(np.all(expectation == feature))
def test_ko_undo(self): gs, moves = parseboard.parse(". B . . . . .|" "B W B . . . .|" "W k W . . . .|" ". W . . . . .|" ". . . . . . .|" ". . . . a . .|" ". . . . . . .|") gs.set_current_player(go.BLACK) # Trigger ko at (1, 1) gs.do_move(moves['k']) ko = gs.get_ko_location() self.assertIsNotNone(ko) copy = gs.copy() self.equality_checks(gs, copy) with copy.try_stone(flatten_idx(moves['a'], gs.get_size())): self.inequality_checks(gs, copy) # Doing move at 'a' clears ko self.assertIsNone(copy.get_ko_location()) self.equality_checks(gs, copy) # Undoing move at 'a' resets ko self.assertEqual(copy.get_ko_location(), ko)
def test_large_group_neighbors(self): gs, _ = parseboard.parse(". . B B B . .|" ". . B B B . .|" ". . B B B . .|" ". . W W W . .|" ". . W W W . .|" ". . W W W . .|" ". . . . . . .|") self.assertTrue(gs.sanity_check_groups())
def test_capture_to_escape_1(self): st, moves = parseboard.parse(". O X . . .|" ". X O X . .|" ". . O X . .|" ". . a . . .|" ". O . . . .|" ". . . . . .|") st.current_player = BLACK # 'a' is not a capture because of ataris self.assertFalse(st.is_ladder_capture(moves['a']))
def test_copy(self): gs, _ = parseboard.parse(". B . . . . .|" "B W W . . . .|" ". B W . B . .|" ". . . . . . B|" ". . B . . . .|" "W . . . W W .|") copy = gs.copy() self.assertTrue(copy.sanity_check_groups()) self.equality_checks(gs, copy)
def test_two_captures(self): st, moves = parseboard.parse(". . . . . .|" ". . . . . .|" ". . a b . .|" ". X O O X .|" ". . X X . .|" ". . . . . .|") st.current_player = BLACK # both 'a' and 'b' should be ladder captures self.assertTrue(st.is_ladder_capture(moves['a'])) self.assertTrue(st.is_ladder_capture(moves['b']))
def test_snapback_1(self): st, moves = parseboard.parse(". . . . . . . . .|" ". . . . . . . . .|" ". . X X X . . . .|" ". . O . . . . . .|" ". . O X . . . . .|" ". . X O a . . . .|" ". . X O X . . . .|" ". . . X . . . . .|" ". . . . . . . . .|") st.current_player = WHITE # 'a' is not an escape for white self.assertFalse(st.is_ladder_escape(moves['a']))
def test_get_ladder_capture(self): gs, moves = parseboard.parse(". . . . . . .|" "B W a . . . .|" ". B . . . . .|" ". . . . . . .|" ". . . . . . .|" ". . . . . W .|") pp = Preprocess(["ladder_capture"], size=7) feature = pp.state_to_tensor(gs)[0, 0] # 1D tensor; no need to transpose expectation = np.zeros((gs.get_size(), gs.get_size())) expectation[moves['a']] = 1 self.assertTrue(np.all(expectation == feature))
def test_two_escapes(self): st, moves = parseboard.parse(". . X . . .|" ". X O a . .|" ". X c X . .|" ". O X b . .|" ". . O . . .|" ". . . . . .|") # place a white stone at c, and reset player to white st.do_move(moves['c'], color=WHITE) st.current_player = WHITE # both 'a' and 'b' should be considered escape moves for white after 'O' at c self.assertTrue(st.is_ladder_escape(moves['a'])) self.assertTrue(st.is_ladder_escape(moves['b'], prey=moves['c']))
def test_get_ladder_escape(self): # On this board, playing at 'a' is ladder escape because there is a breaker on the right. gs, moves = parseboard.parse(". B B . . . .|" "B W a . . . .|" ". B . . . . .|" ". . . . . W .|" ". . . . . . .|" ". . . . . . .|") pp = Preprocess(["ladder_escape"], size=7) gs.set_current_player(go.WHITE) feature = pp.state_to_tensor(gs)[0, 0] # 1D tensor; no need to transpose expectation = np.zeros((gs.get_size(), gs.get_size())) expectation[moves['a']] = 1 self.assertTrue(np.all(expectation == feature))
def test_throw_in_1(self): st, moves = parseboard.parse("X a O X . .|" "b O O X . .|" "O O X X . .|" "X X . . . .|" ". . . . . .|" ". . . O . .|") st.current_player = BLACK # 'a' or 'b' will capture self.assertTrue(st.is_ladder_capture(moves['a'])) self.assertTrue(st.is_ladder_capture(moves['b'])) # after 'a', 'b' doesn't help white escape st.do_move(moves['a']) self.assertFalse(st.is_ladder_escape(moves['b']))
def test_missing_ladder_breaker_1(self): st, moves = parseboard.parse(". B . . . . .|" "B W B . . W .|" "B a c . . . .|" ". b . . . . .|" ". . . . . . .|" ". W . . . . .|" ". . . . . . .|") st.current_player = WHITE # a should not be an escape move for white self.assertFalse(st.is_ladder_escape(moves['a'])) # after 'a', 'b' should still be a capture ... st.do_move(moves['a']) self.assertTrue(st.is_ladder_capture(moves['b'])) # ... but 'c' should not self.assertFalse(st.is_ladder_capture(moves['c']))
def test_breaker_1(self): st, moves = parseboard.parse(". B . . . . .|" "B W a . . W .|" "B b . . . . .|" ". c . . . . .|" ". . . . . . .|" ". . . . . W .|" ". . . . . . .|") st.set_current_player(BLACK) # 'a' should not be a ladder capture, nor 'b' self.assertFalse(is_ladder_capture(st, moves['a'])) self.assertFalse(is_ladder_capture(st, moves['b'])) # after 'a', 'b' should be an escape st.do_move(moves['a']) self.assertTrue(is_ladder_escape(st, moves['b'])) # after 'b', 'c' should not be a capture st.do_move(moves['b']) self.assertFalse(is_ladder_capture(st, moves['c']))
def test_captured_1(self): st, moves = parseboard.parse("d b c . . . .|" "B W a . . . .|" ". B . . . . .|" ". . . . . . .|" ". . . . . . .|" ". . . . . W .|") st.set_current_player(BLACK) # 'a' should catch white in a ladder, but not 'b' self.assertTrue(is_ladder_capture(st, moves['a'])) self.assertFalse(is_ladder_capture(st, moves['b'])) # 'b' should not be an escape move for white after 'a' st.do_move(moves['a']) self.assertFalse(is_ladder_escape(st, moves['b'])) # W at 'b', check 'c' and 'd' st.do_move(moves['b']) self.assertTrue(is_ladder_capture(st, moves['c'])) self.assertFalse(is_ladder_capture(st, moves['d'])) # self-atari
def test_two_escapes(self): gs, moves = parseboard.parse(". . X . . .|" ". X O a . .|" ". X c X . .|" ". O X b . .|" ". . O . . .|" ". . . . . .|") # place a white stone at c, and reset player to white gs.do_move(moves['c'], color=go.WHITE) gs.set_current_player(go.WHITE) pp = Preprocess(["ladder_escape"], size=6) gs.set_current_player(go.WHITE) feature = pp.state_to_tensor(gs)[0, 0] # 1D tensor; no need to transpose # both 'a' and 'b' should be considered escape moves for white after 'O' at c expectation = np.zeros((gs.get_size(), gs.get_size())) expectation[moves['a']] = 1 expectation[moves['b']] = 1 self.assertTrue(np.all(expectation == feature))
def test_merge_and_capture_undo(self): gs, moves = parseboard.parse(". . B B B . .|" ". B W W W B .|" ". B W B W B .|" ". B W c W B .|" ". B W B W B .|" ". B W W W B .|" ". . B B B . .|") gs.set_current_player(go.BLACK) copy = gs.copy() # Initial equality checks self.assertTrue(copy.sanity_check_groups()) self.equality_checks(gs, copy) with copy.try_stone(flatten_idx(moves['c'], gs.get_size())): self.assertTrue(copy.sanity_check_groups()) self.inequality_checks(gs, copy) # Move should now be undone - retry equality checks from above self.assertTrue(copy.sanity_check_groups()) self.equality_checks(gs, copy)
def test_hash_update_matches_actual_hash(self): gs = GameState(size=7) gs, moves = parseboard.parse("a x b . . . .|" "z c d . . . .|" ". . . . . . .|" ". . . y . . .|" ". . . . . . .|" ". . . . . . .|" ". . . . . . .|") # a,b,c,d are black, x,y,z,x are white move_order = ['a', 'x', 'b', 'y', 'c', 'z', 'd', 'x'] for m in move_order: move_1d = flatten_idx(moves[m], gs.get_size()) # 'Try' move and get hash with gs.try_stone(move_1d): hash1 = gs.get_hash() # Actually do move and get hash gs.do_move(moves[m]) hash2 = gs.get_hash() self.assertEqual(hash1, hash2)