def test_tile_pattern_to_tile() -> None: assert tiles.tile_pattern_to_tile(22, 90) == tiles.index_to_tile(22) assert tiles.tile_to_rotation_angle(tiles.tile_pattern_to_tile(31, 0)) == 0 assert tiles.tile_to_rotation_angle(tiles.tile_pattern_to_tile(31, 90)) == 90 assert tiles.tile_to_rotation_angle(tiles.tile_pattern_to_tile(31, 180)) == 180 assert tiles.tile_to_rotation_angle(tiles.tile_pattern_to_tile(31, 270)) == 270
def main() -> None: """ Connect to the server at host:port via TCP to render a board state to the GUI via a GraphicalPlayerObserver """ json_stream = StdinStdoutJSONStream() state_pats_json_r = json_stream.receive_message() board = setup_board(state_pats_json_r.assert_value()) turn_pat_json = json_stream.receive_message().assert_value() act_pat = ActionPat.from_json(turn_pat_json[0] # pylint: disable=unsubscriptable-object ) offered_tiles: List[Tile] = [ index_to_tile(tile_idx) for tile_idx in turn_pat_json[1:] # pylint: disable=unsubscriptable-object ] move = IntermediateMove( tile_pattern_to_tile(act_pat.tile_pat.tile_index, act_pat.tile_pat.rotation_angle), act_pat.player, ) rule_checker = RuleChecker() r = rule_checker.validate_move(board.get_board_state(), offered_tiles, move) if r.is_error(): json_stream.send_message("cheating") else: json_stream.send_message("legal") if DEBUG: board.get_board_state().debug_display_board() r = board.intermediate_move(move) if r.is_error(): print("Failed to render #2") else: board.get_board_state().debug_display_board()
def main(host: str, port: int) -> None: """ Connect to the server at host:port via TCP to render a board state to the GUI via a GraphicalPlayerObserver :param host: The host to connect to :param port: The port to connect to :return: None """ gpo = GraphicalPlayerObserver() json_stream = NetworkJSONStream.tcp_client_to(host, port) json_stream.send_message(AUTHORS) state_pats_json_r = json_stream.receive_message() board = setup_board(state_pats_json_r.assert_value()) gpo.set_players(list(board.live_players.keys())) turn_pat_json = json_stream.receive_message().assert_value() act_pat = ActionPat.from_json(turn_pat_json[0] # pylint: disable=unsubscriptable-object ) gpo.set_color(act_pat.player) offered_tiles: List[Tile] = [ index_to_tile(tile_idx) for tile_idx in turn_pat_json[1:] ] gpo.intermediate_move_offered(offered_tiles, board.get_board_state()) move = IntermediateMove( tile_pattern_to_tile(act_pat.tile_pat.tile_index, act_pat.tile_pat.rotation_angle), act_pat.player, ) gpo.intermediate_move_played(offered_tiles, board.get_board_state(), move) json_stream.close()
def _handle_initial_received(self, initial: List) -> Result[Tuple[BoardPosition, Tile, PortID]]: """ Returns the initial placement given the initial message. """ board_posn = BoardPosition(initial[2], initial[3]) tile = tile_pattern_to_tile(initial[0][0], initial[0][1]) port = network_port_id_to_port_id(initial[1]) return ok((board_posn, tile, port))
def setup_board(board_setup_data: JSON) -> Board: """ Setup the board according to the given board setup data. This is the first JSON value read from the integration test which is an array of initial-place or intermediate-place. Raises an exception if the input is invalid in any way. :param board_setup_data: An array containg either initial-place elements or intermediate-place elements :return: A board created from the setup data """ board = Board() for item in board_setup_data: if len(item) == 5: initial_place = InitialPlace.from_json(item) r = board.initial_move_with_scissors( InitialMove( BoardPosition(initial_place.x_index, initial_place.y_index), tile_pattern_to_tile( initial_place.tile_pat.tile_index, initial_place.tile_pat.rotation_angle, ), network_port_id_to_port_id(initial_place.port), initial_place.player, )) if r.is_error(): raise Exception(r.error()) elif len(item) == 3: intermediate_place = IntermediatePlace.from_json(item) r = board.place_tile_at_index_with_scissors( tile_pattern_to_tile( intermediate_place.tile_pat.tile_index, intermediate_place.tile_pat.rotation_angle, ), BoardPosition(intermediate_place.x_index, intermediate_place.y_index), ) if r.is_error(): raise Exception(r.error()) else: raise Exception(f"Failed to parse JSON input: {item}") return board
def main() -> None: """ Main function for the xboard integration test. Creates a board, applies action pats, and prints data to stdout as described in assignment 4: http://www.ccs.neu.edu/home/matthias/4500-f19/4.html :return: None """ stdin_stream = StdinStdoutJSONStream() board = setup_board(stdin_stream.receive_message().assert_value()) logging_observer = LoggingObserver() board.add_observer(logging_observer) if "red" not in board.live_players: print_and_exit("red never played", board) for act_pat_json in stdin_stream.message_iterator(): act_pat = ActionPat.from_json(act_pat_json.assert_value()) r = board.intermediate_move( IntermediateMove( tile_pattern_to_tile(act_pat.tile_pat.tile_index, act_pat.tile_pat.rotation_angle), act_pat.player, )) if r.is_error(): raise Exception(r.error()) if logging_observer.entered_loop: print_and_exit("infinite", board) seen_pos_port: Set[Tuple[BoardPosition, PortID]] = set() for (pos, port) in board.live_players.values(): if (pos, port) in seen_pos_port: print_and_exit("collision", board) seen_pos_port.add((pos, port)) if "red" not in board.live_players: print_and_exit("red died", board) red_pos, red_port = board.live_players["red"] til = board.get_board_state().get_tile(red_pos) if til is None: raise Exception( "There is no tile at red's position - this should never happen") tile_pat = TilePat(tile_to_index(til), tile_to_rotation_angle(til)) print_and_exit( [ tile_pat.to_json(), "red", port_id_to_network_port_id(red_port), red_pos.x, red_pos.y, ], board, )
def _handle_intermediate_received(self, intermediate: List) -> Result[Tile]: """ Returns an intermediate placement based on the given intermediate message. """ tile = tile_pattern_to_tile(intermediate[0], intermediate[1]) return ok(tile)