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.