1 /** 2 * The chess framework library. 3 * More information is available at http://www.jinchess.com/. 4 * Copyright (C) 2002, 2003 Alexander Maryanovsky. 5 * All rights reserved. 6 * 7 * The chess framework library is free software; you can redistribute 8 * it and/or modify it under the terms of the GNU Lesser General Public License 9 * as published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * The chess framework library is distributed in the hope that it will 13 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with the chess framework library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 package free.chess; 23 24 25 /** 26 * <P>Implements WildVariant for chesslike variants. Subclasses must only define 27 * the initial position and the name of the variant. Although this class is not 28 * abstract, directly instantiating it is discouraged except for cases where 29 * the name or the initial position is unknown at compile time. When the initial 30 * position and the name are known at compile time, its best to instantiate a 31 * subclass which defines them. 32 * 33 * <P>This class also provides some methods for determining the various 34 * properties of a move in the game of chess (en-passant, promotion, castling, 35 * etc.). Variants that only differ from chess in their definition of these 36 * terms can override these methods and implement them accordingly. Note that 37 * it is not necessary to override the 38 * {@link #createMove(Position, Square, Square, Piece, String)} method as it 39 * already calls the forementioned methods when determining the properties of 40 * the created ChessMove. 41 */ 42 43 44 public class ChesslikeGenericVariant implements WildVariant{ 45 46 47 48 /** 49 * An array containing WHITE_QUEEN, WHITE_ROOK, WHITE_BISHOP and WHITE_KNIGHT. 50 * These are the pieces to which a white pawn can be promoted. 51 */ 52 53 private static final ChessPiece [] WHITE_PROMOTION_TARGETS = new ChessPiece[]{ChessPiece.WHITE_QUEEN, ChessPiece.WHITE_ROOK, ChessPiece.WHITE_BISHOP, ChessPiece.WHITE_KNIGHT}; 54 55 56 57 /** 58 * An array containing BLACK_QUEEN, BLACK_ROOK, BLACK_BISHOP and BLACK_KNIGHT. 59 * These are the pieces to which a black pawn can be promoted. 60 */ 61 62 private static final ChessPiece [] BLACK_PROMOTION_TARGETS = new ChessPiece[]{ChessPiece.BLACK_QUEEN, ChessPiece.BLACK_ROOK, ChessPiece.BLACK_BISHOP, ChessPiece.BLACK_KNIGHT}; 63 64 65 66 /** 67 * A white short castling move. 68 */ 69 70 public static final ChessMove WHITE_SHORT_CASTLING = 71 new ChessMove(Square.parseSquare("e1"), Square.parseSquare("g1"), Player.WHITE_PLAYER, 72 false, true, false, null, -1, null, "O-O"); 73 74 75 76 /** 77 * A white long castling move. 78 */ 79 80 public static final ChessMove WHITE_LONG_CASTLING = 81 new ChessMove(Square.parseSquare("e1"), Square.parseSquare("c1"), Player.WHITE_PLAYER, 82 false, false, true, null, -1, null, "O-O-O"); 83 84 85 86 /** 87 * A black short castling move. 88 */ 89 90 public static final ChessMove BLACK_SHORT_CASTLING = 91 new ChessMove(Square.parseSquare("e8"), Square.parseSquare("g8"), Player.BLACK_PLAYER, 92 false, true, false, null, -1, null, "O-O"); 93 94 95 96 /** 97 * A black long castling move. 98 */ 99 100 public static final ChessMove BLACK_LONG_CASTLING = 101 new ChessMove(Square.parseSquare("e8"), Square.parseSquare("c8"), Player.BLACK_PLAYER, 102 false, false, true, null, -1, null, "O-O-O"); 103 104 105 106 107 /** 108 * The initial position of this variant, in FEN format. 109 */ 110 111 private final String initialPositionFEN; 112 113 114 115 116 /** 117 * The name of this variant. 118 */ 119 120 private final String variantName; 121 122 123 124 125 126 /** 127 * Creates a new ChesslikeGenericVariant with the given initial position and 128 * name. The position is specified in FEN format. 129 */ 130 ChesslikeGenericVariant(String initialPositionFEN, String variantName)131 public ChesslikeGenericVariant(String initialPositionFEN, String variantName){ 132 if (initialPositionFEN == null) 133 throw new IllegalArgumentException("The initial position argument may not be null"); 134 if (variantName == null) 135 throw new IllegalArgumentException("The variant name argument may not be null"); 136 137 this.initialPositionFEN = initialPositionFEN; 138 this.variantName = variantName; 139 } 140 141 142 143 144 145 /** 146 * Returns <code>true</code> if the chess move defined by the given arguments 147 * is an en-passant move. Returns false otherwise. The result for an illegal 148 * move is undefined, but it should throw no exceptions. 149 */ 150 isEnPassant(Position pos, Square startingSquare, Square endingSquare, ChessPiece promotionTarget)151 public boolean isEnPassant(Position pos, Square startingSquare, 152 Square endingSquare, ChessPiece promotionTarget){ 153 154 if (promotionTarget!=null) 155 return false; 156 157 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 158 ChessPiece takenPiece = (ChessPiece)pos.getPieceAt(endingSquare); 159 160 if (movingPiece.isPawn()){ 161 Square squareAtIntersection = Square.getInstance(endingSquare.getFile(),startingSquare.getRank()); 162 ChessPiece pieceAtIntersection = (ChessPiece)pos.getPieceAt(squareAtIntersection); 163 164 if (takenPiece!=null) 165 return false; 166 else if (pieceAtIntersection==null) 167 return false; 168 else if (!pieceAtIntersection.isPawn()) 169 return false; 170 else if (pieceAtIntersection.isSameColor(movingPiece)) 171 return false; 172 else if (Math.abs(startingSquare.getFile()-endingSquare.getFile())!=1) 173 return false; 174 else if (movingPiece.isWhite()){ 175 if ((startingSquare.getRank()!=4)||(endingSquare.getRank()!=5)) 176 return false; 177 else 178 return true; 179 } 180 else{ 181 if ((startingSquare.getRank()!=3)||(endingSquare.getRank()!=2)) 182 return false; 183 else 184 return true; 185 } 186 } 187 else 188 return false; 189 } 190 191 192 193 194 195 196 /** 197 * Returns <code>true</code> if the move defined by the given arguments is a 198 * short castling move. Returns <code>false</code> otherwise. The result for 199 * an illegal move is undefined, but it should throw no exceptions. 200 */ 201 isShortCastling(Position pos, Square startingSquare, Square endingSquare, ChessPiece promotionTarget)202 public boolean isShortCastling(Position pos, Square startingSquare, 203 Square endingSquare, ChessPiece promotionTarget){ 204 205 if (promotionTarget!=null) 206 return false; 207 208 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 209 ChessPiece takenPiece = (ChessPiece)pos.getPieceAt(endingSquare); 210 211 if (takenPiece!=null) 212 return false; 213 214 if (movingPiece==ChessPiece.WHITE_KING){ 215 if (!startingSquare.equals("e1")) 216 return false; 217 else if (!endingSquare.equals("g1")) 218 return false; 219 else if (pos.getPieceAt("h1")!=ChessPiece.WHITE_ROOK) 220 return false; 221 else if (pos.getPieceAt("f1")!=null) 222 return false; 223 else 224 return true; 225 } 226 else if (movingPiece==ChessPiece.BLACK_KING){ 227 if (!startingSquare.equals("e8")) 228 return false; 229 else if (!endingSquare.equals("g8")) 230 return false; 231 else if (pos.getPieceAt("h8")!=ChessPiece.BLACK_ROOK) 232 return false; 233 else if (pos.getPieceAt("f8")!=null) 234 return false; 235 else 236 return true; 237 } 238 else 239 return false; 240 } 241 242 243 244 245 /** 246 * Returns <code>true</code> if the move defined by the given arguments is a 247 * long castling move. Returns <code>false</code> otherwise. The result for 248 * an illegal move is undefined, but it should throw no exceptions. 249 */ 250 isLongCastling(Position pos, Square startingSquare, Square endingSquare, ChessPiece promotionTarget)251 public boolean isLongCastling(Position pos, Square startingSquare, 252 Square endingSquare, ChessPiece promotionTarget){ 253 254 if (promotionTarget!=null) 255 return false; 256 257 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 258 ChessPiece takenPiece = (ChessPiece)pos.getPieceAt(endingSquare); 259 260 if (takenPiece!=null) 261 return false; 262 263 if (movingPiece==ChessPiece.WHITE_KING){ 264 if (!startingSquare.equals("e1")) 265 return false; 266 else if (!endingSquare.equals("c1")) 267 return false; 268 else if (pos.getPieceAt("a1")!=ChessPiece.WHITE_ROOK) 269 return false; 270 else if (pos.getPieceAt("b1")!=null) 271 return false; 272 else if (pos.getPieceAt("d1")!=null) 273 return false; 274 else 275 return true; 276 } 277 else if (movingPiece==ChessPiece.BLACK_KING){ 278 if (!startingSquare.equals("e8")) 279 return false; 280 else if (!endingSquare.equals("c8")) 281 return false; 282 else if (pos.getPieceAt("a8")!=ChessPiece.BLACK_ROOK) 283 return false; 284 else if (pos.getPieceAt("b8")!=null) 285 return false; 286 else if (pos.getPieceAt("d8")!=null) 287 return false; 288 else 289 return true; 290 } 291 else 292 return false; 293 } 294 295 296 297 298 /** 299 * Returns the piece captured by the move defined by the given arguments. 300 * Returns <code>null</code> if none. The result for an illegal move is 301 * undefined, but it should throw no exceptions. This is a convenience method 302 * which determines whether the move defined by the given properties is an 303 * en-passant by invoking 304 * {@link #isEnPassant(Position, Square, Square, ChessPiece)}. Keep in mind 305 * that the called method may be overriden. 306 */ 307 getCapturedPiece(Position pos, Square startingSquare, Square endingSquare, ChessPiece promotionTarget)308 public ChessPiece getCapturedPiece(Position pos, Square startingSquare, 309 Square endingSquare, ChessPiece promotionTarget){ 310 311 boolean isEnPassant = isEnPassant(pos, startingSquare, endingSquare, promotionTarget); 312 return getCapturedPiece(pos, startingSquare, endingSquare, promotionTarget, isEnPassant); 313 } 314 315 316 317 318 /** 319 * Returns the piece captured by the move defined by the given arguments. 320 * Returns <code>null</code> if none. The result for an illegal move is 321 * undefined, but it should throw no exceptions. 322 */ 323 getCapturedPiece(Position pos, Square startingSquare, Square endingSquare, ChessPiece promotionTarget, boolean isEnPassant)324 public ChessPiece getCapturedPiece(Position pos, Square startingSquare, 325 Square endingSquare, ChessPiece promotionTarget, boolean isEnPassant){ 326 327 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 328 ChessPiece takenPiece = (ChessPiece)pos.getPieceAt(endingSquare); 329 330 if (isEnPassant) 331 return (movingPiece.isWhite() ? ChessPiece.BLACK_PAWN : ChessPiece.WHITE_PAWN); 332 else 333 return takenPiece; 334 } 335 336 337 338 /** 339 * Returns the double pawn push file of the move defined by the given 340 * arguments, or -1 if that move is not a double pawn push. 341 */ 342 getDoublePawnPushFile(Position pos, Square startingSquare, Square endingSquare)343 public int getDoublePawnPushFile(Position pos, Square startingSquare, Square endingSquare){ 344 Piece piece = pos.getPieceAt(startingSquare); 345 if (((piece == ChessPiece.WHITE_PAWN) && 346 (startingSquare.getRank() == 1) && (endingSquare.getRank() == 3) && 347 (startingSquare.getFile() == endingSquare.getFile()) && 348 (pos.getPieceAt(Square.getInstance(endingSquare.getFile(), 2)) == null)) || 349 ((piece == ChessPiece.BLACK_PAWN) && 350 (startingSquare.getRank() == 6) && (endingSquare.getRank() == 4) && 351 (startingSquare.getFile() == endingSquare.getFile()) && 352 (pos.getPieceAt(Square.getInstance(endingSquare.getFile(), 5)) == null))) 353 return startingSquare.getFile(); 354 else 355 return -1; 356 } 357 358 359 360 361 362 /** 363 * Returns normally (and does nothing) if the given Position object can be 364 * used with this WildVariant. Throws an IllegalArgumentException if the 365 * given Position object cannot be used with this WildVariant. The default 366 * implementation throws an IllegalArgumentException if the given Position 367 * object's wild variant is different from this one. The comparison is done 368 * by calling the <code>equals(Object)</code> method. 369 */ 370 checkPosition(Position pos)371 protected void checkPosition(Position pos){ 372 if (!pos.getVariant().equals(this)) 373 throw new IllegalArgumentException("Wrong position variant: "+pos.getVariant()); 374 } 375 376 377 378 379 /** 380 * Sets the initial position of this chess variant on the given Position object. 381 * 382 * @throws IllegalArgumentException If the given Position is incompatible with 383 * this WildVariant as defined by {@link #checkPosition(Position)} 384 */ 385 init(Position pos)386 public void init(Position pos){ 387 checkPosition(pos); 388 389 pos.setFEN(initialPositionFEN); 390 } 391 392 393 394 395 396 /** 397 * <P>If the a move created by the given starting square and ending square in 398 * the given position is a promotion, returns an array containing a knight, 399 * bishop, rook and queen of the color of the promoted pawn. Otherwise 400 * returns null. 401 * 402 * <P>If you want to use this method from the implementation of some other 403 * wild variant, use the static 404 * {@link #getChessPromotionTargets(Position, Square, Square)} method 405 * instead - it doesn't check the wild variant of the position. 406 * 407 * @throws IllegalArgumentException If the given Position is incompatible with 408 * this WildVariant as defined by {@link #checkPosition(Position)} 409 */ 410 getPromotionTargets(Position pos, Square startingSquare, Square endingSquare)411 public Piece [] getPromotionTargets(Position pos, Square startingSquare, Square endingSquare){ 412 checkPosition(pos); 413 414 return getChessPromotionTargets(pos, startingSquare, endingSquare); 415 } 416 417 418 419 420 /** 421 * Returns the same thing as 422 * {@link #getPromotionTargets(Position, Square, Square)}, only it's static 423 * and doesn't check the wild variant of the position. This method is useful 424 * for other wild variants who have the same promotion targets and don't want 425 * to rewrite the functionality. The only constraint is that the piece at the 426 * piece at the starting square has to be a ChessPiece. 427 */ 428 getChessPromotionTargets(Position pos, Square startingSquare, Square endingSquare)429 public static Piece [] getChessPromotionTargets(Position pos, Square startingSquare, Square endingSquare){ 430 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 431 432 if ((endingSquare.getRank()==7)&&(movingPiece==ChessPiece.WHITE_PAWN)) 433 return (Piece [])WHITE_PROMOTION_TARGETS.clone(); 434 435 if ((endingSquare.getRank()==0)&&(movingPiece==ChessPiece.BLACK_PAWN)) 436 return (Piece [])BLACK_PROMOTION_TARGETS.clone(); 437 438 return null; 439 } 440 441 442 443 444 /** 445 * Creates a ChessMove from the given starting square and ending square in 446 * the given Position. If the move is not a promotion, promotionTarget should 447 * be null. The ChessMove is created with the constructor which takes all the 448 * properties. The properties are determined by calling the various methods 449 * in this class that determine those properties. This means that overriding 450 * these methods and redefining their behaviour is the only thing needed to 451 * implement variants which are mildly different from Chess. 452 * 453 * @throws IllegalArgumentException If the given Position is incompatible with 454 * this WildVariant as defined by {@link #checkPosition(Position)} 455 * 456 * @throws IllegalArgumentException If the promotionTarget is not null and is 457 * not an instance of <code>ChessPiece</code>. 458 * 459 * @throws IllegalArgumentException If the there is no piece at the starting 460 * square. 461 */ 462 createMove(Position pos, Square startingSquare, Square endingSquare, Piece promotionTarget, String moveSAN)463 public Move createMove(Position pos, Square startingSquare, Square endingSquare, 464 Piece promotionTarget, String moveSAN){ 465 466 checkPosition(pos); 467 468 return createChessMove(pos, startingSquare, endingSquare, promotionTarget, moveSAN); 469 } 470 471 472 473 /** 474 * Creates a <code>ChessMove</code> from the specified parameters as 475 * documented in {@link #createMove(Position, Square, Square, Piece, String)} 476 * This method is here solely for the benefit of <code>WildVariant</code> 477 * implementations which need to create normal chess moves but don't want 478 * to reimplement this method. Note that because this method is not static, 479 * to actually use it, you still need to obtain an instance of 480 * <code>Chess</code> via <code>Chess.getInstance()</code>. 481 * Unlike the {@link #createMove(Position, Square, Square, Piece, String)} 482 * method, this method does not enforce the wild variant of the position 483 * by calling {@link #checkPosition(Position)}. 484 */ 485 createChessMove(Position pos, Square startingSquare, Square endingSquare, Piece promotionTarget, String moveSAN)486 public ChessMove createChessMove(Position pos, Square startingSquare, 487 Square endingSquare, Piece promotionTarget, String moveSAN){ 488 // This method is not static because it calls non-static methods (isEnPassant and such). 489 // It's still possible to use it in a static-like manner with: 490 // Chess.getInstance().createChessMove(...) 491 492 if ((promotionTarget != null) && !(promotionTarget instanceof ChessPiece)) 493 throw new IllegalArgumentException("Wrong promotion target type: "+promotionTarget.getClass()); 494 495 Piece movingPiece = pos.getPieceAt(startingSquare); 496 497 if (movingPiece == null) 498 throw new IllegalArgumentException("The moving piece may not be null"); 499 500 Player movingPlayer = movingPiece.getPlayer(); 501 ChessPiece promotionChessTarget = (ChessPiece)promotionTarget; 502 503 boolean isEnPassant = isEnPassant(pos, startingSquare, endingSquare, promotionChessTarget); 504 boolean isShortCastling = isShortCastling(pos, startingSquare, endingSquare, promotionChessTarget); 505 boolean isLongCastling = isLongCastling(pos, startingSquare, endingSquare, promotionChessTarget); 506 ChessPiece capturedPiece = getCapturedPiece(pos, startingSquare, endingSquare, promotionChessTarget, isEnPassant); 507 int doublePawnPushFile = getDoublePawnPushFile(pos, startingSquare, endingSquare); 508 509 return new ChessMove(startingSquare, endingSquare, movingPlayer, isEnPassant, isShortCastling, 510 isLongCastling, capturedPiece, doublePawnPushFile, promotionChessTarget, moveSAN); 511 512 } 513 514 515 516 517 /** 518 * Creates a <code>Move</code> object representing a move just like the 519 * specified one, but made in the specified position. 520 */ 521 createMove(Position pos, Move move)522 public Move createMove(Position pos, Move move){ 523 checkPosition(pos); 524 525 if (!(move instanceof ChessMove)) 526 throw new IllegalArgumentException("Wrong move type: "+move.getClass()); 527 528 ChessMove cmove = (ChessMove)move; 529 return createMove(pos, cmove.getStartingSquare(), cmove.getEndingSquare(), 530 cmove.getPromotionTarget(), cmove.getStringRepresentation()); 531 } 532 533 534 535 536 537 /** 538 * Creates a short castling move for the current player in the specified 539 * position. 540 */ 541 createShortCastling(Position pos)542 public Move createShortCastling(Position pos){ 543 checkPosition(pos); 544 545 Player currentPlayer = pos.getCurrentPlayer(); 546 if (currentPlayer.isWhite()) 547 return WHITE_SHORT_CASTLING; 548 else 549 return BLACK_SHORT_CASTLING; 550 } 551 552 553 554 555 /** 556 * Creates a long castling move for the current player in the specified 557 * position. 558 */ 559 createLongCastling(Position pos)560 public Move createLongCastling(Position pos){ 561 checkPosition(pos); 562 563 Player currentPlayer = pos.getCurrentPlayer(); 564 if (currentPlayer.isWhite()) 565 return WHITE_LONG_CASTLING; 566 else 567 return BLACK_LONG_CASTLING; 568 } 569 570 571 572 573 /** 574 * <P>Makes the given ChessMove in the given Position. <B>This method 575 * shoudln't (and can't) be called directly - call 576 * {@link Position#makeMove(Move)} instead.</B> 577 * 578 * <P>If you want to use this method from an implementation of some other 579 * wild variant, use the static 580 * {@link #makeChessMove(ChessMove, Position, Position.Modifier)} method 581 * instead - it doesn't check the wild variant of the position. 582 * 583 * @throws IllegalArgumentException If the given Position is incompatible with 584 * this WildVariant as defined by {@link #checkPosition(Position)} 585 * 586 * @throws IllegalArgumentException if the given Move is not an instance of 587 * <code>ChessMove</code>. 588 */ 589 makeMove(Move move, Position pos, Position.Modifier modifier)590 public void makeMove(Move move, Position pos, Position.Modifier modifier){ 591 checkPosition(pos); // Practically redundant as (almost) nobody can call this 592 // method except a method in the Position class, which will 593 // be of this wild variant anyway. 594 595 if (!(move instanceof ChessMove)) 596 throw new IllegalArgumentException("Wrong move type: "+move.getClass()); 597 598 ChessMove cmove = (ChessMove)move; 599 600 makeChessMove(cmove, pos, modifier); 601 } 602 603 604 605 606 607 /** 608 * Makes the given ChessMove on the given Position using the given position 609 * modifier. This method is here solely for the benefit of WildVariant 610 * implementations which sometimes need to make a regular ChessMove on a 611 * position and don't want to reimplement this method. Note that because this 612 * method is not static, to actually use it, you still need to obtain an 613 * instance of <code>Chess</code> via <code>Chess.getInstance()</code>. 614 * Unlike the {@link #makeMove(Move, Position, Position.Modifier)} 615 * method, this method does not enforce the wild variant of the position 616 * by calling {@link #checkPosition(Position)}. 617 */ 618 makeChessMove(ChessMove cmove, Position pos, Position.Modifier modifier)619 public void makeChessMove(ChessMove cmove, Position pos, Position.Modifier modifier){ 620 // This method is not static in solidarity with the createChessMove method 621 // which has trouble being static due to using non-static methods (isEnPassant and such). 622 // It's still possible to use it in a static-like manner with: 623 // Chess.getInstance().makeChessMove(...) 624 625 Square startingSquare = cmove.getStartingSquare(); 626 Square endingSquare = cmove.getEndingSquare(); 627 ChessPiece movingPiece = (ChessPiece)pos.getPieceAt(startingSquare); 628 629 modifier.setPieceAt(null, startingSquare); 630 if (cmove.isPromotion()) 631 modifier.setPieceAt(cmove.getPromotionTarget(), endingSquare); 632 else 633 modifier.setPieceAt(movingPiece, endingSquare); 634 635 if (cmove.isEnPassant()) 636 modifier.setPieceAt(null, Square.getInstance(endingSquare.getFile(), startingSquare.getRank())); 637 638 if (cmove.isCastling()){ 639 int rookStartFile = cmove.isShortCastling() ? 7 : 0; 640 int rookEndFile = cmove.isShortCastling() ? 5 : 3; 641 642 Square rookStartingSquare = Square.getInstance(rookStartFile, startingSquare.getRank()); 643 Square rookEndingSquare = Square.getInstance(rookEndFile, startingSquare.getRank()); 644 ChessPiece rook = (ChessPiece)pos.getPieceAt(rookStartingSquare); 645 646 modifier.setPieceAt(null, rookStartingSquare); 647 modifier.setPieceAt(rook, rookEndingSquare); 648 } 649 650 modifier.setCurrentPlayer(cmove.getPlayer().getOpponent()); 651 } 652 653 654 655 656 657 658 /** 659 * Returns what is described by the {@link #parseChessPiece(String)} method. 660 * 661 * <P>If you want to use this method from an implementation of some other 662 * wild variant, use the static {@link #parseChessPiece(String)} method 663 * instead. 664 * 665 * @param piece The string representing the piece. 666 * 667 * @throws IllegalArgumentException if the string is not in the correctformat. 668 */ 669 parsePiece(String piece)670 public Piece parsePiece(String piece){ 671 return parseChessPiece(piece); 672 } 673 674 675 676 677 /** 678 * Calls <code>ChessPiece.fromShortString(String)</code> to parse the piece. 679 * 680 * @param piece The string representing the piece. 681 * 682 * @throws IllegalArgumentException if the string is not in the correctformat. 683 */ 684 parseChessPiece(String piece)685 public static ChessPiece parseChessPiece(String piece){ 686 return ChessPiece.fromShortString(piece); 687 } 688 689 690 691 692 /** 693 * Returns what is described by the {@link #chessPieceToString(ChessPiece)} 694 * method. 695 * 696 * <P>If you want to use this method from an implementation of some other 697 * wild variant, use the static {@link #chessPieceToString(ChessPiece)} method 698 * instead. 699 * 700 * @param piece The string representing the piece. 701 * 702 * @throws IllegalArgumentException if the string is not in the correctformat. 703 */ 704 pieceToString(Piece piece)705 public String pieceToString(Piece piece){ 706 if (!(piece instanceof ChessPiece)) 707 throw new IllegalArgumentException("The piece must be an instance of ChessPiece."); 708 709 return chessPieceToString((ChessPiece)piece); 710 } 711 712 713 714 715 716 /** 717 * Calls <code>ChessPiece.toShortString()</code> to obtain a textual 718 * representation of the piece. 719 */ 720 chessPieceToString(ChessPiece piece)721 public static String chessPieceToString(ChessPiece piece){ 722 return piece.toShortString(); 723 } 724 725 726 727 728 /** 729 * Returns an instance of DefaultPiecePainter. 730 */ 731 createDefaultPiecePainter()732 public PiecePainter createDefaultPiecePainter(){ 733 return new DefaultPiecePainter(); 734 } 735 736 737 738 739 /** 740 * Returns an instance of DefaultBoardPainter. 741 */ 742 createDefaultBoardPainter()743 public BoardPainter createDefaultBoardPainter(){ 744 return new DefaultBoardPainter(); 745 } 746 747 748 749 750 /** 751 * Returns the name of this wild variant. 752 */ 753 getName()754 public String getName(){ 755 return variantName; 756 } 757 758 759 760 761 /** 762 * Returns a textual representation of this wild variant. 763 */ 764 toString()765 public String toString(){ 766 return getName(); 767 } 768 769 770 771 } 772