Spreading of Fire in AgentCubes

Module 10.3 · The same forest, built from rules instead of loops

TipToday’s question

On Wednesday we built a forest fire in R with a matrix and four nested loops. Can we build the same model without writing a loop at all? Today we’ll rebuild it in AgentCubes, a tool where each tree is an agent that follows its own rules, and AgentCubes handles the grid, the loops, and the drawing.

NoteReading and software

Review textbook Module 10.3, “Spreading of Fire,” and our R version of the fire model. Open AgentCubes Online at agentsheets.com in your browser and sign in with the class account I give you in class. There’s nothing to install.

From R to AgentCubes

Here is where each piece of Wednesday’s R model lives in AgentCubes:

In our R model In AgentCubes
The forest matrix The world: a grid you paint agents onto
A cell’s value: TREE, BURNING, EMPTY An agent’s shape: healthy, burning, or dead
Nested for loops over every cell Nothing to write: every agent runs its rules each tick
if / else if A list of if–then rules, checked from top to bottom
runif(1) < p The percent-chance condition
Reading forest, writing new_forest Two methods, check and then act, called by a controller
plot() after the run A plot window that updates while the fire burns

The forest

An AgentCubes world: a square grid of trees, almost all burned to bare black trunks, with a few green trees left. A plot window shows healthy trees falling from 135, burning trees rising and falling, and dead trees rising to nearly 135.

Your instructor’s example world after a fire. The plot tracks healthy (green), burning (red), and dead (black) trees.

The world has a floor agent for the ground, a controller agent (the beaver in the corner) that runs the simulation, and a tree agent with three shapes:

  • healthy: a green tree,
  • burning: a tree on fire, and
  • dead: a bare black trunk.

One difference from R: a burned tree doesn’t become empty ground. It stays on the grid as a dead tree, so it can’t catch fire again.

Each tree also has two attributes, which are numbers that belong to that one agent, like a variable each tree carries around:

  • ignite is 1 when the tree has been set to catch fire.
  • clock counts how many ticks the tree has been burning.

Check, then act

Remember why the R code read from forest and wrote into new_forest? If trees changed as we went, a tree that caught fire a moment ago could spread fire again in the same step.

AgentCubes has the same problem, and we solve it the same way, in two phases each tick:

  1. check: every tree looks at its neighbors and decides what will happen. Nobody changes shape yet.
  2. act: after all the trees have checked, every tree carries out its decision.

The controller

AgentCubes controller rule, while-running: broadcast tree check; broadcast tree act; set @healthy, @burning, and @dead to agents_with_shape of each shape; then plot-to-window each count in the trees window in green, red, and black.

The controller’s while-running method runs once every tick. It broadcasts check to every tree, then broadcasts act, so all the checking finishes before any tree changes. Then it counts the trees of each shape with agents_with_shape() and adds those counts to the plot.

The check method

AgentCubes rule: on check, if see healthy tree and next-to burning tree greater than 0 and percent-chance 1, then set ignite to 1 and set clock to 0.

Read it as one sentence: if I’m a healthy tree, and at least one tree next to me is burning, and a small random chance comes up (1% in this picture), then set ignite to 1 and reset clock to 0.

The tree doesn’t catch fire here. It only makes a note in ignite.

The act method

AgentCubes rules on act: if see healthy tree and test ignite equals 1, change to burning. Else if see burning tree and test clock equals 100, change to dead. Else if see burning tree, set clock to clock plus 1.

AgentCubes tries the rules from top to bottom and uses the first one that’s true, just like if / else if in R:

  1. A healthy tree with ignite = 1 changes to burning.
  2. Otherwise, a burning tree whose clock has reached 100 changes to dead.
  3. Otherwise, a burning tree adds 1 to its clock.

So a burning tree burns for 100 ticks before it dies.

Build it

Follow along as we build it together:

  1. Make the agents. Create a tree agent with three shapes (healthy, burning, dead), a floor agent, and a controller agent.
  2. Paint the world. Cover it with floor, then fill it with healthy trees.
  3. Add the attributes. Give the tree ignite and clock, both starting at 0.
  4. Write on check. Add one rule, as in the picture above.
  5. Write on act. Add the three rules, in this order. What would go wrong if the clock + 1 rule came first?
  6. Light a fire. Draw one burning tree in the middle of the forest.
  7. Write the controller. Broadcast check, then act, then plot the number of healthy, burning, and dead trees.
  8. Run it. Watch the fire spread, and watch the plot as it runs.

How this model differs from ours in R

Look at the example world above. Every cell had a tree, but a few trees survived. In our R model, a forest that full would burn completely. Why the difference?

  • Spreading takes luck. In R, a tree next to a fire always caught fire on the next step. Here, each tick, a tree next to a fire has only a small chance. But a neighbor burns for 100 ticks, so the tree gets 100 tries. At 1% per tick, the chance it never catches is \(0.99^{100}\), about 37%, so it catches fire about 63% of the time.
  • Burning takes time. In R, a tree burned for one step. Here it burns for 100 ticks, and the clock attribute keeps track.
  • Dead trees stay. A burned tree becomes a dead trunk instead of bare ground.

The rules are still local, and the pattern of the whole forest still emerges from them, just as on Wednesday.

Try it

Change one thing at a time, run it again, and compare the plot with the first run:

  • Change the percent-chance to a smaller value, then to a larger one, such as 3. How much of the forest burns each time? How does the shape of the red curve change?
  • Change the 100 in clock = 100 to 20, so trees burn out faster. Why might fewer trees burn?
  • Erase some trees to make the forest less dense, as we did in R with prob_tree. Can you find a density where the fire usually dies out?
ImportantWhat we practiced
  • Agents, shapes, and attributes replace the matrix and its numbers.
  • Rules run in order, and the first true rule wins, just like if / else if.
  • Check, then act is AgentCubes’s version of reading the old grid and writing a new one.
  • Small chances add up. A small chance each tick, repeated over 100 ticks, can make it likely that a tree catches fire.
Back to top