OLD | NEW |
1 part of pop_pop_win.game; | 1 part of pop_pop_win.game; |
2 | 2 |
3 class Game { | 3 class Game { |
4 final Field field; | 4 final Field field; |
5 final Array2d<SquareState> _states; | 5 final Array2d<SquareState> _states; |
6 final EventHandle<EventArgs> _updatedEvent = new EventHandle<EventArgs>(); | 6 final StreamController _updatedEvent = new StreamController(); |
7 final EventHandle<GameState> _gameStateEvent = new EventHandle<GameState>(); | 7 final StreamController<GameState> _gameStateEvent = |
| 8 new StreamController<GameState>(); |
8 | 9 |
9 GameState _state; | 10 GameState _state; |
10 int _bombsLeft; | 11 int _bombsLeft; |
11 int _revealsLeft; | 12 int _revealsLeft; |
12 DateTime _startTime; | 13 DateTime _startTime; |
13 DateTime _endTime; | 14 DateTime _endTime; |
14 | 15 |
15 Game(Field field) : | 16 Game(Field field) |
16 this.field = field, | 17 : this.field = field, |
17 _state = GameState.reset, | 18 _state = GameState.reset, |
18 _states = new Array2d<SquareState>(field.width, field.height, SquareState.hi
dden) { | 19 _states = new Array2d<SquareState>(field.width, field.height, |
| 20 SquareState.hidden) { |
19 assert(field != null); | 21 assert(field != null); |
20 _bombsLeft = field.bombCount; | 22 _bombsLeft = field.bombCount; |
21 _revealsLeft = field.length - field.bombCount; | 23 _revealsLeft = field.length - field.bombCount; |
22 } | 24 } |
23 | 25 |
24 int get bombsLeft => _bombsLeft; | 26 int get bombsLeft => _bombsLeft; |
25 | 27 |
26 int get revealsLeft => _revealsLeft; | 28 int get revealsLeft => _revealsLeft; |
27 | 29 |
28 GameState get state => _state; | 30 GameState get state => _state; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 bool canReveal(int x, int y) { | 73 bool canReveal(int x, int y) { |
72 final currentSS = _states.get(x, y); | 74 final currentSS = _states.get(x, y); |
73 if (currentSS == SquareState.hidden) { | 75 if (currentSS == SquareState.hidden) { |
74 return true; | 76 return true; |
75 } else if (_canChord(x, y)) { | 77 } else if (_canChord(x, y)) { |
76 return true; | 78 return true; |
77 } | 79 } |
78 return false; | 80 return false; |
79 } | 81 } |
80 | 82 |
81 List<Coordinate> reveal(int x, int y) { | 83 List<Point> reveal(int x, int y) { |
82 _ensureStarted(); | 84 _ensureStarted(); |
83 require(canReveal(x, y), "Item cannot be revealed."); | 85 require(canReveal(x, y), "Item cannot be revealed."); |
84 final currentSS = _states.get(x, y); | 86 final currentSS = _states.get(x, y); |
85 | 87 |
86 List<Coordinate> reveals; | 88 List<Point> reveals; |
87 | 89 |
88 // normal reveal | 90 // normal reveal |
89 if (currentSS == SquareState.hidden) { | 91 if (currentSS == SquareState.hidden) { |
90 if (field.get(x, y)) { | 92 if (field.get(x, y)) { |
91 _setLost(); | 93 _setLost(); |
92 reveals = <Coordinate>[]; | 94 reveals = <Point>[]; |
93 } else { | 95 } else { |
94 reveals = _doReveal(x, y); | 96 reveals = _doReveal(x, y); |
95 } | 97 } |
96 } else if (_canChord(x, y)) { | 98 } else if (_canChord(x, y)) { |
97 reveals = _doChord(x, y); | 99 reveals = _doChord(x, y); |
98 } | 100 } |
99 _update(); | 101 _update(); |
100 | 102 |
101 if (_state == GameState.lost) { | 103 if (_state == GameState.lost) { |
102 return null; | 104 return null; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 final adjFlags = _getAdjacentCount(x, y, SquareState.flagged); | 167 final adjFlags = _getAdjacentCount(x, y, SquareState.flagged); |
166 if (adjFlags == adjCount) { | 168 if (adjFlags == adjCount) { |
167 return true; | 169 return true; |
168 } | 170 } |
169 } | 171 } |
170 } | 172 } |
171 } | 173 } |
172 return false; | 174 return false; |
173 } | 175 } |
174 | 176 |
175 List<Coordinate> _doChord(int x, int y) { | 177 List<Point> _doChord(int x, int y) { |
176 // this does not repeat a bunch of validations that have already happened | 178 // this does not repeat a bunch of validations that have already happened |
177 // be careful | 179 // be careful |
178 final currentSS = _states.get(x, y); | 180 final currentSS = _states.get(x, y); |
179 assert(currentSS == SquareState.revealed); | 181 assert(currentSS == SquareState.revealed); |
180 | 182 |
181 final flagged = new List<int>(); | 183 final flagged = new List<int>(); |
182 final hidden = new List<int>(); | 184 final hidden = new List<int>(); |
183 final adjCount = field.getAdjacentCount(x, y); | 185 final adjCount = field.getAdjacentCount(x, y); |
184 assert(adjCount > 0); | 186 assert(adjCount > 0); |
185 | 187 |
186 bool failed = false; | 188 bool failed = false; |
187 | 189 |
188 for (final i in field.getAdjacentIndices(x, y)) { | 190 for (final i in field.getAdjacentIndices(x, y)) { |
189 if (_states[i] == SquareState.hidden) { | 191 if (_states[i] == SquareState.hidden) { |
190 hidden.add(i); | 192 hidden.add(i); |
191 if (field[i]) { | 193 if (field[i]) { |
192 failed = true; | 194 failed = true; |
193 } | 195 } |
194 } else if (_states[i] == SquareState.flagged) { | 196 } else if (_states[i] == SquareState.flagged) { |
195 flagged.add(i); | 197 flagged.add(i); |
196 } | 198 } |
197 } | 199 } |
198 | 200 |
199 // for now we assume counts have been checked | 201 // for now we assume counts have been checked |
200 assert(flagged.length == adjCount); | 202 assert(flagged.length == adjCount); |
201 | 203 |
202 var reveals = <Coordinate>[]; | 204 var reveals = <Point>[]; |
203 | 205 |
204 // if any of the hidden are bombs, we've failed | 206 // if any of the hidden are bombs, we've failed |
205 if (failed) { | 207 if (failed) { |
206 // TODO: assert one of the flags must be wrong, right? | |
207 _setLost(); | 208 _setLost(); |
208 } else { | 209 } else { |
209 for (final i in hidden) { | 210 for (final i in hidden) { |
210 final c = field.getCoordinate(i); | 211 final c = field.getCoordinate(i); |
211 if (canReveal(c.item1, c.item2)) { | 212 if (canReveal(c.item1, c.item2)) { |
212 reveals.addAll(reveal(c.item1, c.item2)); | 213 reveals.addAll(reveal(c.item1, c.item2)); |
213 } | 214 } |
214 } | 215 } |
215 } | 216 } |
216 | 217 |
217 return reveals; | 218 return reveals; |
218 } | 219 } |
219 | 220 |
220 List<Coordinate> _doReveal(int x, int y) { | 221 List<Point> _doReveal(int x, int y) { |
221 assert(_states.get(x, y) == SquareState.hidden); | 222 assert(_states.get(x, y) == SquareState.hidden); |
222 _states.set(x, y, SquareState.revealed); | 223 _states.set(x, y, SquareState.revealed); |
223 _revealsLeft--; | 224 _revealsLeft--; |
224 assert(_revealsLeft >= 0); | 225 assert(_revealsLeft >= 0); |
225 var reveals = [new Coordinate(x, y)]; | 226 var reveals = [new Point(x, y)]; |
226 if (_revealsLeft == 0) { | 227 if (_revealsLeft == 0) { |
227 _setWon(); | 228 _setWon(); |
228 } else if (field.getAdjacentCount(x, y) == 0) { | 229 } else if (field.getAdjacentCount(x, y) == 0) { |
229 for (final i in field.getAdjacentIndices(x, y)) { | 230 for (final i in field.getAdjacentIndices(x, y)) { |
230 if (_states[i] == SquareState.hidden) { | 231 if (_states[i] == SquareState.hidden) { |
231 final c = field.getCoordinate(i); | 232 final c = field.getCoordinate(i); |
232 reveals.addAll(_doReveal(c.item1, c.item2)); | 233 reveals.addAll(_doReveal(c.item1, c.item2)); |
233 assert(state == GameState.started || state == GameState.won); | 234 assert(state == GameState.started || state == GameState.won); |
234 } | 235 } |
235 } | 236 } |
(...skipping 14 matching lines...) Expand all Loading... |
250 void _setLost() { | 251 void _setLost() { |
251 assert(state == GameState.started); | 252 assert(state == GameState.started); |
252 for (int i = 0; i < field.length; i++) { | 253 for (int i = 0; i < field.length; i++) { |
253 if (field[i]) { | 254 if (field[i]) { |
254 _states[i] = SquareState.bomb; | 255 _states[i] = SquareState.bomb; |
255 } | 256 } |
256 } | 257 } |
257 _setState(GameState.lost); | 258 _setState(GameState.lost); |
258 } | 259 } |
259 | 260 |
260 void _update() => _updatedEvent.add(EventArgs.empty); | 261 void _update() => _updatedEvent.add(null); |
261 | 262 |
262 void _setState(GameState value) { | 263 void _setState(GameState value) { |
263 assert(value != null); | 264 assert(value != null); |
264 assert(_state != null); | 265 assert(_state != null); |
265 assert((_state == GameState.reset) == (_startTime == null)); | 266 assert((_state == GameState.reset) == (_startTime == null)); |
266 if (_state != value) { | 267 if (_state != value) { |
267 _state = value; | 268 _state = value; |
268 if (_state == GameState.started) { | 269 if (_state == GameState.started) { |
269 _startTime = new DateTime.now(); | 270 _startTime = new DateTime.now(); |
270 } else if (gameEnded) { | 271 } else if (gameEnded) { |
(...skipping 15 matching lines...) Expand all Loading... |
286 int _getAdjacentCount(int x, int y, SquareState state) { | 287 int _getAdjacentCount(int x, int y, SquareState state) { |
287 int val = 0; | 288 int val = 0; |
288 for (final i in field.getAdjacentIndices(x, y)) { | 289 for (final i in field.getAdjacentIndices(x, y)) { |
289 if (_states[i] == state) { | 290 if (_states[i] == state) { |
290 val++; | 291 val++; |
291 } | 292 } |
292 } | 293 } |
293 return val; | 294 return val; |
294 } | 295 } |
295 } | 296 } |
OLD | NEW |