Computer Chess Club Archives


Search

Terms

Messages

Subject: On Beowulf - long post

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.