RosettaCodeData/Task/Forest-fire/D/forest-fire-2.d

69 lines
2.1 KiB
D

import std.stdio, std.random, std.algorithm, std.typetuple,
simpledisplay;
enum double TREE_PROB = 0.55; // Original tree probability.
enum double F_PROB = 0.01; // Auto combustion probability.
enum double P_PROB = 0.01; // Tree creation probability.
enum worldSide = 600;
enum Cell : ubyte { empty, tree, burning }
alias World = Cell[worldSide][];
immutable white = Color(255, 255, 255),
red = Color(255, 0, 0),
green = Color(0, 255, 0);
void nextState(ref World world, ref World nextWorld,
ref Xorshift rnd, Image img) {
immutable nr = world.length;
immutable nc = world[0].length;
foreach (immutable r, const row; world)
foreach (immutable c, immutable elem; row)
START: final switch (elem) with (Cell) {
case empty:
img.putPixel(c, r, white);
nextWorld[r][c] = rnd.uniform01 < P_PROB ? tree : empty;
break;
case tree:
img.putPixel(c, r, green);
foreach (immutable rowShift; TypeTuple!(-1, 0, 1))
foreach (immutable colShift; TypeTuple!(-1, 0, 1))
if ((r + rowShift) >= 0 && (r + rowShift) < nr &&
(c + colShift) >= 0 && (c + colShift) < nc &&
world[r + rowShift][c + colShift] == Cell.burning) {
nextWorld[r][c] = Cell.burning;
break START;
}
nextWorld[r][c]= rnd.uniform01 < F_PROB ? burning : tree;
break;
case burning:
img.putPixel(c, r, red);
nextWorld[r][c] = empty;
break;
}
swap(world, nextWorld);
}
void main() {
auto rnd = Xorshift(1);
auto world = new World(worldSide);
foreach (ref row; world)
foreach (ref el; row)
el = rnd.uniform01 < TREE_PROB ? Cell.tree : Cell.empty;
auto nextWorld = new World(world[0].length);
auto w= new SimpleWindow(world.length,world[0].length,"ForestFire");
auto img = new Image(w.width, w.height);
w.eventLoop(1, {
auto painter = w.draw;
nextState(world, nextWorld, rnd, img);
painter.drawImage(Point(0, 0), img);
});
}