-
Notifications
You must be signed in to change notification settings - Fork 0
/
Model.elm
230 lines (170 loc) · 4.48 KB
/
Model.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
module Model exposing (..)
type alias Model =
{ board : Board
, rack : Rack
, gameState : GameState
}
defaultModel =
{ board = initialBoard
, rack = initialRack
, gameState = InProgress
}
type GameState
= InProgress
| Win
| Loss
| Tie
type alias Board =
{ zero : Pin
, one : Pin
, two : Pin
, three : Pin
, four : Pin
, five : Pin
, six : Pin
, seven : Pin
}
initialBoard : Board
initialBoard =
{ zero = emptyPin
, one = emptyPin
, two = emptyPin
, three = emptyPin
, four = emptyPin
, five = emptyPin
, six = emptyPin
, seven = emptyPin
}
type PinId
= Zero
| One
| Two
| Three
| Four
| Five
| Six
| Seven
pinIdPossibilities =
[ Zero
, One
, Two
, Three
, Four
, Five
, Six
, Seven
]
getPin pinId board =
case pinId of
Zero ->
board.zero
One ->
board.one
Two ->
board.two
Three ->
board.three
Four ->
board.four
Five ->
board.five
Six ->
board.six
Seven ->
board.seven
place : Ball -> PinId -> Board -> Board
place ball pinId board =
case pinId of
Zero ->
{ board | zero = placeOnPin ball board.zero }
One ->
{ board | one = placeOnPin ball board.one }
Two ->
{ board | two = placeOnPin ball board.two }
Three ->
{ board | three = placeOnPin ball board.three }
Four ->
{ board | four = placeOnPin ball board.four }
Five ->
{ board | five = placeOnPin ball board.five }
Six ->
{ board | six = placeOnPin ball board.six }
Seven ->
{ board | seven = placeOnPin ball board.seven }
placeOnPin newBall ((Pin bottom middle top) as pin) =
if bottom == NoBall then
Pin newBall middle top
else if middle == NoBall then
Pin bottom newBall top
else if top == NoBall then
Pin bottom middle newBall
else
pin
type Pin
= Pin Ball Ball Ball
emptyPin =
Pin NoBall NoBall NoBall
pinHasRoom (Pin bottom middle top) =
bottom == NoBall || middle == NoBall || top == NoBall
type Ball
= NoBall
| Red
| White
type alias Rack =
{ red : Int
, white : Int
}
initialRack : Rack
initialRack =
{ red = 12
, white = 12
}
removeFromRack : Ball -> Rack -> Rack
removeFromRack ball rack =
case ball of
NoBall ->
rack
Red ->
{ rack | red = max 0 <| rack.red - 1 }
White ->
{ rack | white = max 0 <| rack.white - 1 }
getAvailablePinIds : Board -> List PinId
getAvailablePinIds board =
pinIdPossibilities
|> List.filter
(\pinId ->
board
|> getPin pinId
|> pinHasRoom
)
currentScore : Ball -> Board -> Int
currentScore ball board =
countMultiPinPoints ball board.zero board.one board.two
+ countMultiPinPoints ball board.zero board.three board.six
+ countMultiPinPoints ball board.one board.four board.seven
+ countMultiPinPoints ball board.one board.three board.five
+ countMultiPinPoints ball board.two board.four board.six
+ countMultiPinPoints ball board.five board.six board.seven
+ countSinglePinPoints ball board.zero
+ countSinglePinPoints ball board.one
+ countSinglePinPoints ball board.two
+ countSinglePinPoints ball board.three
+ countSinglePinPoints ball board.four
+ countSinglePinPoints ball board.five
+ countSinglePinPoints ball board.six
+ countSinglePinPoints ball board.seven
countSinglePinPoints ball (Pin bottom middle top) =
countMatches ball bottom middle top
countMultiPinPoints : Ball -> Pin -> Pin -> Pin -> Int
countMultiPinPoints ball (Pin bottom1 middle1 top1) (Pin bottom2 middle2 top2) (Pin bottom3 middle3 top3) =
countMatches ball bottom1 bottom2 bottom3
+ countMatches ball middle1 middle2 middle3
+ countMatches ball top1 top2 top3
+ countMatches ball bottom1 middle2 top3
+ countMatches ball top1 middle2 bottom3
countMatches : Ball -> Ball -> Ball -> Ball -> Int
countMatches selectedBallType ball1 ball2 ball3 =
if selectedBallType == ball1 && ball1 == ball2 && ball2 == ball3 then
1
else
0