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.