Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Board |
|
| 2.0425531914893615;2.043 |
1 | /****************************************************************************** | |
2 | * Board.java - Define a backgammon board | |
3 | * $Id$ | |
4 | * | |
5 | * BuckoFIBS - Backgammon by BuckoSoft | |
6 | * Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp. | |
7 | * | |
8 | * $Log$ | |
9 | * Revision 1.16 2013/09/12 06:40:41 dick | |
10 | * static xoToTurn(). | |
11 | * | |
12 | * Revision 1.15 2011/07/04 03:36:01 dick | |
13 | * Add getCanMove(). | |
14 | * | |
15 | * Revision 1.14 2011/06/19 04:14:31 dick | |
16 | * Define turnO and turnX. | |
17 | * | |
18 | * Revision 1.13 2011/06/13 04:38:42 dick | |
19 | * Add parseFibsBoard(s, bool) for debugging boards. | |
20 | * | |
21 | * Revision 1.12 2011/06/10 05:59:32 dick | |
22 | * Add isOpponentMayDouble(). | |
23 | * | |
24 | * Revision 1.11 2011/06/02 19:04:37 dick | |
25 | * Add attributes and methods for dealing with a player resigning. | |
26 | * | |
27 | * Revision 1.10 2011/05/21 20:19:09 dick | |
28 | * If setSortDice(true) then sort any existing dice. | |
29 | * | |
30 | * Revision 1.9 2011/05/21 04:54:40 dick | |
31 | * happenings about doubles goes in Board, not Document. | |
32 | * | |
33 | * Revision 1.8 2011/05/18 05:50:46 dick | |
34 | * Javadoc. | |
35 | * | |
36 | * Revision 1.7 2011/05/17 23:55:25 dick | |
37 | * Add the clone() method. | |
38 | * | |
39 | * Revision 1.6 2011/05/17 23:14:04 dick | |
40 | * getDirectionFromName() does that. | |
41 | * | |
42 | * Revision 1.5 2011/05/16 21:20:43 dick | |
43 | * Javadoc. | |
44 | * | |
45 | * Revision 1.4 2011/05/16 11:35:43 dick | |
46 | * getXOFromName determines the direction from an event. | |
47 | * | |
48 | * Revision 1.3 2011/05/15 18:16:52 dick | |
49 | * Javadoc link fix. | |
50 | * | |
51 | * Revision 1.2 2011/05/14 05:19:46 dick | |
52 | * Still need work on the doubles handling for board/document split. | |
53 | * | |
54 | * Revision 1.1 2011/05/14 04:43:01 dick | |
55 | * I needed to deal with some lightweight Boards. | |
56 | * So finally make the primary document Document | |
57 | * and demote just the Board handling to a domain object. | |
58 | * | |
59 | * Revision 1.10 2011/05/13 18:23:25 dick | |
60 | * Commentality. | |
61 | * | |
62 | * Revision 1.9 2011/05/13 14:18:15 dick | |
63 | * Define constants Home=0 and Bar=25. | |
64 | * | |
65 | * Revision 1.8 2011/05/10 20:34:22 dick | |
66 | * Javadoc. | |
67 | * | |
68 | * Revision 1.7 2011/01/01 06:10:25 dick | |
69 | * Javadoc. | |
70 | * | |
71 | * Revision 1.6 2010/12/29 07:42:24 dick | |
72 | * Sorting dice is optional. | |
73 | * | |
74 | * Revision 1.5 2010/12/24 06:12:07 dick | |
75 | * Handle the onMatchOver message correctly. | |
76 | * | |
77 | * Revision 1.4 2010/03/03 13:12:22 inim | |
78 | * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8 | |
79 | * | |
80 | * Revision 1.3 2010/03/03 12:19:49 inim | |
81 | * 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. | |
82 | * | |
83 | * Revision 1.2 2010/02/08 09:12:35 dick | |
84 | * isRace() determines if a game is race mode. | |
85 | * | |
86 | * Revision 1.1 2010/02/04 05:57:53 inim | |
87 | * Mavenized project folder layout | |
88 | * | |
89 | * Revision 1.35 2010/01/23 06:13:06 dick | |
90 | * removeSavedMatch() removes a match from the saved (unfinished) matches list. | |
91 | * | |
92 | * Revision 1.34 2009/02/24 07:12:35 dick | |
93 | * Correctly parse the match score onMatchOver(). | |
94 | * | |
95 | * Revision 1.33 2009/02/20 10:20:47 dick | |
96 | * Use YourName and OpponentName where possible, instead of just "getName". | |
97 | * | |
98 | * Revision 1.32 2009/02/17 14:44:08 dick | |
99 | * Turn off DEBUG. | |
100 | * | |
101 | * Revision 1.31 2009/02/14 12:04:30 dick | |
102 | * BuckoFIBS is released under the GNU license. | |
103 | * | |
104 | * Revision 1.30 2009/02/12 06:05:26 dick | |
105 | * Javadoc. | |
106 | * | |
107 | * Revision 1.29 2009/02/11 08:59:24 dick | |
108 | * Better beginning and ending your turn. | |
109 | * | |
110 | * Revision 1.28 2009/02/06 07:56:49 dick | |
111 | * Working on doubles. | |
112 | * | |
113 | * Revision 1.27 2009/02/01 21:21:01 dick | |
114 | * Add savedMatches and missManners lists to track other players' behavior. | |
115 | * | |
116 | * Revision 1.26 2009/01/29 08:26:39 dick | |
117 | * Fix the pip count calculation. | |
118 | * | |
119 | * Revision 1.25 2009/01/28 19:42:37 dick | |
120 | * Prettier cvs link in the javadoc. | |
121 | * | |
122 | * Revision 1.24 2009/01/26 07:31:24 dick | |
123 | * Sort the dice high to low. | |
124 | * | |
125 | * Revision 1.23 2009/01/24 17:04:21 dick | |
126 | * When parsing the board, i tried to normalize the data so that the player was always playing 24-1. | |
127 | * That didn't really work out, great for watching, tough for playing. | |
128 | * So get rid of it. | |
129 | * Also, lots of javadoc. | |
130 | * | |
131 | * Revision 1.22 2009/01/22 05:01:26 dick | |
132 | * add getXO(). | |
133 | * | |
134 | * Revision 1.21 2009/01/20 07:41:54 dick | |
135 | * Send a string to the parser to set the initial positions. | |
136 | * | |
137 | * Revision 1.20 2009/01/18 05:26:24 dick | |
138 | * Javadoc. | |
139 | * | |
140 | * Revision 1.19 2009/01/18 04:43:41 dick | |
141 | * Javadoc. | |
142 | * | |
143 | * Revision 1.18 2009/01/10 05:20:36 dick | |
144 | * Turn off DEBUG. | |
145 | * | |
146 | * Revision 1.17 2009/01/10 05:02:27 dick | |
147 | * Totally cleanup who is who. I parse the board so that You is always Player0 and playing 24 to 1. | |
148 | * Get rid of unneeded setters. Only parseFibsBoard can set attributes. | |
149 | * | |
150 | * Revision 1.16 2009/01/09 06:56:07 dick | |
151 | * Change whosTurn parsing. | |
152 | * Turn off DEBUG. | |
153 | * | |
154 | * Revision 1.15 2009/01/08 18:25:26 dick | |
155 | * Add getMatchLength | |
156 | * | |
157 | * Revision 1.14 2009/01/08 01:28:13 dick | |
158 | * getPlayerName returns the list of players in this match. | |
159 | * | |
160 | * Revision 1.13 2009/01/06 08:05:07 dick | |
161 | * Javadoc. | |
162 | * | |
163 | * Revision 1.12 2008/12/20 23:01:39 dick | |
164 | * Support for Own Info. | |
165 | * | |
166 | * Revision 1.11 2008/12/17 04:37:11 dick | |
167 | * Add the direction that the user is playing in. | |
168 | * | |
169 | * Revision 1.10 2008/12/13 06:15:33 dick | |
170 | * Parse home and the bar. | |
171 | * | |
172 | * Revision 1.9 2008/12/12 14:44:22 dick | |
173 | * Fibs board parsing. | |
174 | * | |
175 | * Revision 1.8 2008/12/12 01:19:52 dick | |
176 | * Start reworking for a point based board, not a checker based board. | |
177 | * | |
178 | * Revision 1.7 2008/12/11 20:24:23 dick | |
179 | * Early parsing of FIBS board. | |
180 | * | |
181 | * Revision 1.6 2008/12/10 21:55:14 dick | |
182 | * Add dice attributes. | |
183 | * | |
184 | * Revision 1.5 2008/12/09 01:47:05 dick | |
185 | * Define WHITE and BLACK. | |
186 | * | |
187 | * Revision 1.4 2008/12/08 10:16:31 dick | |
188 | * Add setStartPositions(). | |
189 | * | |
190 | * Revision 1.3 2008/12/08 06:44:07 dick | |
191 | * checkers is an array of int. | |
192 | * | |
193 | * Revision 1.2 2008/03/30 05:38:51 dick | |
194 | * More skeleton checkins. | |
195 | * | |
196 | * Revision 1.1 2008/03/29 08:57:43 dick | |
197 | * BuckoFIBS skeleton checkin. | |
198 | */ | |
199 | ||
200 | /* | |
201 | * This program is free software: you can redistribute it and/or modify | |
202 | * it under the terms of the GNU General Public License as published by | |
203 | * the Free Software Foundation, either version 3 of the License, or | |
204 | * (at your option) any later version. | |
205 | * | |
206 | * This program is distributed in the hope that it will be useful, | |
207 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
208 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
209 | * GNU General Public License for more details. | |
210 | * | |
211 | * You should have received a copy of the GNU General Public License | |
212 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
213 | * | |
214 | * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>. | |
215 | * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp. | |
216 | * | |
217 | */ | |
218 | package com.buckosoft.fibs.domain; | |
219 | ||
220 | ||
221 | ||
222 | /** Define a backgammon board. | |
223 | * This object parses the fibs board command and returns various attributes from the parse. | |
224 | * @author Dick Balaska | |
225 | * @since 2008/03/29 | |
226 | * @version $Revision$ <br> $Date$ | |
227 | * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/domain/Board.java">cvs Board.java</a> | |
228 | * @see <a href="http://www.fibs.com/fibs_interface.html#board_state" target="_top">FIBS Client Protocol Detailed Specification</a> | |
229 | */ | |
230 | 0 | public class Board implements Cloneable { |
231 | private final static boolean DEBUG = false; | |
232 | ||
233 | private int canMove; | |
234 | ||
235 | ||
236 | private int xo; | |
237 | 77 | private int matchLength = 0; |
238 | 77 | private int matchScore[] = new int[2]; |
239 | 1 | private static String initialPositions = "board:Player0:Player1:3:0:0:0:-2:0:0:0:0:5:0:3:0:0:0:-5:5:0:0:0:-3:0:-5:0:0:0:0:2:0:1:0:0:0:0:1:1:1:0:1:-1:0:25:0:0:0:0:2:0:0:0"; |
240 | // private boolean gameOver = true; | |
241 | 77 | private int[][] dice = new int[2][2]; |
242 | private int direction; | |
243 | 77 | private String[] playerName = new String[2]; |
244 | 77 | private int[] points = new int[26]; // 0 and 25 are unused. See bar |
245 | 77 | private int[] bar = new int[2]; |
246 | 77 | private int[] home = new int [2]; |
247 | 77 | private int[] pipCount = new int[2]; |
248 | ||
249 | /** The player playing the 'O' pieces. The value is 0. */ | |
250 | public final static int O = 0; | |
251 | /** The player playing the 'X' pieces. The value is 1. */ | |
252 | public final static int X = 1; | |
253 | /** X's turn is marked with -1 */ | |
254 | public final static int turnX = -1; | |
255 | /** O's turn is marked with 1 */ | |
256 | public final static int turnO = 1; | |
257 | ||
258 | /** We don't know if it is player O or player X */ | |
259 | public final static int XOnot = -2; | |
260 | /** When dealing with pointArrays, the special value Home is 0 */ | |
261 | public final static int Home = 0; | |
262 | /** When dealing with pointArrays, the special value Bar is 25 */ | |
263 | public final static int Bar = 25; | |
264 | ||
265 | /** Convert {@link Board#X} to {@link Board#turnX} and {@link Board#O} to {@link Board#turnO}. | |
266 | * @param xo The board player. | |
267 | * @return The turn. | |
268 | */ | |
269 | public static int xoToTurn(int xo) { | |
270 | 0 | return (xo == Board.X ? Board.turnX : Board.turnO); |
271 | } | |
272 | ||
273 | ||
274 | 77 | private int whosTurn = 0; |
275 | 77 | private int cube = 1; |
276 | ||
277 | 77 | private boolean sortDice = true; |
278 | ||
279 | /** Who has the doubling cube?<br> | |
280 | * -1 = noone, X = X, O = O */ | |
281 | 77 | private int hasCube = 0; |
282 | 77 | private int[] mayDouble = new int[2]; |
283 | 77 | private boolean[] wasDoubled = new boolean[2]; |
284 | ||
285 | ||
286 | /* "External" attributes. That is, not derived by parseBoard */ | |
287 | ||
288 | 77 | private boolean yourTurnToRollOrDouble = false; |
289 | 77 | private boolean acceptDeclineResign = false; |
290 | 77 | private int whoIsResigning = -1; |
291 | 77 | private int resigningPoints = -1; |
292 | ||
293 | /** Create an empty board */ | |
294 | 154 | public Board() { } |
295 | ||
296 | /** Clone this board | |
297 | * @return A new copy of this board. | |
298 | */ | |
299 | public Board clone() { | |
300 | 1 | Board b = new Board(); |
301 | 1 | b.xo = this.xo; |
302 | 1 | b.matchLength = this.matchLength; |
303 | 1 | b.matchScore[0] = this.matchScore[0]; |
304 | 1 | b.matchScore[1] = this.matchScore[1]; |
305 | 1 | b.dice[0][0] = this.dice[0][0]; |
306 | 1 | b.dice[0][1] = this.dice[0][1]; |
307 | 1 | b.dice[1][0] = this.dice[1][0]; |
308 | 1 | b.dice[1][1] = this.dice[1][1]; |
309 | 1 | b.direction = this.direction; |
310 | 1 | b.playerName[0] = this.playerName[0]; |
311 | 1 | b.playerName[1] = this.playerName[1]; |
312 | 27 | for (int i=0; i<26; i++) |
313 | 26 | b.points[i] = this.points[i]; |
314 | 1 | b.bar[0] = this.bar[0]; |
315 | 1 | b.bar[1] = this.bar[1]; |
316 | 1 | b.home[0] = this.home[0]; |
317 | 1 | b.home[1] = this.home[1]; |
318 | 1 | b.whosTurn = this.whosTurn; |
319 | 1 | b.cube = this.cube; |
320 | 1 | b.sortDice = this.sortDice; |
321 | 1 | b.hasCube = this.hasCube; |
322 | 1 | b.mayDouble[0] = this.mayDouble[0]; |
323 | 1 | b.mayDouble[1] = this.mayDouble[1]; |
324 | 1 | b.wasDoubled[0] = this.wasDoubled[0]; |
325 | 1 | b.wasDoubled[1] = this.wasDoubled[1]; |
326 | 1 | b.yourTurnToRollOrDouble = this.yourTurnToRollOrDouble; |
327 | 1 | b.acceptDeclineResign = this.acceptDeclineResign; |
328 | 1 | b.whoIsResigning = this.whoIsResigning; |
329 | 1 | b.resigningPoints = this.resigningPoints; |
330 | 1 | return(b); |
331 | } | |
332 | ||
333 | /** Set the flag saying we want sorted dice or not | |
334 | * @param sortDice true = sort the dice, false = deal with them as received | |
335 | */ | |
336 | public void setSortDice(boolean sortDice) { | |
337 | 5 | this.sortDice = sortDice; |
338 | 5 | if (sortDice) { |
339 | 3 | if (this.dice[0][0] < this.dice[0][1]) { |
340 | 1 | int x = dice[0][0]; |
341 | 1 | dice[0][0] = dice[0][1]; |
342 | 1 | dice[0][1] = x; |
343 | } | |
344 | 3 | if (this.dice[1][0] < this.dice[1][1]) { |
345 | 1 | int x = dice[1][0]; |
346 | 1 | dice[1][0] = dice[1][1]; |
347 | 1 | dice[1][1] = x; |
348 | } | |
349 | } | |
350 | 5 | } |
351 | ||
352 | /** Is it your turn? | |
353 | * @return the yourTurnToRollOrDouble | |
354 | */ | |
355 | public boolean isYourTurnToRollOrDouble() { | |
356 | 8 | return yourTurnToRollOrDouble; |
357 | } | |
358 | ||
359 | /** Set your turn to roll or double | |
360 | * @param yourTurnToRollOrDouble the yourTurnToRollOrDouble to set | |
361 | */ | |
362 | public void setYourTurnToRollOrDouble(boolean yourTurnToRollOrDouble) { | |
363 | 7 | this.yourTurnToRollOrDouble = yourTurnToRollOrDouble; |
364 | 7 | } |
365 | ||
366 | /** We have been doubled and need to accept or decline | |
367 | */ | |
368 | public void setAcceptDeclineDouble() { | |
369 | 2 | this.getWasDoubled()[1] = true; |
370 | 2 | } |
371 | ||
372 | /** Are you in a state where you are required to accept or decline a double? | |
373 | * @return true = opponent has doubled | |
374 | */ | |
375 | public boolean isAcceptDeclineDouble() { | |
376 | 6 | return(this.getWasDoubled()[1]); |
377 | } | |
378 | ||
379 | /** Are you in a state where you are required to accept or decline a resign? | |
380 | * @return true = opponent has offered to resign | |
381 | */ | |
382 | public boolean isAcceptDeclineResign() { | |
383 | 4 | return(this.acceptDeclineResign); |
384 | } | |
385 | ||
386 | public void setAcceptDeclineResign(boolean enabled) { | |
387 | 2 | this.acceptDeclineResign = enabled; |
388 | 2 | } |
389 | ||
390 | /** Someone wants to resign, this is the player | |
391 | * @param xo Board.X or Board.O wants to resign | |
392 | */ | |
393 | public void setWhoIsResigning(int xo) { | |
394 | 2 | this.whoIsResigning = xo; |
395 | 2 | } |
396 | ||
397 | public int getWhoIsResigning() { | |
398 | 2 | return(this.whoIsResigning); |
399 | } | |
400 | ||
401 | public void setResigningPoints(int resigningPoints) { | |
402 | 2 | this.resigningPoints = resigningPoints; |
403 | 2 | } |
404 | ||
405 | public int getResigningPoints() { | |
406 | 2 | return(this.resigningPoints); |
407 | } | |
408 | ||
409 | /** Fetch the points array, the checkers on the board. | |
410 | * 1-24 are used. 0 and 25 are ununsed (see home and bar). | |
411 | * @return The points array. | |
412 | */ | |
413 | public int[] getPoints() { | |
414 | 55 | return(points); |
415 | } | |
416 | ||
417 | /** Get the number of checkers on the bar for both players. | |
418 | * @return The bar | |
419 | */ | |
420 | public int[] getBar() { | |
421 | 6 | return(bar); |
422 | } | |
423 | ||
424 | /** Get the number of checkers in both player's homes. | |
425 | * @return The home array | |
426 | */ | |
427 | public int[] getHome() { | |
428 | 6 | return(home); |
429 | } | |
430 | ||
431 | /** Is there a pending double on the table? | |
432 | * @return an array of wasDoubled | |
433 | */ | |
434 | public boolean[] getWasDoubled() { | |
435 | 10 | return(this.wasDoubled); |
436 | } | |
437 | ||
438 | /** Is there a pending double on the table? | |
439 | * @param xo {@link Board#X} or {@link Board#O} | |
440 | */ | |
441 | public void setWasDoubled(int xo) { | |
442 | 0 | wasDoubled[Board.O] = false; |
443 | 0 | wasDoubled[Board.X] = false; |
444 | 0 | if (xo == Board.O) |
445 | 0 | wasDoubled[Board.O] = true; |
446 | 0 | if (xo == Board.X) |
447 | 0 | wasDoubled[Board.X] = true; |
448 | 0 | } |
449 | ||
450 | /** Are You allowed to double? | |
451 | * @return true is yes. | |
452 | */ | |
453 | public boolean isYouMayDouble() { | |
454 | 6 | return (this.mayDouble[Board.O] == 1); |
455 | } | |
456 | ||
457 | public boolean isOpponentMayDouble() { | |
458 | 3 | return (this.mayDouble[Board.X] == 1); |
459 | ||
460 | } | |
461 | /** Are you playing or just watching? | |
462 | * @return true if playing | |
463 | */ | |
464 | public boolean isYouPlaying() { | |
465 | 4 | return(this.playerName[0].equals("You")); |
466 | } | |
467 | ||
468 | /** Is it your turn to move? That is, have you rolled and should move checkers? | |
469 | * @return whether there is valid dice on the table. | |
470 | */ | |
471 | public boolean isYourMove() { | |
472 | 4 | return(dice[0][0] != 0); |
473 | } | |
474 | ||
475 | /** Get the list of player names who are playing this game. | |
476 | * @return The player Names | |
477 | */ | |
478 | public String[] getPlayerName() { | |
479 | 13 | return(playerName); |
480 | } | |
481 | ||
482 | /** Set the value of one of the playerNames. | |
483 | * @param which Which player to set {@link Board#X} or {@link Board#O} | |
484 | * @param name The name of the player. | |
485 | */ | |
486 | public void setPlayerName(int which, String name) { | |
487 | 2 | this.playerName[which] = name; |
488 | 2 | } |
489 | ||
490 | /** Get the number of points in the match | |
491 | * @return The matchLength | |
492 | */ | |
493 | public int getMatchLength() { | |
494 | 4 | return(matchLength); |
495 | } | |
496 | ||
497 | /** Get the score for both players in this match | |
498 | * @return the score array | |
499 | */ | |
500 | public int[] getMatchScore() { | |
501 | 8 | return(matchScore); |
502 | } | |
503 | ||
504 | /** Place all checkers on their start positions | |
505 | */ | |
506 | public void setStartPositions() { | |
507 | 1 | this.parseFibsBoard(initialPositions); |
508 | 1 | } |
509 | ||
510 | /** Get whether you are playing as X or O | |
511 | * @return -1 if you are X, 1 if you are O <br>({@link Board#turnX} or {@link Board#turnO}) | |
512 | */ | |
513 | public int getXO() { | |
514 | 3 | return(xo); |
515 | } | |
516 | ||
517 | /** Get XO as text. Just a devel function | |
518 | * @return "O" or "X" | |
519 | */ | |
520 | public String getXOAsText() { | |
521 | 0 | return(xo == Board.O ? "O" : "X"); |
522 | } | |
523 | ||
524 | /** Get XO as text. Just a devel function | |
525 | * @return "O" or "X" | |
526 | */ | |
527 | public static String getXOAsText(int xo) { | |
528 | 0 | return(xo == Board.O ? "O" : "X"); |
529 | } | |
530 | ||
531 | /** Get turnXO as text. Just a devel function | |
532 | * @return "O" or "X" | |
533 | */ | |
534 | public static String getTurnAsText(int turn) { | |
535 | 0 | return(turn == Board.turnO ? "turnO" : "turnX"); |
536 | } | |
537 | ||
538 | /** When you pick up the dice, 0 them out so there is a visual cue. | |
539 | * Sometimes it takes fibs a while to send a new board. | |
540 | */ | |
541 | public void clearDice() { | |
542 | 1 | this.dice[0][0] = 0; |
543 | 1 | this.dice[0][1] = 0; |
544 | 1 | } |
545 | ||
546 | /** Get who's turn it is. -1 = X, 1 = O, 0 = game over | |
547 | * @return the whosTurn {@link Board#turnX} or{@link Board#turnO} | |
548 | */ | |
549 | public int getWhosTurn() { | |
550 | 5 | return whosTurn; |
551 | } | |
552 | ||
553 | /** Given a playerName, return whether he is playing {@link Board#X} or {@link Board#O} | |
554 | * @param name The player's name to check | |
555 | * @return Board.X or Board.O for a match, {@link Board#XOnot} for non-match | |
556 | */ | |
557 | public int getXOFromName(String name) { | |
558 | 3 | if (name.equals(playerName[Board.X])) |
559 | 1 | return(Board.X); |
560 | 2 | else if (name.equals(playerName[Board.O])) |
561 | 1 | return(Board.O); |
562 | 1 | return(XOnot); |
563 | } | |
564 | ||
565 | /** Get the playing direction for this player | |
566 | * @param name The player name to check | |
567 | * @return -1 or 1 | |
568 | */ | |
569 | public int getDirectionFromName(String name) { | |
570 | 2 | if (name.equals(playerName[Board.O])) |
571 | 1 | return(direction); |
572 | 1 | return(-direction); |
573 | } | |
574 | ||
575 | /** Get the number displayed on the double cube | |
576 | * @return the cube | |
577 | */ | |
578 | public int getCube() { | |
579 | 4 | return cube; |
580 | } | |
581 | ||
582 | /** Who has the doubling cube? | |
583 | * -1 = noone, X = X, O = O | |
584 | * @return who has the cube | |
585 | */ | |
586 | public int getHasCube() { | |
587 | 4 | return hasCube; |
588 | } | |
589 | ||
590 | /** -1 If you play from position 24 to position 1.<br> | |
591 | * 1 If you play from position 1 to position 24. | |
592 | * @return the direction | |
593 | */ | |
594 | public int getDirection() { | |
595 | 11 | return direction; |
596 | } | |
597 | ||
598 | /** Get the 2x2 array of both player's both dice | |
599 | * @return the dice | |
600 | */ | |
601 | public int[][] getDice() { | |
602 | 21 | return dice; |
603 | } | |
604 | ||
605 | /** Return the number of pieces the player can move this turn. | |
606 | * @return The canMove from this board. | |
607 | */ | |
608 | public int getCanMove() { | |
609 | 0 | return(canMove); |
610 | } | |
611 | ||
612 | /** Handle the '* wins the match' message. <br> | |
613 | * Fibs doesn't send a final board, which should have the final score. | |
614 | * So we have to derive the match over scenario. | |
615 | */ | |
616 | public void onMatchOver(String winner, String score) { | |
617 | 2 | String[] ss = score.split("\\-"); |
618 | 2 | int s0 = Integer.parseInt(ss[0]); |
619 | 2 | int s1 = Integer.parseInt(ss[1]); |
620 | 2 | if (winner.equals("You") || winner.equals(this.playerName[0])) { |
621 | 1 | matchScore[0] = s0; |
622 | 1 | matchScore[1] = s1; |
623 | } else { | |
624 | 1 | matchScore[0] = s1; |
625 | 1 | matchScore[1] = s0; |
626 | } | |
627 | 2 | whosTurn = 0; |
628 | 2 | } |
629 | ||
630 | /** Calculate and return the number of pips for both players. | |
631 | * Used by the {@link com.buckosoft.fibs.BuckoFIBS.gui.boardTab.MatchStatusPanel}. | |
632 | * @return A reference to our local pipCount (reuse object). | |
633 | */ | |
634 | public int[] getPipCount() { | |
635 | int i; | |
636 | 1 | this.pipCount[O] = 0; |
637 | 1 | this.pipCount[X] = 0; |
638 | 25 | for (i=1; i<=24; i++) { |
639 | 24 | if (this.points[i] < 0) |
640 | 4 | pipCount[O] += ((this.getDirection() == -1 ? i : (25 - i)) * -this.points[i]); |
641 | 20 | else if (this.points[i] > 0) |
642 | 4 | pipCount[X] += ((this.getDirection() == 1 ? i : (25 - i)) * this.points[i]); |
643 | } | |
644 | 1 | pipCount[O] += (bar[O]*25); |
645 | 1 | pipCount[X] += (bar[X]*25); |
646 | ||
647 | 1 | return(this.pipCount); |
648 | } | |
649 | ||
650 | /** Is this game a race? | |
651 | * Determine whether all of your checkers are past the opponent's checkers | |
652 | * @return true if this game has turned into a race. | |
653 | */ | |
654 | public boolean isRace() { | |
655 | int i; | |
656 | 8 | int k = 0; |
657 | 8 | if (bar[O] > 0 || bar[X] > 0) |
658 | 2 | return(false); |
659 | 6 | boolean oppositeSeen = false; |
660 | 90 | for (i=1; i<=24; i++) { |
661 | 89 | if (this.points[i] == 0) |
662 | 58 | continue; |
663 | 31 | if (k == 0) { |
664 | 6 | k = this.points[i]; |
665 | 6 | continue; |
666 | } | |
667 | 25 | if (!oppositeSeen) { |
668 | 10 | if (k < 0 && this.points[i] > 0) { |
669 | 1 | oppositeSeen = true; |
670 | 1 | continue; |
671 | } | |
672 | 9 | if (k > 0 && this.points[i] < 0) { |
673 | 5 | oppositeSeen = true; |
674 | 5 | continue; |
675 | } | |
676 | } else { | |
677 | 15 | if (k < 0 && this.points[i] < 0) |
678 | 1 | return(false); |
679 | 14 | if (k > 0 && this.points[i] > 0) |
680 | 4 | return(false); |
681 | } | |
682 | } | |
683 | 1 | return(true); |
684 | } | |
685 | // positions of the fields in a board line | |
686 | private final static int YOU = 1; | |
687 | private final static int SOMEPLAYER = 2; | |
688 | private final static int MATCHLENGTH = 3; | |
689 | private final static int CURRENTSCORES = 4; | |
690 | private final static int BOARD = 6; | |
691 | private final static int TURN = 32; | |
692 | private final static int DICE = 33; | |
693 | private final static int CUBE = 37; | |
694 | private final static int MAYDOUBLE = 38; | |
695 | // private final static int WASDOUBLED = 40; | |
696 | private final static int XO = 41; | |
697 | private final static int DIRECTION = 42; | |
698 | private final static int ONHOME = 45; | |
699 | private final static int ONBAR = 47; | |
700 | private final static int CANMOVE = 49; | |
701 | ||
702 | /** Parse the board state from Fibs. | |
703 | * Opening board looks like this:<br> | |
704 | * board:You:someplayer:3:0:0:0:-2:0:0:0:0:5:0:3:0:0:0:-5:5:0:0:0:-3:0:-5:0:0:0:0:2:0:1:6:2:0:0:1:1:1:0:1:-1:0:25:0:0:0:0:2:0:0:0 | |
705 | * @param s The board | |
706 | * @see <a href="http://www.fibs.com/fibs_interface.html#board_state" target="_top">FIBS Client Protocol Detailed Specification</a> | |
707 | * <pre> | |
708 | * 0 1 2 3 4 5 | |
709 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 | |
710 | * board:You:someplayer:3:0:0:0:-2:0:0:0:0:5:0:3:0:0:0:-5:5:0:0:0:-3:0:-5:0:0:0:0:2:0:1:6:2:0:0:1:1:1:0:1:-1:0:25:0:0:0:0:2:0:0:0 | |
711 | * </pre> | |
712 | */ | |
713 | public void parseFibsBoard(String s) { | |
714 | int i; | |
715 | 48 | String[] t = s.split(":"); |
716 | 48 | xo = Integer.parseInt(t[XO]); |
717 | 48 | direction = Integer.parseInt(t[DIRECTION]); |
718 | 48 | playerName[0] = t[YOU]; |
719 | 48 | playerName[1] = t[SOMEPLAYER]; |
720 | 48 | matchLength = Integer.parseInt(t[MATCHLENGTH]); |
721 | 48 | matchScore[0] = Integer.parseInt(t[CURRENTSCORES+0]); |
722 | 48 | matchScore[1] = Integer.parseInt(t[CURRENTSCORES+1]); |
723 | 1200 | for (i=1; i<=24; i++) { |
724 | 1152 | this.points[i] = Integer.parseInt(t[BOARD+i]) * -xo; |
725 | } | |
726 | 48 | this.whosTurn = Integer.parseInt(t[TURN]); |
727 | 48 | setDice(dice[O], Integer.parseInt(t[DICE+0]), Integer.parseInt(t[DICE+1])); |
728 | 48 | setDice(dice[X], Integer.parseInt(t[DICE+2]), Integer.parseInt(t[DICE+3])); |
729 | 48 | cube = Integer.parseInt(t[CUBE]); |
730 | 48 | mayDouble[0] = Integer.parseInt(t[MAYDOUBLE+0]); |
731 | 48 | mayDouble[1] = Integer.parseInt(t[MAYDOUBLE+1]); |
732 | // wasDoubled[1] = t[WASDOUBLED].equals("1") ? true : false; | |
733 | if (DEBUG) | |
734 | System.out.println("mayDouble[" + mayDouble[0] + "][" + mayDouble[1] + "]"); | |
735 | 48 | if (mayDouble[0] == mayDouble[1]) |
736 | 41 | hasCube = -1; |
737 | 7 | else if (mayDouble[0] == 1) |
738 | 6 | hasCube = X; |
739 | 1 | else if (mayDouble[1] == 1) |
740 | 1 | hasCube = O; |
741 | 48 | home[O] = Integer.parseInt(t[ONHOME+0]); |
742 | 48 | home[X] = Integer.parseInt(t[ONHOME+1]); |
743 | 48 | bar[O] = Integer.parseInt(t[ONBAR+0]); |
744 | 48 | bar[X] = Integer.parseInt(t[ONBAR+1]); |
745 | 48 | canMove = Integer.parseInt(t[CANMOVE]); |
746 | if (DEBUG) | |
747 | System.out.println("xo=" + xo + " direction=" + direction + " canMove=" + canMove | |
748 | + " wasDoubled[1]=" + wasDoubled[1] + " turn=" + this.whosTurn); | |
749 | 48 | } |
750 | ||
751 | /** Parse a board for debug analysis. | |
752 | * Basically this includes points[0] and points[25] which we usually ignore. | |
753 | * @param s The board string | |
754 | * @param debugMode If true then actually parse. | |
755 | */ | |
756 | public void parseFibsBoard(String s, boolean debugMode) { | |
757 | 0 | if (debugMode) { |
758 | 0 | parseFibsBoard(s); |
759 | 0 | String[] t = s.split(":"); |
760 | 0 | this.points[0] = Integer.parseInt(t[BOARD]); |
761 | 0 | this.points[25] = Integer.parseInt(t[BOARD+25]); |
762 | } | |
763 | 0 | } |
764 | ||
765 | /** Sort the dice and set them in the player's dice array | |
766 | * @param d The dice array to store in. | |
767 | * @param d0 value of die 0 | |
768 | * @param d1 value of die 1 | |
769 | */ | |
770 | private void setDice(int[]d, int d0, int d1) { | |
771 | 96 | d[0] = d0; |
772 | 96 | d[1] = d1; |
773 | 96 | if (sortDice && d1 > d0) { |
774 | 5 | d[0] = d1; |
775 | 5 | d[1] = d0; |
776 | } | |
777 | 96 | } |
778 | ||
779 | } |