about summary refs log tree commit diff stats
path: root/hest-life.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-05-16 19:41:29 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-05-16 19:41:29 -0700
commit2beeee4d5df00b3ee5679ae96f64759c2fd7de5b (patch)
tree3c8b6575c3b4aff92023c8c863fa1059b06525aa /hest-life.mu
parentfbaa30b5f75724868d5af5150c654f4ecd3789fd (diff)
downloadmu-2beeee4d5df00b3ee5679ae96f64759c2fd7de5b.tar.gz
game of life working at lowest zoom
Diffstat (limited to 'hest-life.mu')
-rw-r--r--hest-life.mu225
1 files changed, 195 insertions, 30 deletions
diff --git a/hest-life.mu b/hest-life.mu
index 411f6f1f..0e979c38 100644
--- a/hest-life.mu
+++ b/hest-life.mu
@@ -26,11 +26,16 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk)
 }
 
 type environment {
-  data: (handle array handle array boolean)
+  data: (handle array handle array cell)
   zoom: int  # 0 = 1024 px per cell; 5 = 4px per cell; each step adjusts by a factor of 4
   tick: int
 }
 
+type cell {
+  curr: boolean
+  next: boolean
+}
+
 fn render screen: (addr screen), _self: (addr environment) {
   clear-screen screen
   var self/esi: (addr environment) <- copy _self
@@ -39,14 +44,16 @@ fn render screen: (addr screen), _self: (addr environment) {
   {
     break-if-!=
     render0 screen, self
-    return
   }
   compare *zoom, 4
   {
     break-if-!=
     render4 screen, self
-    return
   }
+  # clock
+  var tick-a/eax: (addr int) <- get self, tick
+  set-cursor-position screen, 0x78/x, 0/y
+  draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, *tick-a, 7/fg 0/bg
 }
 
 fn render0 screen: (addr screen), _self: (addr environment) {
@@ -104,11 +111,8 @@ fn render0 screen: (addr screen), _self: (addr environment) {
   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x120/y1, 0x320/x2   0x60/y2,  0x2a/color
   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x1c0/y1  0x320/x2  0x180/y2,  0x2a/color
   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x230/y1, 0x320/x2  0x2a0/y2,  0x2a/color
-  # clock
-  var tick-a/eax: (addr int) <- get self, tick
-  set-cursor-position screen, 0x78/x, 0/y
-  draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, *tick-a, 7/fg 0/bg
   # time-variant portion: 16 repeating steps
+  var tick-a/eax: (addr int) <- get self, tick
   var progress/eax: int <- copy *tick-a
   progress <- and 0xf
   # 7 time steps for getting inputs to sum
@@ -201,13 +205,11 @@ fn step _self: (addr environment) {
   {
     break-if-!=
     increment *tick-a
-    return
   }
   compare *zoom, 4
   {
     break-if-!=
     add-to *tick-a, 0x10
-    return
   }
   var tick/eax: int <- copy *tick-a
   tick <- and 0xf
@@ -222,49 +224,104 @@ fn initialize-environment _self: (addr environment) {
   var self/esi: (addr environment) <- copy _self
   var zoom/eax: (addr int) <- get self, zoom
   copy-to *zoom, 4
-  var data-ah/eax: (addr handle array handle array boolean) <- get self, data
+  var data-ah/eax: (addr handle array handle array cell) <- get self, data
   populate data-ah, 0x100
-  var data/eax: (addr array handle array boolean) <- lookup *data-ah
+  var data/eax: (addr array handle array cell) <- lookup *data-ah
   var y/ecx: int <- copy 0
   {
     compare y, 0xc0
     break-if->=
-    var dest-ah/eax: (addr handle array boolean) <- index data, y
+    var dest-ah/eax: (addr handle array cell) <- index data, y
     populate dest-ah, 0x100
     y <- increment
     loop
   }
-  set self, 0x80, 0x5f
-  set self, 0x81, 0x5f
-  set self, 0x7f, 0x60
-  set self, 0x80, 0x60
-  set self, 0x80, 0x61
+  set self, 0x80, 0x5f, 1/alive
+  set self, 0x81, 0x5f, 1/alive
+  set self, 0x7f, 0x60, 1/alive
+  set self, 0x80, 0x60, 1/alive
+  set self, 0x80, 0x61, 1/alive
+  flush self
 }
 
-fn set _self: (addr environment), _x: int, _y: int {
+fn set _self: (addr environment), _x: int, _y: int, _val: boolean {
   var self/esi: (addr environment) <- copy _self
-  var data-ah/eax: (addr handle array handle array boolean) <- get self, data
-  var data/eax: (addr array handle array boolean) <- lookup *data-ah
+  var data-ah/eax: (addr handle array handle array cell) <- get self, data
+  var data/eax: (addr array handle array cell) <- lookup *data-ah
   var y/ecx: int <- copy _y
-  var row-ah/eax: (addr handle array boolean) <- index data, y
-  var row/eax: (addr array boolean) <- lookup *row-ah
+  var row-ah/eax: (addr handle array cell) <- index data, y
+  var row/eax: (addr array cell) <- lookup *row-ah
   var x/ecx: int <- copy _x
-  var dest/eax: (addr boolean) <- index row, x
-  copy-to *dest, 1/true
+  var cell/eax: (addr cell) <- index row, x
+  var dest/eax: (addr boolean) <- get cell, next
+  var val/ecx: boolean <- copy _val
+  copy-to *dest, val
 }
 
 fn state _self: (addr environment), _x: int, _y: int -> _/eax: boolean {
   var self/esi: (addr environment) <- copy _self
-  var data-ah/eax: (addr handle array handle array boolean) <- get self, data
-  var data/eax: (addr array handle array boolean) <- lookup *data-ah
-  var y/ecx: int <- copy _y
-  var row-ah/eax: (addr handle array boolean) <- index data, y
-  var row/eax: (addr array boolean) <- lookup *row-ah
   var x/ecx: int <- copy _x
-  var src/eax: (addr boolean) <- index row, x
+  var y/edx: int <- copy _y
+  # clip at the edge
+  compare x, 0
+  {
+    break-if->=
+    return 0/false
+  }
+  compare y, 0
+  {
+    break-if->=
+    return 0/false
+  }
+  compare x, 0x100/width
+  {
+    break-if-<
+    return 0/false
+  }
+  compare y, 0xc0/height
+  {
+    break-if-<
+    return 0/false
+  }
+  var data-ah/eax: (addr handle array handle array cell) <- get self, data
+  var data/eax: (addr array handle array cell) <- lookup *data-ah
+  var row-ah/eax: (addr handle array cell) <- index data, y
+  var row/eax: (addr array cell) <- lookup *row-ah
+  var cell/eax: (addr cell) <- index row, x
+  var src/eax: (addr boolean) <- get cell, curr
   return *src
 }
 
+fn flush  _self: (addr environment) {
+  var self/esi: (addr environment) <- copy _self
+  var data-ah/eax: (addr handle array handle array cell) <- get self, data
+  var _data/eax: (addr array handle array cell) <- lookup *data-ah
+  var data/esi: (addr array handle array cell) <- copy _data
+  var y/ecx: int <- copy 0
+  {
+    compare y, 0xc0/height
+    break-if->=
+    var row-ah/eax: (addr handle array cell) <- index data, y
+    var _row/eax: (addr array cell) <- lookup *row-ah
+    var row/ebx: (addr array cell) <- copy _row
+    var x/edx: int <- copy 0
+    {
+      compare x, 0x100/width
+      break-if->=
+      var cell-a/eax: (addr cell) <- index row, x
+      var curr-a/edi: (addr boolean) <- get cell-a, curr
+      var next-a/esi: (addr boolean) <- get cell-a, next
+      var val/eax: boolean <- copy *next-a
+      copy-to *curr-a, val
+      copy-to *next-a, 0/dead
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+}
+
 fn render4 screen: (addr screen), _self: (addr environment) {
   var self/esi: (addr environment) <- copy _self
   var y/ecx: int <- copy 0
@@ -307,4 +364,112 @@ fn render4-cell screen: (addr screen), x: int, y: int, color: int {
 }
 
 fn step4 _self: (addr environment) {
+  var self/esi: (addr environment) <- copy _self
+  var y/ecx: int <- copy 0
+  {
+    compare y, 0xc0/height
+    break-if->=
+    var x/edx: int <- copy 0
+    {
+      compare x, 0x100/width
+      break-if->=
+      var n/eax: int <- num-live-neighbors self, x, y
+      # if neighbors < 2, die of loneliness
+      {
+        compare n, 2
+        break-if->=
+        set self, x, y, 0/dead
+      }
+      # if neighbors > 3, die of overcrowding
+      {
+        compare n, 3
+        break-if-<=
+        set self, x, y, 0/dead
+      }
+      # if neighbors = 2, preserve state
+      {
+        compare n, 2
+        break-if-!=
+        var old-state/eax: boolean <- state self, x, y
+        set self, x, y, old-state
+      }
+      # if neighbors = 3, cell quickens to life
+      {
+        compare n, 3
+        break-if-!=
+        set self, x, y, 1/live
+      }
+      x <- increment
+      loop
+    }
+    y <- increment
+    loop
+  }
+  flush self
+}
+
+fn num-live-neighbors _self: (addr environment), x: int, y: int -> _/eax: int {
+  var self/esi: (addr environment) <- copy _self
+  var result/edi: int <- copy 0
+  # row above: zig
+  decrement y
+  decrement x
+  var s/eax: boolean <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  increment x
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  increment x
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  # curr row: zag
+  increment y
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  subtract-from x, 2
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  # row below: zig
+  increment y
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  increment x
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  increment x
+  s <- state self, x, y
+  {
+    compare s, 0/false
+    break-if-=
+    result <- increment
+  }
+  return result
 }