Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
GameManager |
|
| 4.0;4 |
1 | /****************************************************************************** | |
2 | * GameManager.java - Manage all of the moves that happen in a single game | |
3 | * $Id$ | |
4 | * | |
5 | * BuckoFIBS - Backgammon by BuckoSoft | |
6 | * Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp. | |
7 | * | |
8 | * $Log$ | |
9 | * Revision 1.29 2013/09/12 06:37:01 dick | |
10 | * Doubles dispatches gameEvents. | |
11 | * | |
12 | * Revision 1.28 2011/09/23 02:58:39 dick | |
13 | * Rework a little bit when position gets updated. (and still needs work). | |
14 | * | |
15 | * Revision 1.27 2011/07/16 02:33:09 dick | |
16 | * Add YouDouble. | |
17 | * | |
18 | * Revision 1.26 2011/07/04 03:43:07 dick | |
19 | * Add FirstMove handling. | |
20 | * | |
21 | * Revision 1.25 2011/06/18 19:29:48 dick | |
22 | * Work on resigning and YouCantMove. | |
23 | * | |
24 | * Revision 1.24 2011/06/14 19:18:07 dick | |
25 | * Add YouCantMove handling. | |
26 | * Bearing off only affects You. Others will get a move message. | |
27 | * | |
28 | * Revision 1.23 2011/06/13 04:42:41 dick | |
29 | * Handle FIBS_PlayerWantsToResign. | |
30 | * | |
31 | * Revision 1.22 2011/06/10 20:41:17 dick | |
32 | * Add Undo to sendGameEvent(). | |
33 | * queueGameEvent() tweakage. | |
34 | * | |
35 | * Revision 1.21 2011/06/05 06:56:41 dick | |
36 | * Handle AcceptsAndWins | |
37 | * | |
38 | * Revision 1.20 2011/06/02 19:11:20 dick | |
39 | * Deal with resign messages. | |
40 | * | |
41 | * Revision 1.19 2011/05/23 05:55:42 dick | |
42 | * Add youMoved() which removes any pending "YourMove" from the queue. | |
43 | * | |
44 | * Revision 1.18 2011/05/23 01:11:17 dick | |
45 | * Add playPaused() skeleton. | |
46 | * | |
47 | * Revision 1.17 2011/05/22 05:09:45 dick | |
48 | * Add AcceptReject double. | |
49 | * Fix game opening sequence. | |
50 | * | |
51 | * Revision 1.16 2011/05/21 20:18:29 dick | |
52 | * Sorting dice works. | |
53 | * | |
54 | * Revision 1.15 2011/05/21 04:59:56 dick | |
55 | * Work on GUI integration. | |
56 | * Add the preStartList for events that can't go out before the first board. | |
57 | * | |
58 | * Revision 1.14 2011/05/18 05:55:18 dick | |
59 | * Nice watching, Still needs work for playing. | |
60 | * | |
61 | * Revision 1.13 2011/05/17 23:11:26 dick | |
62 | * Working on passing replay commands to the animator. | |
63 | * | |
64 | * Revision 1.12 2011/05/16 14:18:29 dick | |
65 | * Add support for the CantMove event. | |
66 | * | |
67 | * Revision 1.11 2011/05/16 11:33:58 dick | |
68 | * Add FIBS_PlayerRolls. | |
69 | * | |
70 | * Revision 1.10 2011/05/15 18:17:15 dick | |
71 | * Working on why the last GameMove is empty, instead of bearing off the last checkers. | |
72 | * | |
73 | * Revision 1.9 2011/05/15 02:19:12 dick | |
74 | * GameLine becomes GameBoard. | |
75 | * Rearrange a whole bunch of packages. | |
76 | * | |
77 | * Revision 1.8 2011/05/14 04:43:01 dick | |
78 | * I needed to deal with some lightweight Boards. | |
79 | * So finally make the primary document Document | |
80 | * and demote just the Board handling to a domain object. | |
81 | * | |
82 | * Revision 1.7 2011/05/13 18:24:06 dick | |
83 | * Working on turning off animation, which should skip move events | |
84 | * and just display boards. | |
85 | * | |
86 | * Revision 1.6 2011/05/13 14:29:02 dick | |
87 | * Work with GameEvents, not Lines. | |
88 | * | |
89 | * Revision 1.5 2011/05/11 22:22:42 dick | |
90 | * Working on animating moves. | |
91 | * | |
92 | * Revision 1.4 2011/05/10 16:08:20 dick | |
93 | * Fix the javadoc pointers to the source code. | |
94 | * | |
95 | * Revision 1.3 2010/03/03 13:12:21 inim | |
96 | * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8 | |
97 | * | |
98 | * Revision 1.2 2010/03/03 12:19:49 inim | |
99 | * Moved source to UTF8 encoding from CP1252 encoding. To this end all source files' (c) message was updated to "Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.". This replaces the (c) sign to UTF8, and adds the new year 2010. | |
100 | * | |
101 | * Revision 1.1 2010/02/04 05:57:53 inim | |
102 | * Mavenized project folder layout | |
103 | * | |
104 | * Revision 1.7 2009/02/23 09:44:54 dick | |
105 | * Javadoc. | |
106 | * | |
107 | * Revision 1.6 2009/02/14 13:13:21 dick | |
108 | * BuckoFIBS is released under the GNU license. | |
109 | * Javadoc. | |
110 | * | |
111 | * Revision 1.5 2009/02/11 09:01:20 dick | |
112 | * Don't initialize your turn if its not your turn or you're not playing. | |
113 | * | |
114 | * Revision 1.4 2009/01/31 08:53:08 dick | |
115 | * We're moving checkers, not dice. | |
116 | * | |
117 | * Revision 1.3 2009/01/31 08:48:23 dick | |
118 | * Line contains info about and GameManager initializes YourMove. | |
119 | * | |
120 | * Revision 1.2 2009/01/31 06:08:11 dick | |
121 | * React to the replay buttons being pressed. | |
122 | * | |
123 | * Revision 1.1 2009/01/28 22:26:52 dick | |
124 | * Skeleton GameManager. | |
125 | */ | |
126 | ||
127 | /* | |
128 | * This program is free software: you can redistribute it and/or modify | |
129 | * it under the terms of the GNU General Public License as published by | |
130 | * the Free Software Foundation, either version 3 of the License, or | |
131 | * (at your option) any later version. | |
132 | * | |
133 | * This program is distributed in the hope that it will be useful, | |
134 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
135 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
136 | * GNU General Public License for more details. | |
137 | * | |
138 | * You should have received a copy of the GNU General Public License | |
139 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
140 | * | |
141 | * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>. | |
142 | * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp. | |
143 | * | |
144 | */ | |
145 | package com.buckosoft.fibs.BuckoFIBS; | |
146 | ||
147 | import java.util.LinkedList; | |
148 | ||
149 | import org.slf4j.Logger; | |
150 | import org.slf4j.LoggerFactory; | |
151 | ||
152 | import com.buckosoft.fibs.BuckoFIBS.AudioManager.Cue; | |
153 | import com.buckosoft.fibs.BuckoFIBS.gui.MainDialog; | |
154 | import com.buckosoft.fibs.BuckoFIBS.gui.MainDialogI; | |
155 | import com.buckosoft.fibs.BuckoFIBS.gui.boardTab.ReplayToolbarI; | |
156 | import com.buckosoft.fibs.domain.Board; | |
157 | import com.buckosoft.fibs.domain.CookieString; | |
158 | import com.buckosoft.fibs.domain.gameEvent.GameEvent; | |
159 | import com.buckosoft.fibs.domain.gameEvent.GameEventAcceptAndWin; | |
160 | import com.buckosoft.fibs.domain.gameEvent.GameEventBoard; | |
161 | import com.buckosoft.fibs.domain.gameEvent.GameEventCantMove; | |
162 | import com.buckosoft.fibs.domain.gameEvent.GameEventDouble; | |
163 | import com.buckosoft.fibs.domain.gameEvent.GameEventFirstMove; | |
164 | import com.buckosoft.fibs.domain.gameEvent.GameEventFirstRoll; | |
165 | import com.buckosoft.fibs.domain.gameEvent.GameEventMove; | |
166 | import com.buckosoft.fibs.domain.gameEvent.GameEventPleaseAcceptOrRejectDouble; | |
167 | import com.buckosoft.fibs.domain.gameEvent.GameEventPleaseAcceptOrRejectResign; | |
168 | import com.buckosoft.fibs.domain.gameEvent.GameEventPleaseMove; | |
169 | import com.buckosoft.fibs.domain.gameEvent.GameEventPleaseRollOrDouble; | |
170 | import com.buckosoft.fibs.domain.gameEvent.GameEventRejectResign; | |
171 | import com.buckosoft.fibs.domain.gameEvent.GameEventResign; | |
172 | import com.buckosoft.fibs.domain.gameEvent.GameEventRoll; | |
173 | import com.buckosoft.fibs.domain.gameEvent.GameEventYouDouble; | |
174 | import com.buckosoft.fibs.domain.gameEvent.GameEvent.Life; | |
175 | import com.buckosoft.fibs.domain.gameEvent.GameEvent.Type; | |
176 | import com.buckosoft.fibs.net.FIBSMessages; | |
177 | ||
178 | /** Track each turn in a game. | |
179 | * Provides the ability to go back and forth through the game moves list. | |
180 | * We receive game events from CommandDispatcher and send them to AnimationManager. | |
181 | * @author Dick Balaska | |
182 | * @since 2009/01/28 | |
183 | * @version $Revision$ <br> $Date$ | |
184 | * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/GameManager.java">cvs GameManager.java</a> | |
185 | */ | |
186 | public class GameManager implements FIBSMessages { | |
187 | private final static boolean DEBUG = true; | |
188 | private final static boolean DEBUGsend = true; | |
189 | private final static boolean DEBUGpos = true; | |
190 | private final static boolean DEBUGJibsBoard = true; | |
191 | ||
192 | 0 | private Logger logger = LoggerFactory.getLogger(getClass()); |
193 | ||
194 | private int position; | |
195 | private ReplayToolbarI replayToolbar; | |
196 | private MainDialogI mainDialog; | |
197 | private BFProperties bfProps; | |
198 | ||
199 | private final static int Undo = -2; | |
200 | private final static int Backward = -1; | |
201 | private final static int Start = 0; | |
202 | private final static int Forward = 1; | |
203 | ||
204 | 0 | private LinkedList<GameEvent> preStartList = new LinkedList<GameEvent>(); |
205 | // private boolean resumingMatch = false; | |
206 | ||
207 | /** Construct a GameManager */ | |
208 | 0 | public GameManager() { |
209 | 0 | } |
210 | ||
211 | /** Set the reference to the ReplayToolbar so that we can turn on and off his buttons | |
212 | * @param replayToolbar The replayToolbar | |
213 | */ | |
214 | public void setReplayToolbar(ReplayToolbarI replayToolbar) { | |
215 | 0 | this.replayToolbar = replayToolbar; |
216 | 0 | } |
217 | ||
218 | /** Set the reference to the instance of MainDialog | |
219 | * @param mainDialog The MainDialog that is running | |
220 | */ | |
221 | public void setMainDialog(MainDialog mainDialog) { | |
222 | 0 | this.mainDialog = mainDialog; |
223 | 0 | } |
224 | ||
225 | /** Set the reference to the properties | |
226 | * @param bfProperties | |
227 | */ | |
228 | public void setProperties(BFProperties bfProperties) { | |
229 | 0 | this.bfProps = bfProperties; |
230 | 0 | } |
231 | ||
232 | /** Reset a game to have no moves stored. | |
233 | * @param resumeMatch true if we are resuming a match | |
234 | */ | |
235 | public void reset(boolean resumeMatch) { | |
236 | // this.resumingMatch = resumeMatch; | |
237 | 0 | gameEvents.clear(); |
238 | 0 | preStartList.clear(); |
239 | 0 | position = 0; |
240 | if (DEBUGpos) | |
241 | 0 | logger.info("reset: pos = " + this.position); |
242 | 0 | updateToolbarButtons(); |
243 | 0 | } |
244 | ||
245 | /** Fibs says it is our turn | |
246 | */ | |
247 | public void onRollOrDouble() { | |
248 | 0 | queueGameEvent(new GameEventPleaseRollOrDouble()); |
249 | 0 | } |
250 | ||
251 | /** Player has taken his turn, moved his checkers and picked up the dice. | |
252 | */ | |
253 | public void youMoved() { | |
254 | 0 | this.mainDialog.playSound(Cue.PickUpDice); |
255 | 0 | this.mainDialog.updateBoard(); |
256 | //this.mainDialog.youCantMove(); // you can't move because your turn is over | |
257 | /* Iterator<GameEvent> iter = gameEvents.iterator(); | |
258 | while (iter.hasNext()) { | |
259 | GameEvent ge = iter.next(); | |
260 | if (ge.getType() == Type.PleaseMove) { | |
261 | iter.remove(); | |
262 | break; | |
263 | } | |
264 | } | |
265 | 0 | */ } |
266 | ||
267 | /** Add a FIBS game event message to our game | |
268 | * @param cs The Cookie and String from {@link ClientReceiveParser} | |
269 | */ | |
270 | public void addEvent(CookieString cs) { | |
271 | if (DEBUG) | |
272 | 0 | logger.info("addEvent: " + cs.getCookie() + " " + cs.getString()); |
273 | 0 | switch (cs.getCookie()) { |
274 | case FIBS_Board: | |
275 | 0 | addBoardLine(cs.getString()); |
276 | 0 | break; |
277 | case FIBS_PlayerMoves: | |
278 | 0 | addMove(cs.getString()); |
279 | 0 | break; |
280 | case FIBS_BearingOff: | |
281 | 0 | addBearingOff(cs.getString()); |
282 | 0 | break; |
283 | case FIBS_YouRoll: | |
284 | case FIBS_PlayerRolls: | |
285 | 0 | addRoll(cs.getString()); |
286 | 0 | break; |
287 | case FIBS_CantMove: | |
288 | 0 | addCantMove(cs.getString()); |
289 | 0 | break; |
290 | case FIBS_YouCantMove: | |
291 | 0 | addYouCantMove(cs.getString()); |
292 | 0 | break; |
293 | case FIBS_PleaseMove: | |
294 | 0 | addPleaseMove(cs.getString()); |
295 | 0 | break; |
296 | case FIBS_YourTurnToMove: | |
297 | 0 | addYourTurnToMove(cs.getString()); |
298 | 0 | break; |
299 | case FIBS_MakesFirstMove: | |
300 | 0 | addFirstMove(cs.getString()); |
301 | 0 | break; |
302 | case FIBS_FirstRoll: | |
303 | 0 | addFirstRoll(cs.getString()); |
304 | 0 | break; |
305 | case FIBS_StartingNewGame: | |
306 | 0 | addStartNewGame(cs.getString()); |
307 | 0 | break; |
308 | case FIBS_NewMatchAck2: | |
309 | 0 | addPlayerJoinsYou(cs.getString()); |
310 | 0 | break; |
311 | case FIBS_Turn: | |
312 | 0 | addResumeYourTurn(cs.getString()); |
313 | 0 | break; |
314 | case FIBS_AcceptRejectDouble: | |
315 | 0 | addAcceptRejectDouble(cs.getString()); |
316 | 0 | break; |
317 | case FIBS_PlayerWantsToResign: | |
318 | case FIBS_WatchResign: | |
319 | case FIBS_YouResign: | |
320 | 0 | addResign(cs.getString()); |
321 | 0 | break; |
322 | case FIBS_ResignRefused: | |
323 | 0 | addResignRefused(cs.getString()); |
324 | 0 | break; |
325 | case FIBS_AcceptWins: | |
326 | 0 | addAcceptsAndWins(cs.getString()); |
327 | 0 | break; |
328 | case FIBS_YouDouble: | |
329 | 0 | addYouDouble(cs.getString()); |
330 | 0 | break; |
331 | case FIBS_Doubles: | |
332 | 0 | addOtherDoubles(cs.getString()); |
333 | 0 | break; |
334 | default: | |
335 | 0 | logger.warn("Unhandled event: (" + cs.getCookie() + ") "+ cs.getString()); |
336 | break; | |
337 | } | |
338 | 0 | } |
339 | ||
340 | /** Starting a new game against Player. "<code>Starting a new game with dickbalaska.</code>" | |
341 | * This resets the GameManager and generates a fake board, just so we have something to work against | |
342 | * until a real board arrives. | |
343 | * @param s The string to parse. | |
344 | */ | |
345 | private void addStartNewGame(String s) { | |
346 | 0 | reset(false); |
347 | 0 | GameEventBoard gb = new GameEventBoard(); |
348 | 0 | Board b = gb.getBoard(); |
349 | 0 | b.setStartPositions(); |
350 | 0 | b.setPlayerName(Board.O, "You"); |
351 | 0 | String ss[] = s.split(" "); |
352 | 0 | b.setPlayerName(Board.X, ss[5]); |
353 | if (DEBUG) | |
354 | 0 | logger.info("addStartNewGame: opponent=" + ss[5]); |
355 | 0 | queueGameEvent(gb); |
356 | 0 | } |
357 | /** Handle "<code>** Player dickbalaska has joined you for a 5 point match.</code>" | |
358 | * This is the same as addStartNewGame() except the opponent joined your invite. | |
359 | * @param s The String to parse | |
360 | */ | |
361 | private void addPlayerJoinsYou(String s) { | |
362 | 0 | reset(false); |
363 | 0 | GameEventBoard gb = new GameEventBoard(); |
364 | 0 | Board b = gb.getBoard(); |
365 | 0 | b.setStartPositions(); |
366 | 0 | b.setPlayerName(Board.O, "You"); |
367 | 0 | String ss[] = s.split(" "); |
368 | 0 | b.setPlayerName(Board.X, ss[2]); |
369 | if (DEBUG) | |
370 | 0 | logger.info("addPlayerJoinsYou: opponent=" + ss[2]); |
371 | 0 | queueGameEvent(gb); |
372 | 0 | } |
373 | /** Resume a match, and it's this player's turn upcoming | |
374 | * @param s "<code>turn: Bucko.</code>" | |
375 | */ | |
376 | private void addResumeYourTurn(String s) { | |
377 | 0 | GameEventRoll gr = new GameEventRoll(); |
378 | 0 | String[] ss = s.split(" "); |
379 | 0 | gr.setPlayerName(ss[1].substring(0, ss[1].length()-1)); |
380 | 0 | this.preStartList.add(gr); // let the board fill out the values... |
381 | if (DEBUG) | |
382 | 0 | logger.info("addResumeYourTurn: addPreStart: " + gr.toString()); |
383 | 0 | if (gr.getPlayerName().equals(this.mainDialog.getDocument().getName())) { |
384 | 0 | GameEventPleaseMove gpm = new GameEventPleaseMove(); |
385 | 0 | gpm.setCheckersToMove(2); |
386 | 0 | gpm.setDice(gr.getDice()); |
387 | 0 | this.preStartList.add(gpm); |
388 | if (DEBUG) | |
389 | 0 | logger.info("addResumeYourTurn: addPreStart: " + gpm.toString()); |
390 | } | |
391 | ||
392 | 0 | } |
393 | /** Add this board line to the game log | |
394 | * @param s The board to add | |
395 | */ | |
396 | private void addBoardLine(String s) { | |
397 | 0 | GameEventBoard gb = new GameEventBoard(s); |
398 | 0 | queueGameEvent(gb); |
399 | 0 | if (!this.preStartList.isEmpty()) { |
400 | 0 | Board b = gb.getBoard(); |
401 | if (DEBUGJibsBoard) | |
402 | 0 | this.mainDialog.writeGameMessageln("board:" + b.getPlayerName()[0] + ":" + b.getPlayerName()[1]); |
403 | ||
404 | 0 | b.setSortDice(this.bfProps.isHighDieLeft()); |
405 | 0 | this.mainDialog.getDocument().setBoard(b); |
406 | 0 | for (GameEvent ge : this.preStartList) { |
407 | if (DEBUG) | |
408 | 0 | logger.info("Sending preStart: " + ge.toString()); |
409 | 0 | if (ge.getType() == Type.Roll) { |
410 | 0 | GameEventRoll gr = (GameEventRoll)ge; |
411 | 0 | if (gr.getDice()[0] == 0) { // Do we need the dice roll from the board? |
412 | 0 | if (this.bfProps.isHighDieLeft()) |
413 | 0 | gr.getDice()[0] = b.getDice()[Board.O][0]; |
414 | 0 | gr.getDice()[1] = b.getDice()[Board.O][1]; |
415 | } | |
416 | } | |
417 | 0 | queueGameEvent(ge); |
418 | 0 | } |
419 | // this.resumingMatch = false; | |
420 | 0 | this.preStartList.clear(); |
421 | } | |
422 | 0 | } |
423 | private void addMove(String s) { | |
424 | 0 | GameEventMove gm = new GameEventMove(); |
425 | 0 | gm.parse(s); |
426 | 0 | gm.setWho(this.mainDialog.getDocument().getBoard().getXOFromName(gm.getPlayerName())); |
427 | 0 | gm.setDirection(this.mainDialog.getDocument().getBoard().getDirectionFromName(gm.getPlayerName())); |
428 | if (DEBUG) | |
429 | 0 | logger.info("addMove: " + s); |
430 | 0 | queueGameEvent(gm); |
431 | 0 | } |
432 | /** Bearing off is just a move that comes in funny. | |
433 | * It is only important for You. Opponents and watchers also get a move, so we'll use that. | |
434 | * @param s 'Bearing off: 6 o 2 o ' | |
435 | */ | |
436 | private void addBearingOff(String s) { | |
437 | 0 | GameEventRoll gr = (GameEventRoll)getLastOf(Type.Roll); |
438 | 0 | if (!gr.getPlayerName().equals("You")) |
439 | 0 | return; |
440 | 0 | GameEventMove gm = new GameEventMove(); |
441 | 0 | gm.parseBearingOff(s); |
442 | 0 | gm.setWho(Board.O); |
443 | if (DEBUG) | |
444 | 0 | logger.info("addBearingOff: " + s); |
445 | 0 | queueGameEvent(gm); |
446 | ||
447 | 0 | } |
448 | private void addRoll(String s) { | |
449 | 0 | GameEventRoll gr = new GameEventRoll(); |
450 | 0 | gr.parse(s); |
451 | 0 | gr.setWho(this.mainDialog.getDocument().getBoard().getXOFromName(gr.getPlayerName())); |
452 | if (DEBUG) { | |
453 | 0 | logger.info("addRoll: " + s + " who:" + gr.getWho()); |
454 | } | |
455 | 0 | queueGameEvent(gr); |
456 | 0 | } |
457 | private void addFirstRoll(String s) { | |
458 | 0 | GameEventFirstRoll gfr = new GameEventFirstRoll(); |
459 | 0 | gfr.parse(s); |
460 | //gfr.setWho(this.mainDialog.getDocument().getBoard().getXOFromName(gfr.getPlayerName())); | |
461 | if (DEBUG) { | |
462 | 0 | logger.info("addRoll: " + s + " who:" + gfr.getWho()); |
463 | } | |
464 | 0 | queueGameEvent(gfr); |
465 | 0 | } |
466 | private void addYouCantMove(String unused) { | |
467 | 0 | GameEventCantMove gcm = new GameEventCantMove(); |
468 | 0 | gcm.setWho(Board.O); |
469 | if (DEBUG) | |
470 | 0 | logger.info("addYouCantMove: " + " who:" + gcm.getWho()); |
471 | 0 | queueGameEvent(gcm); |
472 | ||
473 | 0 | } |
474 | private void addCantMove(String s) { | |
475 | 0 | GameEventCantMove gcm = new GameEventCantMove(); |
476 | 0 | gcm.parse(s); |
477 | 0 | gcm.setWho(this.mainDialog.getDocument().getBoard().getXOFromName(gcm.getPlayerName())); |
478 | if (DEBUG) | |
479 | 0 | logger.info("addCantMove: " + s + " who:" + gcm.getWho()); |
480 | 0 | queueGameEvent(gcm); |
481 | 0 | } |
482 | /** Called when the current event is your move. | |
483 | * @param checkersToMove The number of checkers you have to move. | |
484 | */ | |
485 | private void addPleaseMove(String s) { | |
486 | 0 | GameEventPleaseMove gpm = new GameEventPleaseMove(); |
487 | 0 | gpm.parse(s); |
488 | 0 | GameEventRoll gr = (GameEventRoll)getLastOf(Type.Roll); |
489 | 0 | gpm.setDice(gr.getDice()); |
490 | if (DEBUG) | |
491 | 0 | logger.info("addPleaseMove: toMove=" + gpm.getCheckersToMove()); |
492 | 0 | queueGameEvent(gpm); |
493 | 0 | } |
494 | /** Called if You are taking the first turn of the game. "<code>It's your turn to move.</code>" | |
495 | * @param unused | |
496 | */ | |
497 | private void addYourTurnToMove(String s) { | |
498 | 0 | addFirstMove(s); |
499 | 0 | GameEventPleaseMove gpm = new GameEventPleaseMove(); |
500 | //gpm.parse(s); | |
501 | 0 | gpm.setCheckersToMove(2); |
502 | 0 | GameEventRoll gr = (GameEventRoll)getLastOf(Type.Roll); |
503 | 0 | if (gr == null) |
504 | 0 | gr = (GameEventRoll)getLastOf(Type.FirstRoll); |
505 | 0 | gpm.setDice(gr.getDice()); |
506 | if (DEBUG) | |
507 | 0 | logger.info("addYourTurnToMove: toMove=" + gpm.getCheckersToMove()); |
508 | 0 | queueGameEvent(gpm); |
509 | 0 | } |
510 | private void addFirstMove(String s) { | |
511 | 0 | GameEventFirstMove gefm = new GameEventFirstMove(); |
512 | 0 | GameEventFirstRoll gefr = (GameEventFirstRoll)getLastOf(Type.FirstRoll); |
513 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
514 | 0 | gefm.parse(s, gefr, geb.getBoard()); |
515 | if (DEBUG) | |
516 | 0 | logger.info("addFirstMove:"); |
517 | 0 | queueGameEvent(gefm); |
518 | ||
519 | 0 | } |
520 | private void addResign(String s) { | |
521 | 0 | GameEventResign ger = new GameEventResign(); |
522 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
523 | 0 | Board b = geb.getBoard(); |
524 | 0 | ger.parse(s, b); |
525 | ||
526 | if (DEBUG) | |
527 | 0 | logger.info("addResign: s=" + s); |
528 | 0 | queueGameEvent(ger); |
529 | 0 | GameEventPleaseAcceptOrRejectResign geparr = new GameEventPleaseAcceptOrRejectResign(); |
530 | 0 | geparr.setWho(ger.getWho()); |
531 | 0 | geparr.setResigningPoints(ger.getResigningPoints()); |
532 | 0 | queueGameEvent(geparr); |
533 | 0 | } |
534 | private void addResignRefused(String unused) { | |
535 | 0 | GameEventPleaseAcceptOrRejectResign geparr = |
536 | 0 | (GameEventPleaseAcceptOrRejectResign)getLastOf(Type.PleaseAcceptOrRejectResign); |
537 | 0 | if (geparr == null) |
538 | 0 | return; // not enough info to properly work from this (player is most likely starting to watch in mid-game). |
539 | 0 | GameEventRejectResign gerr = new GameEventRejectResign(); |
540 | 0 | gerr.setWho(geparr.getWho() == Board.X ? Board.O : Board.X); |
541 | 0 | GameEventPleaseAcceptOrRejectResign gepaorr = (GameEventPleaseAcceptOrRejectResign)getLastOf(Type.PleaseAcceptOrRejectResign); |
542 | 0 | gerr.setResigningPoints(gepaorr.getResigningPoints()); |
543 | 0 | queueGameEvent(gerr); |
544 | 0 | } |
545 | private void addAcceptsAndWins(String s) { | |
546 | 0 | GameEventAcceptAndWin geaaw = new GameEventAcceptAndWin(); |
547 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
548 | 0 | Board b = geb.getBoard(); |
549 | 0 | geaaw.parse(s, b); |
550 | 0 | queueGameEvent(geaaw); |
551 | 0 | } |
552 | private void addYouDouble(String s) { | |
553 | 0 | GameEventYouDouble geyd = new GameEventYouDouble(); |
554 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
555 | 0 | Board b = geb.getBoard(); |
556 | 0 | b.setWasDoubled(b.getXO()); |
557 | 0 | geyd.setCubeBefore(b.getCube()); |
558 | 0 | geyd.setWhoDoubled(b.getXO()); |
559 | 0 | logger.info("who = " + geb.getBoard().getXOAsText()); |
560 | 0 | logger.info("geyd.whoDoubled = " + geyd.getWhoDoubled()); |
561 | 0 | queueGameEvent(geyd); |
562 | 0 | GameEventPleaseAcceptOrRejectDouble gepard = new GameEventPleaseAcceptOrRejectDouble(); |
563 | 0 | gepard.setGuiEvent(false); |
564 | 0 | gepard.setWhoDoubled(geyd.getWhoDoubled()); |
565 | 0 | logger.info("gepard.setWhoDoubled = " + gepard.getWhoDoubled()); |
566 | 0 | queueGameEvent(gepard); |
567 | ||
568 | 0 | } |
569 | ||
570 | private void addOtherDoubles(String s) { | |
571 | 0 | GameEventDouble ged = new GameEventDouble(); |
572 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
573 | 0 | Board b = geb.getBoard(); |
574 | 0 | ged.parse(s, b); |
575 | 0 | b.setWasDoubled(ged.getWhoDoubled()); |
576 | if (DEBUG) | |
577 | 0 | logger.info("addOtherDoubles: s=" + s); |
578 | 0 | queueGameEvent(ged); |
579 | 0 | GameEventPleaseAcceptOrRejectDouble gepard = new GameEventPleaseAcceptOrRejectDouble(); |
580 | 0 | gepard.setGuiEvent(false); |
581 | 0 | gepard.setWhoDoubled(ged.getWhoDoubled()); |
582 | 0 | queueGameEvent(gepard); |
583 | 0 | } |
584 | private void addAcceptRejectDouble(String s) { | |
585 | 0 | GameEventDouble ged = new GameEventDouble(); |
586 | 0 | GameEventBoard geb = (GameEventBoard)getLastOf(Type.Board); |
587 | 0 | Board b = geb.getBoard(); |
588 | 0 | ged.parse(s, b); |
589 | 0 | b.setWasDoubled(ged.getWhoDoubled()); |
590 | ||
591 | if (DEBUG) | |
592 | 0 | logger.info("addDoubles to You: s=" + s); |
593 | 0 | queueGameEvent(ged); |
594 | 0 | GameEventPleaseAcceptOrRejectDouble gepard = new GameEventPleaseAcceptOrRejectDouble(); |
595 | //gepard.setWho(Board.X); | |
596 | if (DEBUG) | |
597 | 0 | logger.info("addAcceptRejectDouble: add PleaseAcceptRejectDouble"); |
598 | 0 | queueGameEvent(gepard); |
599 | 0 | } |
600 | ||
601 | /////////////////////////////////////////////////////////////////////////// | |
602 | /** Go to the first event in the game log | |
603 | */ | |
604 | public void goFirst() { | |
605 | 0 | this.position = 1; |
606 | if (DEBUGpos) | |
607 | 0 | logger.info("goFirst: pos = " + this.position); |
608 | 0 | sendGameEvent(Start); |
609 | 0 | updateToolbarButtons(); |
610 | 0 | } |
611 | ||
612 | /** Go to the previous event in the game log | |
613 | */ | |
614 | public void goPrev() { | |
615 | 0 | if (this.position > 1) |
616 | 0 | this.position--; |
617 | if (DEBUGpos) | |
618 | 0 | logger.info("goPrev: pos = " + this.position); |
619 | 0 | sendGameEvent(Backward); |
620 | 0 | updateToolbarButtons(); |
621 | 0 | } |
622 | ||
623 | /** Go to the next event in the game log | |
624 | */ | |
625 | public void goNext() { | |
626 | 0 | if (this.position < this.gameEvents.size()) |
627 | 0 | this.position++; |
628 | if (DEBUGpos) | |
629 | 0 | logger.info("goNext: pos = " + this.position); |
630 | 0 | sendGameEvent(Forward); |
631 | 0 | updateToolbarButtons(); |
632 | 0 | } |
633 | ||
634 | /** Go to the last event in the game log | |
635 | */ | |
636 | public void goLast() { | |
637 | 0 | this.position = this.gameEvents.size(); |
638 | if (DEBUGpos) | |
639 | 0 | logger.info("goLast: pos = " + this.position); |
640 | 0 | sendGameEvent(Forward); |
641 | 0 | updateToolbarButtons(); |
642 | 0 | } |
643 | ||
644 | /** Undo a partial move, start your turn over. | |
645 | */ | |
646 | public void goUndo() { | |
647 | 0 | sendGameEvent(Undo); |
648 | 0 | } |
649 | ||
650 | /** Play or Paused pressed */ | |
651 | public void goPlayPaused() { | |
652 | ||
653 | 0 | } |
654 | ||
655 | /////////////////////////////////////////////////////////////////////////// | |
656 | /////////////////////////////////////////////////////////////////////////// | |
657 | /** Send the current Event to the display. | |
658 | * If animation is off, then skip animation events by moving to prev/next. | |
659 | * Synchronized because the timer thread can enter here | |
660 | * @param dir The direction to skip to, if need be. {@link #Forward} or {@link #Backward} | |
661 | */ | |
662 | private synchronized void sendGameEvent(int dir) { | |
663 | //int localpos = this.position; | |
664 | if (DEBUGsend || DEBUGpos) | |
665 | 0 | logger.info("sendGameEvent: position=" + this.position + " size=" + this.gameEvents.size()); |
666 | 0 | if (dir == Undo) { |
667 | // We assume it is a legit undo. | |
668 | // We are going to look for board-rolls-board and rewind to that first board. | |
669 | 0 | boolean lastBoardWasSeen = false; |
670 | 0 | GameEvent ge = null; |
671 | int k; | |
672 | 0 | for (k = this.gameEvents.size()-1; k >= 0; k--) { |
673 | 0 | ge = this.gameEvents.get(k); |
674 | 0 | if (ge.getType() == Type.Board) { |
675 | 0 | if (lastBoardWasSeen) { |
676 | 0 | break; |
677 | } | |
678 | 0 | lastBoardWasSeen = true; |
679 | } | |
680 | 0 | ge = null; |
681 | } | |
682 | 0 | if (ge != null) { |
683 | 0 | for (position = k; position < this.gameEvents.size(); position++) { |
684 | 0 | ge = this.gameEvents.get(position); |
685 | 0 | this.mainDialog.moveEvent(ge); |
686 | } | |
687 | } | |
688 | } | |
689 | 0 | if (dir == Forward && this.replayToolbar.isPlayPause()) { |
690 | ||
691 | } | |
692 | while (true) { | |
693 | 0 | GameEvent ge = this.gameEvents.get(this.position-1); |
694 | if (DEBUGsend) | |
695 | 0 | logger.debug("send: loop top: pos=" + this.position + " ge=" + ge.getType().toString()); |
696 | 0 | if (ge.getType() == Type.Board) { |
697 | // GameBoard gb = (GameBoard)ge; | |
698 | // Board board = this.mainDialog.getDocument().getBoard(); | |
699 | // if (board.isYouPlaying() && board.isYourMove() && position == gameEvents.size()) | |
700 | // this.mainDialog.yourMove(gb.getCheckersToMove()); | |
701 | if (DEBUGsend) { | |
702 | 0 | logger.debug("sendToAnimate a: pos=" + position + " size=" + this.gameEvents.size()); |
703 | 0 | logger.debug("sendToAnimtate a: " + ge.getType().toString()); |
704 | } | |
705 | 0 | this.mainDialog.moveEvent(ge); |
706 | 0 | if ((bfProps.isAnimateMoves() && this.position == gameEvents.size()) |
707 | || dir == Start) { | |
708 | 0 | return; |
709 | } | |
710 | 0 | if (this.position >= gameEvents.size()) { // unless it is the last one in the list |
711 | if (DEBUGsend || DEBUGpos) | |
712 | 0 | logger.info("send: End of list: Don't bump pos " + this.position + " after sending board"); |
713 | 0 | updateToolbarButtons(); |
714 | 0 | return; |
715 | } | |
716 | 0 | this.position += dir; |
717 | if (DEBUGsend || DEBUGpos) | |
718 | 0 | logger.info("send: Set pos to " + this.position + " after sending board"); |
719 | 0 | updateToolbarButtons(); |
720 | } else { | |
721 | 0 | if (bfProps.isAnimateMoves()) { |
722 | if (DEBUGsend) { | |
723 | 0 | logger.info("sendToAnimate b: pos=" + position + " size=" + this.gameEvents.size()); |
724 | 0 | logger.info("sendToAnimate b: " + ge.getType().toString()); |
725 | } | |
726 | 0 | this.mainDialog.moveEvent(ge); |
727 | 0 | updateToolbarButtons(); |
728 | 0 | return; |
729 | } | |
730 | 0 | if (dir == Forward) { // going forward? |
731 | 0 | if (this.position < gameEvents.size()) { |
732 | 0 | this.position++; // try to skip ahead |
733 | } | |
734 | if (DEBUGsend || DEBUGpos) | |
735 | 0 | logger.info("send: skip position to " + this.position + " gameEvents.size=" + gameEvents.size()); |
736 | 0 | if (this.position >= gameEvents.size()) { // unless it is the last one in the list |
737 | if (DEBUGsend || DEBUGpos) { | |
738 | 0 | logger.info("sendToAnimate c: pos=" + position + " size=" + this.gameEvents.size()); |
739 | 0 | logger.info("sendToAnimate c: " + ge.getType().toString()); |
740 | } | |
741 | 0 | this.mainDialog.moveEvent(ge); |
742 | //this.position = localpos; | |
743 | if (DEBUGsend || DEBUGpos) | |
744 | 0 | logger.info("send: pos = " + this.position + " and send nothing"); |
745 | 0 | updateToolbarButtons(); |
746 | 0 | return; |
747 | } | |
748 | if (DEBUGsend) | |
749 | 0 | logger.info("send: Skipping this event"); |
750 | 0 | continue; |
751 | } | |
752 | 0 | this.position--; |
753 | 0 | if (this.position < 1) { |
754 | 0 | this.position = 1; |
755 | if (DEBUGsend) { | |
756 | 0 | logger.info("sendToAnimate d: pos=" + position + " size=" + this.gameEvents.size()); |
757 | 0 | logger.info("sendToAnimate d: " + ge.getType().toString()); |
758 | } | |
759 | 0 | this.mainDialog.moveEvent(ge); |
760 | 0 | updateToolbarButtons(); |
761 | 0 | return; |
762 | } | |
763 | } | |
764 | 0 | } |
765 | } | |
766 | ||
767 | 0 | private LinkedList<GameEvent> gameEvents = new LinkedList<GameEvent>(); |
768 | ||
769 | /** All write access to the gameEvents list is via this function. | |
770 | * @param gameEvent The event to queue at the end. | |
771 | */ | |
772 | private void queueGameEvent(GameEvent gameEvent) { | |
773 | if (DEBUG) | |
774 | 0 | logger.debug("queueGameEvent: a position=" + this.position + " size=" + this.gameEvents.size()); |
775 | 0 | if (!gameEvents.isEmpty()) { |
776 | 0 | GameEvent old = gameEvents.getLast(); |
777 | 0 | if (old.getLife() == Life.Transient) { |
778 | 0 | if (this.position == gameEvents.size()) |
779 | 0 | this.position--; |
780 | 0 | gameEvents.removeLast(); |
781 | if (DEBUG) { | |
782 | 0 | logger.debug("queueGameEvent: b position=" + this.position + " size=" + this.gameEvents.size()); |
783 | 0 | logger.debug("queueGameEvent: b remove old=" + old.getType().toString()); |
784 | } | |
785 | // if (gameEvent.getType() == Type.Board) { | |
786 | // GameEventBoard gb = (GameEventBoard)gameEvent; | |
787 | // gb.setPostEvent(old); | |
788 | // if (DEBUG) | |
789 | // logger.info("queueGameEvent: set post=" + old.getType().toString()); | |
790 | // } | |
791 | } | |
792 | } | |
793 | 0 | gameEvents.add(gameEvent); |
794 | if (DEBUG) | |
795 | 0 | logger.debug("queueGameEvent: queued: " + gameEvent.toString()); |
796 | if (DEBUG) | |
797 | 0 | logger.debug("queueGameEvent: c position=" + this.position + " size=" + this.gameEvents.size()); |
798 | 0 | boolean shouldMove = this.replayToolbar.isPlayPause(); |
799 | 0 | if (shouldMove) { |
800 | 0 | this.position++; |
801 | 0 | sendGameEvent(Forward); |
802 | } else { | |
803 | 0 | updateToolbarButtons(); |
804 | } | |
805 | 0 | } |
806 | ||
807 | private GameEvent getLastOf(Type eventType) { | |
808 | 0 | GameEvent ret = null; |
809 | 0 | for (GameEvent ge : gameEvents) { |
810 | 0 | if (ge.getType() == eventType) |
811 | 0 | ret = ge; |
812 | 0 | } |
813 | 0 | return(ret); |
814 | } | |
815 | ||
816 | private void updateToolbarButtons() { | |
817 | 0 | this.replayToolbar.getJButtonFirst().setEnabled(position > 1); |
818 | 0 | this.replayToolbar.getJButtonBack().setEnabled( position > 1); |
819 | 0 | this.replayToolbar.getJButtonNext().setEnabled( position < gameEvents.size()); |
820 | 0 | this.replayToolbar.getJButtonEnd().setEnabled( position < gameEvents.size()); |
821 | 0 | } |
822 | ||
823 | // Timer goes here | |
824 | } |