home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 57
/
Amiga_Dream_57.iso
/
Amiga
/
Jeux
/
Reflexion
/
Crafty-15.19.lha
/
crafty-15.19
/
src
/
movgen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-13
|
53KB
|
1,292 lines
#include <stdio.h>
#include <stdlib.h>
#include "chess.h"
#include "data.h"
/* modified 03/11/97 */
/*
********************************************************************************
* *
* GenerateCaptures() is used to generate capture and pawn promotion moves *
* from the current position. *
* *
* the destination square set is the set of squares occupied by opponent *
* pieces, plus the set of squares on the 8th rank that pawns can advance to *
* and promote. *
* *
********************************************************************************
*/
int* GenerateCaptures(TREE *tree, int ply, int wtm, int *move)
{
register BITBOARD target, piecebd, moves;
register BITBOARD promotions, pcapturesl, pcapturesr;
register int from, to, temp;
if (wtm) {
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
piecebd=WhiteKnights;
while (piecebd) {
from=LastOne(piecebd);
moves=And(knight_attacks[from],BlackPieces);
temp=from+(knight<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteBishops;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksBishop(from),BlackPieces);
temp=from+(bishop<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteRooks;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksRook(from),BlackPieces);
temp=from+(rook<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteQueens;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksQueen(from),BlackPieces);
temp=from+(queen<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through king_attacks[] to locate to squares |
| that a king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=WhiteKingSQ;
moves=And(king_attacks[from],BlackPieces);
temp=from+(king<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| another exception is capturing enpassant. the first |
| step is to generate all possible pawn promotions. we |
| do this by masking all pawns but those on the 7th |
| rank and then advancing them ahead if the square in |
| front is empty. |
| |
----------------------------------------------------------
*/
promotions=And(Shiftr(And(WhitePawns,rank_mask[RANK7]),8),Compl(Occupied));
while (promotions) {
to=LastOne(promotions);
*move++=(to-8)|(to<<6)|(pawn<<12)|(queen<<18);
Clear(to,promotions);
}
target=Or(BlackPieces,EnPassantTarget(ply));
pcapturesl=And(Shiftr(And(WhitePawns,mask_left_edge),7),target);
while (pcapturesl) {
to=LastOne(pcapturesl);
if (to < 56) {
if(PieceOnSquare(to))
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15);
else
*move++=(to-7)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(queen<<18);
Clear(to,pcapturesl);
}
pcapturesr=And(Shiftr(And(WhitePawns,mask_right_edge),9),target);
while (pcapturesr) {
to=LastOne(pcapturesr);
if (to < 56) {
if(PieceOnSquare(to))
*move++=(to-9)|(to<<6)|(pawn<<12)|(-PieceOnSquare(to)<<15);
else
*move++=(to-9)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(queen<<18);
Clear(to,pcapturesr);
}
}
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
else {
piecebd=BlackKnights;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(knight_attacks[from],WhitePieces);
temp=from+(knight<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackBishops;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksBishop(from),WhitePieces);
temp=from+(bishop<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackRooks;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksRook(from),WhitePieces);
temp=from+(rook<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackQueens;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksQueen(from),WhitePieces);
temp=from+(queen<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through king_attacks[] to locate to squares |
| that a king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=BlackKingSQ;
moves=And(king_attacks[from],WhitePieces);
temp=from+(king<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| another exception is capturing enpassant. the first |
| step is to generate all possible pawn promotions. we |
| do this by masking all pawns but those on the 7th |
| rank and then advancing them ahead if the square in |
| front is empty. |
| |
----------------------------------------------------------
*/
promotions=And(Shiftl(And(BlackPawns,rank_mask[RANK2]),8),
Compl(Occupied));
while (promotions) {
to=FirstOne(promotions);
*move++=(to+8)|(to<<6)|(pawn<<12)|(queen<<18);
Clear(to,promotions);
}
target=Or(WhitePieces,EnPassantTarget(ply));
pcapturesl=And(Shiftl(And(BlackPawns,mask_left_edge),9),target);
while (pcapturesl) {
to=FirstOne(pcapturesl);
if (to > 7) {
if(PieceOnSquare(to))
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15);
else
*move++=(to+9)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(queen<<18);
Clear(to,pcapturesl);
}
pcapturesr=And(Shiftl(And(BlackPawns,mask_right_edge),7),target);
while (pcapturesr) {
to=FirstOne(pcapturesr);
if (to > 7) {
if(PieceOnSquare(to))
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15);
else
*move++=(to+7)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(queen<<18);
Clear(to,pcapturesr);
}
}
return(move);
}
/* modified 01/11/96 */
/*
********************************************************************************
* *
* GenerateCheckEvasions() is used to generate moves when the king is in *
* check. *
* *
* three types of check-evasion moves are generated: *
* *
* (1) generate king moves to squares that are not attacked by the opponent's *
* pieces. this includes capture and non-capture moves. *
* *
* (2) generate interpositions along the rank/file that the checking attack *
* is coming along (assuming (a) only one piece is checking the king, and *
* (b) the checking piece is a sliding piece [bishop, rook, queen]). *
* *
* (3) generate capture moves, but only to the square(s) that are giving *
* check. captures are a special case. if there is one checking piece, then *
* capturing it by any piece is tried. if there are two pieces checking the *
* king, then the only legal capture to try is for the king to capture one of *
* the checking pieces that is on an un-attacked square. *
* *
********************************************************************************
*/
int* GenerateCheckEvasions(TREE *tree, int ply, int wtm, int *move)
{
register BITBOARD target, targetc, targetp, piecebd, moves;
register BITBOARD padvances1, padvances2, pcapturesl, pcapturesr;
register BITBOARD padvances1_all, empty, checksqs;
register int from, to, temp;
register int king_square, checkers, checking_square;
register int check_direction1=0, check_direction2=0;
/*
----------------------------------------------------------
| |
| first, determine how many pieces are attacking the |
| king and where they are, so we can figure out how to |
| legally get out of check. |
| |
----------------------------------------------------------
*/
if (wtm) {
king_square=WhiteKingSQ;
checksqs=And(AttacksTo(tree,king_square),BlackPieces);
checkers=PopCnt(checksqs);
if (checkers == 1) {
checking_square=FirstOne(And(AttacksTo(tree,king_square),
BlackPieces));
if (PieceOnSquare(checking_square) != -pawn)
check_direction1=directions[checking_square][king_square];
target=InterposeSquares(check_direction1,king_square,checking_square);
target=Or(target,And(AttacksTo(tree,king_square),BlackPieces));
target=Or(target,BlackKing);
}
else {
target=BlackKing;
checking_square=FirstOne(checksqs);
if (PieceOnSquare(checking_square) != -pawn)
check_direction1=directions[checking_square][king_square];
Clear(checking_square,checksqs);
checking_square=FirstOne(checksqs);
if (PieceOnSquare(checking_square) != -pawn)
check_direction2=directions[checking_square][king_square];
}
/*
----------------------------------------------------------
| |
| the next step is to produce the set of valid |
| destination squares. for king moves, this is simply |
| the set of squares that are not attacked by enemy |
| pieces (if there are any such squares.) |
| |
| then, if the checking piece is not a knight, we need |
| to know the checking direction so that we can either |
| move the king "off" of that direction, or else "block" |
| that direction. |
| |
| first produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through attacks_to[] to locate to squares |
| that the king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=king_square;
moves=And(king_attacks[from],Compl(WhitePieces));
temp=from+(king<<12);
while (moves) {
to=LastOne(moves);
if (!Attacked(tree,to,0) && (directions[from][to] != check_direction1) &&
(directions[from][to] != check_direction2))
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
if (checkers == 1) {
piecebd=WhiteKnights;
while (piecebd) {
from=LastOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(knight_attacks[from],target);
temp=from+(knight<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteBishops;
while (piecebd) {
from=LastOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksBishop(from),target);
temp=from+(bishop<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteRooks;
while (piecebd) {
from=LastOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksRook(from),target);
temp=from+(rook<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteQueens;
while (piecebd) {
from=LastOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksQueen(from),target);
temp=from+(queen<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6)|((-PieceOnSquare(to))<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| another exception is capturing enpassant. the first |
| step is to generate all possible pawn moves. we do |
| this in 2 operations: (1) shift the pawns forward one |
| rank then and with empty squares; (2) shift the pawns |
| forward two ranks and then and with empty squares. |
| |
----------------------------------------------------------
*/
empty=Compl(Occupied);
targetp=And(target,empty);
padvances1=And(Shiftr(WhitePawns,8),targetp);
padvances1_all=And(Shiftr(WhitePawns,8),empty);
padvances2=And(Shiftr(And(padvances1_all,Shiftr(mask_8,16)),8),targetp);
/*
----------------------------------------------------------
| |
| now that we got 'em, we simply enumerate the to |
| squares as before, but in four steps since we have |
| four sets of potential moves. |
| |
----------------------------------------------------------
*/
while (padvances2) {
to=LastOne(padvances2);
if (!PinnedOnKing(tree,wtm,to-16)) *move++=(to-16)|(to<<6)|(pawn<<12);
Clear(to,padvances2);
}
while (padvances1) {
to=LastOne(padvances1);
if (!PinnedOnKing(tree,wtm,to-8)) {
if (to < 56) *move++=(to-8)|(to<<6)|(pawn<<12);
else {
*move++=(to-8)|(to<<6)|(pawn<<12)|(queen<<18);
*move++=(to-8)|(to<<6)|(pawn<<12)|(rook<<18);
*move++=(to-8)|(to<<6)|(pawn<<12)|(bishop<<18);
*move++=(to-8)|(to<<6)|(pawn<<12)|(knight<<18);
}
}
Clear(to,padvances1);
}
targetc=Or(BlackPieces,EnPassantTarget(ply));
targetc=And(targetc,target);
if (And(And(BlackPawns,target),Shiftl(EnPassantTarget(ply),8)))
targetc=Or(targetc,EnPassantTarget(ply));
pcapturesl=And(Shiftr(And(WhitePawns,mask_left_edge),7),targetc);
pcapturesr=And(Shiftr(And(WhitePawns,mask_right_edge),9),targetc);
while (pcapturesl) {
to=LastOne(pcapturesl);
if (!PinnedOnKing(tree,wtm,to-7)) {
if (to < 56) {
if(PieceOnSquare(to))
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15);
else
*move++=(to-7)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else {
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(queen<<18);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(rook<<18);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(bishop<<18);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(knight<<18);
}
}
Clear(to,pcapturesl);
}
while (pcapturesr) {
to=LastOne(pcapturesr);
if (!PinnedOnKing(tree,wtm,to-9)) {
if (to < 56) {
if(PieceOnSquare(to))
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15);
else
*move++=(to-9)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else {
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(queen<<18);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(rook<<18);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(bishop<<18);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(knight<<18);
}
}
Clear(to,pcapturesr);
}
}
}
/*
----------------------------------------------------------
| |
| first, determine how many pieces are attacking the |
| king and where they are, so we can figure out how to |
| legally get out of check. |
| |
----------------------------------------------------------
*/
else {
king_square=BlackKingSQ;
checksqs=And(AttacksTo(tree,king_square),WhitePieces);
checkers=PopCnt(checksqs);
if (checkers == 1) {
checking_square=FirstOne(And(AttacksTo(tree,king_square),
WhitePieces));
if (PieceOnSquare(checking_square) != pawn)
check_direction1=directions[checking_square][king_square];
target=InterposeSquares(check_direction1,king_square,checking_square);
target=Or(target,And(AttacksTo(tree,king_square),WhitePieces));
target=Or(target,WhiteKing);
}
else {
target=WhiteKing;
checking_square=FirstOne(checksqs);
if (PieceOnSquare(checking_square) != pawn)
check_direction1=directions[checking_square][king_square];
Clear(checking_square,checksqs);
checking_square=FirstOne(checksqs);
if (PieceOnSquare(checking_square) != pawn)
check_direction2=directions[checking_square][king_square];
}
/*
----------------------------------------------------------
| |
| the first step is to produce the set of valid |
| destination squares. for king moves, this is simply |
| the set of squares that are not attacked by enemy |
| pieces (if there are any such squares.) |
| |
| then, if the checking piece is not a knight, we need |
| to know the checking direction so that we can either |
| move the king "off" of that direction, or else "block" |
| that direction. |
| |
| first produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through attacks_to[] to locate to squares |
| that the king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=king_square;
moves=And(king_attacks[from],Compl(BlackPieces));
temp=from+(king<<12);
while (moves) {
to=FirstOne(moves);
if (!Attacked(tree,to,1) && (directions[from][to] != check_direction1) &&
(directions[from][to] != check_direction2))
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
if (checkers == 1) {
piecebd=BlackKnights;
while (piecebd) {
from=FirstOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(knight_attacks[from],target);
temp=from+(knight<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackBishops;
while (piecebd) {
from=FirstOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksBishop(from),target);
temp=from+(bishop<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackRooks;
while (piecebd) {
from=FirstOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksRook(from),target);
temp=from+(rook<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| |
----------------------------------------------------------
*/
piecebd=BlackQueens;
while (piecebd) {
from=FirstOne(piecebd);
if (!PinnedOnKing(tree,wtm,from)) {
moves=And(AttacksQueen(from),target);
temp=from+(queen<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6)|(PieceOnSquare(to)<<15);
Clear(to,moves);
}
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| another exception is capturing enpassant. the first |
| step is to generate all possible pawn moves. we do |
| this in 4 operations: (1) shift the pawns forward one |
| rank then and with empty squares; (2) shift the pawns |
| forward two ranks and then and with empty squares; |
| (3) remove the a-pawn(s) then shift the pawns |
| diagonally left then and with enemy occupied squares; |
| (4) remove the h-pawn(s) then shift the pawns |
| diagonally right then and with enemy occupied squares; |
| note that enemy occupied squares includes the special |
| case of the enpassant target square also. |
| |
----------------------------------------------------------
*/
empty=Compl(Occupied);
targetp=And(target,empty);
padvances1=And(Shiftl(BlackPawns,8),targetp);
padvances1_all=And(Shiftl(BlackPawns,8),empty);
padvances2=And(Shiftl(And(padvances1_all,Shiftl(mask_120,16)),8),targetp);
/*
----------------------------------------------------------
| |
| now that we got 'em, we simply enumerate the to |
| squares as before, but in four steps since we have |
| four sets of potential moves. |
| |
----------------------------------------------------------
*/
while (padvances2) {
to=FirstOne(padvances2);
if (!PinnedOnKing(tree,wtm,to+16)) *move++=(to+16)|(to<<6)|(pawn<<12);
Clear(to,padvances2);
}
while (padvances1) {
to=FirstOne(padvances1);
if (!PinnedOnKing(tree,wtm,to+8)) {
if (to > 7) *move++=(to+8)|(to<<6)|(pawn<<12);
else {
*move++=(to+8)|(to<<6)|(pawn<<12)|(queen<<18);
*move++=(to+8)|(to<<6)|(pawn<<12)|(rook<<18);
*move++=(to+8)|(to<<6)|(pawn<<12)|(bishop<<18);
*move++=(to+8)|(to<<6)|(pawn<<12)|(knight<<18);
}
}
Clear(to,padvances1);
}
targetc=Or(WhitePieces,EnPassantTarget(ply));
targetc=And(targetc,target);
if (And(And(WhitePawns,target),Shiftr(EnPassantTarget(ply),8)))
targetc=Or(targetc,EnPassantTarget(ply));
pcapturesl=And(Shiftl(And(BlackPawns,mask_left_edge),9),targetc);
pcapturesr=And(Shiftl(And(BlackPawns,mask_right_edge),7),targetc);
while (pcapturesl) {
to=FirstOne(pcapturesl);
if (!PinnedOnKing(tree,wtm,to+9)) {
if (to > 7) {
if(PieceOnSquare(to))
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15);
else
*move++=(to+9)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else {
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(queen<<18);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(rook<<18);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(bishop<<18);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(knight<<18);
}
}
Clear(to,pcapturesl);
}
while (pcapturesr) {
to=FirstOne(pcapturesr);
if (!PinnedOnKing(tree,wtm,to+7)) {
if (to > 7) {
if(PieceOnSquare(to))
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15);
else
*move++=(to+7)|(to<<6)|(pawn<<12)|(pawn<<15);
}
else {
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(queen<<18);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(rook<<18);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(bishop<<18);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(knight<<18);
}
}
Clear(to,pcapturesr);
}
}
}
return(move);
}
/* modified 03/11/97 */
/*
********************************************************************************
* *
* GenerateMoves() is used to generate non-capture moves from the current *
* position. *
* *
* once the valid destination squares are known, we have to locate a friendly *
* piece to get a attacks_to[] entry. we then produce the moves for this *
* piece by using the source square as [from] and enumerating each square it *
* attacks into [to]. *
* *
* pawns are handled differently. regular pawn moves are produced by *
* shifting the pawn bitmap 8 bits "forward" and anding this with the *
* complement of the occupied squares bitmap double advances are then *
* produced by anding the pawn bitmap with a mask containing 1's on the *
* second rank, shifting this 16 bits "forward" and then anding this with *
* the complement of the occupied squares bitmap as before. if [to] *
* reaches the 8th rank, we produce a set of four moves, promoting the pawn *
* to knight, bishop, rook and queen. *
* *
********************************************************************************
*/
int* GenerateNonCaptures(TREE *tree, int ply, int wtm, int *move)
{
register BITBOARD target, piecebd, moves;
register BITBOARD padvances1, padvances2, pcapturesl, pcapturesr;
register int from, to, temp;
if (wtm) {
/*
----------------------------------------------------------
| |
| first, produce castling moves if it is legal. |
| |
----------------------------------------------------------
*/
if (WhiteCastle(ply) > 0) {
if ((WhiteCastle(ply)&1) && !And(Occupied,Shiftr(mask_2,5)) &&
!Attacked(tree,E1,0) && !Attacked(tree,F1,0) && !Attacked(tree,G1,0)) {
*move++=12676;
}
if ((WhiteCastle(ply)&2) && !And(Occupied,Shiftr(mask_3,1)) &&
!Attacked(tree,C1,0) && !Attacked(tree,D1,0) && !Attacked(tree,E1,0)) {
*move++=12420;
}
}
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
target=Compl(Occupied);
piecebd=WhiteKnights;
while (piecebd) {
from=LastOne(piecebd);
moves=And(knight_attacks[from],target);
temp=from+(knight<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteBishops;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksBishop(from),target);
temp=from+(bishop<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteRooks;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksRook(from),target);
temp=from+(rook<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=WhiteQueens;
while (piecebd) {
from=LastOne(piecebd);
moves=And(AttacksQueen(from),target);
temp=from+(queen<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through king_attacks[] to locate to squares |
| that a king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=WhiteKingSQ;
moves=And(king_attacks[from],target);
temp=from+(king<<12);
while (moves) {
to=LastOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| first we generate all possible pawn moves. we do |
| this in 4 operations: (1) shift the pawns forward one |
| rank then and with empty squares; (2) shift the pawns |
| forward two ranks and then and with empty squares; |
| (3) remove the a-pawn(s) then shift the pawns |
| diagonally left then and with enemy occupied squares; |
| (4) remove the h-pawn(s) then shift the pawns |
| diagonally right then and with enemy occupied squares. |
| note that the only captures produced are under- |
| promotions, because the rest were done in GenCap. |
| |
----------------------------------------------------------
*/
padvances1=And(Shiftr(WhitePawns,8),target);
padvances2=And(Shiftr(And(padvances1,mask_advance_2_w),8),target);
/*
----------------------------------------------------------
| |
| now that we got 'em, we simply enumerate the to |
| squares as before, but in four steps since we have |
| four sets of potential moves. |
| |
----------------------------------------------------------
*/
while (padvances2) {
to=LastOne(padvances2);
*move++=(to-16)|(to<<6)|(pawn<<12);
Clear(to,padvances2);
}
while (padvances1) {
to=LastOne(padvances1);
if (to < 56) *move++=(to-8)|(to<<6)|(pawn<<12);
else {
*move++=(to-8)|(to<<6)|(pawn<<12)|(rook<<18);
*move++=(to-8)|(to<<6)|(pawn<<12)|(bishop<<18);
*move++=(to-8)|(to<<6)|(pawn<<12)|(knight<<18);
}
Clear(to,padvances1);
}
target=And(BlackPieces,rank_mask[RANK8]);
pcapturesl=And(Shiftr(And(WhitePawns,mask_left_edge),7),target);
pcapturesr=And(Shiftr(And(WhitePawns,mask_right_edge),9),target);
while (pcapturesl) {
to=LastOne(pcapturesl);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(rook<<18);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(bishop<<18);
*move++=(to-7)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(knight<<18);
Clear(to,pcapturesl);
}
while (pcapturesr) {
to=LastOne(pcapturesr);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(rook<<18);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(bishop<<18);
*move++=(to-9)|(to<<6)|(pawn<<12)|((-PieceOnSquare(to))<<15)|(knight<<18);
Clear(to,pcapturesr);
}
}
/*
----------------------------------------------------------
| |
| first, produce castling moves if it is legal. |
| |
----------------------------------------------------------
*/
else {
if (BlackCastle(ply) > 0) {
if ((BlackCastle(ply)&1) && !And(Occupied,Shiftr(mask_2,61)) &&
!Attacked(tree,E8,1) && !Attacked(tree,F8,1) && !Attacked(tree,G8,1)) {
*move++=16316;
}
if ((BlackCastle(ply)&2) && !And(Occupied,Shiftr(mask_3,57)) &&
!Attacked(tree,C8,1) && !Attacked(tree,D8,1) && !Attacked(tree,E8,1)) {
*move++=16060;
}
}
/*
----------------------------------------------------------
| |
| now, produce knight moves by cycling through the |
| *_knight board to locate a [from] square and then |
| cycling through knight_attacks[] to locate to squares |
| that a knight on [from] attacks. |
| |
----------------------------------------------------------
*/
target=Compl(Occupied);
piecebd=BlackKnights;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(knight_attacks[from],target);
temp=from+(knight<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce bishop moves by cycling through the |
| *_bishop board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackBishops;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksBishop(from),target);
temp=from+(bishop<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce rook moves by cycling through the |
| *_rook board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackRooks;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksRook(from),target);
temp=from+(rook<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce queen moves by cycling through the |
| *_queen board to locate a [from] square and then |
| generate the AttacksFrom() bitmap which supplies the |
| list of valid <to> squares. |
| |
----------------------------------------------------------
*/
piecebd=BlackQueens;
while (piecebd) {
from=FirstOne(piecebd);
moves=And(AttacksQueen(from),target);
temp=from+(queen<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
Clear(from,piecebd);
}
/*
----------------------------------------------------------
| |
| now, produce king moves by cycling through the |
| *_king board to locate a [from] square and then |
| cycling through king_attacks[] to locate to squares |
| that a king on [from] attacks. |
| |
----------------------------------------------------------
*/
from=BlackKingSQ;
moves=And(king_attacks[from],target);
temp=from+(king<<12);
while (moves) {
to=FirstOne(moves);
*move++=temp|(to<<6);
Clear(to,moves);
}
/*
----------------------------------------------------------
| |
| now, produce pawn moves. this is done differently due |
| to inconsistencies in the way a pawn moves when it |
| captures as opposed to normal non-capturing moves. |
| first we generate all possible pawn moves. we do |
| this in 4 operations: (1) shift the pawns forward one |
| rank then and with empty squares; (2) shift the pawns |
| forward two ranks and then and with empty squares; |
| (3) remove the a-pawn(s) then shift the pawns |
| diagonally left then and with enemy occupied squares; |
| (4) remove the h-pawn(s) then shift the pawns |
| diagonally right then and with enemy occupied squares. |
| note that the only captures produced are under- |
| promotions, because the rest were done in GenCap. |
| |
----------------------------------------------------------
*/
padvances1=And(Shiftl(BlackPawns,8),target);
padvances2=And(Shiftl(And(padvances1,mask_advance_2_b),8),target);
/*
----------------------------------------------------------
| |
| now that we got 'em, we simply enumerate the to |
| squares as before, but in four steps since we have |
| four sets of potential moves. |
| |
----------------------------------------------------------
*/
while (padvances2) {
to=FirstOne(padvances2);
*move++=(to+16)|(to<<6)|(pawn<<12);
Clear(to,padvances2);
}
while (padvances1) {
to=FirstOne(padvances1);
if (to > 7) *move++=(to+8)|(to<<6)|(pawn<<12);
else {
*move++=(to+8)|(to<<6)|(pawn<<12)|(rook<<18);
*move++=(to+8)|(to<<6)|(pawn<<12)|(bishop<<18);
*move++=(to+8)|(to<<6)|(pawn<<12)|(knight<<18);
}
Clear(to,padvances1);
}
target=And(WhitePieces,rank_mask[RANK1]);
pcapturesl=And(Shiftl(And(BlackPawns,mask_left_edge),9),target);
pcapturesr=And(Shiftl(And(BlackPawns,mask_right_edge),7),target);
while (pcapturesl) {
to=FirstOne(pcapturesl);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(rook<<18);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(bishop<<18);
*move++=(to+9)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(knight<<18);
Clear(to,pcapturesl);
}
while (pcapturesr) {
to=FirstOne(pcapturesr);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(rook<<18);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(bishop<<18);
*move++=(to+7)|(to<<6)|(pawn<<12)|(PieceOnSquare(to)<<15)|(knight<<18);
Clear(to,pcapturesr);
}
}
return(move);
}