A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://inventwithpython.com/bigbookpython/project29.html below:

Forest Fire Sim

#29
Forest Fire Sim

This simulation shows a forest whose trees are constantly growing and then being burned down. On each step of the simulation, there is a 1 percent chance that a blank space grows into a tree and a 1 percent chance that a tree is struck by lightning and burns. Fires will spread to adjacent trees, so a densely packed forest is more likely to suffer a larger fire than a sparsely packed one. This simulation was inspired by Nicky Case’s Emoji Sim at http://ncase.me/simulating/model/.

The Program in Action

When you run forestfiresim.py, the output will look like this:

Figure 29-1: The forest fire simulation, with green As for trees and red Ws for flames

How It Works

This simulation is an example of emergent behavior—the interaction between simple parts in a system creating complicated patterns. Empty spaces grow into trees, lightning turns trees into fire, and fire turns trees back into empty spaces while spreading to neighboring trees. By adjusting the tree growth and lightning strike rate, you can cause the forest to display different phenomena. For example, a low lightning chance but high growth rate causes large, constant forest fires, since the trees tend to be near each other and quickly replenish. A low growth rate but high lightning strike chance creates several small fires that quickly extinguish due to a lack of nearby trees. We don’t explicitly program any of this behavior; rather, it naturally emerges from the system that we created.

  1. """Forest Fire Sim, by Al Sweigart [email protected]
  2. A simulation of wildfires spreading in a forest. Press Ctrl-C to stop.
  3. Inspired by Nicky Case's Emoji Sim http://ncase.me/simulating/model/
  4. View this code at https://nostarch.com/big-book-small-python-projects
  5. Tags: short, bext, simulation"""
  6.
  7. import random, sys, time
  8.
  9. try:
 10.     import bext
 11. except ImportError:
 12.     print('This program requires the bext module, which you')
 13.     print('can install by following the instructions at')
 14.     print('https://pypi.org/project/Bext/')
 15.     sys.exit()
 16.
 17. # Set up the constants:
 18. WIDTH = 79
 19. HEIGHT = 22
 20.
 21. TREE = 'A'
 22. FIRE = 'W'
 23. EMPTY = ' '
 24.
 25. # (!) Try changing these settings to anything between 0.0 and 1.0:
 26. INITIAL_TREE_DENSITY = 0.20  # Amount of forest that starts with trees.
 27. GROW_CHANCE = 0.01  # Chance a blank space turns into a tree.
 28. FIRE_CHANCE = 0.01  # Chance a tree is hit by lightning & burns.
 29.
 30. # (!) Try setting the pause length to 1.0 or 0.0:
 31. PAUSE_LENGTH = 0.5
 32.
 33.
 34. def main():
 35.     forest = createNewForest()
 36.     bext.clear()
 37.
 38.     while True:  # Main program loop.
 39.         displayForest(forest)
 40.
 41.         # Run a single simulation step:
 42.         nextForest = {'width': forest['width'],
 43.                       'height': forest['height']}
 44.
 45.         for x in range(forest['width']):
 46.             for y in range(forest['height']):
 47.                 if (x, y) in nextForest:
 48.                     # If we've already set nextForest[(x, y)] on a
 49.                     # previous iteration, just do nothing here:
 50.                     continue
 51.
 52.                 if ((forest[(x, y)] == EMPTY)
 53.                     and (random.random() <= GROW_CHANCE)):
 54.                     # Grow a tree in this empty space.
 55.                     nextForest[(x, y)] = TREE
 56.                 elif ((forest[(x, y)] == TREE)
 57.                     and (random.random() <= FIRE_CHANCE)):
 58.                     # Lightning sets this tree on fire.
 59.                     nextForest[(x, y)] = FIRE
 60.                 elif forest[(x, y)] == FIRE:
 61.                     # This tree is currently burning.
 62.                     # Loop through all the neighboring spaces:
 63.                     for ix in range(-1, 2):
 64.                         for iy in range(-1, 2):
 65.                             # Fire spreads to neighboring trees:
 66.                             if forest.get((x + ix, y + iy)) == TREE:
 67.                                 nextForest[(x + ix, y + iy)] = FIRE
 68.                     # The tree has burned down now, so erase it:
 69.                     nextForest[(x, y)] = EMPTY
 70.                 else:
 71.                     # Just copy the existing object:
 72.                     nextForest[(x, y)] = forest[(x, y)]
 73.         forest = nextForest
 74.
 75.         time.sleep(PAUSE_LENGTH)
 76.
 77.
 78. def createNewForest():
 79.     """Returns a dictionary for a new forest data structure."""
 80.     forest = {'width': WIDTH, 'height': HEIGHT}
 81.     for x in range(WIDTH):
 82.         for y in range(HEIGHT):
 83.             if (random.random() * 100) <= INITIAL_TREE_DENSITY:
 84.                 forest[(x, y)] = TREE  # Start as a tree.
 85.             else:
 86.                 forest[(x, y)] = EMPTY  # Start as an empty space.
 87.     return forest
 88.
 89.
 90. def displayForest(forest):
 91.     """Display the forest data structure on the screen."""
 92.     bext.goto(0, 0)
 93.     for y in range(forest['height']):
 94.         for x in range(forest['width']):
 95.             if forest[(x, y)] == TREE:
 96.                 bext.fg('green')
 97.                 print(TREE, end='')
 98.             elif forest[(x, y)] == FIRE:
 99.                 bext.fg('red')
100.                 print(FIRE, end='')
101.             elif forest[(x, y)] == EMPTY:
102.                 print(EMPTY, end='')
103.         print()
104.     bext.fg('reset')  # Use the default font color.
105.     print('Grow chance: {}%  '.format(GROW_CHANCE * 100), end='')
106.     print('Lightning chance: {}%  '.format(FIRE_CHANCE * 100), end='')
107.     print('Press Ctrl-C to quit.')
108.
109.
110. # If this program was run (instead of imported), run the game:
111. if __name__ == '__main__':
112.     try:
113.         main()
114.     except KeyboardInterrupt:
115.         sys.exit()  # When Ctrl-C is pressed, end the program.

After entering the source code and running it a few times, try making experimental changes to it. The comments marked with (!) have suggestions for small changes you can make. On your own, you can also try to figure out how to do the following:

Exploring the Program

Try to find the answers to the following questions. Experiment with some modifications to the code and rerun the program to see what effect the changes have.

  1. What happens if you change bext.fg('green') on line 96 to bext.fg('random')?
  2. What happens if you change EMPTY = ' ' on line 23 to EMPTY = '.'?
  3. What happens if you change forest.get((x + ix, y + iy)) == TREE on line 66 to forest.get((x + ix, y + iy)) == EMPTY?
  4. What happens if you change nextForest[(x, y)] = EMPTY on line 69 to nextForest[(x, y)] = FIRE?
  5. What happens if you change forest[(x, y)] = EMPTY on line 86 to forest[(x, y)] = TREE?

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4