Skip to content

Instantly share code, notes, and snippets.

@mecdemort
Created March 24, 2011 19:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mecdemort/885740 to your computer and use it in GitHub Desktop.
Save mecdemort/885740 to your computer and use it in GitHub Desktop.
Game of life
(definterface AutomataOps
(^long bound [^long x])
(^long getCell [^long x ^long y])
(^long countNeighbors [^long x ^long y])
(^long alive [^long cell ^long neighbors])
(^long updateCell [^long x ^long y]))
(defprotocol Automata
(update [this]))
(deftype CellularAutomata [^long dim ^longs cells ^longs birth ^longs live]
AutomataOps
(bound [this x]
(cond (neg? x) (+ x dim)
(>= x dim) (- x dim)
:else x))
(getCell [this x y]
(let [x (.bound this x)
y (.bound this y)]
(aget cells (+ (unchecked-multiply dim x) y))))
(countNeighbors [this x y]
(-> (.getCell this (dec x) (dec y))
(+ , (.getCell this (dec x) y))
(+ , (.getCell this (dec x) (inc y)))
(+ , (.getCell this x (dec y)))
(+ , (.getCell this x (inc y)))
(+ , (.getCell this (inc x) (dec y)))
(+ , (.getCell this (inc x) y))
(+ , (.getCell this (inc x) (inc y)))))
(alive [this cell neighbors]
(if (zero? cell)
(if (and (<= (aget birth 0) neighbors)
(<= neighbors (aget birth 1)))
(long 1)
cell)
(if (and (<= (aget live 0) neighbors)
(<= neighbors (aget live 1)))
cell
(long 0))))
(updateCell [this x y]
(.alive this (.getCell this x y) (.countNeighbors this x y)))
Automata
(update [this]
(CellularAutomata.
dim
(amap cells i res
(let [i (long i)
x (unchecked-divide i dim)
y (unchecked-remainder i dim)]
(.updateCell this x y)))
birth
live)))
(defn new-automata [dim]
(CellularAutomata.
dim
(long-array (repeatedly (* dim dim) #(rand-int 2)))
(long-array [3 3])
(long-array [2 3])))
(def dim 100)
(def world (atom (new-automata dim)))
(defn iterate-world []
(swap! world update))
;;--------------------- UI --------------------------------
(import
'(java.awt Color Graphics Dimension)
'(java.awt.event WindowAdapter MouseAdapter)
'(java.awt.image BufferedImage)
'(javax.swing JPanel JFrame SwingUtilities))
(declare start stop)
(let [scale 5
animation-sleep-ms 50
run-sleep-ms 75
running (atom true)
stopfn #(reset! running nil)
render (fn [g]
(let [world @world
img (BufferedImage. (* scale dim)
(* scale dim)
BufferedImage/TYPE_INT_ARGB)
bg (.getGraphics img)]
(doto bg
(.setColor Color/BLUE)
(.fillRect 0 0 (.getWidth img) (.getHeight img))
(.setColor Color/WHITE))
(doseq [x (range dim)
y (range dim)
:when (zero? (.getCell world x y))]
(.fillRect bg (* x scale) (* y scale) scale scale))
(.drawImage g img 0 0 nil)
(.dispose bg)))
mouse-listener (proxy [MouseAdapter] []
(mouseClicked [e]
(if @running
(stopfn)
(#'start))))
panel (doto (proxy [JPanel] [] (paint [g] (render g)))
(.setPreferredSize
(Dimension.
(* scale dim)
(* scale dim)))
(.addMouseListener mouse-listener))
window-listener (proxy [WindowAdapter] []
(windowClosed [e] (stopfn)))
frame (doto (JFrame.)
(.add panel)
(.addWindowListener window-listener)
(.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
.pack)]
(defn start []
(.show frame)
(reset! running true)
(future
(while @running
(SwingUtilities/invokeAndWait #(.repaint frame))
(Thread/sleep animation-sleep-ms)))
(future
(while @running
(iterate-world)
(Thread/sleep run-sleep-ms))))
(def stop stopfn))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment