How to resolve the algorithm Forest fire step by step in the BASIC programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Forest fire step by step in the BASIC programming language

Table of Contents

Problem Statement

Implement the Drossel and Schwabl definition of the forest-fire model.

It is basically a 2D   cellular automaton   where each cell can be in three distinct states (empty, tree and burning) and evolves according to the following rules (as given by Wikipedia) Neighborhood is the   Moore neighborhood;   boundary conditions are so that on the boundary the cells are always empty ("fixed" boundary condition). At the beginning, populate the lattice with empty and tree cells according to a specific probability (e.g. a cell has the probability 0.5 to be a tree). Then, let the system evolve. Task's requirements do not include graphical display or the ability to change parameters (probabilities   p   and   f )   through a graphical or command line interface.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Forest fire step by step in the BASIC programming language

Source code in the basic programming language

 100  FOR I = 17239 TO 17493
 110      READ B
 120  NEXT 
 130  CALL 17239
 140  END 
 150  DATA 162,23,138,32,71,248,165,38,157,60,3,165,39,157,84,3,202,16,239,162,96
 160  DATA 134,249,134,1,160,0,132,0,152,145,0,200,208,251,232,134,1,224,128,208
 170  DATA 244,44,86,192,44,82,192,44,84,192,44,80,192,32,50,248,162,0,134,0,169
 180  DATA 41,133,2,133,254,169,83,133,4,165,249,133,1,133,3,133,5,73,16,133,255
 190  DATA 133,249,138,134,45,74,168,169,15,144,2,105,224,133,46,185,60,3,133,38
 200  DATA 185,84,3,133,39,160,1,132,44,177,2,145,254,240,79,16,93,169,0,164,44
 210  DATA 145,254,136,81,38,37,46,81,38,145,38,164,44,200,192,41,208,224,165,2
 220  DATA 133,0,165,3,133,1,165,4,133,2,133,254,24,105,42,133,4,165,5,73,16
 230  DATA 133,255,73,16,133,3,105,0,133,5,166,45,232,224,48,208,159,44,0,192
 240  DATA 48,3,76,144,67,44,16,192,44,81,192,96,198,8,208,190,169,101,133,8,169
 250  DATA 68,208,169,169,153,208,165,198,6,208,14,198,7,208,10,169,23,133,6,169
 260  DATA 39,133,7,208,234,177,0,17,4,136,17,0,17,2,17,4,200,200,17,0,17,2,17,4
 270  DATA 48,213,16,137,41

N = 150 : M = 150 : P = 0.03 : F = 0.00003

dim f(N+2,M+2) # 1 tree, 0 empty, 2 fire
dim fn(N+2,M+2)
graphsize N,M
fastgraphics 

for x = 1 to N
	for y = 1 to M
		if rand<0.5 then f[x,y] = 1
	next y
next x

while True
	for x = 1 to N
		for y = 1 to M
			if not f[x,y] and rand<P then fn[x,y]=1
			if f[x,y]=2 then fn[x,y]=0
			if f[x,y]=1 then
				fn[x,y] = 1
				if f[x-1,y-1]=2 or f[x,y-1]=2 or f[x+1,y-1]=2 then fn[x,y]=2
				if f[x-1,y]=2 or f[x+1,y]=2 or rand<F then fn[x,y]=2
				if f[x-1,y+1]=2 or f[x,y+1]=2 or f[x+1,y+1]=2 then fn[x,y]=2
			end if
			# Draw
			if fn[x,y]=0 then color black
			if fn[x,y]=1 then color green
			if fn[x,y]=2 then color yellow
			plot x-1,y-1
		next y
	next x
	refresh
	for x = 1 to N
		for y = 1 to M
			f[x,y] = fn[x,y]
		next y
	next x
end while

      VDU 23,22,400;400;16,16,16,128
      OFF
      
      DIM old&(200,200), new&(200,200)
      p = 0.01
      f = 0.0001
      
      REM 0 = empty, 1 = tree, 2 = burning
      REPEAT
        WAIT 10
        FOR x% = 1 TO 199
          FOR y% = 1 TO 199
            CASE old&(x%,y%) OF
              WHEN 0:
                IF p > RND(1) THEN
                  new&(x%,y%) = 1
                  GCOL 2
                  PLOT 4*x%,4*y%
                ENDIF
              WHEN 1:
                IF f > RND(1) OR old&(x%-1,y%)=2 OR old&(x%+1,y%)=2 OR \
                \ old&(x%-1,y%-1)=2 OR old&(x%,y%-1)=2 OR old&(x%+1,y%-1)=2 OR \
                \ old&(x%-1,y%+1)=2 OR old&(x%,y%+1)=2 OR old&(x%+1,y%+1)=2 THEN
                  new&(x%,y%) = 2
                  GCOL 1
                  PLOT 4*x%,4*y%
                ENDIF
              WHEN 2:
                new&(x%,y%) = 0
                GCOL 15
                PLOT 4*x%,4*y%
            ENDCASE
          NEXT
        NEXT x%
        old&() = new&()
      UNTIL FALSE


'[RC] Forest Fire
'written for FreeBASIC 
'Program code based on BASIC256 from Rosettacode website
'http://rosettacode.org/wiki/Forest_fire#BASIC256
'06-10-2016 updated/tweaked the code
'compile with fbc -s gui

#Define M 400
#Define N 640

Dim As Double     p = 0.003
Dim As Double  fire = 0.00003
'Dim As Double number1
Dim As Integer gen, x, y
Dim As String press

'f0() and fn() use memory from the memory pool
Dim As UByte f0(), fn()
ReDim f0(-1 To N +2, -1 To M +2)
ReDim fn(-1 To N +2, -1 To M +2)

Dim As UByte white  = 15  'color 15 is white
Dim As UByte yellow = 14  'color 14 is yellow
Dim As UByte black  = 0   'color 0 is black
Dim As UByte green  = 2   'color 2 is green
Dim As UByte red    = 4   'color 4 is red

Screen 18 'Resolution 640x480 with at least 256 colors
Randomize Timer

Locate 28,1
Beep
Print " Welcome to Forest Fire"
Locate 29,1
Print " press any key to start"
Sleep
'Locate 28,1
'Print " Welcome to Forest Fire"
Locate 29,1
Print "                       "

' 1 tree, 0 empty, 2 fire
Color green ' this is green color for trees
For x = 1 To N
  For y = 1 To M
    If Rnd < 0.5 Then 'populate original tree density
      f0(x,y) = 1
      PSet (x,y)
    End If
  Next y
Next x

Color white
Locate 29,1
Print " Press any key to continue                        "
Sleep
Locate 29,1
Print " Press 'space bar' to continue/pause, ESC to stop "

Do
  press = InKey
  ScreenLock
  For x = 1 To N
    For y = 1 To M
      If Not f0(x,y) And Rnd<P Then fn(x,y)=1
      If f0(x,y)=2 Then fn(x,y)=0
      If f0(x,y)=1 Then
        fn(x,y) = 1
        If f0(x-1,y-1)=2 OrElse f0(x,y-1)=2 OrElse f0(x+1,y-1)=2 Then fn(x,y)=2
        If f0(x-1,y)=2 OrElse f0(x+1,y)=2 OrElse Rnd<fire Then fn(x,y)=2
        If f0(x-1,y+1)=2 OrElse f0(x,y+1)=2 OrElse f0(x+1,y+1)=2 Then fn(x,y)=2
      End If
      'set up color and drawing
      '0 empty (black),  1 tree (green), 2 fire (white)
      If fn(x,y)=0 Then Color black 'empty
      If fn(x,y)=1 Then Color green 'tree
      If fn(x,y)=2 Then Color red   'fire
      'plot x-1,y-1
      PSet (x-1,y-1)
    Next y
  Next x
  'print generation number
  gen = gen + 1
  Locate 28,1
  Color white 'this is white color
  Print " Generation number # ";gen
  'transfer new generation to current generation
  For x = 1 To N
    For y = 1 To M
      f0(x,y) = fn(x,y)
    Next y
  Next x
  ScreenUnlock

  ' amount for sleep is in milliseconds, 1 = ignore key press
  Sleep 50, 1  ' slow down a little ... goes too fast otherwise
  If press = " " Then Sleep : press = InKey
  If press = "s" Then Sleep
  ' return to do loop up top until "esc" key is pressed.
  ' clicking close windows "X", closes the window immediately 
Loop Until press = Chr(27) OrElse press = Chr(255)+"k"
If press = Chr(255) + "k" Then End

Locate 28,1
Color white
Print " You entered ESC - goodbye                        "
Print " Press any key to exit                            "
Sleep

width%=80
height%=50
DIM world%(width%+2,height%+2,2)
clock%=0
'
empty%=0 ! some mnemonic codes for the different states
burning%=1
tree%=2
'
f=0.0003
p=0.03
max_clock%=100
'
@open_window
@setup_world
DO
  clock%=clock%+1
  EXIT IF clock%>max_clock%
  @display_world
  @update_world
LOOP
@close_window
'
' Setup the world
'
PROCEDURE setup_world
  LOCAL i%,j%
  '
  RANDOMIZE 0
  ARRAYFILL world%(),empty%
  ' with Probability 0.5, create tree in cells
  FOR i%=1 TO width%
    FOR j%=1 TO height%
      IF RND>0.5
        world%(i%,j%,0)=tree%
      ENDIF
    NEXT j%
  NEXT i%
  '
  cur%=0
  new%=1
RETURN
'
' Display world on window
'
PROCEDURE display_world
  LOCAL size%,i%,j%,offsetx%,offsety%,x%,y%
  '
  size%=5
  offsetx%=10
  offsety%=20
  '
  VSETCOLOR 0,15,15,15 ! colour for empty
  VSETCOLOR 1,15,0,0 ! colour for burning
  VSETCOLOR 2,0,15,0 ! colour for tree
  VSETCOLOR 3,0,0,0 ! colour for text
  DEFTEXT 3
  PRINT AT(1,1);"Clock: ";clock%
  '
  FOR i%=1 TO width%
    FOR j%=1 TO height%
      x%=offsetx%+size%*i%
      y%=offsety%+size%*j%
      SELECT world%(i%,j%,cur%)
      CASE empty%
        DEFFILL 0
      CASE tree%
        DEFFILL 2
      CASE burning%
        DEFFILL 1
      ENDSELECT
      PBOX x%,y%,x%+size%,y%+size%
    NEXT j%
  NEXT i%
RETURN
'
' Check if a neighbour is burning
'
FUNCTION neighbour_burning(i%,j%)
  LOCAL x%
  '
  IF world%(i%,j%-1,cur%)=burning%
    RETURN TRUE
  ENDIF
  IF world%(i%,j%+1,cur%)=burning%
    RETURN TRUE
  ENDIF
  FOR x%=-1 TO 1
    IF world%(i%-1,j%+x%,cur%)=burning% OR world%(i%+1,j%+x%,cur%)=burning%
      RETURN TRUE
    ENDIF
  NEXT x%
  RETURN FALSE
ENDFUNC
'
' Update the world state
'
PROCEDURE update_world
  LOCAL i%,j%
  '
  FOR i%=1 TO width%
    FOR j%=1 TO height%
      world%(i%,j%,new%)=world%(i%,j%,cur%)
      SELECT world%(i%,j%,cur%)
      CASE empty%
        IF RND>1-p
          world%(i%,j%,new%)=tree%
        ENDIF
      CASE tree%
        IF @neighbour_burning(i%,j%) OR RND>1-f
          world%(i%,j%,new%)=burning%
        ENDIF
      CASE burning%
        world%(i%,j%,new%)=empty%
      ENDSELECT
    NEXT j%
  NEXT i%
  '
  cur%=1-cur%
  new%=1-new%
RETURN
'
' open and clear window
'
PROCEDURE open_window
  OPENW 1
  CLEARW 1
  VSETCOLOR 4,8,8,0
  DEFFILL 4
  PBOX 0,0,500,400
RETURN
'
' close the window after keypress
'
PROCEDURE close_window
  ~INP(2)
  CLOSEW 1
RETURN


; Some systems reports high CPU-load while running this code.
; This may likely be due to the graphic driver used in the 
; 2D-function Plot().
; If experiencing this problem, please reduce the #Width & #Height
; or activate the parameter #UnLoadCPU below with a parameter 1 or 2.
;
; This code should work with the demo version of PureBasic on both PC & Linux

; General parameters for the world
#f    = 1e-6
#p    = 1e-2
#SeedATree  = 0.005
#Width      = 400
#Height     = 400

; Setting up colours
#Fire       = $080CF7
#BackGround = $BFD5D3
#YoungTree  = $00E300
#NormalTree = $00AC00
#MatureTree = $009500
#OldTree    = $007600
#Black      = $000000

; Depending on your hardware, use this to control the speed/CPU-load.
; 0 = No load reduction
; 1 = Only active about every second frame
; 2 = '1' & release the CPU after each horizontal line.
#UnLoadCPU  = 0

Enumeration
  #Empty  =0
  #Ignited
  #Burning
  #Tree
  #Old=#Tree+20
EndEnumeration

Global Dim Forest.i(#Width, #Height)
Global Title$="Forest fire in PureBasic"
Global Cnt

Macro Rnd()
  (Random(2147483647)/2147483647.0)
EndMacro

Procedure Limit(n, min, max)
  If n<min
    n=min
  ElseIf n>max
    n=max
  EndIf
  ProcedureReturn n
EndProcedure

Procedure SpreadFire(x,y)
  Protected cnt=0, i, j
  For i=Limit(x-1, 0, #Width) To Limit(x+1, 0, #Width)
    For j=Limit(y-1, 0, #Height) To Limit(y+1, 0, #Height) 
      If Forest(i,j)>=#Tree
        Forest(i,j)=#Ignited
      EndIf
    Next
  Next
EndProcedure

Procedure InitMap()
  Protected x, y, type
  For y=1 To #Height
    For x=1 To #Width
      If Rnd()<=#SeedATree
        type=#Tree
      Else
        type=#Empty
      EndIf
      Forest(x,y)=type
    Next
  Next
EndProcedure

Procedure UpdateMap()
  Protected x, y
  For y=1 To #Height
    For x=1 To #Width
      Select Forest(x,y)
        Case #Burning
          Forest(x,y)=#Empty
          SpreadFire(x,y)
        Case #Ignited
          Forest(x,y)=#Burning
        Case #Empty
          If Rnd()<=#p
            Forest(x,y)=#Tree
          EndIf
        Default
          If Rnd()<=#f
            Forest(x,y)=#Burning
          Else
            Forest(x,y)+1
          EndIf
      EndSelect
    Next
  Next
EndProcedure

Procedure PresentMap()
  Protected x, y, c  
  cnt+1
  SetWindowTitle(0,Title$+", time frame="+Str(cnt))
  StartDrawing(ImageOutput(1))
  For y=0 To OutputHeight()-1
    For x=0 To OutputWidth()-1
      Select Forest(x,y)
        Case #Empty
          c=#BackGround
        Case #Burning, #Ignited
          c=#Fire
        Default
          If Forest(x,y)<#Tree+#Old
            c=#YoungTree
          ElseIf Forest(x,y)<#Tree+2*#Old
            c=#NormalTree
          ElseIf Forest(x,y)<#Tree+3*#Old
            c=#MatureTree
          ElseIf Forest(x,y)<#Tree+4*#Old
            c=#OldTree
          Else ; Tree died of old age
            Forest(x,y)=#Empty
            c=#Black
          EndIf
      EndSelect
      Plot(x,y,c)
    Next
    CompilerIf #UnLoadCPU>1
      Delay(1)
    CompilerEndIf
  Next
  StopDrawing()
  ImageGadget(1, 0, 0, #Width, #Height, ImageID(1))
EndProcedure

If OpenWindow(0, 10, 30, #Width, #Height, Title$, #PB_Window_MinimizeGadget)
  SmartWindowRefresh(0, 1)
  If CreateImage(1, #Width, #Height)
    Define Event, freq
    If ExamineDesktops() And DesktopFrequency(0)
      freq=DesktopFrequency(0)
    Else
      freq=60
    EndIf
    AddWindowTimer(0,0,5000/freq)
    InitMap()
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_CloseWindow
          End
        Case #PB_Event_Timer
          CompilerIf #UnLoadCPU>0
            Delay(25)
          CompilerEndIf
          UpdateMap()
          PresentMap()
      EndSelect
    ForEver
  EndIf 
EndIf

Sub Run()
  //Handy named constants
  Const empty = 0
  Const tree = 1
  Const fire = 2
  Const ablaze = &cFF0000    //Using the &c numeric operator to indicate a color in hex
  Const alive = &c00FF00
  Const dead = &c804040
  
  //Our forest
  Dim worldPic As New Picture(480, 480, 32)
  Dim newWorld(120, 120) As Integer
  Dim oldWorld(120, 120) As Integer
  
  //Initialize forest
  Dim rand As New Random
  For x as Integer = 0 to 119
    For y as Integer = 0 to 119
      if rand.InRange(0, 2) = 0 Or x = 119 or y = 119 or x = 0 or y = 0 Then
        newWorld(x, y) = empty
        worldPic.Graphics.ForeColor = dead
        worldPic.Graphics.FillRect(x*4, y*4, 4, 4)
      Else
        newWorld(x, y) = tree
        worldPic.Graphics.ForeColor = alive
        worldPic.Graphics.FillRect(x*4, y*4, 4, 4)
      end if
    Next
  Next
  oldWorld = newWorld
  
  //Burn, baby burn!
  While Window1.stop = False
    For x as Integer = 0 To 119
      For y As Integer = 0 to 119
        Dim willBurn As Integer = rand.InRange(0, Window1.burnProb.Value)
        Dim willGrow As Integer = rand.InRange(0, Window1.growProb.Value)
        if x = 119 or y = 119 or x = 0 or y = 0 Then
          Continue
        end if
        Select Case oldWorld(x, y)
        Case empty
          If willGrow = (Window1.growProb.Value) Then
            newWorld(x, y) = tree
            worldPic.Graphics.ForeColor = alive
            worldPic.Graphics.FillRect(x*4, y*4, 4, 4)
          end if
        Case tree
          if oldWorld(x - 1, y) = fire Or oldWorld(x, y - 1) = fire Or oldWorld(x + 1, y) = fire Or oldWorld(x, y + 1) = fire Or oldWorld(x + 1, y + 1) = fire Or oldWorld(x - 1, y - 1) = fire Or oldWorld(x - 1, y + 1) = fire Or oldWorld(x + 1, y - 1) = fire Or willBurn = (Window1.burnProb.Value) Then
            newWorld(x, y) = fire
            worldPic.Graphics.ForeColor = ablaze
            worldPic.Graphics.FillRect(x*4, y*4, 4, 4)
          end if
        Case fire
          newWorld(x, y) = empty
          worldPic.Graphics.ForeColor = dead
          worldPic.Graphics.FillRect(x*4, y*4, 4, 4)
        End Select
      Next
    Next
    Window1.Canvas1.Graphics.DrawPicture(worldPic, 0, 0)
    oldWorld = newWorld
    me.Sleep(Window1.speed.Value)
  Wend
End Sub

Sub Open()
  //First method to run on the creation of a new Window. We instantiate an instance of our forestFire thread and run it.
  Dim fire As New forestFire
  fire.Run()
End Sub

stop As Boolean  //a globally accessible property of Window1. Boolean properties default to False.

Sub Pushbutton1.Action()
  stop = True
End Sub

graphic #g, 200,200
dim preGen(200,200)
dim newGen(200,200)

for gen = 1 to 200
  for x = 1 to 199
    for y = 1 to 199
      select case preGen(x,y)
        case 0
          if rnd(0) > .99 then newGen(x,y) = 1  : #g "color green ; set "; x; " "; y
        case 2
          newGen(x,y) = 0                       : #g "color brown ; set "; x; " "; y
        case 1
          if preGen(x-1,y-1) = 2 or preGen(x-1,y)   = 2 or preGen(x-1,y+1) = 2 _
          or preGen(x,y-1)   = 2 or preGen(x,y+1)   = 2 or preGen(x+1,y-1) = 2 _
          or preGen(x+1,y)   = 2 or preGen(x+1,y+1) = 2 or rnd(0) > .999 then
              #g "color red ; set "; x; " "; y
              newGen(x,y) = 2
          end if
      end select
      preGen(x-1,y-1) = newGen(x-1,y-1)
    next y
  next x
next gen
render #g

  10 DIM F$(20,30)
  20 DIM N$(20,30)
  30 LET INIT=.5
  40 LET F=.02
  50 LET P=.05
  60 PRINT AT 0,1;"[FOREST FIRE   FOR ROSETTA CODE]"
  70 FOR I=0 TO 21
  80 PRINT AT I,0;"[ ]"
  90 PRINT AT I,31;"[ ]"
 100 NEXT I
 110 FOR I=1 TO 30
 120 PRINT AT 21,I;"[ ]"
 130 NEXT I
 140 LET G=0
 150 LET T=0
 160 PRINT AT 21,1;"[GENERATION 0]"
 170 PRINT AT 21,20;"[COVER]"
 180 FOR I=1 TO 20
 190 FOR J=1 TO 30
 200 IF RND>=INIT THEN GOTO 240
 210 PRINT AT I,J;"0"
 220 LET F$(I,J)="0"
 230 LET T=T+1
 240 NEXT J
 250 NEXT I
 300 PRINT AT 21,26;"[      ]"
 310 LET N=INT (.5+T/6)
 320 GOSUB 1000
 330 PRINT AT 21,26;I$;"[ PC]"
 340 FOR I=1 TO 20
 350 PRINT AT I,0;"[>]"
 360 FOR J=1 TO 30
 380 IF F$(I,J)<>"[a]" THEN GOTO 410
 390 LET N$(I,J)=" "
 400 GOTO 530
 410 IF F$(I,J)<>" " THEN GOTO 433
 420 IF RND<=P THEN LET N$(I,J)="0"
 430 GOTO 530
 433 LET N$(I,J)=CHR$ (1+CODE F$(I,J))
 437 IF N$(I,J)>"Z" THEN LET N$(I,J)="£"
 440 FOR K=I-1 TO I+1
 450 FOR L=J-1 TO J+1
 460 IF K=0 OR L=0 OR K=21 OR L=21 THEN GOTO 480
 470 IF F$(K,L)="[a]" THEN GOTO 510
 480 NEXT L
 490 NEXT K
 500 GOTO 520
 510 LET N$(I,J)="[a]"
 520 IF RND<=F THEN LET N$(I,J)="[a]"
 530 NEXT J
 540 PRINT AT I,0;"[ ]"
 550 NEXT I
 552 LET G=G+1
 554 LET N=G
 556 GOSUB 1000
 558 PRINT AT 21,12;I$
 560 LET T=0
 570 FOR I=1 TO 20
 575 PRINT AT I,31;"[<]"
 580 FOR J=1 TO 30
 590 IF N$(I,J)<>"[a]" AND N$(I,J)<>" " THEN LET T=T+1
 600 NEXT J
 610 LET F$(I)=N$(I)
 620 PRINT AT I,1;F$(I)
 625 PRINT AT I,31;"[ ]"
 630 GOTO 300
1000 LET S$=STR$ N
1010 LET I$=""
1020 FOR K=1 TO LEN S$
1030 LET I$=I$+CHR$ (128+CODE S$(K))
1040 NEXT K
1050 RETURN


Public Class ForestFire
    Private _forest(,) As ForestState
    Private _isBuilding As Boolean
    Private _bm As Bitmap
    Private _gen As Integer
    Private _sw As Stopwatch

    Private Const _treeStart As Double = 0.5
    Private Const _f As Double = 0.00001
    Private Const _p As Double = 0.001

    Private Const _winWidth As Integer = 300
    Private Const _winHeight As Integer = 300

    Private Enum ForestState
        Empty
        Burning
        Tree
    End Enum

    Private Sub ForestFire_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.ClientSize = New Size(_winWidth, _winHeight)
        ReDim _forest(_winWidth, _winHeight)

        Dim rnd As New Random()
        For i As Integer = 0 To _winHeight - 1
            For j As Integer = 0 To _winWidth - 1
                _forest(j, i) = IIf(rnd.NextDouble <= _treeStart, ForestState.Tree, ForestState.Empty)
            Next
        Next

        _sw = New Stopwatch
        _sw.Start()
        DrawForest()
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If _isBuilding Then Exit Sub

        _isBuilding = True
        GetNextGeneration()

        DrawForest()
        _isBuilding = False
    End Sub

    Private Sub GetNextGeneration()
        Dim forestCache(_winWidth, _winHeight) As ForestState
        Dim rnd As New Random()

        For i As Integer = 0 To _winHeight - 1
            For j As Integer = 0 To _winWidth - 1
                Select Case _forest(j, i)
                    Case ForestState.Tree
                        If forestCache(j, i) <> ForestState.Burning Then
                            forestCache(j, i) = IIf(rnd.NextDouble <= _f, ForestState.Burning, ForestState.Tree)
                        End If

                    Case ForestState.Burning
                        For i2 As Integer = i - 1 To i + 1
                            If i2 = -1 OrElse i2 >= _winHeight Then Continue For
                            For j2 As Integer = j - 1 To j + 1
                                If j2 = -1 OrElse i2 >= _winWidth Then Continue For
                                If _forest(j2, i2) = ForestState.Tree Then forestCache(j2, i2) = ForestState.Burning
                            Next
                        Next
                        forestCache(j, i) = ForestState.Empty

                    Case Else
                        forestCache(j, i) = IIf(rnd.NextDouble <= _p, ForestState.Tree, ForestState.Empty)
                End Select
            Next
        Next

        _forest = forestCache
        _gen += 1
    End Sub

    Private Sub DrawForest()
        Dim bmCache As New Bitmap(_winWidth, _winHeight)

        For i As Integer = 0 To _winHeight - 1
            For j As Integer = 0 To _winWidth - 1
                Select Case _forest(j, i)
                    Case ForestState.Tree
                        bmCache.SetPixel(j, i, Color.Green)

                    Case ForestState.Burning
                        bmCache.SetPixel(j, i, Color.Red)
                End Select
            Next
        Next

        _bm = bmCache
        Me.Refresh()
    End Sub

    Private Sub ForestFire_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        e.Graphics.DrawImage(_bm, 0, 0)

        Me.Text = "Gen " & _gen.ToString() & " @ " & (_gen / (_sw.ElapsedMilliseconds / 1000)).ToString("F02") & " FPS: Forest Fire"
    End Sub
End Class


 10 PAPER 6: CLS
 20 DIM n$(20,30)
 30 LET init=.5
 40 LET f=.02
 50 LET p=.05
 60 PAPER 0
 70 FOR i=0 TO 31
 80 PRINT AT 0,i;" "
 90 PRINT AT 21,i;" "
100 NEXT i
110 FOR i=0 TO 21
120 PRINT AT i,0;" "
130 PRINT AT i,31;" "
140 NEXT i
150 INK 7
160 PRINT AT 0,1;"FOREST FIRE   for Rosetta Code"
170 LET generation=0
180 PRINT AT 21,1;"Generation 0"
190 LET trees=0
200 PRINT AT 21,22;"Cover"
210 FOR i=1 TO 20
220 FOR j=1 TO 30
230 IF RND<init THEN PAPER 4: INK 7: PRINT AT i,j;"T": LET trees=trees+1
240 NEXT j
250 NEXT i
260 LET generation=generation+1
270 INK 7
280 PAPER 0
290 PRINT AT 21,12;generation
300 PRINT AT 21,28;"    "
310 PRINT AT 21,28;INT (trees/6+.5);"%"
320 FOR i=1 TO 20
330 FOR j=1 TO 30
340 LET n$(i,j)=SCREEN$ (i,j)
350 IF SCREEN$ (i,j)="B" THEN LET n$(i,j)=" ": GO TO 450
360 IF SCREEN$ (i,j)="T" THEN GO TO 390
370 IF RND<=p THEN LET n$(i,j)="T"
380 GO TO 450
390 FOR k=i-1 TO i+1
400 FOR l=j-1 TO j+1
410 IF SCREEN$ (k,l)="B" THEN LET n$(i,j)="B": LET k=i+2: LET l=j+2
420 NEXT l
430 NEXT k
440 IF RND<=f THEN LET n$(i,j)="B"
450 NEXT j
460 NEXT i
470 LET trees=0
480 FOR i=1 TO 20
490 FOR j=1 TO 30
500 IF n$(i,j)="T" THEN INK 7: PAPER 4: PRINT AT i,j;"T": LET trees=trees+1: GO TO 540
510 IF n$(i,j)="B" THEN INK 6: PAPER 2: PRINT AT i,j;"B": GO TO 540
520 PAPER 6
530 PRINT AT i,j;" "
540 NEXT j
550 NEXT i
560 GO TO 260

  

You may also check:How to resolve the algorithm Loops/N plus one half step by step in the ALGOL 60 programming language
You may also check:How to resolve the algorithm Diversity prediction theorem step by step in the ALGOL 68 programming language
You may also check:How to resolve the algorithm Greyscale bars/Display step by step in the RapidQ programming language
You may also check:How to resolve the algorithm Playing cards step by step in the PicoLisp programming language
You may also check:How to resolve the algorithm Parsing/RPN to infix conversion step by step in the Nim programming language