package com.editev.chess;
import com.editev.util.Lists;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import com.editev.chess.piece.Pawn;
/** A GameHistory is a GameMoves with a history of previous moves.
*
* @see See the source here.
*/
public class GameHistory extends GameMoves {
/** Number of moves in a long game.
* Nearly all games should be shorter than this length for best performance.
*/
public static final int A_LONG_GAME = 127;
/** A list of the moves already applied. */
public final Moves moveHistory = new Moves( A_LONG_GAME );
/** A list of the move indices already applied. */
public final Lists.Shorts moveIndices = new Lists.Shorts( A_LONG_GAME );
/** Lists of the pieces captured by White. */
public final Lists.Bytes whiteCaptures = new Lists.Bytes( 15 );
/** Lists of the pieces captured by Black. */
public final Lists.Bytes blackCaptures = new Lists.Bytes( 15 );
/** Get the list of pieces captured by this color. */
public Lists.Bytes getCaptured( boolean isWhite ) { return isWhite ? whiteCaptures : blackCaptures; }
/** Add a piece to the list of captured pieces */
public void capture( byte piece, boolean isWhite ) {
if (piece == NO_PIECE) return;
if (piece == Pawn.EP_CAPTURE) { // just mark en passant captures as a pawn capture.
piece = isWhite ? Black.PAWN : White.PAWN;
}
getCaptured( isWhite ).append( piece );
}
/** Apply a specific move to this Game and add it to the history!
*
* @return the index of the captured piece, if any (special case for ep).
* @see com.editev.chess.Game. */
public byte applyMove( Move move ) {
moveHistory.append( move );
byte captured = super.applyMove( move ); // apply the move.
capture( captured, isWhiteMove() );
return captured;
}
/** Apply a move by index to this board.
*
* @return the index of the captured piece, if any (special case for ep).
* @param move index of the move to apply.
*/
public byte applyMove( short move ) {
moveIndices.append( move );
return applyMove( getMove( move ) ); // find the move and apply it.
}
/** Separates move in a Move description string. */
public final static String SEPARATOR = "/";
/** Apply a whole list of moves to this game.
*
* @param moves slash-deliniated string listing the moves to apply to this game.
*/
public void applyMoves( String moveString ) {
StringTokenizer st = new StringTokenizer( moveString, SEPARATOR ); // break the moves up into strings
short m;
while (st.hasMoreTokens()) {
try { m = Short.parseShort( st.nextToken() ); } // try to get a index
catch (Exception e) { continue; } // skip to the next token
try { applyMove( m ); } // perform the move at that index.
catch (Exception e) { return; }
}
}
/** Pick a move at random from all the legal moves and apply it.
*
* @return true if there were any legal moves from this position.
*/
public boolean moveRandomly() {
if (getMoveCount() == 0) return false; // no more moves, return false.
short index = (short) (Math.random() * getMoveCount()); // select a move at random.
applyMove( index ); // apply it
return true; // made a move, return true.
}
public String getMoveString() {
if (moves == 0) return "";
StringBuffer moveString = new StringBuffer();
moveString.append( moveIndices.getAt( 0 ) );
for (short i=1; i