Version 0.1

===========
This is a first version where it is possible to play in console.
Rules are not implemented and program crashes when moving a piece that does not
exit or when trying to capture our own pieces...
This commit is contained in:
2006-01-07 16:38:45 +00:00
parent f61b6bb90d
commit 9cd26bfd0c
8 changed files with 818 additions and 0 deletions

View File

@ -0,0 +1,175 @@
package suicideChess;
import suicideChess.Square.NotAValidSquare;
/**
* @author djib
*
* This file contains the board representation.
* The board is represented using bitboards.
* a1 is square 0
* h8 is square 7
* a2 is square 8
* ... and so on
*
* $LastChangedDate$
* $LastChangedRevision$
* $LastChangedBy$
*/
public class Board {
/*************
* CONSTANTS *
*************/
//Some constants to make code more readable
public static final int NB_OF_RANKS = 8;
public static final int NB_OF_FILES = 8;
public static final int NB_OF_SQUARES = NB_OF_RANKS*NB_OF_FILES;
private static final int NB_OF_BITBOARDS = 14;
public class NoPieceOnSquare extends Exception {
/**
* Added by Eclipse
*/
private static final long serialVersionUID = -2750943856086117656L;
NoPieceOnSquare(String s) { super(s); };
}
/********
* DATA *
********/
//The following table is used to map squares to bits
protected static long mapSquaresToBits[];
//static function used to initialise data
static {
mapSquaresToBits = new long[NB_OF_SQUARES];
for(int i=0; i<NB_OF_SQUARES; i++) {
mapSquaresToBits[i] = (1L << i);
}
}
//The following table contains all the bit boards
protected long bitBoards[];
/***************
* CONSTRUCTOR *
* @throws NotAValidSquare
***************/
public Board() throws NotAValidSquare {
bitBoards = new long[NB_OF_BITBOARDS];
addPiece(new Square("a1"),new Piece(Piece.WHITE_ROOK));
addPiece(new Square("b1"),new Piece(Piece.WHITE_KNIGHT));
addPiece(new Square("c1"),new Piece(Piece.WHITE_BISHOP));
addPiece(new Square("d1"),new Piece(Piece.WHITE_QUEEN));
addPiece(new Square("e1"),new Piece(Piece.WHITE_KING));
addPiece(new Square("f1"),new Piece(Piece.WHITE_BISHOP));
addPiece(new Square("g1"),new Piece(Piece.WHITE_KNIGHT));
addPiece(new Square("h1"),new Piece(Piece.WHITE_ROOK));
addPiece(new Square("a2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("b2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("c2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("d2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("e2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("f2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("g2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("h2"),new Piece(Piece.WHITE_PAWN));
addPiece(new Square("a8"),new Piece(Piece.BLACK_ROOK));
addPiece(new Square("b8"),new Piece(Piece.BLACK_KNIGHT));
addPiece(new Square("c8"),new Piece(Piece.BLACK_BISHOP));
addPiece(new Square("d8"),new Piece(Piece.BLACK_QUEEN));
addPiece(new Square("e8"),new Piece(Piece.BLACK_KING));
addPiece(new Square("f8"),new Piece(Piece.BLACK_BISHOP));
addPiece(new Square("g8"),new Piece(Piece.BLACK_KNIGHT));
addPiece(new Square("h8"),new Piece(Piece.BLACK_ROOK));
addPiece(new Square("a7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("b7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("c7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("d7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("e7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("f7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("g7"),new Piece(Piece.BLACK_PAWN));
addPiece(new Square("h7"),new Piece(Piece.BLACK_PAWN));
}
/***********
* METHODS *
***********/
public void doMove(Move move) throws NoPieceOnSquare {
if (move.isCaptureMove()) {
removePiece(move.toSquare(), move.getCapturedPiece());
}
removePiece(move.fromSquare(), move.getMovingPiece());
if (move.isPromotionMove()) {
addPiece(move.toSquare(), move.getPromotionPiece());
} else {
addPiece(move.toSquare(), move.getMovingPiece());
}
}
/* private long getBitBoard(int bitboard_number) {
return bitBoards[bitboard_number];
}
*/
private int squareToBitBoardSquare(Square square) {
//converts a square ("e2") to a BitboardSquare (
return square.getFileNb() -1 + (square.getRank()-1)*NB_OF_FILES;
}
protected void addPiece(Square square, Piece piece) {
//OR :
// 0 OR a = a
// 1 OR a = 1
//add Piece to corresponding bitboard.
bitBoards[piece.getPieceNumber()] |= mapSquaresToBits[squareToBitBoardSquare(square)];
//update the bitboard of all pieces of that color
bitBoards[piece.getColor()] |= mapSquaresToBits[squareToBitBoardSquare(square)];
}
protected void removePiece(Square square, Piece piece) throws NoPieceOnSquare {
//XOR :
// 0 XOR a = a
// 1 XOR 0 = 1 !!! Don't remove a piece that don't exist !!!
// 1 XOR 1 = 0
//remove Piece to corresponding bitboard.
if (SuicideChess.BITBOARD_REMOVEPIECE_CHECK_REMOVE) {
if (checkIsNotEmpty(square, piece)) {
bitBoards[piece.getPieceNumber()] ^= mapSquaresToBits[squareToBitBoardSquare(square)];
} else {
throw new NoPieceOnSquare("Square: "+square + "; Piece: " + piece.getPieceNumber());
}
} else {
bitBoards[piece.getPieceNumber()] ^= mapSquaresToBits[squareToBitBoardSquare(square)];
}
//update the bitboard of all pieces of that color
bitBoards[piece.getColor()] ^= mapSquaresToBits[squareToBitBoardSquare(square)];;
}
//checks if a square is empty for a certain piece
private boolean checkIsNotEmpty(Square square, Piece piece) {
long mask = mapSquaresToBits[squareToBitBoardSquare(square)];
if ((bitBoards[piece.getPieceNumber()] & mask) == 0) {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,152 @@
package suicideChess;
import suicideChess.Square.NotAValidSquare;
/**
* @author djib
*
* This file contains the moves representation.
*
* $LastChangedDate$
* $LastChangedRevision$
* $LastChangedBy$
*/
public class Move {
/********
* DATA *
********/
//integers
private Piece movingPiece;
private Square fromSquare;
private Square toSquare;
private Piece promotionPiece;
private boolean isPromotion;
private boolean isCapture;
private Piece capturePiece;
public class NotAValidMoveException extends Exception {
/**
* Generated by Eclipse
*/
private static final long serialVersionUID = 2194133427162274651L;
NotAValidMoveException(String s) { super(s); };
}
/***************
* CONSTRUCTOR *
***************/
//The string is of type e2e4 (4 chars), b7b8q (5 chars) for promotions
//non capture move
public Move(String move, Piece pieceToMove) throws NotAValidMoveException, NotAValidSquare {
movingPiece = pieceToMove;
isPromotion = false;
isCapture = false;
switch (move.length()) {
case 5:
isPromotion = true;
promotionPiece = new Piece(move.toCharArray()[4], movingPiece.getColor());
//no break statement here on purpose
case 4:
fromSquare = new Square(move.substring(0,2));
toSquare = new Square(move.substring(2,4));
break;
default:
throw new NotAValidMoveException("Invalid Move: "+move);
}
}
//capture move
public Move(String move, Piece pieceToMove, Piece pieceToCapture) throws NotAValidMoveException, NotAValidSquare {
movingPiece = pieceToMove;
isPromotion = false;
isCapture = true;
capturePiece = pieceToCapture;
switch (move.length()) {
case 5:
isPromotion = true;
promotionPiece = new Piece(move.toCharArray()[4], movingPiece.getColor());
//no break statement here on purpose
case 4:
fromSquare = new Square(move.substring(0,2));
toSquare = new Square(move.substring(2,4));
break;
default:
throw new NotAValidMoveException("Invalid Move: "+move);
}
}
/***********
* METHODS *
***********/
public Square fromSquare() {
return fromSquare;
}
public Square toSquare() {
return toSquare;
}
public boolean isPromotionMove() {
return isPromotion;
}
public Piece getPromotionPiece() {
if (isPromotion) {
return promotionPiece;
} else {
return new Piece(Piece.NONE);
}
}
public Piece getMovingPiece() {
return movingPiece;
}
public boolean isCaptureMove() {
return isCapture;
}
public Piece getCapturedPiece() {
return capturePiece;
}
public String toString() {
return fromSquare.toString()+toSquare+promotionPiece;
}
/****************************************
* I do not use those functions anymore *
****************************************
public void setFromSquare(Square square) {
fromSquare = square;
}
public void setToSquare(Square square) {
toSquare = square;
}
public void setPromotionMove(String piece) {
if (piece.length()==0) {
isPromotion=false;
} else {
isPromotion=true;
promotionPiece=new Piece(piece);
}
}
public void setMovingPiece(Piece piece) {
movingPiece = piece;
}
*/
}

View File

@ -0,0 +1,111 @@
/**
*
*/
package suicideChess;
/**
* @author djib
*
* This file contains the moves representation.
*
* $LastChangedDate$
* $LastChangedRevision$
* $LastChangedBy$
*/
public class Piece {
/*************
* CONSTANTS *
*************/
/**
* Take really good care if you want to change those values
* Class BitBoard makes intensive use of those
*/
public static final int NONE=-1;
//Contants used to detect color
public static final int WHITE=0;
public static final int BLACK=1;
//Constants used in the board representation
public static final int WHITE_PIECE = WHITE;
public static final int BLACK_PIECE = BLACK;
public static final int PAWN = 2;
public static final int WHITE_PAWN = PAWN + WHITE;
public static final int BLACK_PAWN = PAWN + BLACK;
public static final int KING = 4;
public static final int WHITE_KING = KING + WHITE;
public static final int BLACK_KING = KING + BLACK;
public static final int QUEEN = 6;
public static final int WHITE_QUEEN = QUEEN + WHITE;
public static final int BLACK_QUEEN = QUEEN + BLACK;
public static final int BISHOP = 8;
public static final int WHITE_BISHOP = BISHOP + WHITE;
public static final int BLACK_BISHOP = BISHOP + BLACK;
public static final int KNIGHT = 10;
public static final int WHITE_KNIGHT = KNIGHT + WHITE;
public static final int BLACK_KNIGHT = KNIGHT + BLACK;
public static final int ROOK = 12;
public static final int WHITE_ROOK = ROOK + WHITE;
public static final int BLACK_ROOK = ROOK + BLACK;
//Constants used for promotion (as used in the xboard protocol)
public static final char KING_CHAR='k';
public static final char QUEEN_CHAR='q';
public static final char BISHOP_CHAR='b';
public static final char KNIGHT_CHAR='n';
public static final char ROOK_CHAR='r';
//may be useful
public static final char PAWN_CHAR='p';
/****************
* PRIVATE DATA *
****************/
private int pieceNumber;
/***************
* CONSTRUCTOR *
***************/
public Piece(int piece) {
pieceNumber = piece;
}
public Piece(char piece, int color) {
pieceNumber = NONE;
switch (piece) {
case PAWN_CHAR:
pieceNumber = PAWN + color;
break;
case KING_CHAR:
pieceNumber = KING + color;
break;
case QUEEN_CHAR:
pieceNumber = QUEEN + color;
break;
case BISHOP_CHAR:
pieceNumber = BISHOP + color;
break;
case KNIGHT_CHAR:
pieceNumber = KNIGHT + color;
break;
case ROOK_CHAR:
pieceNumber = ROOK + color;
break;
}
}
/***********
* METHODS *
***********/
public int getColor() {
return pieceNumber%2; //cf declaration of BLACK and WHITE above and the pieces above.
}
public int getPieceNumber() {
return pieceNumber;
}
}

View File

@ -0,0 +1,61 @@
package suicideChess;
/**
* @author djib
*
* This class avoids the use of strings for squares
*
* $LastChangedDate$
* $LastChangedRevision$
* $LastChangedBy$
*/
public class Square {
private char file;
private int fileNb;
private int rank;
public class NotAValidSquare extends Exception {
/**
* Generated by Eclipse
*/
private static final long serialVersionUID = 7586171991212094565L;
NotAValidSquare(String s) { super(s); };
}
public Square(String square) throws NotAValidSquare {
if (square.length()!=2 || !(Character.isLetter(square.toCharArray()[0])) ||
!(Character.isDigit(square.toCharArray()[1]))) {
throw new NotAValidSquare(square);
}
file = Character.toLowerCase(square.toCharArray()[0]);
fileNb = ((int)file) - ((int)'a') + 1;
rank = Integer.parseInt(square.substring(1,2));
//perform extra check ?
if (SuicideChess.SQUARE_CHECK_INVALID) {
if (fileNb<1 || fileNb>Board.NB_OF_FILES) {
throw new NotAValidSquare(square);
}
if (rank<1 || rank>Board.NB_OF_RANKS) {
throw new NotAValidSquare(square);
}
}
}
public char getFile() {
return file;
}
public int getRank() {
return rank;
}
public int getFileNb() {
return fileNb;
}
public String toString() {
return String.valueOf(file)+String.valueOf(rank);
}
}

View File

@ -0,0 +1,36 @@
package suicideChess;
import tests.TestMoves;
/**
* @author djib
*
* Main File
*
* $LastChangedDate$
* $LastChangedRevision$
* $LastChangedBy$
*/
public class SuicideChess {
/**
* Those flags are used to perform extra checks during the debugging of the
* program. They may be safely all set to false once the program is stable.
* It should improve performance a lot.
*/
//does BitBoard.class removePiece function checks if removing piece is legal ?
public static final boolean BITBOARD_REMOVEPIECE_CHECK_REMOVE = true;
//does Square.class checks if the strings are valid (is "z9" a valid square ?
public static final boolean SQUARE_CHECK_INVALID = true;
/*****************
* MAIN FUNCTION *
*****************/
public static void main(String[] args) {
TestMoves.main(args);
}
}