Skip to content

Instantly share code, notes, and snippets.

@CFiggers
Created June 28, 2024 03:06
Show Gist options
  • Save CFiggers/aa9b57ba48c11fe81733982f5ae5b63b to your computer and use it in GitHub Desktop.
Save CFiggers/aa9b57ba48c11fe81733982f5ae5b63b to your computer and use it in GitHub Desktop.
# John Conway's Game of Life
(def- window
(seq [x :range [-1 2]
y :range [-1 2]
:when (not (and (zero? x) (zero? y)))]
[x y]))
(defn- neighbors
[[x y]]
(map (fn [[x1 y1]] [(+ x x1) (+ y y1)]) window))
(defn tick
"Get the next state in the Game Of Life."
[state]
(def cell-set (frequencies state))
(def neighbor-set (frequencies (mapcat neighbors state)))
(seq [coord :keys neighbor-set
:let [count (get neighbor-set coord)]
:when (or (= count 3) (and (get cell-set coord) (= count 2)))]
coord))
(def x-axis
``
-10 -8 -6 -4 -2 0 2 4 6 8 10
-9 -7 -5 -3 -1 1 3 5 7 9
``)
(defn draw
"Draw cells in the game of life from (x1, y1) to (x2, y2)"
[state &named x1 y1 x2 y2]
(def cellset @{})
(each cell state (put cellset cell true))
(loop [:before (print x-axis)
y :down-to [y1 y2]
:before (prinf "%3d " y)
:after (print)
x :range-to [x1 x2]]
(file/write
stdout
(cond
(get cellset [x y]) "X "
(and (= 0 x) (= 0 y)) "+─"
(= y 0) "──"
(= x 0) "| "
". ")))
(print))
(defmacro cursor-up [&opt n]
(default n 1)
(with-syms [$n]
~(let [,$n ,n]
(prin (string/format "\e[%dA" ,$n)))))
(defmacro cursor-down [&opt n]
(default n 1)
(with-syms [$n]
~(let [,$n ,n]
(prin (string/format "\e[%dB" ,$n)))))
(defmacro hide-cursor [] '(prin "\e[?25l"))
(defmacro show-cursor [] '(prin "\e[?25h"))
(def run-for-steps 30)
(def board-quad-size 10)
(defn translate [arr dx dy]
(seq [[x y] :in arr]
[(+ x dx) (+ y dy)]))
(defn main
[& args]
# Print the first 20 generations of a glider
(def glider @[[-1 -1] [-1 0] [-1 1] [0 -1] [1 0]])
(var *state* @[])
(array/concat *state*
glider
(translate glider 0 -6)
(translate glider 6 0))
(def move-by (+ (* 2 board-quad-size) 5))
(defer (show-cursor) (hide-cursor)
(for i 0 run-for-steps
(print "generation " i)
(draw *state*
:x1 (- board-quad-size)
:y1 board-quad-size
:x2 board-quad-size
:y2 (- board-quad-size))
(os/sleep 0.1)
(cursor-up move-by)
(set *state* (tick *state*)))
(cursor-down move-by)))
@CFiggers
Copy link
Author

A modification of this example, which is Copyright (c) 2023 Calvin Rose and contributors

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