OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Stores the actual data on a player's boat grid, the UI representation for its | 6 * Stores the actual data on a player's boat grid, the UI representation for its |
7 * grid and the status of each shot. Acts as a controller handling isolate | 7 * grid and the status of each shot. Acts as a controller handling isolate |
8 * messages (from the main isolate message and shots from the enemy), and UI | 8 * messages (from the main isolate message and shots from the enemy), and UI |
9 * events. | 9 * events. |
10 */ | 10 */ |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 | 136 |
137 /** local action to generate an asynchronous shot at the enemy. */ | 137 /** local action to generate an asynchronous shot at the enemy. */ |
138 void shoot(int x, int y) { | 138 void shoot(int x, int y) { |
139 superShot(x, y, _id % 2 == 0); | 139 superShot(x, y, _id % 2 == 0); |
140 } | 140 } |
141 | 141 |
142 /** A single shot on (x, y). */ | 142 /** A single shot on (x, y). */ |
143 void singleShot(int x, int y) { | 143 void singleShot(int x, int y) { |
144 if (_canShoot(x, y)) { | 144 if (_canShoot(x, y)) { |
145 _recordPendingShot(x, y); | 145 _recordPendingShot(x, y); |
146 Promise<int> res = enemy.shoot(x, y); // async shot! | 146 Future<int> res = enemy.shoot(x, y); // async shot! |
147 res.addCompleteHandler((int result) { | 147 res.then((int result) { |
148 _recordShotResult(result, x, y); | 148 _recordShotResult(result, x, y); |
149 }); | 149 }); |
150 res.addErrorHandler((String error) { | 150 res.handleException((String error) { |
151 _recordFailedShot(x, y); | 151 _recordFailedShot(x, y); |
| 152 return true; |
152 }); | 153 }); |
153 } | 154 } |
154 } | 155 } |
155 | 156 |
156 /** | 157 /** |
157 * Takes 1 shot, if it's a hit, it then shoots to each of the 4 cardinal | 158 * Takes 1 shot, if it's a hit, it then shoots to each of the 4 cardinal |
158 * directions until a boat is sunk. When [parallel] all directions are | 159 * directions until a boat is sunk. When [parallel] all directions are |
159 * explored in parallel. | 160 * explored in parallel. |
160 */ | 161 */ |
161 void superShot(int x, int y, bool parallel) { | 162 void superShot(int x, int y, bool parallel) { |
162 if (_canShoot(x, y)) { | 163 if (_canShoot(x, y)) { |
163 _recordPendingShot(x, y); | 164 _recordPendingShot(x, y); |
164 Promise<int> firstShot = enemy.shoot(x, y); | 165 Future<int> firstShot = enemy.shoot(x, y); |
165 firstShot.addCompleteHandler((int res) { | 166 firstShot.then((int res) { |
166 _recordShotResult(res, x, y); | 167 _recordShotResult(res, x, y); |
167 if (res == Constants.HIT) { | 168 if (res == Constants.HIT) { |
168 // no miss, but no sunk, search around | 169 // no miss, but no sunk, search around |
169 _exploreAllDirections(x, y, parallel); | 170 _exploreAllDirections(x, y, parallel); |
170 } | 171 } |
171 }); | 172 }); |
172 firstShot.addErrorHandler((String error) { | 173 firstShot.handleException((String error) { |
173 _recordFailedShot(x, y); | 174 _recordFailedShot(x, y); |
| 175 return true; |
174 }); | 176 }); |
175 } | 177 } |
176 } | 178 } |
177 | 179 |
178 static final LEFT_DIR = const [-1, 0]; | 180 static final LEFT_DIR = const [-1, 0]; |
179 static final RIGHT_DIR = const [1, 0]; | 181 static final RIGHT_DIR = const [1, 0]; |
180 static final UP_DIR = const [0, -1]; | 182 static final UP_DIR = const [0, -1]; |
181 static final DOWN_DIR = const [0, 1]; | 183 static final DOWN_DIR = const [0, 1]; |
182 | 184 |
183 Promise<bool> _exploreAllDirections(int x, int y, bool parallel) { | 185 Future<bool> _exploreAllDirections(int x, int y, bool parallel) { |
184 Promise<bool> superShot = new Promise<bool>(); | 186 Completer<bool> superShot = new Completer<bool>(); |
185 if (parallel) { | 187 if (parallel) { |
186 final arr = new List<Promise<bool>>(); | 188 final arr = new List<Future<bool>>(); |
187 arr.add(_exploreDirectionHelper(LEFT_DIR, x, y)); | 189 arr.add(_exploreDirectionHelper(LEFT_DIR, x, y)); |
188 arr.add(_exploreDirectionHelper(RIGHT_DIR, x, y)); | 190 arr.add(_exploreDirectionHelper(RIGHT_DIR, x, y)); |
189 arr.add(_exploreDirectionHelper(UP_DIR, x, y)); | 191 arr.add(_exploreDirectionHelper(UP_DIR, x, y)); |
190 arr.add(_exploreDirectionHelper(DOWN_DIR, x, y)); | 192 arr.add(_exploreDirectionHelper(DOWN_DIR, x, y)); |
191 superShot.waitFor(arr, 4); | 193 Futures.wait(arr).then((arrValues) { |
| 194 superShot.complete(true); |
| 195 }); |
192 } else { | 196 } else { |
193 _seqExploreDirectionHelper(LEFT_DIR, x, y, superShot, | 197 _seqExploreDirectionHelper(LEFT_DIR, x, y, superShot, |
194 _seqExploreDirectionHelper(RIGHT_DIR, x, y, superShot, | 198 _seqExploreDirectionHelper(RIGHT_DIR, x, y, superShot, |
195 _seqExploreDirectionHelper(UP_DIR, x, y, superShot, | 199 _seqExploreDirectionHelper(UP_DIR, x, y, superShot, |
196 _seqExploreDirectionHelper(DOWN_DIR, x, y, superShot, null))))(fal
se); | 200 _seqExploreDirectionHelper(DOWN_DIR, x, y, superShot, null))))(fal
se); |
197 } | 201 } |
198 return superShot; | 202 return superShot.future; |
199 } | 203 } |
200 Function _seqExploreDirectionHelper(List<int> dir, int x, int y, | 204 Function _seqExploreDirectionHelper(List<int> dir, int x, int y, |
201 Promise<bool> seq, void _next(bool res)) { | 205 Completer<bool> seq, void _next(bool res)) { |
202 return (bool res) { | 206 return (bool res) { |
203 if (res) { | 207 if (res) { |
204 seq.complete(true); | 208 seq.complete(true); |
205 } else { | 209 } else { |
206 _exploreDirectionHelper(dir, x, y).then( | 210 _exploreDirectionHelper(dir, x, y).then( |
207 (_next != null) ? _next : (void _(v) {seq.complete(false);})); | 211 (_next != null) ? _next : (void _(v) {seq.complete(false);})); |
208 } | 212 } |
209 }; | 213 }; |
210 } | 214 } |
211 | 215 |
212 Promise<bool> _exploreDirectionHelper(List<int> dir, int x, int y) { | 216 Future<bool> _exploreDirectionHelper(List<int> dir, int x, int y) { |
213 Promise<bool> sunk = new Promise<bool>(); | 217 Completer<bool> sunk = new Completer<bool>(); |
214 _followDir(x + dir[0], y + dir[1], dir[0], dir[1], sunk); | 218 _followDir(x + dir[0], y + dir[1], dir[0], dir[1], sunk); |
215 return sunk; | 219 return sunk.future; |
216 } | 220 } |
217 | 221 |
218 void _followDir(int x, int y, int incX, int incY, Promise<bool> sunk) { | 222 void _followDir(int x, int y, int incX, int incY, Completer<bool> sunk) { |
219 if (_canShoot(x, y)) { | 223 if (_canShoot(x, y)) { |
220 _recordPendingShot(x, y); | 224 _recordPendingShot(x, y); |
221 Promise<int> shot = enemy.shoot(x, y); | 225 Future<int> shot = enemy.shoot(x, y); |
222 shot.addCompleteHandler((int res) { | 226 shot.then((int res) { |
223 _recordShotResult(res, x, y); | 227 _recordShotResult(res, x, y); |
224 switch (res) { | 228 switch (res) { |
225 case Constants.HIT: | 229 case Constants.HIT: |
226 if (!sunk.isDone() && !sunk.isCancelled()) { | 230 if (!sunk.future.isComplete) { |
227 _followDir(x + incX, y + incY, incX, incY, sunk); | 231 _followDir(x + incX, y + incY, incX, incY, sunk); |
228 } | 232 } |
229 break; | 233 break; |
230 case Constants.SUNK: | 234 case Constants.SUNK: |
231 sunk.complete(true); | 235 sunk.complete(true); |
232 break; | 236 break; |
233 case Constants.MISS: | 237 case Constants.MISS: |
234 sunk.complete(false); | 238 sunk.complete(false); |
235 break; | 239 break; |
236 } | 240 } |
237 }); | 241 }); |
238 shot.addErrorHandler((String error) { | 242 shot.handleException((String error) { |
239 _recordFailedShot(x, y); | 243 _recordFailedShot(x, y); |
240 sunk.fail(error); | 244 sunk.completeException(error); |
| 245 return true; |
241 }); | 246 }); |
242 // We don't actually chain sunk.cancel with shot.cancel because individual | 247 // We don't actually chain sunk.cancel with shot.cancel because individual |
243 // shots can't be cancelled. | 248 // shots can't be cancelled. |
244 } else { | 249 } else { |
245 sunk.complete(false); | 250 sunk.complete(false); |
246 } | 251 } |
247 } | 252 } |
248 | 253 |
249 /** checks that a shot is in range and has not been done before. */ | 254 /** checks that a shot is in range and has not been done before. */ |
250 bool _canShoot(int x, int y) { | 255 bool _canShoot(int x, int y) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 case Constants.SUNK: | 298 case Constants.SUNK: |
294 totalHits++; | 299 totalHits++; |
295 boatsSunk++; | 300 boatsSunk++; |
296 _enemyView.addHit(x, y); | 301 _enemyView.addHit(x, y); |
297 enemyGrid.hit(x, y); | 302 enemyGrid.hit(x, y); |
298 break; | 303 break; |
299 } | 304 } |
300 _enemyView.statusBar.updateStatus(); | 305 _enemyView.statusBar.updateStatus(); |
301 } | 306 } |
302 } | 307 } |
OLD | NEW |