Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: A faster move generator than previously known

Author: Dann Corbit

Date: 23:31:03 08/08/03

Go up one level in this thread


On August 08, 2003 at 11:33:00, Thomas McBurney wrote:

>It's a shame I cannot understand C, otherwise this would be interesting to me.
>Maybe I should buy a book on C and learn the damn thing!  Maybe even write a
>competitive chess engine! :)  Anyway, my move generator (written in BASIC) uses
>pre calculated offsets for sliding pieces stored in an array.  Not sure if this
>is considered fast or not, but written in BASIC its guaranteed to be about 10
>times slower than one written in C.  Anyway, here's my move generator.  Have
>fun!
>
>
>SUB GENMOVES (DPTH%, CLR%, PSEUDO%)
>'*********************************************************************
>' GENERATE LIST OF MOVES AND STORE THEM IN MOVELIST(DEPTH,INFO,INDEX#)
>'
>' CLR%=0 - BLACK
>' CLR%=1 - WHITE
>'
>' PSEUDO=1 - ONLY RETURN PSEUDO LEGAL MOVES (FAST)
>' PSEDUO=0 - RETURN 100% LEGAL MOVES (SLOWER)
>'*********************************************************************
>
>MOVELIST(DPTH%, 0, 0) = 0
>
>FOR Y1% = 1 TO 8
>  FOR X1% = 1 TO 8
>    SQ% = ((Y1% * 10) + 10) + (X1% + 1)
>    IF BOARD(SQ%) < 0 AND CLR% = 0 THEN GOSUB PIECEMOVE
>    IF BOARD(SQ%) > 0 AND CLR% = 1 THEN GOSUB PIECEMOVE
>  NEXT
>NEXT
>
>EXIT SUB
>
>PIECEMOVE:
>
>PIECE% = ABS(BOARD(SQ%))
>IF PIECE% = 1 THEN
>  GOSUB PAWNMOVE
>  RETURN
>END IF
>
>STARTDIR% = RANGE(1, PIECE%)
>ENDDIR% = RANGE(2, PIECE%)
>MAXDIST% = 7
>IF PIECE% = 6 OR PIECE% = 2 THEN MAXDIST% = 1 ' king & knight only have max
>distance of 1
>
>SPECIAL% = 0
>
>FOR DIR% = STARTDIR% TO ENDDIR%
>  DIST% = 0
>  DO
>    DIST% = DIST% + 1
>    IF DIST% > MAXDIST% THEN EXIT DO
>    TOSQ% = MOVEGEN(SQ%, DIR%, DIST%)
>    IF TOSQ% = 0 THEN EXIT DO ' INDICATES MOVE OFF BOARD SO CHANGE DIR
>    IF SGN(BOARD(TOSQ%)) = SGN(BOARD(SQ%)) THEN EXIT DO' CHANGE DIR WHEN HIT
>FRIENDLY
>    GOSUB ADDMOVE
>    IF BOARD(TOSQ%) <> 0 THEN EXIT DO ' CHANGE DIRECTION AFTER CAPTURE OF ENEMY
>PIECE
>  LOOP
>NEXT
>
>IF PIECE% = 6 THEN GOSUB CASTLEMOVE
>
>RETURN
>
>ADDMOVE:
>
>IF PSEUDO% = 0 THEN ' verify legal move
>  CALL MAKEMOVE(SQ%, TOSQ%, SPECIAL%, DPTH%)
>  IF CLR% = 0 THEN ILLEGAL% = ATTACKSQ(BKING, 1)
>  IF CLR% = 1 THEN ILLEGAL% = ATTACKSQ(WKING, 0)
>  CALL UNMAKEMOVE(DEPTH)
>  IF ILLEGAL% = 1 THEN RETURN
>END IF
>
>R% = MOVELIST(DPTH%, 0, 0) + 1
>MOVELIST(DPTH%, 1, R%) = SQ%
>MOVELIST(DPTH%, 2, R%) = TOSQ%
>MOVELIST(DPTH%, 3, R%) = SPECIAL%
>MOVELIST(DPTH%, 4, R%) = ABS(BOARD(TOSQ%))
>MOVELIST(DPTH%, 0, 0) = R%
>
>RETURN
>
>PAWNMOVE:
>
>Y% = INT((SQ% - 10) / 10) ' CALCULATE Y COORDINATE
>SPECIAL% = 0
>
>IF BOARD(SQ%) = -1 THEN ' white pawn
>
>  ' MOVE ONE SQUARE FORWARD
>  IF BOARD(SQ% + 10) = 0 THEN TOSQ% = SQ% + 10: GOSUB ADDPAWN
>
>  'TAKE PIECE TO THE LEFT
>  IF BOARD(SQ% + 9) > 0 AND BOARD(SQ% + 9) < 100 THEN
>    TOSQ% = SQ% + 9: GOSUB ADDPAWN
>  END IF
>
>  'TAKE PIECE TO THE RIGHT
>  IF BOARD(SQ% + 11) > 0 AND BOARD(SQ% + 11) < 100 THEN
>    TOSQ% = SQ% + 11: GOSUB ADDPAWN
>  END IF
>
>  ' MOVE TWO SQUARES FORWARD FROM 2ND RANK
>  IF Y% = 2 THEN
>    IF BOARD(SQ% + 10) = 0 AND BOARD(SQ% + 20) = 0 THEN
>      TOSQ% = SQ% + 20
>      GOSUB ADDMOVE
>    END IF
>  END IF
>
>  'EN PASSANT CAPTURE
>  IF SQ% + 9 = BOARD(126) OR SQ% + 11 = BOARD(126) THEN
>    TOSQ% = BOARD(126)
>    SPECIAL% = 7
>    GOSUB ADDMOVE
>  END IF
>END IF
>
>IF BOARD(SQ%) = 1 THEN ' black pawn
>
>  ' MOVE ONE SQUARE FORWARD
>  IF BOARD(SQ% - 10) = 0 THEN TOSQ% = SQ% - 10: GOSUB ADDPAWN
>
>  'TAKE PIECE TO THE LEFT
>  IF BOARD(SQ% - 11) < 0 AND BOARD(SQ% - 11) < 100 THEN
>    TOSQ% = SQ% - 11: GOSUB ADDPAWN
>  END IF
>
>  'TAKE PIECE TO THE RIGHT
>  IF BOARD(SQ% - 9) < 0 AND BOARD(SQ% - 9) < 100 THEN
>    TOSQ% = SQ% - 9: GOSUB ADDPAWN
>  END IF
>
>  ' MOVE TWO SQUARES FORWARD FROM 2ND RANK
>  IF Y% = 7 THEN
>    IF BOARD(SQ% - 10) = 0 AND BOARD(SQ% - 20) = 0 THEN
>      TOSQ% = SQ% - 20
>      GOSUB ADDMOVE
>    END IF
>  END IF
>
>  'EN PASSANT CAPTURE
>  IF SQ% - 9 = BOARD(126) OR SQ% - 11 = BOARD(126) THEN
>    TOSQ% = BOARD(126)
>    SPECIAL% = 7
>    GOSUB ADDMOVE
>  END IF
>END IF
>
>RETURN
>
>
>ADDPAWN:
>
>Y3% = INT((TOSQ% - 10) / 10)
>
>IF Y3% < 8 AND Y3% > 1 THEN
>  GOSUB ADDMOVE
>  RETURN
>END IF
>
>SPECIAL% = 6: GOSUB ADDMOVE ' QUEEN
>SPECIAL% = 5: GOSUB ADDMOVE ' ROOK
>SPECIAL% = 4: GOSUB ADDMOVE ' BISHOP
>SPECIAL% = 3: GOSUB ADDMOVE ' KNIGHT
>SPECIAL% = 0
>RETURN
>
>CASTLEMOVE:
>
>IF BOARD(SQ%) = -6 AND SQ% = 26 THEN
>  IF BOARD(124) = 0 THEN ' HAS SHORT CASTLING RIGHTS
>    IF BOARD(27) = 0 AND BOARD(28) = 0 AND BOARD(29) = -4 THEN
>      IF ATTACKSQ(26, 1) = 0 AND ATTACKSQ(27, 1) = 0 AND ATTACKSQ(28, 1) = 0
>THEN
>        SPECIAL% = 1
>        TOSQ% = 28
>        GOSUB ADDMOVE
>      END IF
>    END IF
>  END IF
>
>  IF BOARD(125) = 0 THEN ' HAS LONG CASTLING RIGHTS
>    IF BOARD(25) = 0 AND BOARD(24) = 0 AND BOARD(23) = 0 AND BOARD(22) = -4 THEN
>      IF ATTACKSQ(26, 1) = 0 AND ATTACKSQ(25, 1) = 0 AND ATTACKSQ(24, 1) = 0
>THEN
>        SPECIAL% = 2
>        TOSQ% = 24
>        GOSUB ADDMOVE
>      END IF
>    END IF
>  END IF
>END IF
>
>IF BOARD(SQ%) = 6 AND SQ% = 96 THEN
>  IF BOARD(122) = 0 THEN ' HAS SHORT CASTLING RIGHTS
>    IF BOARD(97) = 0 AND BOARD(98) = 0 AND BOARD(99) = 4 THEN
>      IF ATTACKSQ(96, 0) = 0 AND ATTACKSQ(97, 0) = 0 AND ATTACKSQ(98, 0) = 0
>THEN
>        SPECIAL% = 1
>        TOSQ% = 98
>        GOSUB ADDMOVE
>      END IF
>    END IF
>  END IF
>
>  IF BOARD(123) = 0 THEN ' HAS LONG CASTLING RIGHTS
>    IF BOARD(95) = 0 AND BOARD(94) = 0 AND BOARD(93) = 0 AND BOARD(92) = 4 THEN
>      IF ATTACKSQ(96, 0) = 0 AND ATTACKSQ(95, 0) = 0 AND ATTACKSQ(94, 0) = 0
>THEN
>        SPECIAL% = 2
>        TOSQ% = 94
>        GOSUB ADDMOVE
>      END IF
>    END IF
>  END IF
>END IF
>
>RETURN
>
>END SUB

// Probably something like this in C:

#include <math.h>

extern void     genmoves(int dpth, int clr, int pseudo);
extern void     piecemove(void);
extern void     addmove(void);
extern void     pawnmove(void);
extern void     addpawn(void);
extern void     castlemove(void);
static int      attacksq[128][2];
static int      board[128];
static int      movelist[100][5][10];   // guessing on dimentions
static int      x_1,
                y_1,
                sq;
static int      piece;
static int      startdir;
static int      enddir;
static int      maxdist;
static int      special;
static int      dir;
static int      dist;
static int      tosq;
static int      pseudo;
static int      dpth;
static int      clr;
static int      illegal;
static int      bking;
static int      wking;
static int      depth;
static int      r;
static int      y;
static int      y3;

int          sgn(int a)
{
    return (a < 0) ? -1 : (a > 0) ? 1 : 0;
}
void            genmoves(int dpth, int clr, int pseudo)
{
// *********************************************************************
//  generate list of moves and store them in movelist(depth,info,index#)
//
//  clr%=0 - black
//  clr%=1 - white
//
//  pseudo=1 - only return pseudo legal moves (fast)
//  pseduo=0 - return 100% legal moves (slower)
// *********************************************************************
    movelist[dpth][0][0] = 0;
    for (y_1 = 1; y_1 <= 8; y_1++) {
        for (x_1 = 1; x_1 <= 8; x_1++) {
            sq = ((y_1 * 10) + 10) + (x_1 + 1);
            if (board[sq] < 0 && clr == 0) {
                piecemove();
            }
            if (board[sq] > 0 && clr == 1) {
                piecemove();
            }
        }
    }
    return;
}
void            piecemove()
{
    piece = abs(board[sq]);
    if (piece == 1) {
        pawnmove();
        return;
    }
    startdir = range(1, piece);
    enddir = range(2, piece);
    maxdist = 7;
    if (piece == 6 || piece == 2) {
        maxdist = 1;
    }
    special = 0;
    for (dir = startdir; dir <= enddir; dir++) {
        dist = 0;
        while (1) {
            dist += 1;
            if (dist > maxdist) {
                break;
            }
            tosq = movegen(sq, dir, dist);
            if (tosq == 0) {
                break;
            }
            if (sgn(board[tosq]) == sgn(board[sq])) {
                break;
            }
            addmove();
            if (board[tosq] != 0) {
                break;
            }
        }
    }
    if (piece == 6) {
        castlemove();
    }
}

void            addmove(void)
{
    if (pseudo == 0) {
        makemove(sq, tosq, special, dpth);
        if (clr == 0) {
            illegal = attacksq[bking][1];
        }
        if (clr == 1) {
            illegal = attacksq[wking][0];
        }
        unmakemove(depth);
        if (illegal == 1) {
            return;

        }
    }
    r = movelist[dpth][0][0] + 1;
    movelist[dpth][1][r] = sq;
    movelist[dpth][2][r] = tosq;
    movelist[dpth][3][r] = special;
    movelist[dpth][4][r] = abs(board[tosq]);
    movelist[dpth][0][0] = r;
}
void            pawnmove(void)
{
    y = floor((sq - 10) / 10);
    special = 0;
    if (board[sq] == -1) {
//  move one square forward
        if (board[sq + 10] == 0) {
            tosq = sq + 10;
            addpawn();
        }
// take piece to the left
        if (board[sq + 9] > 0 && board[sq + 9] < 100) {
            tosq = sq + 9;
            addpawn();
        }
// take piece to the right
        if (board[sq + 11] > 0 && board[sq + 11] < 100) {
            tosq = sq + 11;
            addpawn();
        }
//  move two squares forward from 2nd rank
        if (y == 2) {
            if (board[sq + 10] == 0 && board[sq + 20] == 0) {
                tosq = sq + 20;
                addmove();
            }
        }
// en passant capture
        if (sq + 9 == board[126] || sq + 11 == board[126]) {
            tosq = board[126];
            special = 7;
            addmove();
        }
    }
    if (board[sq] == 1) {
//  move one square forward
        if (board[sq - 10] == 0) {
            tosq = sq - 10;
            addpawn();
        }
// take piece to the left
        if (board[sq - 11] < 0 && board[sq - 11] < 100) {
            tosq = sq - 11;
            addpawn();
        }
// take piece to the right
        if (board[sq - 9] < 0 && board[sq - 9] < 100) {
            tosq = sq - 9;
            addpawn();
        }
//  move two squares forward from 2nd rank
        if (y == 7) {
            if (board[sq - 10] == 0 && board[sq - 20] == 0) {
                tosq = sq - 20;
                addmove();
            }
        }
// en passant capture
        if (sq - 9 == board[126] || sq - 11 == board[126]) {
            tosq = board[126];
            special = 7;
            addmove();
        }
    }
}

void            addpawn()
{
    y3 = floor((tosq - 10) / 10);
    if (y3 < 8 && y3 > 1) {
        addmove();
        return;
    }
    special = 6;
    addmove();
    special = 5;
    addmove();
    special = 4;
    addmove();
    special = 3;
    addmove();
    special = 0;
}

void            castlemove()
{
    if (board[sq] == -6 && sq == 26) {
        if (board[124] == 0) {
            if (board[27] == 0 && board[28] == 0 && board[29] == -4) {
                if (attacksq[26][1] == 0 && attacksq[27][1] == 0 &&
attacksq[28][1] == 0) {
                    special = 1;
                    tosq = 28;
                    addmove();
                }
            }
        }
        if (board[125] == 0) {
            if (board[25] == 0 && board[24] == 0 && board[23] == 0 && board[22]
== -4) {
                if (attacksq[26][1] == 0 && attacksq[25][1] == 0 &&
attacksq[24][1] == 0) {
                    special = 2;
                    tosq = 24;
                    addmove();
                }
            }
        }
        if (board[sq] == 6 && sq == 96) {
            if (board[122] == 0) {
                if (board[97] == 0 && board[98] == 0 && board[99] == 4) {
                    if (attacksq[96][0] == 0 && attacksq[97][0] == 0 &&
attacksq[98][0] == 0) {
                        special = 1;
                        tosq = 98;
                        addmove();
                    }
                }
            }
            if (board[123] == 0) {
                if (board[95] == 0 && board[94] == 0 && board[93] == 0 &&
board[92] == 4) {
                    if (attacksq[96][0] == 0 && attacksq[95][0] == 0 &&
attacksq[94][0] == 0) {
                        special = 2;
                        tosq = 94;
                        addmove();
                    }
                }
            }
        }
    }
}



This page took 0 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.