Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: A faster move generator than previously known

Author: Thomas McBurney

Date: 08:33:00 08/08/03

Go up one level in this thread


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


>You guys can figure out the rest i bet seeing this code.
>
>All that bitboard idiocy always. This kicks the hell out of it.
>
>Vincent Diepeveen,
>8 august 2003  5:53 AM
>
>#if MSVC
>__inline
>#endif
>void GenMovesI(RecursionBlock *rb,int sq) {
>  int SRsq,piece,u,xside,*s,*t,side,*v,*w;
>
>  side  = rb->side;
>  xside = rb->xside;
>  SRsq  = (sq<<6);
>  piece = board[sq];
>  if( piece == pawn ) {
>    v = ipiecepos[side][sq];
>    w = ipawndir[side][sq];
>    u = *v++;
>    if( row(u) != 0 && row(u) != 7 ) {
>      if( color[u] == neutral) {
>        rb->zetend->zet = (SRsq|u);
>        rb->zetend++;
>        if( (u=*v) != 128 && color[u] == neutral ) { /* indien u == sq dan false
>*/
>          rb->zetend->zet = (SRsq|u);
>          rb->zetend++;
>        }
>      }
>
>      u = *w++;
>      if( color[u] == xside ) {/* ppos bevat geen 100, maar sq. */
>        rb->zetend->zet = (SRsq|u|move_captures);
>        rb->zetend++;
>      }
>      if( (u=*w) != 128 && color[u] == xside ) {
>        rb->zetend->zet = (SRsq|u|move_captures);
>        rb->zetend++;
>      }
>    }
>    else {
>      if( color[u] == neutral) {
>        rb->zetend->zet = (SRsq|u|move_pqueen);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_pknight);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_prook);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_pbishop);
>        rb->zetend++;
>      }
>      u = *w++;
>      if( color[u] == xside) {/* captures */
>        rb->zetend->zet = (SRsq|u|move_captures|move_pqueen);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_pknight);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_prook);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_pbishop);
>        rb->zetend++;
>      }
>      if( (u=*w) != 128 && color[u] == xside) {
>        rb->zetend->zet = (SRsq|u|move_captures|move_pqueen);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_pknight);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_prook);
>        rb->zetend++;
>        rb->zetend->zet = (SRsq|u|move_captures|move_pbishop);
>        rb->zetend++;
>      }
>    }
>  }
>  else {
>    t = cancapside[side];
>    if( sweep[piece] ) {
>      int *vh,*wh,uh;
>      s  = andscan[0];
>      vh = ipiecepos[piece][sq];
>      wh = iskippos[sq];
>      uh = *vh++;
>      do {
>        int p1=snelbord[uh],sh=wh[uh]; /* local variables is faster for GCC/MSVC
>*/
>        vh += (s[p1]&sh);
>        if( color[uh] != side ) {
>          rb->zetend->zet = (SRsq|uh|t[p1]);
>          rb->zetend++;
>        }
>      } while( (uh=*vh++) != 128 );
>
>      /*vi = gentable[piece-3][sq];
>      s  = doorscan[0];
>      u  = vi[sq];
>      do {
>        if( color[u] != side ) {
>          cappiece = snelbord[u];
>          rb->zetend->zet = (SRsq|u|t[cappiece]);
>          rb->zetend++;
>          u = vi[(s[cappiece]|u)];
>        }
>        else {
>          u = vi[(64|u)];
>        }
>      } while( u != 128 );*/
>    }
>    else {
>      v = ipiecepos[piece][sq];
>      u = *v++;
>      do {
>        if( color[u] != side ) {
>          rb->zetend->zet = (SRsq|u|t[snelbord[u]]);
>          rb->zetend++;
>        }
>      } while( (u=*v++) != 128 );
>    }
>  }
>}
>
>void MoveListI(RecursionBlock *rb,struct Move *CFEP) {
>/* Generate all semi-legal moves. Check is ignored.
>*/
>  int f,to,from,u,*psq,*pend,*w;
>
>  to = CFEP->zet&63;
>  rb->zetend = rb->SemiLegals;
>  if( board[to] == pawn ) { /* for enpassant */
>    from = (CFEP->zet>>6)&63;
>    if( to-from == 16 || from-to == 16 ) {
>      f = (to+from)>>1;
>      w = ipawndir[rb->xside][f];
>      u = *w++;
>      if( color[u] == rb->side && board[u] == pawn ) {
>        rb->zetend->zet = ((u<<6)|f|move_captures|move_enpassant);
>        rb->zetend++;
>      }
>      if( (u=*w) != 128 && color[u] == rb->side && board[u] == pawn ) {
>        rb->zetend->zet = ((u<<6)|f|move_captures|move_enpassant);
>        rb->zetend++;
>      }
>    }
>  }
>
>  psq  = PieceList[rb->side];
>  pend = PieceList[rb->side]+PieceMax[rb->side];
>  if( !castld[rb->side] ) {
>    u = *psq;
>    if( castle(rb->side,u,u+2) ) {
>      rb->zetend->zet = ((u<<6)|(u+2)|move_castles);
>      rb->zetend++;
>    }
>    if( castle(rb->side,u,u-2) ) {
>      rb->zetend->zet = ((u<<6)|(u-2)|move_castles);
>      rb->zetend++;
>    }
>  }
>
>  #if BOUNDSCHECKING
>  pend++;
>  do {
>    pend--;
>    if( *pend != 64 )
>      GenMovesI(rb,*pend);
>  } while( pend > psq );
>  #else
>  do {
>    if( *pend != 64 )
>      GenMovesI(rb,*pend);
>  } while( --pend >= psq );
>  #endif
>} /* End MoveList() */



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.