Browse Source

feat: Adding Game of Life example

Matthias Ladkau 3 years ago
parent
commit
0312fd1314

+ 2 - 2
ecal-support/package.json

@@ -14,12 +14,12 @@
             "id": "ecal",
             "aliases": ["Event Condition Action Language", "ecal"],
             "extensions": [".ecal"],
-            "configuration": "./ecal-support/language-configuration.json"
+            "configuration": "./language-configuration.json"
         }],
         "grammars": [{
             "language": "ecal",
             "scopeName": "source.ecal",
-            "path": "./ecal-support/syntaxes/ecal.tmLanguage.json"
+            "path": "./syntaxes/ecal.tmLanguage.json"
         }]
     }
 }

+ 2 - 2
ecal-support/syntaxes/ecal.tmLanguage.json

@@ -48,14 +48,14 @@
 		},
 		"identifiers": {
 			"patterns": [{
-				"match": "([a-z]+)\\(",
+				"match": "([a-zA-Z]+)\\(",
 				"captures": {
 					"1": {
 						"name": "entity.name.function.ecal"
 					}
 				}
 			}, {
-				"match": "([a-z]+) :?=",
+				"match": "([a-zA-Z]+) :?=",
 				"captures": {
 					"1": {
 						"name": "storage.type.var.ecal"

+ 192 - 0
examples/game_of_life/game_of_life.ecal

@@ -0,0 +1,192 @@
+/*
+Conway's Game of Life
+
+A zero-player game that evolves based on its initial state.
+
+Some examples:
+
+grid := [              # Normally evolving
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+]
+
+grid := [              # Blinker oscillator
+    [ 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 1, 0, 0 ], 
+    [ 0, 0, 1, 0, 0 ], 
+    [ 0, 0, 1, 0, 0 ], 
+    [ 0, 0, 0, 0, 0 ], 
+]
+
+grid := [              # Still life
+    [ 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 1, 1, 0, 0 ], 
+    [ 0, 1, 0, 0, 1, 0 ], 
+    [ 0, 0, 1, 1, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0 ], 
+]
+
+grid := [              # Glider spaceship
+    [ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+]
+
+*/
+
+grid := [              # Penta-decathlon oscillator
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ]
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ], 
+    [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+]
+
+/*
+output displays a given grid.
+*/
+func output(grid) {
+    for row in grid {
+        displayRow := []
+        for i in row { 
+            if i == 0 { 
+                i := ' '
+            } else { 
+                i := '*'
+            }
+            displayRow := add(displayRow, i)
+        }
+        log("{{displayRow}}")
+    }
+}
+
+/*
+newGrid allocates a new grid.
+*/
+func newGrid() {
+    result := []
+
+    for row in range(0, len(grid)-1) {
+        newrow := []
+        for col in range(0, len(grid[0])-1) {
+            newrow := add(newrow, 0)
+        }
+        result := add(result, newrow)
+    }
+
+    return result
+}
+
+/*
+compareGrids compares two grids and returns a delta of differences.
+*/
+func compareGrids(g1, g2) {
+    delta := 0
+
+    for row in range(0, len(grid)-1) {
+        for col in range(0, len(grid[0])-1) {
+            if g1[row][col] != g2[row][col] {
+                delta := delta + 1
+            }
+        }
+    }
+
+    return delta
+}
+
+/*
+nextGen calculates the next generation for a given grid.
+*/
+func nextGen() {
+
+    future := newGrid()
+
+    for row in range(0, len(grid)-1) {
+        for col in range(0, len(grid[0])-1) {
+
+            # Finding number of neighbours that are alive 
+            
+            aliveNeighbours := 0
+            for i in range(-1, 1) { 
+                for j in range(-1, 1) {
+                    try {
+                      aliveNeighbours := aliveNeighbours + grid[row + i][col + j]
+                    } except {
+                        # Don't care about out of bounds errors
+                    }
+                }
+            }
+
+            # Subtract the cell itself if alive 
+
+            aliveNeighbours := aliveNeighbours - grid[row][col]; 
+
+            # Apply the rules
+
+            if grid[row][col] == 1 and aliveNeighbours < 2 {
+                # Cell is lonely and dies         
+            } elif grid[row][col] == 1 and aliveNeighbours > 3 {
+                # Cell dies due to over population             
+            } elif grid[row][col] == 0 and aliveNeighbours == 3 { 
+                # A new cell is born 
+                future[row][col] := 1
+            } else {
+                # Unchanged
+                future[row][col] := grid[row][col]
+            }
+
+            # log("row: {{row}} col: {{col}} val: {{grid[row][col]}} aliveNeighbours:{{aliveNeighbours}} -> {{future[row][col]}}")
+
+        }
+    }
+
+    return future
+}
+
+output(grid)
+
+# Evolve the grid for 33 generations
+
+for i in range(1, 33) {
+    next := nextGen()
+    
+    delta := compareGrids(grid, next)
+    if delta == 0 {
+        delta := "0 (still life)"
+    }
+    
+    log("Gen: {{i}} - delta {{delta}}")
+    
+    output(next)
+    grid := next
+}

+ 2 - 0
examples/game_of_life/run.sh

@@ -0,0 +1,2 @@
+#!/bin/sh
+../../ecal run game_of_life.ecal