September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -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();
}
}