Last active
November 29, 2020 08:37
-
-
Save chochos/5052213 to your computer and use it in GitHub Desktop.
The Game of Life, implemented in Ceylon, for display in the Ceylon web IDE. You can run this on https://trybeta-ceylon.rhcloud.com/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cell(index) { | |
doc "The index of the Cell inside its Matrix." | |
shared Integer index; | |
doc "The current state of the Cell." | |
shared variable Boolean state = false; | |
doc "The next state of the Cell." | |
variable Boolean ns = false; | |
shared Boolean nextState { return ns; } | |
assign nextState { | |
ns = nextState; | |
} | |
doc "Evaluates the next state of the Cell, which | |
depends on the states of its neighboring cells." | |
shared void evaluateNextState([Cell+] neighbors) { | |
value alives = neighbors.count((Cell c) => c.state); | |
if (state) { | |
ns = alives > 1 && alives < 4; | |
} else { | |
ns = alives == 3; | |
} | |
} | |
doc "Copies the next state to the current state." | |
shared void evolve() { | |
state = ns; | |
} | |
shared actual String string => | |
"Cell: ``state then 1 else 0``"; | |
} | |
class Matrix(gridSize) satisfies Iterable<Cell> { | |
doc "The number of rows and columns of the Matrix." | |
shared Integer gridSize; | |
value sb = SequenceBuilder<Cell>(); | |
for (i in 0..(gridSize*gridSize-1)) { | |
sb.append(Cell(i)); | |
} | |
value grid = sb.sequence; | |
shared actual Iterator<Cell> iterator => | |
grid.iterator; | |
doc "Returns the cells to the left and righ of the cell | |
at the specified index." | |
shared [Cell,Cell] getLeftRightNeighbors(Integer index) { | |
variable value i = index - 1; | |
//The cell to the left | |
if (index%gridSize == 0) { | |
i+=gridSize; | |
} | |
assert(exists c1 = grid[i]); | |
//The cell to the right | |
i = index + 1; | |
if (i%gridSize == 0) { | |
i -= gridSize; | |
} | |
assert(exists c2 = grid[i]); | |
return [c1,c2]; | |
} | |
doc "Returns the 8 cells surrounding the one at | |
the specified index." | |
shared [Cell+] getNeighbors(Integer index) { | |
value sb = SequenceBuilder<Cell>(); | |
//Left and right | |
variable value sameRow = getLeftRightNeighbors(index); | |
sb.append(sameRow[0]); | |
sb.append(sameRow[1]); | |
//The cell above | |
variable value i = index - gridSize; | |
if (i < 0) { | |
i += grid.size; | |
} | |
if (exists c = grid[i]) { | |
sb.append(c); | |
sameRow = getLeftRightNeighbors(i); | |
sb.append(sameRow[0]); | |
sb.append(sameRow[1]); | |
} | |
//The cell below | |
i = index + gridSize; | |
if (i >= grid.size) { | |
i -= grid.size; | |
} | |
if (exists c = grid[i]) { | |
sb.append(c); | |
sameRow = getLeftRightNeighbors(i); | |
sb.append(sameRow[0]); | |
sb.append(sameRow[1]); | |
} | |
assert(nonempty r = sb.sequence); | |
return r; | |
} | |
shared void beginEvaluate(void draw(Cell c)) { | |
for (c in this) { | |
c.evaluateNextState(getNeighbors(c.index)); | |
draw(c); | |
} | |
} | |
shared void finishEvaluate(void draw(Cell c)) { | |
for (c in this) { | |
c.evolve(); | |
draw(c); | |
} | |
} | |
doc "Sets the state of the cell at the specified index." | |
shared void setState(Integer index, Boolean state = true) { | |
if (exists c = grid[index]) { | |
c.state = state; | |
} | |
} | |
} | |
value life = Matrix(20); | |
void draw1(void f())() { | |
dynamic { | |
life.beginEvaluate(void (Cell c) { | |
value td = document.getElementById("c"+c.index.string); | |
if (c.state!=c.nextState) { | |
td.setAttribute("style", c.state then "background:#800" else "background:#b00"); | |
} | |
}); | |
setTimeout(f, 50); | |
} | |
} | |
void draw2() { | |
dynamic { | |
life.finishEvaluate(void(Cell c) { | |
value td = document.getElementById("c"+c.index.string); | |
td.setAttribute("style", c.state then "background:#f00" else "background:#000"); | |
}); | |
setTimeout(draw1(draw2), 150); | |
} | |
} | |
dynamic { | |
if (!document.getElementById("lifegrid") exists) { | |
value table = document.createElement("table"); | |
table.setAttribute("id", "lifegrid"); | |
table.setAttribute("style", "border:0;background:black"); | |
value corePage = document.getElementById("core-page"); | |
corePage.insertBefore(table, corePage.childNodes[3]); | |
} | |
value sb = StringBuilder(); | |
variable value count = 0; | |
for (row in 1..life.gridSize) { | |
sb.append("<tr>"); | |
for (col in 1..life.gridSize) { | |
sb.append("<td style=\"background:#000\" id=\"c``count++``\"> </td>"); | |
} | |
sb.append("</tr>"); | |
} | |
document.getElementById("lifegrid").innerHTML=sb.string; | |
for (c in life) { | |
dynamic { | |
c.state = Math.random() > 0.7; | |
} | |
} | |
draw1(draw2)(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That's nice!