Skip to content

Instantly share code, notes, and snippets.

@chochos
Last active November 29, 2020 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chochos/5052213 to your computer and use it in GitHub Desktop.
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/
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++``\">&nbsp;</td>");
}
sb.append("</tr>");
}
document.getElementById("lifegrid").innerHTML=sb.string;
for (c in life) {
dynamic {
c.state = Math.random() > 0.7;
}
}
draw1(draw2)();
}
@mrduckieduck
Copy link

That's nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment