469 lines
23 KiB
Markdown
469 lines
23 KiB
Markdown
# Assignment Specification
|
||
|
||
Below is the assignment specification, in full, slightly edited for context and
|
||
appearence.
|
||
|
||
## Introduction
|
||
|
||
Computers can be used to build models of complex real world systems such as the
|
||
weather, traffic and stockmarkets. Computer models can help us to understand the
|
||
dynamics of these real world systems, and to make decisions about them. For
|
||
example, a model that can predict Saturday's weather could help us decid
|
||
whether to go to the beach or not. A traffic model could help us plan where to
|
||
build a new road to reduce traffic jams. A model of the stockmarket could help
|
||
us decide when to buy and sell shares.
|
||
|
||
In this project, you will build a simple model of a bushfire spreading across a
|
||
landscape represented as a two-dimensional grid. The speed and direction that a
|
||
bushfire will spread in is affected by many factors, including the amount and
|
||
type of fuel (trees) available, the slope of the land, and the direction of the
|
||
wind. Your model will help forecast how much damage (number of grid squares
|
||
burnt) a fire will do before it burns out.
|
||
|
||
Models like this (but much more complicated!) are used to help predict which way
|
||
a fire might spread, to assess where high risk fires are most likely to occur,
|
||
and help understand how the damage cause by fires can be reduced via management
|
||
practices. See Phoenix rapid fire for an example of a much more complex model
|
||
(developed at the University of Melbourne).
|
||
|
||
In this project we will look at three different problems related to a bushfire
|
||
|
||
- How to build a bushfire model from a data file.
|
||
- How to determine if a cell in a specific location will ignite.
|
||
- How to model the spread of a bushfire.
|
||
|
||
You will also need to write and submit a set of test cases for evaluating
|
||
the model.
|
||
|
||
### The bushfire model
|
||
|
||
We model a bushfire as occurring in a square grid made up of M by M cells. The
|
||
cell (i, j) refers to the cell in the ith row and the jth column of the grid.
|
||
Each cell typically has eight adjacent cells (horizontally, vertically and
|
||
diagonally). Cells on the edge of the grid are adjacent to only five other
|
||
cells; cells in the corners of the grid are adjacent to only three other cells.
|
||
For convenience, we take the top of the grid to be North, the right side to
|
||
East, the bottom to be South and the left side to be West. See
|
||
[images/bushfire_model.png](../images/bushfire_model.png) for reference.
|
||
|
||
Each cell in the M by M grid has several attributes:
|
||
|
||
- **fuel load**: the amount of combustible material (trees, leaf litter, etc) in
|
||
that cell. The fuel load of a cell is represented as a non-negative integer,
|
||
where 0 equates to no combustible material.
|
||
- **height**: the elevation of the cell. Height is represented as a positive
|
||
integer (a cell with height 3 is higher than a cell with height 2, which is in
|
||
turn higher than a cell with height 1, and so on). Fires will tend to spread
|
||
more rapidly uphill, and more slowly downhill, compared to flat ground.
|
||
- **burning**: a Boolean value indicating whether the cell is currently burning
|
||
or not. A cell can only be burning if it's fuel load is greater than 0.
|
||
|
||
In addition, the entire grid is characterised by three further attributes:
|
||
|
||
- **ignition threshold**: how combustible the landscape is (for instance, a dry
|
||
landscape would be more combustible than a wet landscape, and have a lower
|
||
ignition threshold). The ignition threshold is represented by an integer
|
||
greater than 0. A non-burning cell will start burning if its ignition
|
||
factor (explained below) is greater than or equal to the ignition threshold.
|
||
- **ignition factor**: the intensity of fire around a particular non-burning
|
||
cell at a given point in time that, in combination with the ignition threshold
|
||
described above, will be used to determine whether a cell will start burning.
|
||
The ignition factor is floating point number; details of how to calculate the
|
||
ignition factor are provided in the following sections.
|
||
- **wind direction**: if a wind is blowing, it can carry embers that allow a
|
||
fire to spread more rapidly in a particular direction. Wind may blow from one
|
||
fire to directions: North, Northeast, East, Southeast, South, Southwest, West
|
||
or Northwest (abbreviated N, NE, E, SE, S, SW, W, NW) or there may be no wind.
|
||
How the wind affects ignition will be explained further.
|
||
|
||
## Part 1 - Parse a bushfire scenario file
|
||
|
||
Your task is to write a function `parse_scenario(filename)` that parses a file
|
||
with the structure described below, validates the contents and returns either a
|
||
dictionary containing all values required to specify a model scenario if the
|
||
contents are valid, or `None` if any of the contents are invalid.
|
||
|
||
The structure of the file is as follows:
|
||
|
||
- an integer specifying the width and height (M) of the square landscape grid;
|
||
- M lines, each containing M integer values (separated by commas), defining the
|
||
initial fuel load of the landscape (a visual representation of the M by
|
||
M grid);
|
||
- M lines, each containing M integer values (separated by commas), defining the
|
||
height of the landscape (again, a visual representation of the M by M grid);
|
||
- an integer specifying the ignition threshold for this scenario;
|
||
- a one or two character string specifying the wind direction for this scenario
|
||
(or `None` if there is no wind); and
|
||
- one or more lines, each containing the (i, j) coordinates (row number, column
|
||
number) of a cell which is burning at the start of the simulation.
|
||
|
||
For example, the file [bushfire-0.txt](../data/bushfire-0.txt) specifies a 2 by
|
||
2 landscape:
|
||
|
||
- there is an initial fuel load of 2 in three of the four cells, with a fuel
|
||
load of 0 in the cell (1, 0);
|
||
- the height of all cells in the first column (j = 0) is 1, while the height of
|
||
all cells in the second column (j = 1) is 2 (i.e., the landscape slopes up
|
||
toward the East);
|
||
- the dimensions of the grid are a positive integer;
|
||
- the ignition threshold is a positive integer not greater than eight;
|
||
- the wind direction is valid; and
|
||
- the coordinates of the burning cells are (a) located on the landscape, and (b)
|
||
have non-zero initial fuel load.
|
||
|
||
If all values are valid, your function should return a dictionary with key/value
|
||
pairs as follows:
|
||
|
||
- `f_grid`: a list of lists (of dimensions M by M);
|
||
- `h_grid`: a list of lists (of dimensions M by M);
|
||
- `i_threshold`: an integer;
|
||
- `w_direction`: a string or `None`; and
|
||
- `burn_seeds`: a list of tuples.
|
||
|
||
If there is no wind, `w_direction` can be either an empty string `''` or `None`.
|
||
If any values are invalid, your function should return `None`.
|
||
|
||
For example:
|
||
|
||
>>> parse_scenario('data/bushfire-0.txt')
|
||
|
||
{'f_grid': [[2, 2], [0, 2]], 'h_grid': [[1, 2], [1, 2]], 'i_threshold': 1, 'w_direction': 'N', 'burn_seeds': [(0, 0)]}
|
||
|
||
>>> parse_scenario('data/bushfire-1.txt')
|
||
|
||
{'f_grid': [[1, 2, 1], [0, 1, 2], [0, 0, 1]], 'h_grid': [[1, 1, 1], [2, 1, 2], [3, 2, 2]], 'i_threshold': 1, 'w_direction': 'N', 'burn_seeds': [(1, 1)]}
|
||
|
||
## Updating the model
|
||
|
||
The state of the bushfire model is defined by the attributes (fuel load, height,
|
||
burning, ignition threshold and wind direction) described in a previous section.
|
||
Of these, fuel load and burning status may change over time as the bushfire
|
||
spreads. Height, ignition threshold and wind direction are fixed and never
|
||
change.
|
||
|
||
The state of the model is updated in discrete timesteps, t = 0, 1, 2, ...,
|
||
and at each timestep, the following things happen:
|
||
|
||
- If a cell is currently burning, it's fuel load will be reduced by one in the
|
||
following timestep. If this will result in its fuel load reaching zero, it
|
||
will stop burning in the following timestep.
|
||
- If a cell is not currently burning, it may start burning, depending on its
|
||
proximity to other cells which are burning in this timestep. The rules
|
||
describing how to determine if a cell catches fire are described in the
|
||
next section.
|
||
|
||
Note, the future state of each cell in time t + 1 is determined on the basis of
|
||
the current state of the grid at time t. We stop updating the model when no
|
||
cells are burning, as the state will not change after this point.
|
||
|
||
### Determining when a cell catches fire (simple)
|
||
|
||
To determine whether a cell (i, j) catches fire, we calculate its ignition
|
||
factor and compare this to the landscape's ignition threshold. As stated above,
|
||
a cell will catch fire if its ignition factor is greater than or equal to the
|
||
ignition threshold. A cell must be currently not burning and have a fuel load
|
||
greater than 0 in order to catch fire.
|
||
|
||
We will start by considering the simplest case: a flat landscape with no wind in
|
||
which cell (i, j) is not currently burning. In this case, each cell adjacent to
|
||
(i, j) that is burning contributes 1 point to (i, j)'s ignition factor. Thus, if
|
||
the ignition threshold is 1, (i, j) will start burning if it is adjacent to at
|
||
least one burning cell. If the ignition threshold is 2, (i, j) will start
|
||
burning only if it is adjacent to at least two burning cells.
|
||
|
||
Consider the sequence of landscape states shown in
|
||
[simple_bushfire_model.png](../images/simple_bushfire_model.png), in
|
||
which all cells are of the same height, there is no wind, and the ignition
|
||
threshold is 1. At the first timestep (t = 0), the two cells (0, 0) and (0, 1)
|
||
are burning. During this timestep, the fuel load of each of these two cells will
|
||
decrease by one (causing the fire in (0, 0) to stop burning in the next time
|
||
step, t = 1). If we then consider at the surrounding cells, (1, 0) has a fuel
|
||
load of 0, so it cannot catch fire. Cells (0, 2), (1, 1) and (1, 2) each have a
|
||
fuel load greater than 0 and are adjacent to one of the currently burning cells,
|
||
(0, 1), therefore they will start burning in the next time step (t = 1).
|
||
|
||
The example in
|
||
[simple_bushfire_model_2.png](../images/simple_bushfire_model_2.png) is
|
||
identical to that in the previous example, but the ignition threshold is now 2,
|
||
meaning that each non-burning cell needs to be adjacent to two or more burning
|
||
cells in order to start burning. Therefore, cells (0, 2) and cells (1, 2) will
|
||
not start burning at t = 1, as they were only adjacent to a single burning cell
|
||
at t = 0.
|
||
|
||
Only cells that are located within the bounds of the landscape grid can
|
||
contribute to a cell's ignition factor. Thus, a cell located in the corner of a
|
||
grid will, in this simple case, only have three adjacent cells that may cause it
|
||
to start burning.
|
||
|
||
### Determining when a cell catches fire (height included)
|
||
|
||
Height and wind modify can modify the calculation of the basic ignition factor
|
||
described in the previous section. The effect of landscape height is described
|
||
in this section.
|
||
|
||
On a flat landscape, where neighbouring cells are of the same height, each
|
||
burning cell contributes 1 point to an adjacent non-burning cell's
|
||
ignition factor.
|
||
|
||
However, bushfires tend to spread more rapidly uphill, therefore if a cell
|
||
(i, j) has height that is greater than that of an adjacent burning cell, that
|
||
cell will contribute twice as much (i.e., 2 points) to (i, j)'s ignition factor.
|
||
Conversely, bushfires tend to spread more slowly downhill, therefore an adjacent
|
||
burning cell with height greater than (i, j)'s height will contribute only half
|
||
as much (i.e., 0.5 points) to (i, j)'s ignition factor.
|
||
|
||
In the sequence shown in
|
||
[height_bushfire_model.png](../images/height_bushfire_model.png), the height of
|
||
each cell is indicated by a small blue number. No wind is blowing and the
|
||
ignition threshold of the landscape is 2. At the first timestep (t = 0), a
|
||
single cell (0, 0) is burning. The cell to the South of it (1, 0) has a fuel
|
||
load of 0 and hence cannot catch fire. On a flat landscape, the other two
|
||
adjacent cells (0, 1) and (1, 1) would not catch fire either, as their ignition
|
||
factor would only be 1 (from the single burning cell (0, 0)), below the ignition
|
||
threshold of 2. However, in this landscape, cells (0, 1) and (1, 1) are higher
|
||
than cell (0, 0), therefore its contribution to their ignition factor is doubled
|
||
to 2 points, high enough to equal the landscape's ignition threshold and cause
|
||
them to start burning in the following timestep (t = 1).
|
||
|
||
In constrast, the top-right cell (0, 2) will escape being burnt in timestep
|
||
t = 2 (and beyond) as it is lower than the surrounding cells, hence they each
|
||
contribute only 0.5 points to its ignition factor. Thus, even when all three
|
||
surrounding cells are burning, (0, 2)'s ignition factor is only 1.5, below the
|
||
landscape ignition threshold of 2.
|
||
|
||
### Determining when a cell catches fire (wind included)
|
||
|
||
Wind can carry burning embers that allow a fire to spread more rapidly in a
|
||
particular direction. If a wind is blowing, up to three additional cells are
|
||
considered to be adjacent to (i, j) for the purpose of calculating its
|
||
ignition factor.
|
||
|
||
For example, as shown in [wind_example.png](../images/wind_example.png), if a
|
||
wind is blowing from the North, the cell two cells above (i, j) and the cells
|
||
immediately to the left and right of this cell are considered adjacent to (i, j)
|
||
(i.e., cells (i − 2, j − 1), (i − 2, j) and (i − 2, j + 1)). If any of these
|
||
additional cells are burning, they will also contribute when calculating
|
||
(i, j)'s ignition factor.
|
||
|
||
If a wind is blowing from the Southwest, the cell two cells below and to the
|
||
left of (i, j) and the cells immediately above and to the right of this cell are
|
||
considered adjacent to (i, j). That is, cells (i + 1, j − 2), (i + 2, j − 2) and
|
||
(i + 2, j − 1). Of course, these additional cells must be within the bounds of
|
||
the landscape in order to have any effect, as in the simple case in the previous
|
||
section.
|
||
|
||
The sequence shown in
|
||
[wind_bushfire_model.png](../images/wind_bushfire_model.png) is identical to the
|
||
simple example shown in the previous section (on a flat landscape, with ignition
|
||
threshold of 2) except that the wind is now blowing from the Northwest. As a
|
||
consequence, cell (0, 0) is considered adjacent to (1, 2), which therefore has
|
||
an ignition factor of 2 (as (0, 1) is also adjacent and burning) and hence will
|
||
start burning at t = 1. In addition, (0, 0) and (0, 1) are also both considered
|
||
adjacent to (2, 2), which will also start burning at t = 1. Bushfires spread
|
||
much more rapidly when the wind is blowing!
|
||
|
||
When considering the joint effects of height and wind, you should compare the
|
||
heights of (i, j) and each of its adjacent cells on a pairwise basis,
|
||
disregarding the heights of any other surrounding cells. For example, if (0, 0)
|
||
was higher than (2, 2) and (0, 1) was lower than (2, 2) then they would
|
||
contribute 0.5 points and 2 points respectively to (2, 2)'s ignition factor,
|
||
irrespective of the heights of the intervening cells (e.g., (1, 1)).
|
||
|
||
## Part 2 - Determine if a cell starts burning
|
||
|
||
Based on the rules described earlier, your task is to write a function
|
||
`check_ignition(b_grid, f_grid, h_grid, i_threshold, w_direction, i, j)` that
|
||
takes as arguments the burning state `b_grid` (at time t), current fuel load
|
||
`f_grid` (at time t), height `h_grid`, ignition threshold `i_threshold`, wind
|
||
direction `w_direction` and coordinates `i` and `j` of a cell, and returns
|
||
`True` if that cell will catch fire at time t + 1 and `False` otherwise.
|
||
|
||
The arguments are of the following types:
|
||
|
||
- `b_grid`: a list of lists of Boolean values (of dimensions M by M)
|
||
- `f_grid`: a list of lists of integers (of dimensions M by M)
|
||
- `h_grid`: a list of lists of integers (of dimensions M by M)
|
||
- `i_threshold`: an integer
|
||
- `w_direction`: a string (if wind is blowing), otherwise `None` (if no wind
|
||
is blowing)
|
||
- `i` and `j`: integers (i, j < M)
|
||
|
||
You may assume that all arguments are valid, as defined in Part 1.
|
||
|
||
For example:
|
||
|
||
>>> check_ignition([[True, False], [False, False]], [[2, 2], [2, 2]], [[1, 1], [1, 1]], 1, 'N', 0, 1)
|
||
|
||
True
|
||
|
||
>>> check_ignition([[True, False], [False, False]], [[2, 0], [2, 2]], [[1, 1], [1, 1]], 1, 'N', 1, 0)
|
||
|
||
True
|
||
|
||
>>> check_ignition([[True, True, False], [False, False, False], [False, False, False]], [[1, 1, 1], [1, 1, 1], [1, 0, 0]], [[2, 2, 1], [2, 3, 1], [1, 1, 1]], 1, None, 0, 2)
|
||
|
||
False
|
||
|
||
>>> check_ignition([[True, True, False], [False, False, False], [False, False, False]], [[1, 1, 1], [1, 1, 1], [1, 0, 0]], [[2, 2, 1], [2, 3, 1], [1, 1, 1]], 2, None, 1, 1)
|
||
|
||
True
|
||
|
||
## Part 3 - Run the model
|
||
|
||
Your task is to write a function `run_model(f_grid, h_grid, i_threshold,
|
||
w_direction, burn_seeds)` that takes as arguments the initial fuel load `f_grid`
|
||
(i.e., at time t = 0), height `h_grid`, ignition threshold `i_threshold`, wind
|
||
direction `w_direction` and a list of cells `burn_seeds` that are burning at
|
||
time t = 0, and returns a tuple containing (a) the final state of the landscape
|
||
once the fire has stopped burning, and (b) the total number of cells that have
|
||
been burnt by the fire (including any initially burning cells in `burn_seeds`).
|
||
|
||
The arguments are of the following types:
|
||
|
||
- `f_grid`: a list of lists (of dimensions M by M)
|
||
- `h_grid`: a list of lists (of dimensions M by M)
|
||
- `i_threshold`: an integer
|
||
- `w_direction`: a string
|
||
- `burn_seeds`: a list of integer tuples (i, j) where i, j < M
|
||
|
||
You may assume that all arguments are valid, as defined in previous parts.
|
||
|
||
You may find it helpful to define one or more additional functions that carry
|
||
out a single step of the model run, determining the new burning state and fuel
|
||
load at time t + 1 on the basis of the model state at time t.
|
||
|
||
For example:
|
||
|
||
>>> run_model([[2, 2], [2, 2]], [[1, 1], [1, 1]], 1, 'N', [(0, 0)])
|
||
|
||
([[0, 0], [0, 0]], 4)
|
||
|
||
>>> run_model([[2, 0], [0, 2]], [[1, 1], [1, 1]], 2, 'S', [(0, 0)])
|
||
|
||
([[0, 0], [0, 2]], 1)
|
||
|
||
## Part 4 - Test cases
|
||
|
||
In addition to implementing your solutions, you are also required to submit a
|
||
set of test cases that can be used to test your Part 3 `run_model` function.
|
||
|
||
You should aim to make your test cases as complete as possible. That is, they
|
||
should be sufficient to pick up incorrect implementations of the model.
|
||
|
||
Your set of test cases may assume that the input passed to your function will be
|
||
of the correct types and will be well-formed.
|
||
|
||
Your test cases suite will be evaluated by running it on several known incorrect
|
||
implementations, in which it should detect incorrect behaviour; i.e., returning
|
||
an incorrect final state of the landscape and/or number of cells burnt.
|
||
|
||
You should specify your test cases as a series of calls to the function
|
||
`test_run_model(run_model, input_args, expected_return_value)`, where the first
|
||
argument `run_model` is the model you created in Part 3, the second argument,
|
||
`input_args` contains a list of `f_grid`, `h_grid`, `i_threshold`,
|
||
`w_direction`, `burn_seeds` representing the call to the function `run_model`
|
||
(described in Part 3) and `expected_return_value` is the expected return from
|
||
the function `run_model`, namely a list containing the final state of the
|
||
landscape once the fire has stopped burning, and the total number of cells that
|
||
have been burnt by the fire as in Part 3).
|
||
|
||
`test_run_model` will return `True` if the model successfully passes the test,
|
||
and `False` otherwise.
|
||
|
||
For example, using the first two examples from Part 2:
|
||
|
||
>>> test_run_model(run_model, [[[2, 2], [2, 2]], [[1, 1], [1, 1]], 1, 'N', [(0, 0)]],
|
||
[[[0, 0], [0, 0]], 4])
|
||
|
||
True
|
||
|
||
>>> test_run_model(run_model, [[[2, 0], [0, 2]], [[1, 1], [1, 1]], 2, 'S', [(0, 0)]],
|
||
[[[0, 0], [0, 2]], 1])
|
||
|
||
True
|
||
|
||
## Part 5 - Bonus
|
||
|
||
The final part is for bonus marks, and is deliberately quite a bit harder than
|
||
the four basic questions (and the number of marks on offer is deliberately not
|
||
commensurate with the amount of effort required — bonus marks aren't meant to be
|
||
easy to get!). Only attempt this is you have completed the earlier questions,
|
||
and are up for a challenge!
|
||
|
||
In this question, you will use the bushfire model to determine the optimal cell
|
||
or cells in a landscape in which to conduct a prescribed burn in order to best
|
||
protect a town from a future bushfire of unknown timing and origin.
|
||
|
||
For this question, we modify our original definition of a landscape to include a
|
||
town cell, containing a town. The town cell has a non-zero fuel load; that is,
|
||
the town can catch fire.
|
||
|
||
### Prescribed burns
|
||
|
||
A prescribed burn is a controlled fire used as part of forest management in
|
||
order to reduce the risk of future uncontrolled fires.
|
||
|
||
In our simulation model, the rules of a prescribed burn are that it will only
|
||
occur on a day with no wind, and will commence on a single prescribed burn cell
|
||
with a non-zero fuel load. A prescribed burn will not be conducted on the cell
|
||
containing the town.
|
||
|
||
A prescribed burn spreads just like a normal bushfire; however, due to the
|
||
controlled nature of the fire, any burning cell contributes only half as many
|
||
points to the ignition factor of adjacent cells as it ordinarily would (taking
|
||
slope into account). That is, if it would normally contribute 0.5, 1 or 2
|
||
points, it will now only contribute 0.25, 0.5, or 1 points. This reduction
|
||
applies both to the original prescribed burn cell and to any cell that
|
||
subsequently catches fire during the prescribed burn. As with a normal bushfire,
|
||
a prescribed burn will continue until no cells remain on fire.
|
||
|
||
### Scoring prescribed burn cells
|
||
|
||
We filter out invalid prescribed burn cells and score the remaining valid
|
||
prescribed burn cells as follows:
|
||
|
||
- Any prescribed burn cell that results in the the town cell catching fire is
|
||
deemed invalid.
|
||
- Following the completion of a prescribed burn, we will consider scenarios in
|
||
which potential bushfires start in any (single) seed cell with a non-zero fuel
|
||
load (after the prescribed burn), except for the town cell, on a day with any
|
||
possible wind conditions. Thus, for a landscape of dimensions M, we will
|
||
consider up to 9 × (M^2 − 2) bushfire scenarios. 2 is subtracted because we
|
||
don't seed a bushfire on the town cell or cells with zero fuel load, of which
|
||
there is at least one, being the cell in which the prescribed burn was
|
||
conducted. For each seed cell there are 9 possible wind directions to
|
||
consider, including no wind.
|
||
- Valid prescribed burn cells are scored according to the proportion of
|
||
scenarios in which the town cell caught fire.
|
||
|
||
The optimal cell or cells for prescribed burning are those with the lowest
|
||
score; that is, that have been more effective at protecting the town.
|
||
|
||
In the first example below, there are 4 cells with a non-zero fuel load, one of
|
||
which (1, 1) is the town cell. Therefore there are three cells in which a
|
||
prescribed burn can be conducted. None of these will result in the town being
|
||
burnt, therefore they are all valid. When we test the 18 possible bushfire
|
||
scenarios, we find that for one valid prescribed burn cell (0, 1), all
|
||
subsequent bushfires will result in the town catching fire. For the other two
|
||
prescribed burn cells ((0, 0) and (1, 0)), only half of the subsequent bushfires
|
||
will result in the town catching fire; thus, either of these would be the
|
||
optimal location in which to carry out a prescribed burn in this landscape.
|
||
|
||
Your task is to write a function `plan_burn(f_grid, h_grid, i_threshold,
|
||
town_cell)` that determines the optimal prescribed burn cell or cells. `f_grid`,
|
||
`h_grid` and `i_threshold` are all as defined in Parts 2 and 3. `town_cell` is a
|
||
tuple containing the coordinates of the town cell.
|
||
|
||
Your function should return a sorted list containing the coordinates of the
|
||
optimal prescribed burn cell or cells, as defined above. If there are no valid
|
||
prescribed burn cells, this list will be empty.
|
||
|
||
For example:
|
||
|
||
>>> plan_burn([[2, 2], [1, 2]], [[1, 2], [1, 2]], 2, (1, 1))
|
||
|
||
[(0, 0), (1, 0)]
|
||
|
||
>>> plan_burn([[0, 0, 0, 0, 0], [0, 2, 2, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 1, 0], [1, 0, 0, 0, 0]], [[2, 2, 2, 2, 2], [2, 1, 2, 2, 2], [2, 2, 2, 2, 2], [2, 2, 2, 1, 2], [2, 2, 2, 2, 2]], 2, (3, 3))
|
||
|
||
[(1, 1), (1, 2), (2, 3)]
|