226 lines
10 KiB
Python
226 lines
10 KiB
Python
|
# 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
|