Lab 6 - Programming a Fire Model
The code we took from the example can make the patches red as you can see in the above but what we really want it to do is to ignite the patches. Replace the code that says “set pcolor red” with “ignite”. Now we build a procedure that will ignite the patches. Below the last procedure the “to ignite” procedure will sprout one turtle, set its breed to fires and its color to red. Then you have the patch set its pcolor to black and add it to the count of burned-trees. Nothing much happens because we have no GO procedure to tell the turtles the rules. So, let’s go.
Go
In our flow chart, the first thing to consider is that if there no turtles the program should stop. Don’t forget the question mark after the “any” or you will see the yellow error banner. Continue with the flow chart and ask fires to set a heading nearly the same as the wind-direction. If the winds are light and variable the heading may vary a good deal but if the winds are strong and steady, the heading won’t vary as much. Try to make the variation in the heading inversely proportional to the wind-speed. A part of the fire could also continue from one variation to the next iteration, thus moving farther away from the course of the wind. Code should be something like:
Locals [
New-heading
]
(this has to be at the top of the go program)
Set new-heading wind-direction + random some value/ windspeed – random some value /windspeed
Set heading new-heading
The “some value” is something you can try out to see what makes the fire burn as you expect with various wind speeds. Both the plus and minus make the variation to the right and to the left possible.
Now that we have fire with a heading, we need to build a statement about what the fire will do. This procedure has several sub-procedures that must be included. Let’s start with the “if patch is green” condition. If the patch ahead one is a shade of green the fire will go to that patch and ignite it, if not then the fire will die. The shades of green are listed in the code examples in the models library. Use an “ifelse” statement like this:
Ifelse pcolor-of patch-ahead 1 > 50 and pcolor-of patch-ahead 1 < 60 [ fd 1 ask patch-here [ ignite ] ] [ die ]
In plain English, this says to look ahead one patch and if the patch is a shade of green, go forward one step and set fire to the patch – if the patch is not a shade of green then die.
In order to propagate the fire, burning patches need to generate sparks that can be carried on the wind as a function of the windspeed to other patches to set them on fire. If we want the patch to produce the sparks, we use the sprout command. If we want the turtle (fire) to produce the sparks, we use the hatch command. Our flow chart says that the fire will produce the sparks so use the hatch command. How many should we hatch? At each iteration, the number will grow exponentially, so as few as two will provide lots of opportunity for fire to spread. We only want to hatch sparks if the patch the fire is on is a shade of green, so we will need to put the procedure for sparks inside the first conditional statement of the ifelse we already built. After the closing bracket for the patch ignite statement add a procedure that hatches two turtles and commands them to set some variables like their breed, color, and heading. Sparks are red and their heading is again determined by the wind-direction. Use the same code for heading used for fires. Sparks also cause fire to jump over various obstacles so use a jump command instead of a forward command. How far will the sparks jump? That is a function of the windspeed and the sparks lifespan. For now let’s deal with windspeed only. Think about how far wind will carry the sparks from a fire. In the model, we could say that the wind would carry the spark one patch per 10 mph. A sixty mile an hour wind will cause sparks to fly six patches. This would also mean that it takes a 10 mph wind to move the fire at all, since less that 10 mph results in movement of less than one patch and causes the death of the spark.
Let’s make it a jump of 1/10 of windspeed.
This will create a problem for us in that our no-wrap boundary is only going to stop one-step-at-a-time turtles. These jumping turtles will cross that boundary. How do we prevent that? How could you make a wider boundary?
If our sparks land on trees (patches with a shade of green), we want them to become fires, if not on a green patch they should die. An ifelse statement just after the jump command will look just like the one we did for fires after we gave them a heading. In the first condition brackets, we will set the breed of the sparks to the breed fires. In the second, we will ask the sparks to die.
The last thing we want our fires to do is to become embers and die out. Fires act on one condition – is the patch green? – if it is then burn the patch, make sparks and become embers and die—if it isn’t then just die. The last thing that needs to be inside the bracket for if the patch ahead is green is to hatch 1 fires and set breed of the old fires to embers. Make sure this is outside the brackets of what the sparks are doing because you don’t want sparks doing what the fire is doing.
Finally, outside the brackets of the ask fires procedure, call the procedure to fade embers. Then build a procedure to fade the embers and have them die. In this fade-embers procedure you will ask embers to set color color minus (a value like .2) to fade the color to a darker color. The bigger the value is the faster the fade. Following that is a conditional “If” statement that kills the embers. If color < 50.4 [die]
Your program should now work. This is a check-point. Compare your code to the code following:
globals [ initial-trees burned-trees ] breeds [ fires sparks embers ] patches-own [ elevation ] to setup ca ask patches [ if random-float 100 < (density) [ set pcolor green ] ] ask patches [ if hilly [ set elevation random 10000 ] if valley [ if pcolor = green [ set elevation (0 + (abs pycor * 90) + random 1000) ] ] if ridge [ if pcolor = green [ set elevation (10000 - (abs pycor * 90) - random 1000) ] ] ] repeat smoothness [diffuse elevation 1 ] ask patches with [pcolor = green] [ set pcolor scale-color green elevation -500 9900 ] ask patches with [pxcor >= (screen-edge-x - 10)] [ set pcolor blue ] ask patches with [pycor >= (screen-edge-y - 10)] [ set pcolor blue ] end to patch-draw if mouse-down? [ ask patch-at mouse-xcor mouse-ycor [ ignite ] ] end to ignite sprout 1 [ set breed fires set color red ] set pcolor black set burned-trees burned-trees + 1 end to go locals [ new-heading previous-patch ] if not any? turtles [stop] ask fires [ set new-heading wind-direction + random 180 / sqrt (windspeed + 1) - random 180 / sqrt (windspeed + 1) set heading new-heading ifelse pcolor-of patch-ahead 1 > 50 and pcolor-of patch-ahead 1 < 60 and random drought > 100 and elevation-of patch-ahead 1 >= (elevation-of patch-here - random 500) [ fd 1 ask patch-here [ ignite ] hatch 2 [ set previous-patch patch-here set breed sparks set color red set new-heading wind-direction + random 180 / sqrt (windspeed + 1) - random 180 / sqrt (windspeed + 1) set heading new-heading jump windspeed / 10 ifelse pcolor-of patch-here > 50 and pcolor-of patch-here < 60 and random drought > 100 and elevation-of patch-here > (elevation-of previous-patch - random 500) [ set breed fires ] [ die ] ] hatch 1 [ set breed fires ] set breed embers ] [ die ] ] fade-embers end to fade-embers ask embers [ set color color - .2 if color < 50.4 [die] ] end
We have left only to modify the program to include the effects of drought and topography on the way the fire burns. Think about where we would need these modifications? These will be “if” statements. A patch will burn if it is dry enough. A patch will be more likely to burn if it lies uphill from the current fire.
Let’s tack the drought condition onto the green patch condition by simply adding an and statement that looks like this:
…and random drought > 100
Put this line into both the fires and sparks conditional statements about whether the patch is green. Test it out. Does it work? Can you prevent the spread of the fire based on how long the drought has been going?
Adding another condition for elevation is a simple matter for the fires which move from patch to patch, so let’s do that now. In that same line that you put the drought statement for fires add a conditional statement about the elevation of the patch ahead as compared to the patch the turtle is on. To provide some opportunity for fires to spread downhill you should include a random number subtracted from the current patch elevation. You will add something like this to the conditional statement:
and elevation-of patch-ahead 1 >= (elevation-of patch-here - random 1000)
Sparks jump so you will need to keep track of the elevation of the patch they were on before they jumped. Add a local variable in the go procedure called previous-patch. In the procedures for the sparks hatched after you ignited the patch have the sparks set previous-patch as patch-here. Then in the condition for sparks to become fires add an and that compares the elevation of the patch here and the elevation of the previous patch minus a random number so it can spread to a lesser extent downhill.
|