| 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 |