September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,135 +1,124 @@
|
|||
import ceylon.random {
|
||||
|
||||
DefaultRandom
|
||||
}
|
||||
import ceylon.random { DefaultRandom }
|
||||
|
||||
class Cell of tree | empty | burning {
|
||||
|
||||
shared new tree {}
|
||||
shared new empty {}
|
||||
shared new burning {}
|
||||
}
|
||||
abstract class Cell() of tree | dirt | burning {}
|
||||
object tree extends Cell() { string => "A"; }
|
||||
object dirt extends Cell() { string => " "; }
|
||||
object burning extends Cell() { string => "#"; }
|
||||
|
||||
class Forest(Integer width, Integer height, Float f, Float p) {
|
||||
|
||||
value random = DefaultRandom();
|
||||
function chance(Float probability) => random.nextFloat() < probability;
|
||||
|
||||
object doubleBufferedGrid satisfies Iterable<Array<Cell>, Null> {
|
||||
|
||||
function makeGrid(Cell|Cell() initialValue) => [
|
||||
for(j in 0:height)
|
||||
Array {
|
||||
for(i in 0:width)
|
||||
switch(initialValue)
|
||||
case(is Cell) initialValue
|
||||
case(is Cell()) initialValue()
|
||||
}
|
||||
];
|
||||
|
||||
value grids = [
|
||||
makeGrid(() =>
|
||||
if(chance(0.5))
|
||||
then Cell.tree
|
||||
else Cell.empty),
|
||||
makeGrid(Cell.empty)
|
||||
];
|
||||
|
||||
variable value firstIsFront = true;
|
||||
value front => firstIsFront then grids.first else grids.last;
|
||||
value back => firstIsFront then grids.last else grids.first;
|
||||
|
||||
iterator() => front.iterator();
|
||||
shared Cell? get(Integer x, Integer y) => front[y]?.get(x);
|
||||
shared void set(Integer x, Integer y, Cell cell) => back[y]?.set(x, cell);
|
||||
shared void flip() => firstIsFront = !firstIsFront;
|
||||
}
|
||||
|
||||
shared void evolve() {
|
||||
|
||||
function fireNearby(Integer x, Integer y) {
|
||||
for(i in -1..1) {
|
||||
for(j in -1..1) {
|
||||
if(i == 0 && j == 0) {
|
||||
continue;
|
||||
}
|
||||
if(exists cell = doubleBufferedGrid.get(x + i, y + j),
|
||||
cell == Cell.burning) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for(j->row in doubleBufferedGrid.indexed) {
|
||||
for(i->cell in row.indexed) {
|
||||
switch(cell)
|
||||
case(Cell.burning) {
|
||||
doubleBufferedGrid.set(i, j, Cell.empty);
|
||||
}
|
||||
case(Cell.empty) {
|
||||
value nextCell = chance(p) then Cell.tree else Cell.empty;
|
||||
doubleBufferedGrid.set(i, j, nextCell);
|
||||
}
|
||||
case(Cell.tree) {
|
||||
value nextCell =
|
||||
fireNearby(i, j) || chance(f)
|
||||
then Cell.burning
|
||||
else Cell.tree;
|
||||
doubleBufferedGrid.set(i, j, nextCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doubleBufferedGrid.flip();
|
||||
}
|
||||
|
||||
shared void display() {
|
||||
|
||||
void drawLine() => print("-".repeat(width + 2));
|
||||
|
||||
drawLine();
|
||||
for(row in doubleBufferedGrid) {
|
||||
process.write("|");
|
||||
for(cell in row) {
|
||||
switch(cell)
|
||||
case(Cell.empty) {
|
||||
process.write(" ");
|
||||
}
|
||||
case(Cell.tree) {
|
||||
process.write("A");
|
||||
}
|
||||
case(Cell.burning) {
|
||||
process.write("#");
|
||||
}
|
||||
}
|
||||
print("|");
|
||||
}
|
||||
drawLine();
|
||||
}
|
||||
|
||||
value random = DefaultRandom();
|
||||
function chance(Float probability) => random.nextFloat() < probability;
|
||||
value sparked => chance(f);
|
||||
value sprouted => chance(p);
|
||||
|
||||
alias Point => Integer[2];
|
||||
interface Row => {Cell*};
|
||||
|
||||
object doubleBufferedGrid satisfies
|
||||
Correspondence<Point, Cell> &
|
||||
KeyedCorrespondenceMutator<Point, Cell> {
|
||||
|
||||
value grids = [
|
||||
Array {
|
||||
for (j in 0:height)
|
||||
Array {
|
||||
for (i in 0:width)
|
||||
chance(0.5) then tree else dirt
|
||||
}
|
||||
},
|
||||
Array {
|
||||
for (j in 0:height)
|
||||
Array.ofSize(width, dirt)
|
||||
}
|
||||
];
|
||||
|
||||
variable value showFirst = true;
|
||||
value currentState => showFirst then grids.first else grids.last;
|
||||
value nextState => showFirst then grids.last else grids.first;
|
||||
|
||||
shared void swapStates() => showFirst = !showFirst;
|
||||
|
||||
shared {Row*} rows => currentState;
|
||||
|
||||
shared actual Boolean defines(Point key) =>
|
||||
let (x = key[0], y = key[1])
|
||||
0 <= x < width && 0 <= y < height;
|
||||
shared actual Cell? get(Point key) =>
|
||||
let (x = key[0], y = key[1])
|
||||
currentState.get(y)?.get(x);
|
||||
|
||||
shared actual void put(Point key, Cell cell) {
|
||||
value [x, y] = key;
|
||||
nextState.get(y)?.set(x, cell);
|
||||
}
|
||||
}
|
||||
|
||||
variable value evolutions = 0;
|
||||
shared Integer generation => evolutions + 1;
|
||||
|
||||
shared void evolve() {
|
||||
|
||||
evolutions++;
|
||||
|
||||
function firesNearby(Integer x, Integer y) => {
|
||||
for (j in y - 1 : 3)
|
||||
for (i in x - 1 : 3)
|
||||
doubleBufferedGrid[[i, j]]
|
||||
}.coalesced.any(burning.equals);
|
||||
|
||||
for(j->row in doubleBufferedGrid.rows.indexed) {
|
||||
for(i->cell in row.indexed) {
|
||||
switch (cell)
|
||||
case (burning) {
|
||||
doubleBufferedGrid[[i, j]] = dirt;
|
||||
}
|
||||
case (dirt) {
|
||||
doubleBufferedGrid[[i, j]] = sprouted then tree else dirt;
|
||||
}
|
||||
case (tree) {
|
||||
doubleBufferedGrid[[i, j]] =
|
||||
firesNearby(i, j) || sparked
|
||||
then burning else tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doubleBufferedGrid.swapStates();
|
||||
}
|
||||
|
||||
shared void display() {
|
||||
|
||||
void drawLine() => print("-".repeat(width + 2));
|
||||
|
||||
drawLine();
|
||||
for (row in doubleBufferedGrid.rows) {
|
||||
process.write("|");
|
||||
for (cell in row) {
|
||||
process.write(cell.string);
|
||||
}
|
||||
print("|");
|
||||
}
|
||||
drawLine();
|
||||
}
|
||||
}
|
||||
|
||||
shared void run() {
|
||||
|
||||
value forest = Forest(78, 38, 0.02, 0.03);
|
||||
variable value generation = 1;
|
||||
|
||||
while(true) {
|
||||
|
||||
forest.display();
|
||||
forest.evolve();
|
||||
|
||||
print("Generation ``generation++``
|
||||
Press enter for next generation or q and then enter to quit");
|
||||
|
||||
value input = process.readLine();
|
||||
if(exists input) {
|
||||
switch(input.trimmed)
|
||||
case("q" | "Q") {
|
||||
return;
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
value forest = Forest(78, 38, 0.02, 0.03);
|
||||
|
||||
while (true) {
|
||||
|
||||
forest.display();
|
||||
|
||||
print("Generation ``forest.generation``");
|
||||
print("Press enter for next generation or q and then enter to quit");
|
||||
|
||||
value input = process.readLine();
|
||||
if (exists input, input.trimmed.lowercased == "q") {
|
||||
return;
|
||||
}
|
||||
|
||||
forest.evolve();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue