Author: Vincent Diepeveen
Date: 05:56:05 06/05/01
Hello,
Of course giving comments is easily, so i coudln't resist giving
some comment.
If you teach someone to learn how to setup a chessprogram,
i would expect not very fast code, but at least i would expect
EFFICIENTLY programmed things.
Let's compare the old gnuchess 4.x code, i still have it here
for those who want to rip the move generator out of it:
for (i = PieceCnt[side]; i >= 0; i--)
GenMoves (ply, PieceList[side][i], side, xside);
So for all pieces of 1 side it generates the moves.
Now i'm not a fan of using 8 bits arrays, and the SHORT defines
definitely are outdated with nowadays 32 bits processors too (short int
used to be a 16 bits integer).
However, see the code below:
though you can speed this up bigtime (at least a factor 2) at
nowadays processors and definitely make it look a lot better,
it's very nice code to read when i later compare it to what i see
in BEOWULF
inline
void
GenMoves (register SHORT ply, register SHORT sq, SHORT side, SHORT xside)
/*
* Generate moves for a piece. The moves are taken from the precalulated
* array nextpos/nextdir. If the board is free, next move is choosen from
* nextpos else from nextdir.
*/
{
register SHORT u, piece;
register UCHAR *ppos, *pdir;
TrP = &TrPnt[ply + 1];
piece = board[sq];
if (piece == pawn)
{
ppos = nextpos[ptype[side][piece]][sq];
pdir = nextdir[ptype[side][piece]][sq];
u = ppos[sq]; /* follow no captures thread */
if (color[u] == neutral)
{
LinkMove (ply, sq, u, 0, xside);
u = ppos[u];
if (color[u] == neutral)
LinkMove (ply, sq, u, 0, xside);
}
u = pdir[sq]; /* follow captures thread */
if (color[u] == xside /*&& board[u] != king*/)
{
LinkMove (ply, sq, u, capture, xside);
}
u = pdir[u];
if (color[u] == xside /*&& board[u] != king*/)
{
LinkMove (ply, sq, u, capture, xside);
}
}
else
{
ppos = nextpos[piece][sq];
pdir = nextdir[piece][sq];
u = ppos[sq];
do
{
if (color[u] == neutral)
{
LinkMove (ply, sq, u, 0, xside);
u = ppos[u];
}
else
{
if (color[u] == xside /*&& board[u] != king*/)
{
LinkMove (ply, sq, u, capture, xside);
}
u = pdir[u];
}
}
while (u != sq);
}
}
Now see what i get in beowulf. Instead of that in 2001 dudes program
better they program things out FOR EVERY PIECE.
Even blackpawns and whitepawns are written out.
Man such a student i would directly ship back.
"Please make the code more general student, if you multiply a 2048 x 2048
array you don't write out every multiplication either!".
See here below the horror which i found in moves.c from beowulf project.
How do you plan to let people learn from this code?
They must learn to "write everything out"??
Please use a few for loops, even in bitboards you can do that,
or have you forgotten how loops work?
MOVE *GenerateMoves(const Board * B, const int side, MOVE * movelist)
{
int to,
from,
i;
MOVE tempmove;
BITBOARD tsq = 0,
temp,
mask;
/* Generate moves for white pawns first */
if (side == WHITE) {
/* Promotions */
tsq = ((B->WhitePawns >> 8) & FullRank) & ~(B->All);
while (tsq) {
to = FirstPiece(tsq);
from = to + 8;
tempmove = from + (to << 6);
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
RemoveFirst(tsq);
}
/* Captures (including En-Passant) */
tsq = (((B->WhitePawns & ~(FileMask[FileH])) >> 7) | ((B->WhitePawns &
~(FileMask[FileA])) >> 9));
if (B->ep >= 0)
tsq &= (B->BlackPieces | Mask[B->ep]);
else
tsq &= B->BlackPieces;
while (tsq) {
to = FirstPiece(tsq);
if (File(to) > 0) {
from = to + 7;
if (B->WhitePawns & Mask[from]) {
tempmove = from + (to << 6);
if (Rank(to) == 0)
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
else {
/* Check for en-passant move */
if (!(B->BlackPieces & Mask[to]))
tempmove += (1 << 16);
/* Store move */
*movelist++ = tempmove;
}
}
}
if (File(to) < 7) {
from = to + 9;
if (B->WhitePawns & Mask[from]) {
tempmove = from + (to << 6);
if (Rank(to) == 0)
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
else {
/* Check for en-passant move */
if (!(B->BlackPieces & Mask[to]))
tempmove += (1 << 16);
/* Store move */
*movelist++ = tempmove;
}
}
}
RemoveFirst(tsq);
}
/* Pushes */
/* One rank pushes */
tsq = (B->WhitePawns >> 8) & ~(B->All);
tsq &= ~RankMask[Rank8];
/* Two rank initial pushes */
temp = (((B->WhitePawns & RankMask[Rank2]) >> 16) & ~(B->All));
/* Ensure that the 'step-over' square is empty too! */
temp &= ~(B->All >> 8);
/* Add them on */
tsq |= temp;
while (tsq) {
to = FirstPiece(tsq);
if (B->WhitePawns & Mask[to + 8])
from = to + 8;
else
from = to + 16;
*movelist++ = from + (to << 6);
RemoveFirst(tsq);
}
}
/* ... or black pawns */
if (side == BLACK) {
/* Promotions */
tsq = ((B->BlackPawns << 8) & RankMask[Rank1]) & ~(B->All);
while (tsq) {
to = FirstPiece(tsq);
from = to - 8;
tempmove = from + (to << 6);
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
RemoveFirst(tsq);
}
/* Captures (including En-Passant) */
tsq = (((B->BlackPawns & ~(FileMask[FileH])) << 9) | ((B->BlackPawns &
~(FileMask[FileA])) << 7));
if (B->ep >= 0)
tsq &= (B->WhitePieces | Mask[B->ep]);
else
tsq &= B->WhitePieces;
while (tsq) {
to = FirstPiece(tsq);
if (File(to) > 0) {
from = to - 9;
if (B->BlackPawns & Mask[from]) {
tempmove = from + (to << 6);
if (Rank(to) == 7)
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
else {
/* Check for en-passant move */
if (to == B->ep)
tempmove += (1 << 16);
/* Store move */
*movelist++ = tempmove;
}
}
}
if (File(to) < 7) {
from = to - 7;
if (B->BlackPawns & Mask[from]) {
tempmove = from + (to << 6);
if (Rank(to) == 7)
for (i = 1; i < 5; i++)
*movelist++ = (tempmove + (i << 12));
else {
/* Check for en-passant move */
if (to == B->ep)
tempmove += (1 << 16);
/* Store move */
*movelist++ = tempmove;
}
}
}
RemoveFirst(tsq);
}
/* Pushes */
/* One rank pushes */
tsq = (B->BlackPawns << 8) & ~(B->All);
tsq &= ~RankMask[Rank1];
/* Two rank initial pushes */
temp = (((B->BlackPawns & RankMask[Rank7]) << 16) & ~(B->All));
/* Ensure that the 'step-over' square is empty too! */
temp &= ~(B->All << 8);
/* Add them on */
tsq |= temp;
while (tsq) {
to = FirstPiece(tsq);
if (B->BlackPawns & Mask[to - 8])
from = to - 8;
else
from = to - 16;
*movelist++ = from + (to << 6);
RemoveFirst(tsq);
}
}
/* Now Generate King Moves */
if (side == WHITE) {
from = B->WhiteKing;
tsq = KingMoves[from] & ~(B->WhitePieces);
} else {
from = B->BlackKing;
tsq = KingMoves[from] & ~(B->BlackPieces);
}
/* tsq holds a board of all possible target squares */
while (tsq) {
to = FirstPiece(tsq);
*movelist++ = from + (to << 6);
RemoveFirst(tsq);
}
/* Now Generate Knight Moves */
if (side == WHITE)
tsq = B->WhiteKnights;
else
tsq = B->BlackKnights;
/* tsq holds a board of all possible knights */
while (tsq) {
from = FirstPiece(tsq);
if (side == WHITE)
temp = KnightMoves[from] & ~(B->WhitePieces);
else
temp = KnightMoves[from] & ~(B->BlackPieces);
/* temp holds a board of all possible target squares for this knight */
while (temp) {
to = FirstPiece(temp);
*movelist++ = from + (to << 6);
RemoveFirst(temp);
}
RemoveFirst(tsq);
}
/* Now Generate Rook Moves */
if (side == WHITE)
tsq = B->WhiteRooks;
else
tsq = B->BlackRooks;
/* tsq now holds a board of all rooks */
while (tsq) {
from = FirstPiece(tsq);
/* First generate horizontal moves */
mask = (B->All >> (Rank(from) << 3)) & FullRank;
temp = MovesRank[from][mask];
/* Nextt generate vertical moves */
mask = (B->R90 >> (File(from) << 3)) & FullRank;
temp |= MovesFile[from][mask];
if (side == WHITE)
temp &= ~(B->WhitePieces);
else
temp &= ~(B->BlackPieces);
/* temp holds a board of all possible target squares */
while (temp) {
to = FirstPiece(temp);
*movelist++ = from + (to << 6);
RemoveFirst(temp);
}
RemoveFirst(tsq);
}
/* Now Generate Bishop Moves See above for comments, or look at my
* webpage http://www.ast.cam.ac.uk/~cmf/chess/theory.html */
if (side == WHITE)
tsq = B->WhiteBishops;
else
tsq = B->BlackBishops;
while (tsq) {
from = FirstPiece(tsq);
mask = ((B->R45 >> DiagShifts_a1h8[from]) & DiagonalMask_a1h8[from]);
temp = Movesa1h8[from][mask];
mask = ((B->L45 >> DiagShifts_a8h1[from]) & DiagonalMask_a8h1[from]);
temp |= Movesa8h1[from][mask];
if (side == WHITE)
temp &= ~(B->WhitePieces);
else
temp &= ~(B->BlackPieces);
while (temp) {
to = FirstPiece(temp);
*movelist++ = from + (to << 6);
RemoveFirst(temp);
}
RemoveFirst(tsq);
}
/* Now Generate Queen Moves */
if (side == WHITE)
tsq = B->WhiteQueens;
else
tsq = B->BlackQueens;
while (tsq) {
from = FirstPiece(tsq);
mask = ((B->R45 >> DiagShifts_a1h8[from]) & DiagonalMask_a1h8[from]);
temp = Movesa1h8[from][mask];
mask = ((B->L45 >> DiagShifts_a8h1[from]) & DiagonalMask_a8h1[from]);
temp |= Movesa8h1[from][mask];
mask = (B->All & RankMask[(Rank(from))]) >> (Rank(from) << 3);
temp |= MovesRank[from][mask];
mask = (B->R90 & RankMask[(File(from))]) >> (File(from) << 3);
temp |= MovesFile[from][mask];
if (side == WHITE)
temp &= ~(B->WhitePieces);
else
temp &= ~(B->BlackPieces);
while (temp) {
to = FirstPiece(temp);
*movelist++ = from + (to << 6);
RemoveFirst(temp);
}
RemoveFirst(tsq);
}
/* Generate Castling Moves */
if (side == WHITE) {
tempmove = (e1) + (1 << 15);
/* O-O */
if ((B->castle & 1) && B->pieces[h1] == wrook) {
mask = 96;
if (!(B->All & (mask << 56)))
*movelist++ = tempmove + (g1 << 6);
}
/* O-O-O */
if ((B->castle & 2) && B->pieces[a1] == wrook) {
mask = 14;
if (!(B->All & (mask << 56)))
*movelist++ = tempmove + (c1 << 6);
}
} else {
tempmove = (e8) + (1 << 15);
/* O-O */
if ((B->castle & 4) && B->pieces[h8] == brook) {
if (!(B->All & 96))
*movelist++ = tempmove + (g8 << 6);
}
/* O-O-O */
if ((B->castle & 8) && B->pieces[a8] == brook) {
if (!(B->All & 14))
*movelist++ = tempmove + (c8 << 6);
}
}
/* Return the last element so we know where we got up to in the move list
* i.e. how many moves there are to check */
return movelist;
}
This page took 0.02 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.