# Title: Project 2 - Determine if a cell starts burning # Author: Rory Healy # Date created - 9th May 2019 def get_adjacent_cells(b_grid, wind): '''Returns a list of cells that are considered adjacent to the cells that are currently burning.''' # Note: all_adjacent_cells includes cells that aren't in all_cells_list. # Hence, adjacent_cells_list is returned once these invalid cells have # been removed. all_adjacent_cells = [] adjacent_cells_list = [] all_cells_list = [] burning_cells = [] # Sets up a matrix of cells with their respective (i, j) values. for row in range(len(b_grid)): for column in range(len(b_grid)): all_cells_list.append([row, column]) # Adds all cells around the burning cells to all_adjacent_cells. for row in range(len(b_grid)): for column in range(len(b_grid)): if b_grid[row][column] is True: all_adjacent_cells.append([row - 1, column - 1]) all_adjacent_cells.append([row - 1, column]) all_adjacent_cells.append([row - 1, column + 1]) all_adjacent_cells.append([row, column + 1]) all_adjacent_cells.append([row + 1, column + 1]) all_adjacent_cells.append([row + 1, column]) all_adjacent_cells.append([row + 1, column - 1]) all_adjacent_cells.append([row, column - 1]) burning_cells.append([row, column]) # Adds cells to all_adjacent_cells based on the wind. for burning_cell in burning_cells: if wind == 'N': row_adjustment = -2 for column_adjustment in [-1, 0, 1]: all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'NW': for row_adjustment in [-1, -2]: for column_adjustment in [-1, -2]: if (row_adjustment, column_adjustment) != (-1, -1): all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'W': column_adjustment = -2 for row_adjustment in [-1, 0, 1]: all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'SW': for row_adjustment in [-1, -2]: for column_adjustment in [1, 2]: if (row_adjustment, column_adjustment) != (-1, 1): all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'S': row_adjustment = 2 for column_adjustment in [-1, 0, 1]: all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'SE': for row_adjustment in [1, 2]: for column_adjustment in [1, 2]: if (row_adjustment, column_adjustment) != (1, 1): all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'E': column_adjustment = 2 for row_adjustment in [-1, 0, 1]: all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) elif wind == 'NE': for row_adjustment in [-1, -2]: for column_adjustment in [1, 2]: if (row_adjustment, column_adjustment) != (-1, 1): all_adjacent_cells.append([burning_cell[0] + row_adjustment, burning_cell[1] + column_adjustment]) # Removes cells from adjacent_cells_list that don't fit the size of the # grid, are already in adjacent_cells_list, or are in burning_cells. for cell in all_adjacent_cells: if cell in all_cells_list: if cell not in burning_cells: if cell not in adjacent_cells_list: adjacent_cells_list.append(cell) return adjacent_cells_list def get_height_impact_model(h_grid, burning_cells): '''Creates a matrix of the same size as h_grid with the values of each cell (i, j) equal to the factor by which ignition_factor is affected by (e.g. [[0.5], [0.5], [2], [1]]). This is used so that the ignition factor for each cell can be multiplied by this factor that is influenced by the height.''' all_cells_list = [] height_impact_list = [] # Sets up a matrix of cells with their respective (i, j) values, and # generates a black matrix height_impact_list, which is to be filled in # later. for row in range(len(h_grid)): height_impact_list.append([]) for column in range(len(h_grid)): all_cells_list.append([row, column]) height_impact_list[row].append([]) # Generates a value for each cell based on the relative value of the height # of that cell to the height of the burning cells- either 0.5, 1, or 2. for x in range(len(burning_cells)): # Generates a list of adjacent cells for each burning cell. burning_cell_x = burning_cells[x] row = burning_cell_x[0] column = burning_cell_x[1] directly_adjacent_cells = [] directly_adjacent_cells.append([row - 1, column - 1]) directly_adjacent_cells.append([row - 1, column]) directly_adjacent_cells.append([row - 1, column + 1]) directly_adjacent_cells.append([row, column + 1]) directly_adjacent_cells.append([row + 1, column + 1]) directly_adjacent_cells.append([row + 1, column]) directly_adjacent_cells.append([row + 1, column - 1]) directly_adjacent_cells.append([row, column - 1]) # Finds the height of the burning cell currently in the loop and # compares it to the cells surrounding this cell, and assigns the cell # an ignition multiplication factor. burning_cell_x_i = burning_cell_x[0] burning_cell_x_j = burning_cell_x[1] burning_cell_x_height = h_grid[burning_cell_x_i][burning_cell_x_j] # Removes cells from directly_adjacent_cells that don't fit the size of # the grid. direct_adjacent_cells = [] for cell in directly_adjacent_cells: if cell in all_cells_list: direct_adjacent_cells.append(cell) for cell in direct_adjacent_cells: cell_i = cell[0] cell_j = cell[1] cell_height = h_grid[cell_i][cell_j] if cell_height < burning_cell_x_height: height_impact_list[cell_i][cell_j] = 0.5 elif cell_height == burning_cell_x_height: height_impact_list[cell_i][cell_j] = 1 elif cell_height > burning_cell_x_height: height_impact_list[cell_i][cell_j] = 2 return height_impact_list def check_ignition(b_grid, f_grid, h_grid, i_threshold, w_direction, i, j): '''Returns True or False if a cell at (i, j) will start burning in the next timestep based on the factors influencing it's likelihood to burn, as described to the right.''' # Defines values to be used in this function based on the inputs. fuel_load = f_grid[i][j] wind = w_direction ignition_threshold = i_threshold input_cell_is_burning = b_grid[i][j] burning_cells = [] cells_list = [] for row in range(len(b_grid)): for column in range(len(b_grid)): if b_grid[row][column] is True: burning_cells.append([row, column]) for row in range(len(b_grid)): for column in range(len(b_grid)): cells_list.append([row, column]) # Gets the cells adjacent to the burning cells, and the impact that the # height has on the ignition factor of each cell. adjacent_cells = get_adjacent_cells(b_grid, wind) height_model = get_height_impact_model(h_grid, burning_cells) # Adds all cells around the input cell to directly_adjacent_cells. Note # that directly_adjacent_cells contains cells outside the matrix, whereas # direct_cells_list does not. directly_adjacent_cells = [] direct_cells_list = [] directly_adjacent_cells.append([i - 1, j - 1]) directly_adjacent_cells.append([i - 1, j]) directly_adjacent_cells.append([i - 1, j + 1]) directly_adjacent_cells.append([i, j + 1]) directly_adjacent_cells.append([i + 1, j + 1]) directly_adjacent_cells.append([i + 1, j]) directly_adjacent_cells.append([i + 1, j - 1]) directly_adjacent_cells.append([i, j - 1]) # Removes cells from directly_adjacent_cells that don't fit the size of the # grid. for cell in directly_adjacent_cells: if cell in cells_list: direct_cells_list.append(cell) # Calculates the ignition factor. ignition_factor = 0 for cell in direct_cells_list: if cell in adjacent_cells: ignition_factor += 1 ignition_factor = height_model[i][j] * ignition_factor # Determines what to return based on ignition_factor, fuel_load and # input_cell_is_burning. if (input_cell_is_burning is True) and (fuel_load > 0): return True elif ignition_factor > ignition_threshold: return True return False