RosettaCodeData/Task/Forest-fire/Lua/forest-fire.lua

98 lines
2.4 KiB
Lua

-- ForestFire automaton implementation
-- Rules: at each step:
-- 1) a burning tree disappears
-- 2) a non-burning tree starts burning if any of its neighbours is
-- 3) an empty spot may generate a tree with prob P
-- 4) a non-burning tree may ignite with prob F
local socket = require 'socket' -- needed for socket.sleep
local curses = require 'curses'
local p_spawn, p_ignite = 0.005, 0.0002
local naptime = 0.03 -- seconds
local forest_x, forest_y = 60, 30
local forest = (function (x, y)
local wrl = {}
for i = 1, y do
wrl[i] = {}
for j = 1, x do
local rand = math.random()
wrl[i][j] = (rand < 0.5) and 1 or 0
end
end
return wrl
end)(forest_x, forest_y)
math.randomseed(os.time())
forest.step = function (self)
for i = 1, #self do
for j = 1, #self[i] do
if self[i][j] == 0 then
if math.random() < p_spawn then self[i][j] = 1 end
elseif self[i][j] == 1 then
if self:ignite(i, j) or math.random() < p_ignite then self[i][j] = 2 end
elseif self[i][j] == 2 then self[i][j] = 0
else error("Error: forest[" .. i .. "][" .. j .. "] is " .. self[i][j] .. "!")
end
end
end
end
forest.draw = function (self)
for i = 1, #self do
for j = 1, #self[i] do
if self[i][j] == 0 then win:mvaddch(i,j," ")
elseif self[i][j] == 1 then
win:attron(curses.color_pair(1))
win:mvaddch(i,j,"Y")
win:attroff(curses.color_pair(1))
elseif self[i][j] == 2 then
win:attron(curses.color_pair(2))
win:mvaddch(i,j,"#")
win:attroff(curses.color_pair(2))
else error("self[" .. i .. "][" .. j .. "] is " .. self[i][j] .. "!")
end
end
end
end
forest.ignite = function (self, i, j)
for k = i - 1, i + 1 do
if k < 1 or k > #self then goto continue1 end
for l = j - 1, j + 1 do
if l < 1 or
l > #self[i] or
math.abs((k - i) + (l - j)) ~= 1
then
goto continue2
end
if self[k][l] == 2 then return true end
::continue2::
end
::continue1::
end
return false
end
local it = 1
curses.initscr()
curses.start_color()
curses.echo(false)
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
win = curses.newwin(forest_y + 2, forest_x, 0, 0)
win:clear()
win:mvaddstr(forest_y + 1, 0, "p_spawn = " .. p_spawn .. ", p_ignite = " .. p_ignite)
repeat
forest:draw()
win:move(forest_y, 0)
win:clrtoeol()
win:addstr("Iteration: " .. it .. ", nap = " .. naptime*1000 .. "ms")
win:refresh()
forest:step()
it = it + 1
socket.sleep(naptime)
until false