-
Notifications
You must be signed in to change notification settings - Fork 0
/
Game.elm
128 lines (102 loc) · 3.54 KB
/
Game.elm
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
126
127
128
module Game (init, view, update,
pixelToCellCoord, Model,
Update (Metabolism, Evolve),
Metabolism (Mitosis, Apoptosis, CircleOfLife),
CellCoord (CellCoord),
getCell) where
import Graphics.Element as GElem exposing (Element)
import Graphics.Collage as GColl exposing (Form)
import Array exposing (Array)
import Cell
import Matrix exposing (Matrix)
import Util
(canvas_width, canvas_height) = (1600, 800)
(cell_count_w, cell_count_h) = (100, 50)
-- model
type alias Model = Matrix Cell.Model
type CellCoord = CellCoord (Int, Int)
init : Model
init =
Matrix.create (cell_count_w, cell_count_h) Cell.Dead
revertCell : Model -> CellCoord -> Model
revertCell model coord =
let cellModel = getCell model coord
in setCell model coord (Cell.reverse cellModel)
getCell : Model -> CellCoord -> Cell.Model
getCell model (CellCoord coord) =
Matrix.get model coord
setCell : Model -> CellCoord -> Cell.Model -> Matrix Cell.Model
setCell model (CellCoord coord) cell =
Matrix.set model coord cell
getCellNeighbours : Model -> CellCoord -> List Cell.Model
getCellNeighbours model (CellCoord coord) =
Matrix.neighbours model coord
aliveNeighbours : CellCoord -> Model -> Int
aliveNeighbours coord model =
let countAlive cellModel count =
case cellModel of
Cell.Alive -> count + 1
Cell.Dead -> count
in List.foldl countAlive 0 (getCellNeighbours model coord)
evolveCell : CellCoord -> Model -> Cell.Model
evolveCell coord model =
let n = aliveNeighbours coord model
in case getCell model coord of
Cell.Alive -> if
| n < 2 -> Cell.Dead
| n > 3 -> Cell.Dead
| otherwise -> Cell.Alive
Cell.Dead -> if
| n == 3 -> Cell.Alive
| otherwise -> Cell.Dead
evolve : Model -> Model
evolve model =
Matrix.indexedMap (\index _ -> evolveCell (CellCoord index) model) model
-- view
view : Model -> Element
view =
scene << draw
scene : List Form -> Element
scene forms =
GColl.collage canvas_width canvas_height (
calibrate (-canvas_width / 2 + 50, -canvas_height / 2 + 50) forms)
calibrate : (Float, Float) -> List Form -> List Form
calibrate offset forms =
List.map (GColl.move offset) forms
draw : Model -> List Form
draw model =
List.map2 (<|)
(List.concat arrangementFuncs)
(List.concat <| drawCells model)
drawCells : Model -> List (List Form)
drawCells model =
Array.map (Array.toList << Array.map Cell.draw) (Matrix.toArray model) |> Array.toList
move_Int : (Int, Int) -> Form -> Form
move_Int (x, y) =
GColl.move (toFloat x, toFloat y)
arrangementFuncs : List (List (Form -> Form))
arrangementFuncs =
let forEachColumn xPos =
List.map (move_Int << (,) xPos) (Util.rangeIntList 0 Cell.size cell_count_h)
in List.map forEachColumn (Util.rangeIntList 0 Cell.size cell_count_w)
pixelToCellCoord : (Int, Int) -> Maybe CellCoord
pixelToCellCoord (x, y) =
let x_coor = (x + Cell.size) // Cell.size - 1
y_coor = (y + Cell.size) // Cell.size - 1
in if | y_coor >= cell_count_h || y_coor < 0 ||
x_coor >= cell_count_w || x_coor < 0 -> Nothing
| otherwise -> Just (CellCoord (x_coor, y_coor))
-- update
type Update = Metabolism Metabolism
| Evolve
type Metabolism = Mitosis CellCoord
| Apoptosis CellCoord
| CircleOfLife CellCoord
update : Update -> Model -> Model
update update model =
case update of
Metabolism m -> case m of
Mitosis coord -> setCell model coord Cell.Alive
Apoptosis coord -> setCell model coord Cell.Dead
CircleOfLife coord -> revertCell model coord
Evolve -> evolve model