static void fill_random_cell(board_t *board) { /* we don't want randomness while doing testcases. */ if (test_status == DOING_TESTS) { return; } /* bitmap of all the unoccupied squares */ int bitmap_flipped = ~board->occupied_cells & ((1 << SIZE) - 1); if (bitmap_flipped) { //numbers of unoccupied cells int num_unoccupied = PopCnt(bitmap_flipped); /* remove a bit from the bottom of `bitmap_flipped`, `rand() % num_unoccupied` times. */ //this is to get the cell that is not occupied to used in the following for (int r = rand() % num_unoccupied; r; --r) { bitmap_flipped &= bitmap_flipped - 1; } /* Get the index of the lowermost bit, which should now be a random index of the unoccupied squares. */ //auto occupy the cell which 2 or 4 and the probability of 2 is larger than 4's int rand_i = LSB(bitmap_flipped); int rand_val = (rand() % 9) ? 2 : 4; board->cells[rand_i] = rand_val; board->occupied_cells |= (1 << rand_i); //board->score += rand_val; } }
int main(int argc, char **argv) { int seed = time(NULL); //seed = 1394569404; //printf("Random seed: %d\n", seed); srand(seed); printf("%d %d %d\n", LSB(0x11), MSB(0x11), PopCnt(0xFFFF)); precalc_init(); if (argc == 2) { if (0 == strcmp(argv[1], "--human")) { board_t board = board_init(); while (1) { board_print(board); printf("[hjkl] "); char key = getchar(); getchar(); // eat newline if (key == 'k') { board_move(&board, MOVE_UP); } else if (key == 'l') { board_move(&board, MOVE_RIGHT); } else if (key == 'j') { board_move(&board, MOVE_DOWN); } else if (key == 'h') { board_move(&board, MOVE_LEFT); } } } else if (0 == strcmp(argv[1], "--test")) { test_status = DOING_TESTS; // disable board_fill_random_cell test_run_testcases(); test_status = NOT_DOING_TESTS; } else if (0 == strcmp(argv[1], "--ai")) { ai_loop(); } else { interface_main(argv[1]); } } else { printf("c2048, compiled with AI_DEPTH=%d AI_NUM_TRIES=%d\n\n", AI_DEPTH, AI_NUM_TRIES); puts("--human Play on the console, using hjkl to move around"); puts("--test Runs some testcases"); puts("--ai Runs infinitly many games in a row, while tracking stats (avg, max, nps, etc.)"); return 1; } return 0; }
void ValidatePosition(int ply, int move, char *caller) { BITBOARD temp, temp1, temp_occ, temp_occ_rl90, temp_occ_rl45; BITBOARD temp_occ_rr45, temp_occx, cattacks, rattacks; int i,square,error; int temp_score; /* first, test w_occupied and b_occupied */ error=0; temp_occ=Or(Or(Or(Or(Or(WhitePawns,WhiteKnights),WhiteBishops), WhiteRooks),WhiteQueens),WhiteKing); if(Xor(WhitePieces,temp_occ)) { Print(1,"ERROR white occupied squares is bad!\n"); Display2BitBoards(temp_occ,WhitePieces); error=1; } temp_occ=Or(Or(Or(Or(Or(BlackPawns,BlackKnights),BlackBishops), BlackRooks),BlackQueens),BlackKing); if(Xor(BlackPieces,temp_occ)) { Print(1,"ERROR black occupied squares is bad!\n"); Display2BitBoards(temp_occ,BlackPieces); error=1; } /* now test rotated occupied bitboards. */ temp_occ_rl90=0; temp_occ_rl45=0; temp_occ_rr45=0; for (i=0;i<64;i++) { if (PieceOnSquare(i)) { temp_occ_rl90=Or(temp_occ_rl90,set_mask_rl90[i]); temp_occ_rl45=Or(temp_occ_rl45,set_mask_rl45[i]); temp_occ_rr45=Or(temp_occ_rr45,set_mask_rr45[i]); } } if(Xor(OccupiedRL90,temp_occ_rl90)) { Print(1,"ERROR occupied squares (rotated left 90) is bad!\n"); Display2BitBoards(temp_occ_rl90,OccupiedRL90); error=1; } if(Xor(OccupiedRL45,temp_occ_rl45)) { Print(1,"ERROR occupied squares (rotated left 45) is bad!\n"); Display2BitBoards(temp_occ_rl45,OccupiedRL45); error=1; } if(Xor(OccupiedRR45,temp_occ_rr45)) { Print(1,"ERROR occupied squares (rotated right 45) is bad!\n"); Display2BitBoards(temp_occ_rr45,OccupiedRR45); error=1; } /* now test bishops_queens and rooks_queens */ temp_occ=Or(Or(Or(WhiteBishops,WhiteQueens),BlackBishops), BlackQueens); if(Xor(BishopsQueens,temp_occ)) { Print(1,"ERROR bishops_queens is bad!\n"); Display2BitBoards(temp_occ,BishopsQueens); error=1; } temp_occ=Or(Or(Or(WhiteRooks,WhiteQueens),BlackRooks), BlackQueens); if(Xor(RooksQueens,temp_occ)) { Print(1,"ERROR rooks_queens is bad!\n"); Display2BitBoards(temp_occ,RooksQueens); error=1; } /* check individual piece bit-boards to make sure two pieces don't occupy the same square (bit) */ temp_occ=Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor(Xor( WhitePawns,WhiteKnights),WhiteBishops),WhiteRooks), WhiteQueens),BlackPawns),BlackKnights),BlackBishops), BlackRooks),BlackQueens),WhiteKing),BlackKing); temp_occx=Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or( WhitePawns,WhiteKnights),WhiteBishops),WhiteRooks), WhiteQueens),BlackPawns),BlackKnights),BlackBishops), BlackRooks),BlackQueens),WhiteKing),BlackKing); if(Xor(temp_occ,temp_occx)) { Print(1,"ERROR two pieces on same square\n"); error=1; } /* test material_evaluation */ temp_score=PopCnt(WhitePawns)*PAWN_VALUE; temp_score-=PopCnt(BlackPawns)*PAWN_VALUE; temp_score+=PopCnt(WhiteKnights)*KNIGHT_VALUE; temp_score-=PopCnt(BlackKnights)*KNIGHT_VALUE; temp_score+=PopCnt(WhiteBishops)*BISHOP_VALUE; temp_score-=PopCnt(BlackBishops)*BISHOP_VALUE; temp_score+=PopCnt(WhiteRooks)*ROOK_VALUE; temp_score-=PopCnt(BlackRooks)*ROOK_VALUE; temp_score+=PopCnt(WhiteQueens)*QUEEN_VALUE; temp_score-=PopCnt(BlackQueens)*QUEEN_VALUE; if(temp_score != Material) { Print(1,"ERROR material_evaluation is wrong, good=%d, bad=%d\n", temp_score,Material); error=1; } temp_score=PopCnt(WhiteKnights)*knight_v; temp_score+=PopCnt(WhiteBishops)*bishop_v; temp_score+=PopCnt(WhiteRooks)*rook_v; temp_score+=PopCnt(WhiteQueens)*queen_v; if(temp_score != TotalWhitePieces) { Print(1,"ERROR white_pieces is wrong, good=%d, bad=%d\n", temp_score,TotalWhitePieces); error=1; } temp_score=PopCnt(WhitePawns); if(temp_score != TotalWhitePawns) { Print(1,"ERROR white_pawns is wrong, good=%d, bad=%d\n", temp_score,TotalWhitePawns); error=1; } temp_score=PopCnt(BlackKnights)*knight_v; temp_score+=PopCnt(BlackBishops)*bishop_v; temp_score+=PopCnt(BlackRooks)*rook_v; temp_score+=PopCnt(BlackQueens)*queen_v; if(temp_score != TotalBlackPieces) { Print(1,"ERROR black_pieces is wrong, good=%d, bad=%d\n", temp_score,TotalBlackPieces); error=1; } temp_score=PopCnt(BlackPawns); if(temp_score != TotalBlackPawns) { Print(1,"ERROR black_pawns is wrong, good=%d, bad=%d\n", temp_score,TotalBlackPawns); error=1; } /* now test the board[...] to make sure piece values are correct. */ /* test pawn locations */ temp=WhitePawns; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != pawn) { Print(1,"ERROR! board[%d]=%d, should be 1\n",square, PieceOnSquare(square)); error=1; } Clear(square,temp); } temp=BlackPawns; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -pawn) { Print(1,"ERROR! board[%d]=%d, should be -1\n",square, PieceOnSquare(square)); error=1; } Clear(square,temp); } /* test knight locations */ temp=WhiteKnights; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != knight) { Print(1,"ERROR! board[%d]=%d, should be 2\n",square, PieceOnSquare(square)); error=1; } Clear(square,temp); } temp=BlackKnights; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -knight) { Print(1,"ERROR! board[%d]=%d, should be -2\n",square, PieceOnSquare(square)); error=1; } Clear(square,temp); } /* test bishop locations */ temp=WhiteBishops; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != bishop) { Print(1,"ERROR! board[%d]=%d, should be 3\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksBishop(square); cattacks=ValidateComputeBishopAttacks(square); if (rattacks != cattacks) { Print(1,"ERROR! bishop attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } temp=BlackBishops; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -bishop) { Print(1,"ERROR! board[%d]=%d, should be -3\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksBishop(square); cattacks=ValidateComputeBishopAttacks(square); if (rattacks != cattacks) { Print(1,"ERROR! bishop attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } /* test rook locations */ temp=WhiteRooks; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != rook) { Print(1,"ERROR! board[%d]=%d, should be 4\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksRook(square); cattacks=ValidateComputeRookAttacks(square); if (rattacks != cattacks) { Print(1,"ERROR! Rook attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } temp=BlackRooks; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -rook) { Print(1,"ERROR! board[%d]=%d, should be -4\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksRook(square); cattacks=ValidateComputeRookAttacks(square); if (rattacks != cattacks) { Print(1,"ERROR! Rook attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } /* test queen locations */ temp=WhiteQueens; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != queen) { Print(1,"ERROR! board[%d]=%d, should be 5\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksQueen(square); cattacks=Or(ValidateComputeRookAttacks(square),ValidateComputeBishopAttacks(square)); if (rattacks != cattacks) { Print(1,"ERROR! queen attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } temp=BlackQueens; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -queen) { Print(1,"ERROR! board[%d]=%d, should be -5\n",square, PieceOnSquare(square)); error=1; } rattacks=AttacksQueen(square); cattacks=Or(ValidateComputeRookAttacks(square),ValidateComputeBishopAttacks(square)); if (rattacks != cattacks) { Print(1,"ERROR! queen attacks wrong, square=%d\n",square); Display2BitBoards(rattacks,cattacks); error=1; } Clear(square,temp); } /* test king locations */ temp=WhiteKing; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != king) { Print(1,"ERROR! board[%d]=%d, should be 6\n",square, PieceOnSquare(square)); error=1; } if (WhiteKingSQ != square) { Print(1,"ERROR! white_king is %d, should be %d\n", WhiteKingSQ,square); error=1; } Clear(square,temp); } temp=BlackKing; while(temp) { square=FirstOne(temp); if (PieceOnSquare(square) != -king) { Print(1,"ERROR! board[%d]=%d, should be -6\n",square, PieceOnSquare(square)); error=1; } if (BlackKingSQ != square) { Print(1,"ERROR! black_king is %d, should be %d\n", BlackKingSQ,square); error=1; } Clear(square,temp); } /* test board[i] fully now. */ for (i=0;i<64;i++) switch (PieceOnSquare(i)) { case -king: if (!And(BlackKing,set_mask[i])) { Print(1,"ERROR! b_king/board[%d] don't agree!\n",i); error=1; } break; case -queen: if (!And(BlackQueens,set_mask[i])) { Print(1,"ERROR! b_queen/board[%d] don't agree!\n",i); error=1; } break; case -rook: if (!And(BlackRooks,set_mask[i])) { Print(1,"ERROR! b_rook/board[%d] don't agree!\n",i); error=1; } break; case -bishop: if (!And(BlackBishops,set_mask[i])) { Print(1,"ERROR! b_bishop/board[%d] don't agree!\n",i); error=1; } break; case -knight: if (!And(BlackKnights,set_mask[i])) { Print(1,"ERROR! b_knight/board[%d] don't agree!\n",i); error=1; } break; case -pawn: if (!And(BlackPawns,set_mask[i])) { Print(1,"ERROR! b_pawn/board[%d] don't agree!\n",i); error=1; } break; case king: if (!And(WhiteKing,set_mask[i])) { Print(1,"ERROR! w_king/board[%d] don't agree!\n",i); error=1; } break; case queen: if (!And(WhiteQueens,set_mask[i])) { Print(1,"ERROR! w_queen/board[%d] don't agree!\n",i); error=1; } break; case rook: if (!And(WhiteRooks,set_mask[i])) { Print(1,"ERROR! w_rook/board[%d] don't agree!\n",i); error=1; } break; case bishop: if (!And(WhiteBishops,set_mask[i])) { Print(1,"ERROR! w_bishop/board[%d] don't agree!\n",i); error=1; } break; case knight: if (!And(WhiteKnights,set_mask[i])) { Print(1,"ERROR! w_knight/board[%d] don't agree!\n",i); error=1; } break; case pawn: if (!And(WhitePawns,set_mask[i])) { Print(1,"ERROR! w_pawn/board[%d] don't agree!\n",i); error=1; } break; } /* test empty squares now */ temp=Compl(Or(temp_occ,temp_occx)); while(temp) { square=FirstOne(temp); if (PieceOnSquare(square)) { Print(1,"ERROR! board[%d]=%d, should be 0\n",square, PieceOnSquare(square)); error=1; } Clear(square,temp); } /* test total piece count now */ temp=PopCnt(Occupied); if (temp != TotalPieces) { Print(1,"ERROR! TotalPieces is wrong, correct=%d bad=%d\n", temp,TotalPieces); error=1; } /* test hash key */ temp=0; temp1=0; for (i=0;i<64;i++) { switch (PieceOnSquare(i)) { case king: temp=Xor(temp,w_king_random[i]); break; case queen: temp=Xor(temp,w_queen_random[i]); break; case rook: temp=Xor(temp,w_rook_random[i]); break; case bishop: temp=Xor(temp,w_bishop_random[i]); break; case knight: temp=Xor(temp,w_knight_random[i]); break; case pawn: temp=Xor(temp,w_pawn_random[i]); temp1=Xor(temp1,w_pawn_random[i]); break; case -pawn: temp=Xor(temp,b_pawn_random[i]); temp1=Xor(temp1,b_pawn_random[i]); break; case -knight: temp=Xor(temp,b_knight_random[i]); break; case -bishop: temp=Xor(temp,b_bishop_random[i]); break; case -rook: temp=Xor(temp,b_rook_random[i]); break; case -queen: temp=Xor(temp,b_queen_random[i]); break; case -king: temp=Xor(temp,b_king_random[i]); break; default: break; } } if (EnPassant(ply)) HashEP(EnPassant(ply),temp); if (!(WhiteCastle(ply)&1)) HashCastleW(0,temp); if (!(WhiteCastle(ply)&2)) HashCastleW(1,temp); if (!(BlackCastle(ply)&1)) HashCastleB(0,temp); if (!(BlackCastle(ply)&2)) HashCastleB(1,temp); if(Xor(temp,HashKey)) { Print(1,"ERROR! hash_key is bad.\n"); error=1; } if(Xor(temp1,PawnHashKey)) { Print(1,"ERROR! pawn_hash_key is bad.\n"); error=1; } if (error) { /* Print(0,"active path:\n"); for (i=1;i<=ply;i++) DisplayChessMove("move=",move); */ Print(0,"current move:\n"); DisplayChessMove("move=",move); DisplayChessBoard(stdout,search); Print(0,"called from %s, ply=%d\n",caller,ply); Print(0,"node=%d\n",nodes_searched+q_nodes_searched); exit(1); } }
void SetChessBitBoards(SEARCH_POSITION *new_pos) { int i; search.hash_key=0; search.pawn_hash_key=0; /* place pawns */ search.w_pawn=0; search.b_pawn=0; for (i=0;i<64;i++) { if(search.board[i]==pawn) { search.w_pawn=Or(search.w_pawn,set_mask[i]); search.hash_key=Xor(search.hash_key,w_pawn_random[i]); search.pawn_hash_key=search.pawn_hash_key^w_pawn_random32[i]; } if(search.board[i]==-pawn) { search.b_pawn=Or(search.b_pawn,set_mask[i]); search.hash_key=Xor(search.hash_key,b_pawn_random[i]); search.pawn_hash_key=search.pawn_hash_key^b_pawn_random32[i]; } } /* place knights */ search.w_knight=0; search.b_knight=0; for (i=0;i<64;i++) { if(search.board[i] == knight) { search.w_knight=Or(search.w_knight,set_mask[i]); search.hash_key=Xor(search.hash_key,w_knight_random[i]); } if(search.board[i] == -knight) { search.b_knight=Or(search.b_knight,set_mask[i]); search.hash_key=Xor(search.hash_key,b_knight_random[i]); } } /* place bishops */ search.w_bishop=0; search.b_bishop=0; for (i=0;i<64;i++) { if(search.board[i] == bishop) { search.w_bishop=Or(search.w_bishop,set_mask[i]); search.hash_key=Xor(search.hash_key,w_bishop_random[i]); } if(search.board[i] == -bishop) { search.b_bishop=Or(search.b_bishop,set_mask[i]); search.hash_key=Xor(search.hash_key,b_bishop_random[i]); } } /* place rooks */ search.w_rook=0; search.b_rook=0; for (i=0;i<64;i++) { if(search.board[i] == rook) { search.w_rook=Or(search.w_rook,set_mask[i]); search.hash_key=Xor(search.hash_key,w_rook_random[i]); } if(search.board[i] == -rook) { search.b_rook=Or(search.b_rook,set_mask[i]); search.hash_key=Xor(search.hash_key,b_rook_random[i]); } } /* place queens */ search.w_queen=0; search.b_queen=0; for (i=0;i<64;i++) { if(search.board[i] == queen) { search.w_queen=Or(search.w_queen,set_mask[i]); search.hash_key=Xor(search.hash_key,w_queen_random[i]); } if(search.board[i] == -queen) { search.b_queen=Or(search.b_queen,set_mask[i]); search.hash_key=Xor(search.hash_key,b_queen_random[i]); } } /* place kings */ for (i=0;i<64;i++) { if(search.board[i] == king) { search.white_king=i; search.hash_key=Xor(search.hash_key,w_king_random[i]); } if(search.board[i] == -king) { search.black_king=i; search.hash_key=Xor(search.hash_key,b_king_random[i]); } } if (new_pos->enpassant_target) HashEP(new_pos->enpassant_target,search.hash_key); if (!(new_pos->w_castle&1)) HashCastleW(0,search.hash_key); if (!(new_pos->w_castle&2)) HashCastleW(1,search.hash_key); if (!(new_pos->b_castle&1)) HashCastleB(0,search.hash_key); if (!(new_pos->b_castle&2)) HashCastleB(1,search.hash_key); /* initialize combination boards that show multiple pieces. */ search.bishops_queens=Or(Or(Or(search.w_bishop,search.w_queen),search.b_bishop),search.b_queen); search.rooks_queens=Or(Or(Or(search.w_rook,search.w_queen),search.b_rook),search.b_queen); search.w_occupied=Or(Or(Or(Or(Or(search.w_pawn,search.w_knight),search.w_bishop),search.w_rook), search.w_queen),set_mask[search.white_king]); search.b_occupied=Or(Or(Or(Or(Or(search.b_pawn,search.b_knight),search.b_bishop),search.b_rook), search.b_queen),set_mask[search.black_king]); /* now initialize rotated occupied bitboards. */ search.occupied_rl90=0; search.occupied_rl45=0; search.occupied_rr45=0; for (i=0;i<64;i++) { if (search.board[i]) { search.occupied_rl90=Or(search.occupied_rl90,set_mask_rl90[i]); search.occupied_rl45=Or(search.occupied_rl45,set_mask_rl45[i]); search.occupied_rr45=Or(search.occupied_rr45,set_mask_rr45[i]); } } /* initialize black/white piece counts. */ search.white_pieces=0; search.white_pawns=0; search.black_pieces=0; search.black_pawns=0; search.material_evaluation=0; for (i=0;i<64;i++) { switch (search.board[i]) { case pawn: search.material_evaluation+=PAWN_VALUE; search.white_pawns+=pawn_v; break; case knight: search.material_evaluation+=KNIGHT_VALUE; search.white_pieces+=knight_v; break; case bishop: search.material_evaluation+=BISHOP_VALUE; search.white_pieces+=bishop_v; break; case rook: search.material_evaluation+=ROOK_VALUE; search.white_pieces+=rook_v; break; case queen: search.material_evaluation+=QUEEN_VALUE; search.white_pieces+=queen_v; break; case -pawn: search.material_evaluation-=PAWN_VALUE; search.black_pawns+=pawn_v; break; case -knight: search.material_evaluation-=KNIGHT_VALUE; search.black_pieces+=knight_v; break; case -bishop: search.material_evaluation-=BISHOP_VALUE; search.black_pieces+=bishop_v; break; case -rook: search.material_evaluation-=ROOK_VALUE; search.black_pieces+=rook_v; break; case -queen: search.material_evaluation-=QUEEN_VALUE; search.black_pieces+=queen_v; break; default: ; } } TotalPieces=PopCnt(Occupied); if (new_pos == &position[0]) { rephead_b=replist_b; rephead_w=replist_w; } }
void InitializeAttackBoards(void) { int i, j, frank, ffile, trank, tfile; int sq, lastsq; int knightsq[8]={-17,-15,-10,-6,6,10,15,17}; int bishopsq[4]={-9,-7,7,9}; int rooksq[4]={-8,-1,1,8}; BITBOARD sqs; /* initialize pawn attack boards */ for(i=0;i<64;i++) { w_pawn_attacks[i]=0; if (i < 56) for(j=2;j<4;j++) { sq=i+bishopsq[j]; if((abs(sq/8-i/8)==1) && (abs((sq&7) - (i&7))==1) && (sq < 64) && (sq > -1)) w_pawn_attacks[i]=Or(w_pawn_attacks[i],Shiftr(mask_1,sq)); } b_pawn_attacks[i]=0; if (i > 7) for(j=0;j<2;j++) { sq=i+bishopsq[j]; if((abs(sq/8-i/8)==1) && (abs((sq&7)-(i&7))==1) && (sq < 64) && (sq > -1)) b_pawn_attacks[i]=Or(b_pawn_attacks[i],Shiftr(mask_1,sq)); } } /* initialize knight attack board */ for(i=0;i<64;i++) { knight_attacks[i]=0; frank=i/8; ffile=i&7; for(j=0;j<8;j++) { sq=i+knightsq[j]; if((sq < 0) || (sq > 63)) continue; trank=sq/8; tfile=sq&7; if((abs(frank-trank) > 2) || (abs(ffile-tfile) > 2)) continue; knight_attacks[i]=Or(knight_attacks[i],Shiftr(mask_1,sq)); } } /* initialize bishop/queen attack boards and masks */ for(i=0;i<64;i++) { bishop_attacks[i]=0; for(j=0;j<4;j++) { sq=i; lastsq=sq; sq=sq+bishopsq[j]; while((abs(sq/8-lastsq/8)==1) && (abs((sq&7)-(lastsq&7))==1) && (sq < 64) && (sq > -1)) { bishop_attacks[i]=Or(bishop_attacks[i],Shiftr(mask_1,sq)); queen_attacks[i]=Or(queen_attacks[i],Shiftr(mask_1,sq)); if(bishopsq[j]==7) plus7dir[i]=Or(plus7dir[i],Shiftr(mask_1,sq)); else if(bishopsq[j]==9) plus9dir[i]=Or(plus9dir[i],Shiftr(mask_1,sq)); else if(bishopsq[j]==-7) minus7dir[i]=Or(minus7dir[i],Shiftr(mask_1,sq)); else minus9dir[i]=Or(minus9dir[i],Shiftr(mask_1,sq)); lastsq=sq; sq=sq+bishopsq[j]; } } } plus1dir[64]=0; plus7dir[64]=0; plus8dir[64]=0; plus9dir[64]=0; minus1dir[64]=0; minus7dir[64]=0; minus8dir[64]=0; minus9dir[64]=0; /* initialize rook/queen attack boards */ for(i=0;i<64;i++) { rook_attacks[i]=0; for(j=0;j<4;j++) { sq=i; lastsq=sq; sq=sq+rooksq[j]; while((((abs(sq/8-lastsq/8)==1) && (abs((sq&7)-(lastsq&7))==0)) || ((abs(sq/8-lastsq/8)==0) && (abs((sq&7)-(lastsq&7))==1))) && (sq < 64) && (sq > -1)) { rook_attacks[i]=Or(rook_attacks[i],Shiftr(mask_1,sq)); queen_attacks[i]=Or(queen_attacks[i],Shiftr(mask_1,sq)); if(rooksq[j]==1) plus1dir[i]=Or(plus1dir[i],Shiftr(mask_1,sq)); else if(rooksq[j]==8) plus8dir[i]=Or(plus8dir[i],Shiftr(mask_1,sq)); else if(rooksq[j]==-1) minus1dir[i]=Or(minus1dir[i],Shiftr(mask_1,sq)); else minus8dir[i]=Or(minus8dir[i],Shiftr(mask_1,sq)); lastsq=sq; sq=sq+rooksq[j]; } } } /* initialize king attack board */ for(i=0;i<64;i++) { king_attacks[i]=0; king_attacks_1[i]=0; king_attacks_2[i]=0; for (j=0;j<64;j++) { if (Distance(i,j) == 1) king_attacks[i]=Or(king_attacks[i],set_mask[j]); if (Distance(i,j) <= 1) king_attacks_1[i]=Or(king_attacks_1[i],set_mask[j]); if (Distance(i,j) <= 2) king_attacks_2[i]=Or(king_attacks_2[i],set_mask[j]); } } /* direction[sq1][sq2] gives the "move direction" to move from sq1 to sq2. obstructed[sq1][sq2] gives a bit vector that indicates which squares must be unoccupied in order for <sq1> to attack <sq2>, assuming a sliding piece is involved. to use this, you simply have to Or(obstructed[sq1][sq2],occupied_squares) and if the result is "0" then a sliding piece on sq1 would attack sq2 and vice-versa. */ for (i=0;i<64;i++) { for (j=0;j<64;j++) obstructed[i][j]=(BITBOARD) -1; sqs=plus1dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=1; obstructed[i][j]=Xor(plus1dir[i],plus1dir[j-1]); Clear(j,sqs); } sqs=plus7dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=7; obstructed[i][j]=Xor(plus7dir[i],plus7dir[j-7]); Clear(j,sqs); } sqs=plus8dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=8; obstructed[i][j]=Xor(plus8dir[i],plus8dir[j-8]); Clear(j,sqs); } sqs=plus9dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=9; obstructed[i][j]=Xor(plus9dir[i],plus9dir[j-9]); Clear(j,sqs); } sqs=minus1dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=-1; obstructed[i][j]=Xor(minus1dir[i],minus1dir[j+1]); Clear(j,sqs); } sqs=minus7dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=-7; obstructed[i][j]=Xor(minus7dir[i],minus7dir[j+7]); Clear(j,sqs); } sqs=minus8dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=-8; obstructed[i][j]=Xor(minus8dir[i],minus8dir[j+8]); Clear(j,sqs); } sqs=minus9dir[i]; while (sqs) { j=FirstOne(sqs); directions[i][j]=-9; obstructed[i][j]=Xor(minus9dir[i],minus9dir[j+9]); Clear(j,sqs); } } { int diag_sq[64] = { 0, 1, 0, 2, 1, 0, 3, 2, 1, 0, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 6, 5, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0, 4, 3, 2, 1, 0, 3, 2, 1, 0, 2, 1, 0, 1, 0, 0 }; int bias_rl45[64] = { 0, 1, 1, 3, 3, 3, 6, 6, 6, 6, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 21, 21, 21, 28, 28, 28, 28, 28, 28, 28, 28, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 49, 49, 49, 49, 49, 54, 54, 54, 54, 58, 58, 58, 61, 61, 63 }; int square, pcs, attacks; int rsq, tsq; int mask; /* initialize the rotated attack board that is based on the normal chess */ for (square=0;square<64;square++) { for (i=0;i<256;i++) { rook_attacks_r0[square][i]=0; rook_mobility_r0[square][i]=0; } for (pcs=0;pcs<256;pcs++) { attacks=InitializeFindAttacks(7-File(square),pcs,8); while (attacks) { sq=first_ones_8bit[attacks]; rook_attacks_r0[square][pcs]= Or(rook_attacks_r0[square][pcs],set_mask[(square&56)+sq]); attacks=attacks&(~(1<<(7-sq))); } rook_mobility_r0[square][pcs]=PopCnt(rook_attacks_r0[square][pcs]); } } /* initialize the rotated attack board that is based on one that rotated left 90 degrees (which lines up a file horizontally, rather than its normal vertical orientation.) */ for (square=0;square<64;square++) { for (i=0;i<256;i++) { rook_attacks_rl90[square][i]=0; rook_mobility_rl90[square][i]=0; } for (pcs=0;pcs<256;pcs++) { attacks=InitializeFindAttacks(Rank(square),pcs,8); while (attacks) { sq=first_ones_8bit[attacks]; rook_attacks_rl90[square][pcs]= Or(rook_attacks_rl90[square][pcs], set_mask[init_r90[((square&7)<<3)+sq]]); attacks=attacks&(~(1<<(7-sq))); } rook_mobility_rl90[square][pcs]=PopCnt(rook_attacks_rl90[square][pcs]); } } /* initialize the rotated attack board that is based on one that is rotated left 45 degrees (which lines up the (a8-h1) diagonal horizontally. */ for (square=0;square<64;square++) { for (i=0;i<256;i++) { bishop_attacks_rl45[square][i]=0; bishop_mobility_rl45[square][i]=0; } for (pcs=0;pcs<(1<<diagonal_length[init_l45[square]]);pcs++) { rsq=init_l45[square]; tsq=diag_sq[rsq]; attacks=InitializeFindAttacks(tsq,pcs,diagonal_length[rsq])<< (8-diagonal_length[rsq]); while (attacks) { sq=first_ones_8bit[attacks]; bishop_attacks_rl45[square][pcs]= Or(bishop_attacks_rl45[square][pcs], set_mask[init_ul45[sq+bias_rl45[rsq]]]); attacks=attacks&(~(1<<(7-sq))); } } mask=(1<<diagonal_length[init_l45[square]])-1; for (pcs=0;pcs<256;pcs++) { if ((pcs&mask) != pcs) bishop_attacks_rl45[square][pcs]= bishop_attacks_rl45[square][pcs&mask]; bishop_mobility_rl45[square][pcs]= PopCnt(bishop_attacks_rl45[square][pcs]); } } /* initialize the rotated attack board that is based on one that is rotated right 45 degrees (which lines up the (a1-h8) diagonal horizontally, */ for (square=0;square<64;square++) { for (i=0;i<256;i++) { bishop_attacks_rr45[square][i]=0; bishop_mobility_rr45[square][i]=0; } for (pcs=0;pcs<(1<<diagonal_length[init_r45[square]]);pcs++) { rsq=init_r45[square]; tsq=diag_sq[rsq]; attacks=InitializeFindAttacks(tsq,pcs,diagonal_length[rsq])<< (8-diagonal_length[rsq]); while (attacks) { sq=first_ones_8bit[attacks]; bishop_attacks_rr45[square][pcs]= Or(bishop_attacks_rr45[square][pcs], set_mask[init_ur45[sq+bias_rl45[rsq]]]); attacks=attacks&(~(1<<(7-sq))); } } mask=(1<<diagonal_length[init_r45[square]])-1; for (pcs=0;pcs<256;pcs++) { if ((pcs&mask) != pcs) bishop_attacks_rr45[square][pcs]= bishop_attacks_rr45[square][pcs&mask]; bishop_mobility_rr45[square][pcs]= PopCnt(bishop_attacks_rr45[square][pcs]); } } } }