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 public class Board implements Cloneable { 231 private final static boolean DEBUG = false; 232 233 private int canMove; 234 235 236 private int xo; 237 private int matchLength = 0; 238 private int matchScore[] = new int[2]; 239 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 private int[][] dice = new int[2][2]; 242 private int direction; 243 private String[] playerName = new String[2]; 244 private int[] points = new int[26]; // 0 and 25 are unused. See bar 245 private int[] bar = new int[2]; 246 private int[] home = new int [2]; 247 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 return (xo == Board.X ? Board.turnX : Board.turnO); 271 } 272 273 274 private int whosTurn = 0; 275 private int cube = 1; 276 277 private boolean sortDice = true; 278 279 /** Who has the doubling cube?<br> 280 * -1 = noone, X = X, O = O */ 281 private int hasCube = 0; 282 private int[] mayDouble = new int[2]; 283 private boolean[] wasDoubled = new boolean[2]; 284 285 286 /* "External" attributes. That is, not derived by parseBoard */ 287 288 private boolean yourTurnToRollOrDouble = false; 289 private boolean acceptDeclineResign = false; 290 private int whoIsResigning = -1; 291 private int resigningPoints = -1; 292 293 /** Create an empty board */ 294 public Board() { } 295 296 /** Clone this board 297 * @return A new copy of this board. 298 */ 299 public Board clone() { 300 Board b = new Board(); 301 b.xo = this.xo; 302 b.matchLength = this.matchLength; 303 b.matchScore[0] = this.matchScore[0]; 304 b.matchScore[1] = this.matchScore[1]; 305 b.dice[0][0] = this.dice[0][0]; 306 b.dice[0][1] = this.dice[0][1]; 307 b.dice[1][0] = this.dice[1][0]; 308 b.dice[1][1] = this.dice[1][1]; 309 b.direction = this.direction; 310 b.playerName[0] = this.playerName[0]; 311 b.playerName[1] = this.playerName[1]; 312 for (int i=0; i<26; i++) 313 b.points[i] = this.points[i]; 314 b.bar[0] = this.bar[0]; 315 b.bar[1] = this.bar[1]; 316 b.home[0] = this.home[0]; 317 b.home[1] = this.home[1]; 318 b.whosTurn = this.whosTurn; 319 b.cube = this.cube; 320 b.sortDice = this.sortDice; 321 b.hasCube = this.hasCube; 322 b.mayDouble[0] = this.mayDouble[0]; 323 b.mayDouble[1] = this.mayDouble[1]; 324 b.wasDoubled[0] = this.wasDoubled[0]; 325 b.wasDoubled[1] = this.wasDoubled[1]; 326 b.yourTurnToRollOrDouble = this.yourTurnToRollOrDouble; 327 b.acceptDeclineResign = this.acceptDeclineResign; 328 b.whoIsResigning = this.whoIsResigning; 329 b.resigningPoints = this.resigningPoints; 330 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 this.sortDice = sortDice; 338 if (sortDice) { 339 if (this.dice[0][0] < this.dice[0][1]) { 340 int x = dice[0][0]; 341 dice[0][0] = dice[0][1]; 342 dice[0][1] = x; 343 } 344 if (this.dice[1][0] < this.dice[1][1]) { 345 int x = dice[1][0]; 346 dice[1][0] = dice[1][1]; 347 dice[1][1] = x; 348 } 349 } 350 } 351 352 /** Is it your turn? 353 * @return the yourTurnToRollOrDouble 354 */ 355 public boolean isYourTurnToRollOrDouble() { 356 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 this.yourTurnToRollOrDouble = yourTurnToRollOrDouble; 364 } 365 366 /** We have been doubled and need to accept or decline 367 */ 368 public void setAcceptDeclineDouble() { 369 this.getWasDoubled()[1] = true; 370 } 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 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 return(this.acceptDeclineResign); 384 } 385 386 public void setAcceptDeclineResign(boolean enabled) { 387 this.acceptDeclineResign = enabled; 388 } 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 this.whoIsResigning = xo; 395 } 396 397 public int getWhoIsResigning() { 398 return(this.whoIsResigning); 399 } 400 401 public void setResigningPoints(int resigningPoints) { 402 this.resigningPoints = resigningPoints; 403 } 404 405 public int getResigningPoints() { 406 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 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 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 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 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 wasDoubled[Board.O] = false; 443 wasDoubled[Board.X] = false; 444 if (xo == Board.O) 445 wasDoubled[Board.O] = true; 446 if (xo == Board.X) 447 wasDoubled[Board.X] = true; 448 } 449 450 /** Are You allowed to double? 451 * @return true is yes. 452 */ 453 public boolean isYouMayDouble() { 454 return (this.mayDouble[Board.O] == 1); 455 } 456 457 public boolean isOpponentMayDouble() { 458 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 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 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 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 this.playerName[which] = name; 488 } 489 490 /** Get the number of points in the match 491 * @return The matchLength 492 */ 493 public int getMatchLength() { 494 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 return(matchScore); 502 } 503 504 /** Place all checkers on their start positions 505 */ 506 public void setStartPositions() { 507 this.parseFibsBoard(initialPositions); 508 } 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 return(xo); 515 } 516 517 /** Get XO as text. Just a devel function 518 * @return "O" or "X" 519 */ 520 public String getXOAsText() { 521 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 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 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 this.dice[0][0] = 0; 543 this.dice[0][1] = 0; 544 } 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 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 if (name.equals(playerName[Board.X])) 559 return(Board.X); 560 else if (name.equals(playerName[Board.O])) 561 return(Board.O); 562 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 if (name.equals(playerName[Board.O])) 571 return(direction); 572 return(-direction); 573 } 574 575 /** Get the number displayed on the double cube 576 * @return the cube 577 */ 578 public int getCube() { 579 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 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 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 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 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 String[] ss = score.split("\\-"); 618 int s0 = Integer.parseInt(ss[0]); 619 int s1 = Integer.parseInt(ss[1]); 620 if (winner.equals("You") || winner.equals(this.playerName[0])) { 621 matchScore[0] = s0; 622 matchScore[1] = s1; 623 } else { 624 matchScore[0] = s1; 625 matchScore[1] = s0; 626 } 627 whosTurn = 0; 628 } 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 this.pipCount[O] = 0; 637 this.pipCount[X] = 0; 638 for (i=1; i<=24; i++) { 639 if (this.points[i] < 0) 640 pipCount[O] += ((this.getDirection() == -1 ? i : (25 - i)) * -this.points[i]); 641 else if (this.points[i] > 0) 642 pipCount[X] += ((this.getDirection() == 1 ? i : (25 - i)) * this.points[i]); 643 } 644 pipCount[O] += (bar[O]*25); 645 pipCount[X] += (bar[X]*25); 646 647 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 int k = 0; 657 if (bar[O] > 0 || bar[X] > 0) 658 return(false); 659 boolean oppositeSeen = false; 660 for (i=1; i<=24; i++) { 661 if (this.points[i] == 0) 662 continue; 663 if (k == 0) { 664 k = this.points[i]; 665 continue; 666 } 667 if (!oppositeSeen) { 668 if (k < 0 && this.points[i] > 0) { 669 oppositeSeen = true; 670 continue; 671 } 672 if (k > 0 && this.points[i] < 0) { 673 oppositeSeen = true; 674 continue; 675 } 676 } else { 677 if (k < 0 && this.points[i] < 0) 678 return(false); 679 if (k > 0 && this.points[i] > 0) 680 return(false); 681 } 682 } 683 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 String[] t = s.split(":"); 716 xo = Integer.parseInt(t[XO]); 717 direction = Integer.parseInt(t[DIRECTION]); 718 playerName[0] = t[YOU]; 719 playerName[1] = t[SOMEPLAYER]; 720 matchLength = Integer.parseInt(t[MATCHLENGTH]); 721 matchScore[0] = Integer.parseInt(t[CURRENTSCORES+0]); 722 matchScore[1] = Integer.parseInt(t[CURRENTSCORES+1]); 723 for (i=1; i<=24; i++) { 724 this.points[i] = Integer.parseInt(t[BOARD+i]) * -xo; 725 } 726 this.whosTurn = Integer.parseInt(t[TURN]); 727 setDice(dice[O], Integer.parseInt(t[DICE+0]), Integer.parseInt(t[DICE+1])); 728 setDice(dice[X], Integer.parseInt(t[DICE+2]), Integer.parseInt(t[DICE+3])); 729 cube = Integer.parseInt(t[CUBE]); 730 mayDouble[0] = Integer.parseInt(t[MAYDOUBLE+0]); 731 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 if (mayDouble[0] == mayDouble[1]) 736 hasCube = -1; 737 else if (mayDouble[0] == 1) 738 hasCube = X; 739 else if (mayDouble[1] == 1) 740 hasCube = O; 741 home[O] = Integer.parseInt(t[ONHOME+0]); 742 home[X] = Integer.parseInt(t[ONHOME+1]); 743 bar[O] = Integer.parseInt(t[ONBAR+0]); 744 bar[X] = Integer.parseInt(t[ONBAR+1]); 745 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 } 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 if (debugMode) { 758 parseFibsBoard(s); 759 String[] t = s.split(":"); 760 this.points[0] = Integer.parseInt(t[BOARD]); 761 this.points[25] = Integer.parseInt(t[BOARD+25]); 762 } 763 } 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 d[0] = d0; 772 d[1] = d1; 773 if (sortDice && d1 > d0) { 774 d[0] = d1; 775 d[1] = d0; 776 } 777 } 778 779 }