def xstrategy(): # Initialize objects to read to input_obj = "" # Read from STDIN indefinitely until stream is closed for k in sys.stdin: input_obj += k # Load from read string json_list = json.loads(input_obj) # Get desired depth and state from json_list depth = json_list[0] state = json_list[1] # Find the first player in the json state first_player_color = _str_to_color(state['players'][0]['color']) # Load the json state into a State object initialized_state = initialize_state(state) # Check if the first player in the array is stuck and print false to STDOUT if so if first_player_color in initialized_state.stuck_players: print(json.dumps(False)) else: # Compute the best action the first player can take given the current state and depth best_action = Strategy.get_best_action(initialized_state, depth) # Print the best action to STDOUT print(_action_to_json(best_action))
def test_get_next_state_success(self): # Test successful get next state json_obj = { 'players': [ {'score': 0, 'places': [[1, 0], [2, 0], [0, 0]], 'color': 'white'}, {'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black'}, {'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown'} ], 'board': [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]] } # Initialize state from json object state = initialize_state(json_obj) # Expected state after getting next state expected_state = { 'players': [ {'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black'}, {'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown'}, {'score': 4, 'places': [[3, 0], [2, 0], [0, 0]], 'color': 'white'} ], 'board': [[4, 4, 4], [0, 4, 4], [4, 4, 4], [4, 4, 4]] } # Get next state next_state = _get_next_state(state) # Make sure json representations of the states are as expected self.assertDictEqual(expected_state, _state_to_json(next_state))
def test_get_next_state_fail4(self): # Test failure of get_next_state due to invalid action with self.assertRaises(InvalidActionException): json_obj = { 'players': [{ 'score': 0, 'places': [[1, 0], [2, 0], [0, 0]], 'color': 'white' }, { 'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black' }, { 'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown' }], 'board': [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]] } # Initialize state from json object state = initialize_state(json_obj) # Get next state _get_next_state(state, Position(1, 1), Position(1, 0))
def decode_message(self, msg: json): """ Validate this JSON message, return the type (string) if valid :return: tuple(type, args) containing string type and converted (decoded) arguments for this message """ if not len(msg) == 2: raise JsonDecodeException('Expected JSON message array to have length 2 [type, args]') if not isinstance(msg[0], str): raise JsonDecodeException('Expected str for JSON message type!') if not isinstance(msg[1], list): raise JsonDecodeException('Expected list for args in JSON message.') type = msg[0] args = msg[1] if type == 'start' or type == 'end': if not len(args) == 1 or not isinstance(args[0], bool): raise JsonDecodeException('Invalid format for tournament start / end message.') return type, args elif type == 'playing-as': if not len(args) == 1 or not isinstance(args[0], str): raise JsonDecodeException('Invalid format for playing-as message.') return type, [_str_to_color(color) for color in args] elif type == 'playing-with': if not len(args) > 0 or not all(isinstance(color, str) for color in args): raise JsonDecodeException('Invalid format for playing-with message.') return type, [_str_to_color(color) for color in args] elif type == 'setup': if not len(args) == 1: raise JsonDecodeException('Invalid format for setup message.') return type, [initialize_state(args[0])] elif type == 'take-turn': if not len(args) == 2: raise JsonDecodeException('Invalid format for take-turn message.') return type, [initialize_state(args[0]), [self.decode_action(action) for action in args[1]]] else: raise JsonDecodeException('Unknown type of JSON message.')
def test_get_next_state_success(self): # Test successful get next state json_obj = { 'players': [{ 'score': 0, 'places': [[1, 0], [2, 0], [0, 0]], 'color': 'white' }, { 'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black' }, { 'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown' }], 'board': [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]] } # Initialize state from json object state = initialize_state(json_obj) # From position and to position for a valid action pos1 = Position(2, 0) pos2 = Position(3, 0) # Get next state next_state = _get_next_state(state, pos1, pos2) expected_state = { 'players': [{ 'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black' }, { 'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown' }, { 'score': 4, 'places': [[1, 0], [3, 0], [0, 0]], 'color': 'white' }], 'board': [[4, 4, 4], [4, 4, 4], [0, 4, 4], [4, 4, 4]] } self.assertDictEqual(_state_to_json(next_state), expected_state)
def xtree() -> None: """ Reads in a game state from STDIN and writes the next game state to STDOUT. The next game state is the one resulting from the first player's first penguin moving in the first permissible direction. If said penguin cannot move in any direction then False is written to STDOUT instead. """ # Initialize objects to read to input_obj = "" # Read from STDIN indefinitely until stream is closed for k in sys.stdin: input_obj += k # Load from read string json_obj = json.loads(input_obj) # Convert from and to position to a Position object from_pos = Position(json_obj['from'][0], json_obj['from'][1]) to_pos = Position(json_obj['to'][0], json_obj['to'][1]) # Initialize State object from json representation of state init_state = initialize_state(json_obj['state']) # Get the state after player 1 takes their first action state = _get_next_state(init_state, from_pos, to_pos) # Find an action Player 2 can take to reach a neighboring tile from player 1 action = _find_action_to_neighboring_tile(state, to_pos) # If there is no next state for first avatar, print False if action is None: print(json.dumps(False)) else: # Write JSON to STDOUT print(json.dumps(_action_to_json(action)))
def test_get_next_state_fail2(self): # Test failure of get_next_state due to invalid type for from_pos with self.assertRaises(TypeError): json_obj = { 'players': [{ 'score': 0, 'places': [[1, 0], [2, 0], [0, 0]], 'color': 'white' }, { 'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black' }, { 'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown' }], 'board': [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]] } # Initialize state from json object state = initialize_state(json_obj) _get_next_state(state, 4, Position(1, 2))
def test_find_action_to_neighboring_tile_fail2(self): # Test failing find action to neighboring tile due to invalid position type with self.assertRaises(TypeError): json_obj = { 'players': [{ 'score': 0, 'places': [[1, 0], [2, 0], [0, 0]], 'color': 'white' }, { 'score': 0, 'places': [[1, 1], [2, 1], [3, 1]], 'color': 'black' }, { 'score': 0, 'places': [[0, 1], [1, 2], [3, 2]], 'color': 'brown' }], 'board': [[4, 4, 4], [4, 4, 4], [4, 4, 4], [4, 4, 4]] } # Initialize state from json object state = initialize_state(json_obj) _find_action_to_neighboring_tile(state, "Hello")
def testinitialize_state_fail3(self): # Fails due to json_obj not containing board with self.assertRaises(ValueError): initialize_state({'players': []})
def testinitialize_state_fail1(self): # Fails due to json_obj being invalid with self.assertRaises(TypeError): initialize_state('')