def _compute_horizontal_edges(self, vertex: IVertex, row: int, column: int, matrix: List[List[int]]) -> None: """ Function that receives a vertex(node), and compute all the neighbour horizontal edges, looking for valid edges. :param IVertex vertex: Current vertex to be analysed. :param int row: Current row where vertex is. :param int column: Current column where vertex is. :param List[List[int]] matrix: The entire matrix. :rtype: None. """ # left edge if column - 1 >= 0: if matrix[row][column - 1] == 1: edge = Edge(vertex.vertex_id, convert_number_to_letter(row) + str(column - 1), 1) vertex.add_edge(edge) # right edge if column + 1 < self.size: if matrix[row][column + 1] == 1: edge = Edge(vertex.vertex_id, convert_number_to_letter(row) + str(column + 1), 1) vertex.add_edge(edge)
def moving_possibilities(self, player_position: str, possibilities: List[str], matrix: List[List[int]], size: int) -> None: print('Possibilities of Moving') print(colored('You are on the Yellow tile', 'yellow')) print(colored('Green tiles are the possibilities', 'green')) print(' ' * 4, end="") for column in range(size): print('{:4}'.format(column), end="") print('\n') for row in range(size): print('{:7}'.format(convert_number_to_letter(row)), end="") for column in range(size): color = 'white' attrs = ['bold'] position = convert_number_to_letter(row) + str(column) if position in possibilities: color = 'green' attrs.append('blink') elif player_position == position: color = 'yellow' attrs.append('blink') print(colored( '{:4}'.format('*' if matrix[row][column] == 1 else ' '), color, attrs=attrs), end="") print('')
def map_info(self, player: IPlayer, players: List[IPlayer], matrix: List[List[int]], size: int) -> None: foes_positions = [] print( colored( '\n {name} is currently at position: {position}, ' 'with {life} HP'.format(name=player.name, position=player.position, life=player.life), 'green')) for opponent in players: foes_positions.append(opponent.position) print( colored( 'Enemy {name}({job}) is currently at position: {position}, ' 'with {life} HP'.format(name=opponent.name, job=opponent.job.get_name(), position=opponent.position, life=opponent.life), 'red')) print(' ' * 4, end="") for column in range(size): print('{:4}'.format(column), end="") print('\n') for row in range(size): print('{:7}'.format(convert_number_to_letter(row)), end="") for column in range(size): color = 'white' attrs = ['bold'] position = convert_number_to_letter(row) + str(column) if player.position == position: color = 'green' attrs.append('blink') elif position in foes_positions: color = 'red' print(colored( '{:4}'.format('*' if matrix[row][column] == 1 else ' '), color, attrs=attrs), end="") print('\n')
def is_vertex_valid(self, row: int, column: int) -> bool: """ Returns True if vertex exists, otherwise False. :param int row: Row of the vertex. :param int column: Column of the vertex. :rtype: List[str] """ letter = convert_number_to_letter(row) vertex = self.graph_dict.get(letter + str(column)) return True if vertex.value == 1 else False
def _compute_diagonal_edges(self, vertex: IVertex, row: int, column: int, matrix: List[List[int]]) -> None: """ Function that receives a vertex(node), and compute all the neighbour diagonal edges, looking for valid edges. Remember that diagonal edges, are weighted as sqrt(2) * 1. :param IVertex vertex: Current vertex to be analysed. :param int row: Current row where vertex is. :param int column: Current column where vertex is. :param List[List[int]] matrix: The entire matrix. :rtype: None. """ if column - 1 >= 0 and row - 1 >= 0: if matrix[row - 1][column - 1] == 1: edge = Edge( vertex.vertex_id, convert_number_to_letter(row - 1) + str(column - 1), 1.414) vertex.add_edge(edge) if column + 1 < self.size and row + 1 < self.size: if matrix[row + 1][column + 1] == 1: edge = Edge( vertex.vertex_id, convert_number_to_letter(row + 1) + str(column + 1), 1.414) vertex.add_edge(edge) if column - 1 >= 0 and row + 1 < self.size: if matrix[row + 1][column - 1] == 1: edge = Edge( vertex.vertex_id, convert_number_to_letter(row + 1) + str(column - 1), 1.414) vertex.add_edge(edge) if row - 1 >= 0 and column + 1 < self.size: if matrix[row - 1][column + 1] == 1: edge = Edge( vertex.vertex_id, convert_number_to_letter(row - 1) + str(column + 1), 1.414) vertex.add_edge(edge)
def plain_map(self, matrix: List[List[int]], size: int) -> None: # Print the columns first print(' ' * 4, end="") for column in range(size): print('{:4}'.format(column), end="") print('\n') for row in range(size): print('{:7}'.format(convert_number_to_letter(row)), end="") for column in range(size): print('{:4}'.format('*' if matrix[row][column] == 1 else ' '), end="") print('')
def pick_available_position(self, selected_positions: List[str]) -> str: """ Function that will be called on game construction, to place players randomly in the map, considering that player can't start in a tile that there is already another player. :param List[str] selected_positions: The available positions to scan. :rtype: str. """ while True: row = random.randint(0, self.size - 1) column = random.randint(0, self.size - 1) vertex_valid = self.graph.is_vertex_valid(row, column) position = convert_number_to_letter(row) + str(column) if vertex_valid and position not in selected_positions: return position
def test_graph_generation(self) -> None: size = random.randint(1, 10) new_graph = Graph(size=size) new_graph.init_graph() self.assertEqual(len(new_graph.matrix), size) self.assertEqual(len(new_graph.matrix[0]), size) for i in range(0, size): for j in range(0, size): current_row = convert_number_to_letter(i) current_column = j position = current_row + str(current_column) self.assertIn(position, new_graph.graph_dict) map_value = new_graph.graph_dict.get(position) self.assertEqual(current_row, map_value.position.get('row')) self.assertEqual(current_column, map_value.position.get('column')) self.assertEqual(position, map_value.vertex_id)
def _create_matrix_dfs_traverse(self, matrix: List[List[int]], row: int, column: int, visited: List[List[bool]]) -> None: """ Private recursive method to create a matrix, using DFS preorder algorithm for traversing the matrix, and building each of the positions of it. It's a squared adjacent matrix, that will be converted into a graph, that represents the map. 0 vertexes means invalid nodes, where players can not walk on, and 1 are the valid ones. Also, it computes the edges between two valid nodes(vertexes), adopting a square logic, horizontal/vertical edges have a weight(distance) of 1, and diagonal is weighted based in sqrt(2) * 1, which is the square diagonal formula. :param List[List[int]] matrix: The squared list, that represents the matrix. :param int row: The current row that is being visited by the traversal recursive function. :param int column: The current column that is being visited by the traversal recursive function. :param List[List[int]] matrix: The squared array, that represents the matrix. :param List[List[bool]]: squared list that represents the nodes that have already been visited. :rtype: None. """ if row >= self.size or column >= self.size or visited[row][column]: return visited[row][column] = True letter_row = convert_number_to_letter(row) vertex_id = letter_row + str(column) position = {'row': letter_row, 'column': column} vertex = Vertex(vertex_id, matrix[row][column], position) if vertex.value == 1: self._compute_vertical_edges(vertex, row, column, matrix) self._compute_horizontal_edges(vertex, row, column, matrix) self._compute_diagonal_edges(vertex, row, column, matrix) self.graph_dict[vertex_id] = vertex self._create_matrix_dfs_traverse(matrix, row + 1, column, visited) self._create_matrix_dfs_traverse(matrix, row, column + 1, visited)
def test_convert_number_to_letter(self) -> None: self.assertEqual(convert_number_to_letter(0), 'A') self.assertEqual(convert_number_to_letter(1), 'B') self.assertEqual(convert_number_to_letter(17), 'R') self.assertEqual(convert_number_to_letter(25), 'Z')