RosettaCodeData/Task/Forest-fire/FutureBasic/forest-fire.basic
2026-04-30 12:34:36 -04:00

222 lines
5.1 KiB
Text

//
// FOREST FIRE SIMULATION
//
// Using FutureBasic 7.0.34
// August 2025, R.W.
//
Boolean running
BlockOperationRef dCode
OperationQueueRef cQueue
OperationQueueRef opQueue
long N, M
double pfire, ptree, generation
long dimx, dimy
long f(142,142) // the forest
long future(142,142) // the predicted future
CFStringRef gen
CGFloat red, green, blue
colorRef colR
float rndf
pfire=0.00002: ptree=0.002 //probabilities
begin enum 1
_window
_generation
_toggle
end enum
// Build window
void local fn BuildWindow
CGRect r = fn CGRectMake( 0, 0, 570, 570 )
window _window, @"Forest Fire Simulation", r, NSWindowStyleMaskTitled + ¬
NSWindowStyleMaskClosable
WindowSetBackgroundColor( _window, fn ColorBlack) //ColorWindowBackground )
ViewSetFlipped( _WindowContentViewTag, YES )
WindowSubclassContentView(_Window)
ViewSetNeedsDisplay( _windowContentViewTag )
windowcenter (_Window)
AppSetAppearance(fn AppearanceNamed(NSAppearanceNameDarkAqua))
WindowMakeFirstResponder( _Window, _windowContentViewTag )
ViewSetAcceptsFirstResponder( _Window, _true )
end fn
void local fn DrawControls
gen = @""
CGRect r = fn CGRectMake( 10, 532, 220, 32 )
textlabel _generation, gen,r,_window
r = fn CGRectMake( 450, 530, 100, 24 )
button _toggle,,, @"Start", r, , , _Window
end fn
//
// Populate the array with empty and tree cells according to a
// specific probability
// (e.g. a cell has the probability 0.5 to be a tree)
void local fn buildForest
int x, y
// Initialize forest with trees (1) or empty (0)
for y = 1 to N
for x = 1 to M
rndf = (rnd(65536)-1)/65536.0
// a cell has the probability 0.5 to be a tree
if rndf < 0.5 then f(x,y) = 1 else f(x,y) = 0
next
next
end fn
//
// Draw the forest
local fn DrawForest
int x, y
cls
for y = 1 to N
for x = 1 to M
red = 0.0: green = 0.0: blue = 0.0 //black
if f(x,y) == 1
red = 0: green = 0.50: blue = 0 //green
else
if f(x,y) == 2
red = 0.97: green = 0.49: blue = 0 //red
end if
end if
Colr = fn ColorWithRGB(red,green,blue,1.0)
pen 1, colr
oval fill (x*4,y*4,3.2,3.2), colr
next
next
end fn
//
// Simulates the forest fire
local fn simulate
int x, y, xx, yy, localfire
// A burning cell turns into an empty cell
// A tree will burn if at least one neighbor is burning
// A tree ignites with probability pfire even if no neighbor is burning
// An empty space grows a tree with probability ptree
//
for y = 1 to N
for x = 1 to M
rndf = (rnd(65536)-1)/65536.0
select case f(x,y)
case 0 // empty
if rndf < ptree
future(x,y) = 1
else
future(x,y) = 0
end if
case 1 // tree
if rndf < pfire
future(x,y) = 2 // probability of ignition
else
// check neighbors for fire
localFire = 0
for yy = y-1 to y+1
for xx = x-1 to x+1
if f(xx,yy) == 2 then localFire = 1
next
next
if localFire == 1
future(x,y) = 2
else
future(x,y) = 1
end if
end if
case 2 // burning
future(x,y) = 0
end select
next
next
// Copy future to forest
for y = 1 to N
for x = 1 to M
f(x,y) = future(x,y)
next
next
generation++
end fn
//
// Executed as long as we are running
//
local fn tillTheCowsComeHome (dPtr as Ptr)
while running
dispatchmain
fn drawforest
dispatchend
fn Simulate
delay 110
wend
// callback canned
OperationCancel (dCode )
end fn
// Begin animation
void local fn Animate
// setup dispatch queue w/ callback
dCode = fn BlockOperationWithCallback( @fn tillTheCowsComeHome, NULL )
cQueue = fn OperationQueueInit // Init queue
OperationQueueSetMaxConcurrentOperationCount( cQueue, 1 ) // serial only
OperationQueueAddOperations( cQueue, @[dCode], NO ) // add to queue
end fn
//
// App Event handler
//
void local fn DoAppEvent( ev as long )
select ( ev )
case _appWillTerminate
if running then OperationCancel (dCode )
end select
end fn
//
// Dialog handler
void local fn DoDialog( ev as long, tag as long, wnd as long, obj as CFTypeRef )
select ( ev )
case _btnClick
select ( tag )
case _toggle
running = !running // toggles run status
if running
button _toggle,,, @"Stop"
fn Animate
textlabel _generation, @""
else
button _toggle,,, @"Start"
gen = concat(@"Stopped at Generation: ",str(generation))
textlabel _generation, gen
end if
end select
case _windowShouldClose
if running then OperationCancel (dCode )
end
end select
end fn
//==========================================
on dialog fn DoDialog
fn BuildWindow
fn DrawControls
randomize
N = 130 // number of rows
M = 140 // number of columns
generation = 1
running = _False
fn buildForest
fn drawForest
handleEvents