Carp/examples/game_of_life.carp

126 lines
3.3 KiB
Plaintext
Raw Permalink Normal View History

2017-09-06 11:05:19 +03:00
(use IO)
(use System)
(use Int)
(use Double)
(use Array)
2017-06-26 12:15:03 +03:00
(load "core/SDL.carp")
(load "core/SDL_image.carp")
2018-10-25 13:45:31 +03:00
(use SDL)
(use SDLApp)
(use SDL.Event)
(use SDL.Keycode)
(use SDL.Mouse)
(use SDL.MouseState)
2017-06-26 12:15:03 +03:00
(Project.config "title" "Life")
2017-06-26 12:15:03 +03:00
(def width 60)
(def height 60)
(defn handle-key [app event play]
2018-10-25 13:45:31 +03:00
(let [key (keycode event)]
2017-06-26 12:15:03 +03:00
(cond
2018-10-25 13:45:31 +03:00
(= key escape) (do (stop app) false)
(= key space) (not play)
(do (println "Unrecognized key.")
2017-06-26 12:15:03 +03:00
play))))
(defn handle-mouse [world]
2018-10-25 13:45:31 +03:00
(let [mouse &(MouseState.get)
index (+ (/ @(x mouse) 10) (* (/ @(y mouse) 10) width))]
2019-10-31 12:23:23 +03:00
(aset! world index (not @(unsafe-nth world index)))))
2017-06-26 12:15:03 +03:00
(defn handle-events [app rend world play]
2018-10-25 13:45:31 +03:00
(let [event (init)
2017-06-26 12:15:03 +03:00
new-play play]
(do
(while (poll (Pointer.address &event))
2018-10-25 13:45:31 +03:00
(let [et (type (ref event))]
(cond (= et quit) (stop app)
(= et key-down) (set! new-play (handle-key app (ref event) play))
(= et mouse-button-down) (handle-mouse world)
2017-06-26 12:15:03 +03:00
())))
new-play)))
(defn cell-index [x y]
(+ x (* y width)))
(defn draw [rend world play]
(do
(if play
2018-10-25 13:45:31 +03:00
(set-render-draw-color rend 0 0 0 255)
(set-render-draw-color rend 0 100 50 255))
(render-clear rend)
2017-06-26 12:15:03 +03:00
(for [y 0 height]
(for [x 0 width]
2018-10-25 13:45:31 +03:00
(let [square (rect (* x 10) (* y 10) 9 9)]
2017-06-26 12:15:03 +03:00
(do
2019-10-31 12:23:23 +03:00
(if @(unsafe-nth world (cell-index x y))
2018-10-25 13:45:31 +03:00
(set-render-draw-color rend 255 255 255 255)
(set-render-draw-color rend 50 50 50 255))
(render-fill-rect rend (Pointer.address &square))
2017-06-26 12:15:03 +03:00
))))
2018-10-25 13:45:31 +03:00
(render-present rend)))
2017-06-26 12:15:03 +03:00
(defn cell-value [world x y]
(cond
(< x 0) 0
(< (dec width) x) 0
(< y 0) 0
(< (dec height) y) 0
2019-10-31 12:23:23 +03:00
(if @(unsafe-nth world (cell-index x y))
2017-06-26 12:15:03 +03:00
1
0)))
(defn neighbours [world x y]
(let [a (cell-value world (dec x) (dec y))
b (cell-value world x (dec y))
c (cell-value world (inc x) (dec y))
2017-06-26 12:15:03 +03:00
d (cell-value world (dec x) y)
e 0
f (cell-value world (inc x) y)
2017-06-26 12:15:03 +03:00
g (cell-value world (dec x) (inc y))
h (cell-value world x (inc y))
i (cell-value world (inc x) (inc y))]
(sum (ref [a b c
d e f
g h i]))))
(defn tick [world newWorld]
(for [i 0 (length world)]
2017-06-26 12:15:03 +03:00
(let [x (mod i height)
y (/ i width)
total (neighbours world x y)
newState (cond
(< total 2) false
(= total 3) true
(> total 3) false
2019-10-31 12:23:23 +03:00
@(unsafe-nth world i))]
2017-06-26 12:15:03 +03:00
(aset! newWorld i newState))))
(defn flip []
(= 0 (random-between 0 20)))
(defn main []
(do
2018-10-25 13:45:31 +03:00
(Random.seed)
(let [app (create "~ Game of Life ~" 800 600)
rend @(renderer &app)
2020-03-17 23:31:46 +03:00
world (repeat (* height width) &flip)
2017-06-26 12:15:03 +03:00
play false]
(while true
(do
(let [new-play (handle-events (ref app) rend (ref world) play)]
(do
(set! play new-play)
(if new-play
2018-10-25 13:45:31 +03:00
(let [newWorld (replicate (* height width) &false)]
2017-06-26 12:15:03 +03:00
(do
(tick (ref world) (ref newWorld))
(set! world newWorld)
2018-10-25 13:45:31 +03:00
(delay 50)))
2017-06-26 12:15:03 +03:00
())))
(draw rend (ref world) play)
2018-10-25 13:45:31 +03:00
(delay 30))))))