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