-
Notifications
You must be signed in to change notification settings - Fork 178
/
game_of_life.carp
125 lines (112 loc) · 3.31 KB
/
game_of_life.carp
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
(use IO)
(use System)
(use Int)
(use Double)
(use Array)
(load "core/SDL.carp")
(load "core/SDL_image.carp")
(use SDL)
(use SDLApp)
(use SDL.Event)
(use SDL.Keycode)
(use SDL.Mouse)
(use SDL.MouseState)
(Project.config "title" "Life")
(def width 60)
(def height 60)
(defn handle-key [app event play]
(let [key (keycode event)]
(cond
(= key escape) (do (stop app) false)
(= key space) (not play)
(do (println "Unrecognized key.")
play))))
(defn handle-mouse [world]
(let [mouse &(MouseState.get)
index (+ (/ @(x mouse) 10) (* (/ @(y mouse) 10) width))]
(aset! world index (not @(unsafe-nth world index)))))
(defn handle-events [app rend world play]
(let [event (init)
new-play play]
(do
(while (poll (Pointer.address &event))
(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)
())))
new-play)))
(defn cell-index [x y]
(+ x (* y width)))
(defn draw [rend world play]
(do
(if play
(set-render-draw-color rend 0 0 0 255)
(set-render-draw-color rend 0 100 50 255))
(render-clear rend)
(for [y 0 height]
(for [x 0 width]
(let [square (rect (* x 10) (* y 10) 9 9)]
(do
(if @(unsafe-nth world (cell-index x y))
(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))
))))
(render-present rend)))
(defn cell-value [world x y]
(cond
(< x 0) 0
(< (dec width) x) 0
(< y 0) 0
(< (dec height) y) 0
(if @(unsafe-nth world (cell-index x y))
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))
d (cell-value world (dec x) y)
e 0
f (cell-value world (inc x) y)
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)]
(let [x (mod i height)
y (/ i width)
total (neighbours world x y)
newState (cond
(< total 2) false
(= total 3) true
(> total 3) false
@(unsafe-nth world i))]
(aset! newWorld i newState))))
(defn flip []
(= 0 (random-between 0 20)))
(defn main []
(do
(Random.seed)
(let [app (create "~ Game of Life ~" 800 600)
rend @(renderer &app)
world (repeat (* height width) &flip)
play false]
(while true
(do
(let [new-play (handle-events (ref app) rend (ref world) play)]
(do
(set! play new-play)
(if new-play
(let [newWorld (replicate (* height width) &false)]
(do
(tick (ref world) (ref newWorld))
(set! world newWorld)
(delay 50)))
())))
(draw rend (ref world) play)
(delay 30))))))