Coverage Report - com.buckosoft.fibs.BuckoFIBS.gui.boardTab.boardPane.BoardPane
 
Classes in this File Line Coverage Branch Coverage Complexity
BoardPane
0%
0/560
0%
0/254
5.419
BoardPane$1
0%
0/3
N/A
5.419
BoardPane$2
0%
0/3
N/A
5.419
BoardPane$BoardSpecs
0%
0/1
N/A
5.419
 
 1  
 /******************************************************************************
 2  
  * BoardPane.java - Draw 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.9  2013/09/12 06:42:28  dick
 10  
  * Animating the double cube.
 11  
  *
 12  
  * Revision 1.8  2013/09/10 00:21:58  dick
 13  
  * Javadoc and debug
 14  
  *
 15  
  * Revision 1.7  2011/07/04 03:44:35  dick
 16  
  * Add FirstRoll handling.
 17  
  *
 18  
  * Revision 1.6  2011/06/19 04:14:09  dick
 19  
  * Send the board to the MatchStatusPanel as well.
 20  
  *
 21  
  * Revision 1.5  2011/06/18 19:34:09  dick
 22  
  * Always draw red dice on CantMove.  Who cares whose dice they are.
 23  
  * Push our resign flag a little onto his board.
 24  
  *
 25  
  * Revision 1.4  2011/06/05 06:56:05  dick
 26  
  * Draw the AcceptAndWin animation.
 27  
  *
 28  
  * Revision 1.3  2011/06/02 19:18:30  dick
 29  
  * Deal with painting resign.
 30  
  *
 31  
  * Revision 1.2  2011/05/31 19:38:56  dick
 32  
  * Use the AnimateEventDiceRoll constants, instead of hard coded numbers.
 33  
  *
 34  
  * Revision 1.1  2011/05/22 22:56:08  dick
 35  
  * c.b.f.B.g.boardTab.board becomes c.b.f.B.g.boardTab.boardPane .
 36  
  *
 37  
  * Revision 1.8  2011/05/22 05:24:07  dick
 38  
  * diceUsed is always false during a DiceRoll animation.
 39  
  *
 40  
  * Revision 1.7  2011/05/21 05:03:02  dick
 41  
  * Doubling functions are in the Board, not the Document.
 42  
  * BoardPane only care about Board.
 43  
  *
 44  
  * Revision 1.6  2011/05/17 22:50:04  dick
 45  
  * AnimateEvent moves to c.b.f.B.g.b.b which is where it is used.
 46  
  *
 47  
  * Revision 1.5  2011/05/16 21:25:56  dick
 48  
  * Handle Home and Bar during Move.
 49  
  *
 50  
  * Revision 1.4  2011/05/16 14:18:41  dick
 51  
  * Draw the CantMove event.
 52  
  *
 53  
  * Revision 1.3  2011/05/16 11:40:03  dick
 54  
  * Painting animated dice rolls.
 55  
  * More work on painting moving checkers.
 56  
  *
 57  
  * Revision 1.2  2011/05/15 04:38:03  dick
 58  
  * Still draw the animation's extraCheckers even if there is no open event.
 59  
  *
 60  
  * Revision 1.1  2011/05/15 02:17:54  dick
 61  
  * Move the AnimateEvents to their own package.
 62  
  *
 63  
  * Revision 1.11  2011/05/14 05:19:31  dick
 64  
  * Still need work on the doubles handling for board/document split.
 65  
  *
 66  
  * Revision 1.10  2011/05/14 04:43:01  dick
 67  
  * I needed to deal with some lightweight Boards.
 68  
  * So finally make the primary document Document
 69  
  * and demote just the Board handling to a domain object.
 70  
  *
 71  
  * Revision 1.9  2011/05/13 18:26:22  dick
 72  
  * Debugging animation.
 73  
  *
 74  
  * Revision 1.8  2011/05/13 14:56:15  dick
 75  
  * Add support for animating checkers on the board.
 76  
  *
 77  
  * Revision 1.7  2011/05/11 22:22:04  dick
 78  
  * Working on animating checkers.
 79  
  *
 80  
  * Revision 1.6  2011/01/04 20:05:26  dick
 81  
  * If there are 3 columns of checkers on a point, draw the point number in the correct y coordinate.
 82  
  *
 83  
  * Revision 1.5  2011/01/01 06:11:14  dick
 84  
  * Javadoc.
 85  
  *
 86  
  * Revision 1.4  2010/12/29 07:50:05  dick
 87  
  * Display the dice in grey as they are used up.
 88  
  *
 89  
  * Revision 1.3  2010/03/03 13:12:21  inim
 90  
  * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8
 91  
  *
 92  
  * Revision 1.2  2010/03/03 12:19:49  inim
 93  
  * 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.
 94  
  *
 95  
  * Revision 1.1  2010/02/04 05:57:53  inim
 96  
  * Mavenized project folder layout
 97  
  *
 98  
  * Revision 1.6  2009/02/14 15:19:12  dick
 99  
  * BuckoFIBS is released under the GNU license.
 100  
  *
 101  
  * Revision 1.5  2009/02/12 06:28:03  dick
 102  
  * Add hoverTo home.
 103  
  *
 104  
  * Revision 1.4  2009/02/06 07:56:49  dick
 105  
  * Working on doubles.
 106  
  *
 107  
  * Revision 1.3  2009/02/05 06:01:43  dick
 108  
  * Draw the double cube being pushed.
 109  
  * Draw the minidice.
 110  
  *
 111  
  * Revision 1.2  2009/01/31 06:06:55  dick
 112  
  * If there are 6 or more checkers on a point, then draw the point number centered on #6.
 113  
  *
 114  
  * Revision 1.1  2009/01/28 19:37:28  dick
 115  
  * package com.buckosoft.fibs.gui.board becomes com.buckosoft.fibs.BuckoFIBS.gui.board.
 116  
  *
 117  
  * Revision 1.25  2009/01/28 08:32:49  dick
 118  
  * Turn off DEBUG.
 119  
  *
 120  
  * Revision 1.24  2009/01/27 05:45:39  dick
 121  
  * Hover off of the bar.
 122  
  *
 123  
  * Revision 1.23  2009/01/26 06:07:34  dick
 124  
  * I believe checkers always draw in their correct colors now.
 125  
  *
 126  
  * Revision 1.22  2009/01/24 17:08:36  dick
 127  
  * Wrassle with drawing the right colored pieces in the right places.
 128  
  *
 129  
  * Revision 1.21  2009/01/22 05:04:49  dick
 130  
  * More moving checkers on the board.  There are issues with playing 1-24 vs. 24-1.
 131  
  *
 132  
  * Revision 1.20  2009/01/20 07:42:52  dick
 133  
  * Add hover colors and checkers.
 134  
  *
 135  
  * Revision 1.19  2009/01/18 05:06:08  dick
 136  
  * mouse event handling.
 137  
  * Add paintPointNumbers
 138  
  * Make some methods/attributes protected so that BoardGui can get at them.
 139  
  *
 140  
  * Revision 1.18  2009/01/10 05:06:15  dick
 141  
  * Fix the color of the dice, the position of the cube, and tweak the position of the bar.
 142  
  *
 143  
  * Revision 1.17  2009/01/08 18:47:02  dick
 144  
  * Assign a dummy board.
 145  
  *
 146  
  * Revision 1.16  2009/01/08 01:34:00  dick
 147  
  * Javadoc.
 148  
  *
 149  
  * Revision 1.15  2009/01/07 04:30:06  dick
 150  
  * Javadoc.
 151  
  *
 152  
  * Revision 1.14  2008/12/20 23:02:40  dick
 153  
  * Dice, checkers on bar, and double cube.
 154  
  *
 155  
  * Revision 1.13  2008/12/16 20:08:13  dick
 156  
  * Start painting on the bar.
 157  
  *
 158  
  * Revision 1.12  2008/12/12 23:24:43  dick
 159  
  * Switch around the colors of the dice and checkers.
 160  
  *
 161  
  * Revision 1.11  2008/12/12 14:45:51  dick
 162  
  * Update drawing to the new FIBS based board (based on points instead of checkers).
 163  
  *
 164  
  * Revision 1.10  2008/12/12 01:19:52  dick
 165  
  * Start reworking for a point based board,  not a checker based board.
 166  
  *
 167  
  * Revision 1.9  2008/12/11 09:57:25  dick
 168  
  * Javadoc.
 169  
  *
 170  
  * Revision 1.8  2008/12/10 23:46:59  dick
 171  
  * Drawing nice dice.
 172  
  *
 173  
  * Revision 1.7  2008/12/10 21:56:12  dick
 174  
  * Early dice drawing.
 175  
  *
 176  
  * Revision 1.6  2008/12/08 10:17:15  dick
 177  
  * Display the checkers on the board.
 178  
  *
 179  
  * Revision 1.5  2008/12/08 06:45:39  dick
 180  
  * Drawing checkers in the home position.
 181  
  *
 182  
  * Revision 1.4  2008/04/07 06:13:26  dick
 183  
  * Generalize calculating the board's points.
 184  
  *
 185  
  * Revision 1.3  2008/04/05 01:43:22  dick
 186  
  * Draw the points.
 187  
  */
 188  
 
 189  
 /* 
 190  
  * This program is free software: you can redistribute it and/or modify
 191  
  * it under the terms of the GNU General Public License as published by
 192  
  * the Free Software Foundation, either version 3 of the License, or
 193  
  * (at your option) any later version.
 194  
  *
 195  
  * This program is distributed in the hope that it will be useful,
 196  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 197  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 198  
  * GNU General Public License for more details.
 199  
  *
 200  
  * You should have received a copy of the GNU General Public License
 201  
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 202  
  *
 203  
  * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>.
 204  
  * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp.
 205  
  * 
 206  
  */
 207  
 package com.buckosoft.fibs.BuckoFIBS.gui.boardTab.boardPane;
 208  
 
 209  
 import java.awt.Color;
 210  
 import java.awt.Dimension;
 211  
 import java.awt.Font;
 212  
 import java.awt.FontMetrics;
 213  
 import java.awt.Graphics;
 214  
 import java.awt.Point;
 215  
 
 216  
 import javax.swing.JPanel;
 217  
 
 218  
 import org.slf4j.Logger;
 219  
 import org.slf4j.LoggerFactory;
 220  
 
 221  
 import com.buckosoft.fibs.BuckoFIBS.BFProperties;
 222  
 import com.buckosoft.fibs.BuckoFIBS.gui.boardTab.BoardTab;
 223  
 import com.buckosoft.fibs.BuckoFIBS.gui.boardTab.boardPane.AnimateEvent.Type;
 224  
 import com.buckosoft.fibs.domain.Board;
 225  
 
 226  
 /** Draw a backgammon board. <br>
 227  
  * checker width is a root.<br>
 228  
  * There are 16.5 checker widths in a board.<br>
 229  
  * 12 points<br>
 230  
  * 1.5 left side, right side, bar.<br>
 231  
  * ebeh, still need to make sure that 5 checkers will fit on a point.
 232  
  * @author Dick Balaska
 233  
  * @since 2008/04/01
 234  
  * @version $Revision$ <br> $Date$
 235  
  * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/gui/boardTab/BoardPane.java">cvs BoardPane.java</a>
 236  
  */
 237  
 public class BoardPane extends JPanel {
 238  
         private        final static boolean DEBUG = false;
 239  
         private        final static boolean DEBUGa = false;                // animate foo
 240  0
     private Logger logger = LoggerFactory.getLogger(getClass());
 241  
         private static final long serialVersionUID = 1L;
 242  
         
 243  
         
 244  
         // Assign a dummy board, just so Visual Editor will have something to draw.
 245  
         // This will get overwritten by the real board during runtime.
 246  0
         protected        Board                        board = new Board();  //  @jve:decl-index=0:
 247  
         //protected        Document                document;
 248  0
         private                BoardTab                boardTab = null;
 249  0
         protected        BFProperties        properties = null;
 250  
 
 251  
         /** Drawing dimensions and hints */
 252  0
         public                BoardSpecs bs = new BoardSpecs();  //  @jve:decl-index=0:
 253  
 
 254  0
         private        Color        boxColor = Color.darkGray;  //  @jve:decl-index=0:
 255  0
         private        Color        boardColor = Color.lightGray;  //  @jve:decl-index=0:
 256  0
         private        Color        bPointColor = Color.pink;  //  @jve:decl-index=0:
 257  0
         private        Color        wPointColor = Color.red;  //  @jve:decl-index=0:
 258  0
         private        Color        bCheckerColor = Color.black;
 259  0
         private        Color        bTrimColor = Color.white;
 260  0
         private        Color        wCheckerColor = Color.white;
 261  0
         private Color        wGreyColor = Color.gray;
 262  0
         private        Color        wTrimColor = Color.black;
 263  
         
 264  
 //        private        Color        hoverColor = Color.lightGray;
 265  0
         private        Color        hoverColor = new Color(200,200,200,192);
 266  
 //        private        Color        hoverToColor = Color.yellow;
 267  0
         private        Color        hoverToColor = new Color(255,255,0,150);
 268  
         
 269  
         protected static final int POINT_UNKNOWN = -1;
 270  
         protected static final int POINT_BAR = -2;
 271  
         protected static final int POINT_DICE = -3;
 272  
         protected static final int POINT_DOUBLE = -4;
 273  
         protected static final int POINT_BAR_DICE = -5;
 274  
         protected static final int POINT_REJECT = -6;
 275  
         
 276  
         
 277  
 
 278  0
         protected int        hoverPoint = POINT_UNKNOWN;
 279  
         
 280  
         /** 1-24 are any "shadow" checkers on a point */
 281  0
         protected int[] hoverTo = new int[26];
 282  
         
 283  
         /** Used for drawing the points */
 284  0
         private        int[] xPoints = new int[4];
 285  
         /** Used for drawing the points */
 286  0
         private int[] yPoints = new int[4];
 287  
 
 288  0
         protected boolean[] diceUsed = new boolean[2];
 289  
         
 290  
         protected        AnimateManager        animateManager;
 291  
         
 292  
         /** Default/only constructor */
 293  
         public BoardPane() {
 294  0
                 super();
 295  0
                 initialize();                
 296  0
                 this.animateManager = new AnimateManager();
 297  0
                 this.animateManager.setBoardPane(this);
 298  0
                 this.animateManager.setProperties(properties);
 299  0
         }
 300  
 
 301  
         /** Precalculate the dimensions of a board for drawing
 302  
          * @author Dick Balaska
 303  
          * @since 2008/04/01
 304  
          * @version $Revision$ <br> $Date$
 305  
          * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/gui/board/BoardPane.java">cvs BoardPane.java</a>
 306  
          */
 307  0
         public class BoardSpecs {
 308  
                 /** Width of the board */
 309  
                 public int        w;
 310  
                 /** Height of the board */
 311  
                 public int        h;
 312  
                 /** diameter of a checker */
 313  
                 public int        checkerSize;
 314  
                 /** checkerSize * 1.5 */
 315  
                 public int c15;
 316  
                 /** checkerSize / 2 */
 317  
                 public int        c2;
 318  
                 /** checkerSize / 3 for in home */
 319  
                 public int checkerHeight;
 320  
                 public int dieSize;
 321  
                 public int extra;
 322  
                 public int barWidth;
 323  
                 /** How tall is the point */
 324  
                 public int        pointHeight;
 325  
 //                public Color        cColor;
 326  
 //                public Color        tColor;
 327  
         }
 328  
         
 329  
         /** Set the reference to the backgammon board.
 330  
          * @param board the board to set
 331  
          */
 332  
         public void setBoard(Board board) {
 333  0
                 this.board = board;
 334  0
                 this.boardTab.setMatchStatusPanelBoard(board);
 335  0
         }
 336  
 
 337  
         public void setBoardTab(BoardTab boardTab) {
 338  0
                 this.boardTab = boardTab;
 339  0
         }
 340  
 
 341  
 
 342  
         /** This method initializes this
 343  
          * @return void
 344  
          */
 345  
         private void initialize() {
 346  0
                 this.setSize(400, 300);
 347  0
                 this.setPreferredSize(new Dimension(400, 300));
 348  0
                 this.addMouseListener(new java.awt.event.MouseAdapter() {   
 349  
                         public void mousePressed(java.awt.event.MouseEvent e) {    
 350  0
                                 onMousePressed(e);
 351  0
                         }
 352  
                 });
 353  0
                 this.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
 354  
                         public void mouseMoved(java.awt.event.MouseEvent e) {
 355  0
                                 onMouseMoved(e);
 356  0
                         }
 357  
                 });
 358  0
         }
 359  
 
 360  
         protected void setHoverPoint(int p) {
 361  
                 if (DEBUG)
 362  
                         System.out.println("setHoverPoint(" + p + ")");
 363  0
                 hoverPoint = p;
 364  
                 int i;
 365  0
                 for (i=0; i<hoverTo.length; i++)
 366  0
                         hoverTo[i] = 0;
 367  0
         }
 368  
 
 369  
         protected void onMouseClicked(java.awt.event.MouseEvent e) {
 370  0
                 System.out.println("onMouseClicked: Should be overridden");
 371  0
         }
 372  
 
 373  
         protected void onMousePressed(java.awt.event.MouseEvent e) {
 374  0
                 System.out.println("onMousePressed: Should be overridden");
 375  0
         }
 376  
 
 377  
         protected void onMouseMoved(java.awt.event.MouseEvent e) {
 378  0
                 System.out.println("onMouseMoved: Should be overridden");
 379  0
         }
 380  
 
 381  
         /** Paint the entire backgammon board and all of it's pieces.
 382  
          * @param g The Graphics to use
 383  
          */
 384  
         public void paint(Graphics g) {
 385  0
                 super.paint(g);
 386  0
                 bs.w = this.getWidth();
 387  0
                 bs.h = this.getHeight();
 388  0
                 bs.checkerSize = (int)(((double)bs.w)/16.5);
 389  0
                 bs.c2 = bs.checkerSize / 2;
 390  0
                 bs.c15 = (int)((double)bs.checkerSize * 1.5);
 391  0
                 bs.checkerHeight = bs.checkerSize/3;
 392  0
                 bs.extra = bs.w-((bs.checkerSize*12)+(bs.c15*3));
 393  0
                 bs.barWidth = bs.checkerSize + bs.extra;
 394  0
                 bs.pointHeight = bs.h/2-bs.c15;                // XXX: make something up for now. This could be better.
 395  
 
 396  
                 // fill with the board color (shouldn't this be in "erase"?)
 397  0
                 g.setColor(boardColor);
 398  0
                 g.fillRect(0, 0, bs.w, bs.h);
 399  
         
 400  
                 // draw left end
 401  0
                 g.setColor(boxColor);
 402  0
                 g.fillRect(0, 0, bs.c15, bs.h);
 403  
                 // draw right end
 404  0
                 g.fillRect(bs.w-bs.c15, 0, bs.w, bs.h);
 405  
                 // draw bar
 406  0
                 g.fillRect(bs.w/2-bs.barWidth/2, 0, bs.barWidth, bs.h);
 407  
                 int x, y, w;
 408  0
                 y = bs.pointHeight;
 409  
                 int p;
 410  0
                 for (p=1; p<=12; p++) {                // points 1-12
 411  0
                         x = getPointX(p);
 412  0
                         if ((p & 1) != 0)
 413  0
                                 g.setColor(wPointColor);
 414  
                         else
 415  0
                                 g.setColor(bPointColor);
 416  0
                         xPoints[0] = x;
 417  0
                         yPoints[0] = bs.h;
 418  0
                         xPoints[1] = x+bs.c2;
 419  0
                         yPoints[1] = bs.h-y;
 420  0
                         xPoints[2] = x+bs.checkerSize;
 421  0
                         yPoints[2] = bs.h;
 422  0
                         xPoints[3] = x;
 423  0
                         yPoints[3] = bs.h;
 424  0
                         g.fillPolygon(xPoints, yPoints, 4);
 425  0
                         g.setColor(Color.black);
 426  0
                         g.drawLine(x, bs.h, x+bs.c2, bs.h-y);
 427  0
                         g.drawLine(x+bs.c2, bs.h-y, x+bs.checkerSize, bs.h);
 428  
                 }
 429  0
                 for (p=13; p<=24; p++) {
 430  0
                         x = getPointX(p);
 431  0
                         if ((p & 1) == 1)
 432  0
                                 g.setColor(wPointColor);
 433  
                         else
 434  0
                                 g.setColor(bPointColor);
 435  0
                         xPoints[0] = x;
 436  0
                         yPoints[0] = 0;
 437  0
                         xPoints[1] = x+bs.c2;
 438  0
                         yPoints[1] = y;
 439  0
                         xPoints[2] = x+bs.checkerSize;
 440  0
                         yPoints[2] = 0;
 441  0
                         xPoints[3] = x;
 442  0
                         yPoints[3] = 0;
 443  0
                         g.fillPolygon(xPoints, yPoints, 4);
 444  0
                         g.setColor(Color.black);
 445  0
                         g.drawLine(x, 0, x+bs.c2, y);
 446  0
                         g.drawLine(x+bs.c2, y, x+bs.checkerSize, 0);
 447  
                 }
 448  0
                 paintCheckers(g);
 449  0
                 paintDice(g);
 450  0
                 paintDoubleCube(g);
 451  0
                 paintPointNumbers(g);
 452  0
                 if (this.board.isYourTurnToRollOrDouble()) {
 453  0
                         int miniDieSize = bs.barWidth/2;
 454  0
                         x = bs.w/2-bs.barWidth/2;
 455  0
                         y = bs.h-miniDieSize-2;
 456  0
                         paintDie(g, miniDieSize, x, y, 6, Color.white, Color.white, Color.black);
 457  0
                         paintDie(g, miniDieSize, x+miniDieSize, y, 6, Color.white, Color.white, Color.black);
 458  0
                         g.setColor(Color.yellow);
 459  0
                         g.drawRoundRect(x-2, y-2, miniDieSize*2+2, miniDieSize+2, miniDieSize/4+2, miniDieSize/4+2);
 460  0
                         g.drawRoundRect(x-1, y-1, miniDieSize*2+1, miniDieSize+1, miniDieSize/4+1, miniDieSize/4+1);
 461  
                         
 462  
                 }
 463  0
                 if (board.isAcceptDeclineDouble() || board.isAcceptDeclineResign()) {
 464  0
                         g.setColor(Color.red);
 465  0
                         x = getDeclineX();
 466  0
                         y = getDeclineY();
 467  0
                         w = bs.c15;
 468  0
                         g.drawLine(x, y, x+w, y+w);
 469  0
                         g.drawLine(x+w, y, x, y+w);
 470  0
                         g.drawLine(x+1, y, x+w+1, y+w);
 471  0
                         g.drawLine(x+w+1, y, x+1, y+w);
 472  
 
 473  
                 }
 474  0
                 paintResign(g);
 475  0
                 paintAnimatedCheckers(g);
 476  0
         }
 477  
 
 478  
         protected        int        getDeclineX() {
 479  0
                 return(bs.w-bs.c15);
 480  
         }
 481  
         protected        int        getDeclineY() {
 482  0
                 return(bs.h/2 - bs.c15/2);
 483  
         }
 484  
         private void paintCheckers(Graphics g) {
 485  0
                 int[] p = this.board.getPoints();
 486  
                 int i;
 487  
                 int j;
 488  
                 int c;
 489  0
                 if (p == null)
 490  0
                         return;
 491  
                 if (DEBUG)
 492  
                         System.out.println("xo=" + board.getXO() + " dir=" + board.getDirection());
 493  0
                 for (i=1; i<=24; i++) {
 494  0
                         c = Math.abs(p[i]);
 495  0
                         if (c == 0 && hoverTo[i] == 0)
 496  0
                                 continue;
 497  0
                         Color cColor = bCheckerColor;
 498  0
                         Color tColor = bTrimColor;
 499  
                         //if (p[i]*board.getXO() > 0) {
 500  0
                         if (p[i] < 0) {
 501  
                                 if (DEBUG)
 502  
                                         System.out.println("p[" + i + "]=" + p[i]);
 503  0
                                 cColor = wCheckerColor;
 504  0
                                 tColor = wTrimColor;
 505  
                         }
 506  0
                         int x = getPointX(i);
 507  0
                         for (j=0; j<c+hoverTo[i]; j++) {
 508  0
                                 int y = getNthCheckerY(i, j);
 509  0
                                 if (i == hoverPoint && j == c-1) 
 510  0
                                         cColor = hoverColor;
 511  0
                                 if (j>=c)
 512  0
                                         cColor = hoverToColor;
 513  0
                                 g.setColor(cColor);
 514  0
                                 g.fillArc(x, y, bs.checkerSize, bs.checkerSize, 0, 360);
 515  0
                                 g.setColor(tColor);
 516  0
                                 g.drawArc(x, y, bs.checkerSize, bs.checkerSize, 0, 360);
 517  
                         }
 518  
                 }
 519  0
                 p = this.board.getHome();
 520  0
                 for (j=0; j<p[1]; j++)
 521  0
                         paintCheckerInHome(g, Board.X, j, bCheckerColor, bTrimColor);
 522  0
                 for (j=0; j<p[0]; j++)
 523  0
                         paintCheckerInHome(g, Board.O, j, wCheckerColor, wTrimColor);
 524  0
                 if (hoverTo[0] > 0)
 525  0
                         paintCheckerInHome(g, Board.O, j, hoverToColor, wTrimColor);
 526  0
                 int[] bar = board.getBar();
 527  0
                 for (j=0; j<bar[Board.O]; j++)
 528  0
                         paintCheckerOnBar(g, Board.O, j, wCheckerColor, wTrimColor);
 529  0
                 for (j=0; j<bar[Board.X]; j++)
 530  0
                         paintCheckerOnBar(g, Board.X,  j, bCheckerColor, bTrimColor);
 531  0
         }
 532  
 
 533  
         protected int getCheckerYOnBar(int who, int checker) {
 534  0
                 int y = bs.h/2 + bs.checkerSize + ((checker % 5) * bs.checkerSize);
 535  0
                 y -= (checker/5*bs.checkerHeight);
 536  0
                 if (who == Board.O)
 537  0
                         y = bs.h - bs.checkerSize -y;
 538  
                 
 539  0
                 return(y);
 540  
         }
 541  
 
 542  
         private void paintCheckerOnBar(Graphics g, 
 543  
                         int who, int c, Color cColor, Color tColor) {
 544  0
                 if (hoverPoint == POINT_BAR && c == 0)
 545  0
                         cColor = hoverColor;
 546  0
                 int x = bs.w/2 - bs.checkerSize/2;
 547  0
                 int y = getCheckerYOnBar(who, c);
 548  0
                 g.setColor(cColor);
 549  0
                 g.fillArc(x, y, bs.checkerSize, bs.checkerSize, 0, 360);
 550  0
                 g.setColor(tColor);
 551  0
                 g.drawArc(x, y, bs.checkerSize, bs.checkerSize, 0, 360);
 552  0
         }
 553  
 
 554  
         protected int        getCheckerYInHome(int who, int checker) {
 555  
                 int y;
 556  0
                 y = checker * bs.checkerHeight;
 557  0
                 if (who == Board.O)
 558  0
                         y = bs.h - (checker+1) * bs.checkerHeight;
 559  0
                 return(y);
 560  
         }
 561  
 
 562  
         private void paintCheckerInHome(Graphics g, 
 563  
                         int who, int checker, Color cColor, Color tColor) {
 564  0
                 int x = bs.w-(bs.c15/2)-(bs.checkerSize/2);
 565  0
                 int y = getCheckerYInHome(who, checker);
 566  0
                 g.setColor(cColor);
 567  0
                 g.fillArc(x, y, bs.checkerSize, bs.checkerHeight, 0, 180);
 568  0
                 g.setColor(tColor);
 569  0
                 g.drawArc(x, y, bs.checkerSize, bs.checkerHeight, 0, 180);
 570  0
         }
 571  
 
 572  
         /** Return the left side of a point
 573  
          * @param p The point to calculate
 574  
          * @return The x of the left side of the triangle
 575  
          */
 576  
         protected int        getPointX(int p) {
 577  0
                 if (p == Board.Bar)
 578  0
                         return(bs.w/2-bs.c2);
 579  0
                 if (p == Board.Home)
 580  0
                         return(bs.w-(bs.c15/2)-(bs.checkerSize/2));
 581  
 
 582  0
                 if (p > 12)
 583  0
                         p = 25 - p;
 584  0
                 p--;
 585  0
                 int x = (bs.w - bs.c15 - bs.checkerSize) - ((bs.checkerSize+1)*p) - 2;
 586  0
                 if (p > 5)
 587  0
                         x -= bs.barWidth + 2;
 588  0
                 return(x);
 589  
         }
 590  
 
 591  
         /** Calculate the y for a checker
 592  
          * @param p The point to calculate
 593  
          * @param c The checker number on the point.  There can be between 1-15 checkers sitting on a point.
 594  
          *                     (If there's 0, then there's no point of drawing).
 595  
          *                        This number is 0 based.
 596  
          * @return The y value to draw the checker at.
 597  
          */
 598  
         protected int getNthCheckerY(int p, int c) {
 599  0
                 if (board.getDirection() > 0)
 600  0
                         p = 25-p;
 601  0
                 int y = (c % 5) * bs.checkerSize;
 602  0
                 y += (c/5*bs.checkerHeight);
 603  0
                 if (p <= 12)
 604  0
                         y = bs.h - bs.checkerSize -y;
 605  0
                 return(y);
 606  
         }
 607  
 
 608  
         ///////////////////////////////////////////////////////////////////////////
 609  
         /** Paint the dice
 610  
          * @param g The Graphics we draw to
 611  
          */
 612  
         private void paintDice(Graphics g) {
 613  0
                 Color cColor = bCheckerColor;
 614  0
                 Color tColor = bTrimColor;
 615  0
                 Color gColor = wGreyColor;
 616  
 
 617  0
                 bs.dieSize = bs.checkerSize;
 618  0
                 int y = bs.h/2-bs.c2;
 619  0
                 int x0 = this.getPointX(9) - bs.c15;
 620  0
                 int x1 = x0+bs.c15;
 621  0
                 int size = bs.dieSize;
 622  0
                 int[][] dice = board.getDice();
 623  
 
 624  0
                 AnimateEvent ae = this.animateManager.getHeadEvent();
 625  0
                 if (ae != null) {
 626  0
                         if (ae.getType() == Type.Roll) {
 627  0
                                 AnimateEventDiceRoll aedr = (AnimateEventDiceRoll)ae;
 628  0
                                 for (int i=0; i<diceUsed.length; i++)
 629  0
                                         diceUsed[i] = false;
 630  0
                                 if (aedr.getWho() == Board.X){
 631  0
                                         int miniSize = bs.barWidth/2;
 632  0
                                         int miniX = bs.w/2-bs.barWidth/2;
 633  0
                                         int miniY = 0;        // bs.h-miniSize-2;
 634  0
                                         int[] pos = aedr.getDiceParms(miniX, miniX+miniSize, miniY, miniSize, x0, x1, y, bs.dieSize);
 635  0
                                         x0 = pos[AnimateEventDiceRoll.XL];
 636  0
                                         x1 = pos[AnimateEventDiceRoll.XR];
 637  0
                                         y = pos[AnimateEventDiceRoll.Y];
 638  0
                                         size = pos[AnimateEventDiceRoll.SIZE];
 639  0
                                         dice[Board.X][0] = aedr.dice[0];
 640  0
                                         dice[Board.X][1] = aedr.dice[1];
 641  
                                 }
 642  
                         }
 643  0
                         if (ae.getType() == Type.FirstRoll) {
 644  0
                                 AnimateEventFirstRoll aefr = (AnimateEventFirstRoll)ae;
 645  0
                                 for (int i=0; i<diceUsed.length; i++)
 646  0
                                         diceUsed[i] = false;
 647  
                                 // Calculate the black die
 648  0
                                 int miniSize = bs.barWidth/2;
 649  0
                                 int miniX = bs.w/2-bs.barWidth/2;
 650  0
                                 int miniY = 0;        // bs.h-miniSize-2;
 651  0
                                 x0 = (int)(((x0-miniX)*ae.offset)+miniX);
 652  0
                                 y =  (int)(((y-miniY)*ae.offset)+miniY);
 653  0
                                 size = (int)(((bs.dieSize-miniSize)*ae.offset)+miniSize);
 654  
                                 // We have to paint the die here because Board.X is 0
 655  0
                                 paintDie(g, size, x0, y, aefr.getBlackDie(), cColor, cColor, tColor);
 656  
 
 657  
                         }
 658  0
                         if (ae.getType() == Type.CantMove){
 659  0
                                 cColor = Color.red;
 660  
                         }
 661  0
                         if (ae instanceof AnimateEventResign) {
 662  0
                                 cColor = makeTranslucent(cColor);
 663  0
                                 tColor = makeTranslucent(tColor);
 664  
                         }
 665  
                 }
 666  
                 // paint the black/opponent dice
 667  0
                 if (ae == null || ae.getType() != Type.FirstRoll) {
 668  0
                         if (dice[Board.X][0] != 0)
 669  0
                                 paintDie(g, size, x0, y, dice[Board.X][0], cColor, cColor, tColor);
 670  0
                         if (dice[Board.X][1] != 0)
 671  0
                                 paintDie(g, size, x1, y, dice[Board.X][1], cColor, cColor, tColor);
 672  
                 }
 673  0
                 if (ae != null && ae.getType() == Type.CantMove && ae.getWho() == Board.X) {
 674  0
                         g.setColor(Color.red);
 675  0
                         y = y + size + size/2;
 676  0
                         g.drawLine(x0, y, x1+size, y-size*2);
 677  0
                         g.drawLine(x0-1, y, x1+size-1, y-size*2);
 678  0
                         g.drawLine(x0, y-size*2, x1+size, y);
 679  0
                         g.drawLine(x0-1, y-size*2, x1+size-1, y);
 680  
                         
 681  
                 }
 682  
                 // Do white dice
 683  0
                 Color luColor = wCheckerColor;
 684  0
                 Color ldColor = wCheckerColor;
 685  0
                 Color ruColor = wCheckerColor;
 686  0
                 Color rdColor = wCheckerColor;
 687  0
                 tColor = wTrimColor;
 688  
 
 689  0
                 if (diceUsed.length == 2) {
 690  0
                         if (diceUsed[0]) {
 691  0
                                 luColor = gColor;
 692  0
                                 ldColor = gColor;
 693  
                         }
 694  0
                         if (diceUsed[1]) {
 695  0
                                 ruColor = gColor;
 696  0
                                 rdColor = gColor;
 697  
                         }
 698  
                 }
 699  0
                 if (diceUsed.length == 4) {
 700  0
                         if (diceUsed[3])
 701  0
                                 luColor = gColor;
 702  0
                         if (diceUsed[2])
 703  0
                                 ldColor = gColor;
 704  0
                         if (diceUsed[1])
 705  0
                                 ruColor = gColor;
 706  0
                         if (diceUsed[0])
 707  0
                                 rdColor = gColor;
 708  
                 }
 709  0
                 x0 = this.getPointX(4);
 710  0
                 x1 = x0+bs.c15;
 711  0
                 y = bs.h/2-bs.c2;
 712  0
                 size = bs.dieSize;
 713  0
                 if (ae != null) {
 714  0
                         if (ae.getType() == Type.Roll) {
 715  0
                                 AnimateEventDiceRoll aedr = (AnimateEventDiceRoll)ae;
 716  0
                                 if (aedr.getWho() == Board.O){
 717  0
                                         int miniSize = bs.barWidth/2;
 718  0
                                         int miniX = bs.w/2-bs.barWidth/2;
 719  0
                                         int miniY = bs.h-miniSize-2;
 720  0
                                         int[] pos = aedr.getDiceParms(miniX, miniX+miniSize, miniY, miniSize, x0, x1, y, bs.dieSize);
 721  0
                                         x0 = pos[0];
 722  0
                                         x1 = pos[1];
 723  0
                                         y = pos[2];
 724  0
                                         size = pos[3];
 725  0
                                         dice[Board.O][0] = aedr.dice[0];
 726  0
                                         dice[Board.O][1] = aedr.dice[1];
 727  
                                 }
 728  
                         }
 729  0
                         if (ae.getType() == Type.CantMove) {
 730  0
                                 luColor = Color.red;
 731  0
                                 ldColor = Color.red;
 732  0
                                 ruColor = Color.red;
 733  0
                                 rdColor = Color.red;
 734  
                         }
 735  0
                         if (ae.getType() == Type.FirstRoll) {
 736  0
                                 AnimateEventFirstRoll aefr = (AnimateEventFirstRoll)ae;
 737  
                                 // Calculate the white die
 738  0
                                 int miniSize = bs.barWidth/2;
 739  0
                                 int miniX = bs.w/2-bs.barWidth/2;
 740  0
                                 int miniY = bs.h-miniSize-2;
 741  0
                                 x0 = (int)(((x0-miniX)*ae.offset)+miniX);
 742  0
                                 y =  (int)(((y-miniY)*ae.offset)+miniY);
 743  0
                                 size = (int)(((bs.dieSize-miniSize)*ae.offset)+miniSize);
 744  
                                 // We have to paint the die here because Board.X is 0
 745  0
                                 paintDie(g, size, x0, y, aefr.getWhiteDie(),  luColor, ldColor, tColor);
 746  
 
 747  
                         }
 748  0
                         if (ae instanceof AnimateEventResign) {
 749  0
                                 luColor = makeTranslucent(luColor);
 750  0
                                 ldColor = makeTranslucent(ldColor);
 751  0
                                 ruColor = makeTranslucent(ruColor);
 752  0
                                 rdColor = makeTranslucent(rdColor);
 753  0
                                 tColor = makeTranslucent(tColor);
 754  
                         }
 755  
                 }
 756  0
                 if (ae == null || ae.getType() != Type.FirstRoll) {
 757  0
                         if (dice[Board.O][0] != 0)
 758  0
                                 paintDie(g, size, x0, y, dice[Board.O][0], luColor, ldColor, tColor);
 759  0
                         if (dice[Board.O][1] != 0)
 760  0
                                 paintDie(g, size, x1, y, dice[Board.O][1], ruColor, rdColor, tColor);
 761  
                 }
 762  0
                 if (ae != null && ae.getType() == Type.CantMove && ae.getWho() == Board.O){
 763  0
                         g.setColor(Color.red);
 764  0
                         y = y + size + size/2;
 765  0
                         g.drawLine(x0, y, x1+size, y-size*2);
 766  0
                         g.drawLine(x0-1, y, x1+size-1, y-size*2);
 767  0
                         g.drawLine(x0, y-size*2, x1+size, y);
 768  0
                         g.drawLine(x0-1, y-size*2, x1+size-1, y);
 769  
                 }
 770  0
         }
 771  
         
 772  
         /*  0   4
 773  
          *  1 3 5
 774  
          *  2   6
 775  
          */
 776  0
         private final static boolean[][] diePoints = new boolean[][] {
 777  
                 {false,false,false,false,false,false,false},        // 0
 778  
                 {false,false,false,true,false,false,false},                // 1
 779  
                 {false,false,true,false,true,false,false},                // 2
 780  
                 {false,false,true,true,true,false,false},                // 3
 781  
                 {true,false,true,false,true,false,true},                // 4
 782  
                 {true,false,true,true,true,false,true},                        // 5
 783  
                 {true,true,true,false,true,true,true},                        // 6
 784  
         };
 785  
         private        final static double y0m = 25.0/100.0;
 786  
         private        final static double y2m = 75.0/100.0;
 787  
 
 788  
         /** Paint one die on the board
 789  
          * @param g The graphics to use
 790  
          * @param dieSize The number of pixels to draw the die in
 791  
          * @param x The left side of the die
 792  
          * @param y The bottom of the die
 793  
          * @param n The number of dots to draw (value of the die)
 794  
          * @param uColor The top half color
 795  
          * @param dColor The bottom half color
 796  
          * @param tColor The trim (border) color
 797  
          */
 798  
         private void paintDie(Graphics g, int dieSize,
 799  
                                                   int x, int y, int n, Color uColor, Color dColor, Color tColor) {
 800  0
                 int dotSize = dieSize/4;
 801  0
                 int dotSize2 = dotSize/2;
 802  0
                 g.setColor(uColor);
 803  0
                 g.setClip(x-1, y+0, dieSize+1, dieSize/2+1);
 804  0
                 g.fillRoundRect(x, y, dieSize, dieSize, dieSize/4, dieSize/4);
 805  0
                 g.setColor(dColor);
 806  0
                 g.setClip(x-1, y+dieSize/2+1, dieSize+1, dieSize/2+1);
 807  0
                 g.fillRoundRect(x, y, dieSize, dieSize, dieSize/4, dieSize/4);
 808  0
                 g.setClip(null);
 809  0
                 g.setColor(tColor);
 810  0
                 g.drawRoundRect(x, y, dieSize, dieSize, dieSize/4, dieSize/4);
 811  0
                 int dX[] = new int[3];
 812  0
                 int dY[] = new int[3];
 813  0
                 dX[0] = (int)(x + ((double)dieSize * y0m)) - dotSize2;
 814  0
                 dX[1] = (int)(x + ((double)dieSize / 2.0)) - dotSize2;
 815  0
                 dX[2] = (int)(x + ((double)dieSize * y2m)) - dotSize2;
 816  0
                 dY[0] = (int)(y + ((double)dieSize * y0m)) - dotSize2;
 817  0
                 dY[1] = (int)(y + ((double)dieSize / 2.0)) - dotSize2;
 818  0
                 dY[2] = (int)(y + ((double)dieSize * y2m)) - dotSize2;
 819  
                 /*  0   4
 820  
                  *  1 3 5
 821  
                  *  2   6
 822  
                  */
 823  0
                 if (diePoints[n][0])
 824  0
                         g.fillArc(dX[0], dY[0], dotSize, dotSize, 0, 360);
 825  0
                 if (diePoints[n][1])
 826  0
                         g.fillArc(dX[0], dY[1], dotSize, dotSize, 0, 360);
 827  0
                 if (diePoints[n][2])
 828  0
                         g.fillArc(dX[0], dY[2], dotSize, dotSize, 0, 360);
 829  0
                 if (diePoints[n][3])
 830  0
                         g.fillArc(dX[1], dY[1], dotSize, dotSize, 0, 360);
 831  0
                 if (diePoints[n][4])
 832  0
                         g.fillArc(dX[2], dY[0], dotSize, dotSize, 0, 360);
 833  0
                 if (diePoints[n][5])
 834  0
                         g.fillArc(dX[2], dY[1], dotSize, dotSize, 0, 360);
 835  0
                 if (diePoints[n][6])
 836  0
                         g.fillArc(dX[2], dY[2], dotSize, dotSize, 0, 360);
 837  0
         }
 838  
 
 839  
 
 840  0
         Font        doubleCubeFont = new Font("Arial", Font.BOLD, 18);
 841  
 
 842  
         private void paintDoubleCube(Graphics g) {
 843  0
                 Point p = getDoubleCubeXY();
 844  0
                 int w2 = getDoubleCubeWidth()/2;
 845  0
                 int x = p.x - w2;
 846  0
                 int y = p.y - w2;
 847  0
                 AnimateEvent ae = animateManager.getHeadEvent();
 848  0
                 if (ae != null) {
 849  0
                         AnimateEventDouble aed = null;
 850  0
                         if (ae.getType() == Type.Double) {
 851  0
                                 aed = (AnimateEventDouble)ae;
 852  0
                                 if (properties.isDEBUG_ShowAnimatePath()) {
 853  0
                                         aed.calculate(board);
 854  0
                                         g.setColor(Color.blue);
 855  0
                                         for (double d = 0.0; d <= 1.0; d += 0.002) {
 856  0
                                                 int pp[] = aed.getXY(d);
 857  0
                                                 g.drawRect(pp[0]-1, pp[1]-1, 3, 3);
 858  
                                         }
 859  0
                                         g.setColor(Color.green);
 860  0
                                                 for (int i=0; i<aed.x.length; i++ ) {
 861  0
                                                         g.drawRect((int)aed.x[i]-3, (int)aed.y[i]-3, 6, 6);                
 862  
                                                 }
 863  
                                 }
 864  0
                                 int[] xy = aed.getXY(aed.getOffset());
 865  0
                                 x = xy[0] - w2;
 866  0
                                 y = xy[1] - w2;
 867  
                         }
 868  
                 }
 869  
                 //logger.info("paintdoubleCube x/y = " + x + "/" + y);
 870  0
                 int cubeValue = board.getCube();
 871  0
                 int w = getDoubleCubeWidth();
 872  0
                 if (board.getWasDoubled()[0] || board.getWasDoubled()[1]) {
 873  0
                         cubeValue *= 2;
 874  0
                         if (cubeValue > 64)
 875  0
                                 cubeValue = 1;
 876  
                 }
 877  0
                 g.setColor(Color.white);
 878  0
                 g.fillRoundRect(x, y, w, w, w/4, w/4);
 879  0
                 g.setColor(Color.black);
 880  0
                 g.drawRoundRect(x, y, w, w, w/4, w/4);
 881  0
                 g.setColor(Color.yellow);
 882  0
                 if (this.board.isYourTurnToRollOrDouble()) {
 883  0
                         g.drawRoundRect(x, y, w, w, w/4, w/4);
 884  0
                         g.drawRoundRect(x-1, y-1, w+2, w+2, w/4+1, w/4+1);
 885  
                 }
 886  
 
 887  0
                 g.setColor(Color.black);
 888  0
                 g.setFont(doubleCubeFont);
 889  0
                 FontMetrics fm = g.getFontMetrics();
 890  0
                 String s = "" + cubeValue; 
 891  0
                 int sw = fm.stringWidth(s);
 892  0
                 x = x + w/2 - sw/2;
 893  0
                 y = y + w/2 - fm.getAscent()/2 + fm.getAscent();
 894  0
                 g.drawString(s, x, y);
 895  0
         }
 896  
 
 897  
         protected Point getDoubleCubeXY() {
 898  0
                 int w = getDoubleCubeWidth();
 899  0
                 int x = bs.c15/2;
 900  0
                 int y = bs.h/2;
 901  0
                 if (board.getHasCube() == Board.O)
 902  0
                         y = 0 + w;
 903  0
                 if (board.getHasCube() == Board.X)
 904  0
                         y = bs.h - w*2;
 905  0
                 if (board.getWasDoubled()[0]) {
 906  0
                         logger.info("wasDoubled[0]");
 907  0
                         return(getDoubleCubePushXY());
 908  
                 }
 909  0
                 if (board.getWasDoubled()[1]) {
 910  0
                         logger.info("wasDoubled[1]");
 911  0
                         return(getDoubleCubePushXY());
 912  
                 }
 913  0
                 return(new Point(x,y));
 914  
         }
 915  
 
 916  
         // XXX
 917  
         protected Point getDoubleCubePushXY() {
 918  0
                 int[] bp = board.getPoints();
 919  
                 //final int[] points0 = new int[] {8,  9,10, 5, 4, 3, 2,11,12, 6, 1};
 920  
                 //final int[] points1 = new int[] {17,16,15,20,21,22,23,14,18,13,24};
 921  0
                 final int[] points1 = new int[] { 4, 5, 3, 2, 8, 9,10,11, 1, 7,12,19};
 922  0
                 final int[] points0 = new int[] {21,20,22,23,17,16,15,14,24,18,13,6};
 923  0
                 int[] check = points1;
 924  0
                 int dir = Board.turnO;
 925  0
                 AnimateEvent ae = animateManager.getHeadEvent();
 926  0
                 if (ae != null) {
 927  
                         AnimateEventDouble aed;
 928  0
                         if (ae.getType() == Type.Double) {
 929  0
                                 aed = (AnimateEventDouble)ae;
 930  0
                                 board.setWasDoubled(aed.getWhoDoubled());
 931  0
                                 logger.info("(aed) set board.wasdoubled(" + Board.getXOAsText(aed.getWhoDoubled()) + ")");
 932  
 /*                                if (aed.getWhoDoubled() == Board.turnO) {
 933  
                                         check = points0;
 934  
                                         dir = Board.turnX;
 935  
                                         logger.info("(aed) use other points1;");
 936  
                                 }
 937  
 */                        }
 938  
                 }
 939  0
                 logger.info("wasDoubled[0/1] = " + board.getWasDoubled()[0] + "/" + board.getWasDoubled()[1] + " dir = " + Board.getTurnAsText(board.getDirection()));
 940  0
                 if ((board.getWasDoubled()[Board.X] && board.getDirection() == Board.turnO)
 941  0
                  || (board.getWasDoubled()[Board.O] && board.getDirection() == Board.turnX)) {
 942  0
                         check = points0;
 943  0
                         dir = Board.turnX;
 944  0
                         logger.info("use other points0;");
 945  
                 }
 946  0
                 int f = 0;
 947  0
                 int h = 0;
 948  0
                 for (h = 0; h < 2; h++) {
 949  0
                         for (int i : check) {
 950  0
                                 if (bp[i] == 0) {
 951  0
                                         f = i;
 952  0
                                         break;
 953  
                                 }
 954  
                         }
 955  0
                         if (f != 0)
 956  0
                                 break;
 957  
                 }
 958  0
                 int x = getPointX(f);
 959  0
                 logger.info("f = " + f + " h = " + h);
 960  0
                 x += bs.c2;
 961  0
                 int y = bs.checkerSize * (h+1) + getDoubleCubeWidth()/2;
 962  0
                 if (dir == Board.turnX) {
 963  0
                         y = bs.h - y; // - getDoubleCubeWidth();
 964  0
                         logger.info("dir = turnX");
 965  
                 }
 966  
                 //logger.info("push x/y = " + x + "/" + y);
 967  0
                 return(new Point(x,y));
 968  
         }
 969  
 
 970  
         protected int getDoubleCubeWidth() {
 971  0
                 return((bs.c15 + bs.dieSize) / 2);
 972  
         }
 973  
 
 974  0
         Font        pointNumbersFont = new Font("Arial", Font.BOLD, 11);
 975  
         private void paintPointNumbers(Graphics g) {
 976  0
                 if (!this.properties.isShowPointNumbers())
 977  0
                         return;
 978  
                 int p;
 979  
                 int x,y;
 980  
                 String s;
 981  0
                 int f = 0;
 982  
                 int t;
 983  0
                 boolean reverse = board.getDirection() > 0;
 984  0
                 g.setFont(pointNumbersFont);
 985  0
                 FontMetrics fm = g.getFontMetrics();
 986  0
                 for (p=1; p<=12; p++) {
 987  0
                         f = p;
 988  0
                         if (reverse)
 989  0
                                 f = 25-p;
 990  0
                         s = "" + f;
 991  0
                         int sw = fm.stringWidth(s);
 992  0
                         x = getPointX(p) + bs.c2 - sw/2;
 993  0
                         y = bs.h - bs.c2 + fm.getAscent()/2;
 994  0
                         t = board.getPoints()[f];
 995  0
                         if (t < -5 || t > 5)
 996  0
                                 y = this.getNthCheckerY(f, 5) + bs.c2 + fm.getAscent()/2;
 997  
 //                        g.setColor(Color.red);
 998  
 //                        g.drawRect(x-1, y-1, 3, 3);
 999  0
                         if (t > 0)
 1000  0
                                 g.setColor(Color.white);
 1001  
                         else
 1002  0
                                 g.setColor(Color.blue);
 1003  0
                         g.drawString(s, x, y);
 1004  
                 }
 1005  0
                 for (p=13; p<=24; p++) {
 1006  0
                         f = p;
 1007  0
                         if (reverse)
 1008  0
                                 f = 25-p;
 1009  0
                         s = "" + f;
 1010  0
                         int sw = fm.stringWidth(s);
 1011  0
                         x = getPointX(p) + bs.c2 - sw/2;
 1012  0
                         y = bs.c2 + fm.getAscent()/2;
 1013  0
                         t = board.getPoints()[f];
 1014  0
                         if (t < -5 || t > 5)
 1015  0
                                 y = this.getNthCheckerY(f, 5) + bs.c2 + fm.getAscent()/2;
 1016  0
                         if (t < -10 || t > 10)
 1017  0
                                 y = this.getNthCheckerY(f, 10) + bs.c2 + fm.getAscent()/2;
 1018  
                                 
 1019  0
                         if (t > 0)
 1020  0
                                 g.setColor(Color.white);
 1021  
                         else
 1022  0
                                 g.setColor(Color.blue);
 1023  0
                         g.drawString(s, x, y);
 1024  
                 }
 1025  0
         }
 1026  
 
 1027  
         /** Callback from AnimationManager to refresh the whole BoardTab
 1028  
          */
 1029  
         public void        updateBoardTab() {
 1030  0
                 this.boardTab.updateBoard();
 1031  0
         }
 1032  
 
 1033  
         /** Given a Color, return a translucent copy of that color
 1034  
          * @param c The color to translucify
 1035  
          * @return
 1036  
          */
 1037  
         private Color        makeTranslucent(Color c) {
 1038  0
                 return(new Color(c.getRed(), c.getGreen(), c.getBlue(), 48));
 1039  
         }
 1040  
 
 1041  0
         private        static         final Color        endColor = new Color(20,255,20,150);
 1042  
         private void        paintAnimatedCheckers(Graphics g) {
 1043  0
                 AnimateEvent ae = animateManager.getHeadEvent();
 1044  0
                 if (ae != null) {
 1045  0
                         AnimateEventMove aem = null;
 1046  0
                         if (ae.getType() == Type.Move) {
 1047  0
                                 aem = (AnimateEventMove)ae;
 1048  0
                                 if (properties.isDEBUG_ShowAnimatePath()) {
 1049  0
                                         aem.calculate();
 1050  0
                                         g.setColor(Color.blue);
 1051  0
                                         for (double d = 0.0; d <= 1.0; d += 0.002) {
 1052  0
                                                 int p[] = aem.getXY(d);
 1053  0
                                                 g.drawRect(p[0]-1, p[1]-1, 3, 3);
 1054  
                                         }
 1055  0
                                         g.setColor(Color.green);
 1056  0
                                         for (int i=0; i<aem.x.length; i++ ) {
 1057  0
                                                 g.drawRect((int)aem.x[i]-3, (int)aem.y[i]-3, 6, 6);                
 1058  
                                         }
 1059  
                                 }
 1060  0
                                 g.setColor(aem.getColor(aem.getOffset()));
 1061  0
                                 int[] xy = aem.getXY(aem.getOffset());
 1062  0
                                 g.fillArc(xy[0]-bs.c2, xy[1]-bs.c2, bs.checkerSize, bs.checkerSize, 0, 360);
 1063  
                         }
 1064  
                 }
 1065  0
                 if (animateManager.extraCheckersIndex != 0) {
 1066  
                         if (DEBUGa) {
 1067  
                                 logger.debug("extraCheckers: " + (animateManager.extraCheckersIndex/2));
 1068  
                                 for (int i=0; i<animateManager.extraCheckersIndex; i+=2)
 1069  
                                         logger.debug("checker[" + i + "]=" + animateManager.extraCheckers[i] + "/" + animateManager.extraCheckers[i+1]);
 1070  
                         }
 1071  0
                         g.setColor(endColor);
 1072  0
                         for (int i=0; i<animateManager.extraCheckersIndex; i+=2) {
 1073  0
                                 if (animateManager.extraCheckers[i] == Board.Home) {
 1074  0
                                         paintCheckerInHome(g, animateManager.extraCheckersWho, animateManager.extraCheckers[i+1], endColor, endColor);
 1075  
                                 //} else if (animateManager.extraCheckers[i] == Board.Bar) {
 1076  
                                         
 1077  
                                 } else {
 1078  0
                                         int x = getPointX(animateManager.extraCheckers[i]);
 1079  0
                                         int y = this.getNthCheckerY(animateManager.extraCheckers[i], animateManager.extraCheckers[i+1]);
 1080  0
                                         g.fillArc(x, y, bs.checkerSize, bs.checkerSize, 0, 360);
 1081  
                                 }
 1082  
                         }
 1083  
                 }
 1084  
 //                g.setColor(Color.black);
 1085  
 //                g.fillArc(xy[0]-bs.c2, xy[1]-bs.c2, bs.checkerSize, bs.checkerSize, 0, 360);
 1086  0
         }
 1087  
         
 1088  
         private void paintResign(Graphics g) {
 1089  0
                 AnimateEvent ae = this.animateManager.getHeadEvent();
 1090  0
                 if (ae != null && ae instanceof AnimateEventResign) {        // ().getType() == Type.Resign || ae.getType() == Type.PleaseAcceptOrRejectResign)) {
 1091  0
                         AnimateEventResign aer = (AnimateEventResign)ae;
 1092  0
                         int flagSize = (int)(bs.checkerSize*2.5);
 1093  0
                         int miniSize = bs.barWidth/2;
 1094  0
                         int miniX = bs.w/2-bs.barWidth/2;
 1095  0
                         int miniY = 0;        // bs.h-miniSize-2;
 1096  
 //                        int y = bs.h/2-bs.c2;
 1097  0
                         int y = (int)(bs.h-bs.pointHeight-(flagSize*0.75));
 1098  0
                         int x = this.getPointX(4); // - bs.c15;
 1099  0
                         if (aer.getWho() == Board.O){
 1100  0
                                 miniY = bs.h-miniSize-2;
 1101  0
                                 x = this.getPointX(9) - bs.c15;
 1102  0
                                 y = (int)(0+bs.pointHeight-(flagSize*0.25));
 1103  
                         }
 1104  0
                         int[] pos = aer.getFlagParms(miniX, miniY, miniSize, x, y, flagSize);
 1105  0
                         g.drawImage(aer.getIcon().getImage(), pos[AnimateEventResign.X], pos[AnimateEventResign.Y],
 1106  
                                         pos[AnimateEventResign.WIDTH], pos[AnimateEventResign.HEIGHT], null);
 1107  0
                         Font f = doubleCubeFont;                // XXX: Should calculate our own font, use this for now
 1108  0
                         g.setFont(f);
 1109  0
                         g.setColor(Color.black);
 1110  0
                         g.drawString("" + aer.getResigningPoints(), 
 1111  
                                         (int)(pos[AnimateEventResign.X]+pos[AnimateEventResign.WIDTH]*0.25), 
 1112  
                                         (int)(pos[AnimateEventResign.Y]+pos[AnimateEventResign.HEIGHT]*0.30));
 1113  0
                         if (ae instanceof AnimateEventRejectResign) {
 1114  0
                                 g.setColor(Color.red);
 1115  0
                                 g.drawLine(pos[AnimateEventResign.X],
 1116  
                                                    pos[AnimateEventResign.Y],
 1117  
                                                    pos[AnimateEventResign.X]+pos[AnimateEventResign.WIDTH],
 1118  
                                                    pos[AnimateEventResign.Y]+pos[AnimateEventResign.HEIGHT]);
 1119  0
                                 g.drawLine(pos[AnimateEventResign.X]+1,
 1120  
                                                    pos[AnimateEventResign.Y],
 1121  
                                                    pos[AnimateEventResign.X]+pos[AnimateEventResign.WIDTH]+1,
 1122  
                                                    pos[AnimateEventResign.Y]+pos[AnimateEventResign.HEIGHT]);
 1123  0
                                 if (ae.getOffset() > 0.5) {
 1124  0
                                         g.drawLine(pos[AnimateEventResign.X]+pos[AnimateEventResign.WIDTH],
 1125  
                                                         pos[AnimateEventResign.Y],
 1126  
                                                         pos[AnimateEventResign.X],
 1127  
                                                         pos[AnimateEventResign.Y]+pos[AnimateEventResign.HEIGHT]);
 1128  0
                                         g.drawLine(pos[AnimateEventResign.X]+pos[AnimateEventResign.WIDTH]+1,
 1129  
                                                         pos[AnimateEventResign.Y],
 1130  
                                                         pos[AnimateEventResign.X]+1,
 1131  
                                                         pos[AnimateEventResign.Y]+pos[AnimateEventResign.HEIGHT]);
 1132  
                                 }
 1133  0
                         } else if (ae instanceof AnimateEventAcceptAndWin) {
 1134  0
                                 AnimateEventAcceptAndWin aeaaw = (AnimateEventAcceptAndWin)ae;
 1135  0
                                 pos = aeaaw.getFlagParms(miniX, miniY, miniSize, x, y, flagSize);
 1136  0
                                 g.drawImage(aer.getIcon().getImage(), pos[AnimateEventResign.X], pos[AnimateEventResign.Y],
 1137  
                                                 pos[AnimateEventResign.WIDTH], pos[AnimateEventResign.HEIGHT], null);
 1138  
                                 
 1139  
                         }
 1140  
                 }
 1141  0
         }
 1142  
 }