def beta_play(self, board_history): # work in progress current_board = board_history[0] opponent_point = MaybeStone.flip_stone(self.stone) all_opponent_connections = [] for point in Board.get_points(current_board, opponent_point): all_opponent_connections.append(get_blob(current_board, point)) all_opponent_liberties = [] for connection in all_opponent_connections: all_opponent_liberties.append( get_blob_liberties(current_board, connection)) connections_with_one_liberty = set() for liberties_set in all_opponent_liberties: if len(liberties_set) == 1: connections_with_one_liberty.union(liberties_set) for row, maybe_stones in enumerate(current_board): for column, maybe_stone in enumerate(current_board): if (column, row) in connections_with_one_liberty: try: RuleChecker.check_move(self.stone, (column, row), board_history) return Point.point_to_string((column, row)) except IllegalMoveError: pass except ImproperHistoryError as e: # raise PlayerCommandError('Invalid history') from e return 'This history makes no sense!' return 'pass'
def test_check_player_color(self): rule_checker = RuleChecker() valid_colors = ['white', 'black', 'red', 'green', 'blue'] for color in valid_colors: self.assertAlmostEqual(rule_checker.check_player_color(color), True) self.assertAlmostEqual(rule_checker.check_player_color("orange"), False)
def initial_setUp(self): self.T = TP.extract_transcript('transcriptparser/test.pdf') with mock.patch.object(attendanceparser.parser, 'get_attendance', return_value=mock_attendance): self.A: List[Attendance] = AP.parse_attendance(self.T.student_id) self.C: RuleChecker = RuleChecker(self.T, self.A)
def execute_turn(self, action): # Check for double pass if action == "pass": if not self.last_turn_was_pass: self.last_turn_was_pass = True self._update_history(self.board_hist[0]) return deepcopy(self.board_hist) elif self.last_turn_was_pass: return self.end_game() elif action == "GO has gone crazy!" or action == "This history makes no sense!": if self.current_turn == "B": return self.end_game(self.black_player) else: return self.end_game(self.white_player) else: self.last_turn_was_pass = False action = Point.string_to_point(action) try: new_board = RuleChecker.check_move(self.current_turn, action, self.board_hist) self._update_history(new_board) return deepcopy(self.board_hist) except RuleCheckerError as e: if self.current_turn == "B": return self.end_game(self.black_player) else: return self.end_game(self.white_player)
def test_check_player_dead(self): rule_checker = RuleChecker() board = Board() player = Avatar('green') tile_1 = HandTile([('n1', 's2'), ('n2', 'e2'), ('e1', 'w2'), ('s1', 'w1')]) tile_2 = HandTile([('n1', 'e2'), ('n2', 'w2'), ('e1', 's1'), ('s2', 'w1')]) board.first_turn(player, tile_1, 'a1', 'n1') self.assertAlmostEqual(player.current_port, 's2') self.assertAlmostEqual(player.current_tile, 'a1') self.assertAlmostEqual( rule_checker.check_player_dead(board, tile_2, "a2", player), True) self.assertAlmostEqual( rule_checker.check_player_dead(board, tile_1, "a2", player), False)
def test_check_turn(self): rc = RuleChecker() empty_board = Board() player = Avatar("white") tile = HandTile([('s1', 'e2'), ('s2', 'w1'), ('e1', 'n2'), ('n1', 'w2')]) tile_2 = HandTile([('n1', 's2'), ('n2', 'e2'), ('e1', 'w2'), ('s1', 'w1')]) suicide_tile = HandTile([('n1', 'w1'), ('n2', 'e1'), ('s2', 'e2'), ('s1', 'w2')]) empty_board.first_turn(player, tile, "a1", "n2") self.assertAlmostEqual(player.current_port, "e1") self.assertAlmostEqual(player.current_tile, "a1") player.tiles = [tile_2, suicide_tile] # Tile has to be at the correct coordinate self.assertAlmostEqual( rc.check_turn(empty_board, tile_2, "a1", player)["legal"], False) self.assertAlmostEqual( rc.check_turn(empty_board, tile_2, "a2", player)["legal"], False) self.assertAlmostEqual( rc.check_turn(empty_board, tile_2, "b1", player)["legal"], True) # Tile cannot cause a suicide if there are other options self.assertAlmostEqual( rc.check_turn(empty_board, suicide_tile, "b1", player)["legal"], False) player.tiles = [suicide_tile] self.assertAlmostEqual( rc.check_turn(empty_board, suicide_tile, "b1", player)["legal"], True)
def dumb_play(self, board_history): if self.stone == None: raise PlayerCommandError( 'You need to set the stone before you can play.') current_board = board_history[0] for column, maybe_stones in enumerate(current_board): for row, maybe_stone in enumerate(current_board): try: RuleChecker.check_move(self.stone, (column, row), board_history) return Point.point_to_string((column, row)) except IllegalMoveError: pass except ImproperHistoryError as e: # raise PlayerCommandError('Invalid history') from e return 'This history makes no sense!' return 'pass'
def test_valid_starting_port(self): rc = RuleChecker() coordinate = "a1" port_valid_north = 'n1' port_valid_west = 'w1' port_invalid = 's2' port_invalid_side = 'x2' port_invalid_space = 'n5' self.assertAlmostEqual( rc.valid_starting_port(coordinate, port_valid_north), True) self.assertAlmostEqual( rc.valid_starting_port(coordinate, port_valid_west), True) self.assertAlmostEqual( rc.valid_starting_port(coordinate, port_invalid), False) self.assertAlmostEqual( rc.valid_starting_port(coordinate, port_invalid_side), False) self.assertAlmostEqual( rc.valid_starting_port(coordinate, port_invalid_space), False)
def end_game(self, committed_illegal=""): # Checks the score using RuleChecker and returns the name(s) of the winner(s) score = RuleChecker.get_score(self.board_hist[0]) black_score = score["B"] white_score = score["W"] # Cheating players: winning player, cheating player, cheating flag if committed_illegal == self.black_player: return [self.white_player, self.black_player, 2] elif committed_illegal == self.white_player: return [self.black_player, self.white_player, 2] if black_score > white_score: return [self.black_player] elif white_score > black_score: return [self.white_player] elif black_score == white_score: winners = [self.black_player, self.white_player] return winners
def n1play(self, board_history): if self.stone == None: raise PlayerCommandError( 'You need to set the stone before you can play.') current_board = copy.deepcopy(board_history[0]) opponent_point = MaybeStone.flip_stone(self.stone) for column_index in range(MAX_COLUMN): for row_index in range(MAX_ROW): if self.check_for_adjacent_stones(opponent_point, (column_index, row_index), current_board): try: # Try putting a stone in the current position new_board = RuleChecker.check_move( self.stone, (column_index, row_index), board_history) try: Board.place(current_board, self.stone, (column_index, row_index)) # See if capture occurred by comparing with just placing if current_board != new_board: return Point.point_to_string( (column_index, row_index)) else: Board.remove(current_board, self.stone, (column_index, row_index)) except BoardStateError as e: pass except IllegalMoveError as e: pass except ImproperHistoryError as e: # raise PlayerCommandError('Invalid history') from e return 'This history makes no sense!' return self.dumb_play(board_history)
def __init__(self): self.tiles = {} self.rule_checker = RuleChecker()
class Board: # Constructor def __init__(self): self.tiles = {} self.rule_checker = RuleChecker() # returns true if the given board coordinate has a tile on it def is_coordinate_occupied(self, board_coordinate): return board_coordinate in self.tiles.keys() # returns dictionary of north, south, east, west neighbors of the given square def get_board_coordinate_neighbors(self, board_coordinate): neighbors = {NORTH: None, SOUTH: None, WEST: None, EAST: None} for side in neighbors.keys(): neighbor = get_coordinate_neighbor(board_coordinate, side) if self.is_coordinate_occupied(neighbor): neighbor = self.tiles[neighbor] elif neighbor != EDGE: neighbor = None neighbors[side] = neighbor return neighbors # Converts hand_tile to a BoardTile and initializes its neighbors def convert_to_board_tile(self, hand_tile, board_coordinate): tile_neighbors = self.get_board_coordinate_neighbors(board_coordinate) board_tile = BoardTile(hand_tile.paths, tile_neighbors) return board_tile # hand_tile is a HandTile , board_coordinate is a string of 2 characters # in battleship coordiates -> 10x10 board is A-J 1-10 # returns the generated board tile def place_tile(self, hand_tile, board_coordinate): board_tile = self.convert_to_board_tile(hand_tile, board_coordinate) self.tiles[board_coordinate] = board_tile # Link the newly created board tile to any of its neighbors currently on the board sides = [NORTH, SOUTH, EAST, WEST] for side in sides: new_neighbor_coordinate = get_coordinate_neighbor( board_coordinate, side) if self.is_coordinate_occupied(new_neighbor_coordinate): new_neighbor = self.tiles[new_neighbor_coordinate] new_neighbor.set_neighbor(get_opposite_side(side), board_tile) return board_tile # given a board coordinate and a starting port on the tile at that location # return the end board coordinate and port of that path on this board # or EDGE if they fall off the board # board_coordinate must have a tile on it (be in board.tiles) def end_of_path(self, board_coordinate, starting_port): board_tile = self.tiles[board_coordinate] end_port = board_tile.end_of_path(starting_port) neighboring_side = port_to_side(end_port) neighbor_to_move_to = board_tile.neighbors[neighboring_side] if neighbor_to_move_to == EDGE: return {TILE: EDGE, PORT: EDGE} elif neighbor_to_move_to == None: return {TILE: board_coordinate, PORT: end_port} else: new_tile_location = get_coordinate_neighbor( board_coordinate, neighboring_side) starting_port_on_new_tile = get_connecting_port(end_port) return self.end_of_path(new_tile_location, starting_port_on_new_tile) # moves given player to given board_coordinate and moves them along the path # throws exception if player cannot be moved (if there is no tile at the connecting side) def move_player(self, player): starting_port = player.current_port new_coordiate = get_connecting_coordinate(player.current_tile, starting_port) if self.is_coordinate_occupied(new_coordiate): port_on_new_tile = get_connecting_port(starting_port) ending_location = self.end_of_path(new_coordiate, port_on_new_tile) player.current_tile = ending_location[TILE] player.current_port = ending_location[PORT] else: logging.info("Player cannot be moved, no tile at: %s", new_coordiate) sys.exit(1) # places a player and a handtile on the board at the given coordinate and port # this is part of the players intial turn def first_turn(self, player, hand_tile, board_coordinate, starting_port): # Rule Checker : sees if tile location is valid first_turn_check = self.rule_checker.check_first_turn( self, hand_tile, board_coordinate, starting_port)[LEGAL] if first_turn_check: board_tile = self.place_tile(hand_tile, board_coordinate) end_port = board_tile.end_of_path(starting_port) player.place_avatar(board_coordinate, end_port) else: logging.info("Invalid initial tile placement: %s", board_coordinate) sys.exit(1) def take_turn(self, hand_tile, board_coordinate, player): # Rule Checker : sees if turn is valid turn_check = self.rule_checker.check_turn(self, hand_tile, board_coordinate, player)[LEGAL] if turn_check: self.place_tile(hand_tile, board_coordinate) self.move_player(player) else: logging.info("Invalid turn: %s", board_coordinate) sys.exit(1) def get_port_coordinate(self, port): return (0, 0)
def __init__(self): self.deck = Deck() self.board = Board() self.player_dictionary = {} self.rule_checker = RuleChecker() self.dead_players = []
class GameState: def __init__(self): self.deck = Deck() self.board = Board() self.player_dictionary = {} self.rule_checker = RuleChecker() self.dead_players = [] #################### Public methods ################################### # checks if an initial tile placement is legal # tile_index -> int : 0 - 34 (represents the index in all_tiles) # rotation -> int : 0, 90, 180, 270 (represents the number of roations for the given tile) # boar_coordinate -> string : valid_cooridinate() (coordinate the tile is placed at) # starting_port -> string : valid_port() (port on the edge of the board the player starts at) def initial_placement_check(self, tile_index, rotation, board_coordinate, starting_port): tile = self.deck.get_tile(tile_index) number_of_rotations = get_number_of_rotations(rotation) tile.rotate(number_of_rotations) return self.rule_checker.check_first_turn(self.board, tile, board_coordinate, starting_port) # performs a players first turn, returns the validity of that turn (if not valid kills player) # player_color -> string : valid_color() (the color of the player making the turn) # tile_index -> int : 0 - 34 (represents the index in all_tiles) # rotation -> int : 0, 90, 180, 270 (represents the number of roations for the given tile) # boar_coordinate -> string : valid_cooridinate() (coordinate the tile is placed at) # starting_port -> string : valid_port() (port on the edge of the board the player starts at) def player_first_turn(self, player_color, tile_index, rotation, board_coordinate, starting_port): new_player = Avatar(player_color) self.player_dictionary[player_color] = new_player first_turn_rule_check = self.initial_placement_check( tile_index, rotation, board_coordinate, starting_port) if first_turn_rule_check[LEGAL]: tile = self.deck.get_tile(tile_index) number_of_rotations = get_number_of_rotations(rotation) tile.rotate(number_of_rotations) self.board.first_turn(new_player, tile, board_coordinate, starting_port) else: self.dead_players.append(player_color) return first_turn_rule_check # checks if an players turn is legal # player_color -> string : valid_color() (the color of the player making the turn) # tile_index -> int : 0 - 34 (represents the index in all_tiles) # rotation -> int : 0 - 3 (represents the number of roations for the given tile) # boar_coordinate -> string : valid_cooridinate() (coordinate the tile is placed at) # tile_choices -> array[int] : 2 - 3 (tile options the player had to choose from) def rule_check(self, player_color, tile_index, rotation, board_coordinate, tile_choices): player = self.player_dictionary[player_color] players_tiles = self.deck.get_tiles(tile_choices) player.tiles = players_tiles tile = self.deck.get_tile(tile_index) number_of_rotations = get_number_of_rotations(rotation) tile.rotate(number_of_rotations) return self.rule_checker.check_turn(self.board, tile, board_coordinate, player) # performs a players turn, returns the result or validity of that turn (if not valid kills player) # player_color -> string : valid_color() (the color of the player making the turn) # tile_index -> int : 0 - 34 (represents the index in all_tiles) # rotation -> int : 0 - 3 (represents the number of roations for the given tile) # boar_coordinate -> string : valid_cooridinate() (coordinate the tile is placed at) # tile_choices -> array[int] : 2 - 3 (tile options the player had to choose from) def player_take_turn(self, player_color, tile_index, rotation, board_coordinate, tile_choices): rule_check = self.rule_check(player_color, tile_index, rotation, board_coordinate, tile_choices) if rule_check[LEGAL]: player = self.player_dictionary[player_color] tile = self.deck.get_tile(tile_index) number_of_rotations = get_number_of_rotations(rotation) tile.rotate(number_of_rotations) self.board.take_turn(tile, board_coordinate, player) players_killed = self.update_other_players_positions( player, board_coordinate) result = self.get_turn_results(players_killed) self.dead_players.extend(players_killed) return result else: self.dead_players.append(player_color) return rule_check #################### Private methods ####################### # returns a set of the remaining living player colors def get_living_players(self): players_set = set(self.player_dictionary.keys()) dead_players_set = set(self.dead_players) living_players_set = players_set.difference(dead_players_set) return living_players_set # given a list of player colors move those players # expectation that these players are all moveable otherwise # throws an exception def move_players(self, players_to_move): for player_color in players_to_move: player = self.player_dictionary[player_color] self.board.move_player(player) # updates the positions of the other players still on the board # given the current player and where they placed the tile on their turn # returns the players killed in this turn def update_other_players_positions(self, current_player, board_coordinate): players_killed = [] if current_player.is_player_dead(): players_killed.append(current_player.color) living_players = self.get_living_players() living_players.discard(current_player.color) players_to_move = [] for player_color in living_players: player = self.player_dictionary[player_color] if player.get_connecting_coordinate() == board_coordinate: players_to_move.append(player.color) self.move_players(players_to_move) for player_color in players_to_move: if self.player_dictionary[player_color].is_player_dead(): players_killed.append(player_color) return players_killed # given the players killed during a turn return the results of a legal move def get_turn_results(self, players_killed): result = {LEGAL: True, PLAYERS_KILLED: [], GAME_OVER: False} is_game_over = len(self.player_dictionary) - len(self.dead_players) < 2 is_tie = len(self.player_dictionary) == len(self.dead_players) if is_game_over: result[GAME_OVER] = True if is_tie: result[WINNERS] = players_killed result[LOSERS] = self.dead_players else: result[WINNERS] = self.get_living_players() result[LOSERS] = self.dead_players else: self.dead_players.extend(players_killed) result[PLAYERS_KILLED] = players_killed return result
def refresh_checker(self): self.C: RuleChecker = RuleChecker(self.T, self.A)
def test_check_first_turn(self): rc = RuleChecker() empty_board = Board() player = Avatar("white") suicide_tile = HandTile([('s1', 's2'), ('e2', 'e1'), ('n2', 'n1'), ('w1', 'w2')]) tile = HandTile([('n1', 's2'), ('n2', 'e2'), ('e1', 'w2'), ('s1', 'w1')]) # Not on edge not_the_edge = rc.check_first_turn(empty_board, suicide_tile, "c7", "w2") self.assertAlmostEqual(not_the_edge["legal"], False) self.assertAlmostEqual(not_the_edge["rules broken"], [ "tile placement is not on the board's edge", "starting port is invalid" ]) # No suicides suicide_move = rc.check_first_turn(empty_board, suicide_tile, "a1", "n1") self.assertAlmostEqual(suicide_move["legal"], False) self.assertAlmostEqual(suicide_move["rules broken"], ["tile placement is avoidable suicide"]) self.assertAlmostEqual( rc.check_first_turn(empty_board, suicide_tile, "a1", "n2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, suicide_tile, "a1", "w1")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, suicide_tile, "a1", "w2")["legal"], False) # No iterior ports allowed interior_port_move = rc.check_first_turn(empty_board, suicide_tile, "a1", "e2") self.assertAlmostEqual(interior_port_move["legal"], False) self.assertAlmostEqual(interior_port_move["rules broken"], ["starting port is invalid"]) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a1", "n2")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a1", "s2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a1", "w2")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a2", "e1")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a2", "n1")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a2", "s1")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "a2", "w1")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "b1", "e2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "b1", "n2")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "b1", "s2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "b1", "w2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "j10", "e2")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "j10", "n2")["legal"], False) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "j10", "s2")["legal"], True) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "j10", "w2")["legal"], False) empty_board.first_turn(player, tile, "a1", "n1") # No neighbors placed_on_occupied_spot = rc.check_first_turn(empty_board, tile, "a1", "s2") self.assertAlmostEqual(placed_on_occupied_spot["legal"], False) self.assertAlmostEqual(placed_on_occupied_spot["rules broken"], [ 'coordinate is already occupied', 'starting port is invalid', 'tile placement is avoidable suicide' ]) placed_tile_with_neighbors = rc.check_first_turn( empty_board, tile, "a1", "s1") self.assertAlmostEqual(placed_tile_with_neighbors["legal"], False) self.assertAlmostEqual(placed_tile_with_neighbors["rules broken"], [ 'coordinate is already occupied', 'starting port is invalid', 'tile placement is avoidable suicide' ]) self.assertAlmostEqual( rc.check_first_turn(empty_board, tile, "b1", "e2")["legal"], False)