Code:
/* BoardDevice.cpp
* V0.1.0 Written by Daniel Jeremiah O'Neill.
* This version compleated at 3:20AM GMT+10 Wednesday 5th May 2010.
* Functions as a chess board with any legal chess pieces on it, does no error
* checking, any configuration is possible, multiple kings per side, more than
* 8 pawns, etc... Allows a variety of manipulative functions, as well as
* a usefull generate hash function, by which a board may be stored or
* identified.
*/
#include "BoardDevice.h"
/* BoardDevice::Clear()
* Places the board in a state of null. There are no pieces on the board in this
* state, the castling flags are set to false, that is, castling is turned off,
* and the en'Passant pawn is set to cleared - no en'Passant phantom.
* Further more, it wipes the board hash data clean, setting all values there
* to null as well.
*/
void BoardDevice::Clear()
{
BoardDevice::WhitePawns=BoardDevice::BlackPawns=0ULL;
BoardDevice::WhiteKnights=BoardDevice::BlackKnights=0ULL;
BoardDevice::WhiteBishops=BoardDevice::BlackBishops=0ULL;
BoardDevice::WhiteRooks=BoardDevice::BlackRooks=0ULL;
BoardDevice::WhiteQueens=BoardDevice::BlackQueens=0ULL;
BoardDevice::WhiteKing=BoardDevice::BlackKing=0ULL;
BoardDevice::WhitePieces=BoardDevice::BlackPieces=0ULL;
BoardDevice::EnPassantPhantomPawn=BoardDevice::CastlingFlags=0;
for (int i=0;i<34;i++) BoardDevice::BoardHash[i]=0;
}
/* BoardDevice::Destroy()
* For the destruction of this class only! Destroys the only array in memory,
* that is the board hash data.
*/
void BoardDevice::Destroy()
{
delete[] &BoardHash;
}
/* BoardDevice::Reset()
* Resets the board and places it into a new game configuration. 8 pawns are
* places along the rank that is one square in from the current colors side,
* rooks are placed in all corners, knights next to them, bishops next to
* knights, a king on the right, and a queen on the left of the two vacant
* squares that remain. The castling flags are set to 1111, all true, that
* is, all castle moves, short and long for both colors, are enabled, the
* en'Passant phantom pawn is set to cleared - no en'Passant phnatom.
* When this is done, Reset() returns a true value in the bool.
*/
bool BoardDevice::Reset()
{
BoardDevice::WhitePawns=65280ULL;
BoardDevice::WhiteKnights=66ULL;
BoardDevice::WhiteBishops=36ULL;
BoardDevice::WhiteRooks=129ULL;
BoardDevice::WhiteQueens=16ULL;
BoardDevice::WhiteKing=8ULL;
BoardDevice::WhitePieces=65535ULL;
BoardDevice::BlackPawns=71776119061217280ULL;
BoardDevice::BlackKnights=4755801206503243776ULL;
BoardDevice::BlackBishops=2594073385365405696ULL;
BoardDevice::BlackRooks=9295429630892703744ULL;
BoardDevice::BlackQueens=1152921504606846976ULL;
BoardDevice::BlackKing=576460752303423488ULL;
BoardDevice::BlackPieces=18446462598732840960ULL;
BoardDevice::CastlingFlags=15;
BoardDevice::EnPassantPhantomPawn=0;
return true;
}
/* BoardDevice::TestPiece(unsigned char Square, unsigned char PieceType)
* Tests square 'Square' to see if piece 'PieceType' is present, returns
* true if it is, or false, indicating it is not, false may also indicate
* that the input values are out of range, Square must be between 0 and
* 63, while PieceType is shown on the table below.
* +--------+--------------------------------------------------------------+
* | Value | Piece Type |
* +--------+--------------------------------------------------------------+
* | 0 | White Pawn |
* | 1 | White Knight |
* | 2 | White Bishop |
* | 3 | White Rook |
* | 4 | White Queen |
* | 5 | White King |
* | 6 | White Piece |
* | 7 | Black Pawn |
* | 8 | Black Knight |
* | 9 | Black Bishop |
* | 10 | Black Rook |
* | 11 | Black Queen |
* | 12 | Black King |
* | 13 | Black Piece |
* +--------+--------------------------------------------------------------+
*/
bool BoardDevice::TestPiece(unsigned char Square, unsigned char PieceType)
{
switch(PieceType)
{
case 0:
if ((BoardDevice::WhitePawns&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 1:
if ((BoardDevice::WhiteKnights&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 2:
if ((BoardDevice::WhiteBishops&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 3:
if ((BoardDevice::WhiteRooks&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 4:
if ((BoardDevice::WhiteQueens&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 5:
if ((BoardDevice::WhiteKing&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 6:
if ((BoardDevice::WhitePieces&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 7:
if ((BoardDevice::BlackPawns&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 8:
if ((BoardDevice::BlackKnights&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 9:
if ((BoardDevice::BlackBishops&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 10:
if ((BoardDevice::BlackRooks&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 11:
if ((BoardDevice::BlackQueens&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 12:
if ((BoardDevice::BlackKing&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
case 13:
if ((BoardDevice::BlackPieces&BoardDevice::GetSquareBit(Square))!=0)
return true;
else
return false;
default:
return false;
}
}
/* BoardDevice::RemovePiece(unsigned char Square, unsigned char PieceType)
* Removes a valid piece from the board, the piece must exist to be removed,
* if it does not, RemovePiece(unsigned char Square, unsigned char PieceType)
* returns a false value, indicating an error. After checking the input
* variables for faults, the function attempts to alter data, after which it
* returns true - success.
* Square is a value between 0 and 63, any value outside this range will
* cause the function to return false.
* PieceType can be any of the values listed on the table below, any other
* value will return false, indicating an error, no piece will be removed.
* +--------+--------------------------------------------------------------+
* | Value | Piece Type |
* +--------+--------------------------------------------------------------+
* | 0 | White Pawn |
* | 1 | White Knight |
* | 2 | White Bishop |
* | 3 | White Rook |
* | 4 | White Queen |
* | 5 | White King |
* | 6 | White Piece (Unused, trying to use this value will cause the |
* | | function to return false, indicating an error, no piece will |
* | | be removed. |
* | 7 | Black Pawn |
* | 8 | Black Knight |
* | 9 | Black Bishop |
* | 10 | Black Rook |
* | 11 | Black Queen |
* | 12 | Black King |
* | 13 | Black Piece (Unused, trying to use this value will cause the |
* | | function to return false, indicating an error, no piece will |
* | | be removed. |
* +--------+--------------------------------------------------------------+
*/
bool BoardDevice::RemovePiece(unsigned char Square, unsigned char PieceType)
{
if (Square>63) return false;
switch (PieceType)
{
case 0:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhitePawns&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 1:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhiteKnights&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 2:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhiteBishops&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 3:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhiteRooks&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 4:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhiteQueens&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 5:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::WhiteKing&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::WhitePieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 7:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackPawns&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 8:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackKnights&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 9:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackBishops&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 10:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackRooks&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 11:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackQueens&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
case 12:
if (!BoardDevice::TestPiece(Square, PieceType)) return false;
BoardDevice::BlackKing&=BoardDevice::GetInvertedSquareBit(Square);
BoardDevice::BlackPieces&=BoardDevice::GetInvertedSquareBit(Square);
break;
default:
return false;
}
return true;
}
/* BoardDevice::PlacePiece(unsigned char Square, unsigned char PieceType)
* Places a valid piece on the board, the square must be empty for the piece
* to be placed, if it is not, PlacePiece(unsigned char Square, unsigned
* char PieceType) returns a false value, indicating an error. After
* checking input values for faults, the function attempts to alter data,
* adter which it reutrns true - success.
* Square is a value between 0 and 63, any value outside this range will
* cause the function to return false.
* PieceType can be any of the values listed on the table below, any other
* value will return false, indicating an error, no piece will be removed.
* +--------+--------------------------------------------------------------+
* | Value | Piece Type |
* +--------+--------------------------------------------------------------+
* | 0 | White Pawn |
* | 1 | White Knight |
* | 2 | White Bishop |
* | 3 | White Rook |
* | 4 | White Queen |
* | 5 | White King |
* | 6 | White Piece (Unused, trying to use this value will cause the |
* | | function to return false, indicating an error, no piece will |
* | | be removed. |
* | 7 | Black Pawn |
* | 8 | Black Knight |
* | 9 | Black Bishop |
* | 10 | Black Rook |
* | 11 | Black Queen |
* | 12 | Black King |
* | 13 | Black Piece (Unused, trying to use this value will cause the |
* | | function to return false, indicating an error, no piece will |
* | | be removed. |
* +--------+--------------------------------------------------------------+
*/
bool BoardDevice::PlacePiece(unsigned char Square, unsigned char PieceType)
{
if (Square>64) return false;
switch (PieceType)
{
case 0:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhitePawns|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 1:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhiteKnights|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 2:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhiteBishops|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 3:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhiteRooks|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 4:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhiteQueens|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 5:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::WhiteKing|=BoardDevice::GetSquareBit(Square);
BoardDevice::WhitePieces|=BoardDevice::GetSquareBit(Square);
break;
case 7:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackPawns|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
case 8:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackKnights|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
case 9:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackBishops|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
case 10:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackRooks|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
case 11:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackQueens|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
case 12:
if (BoardDevice::TestPiece(Square,6)|BoardDevice::TestPiece(Square,13)) return false;
BoardDevice::BlackKing|=BoardDevice::GetSquareBit(Square);
BoardDevice::BlackPieces|=BoardDevice::GetSquareBit(Square);
break;
default:
return false;
}
return true;
}
/* BoardDevice::GetCastlingFlags()
* Returns a value between 0000 and 1111, these flags in order from left to
* right indicate the following castle moves are available if the flag is 1.
* Black Long(Queen Side) Castle
* Black Short(King Side) Castle
* White Long(Queen Side) Castle
* White Short(King Side) Castle
*/
unsigned char BoardDevice::GetCastlingFlags()
{
return BoardDevice::CastlingFlags;
}
/* BoardDevice::GetPhantomPawnInfo()
* Returns a value of 0 in bit 7 if no en'Passant phantom pawn is present,
* otherwise, if bit 7 is set to 1, bits 0-6 contain a value between 0 and
* 63 indicating the square upon which it is preent. Optionally, and
* uneeded, bit 8 may be set to 1 if the pawn is black, and 0 if the pawn
* is white.
*/
unsigned char BoardDevice::GetPhantomPawnInfo()
{
return BoardDevice::EnPassantPhantomPawn;
}
/* BoardDevice::GetSquareBit(unsigned char Square)
* Accepts a value between 0 and 63 indicating a sqaure on the chess board,
* returns a value of 2 to the power of Square, or 0 on error.
*/
unsigned long long BoardDevice::GetSquareBit(unsigned char Square)
{
if (Square>63) return 0ULL;
return 1ULL<<Square;
}
/* BoardDevice::GetInvertedSquareBit(unsigned char Square)
* Accepts a value between 0 and 63 indicating a sqaure on the chess board,
* similar to GetSquareBit(unsigned char Square) this function returns a
* a value where the flag is turned off, and all other flags are on.
*/
unsigned long long BoardDevice::GetInvertedSquareBit(unsigned char Square)
{
if (Square>63) return 18446744073709551615ULL;
return 18446744073709551615ULL-(1ULL<<Square);
}
/* BoardDevice::GetBitBoard(unsigned char PieceType)
* This function returns a value of zero if the PieceType is out of range,
* otherwise, it returns the associated BitBoard as shown on the table
* below. The BitBoard contains a 0 flag when the square does not contain
* a piece of the asociated type, and a 1 flag when it does.
* +--------+--------------------------------------------------------------+
* | Value | Piece Type |
* +--------+--------------------------------------------------------------+
* | 0 | White Pawn |
* | 1 | White Knight |
* | 2 | White Bishop |
* | 3 | White Rook |
* | 4 | White Queen |
* | 5 | White King |
* | 6 | White Piece |
* | 7 | Black Pawn |
* | 8 | Black Knight |
* | 9 | Black Bishop |
* | 10 | Black Rook |
* | 11 | Black Queen |
* | 12 | Black King |
* | 13 | Black Piece |
* +--------+--------------------------------------------------------------+
*/
unsigned long long BoardDevice::GetBitBoard(unsigned char PieceType)
{
switch (PieceType)
{
case 0:
return BoardDevice::WhitePawns;
case 1:
return BoardDevice::WhiteKnights;
case 2:
return BoardDevice::WhiteBishops;
case 3:
return BoardDevice::WhiteRooks;
case 4:
return BoardDevice::WhiteQueens;
case 5:
return BoardDevice::WhiteKing;
case 6:
return BoardDevice::WhitePieces;
case 7:
return BoardDevice::BlackPawns;
case 8:
return BoardDevice::BlackKnights;
case 9:
return BoardDevice::BlackBishops;
case 10:
return BoardDevice::BlackRooks;
case 11:
return BoardDevice::BlackQueens;
case 12:
return BoardDevice::BlackKing;
case 13:
return BoardDevice::BlackPieces;
default:
return 0ULL;
}
}
/* BoardDevice::GetBoardHash()
* Returns a 34 byte hash indicating the current state of the board.
* This hash functions as an ID for the current board state, only one
* such value can exist per board configuration.
*/
unsigned char* BoardDevice::GetBoardHash()
{
for (unsigned char i=0;i<64;i++) BoardDevice::BoardHash[i]=0;
for (unsigned char i=0;i<32;i++)
{
if (BoardDevice::TestPiece(i*2,0)) BoardDevice::BoardHash[i]|=1;
if (BoardDevice::TestPiece(i*2+1,0)) BoardDevice::BoardHash[i]|=16;
if (BoardDevice::TestPiece(i*2,1)) BoardDevice::BoardHash[i]|=2;
if (BoardDevice::TestPiece(i*2+1,1)) BoardDevice::BoardHash[i]|=32;
if (BoardDevice::TestPiece(i*2,2)) BoardDevice::BoardHash[i]|=3;
if (BoardDevice::TestPiece(i*2+1,2)) BoardDevice::BoardHash[i]|=48;
if (BoardDevice::TestPiece(i*2,3)) BoardDevice::BoardHash[i]|=4;
if (BoardDevice::TestPiece(i*2+1,3)) BoardDevice::BoardHash[i]|=64;
if (BoardDevice::TestPiece(i*2,4)) BoardDevice::BoardHash[i]|=5;
if (BoardDevice::TestPiece(i*2+1,4)) BoardDevice::BoardHash[i]|=80;
if (BoardDevice::TestPiece(i*2,5)) BoardDevice::BoardHash[i]|=6;
if (BoardDevice::TestPiece(i*2+1,5)) BoardDevice::BoardHash[i]|=96;
if (BoardDevice::TestPiece(i*2,7)) BoardDevice::BoardHash[i]|=8;
if (BoardDevice::TestPiece(i*2+1,7)) BoardDevice::BoardHash[i]|=128;
if (BoardDevice::TestPiece(i*2,8)) BoardDevice::BoardHash[i]|=9;
if (BoardDevice::TestPiece(i*2+1,8)) BoardDevice::BoardHash[i]|=144;
if (BoardDevice::TestPiece(i*2,9)) BoardDevice::BoardHash[i]|=10;
if (BoardDevice::TestPiece(i*2+1,9)) BoardDevice::BoardHash[i]|=160;
if (BoardDevice::TestPiece(i*2,10)) BoardDevice::BoardHash[i]|=11;
if (BoardDevice::TestPiece(i*2+1,10)) BoardDevice::BoardHash[i]|=176;
if (BoardDevice::TestPiece(i*2,11)) BoardDevice::BoardHash[i]|=12;
if (BoardDevice::TestPiece(i*2+1,11)) BoardDevice::BoardHash[i]|=192;
if (BoardDevice::TestPiece(i*2,12)) BoardDevice::BoardHash[i]|=13;
if (BoardDevice::TestPiece(i*2+1,12)) BoardDevice::BoardHash[i]|=208;
}
BoardHash[32]=BoardDevice::GetCastlingFlags();
BoardHash[33]=BoardDevice::GetPhantomPawnInfo();
return BoardHash;
}
/* ToDo: Add a function that allows a Board to be setup from a hash value.
*/
EDIT:I know its not perfect, like the testpiece() function could have break; instead of elses, with a final return false at the end, but I'm still working on this