1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// Conway's Game of Life in Baba Yaga
// Clean, working implementation
// Get element at index from list (with bounds checking)
at : xs i ->
when (i >= 0 and i < length xs) is
true then slice xs i (i + 1).0
_ then 0;
// Get 2D element from grid
get2d : grid row col ->
when (row >= 0 and row < length grid) is
true then at (at grid row) col
_ then 0;
// Create range of integers [start, end)
range : start end ->
when (start >= end) is
true then []
_ then prepend start (range (start + 1) end);
// Sum a list of numbers
sum : xs -> reduce (acc x -> acc + x) 0 xs;
// Count living neighbors around position (row, col)
countNeighbors : grid row col ->
with (
// Get all 8 neighbor positions
neighbors : [
get2d grid (row - 1) (col - 1),
get2d grid (row - 1) col,
get2d grid (row - 1) (col + 1),
get2d grid row (col - 1),
get2d grid row (col + 1),
get2d grid (row + 1) (col - 1),
get2d grid (row + 1) col,
get2d grid (row + 1) (col + 1)
];
) -> sum neighbors;
// Apply Game of Life rules to a single cell
nextCellState : grid row col ->
with (
current : get2d grid row col;
neighbors : countNeighbors grid row col;
isAlive : current = 1;
) ->
when isAlive is
true then
when (neighbors = 2 or neighbors = 3) is
true then 1
_ then 0
_ then
when (neighbors = 3) is
true then 1
_ then 0;
// Generate next row for the grid
nextRow : grid rowIndex width ->
map (col -> nextCellState grid rowIndex col) (range 0 width);
// Generate next generation of the entire grid
nextGeneration : grid ->
with (
height : length grid;
width : length (at grid 0);
) ->
map (row -> nextRow grid row width) (range 0 height);
// Pretty print a grid
printGrid : grid title ->
with (
printRow : row -> io.out (map (cell -> when cell is 1 then "#" _ then ".") row);
) -> with (
_ : io.out "";
_ : io.out title;
_ : io.out (map (_ -> "-") (range 0 20));
_ : map printRow grid;
_ : io.out "";
) -> grid;
// Test patterns
// Glider pattern (moves diagonally)
glider : [
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[1, 1, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]
];
// Blinker pattern (oscillates)
blinker : [
[0, 0, 0],
[1, 1, 1],
[0, 0, 0]
];
// Block pattern (still life)
block : [
[1, 1],
[1, 1]
];
// Run simulations
io.out "Conway's Game of Life in Baba Yaga";
io.out "====================================";
// Glider evolution
g0 : printGrid glider "Glider - Generation 0";
g1 : printGrid (nextGeneration g0) "Glider - Generation 1";
g2 : printGrid (nextGeneration g1) "Glider - Generation 2";
g3 : printGrid (nextGeneration g2) "Glider - Generation 3";
g4 : printGrid (nextGeneration g3) "Glider - Generation 4";
// Blinker oscillation
b0 : printGrid blinker "Blinker - Generation 0";
b1 : printGrid (nextGeneration b0) "Blinker - Generation 1";
b2 : printGrid (nextGeneration b1) "Blinker - Generation 2";
// Block (should stay the same)
bl0 : printGrid block "Block - Generation 0";
bl1 : printGrid (nextGeneration bl0) "Block - Generation 1";
io.out "Simulation complete!";
|