about summary refs log tree commit diff stats
path: root/js/baba-yaga/scratch/baba/conway.baba
blob: a8811a71d904c0b45170b8fd3bfb4e8f7b1b1e82 (plain) (blame)
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!";