Coverage Report - com.buckosoft.fibs.domain.Board
 
Classes in this File Line Coverage Branch Coverage Complexity
Board
90%
185/204
77%
68/88
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  
 }