def next_move(self, player, board): if player.tile is None: for x, y in revolve(10, True): port = None for p in Port: coords = get_coordinates_in_direction(x, y, p.direction) if board.get_tile_at(*coords) is OutOfBounds: port = p break tile = player.tile_hand[2] placement = InitialPlacement(tile.index, tile.rotation.value, player.color.value, x, y, port.name) if all( r.is_valid(placement, board, player) for r in rules.ALL): return placement else: x, y = get_coordinates_in_direction(player.tile.x, player.tile.y, player.port.direction) tile = player.tile_hand[0] return IntermediatePlacement(tile.index, tile.rotation.value, player.color.value, x, y)
def _get_player_state(self, player: Player): """ Determines the state of the given player in the game. :return: the state of the player :rtype: PlayerState """ # short-circuit if the player hasn't made their first move, yet if player.tile is None: return PlayerState.ALIVE adjacent = self.board.get_tile_at(*get_coordinates_in_direction( player.tile.x, player.tile.y, player.port.direction)) if adjacent is not None and adjacent is not OutOfBounds: # advance the player onto the adjacent tile and recur player.tile = adjacent player.port = adjacent.get_exit_port(player.port.neighbor) return self._get_player_state(player) elif adjacent is OutOfBounds: death_tile = (player.tile, player.port) if death_tile in self.start_positions: # a player has collided if they end at another's start position return PlayerState.COLLIDED return PlayerState.DEAD elif adjacent is None: return PlayerState.ALIVE
def is_valid(self, next_move, board, player): if next_move.is_initial: for direction in Direction: tile = board.get_tile_at(*get_coordinates_in_direction( next_move.x, next_move.y, direction)) if tile is not OutOfBounds and tile is not None: return False, self.ERROR_MSG return True, None
def is_valid(self, next_move, board, player): if not next_move.is_initial: correct_x, correct_y = get_coordinates_in_direction( player.tile.x, player.tile.y, player.port.direction) if next_move.x != correct_x or next_move.y != correct_y: return False, self.ERROR_MSG return True, None
def _will_survive(self, tile, x, y, entry_port, board): exit_port = tile.get_exit_port(entry_port) next_x, next_y = get_coordinates_in_direction(x, y, exit_port.direction) next_tile = board.get_tile_at(next_x, next_y) if next_tile is OutOfBounds: # the player moves off the board return False elif next_tile is None: # the player reaches an unoccupied space on the board return True else: return self._will_survive(next_tile, next_x, next_y, exit_port.neighbor, board)
def is_valid(self, next_move, board, player): # has the player at the exit port tile = next_move.build_tile() if player.tile is None else player.tile port = tile.get_exit_port( next_move.port) if player.port is None else player.port if self._will_survive(tile, next_move.x, next_move.y, port.neighbor, board): # short circuit if the player's move is valid return True, None x, y = get_coordinates_in_direction(tile.x, tile.y, port.direction) # otherwise, figure out if they have any survivable moves if any( self._will_survive(t, x, y, port.neighbor, board) for t in self._possible_tiles(player)): return False, self.ERROR_MSG # there are no survivable moves, allow this one return True, None