For this assignment, you will create a Python source file containing a Python function(s) implementing each of the problems described below. If you find it useful for any of the problems in this assignment, you may define additional helper functions that your primary function for that problem calls to solve a sub-problem. Definitions for these helper functions should be included in the same Python source file as the primary function they help. You should store a source file for each problem in a folder named pa10.
Note: You are responsible for protecting your solutions to these problems from being seen by other students either physically (e.g., by looking over your shoulder) or electronically. (More information can be found in the instructions for Programming Assignment 2.)
In this assignment, you will develop a simple graphical simulation that analyzes how forest fires spread and how forests regrow after fires. Each time step of the simulation represents one day.
On each day, if a tree is on fire, it may turn to ashes. If a tree is ashes, it may turn into a shoot (i.e. baby tree). If a tree is a shoot, it may starting growing. If a tree is growing, it may reach maturity. If a tree is mature and at least one of its neighbors is on fire, it may ignite (i.e. catch on fire).
This simulation will show how the forest evolves over time, represented by a square 15 × 15 matrix.
Here is a sample of what the first eight "days" of the simulation might look like:
Top row: Days 1-4 of simulation. Bottom row: Days 5-8 of simulation.
NOTE: Your results might not match these exactly since our seed may be
different.
Each snapshot above is a time step of the simulation shown in a 300 × 300 window (in pixels). Notice that the window is "divided" up into 15 × 15 squares. Each of these 225 squares represents one tree in the simulated forest.
To perform the simulation, you will need to use the Canvas object in PythonLabs to display the simulation.
In addition to the display, you will also need to use random number generators in this simulation. Suppose an event occurs with a chance of 20 percent. We can write a function that returns True if the event occurs and False otherwise given that the chance of the event happening is 20%:
def event(): if randint(0,99) < 20: return True else: return False
Assuming the randint generator is uniform, then this returns True if randint(0,99) is 0 through 19, and False if randint(0,99) is 20 through 99. So 20% of the values will cause the function to return true.
More generally for a chance of p percent, where p is between 0 and 100, inclusive:
def event(p): if (randint(0,99) < p): return True else: return FalseComplete the problems below to build this forest fire simulation in Python.
[3 points] Write a function display(forest) (in the file display.py). The parameter forest is a 15 X 15 matrix representing the 225 trees of the forest for the simuation. Each tree is a cell of the matrix. Each cell has an integer in the range 0 through 4 (inclusive), which encodes the tree's state as follows:
0 on fire 1 in ashes 2 a shoot (i.e. baby tree) 3 growing tree 4 mature tree
Your function should go through the entire matrix and display each "tree" as a square of size 20 pixels X 20 pixels in one of the following colors:
red on fire black in ashes light green a shoot green growing tree dark green mature tree
General algorithm:
Test your function using this Python function that creates a matrix of size 15 × 15 and fills each cell with a random integer between 0 and 4:
def test_display(): # seed the random number generator seed(15110) # create a canvas of size 300 X 300 Canvas.init(340, 340, "Testing_Display") # extra for PythonLabs bug # initialize forest matrix randomly forest = [0] * 15 # 15 rows for i in range(0,15): forest[i] = [0] * 15 # create 15 columns for each row for j in range(0,15): # pick a random tree state (0-4) for each tree in forest forest[i][j] = randint(0,4) # display the forest using your display function display(forest)
Put this function in the same file as your function. Be sure to import the necessary modules for your code to run correctly.
[4 points] Next, you will write 3 functions to test a specific tree in the forest to see if it changes its state. Complete all of these functions in the file tests.py.
General algorithm: Test to see if the cell forest[i][j] represents a tree on fire and use the event function above to see if it returns True given the percentage p. If both of these conditions are True, then return True. Otherwise, return False.
General algorithm: Test to see if the cell forest[i][j] represents a tree that is not on fire and is not mature, and then use the event function above to see if it returns True given the percentage p. If both of these conditions are True, then return True. Otherwise, return False.
General algorithm: Test to see if the cell forest[i][j] represents a tree that is mature, then test to see if at least one of its neighbors is on fire, and then use the event function above to see if it returns True given the percentage p. If both of these conditions are True, then return True. Otherwise, return False.
NOTE: Be careful when you test the neighbors. You might be on the edge of the forest. If you test for a neighbor and you go off of the matrix, you might cause your program to crash. It will help here to look at each neighbor separately rather than trying to evaluate all four neighbors in one statement.
Test your cool function using the following function which creates a simple small forest of size 3 X 5 and calls the function directly on each cell, printing the results for cool given a chance of 20%.
def test_cool(): forest = [ [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 2, 3, 4, 4] ] for i in range(0,len(forest)): for j in range(0,len(forest[i])): print(cool(forest, i, j, 20),end= " ") print()
Sample output:
False False True False False False False False False True False False False False FalseIn general, for the first two rows, a total of two outputs on average should be True. (This means that if you ran the test many times, the average number of True values in each of the first two lines will be approximately 2, but it may not be 2 for any one specific test.) For the last row, all outputs should be False.
Write two additional test functions to test grow and ignite. Test your functions carefully.
[3 points] Write a function update(forest) (in the file update.py). This function takes a 15 × 15 matrix representing our forest, as described above, for the current time step of the simulation, and returns a new 15 × 15 matrix representing our forest during the next time step (i.e. after one day has passed).
The basic idea here is that we start with the current forest in the array forest and create a new snapshot of the forest after one time step in an array new_forest. Each cell new_forest[row][column] represents the new status of the cell in the forest from forest[row][column].
General Algorithm:
Test your update function using the following function which creates a random forest and runs the simulation for 40 "days":
def run_simulation(): # seed the random number generator seed(15110) # create a canvas of size 300 X 300 Canvas.init(340, 340, "Testing_Display") # larger for PythonLabs bug # initialize forest matrix randomly forest = [0] * 15 # 15 rows for i in range(0,15): forest[i] = [0] * 15 # create 15 columns for each row for j in range(0,15): forest[i][j] = randint(0,4) # pick a random tree state (0-4) display(forest) Canvas.delay = 2 for day in range(0,40): forest = update(forest) # typo fixed display(forest) # typo fixed Canvas.update()
You should now have a pa10 directory that contains the required files, display.py, tests.py, and update.py, each—in turn—containing the corresponding function(s). You do not have to hand in the testing functions since we will have copies of these. Zip up your directory and upload it using the handin system.