package com.editev.chess; import com.editev.util.Filter; import com.editev.util.Function; import com.editev.util.Enum; import com.editev.chess.piece.Piece; import java.util.Enumeration; /** A Game that can enumerate its legal Moves. * * @see See the source here. */ public class Game extends GameState { /** @return true if this move is illegal for this Game. * Checks a move for legality for this Game. * * @param move the move to check for legality. */ public boolean isIllegal( Move move ) { //if (isStalemate) return true; // all moves are invalid after a stalemate if (!move.target.isValid()) return true; // don't even consider invalid moves. byte fromPiece = getPieceIndex( move ); // piece on the start square byte toPiece = getPieceIndex( move.target ); // piece on the end square Piece piece = getPiece( move ); return !canMove( fromPiece ) // moving opponent's piece || canMove( toPiece ) // capturing your own piece || piece.pieceBetween( move, this ) // moving over pieces || piece.isIllegal( move, this ) // piece rules: castling, check, promotion. || resultsInCheck( move, piece ); // moving into check } /** apply a Move to the Game -- in other words, to the board and to the game.

* * @return the index of the captured piece, if any (special case for ep). * @param sq the Move to apply. */ public byte applyMove( Move move ) { Piece piece = getPiece( move.source ); // get the Piece from the Board. if (piece.isIrreversible( move, this )) { // Irreversible moves let us clear out the history list. irreversibleMove(); //history.clear(); } else { //history.append( this ); // remember this board position } byte captured = piece.applyMoveToBoard( move, this ); piece.applyMoveToState( move, this ); //if (getReversibleMoves() > 50 || thirdTime()) isStalemate = true; return captured; } /** Enumeration of every legal move for this Game. * Don't change the game in the middle of getting the enumeration or this might not work. * @return a new Enumeration of all legal moves for this game. */ public Enumeration enumerateAllLegalMoves() { return new Enum.Filtered( new AcceptLegalMoves(), // filter accepts only legal moves.. new Enum.Compound( // for each legal move for each piece. new Enum.Mapped( new MakePieceMoveEnumerator(), // map Pieces to a list of moves for that Piece. new Enum.Filtered( new AcceptOnTheMove(), // filter accepts only pieces that are on-the move new Move().getEnumeration() // for each square on the board, ) ) ) ); } /** An enumeration of all Moves for the piece in the Move. */ class PieceMoveEnumerator extends Enum.Lookahead { /** The Piece that's doing the moving. */ public final Piece piece; /** The Move that's being enumerated. */ public final Move move; /** Create the iterator starting with a Move. */ public PieceMoveEnumerator( Move move ) { this.move = move; this.piece = getPiece( move ); // get the Piece for this move. next = move; piece.firstMoveIndex( move ); } /** Retrieve the next move (legal or not!) * @see com.editev.util.Enum.Lookahead. */ protected void next() { next = piece.incrementMoveIndex( move ) ? move : null; } } /** Constructs a list of Piece moves from a Square. */ class MakePieceMoveEnumerator implements Function { /** Create a new emumeration of the Pieces * @return an enumeration of moves for the piece moving. * @param discard ignore this: we look at the central iterator Move. */ public Object eval( Object move ) { return new PieceMoveEnumerator( (Move) move ); } }; /** A class only accept legal moves. */ class AcceptLegalMoves implements Filter { /** @param move a move to check for legality. * @return true if the Move is legal.*/ public boolean accept( Object move ) { return !isIllegal( (Move) move ); } }; /** Only accepts Squares containing pieces that are on-the-move. */ class AcceptOnTheMove implements Filter { /** @param move a move which might have a Piece. * * @return true if the source of the Move contains a Piece and that Piece is on-the-move. */ public boolean accept( Object move ) { byte piece = getPieceIndex( (Move) move ); return piece != NO_PIECE && isWhiteMove() == White.is( piece ); } } /** Is this board position appearing for the third time? */ /* public boolean thirdTime() { boolean first=false; for (int i=history.getLength()-1; i>=0; i--) { if (history.getAt( i ).equals( this )) { if (first) return true; // found the second dupe of this board. first = true; // found the first dupe. } } return false; } */ }