def test_valid_move(self): """ STS-1 Test 1 """ s = State() request = s.to_dict() request.pop('winner', None) request['piece'] = 1 request['target'] = 18 result = self.app.post('/move', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(200, result.status_code, 'Status is OK') expected = s.get_child(1 << 1, 1 << 18) expected = expected.to_dict() jd = json.loads(result.data) jd['prev_move'] = tuple(jd['prev_move']) jd['can_castle'] = tuple(jd['can_castle']) # subset because we're not considering jd['valid_moves'] self.assertTrue(expected.items() <= jd.items(), 'Returned response')
def test_search(self): s = State((0, 0, 0, 0, 2 << 16, 4 << 16), (0, 0, 0, 0, 0, 1), turn='w', in_check=False) agent = SampleMinimaxAgent() selected_move = agent.select_move(s) self.assertEqual(selected_move, (2 << 16, 2 << 8), 'Checkmate in 1')
def test_select_move_playout(self): agent = RandomPlayoutAgent(max_time=1, max_depth=2) s = State((0, 0, 0, 0, 2 << 16, 4 << 16), (0, 0, 0, 0, 0, 1), turn='w', in_check=False) random.seed(124915) selected_move = agent.select_move(s) self.assertEqual(selected_move, (2 << 16, 2 << 8), 'Checkmate in 1')
def test_select_move_random(self): agent = RandomMoveAgent() s = State() random.seed(124915) moves = set() for i in range(10): moves.add(agent.select_move(s)) self.assertTrue(len(moves) > 1)
def test_gradients(self): state_list = [State(), State(turn='b')] reward = GameResult.P1_WINS np.random.seed(185192) a1 = ValueNetworkAgent() a1.update(state_list, reward, use_numerical=False) actual_dwo, actual_dwh = a1.wo, a1.wh np.random.seed(185192) a2 = ValueNetworkAgent() a2.update(state_list, reward, use_numerical=True) expected_dwo, expected_dwh = a1.wo, a1.wh dwo_equal = np.allclose(actual_dwo, expected_dwo, 1e-8) dwh_equal = np.allclose(actual_dwh, expected_dwh, 1e-8) self.assertTrue(dwo_equal, 'dW_o almost equal') self.assertTrue(dwh_equal, 'dW_h almost equal')
def test_select_move_black(self): s = State(turn='b') a = ValueNetworkAgent() move = a.select_move(s) is_legal = True try: s.get_child(*move) except IllegalMoveException: is_legal = False self.assertTrue(is_legal, 'White select move')
def test_reset(self): s = State() result = self.app.get('/reset') jd = json.loads(result.data) jd['can_castle'] = tuple(jd['can_castle']) actual = State.from_dict(jd['pieces'], jd['turn'], jd['in_check'], jd['can_castle'], jd['prev_move']) self.assertEqual(s, actual, 'Reset board state')
def play_and_update(self): self.setup_iteration() n_moves = 0 result = GameResult.NONTERMINAL states = [] state = State() while n_moves < self.max_iter and result == GameResult.NONTERMINAL: states.append(state) move = self.select_move(state) state = state.get_child(*move) result = state.is_terminal() n_moves += 1 self.update(states, result) self.teardown_iteration()
def test_winning(self): s = State((0, 0, 0, 0, 2 << 16, 4 << 16), (0, 0, 0, 0, 0, 1), turn='w', in_check=False) request = s.to_dict() request.pop('winner', None) request['piece'] = 17 request['target'] = 9 result = self.app.post('/moveai', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(200, result.status_code, 'Status is OK') data = json.loads(result.data) self.assertEqual(data['winner'], 'P1_WINS', 'White wins')
def reset(): s = State() moves = [i.prev_move for i in s.get_children()] legal_move_dict = {} for piece, target in moves: legal_move_dict[piece.bit_length() - 1] = legal_move_dict.get( piece.bit_length() - 1, []) + [target.bit_length() - 1] d = s.to_dict() d['legal_moves'] = legal_move_dict response = jsonify(d) response.status_code = 200 return response return response
def test_stalemate(self): s = State((0, 0, 0, 0, 1 << 24, 4 << 16), (0, 0, 0, 0, 0, 2), turn='w', in_check=False) request = s.to_dict() request.pop('winner', None) request['piece'] = 24 request['target'] = 16 result = self.app.post('/moveai', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(200, result.status_code, 'Status is OK') data = json.loads(result.data) self.assertEqual(data['winner'], 'DRAW', 'White moves, stalemate ensues')
def test_invalid_move(self): """ STS-1 Test 2 """ s = State() request = s.to_dict() request.pop('winner', None) request['piece'] = 1 request['target'] = 20 result = self.app.post('/move', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(400, result.status_code, 'Illegal request throws error') result_message = json.loads(result.data)['message'] self.assertEqual(result_message, 'Completely and utterly illegal move', 'Illegal move message')
def test_capture(self): s = State(wp=0x0800F000, bp=0x1000000000) request = s.to_dict() request.pop('winner', None) request['piece'] = 27 request['target'] = 36 result = self.app.post('/move', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(200, result.status_code, 'Status is OK') expected = s.get_child(1 << 27, 1 << 36) expected = expected.to_dict() jd = json.loads(result.data) jd['prev_move'] = tuple(jd['prev_move']) jd['can_castle'] = tuple(jd['can_castle']) self.assertTrue(expected.items() <= jd.items(), 'Returned response')
def test_valid_nowin(self): s = State() request = s.to_dict() request.pop('winner', None) request['piece'] = 1 request['target'] = 18 result = self.app.post('/moveai', data=json.dumps(request), headers={'content-type': 'application/json'}) self.assertEqual(200, result.status_code, 'Status is OK') move_one = s.get_child(1 << 1, 1 << 18) possible_children = set(move_one.get_children()) data = json.loads(result.data) actual = State.from_dict(data['pieces'], data['turn'], data['in_check'], data['can_castle'], data['prev_move']) self.assertTrue(actual in possible_children, 'Valid responding move')
@property def max_depth(self): return self._max_depth def select_move(self, state: 'State'): self.n_ab = self.n_heuristic = 0 return super(CountingMinimaxAgent, self).select_move(state) def _alpha_beta(self, state: 'State', depth: int, alpha: float, beta: float, maxer: bool): self.n_ab += 1 return super(CountingMinimaxAgent, self)._alpha_beta(state, depth, alpha, beta, maxer) def heuristic(self, state: 'State'): self.n_heuristic += 1 return super(CountingMinimaxAgent, self).heuristic(state) if __name__ == '__main__': a = CountingMinimaxAgent(6) s = State() start = time.time() a.select_move(s) end = time.time() heuristic_per_second = a.n_heuristic / (end - start) ab_per_second = a.n_ab / (end - start) print('Heuristic Evaluations per second: %.1f' % heuristic_per_second) print('Alpha Beta Evaluations per second: %.1f' % ab_per_second)