inline Bitboard in_between(Index a, Index b) { // from https://chessprogramming.wikispaces.com/Square+Attacked+By#Obstructed // haven't taken the time to understand auto in_between_fn = [](Index sq1, Index sq2) { const Bitboard m1 = Bitboard(-1); const Bitboard a2a7 = Bitboard(0x0001010101010100); const Bitboard b2g7 = Bitboard(0x0040201008040200); const Bitboard h1b7 = Bitboard(0x0002040810204080); /* Thanks Dustin, g2b7 did not work for c1-a3 */ Bitboard btwn, line, rank, file; btwn = (m1 << sq1) ^ (m1 << sq2); file = (sq2 & 7) - (sq1 & 7); rank = ((sq2 | 7) - sq1) >> 3 ; line = ( (file & 7) - 1) & a2a7; /* a2a7 if same file */ line += 2 * (( (rank & 7) - 1) >> 58); /* b1g1 if same rank */ line += (((rank - file) & 15) - 1) & b2g7; /* b2g7 if same diagonal */ line += (((rank + file) & 15) - 1) & h1b7; /* h1b7 if same antidiag */ line *= btwn & -btwn; /* mul acts like shift by smaller square */ return line & btwn; /* return the bits on that line in-between */ }; static auto _in_between = [&]() { array2d<Bitboard, cardinality, cardinality> result; for (Index a: indices) for (Index b: indices) result[a][b] = in_between_fn(a, b); return result; }(); return _in_between[a][b]; }
/*attacked() returns 1 if square 'target' is attacked by color 'color' and 0 otherwise*/ int attacked(const int target, const int color) { int c; unsigned __int64 all; all = Bitboard(BLACK) | Bitboard(WHITE); for (c = 0;c < 16;c++) { if (Active(color, c)) { assert(Name(color,0)==king); if (c>0) assert(Name(color,c)!=king); if (Kind(color, c)&table_attack[target - Position(color, c) + 128]) { if (IsNoSlide(color, c)) return 1; if ((all&(bit_ray[Position(color, c)][target])) == 0) return 1; } } } switch (color) { case BLACK: if (File(target) != FilaA && IsBPawn(target + UP_L)) return 1; if (File(target) != FilaH && IsBPawn(target + UP_R)) return 1; break; case WHITE: if (File(target) != FilaA && IsWPawn(target + DOWN_L)) return 1; if (File(target) != FilaH && IsWPawn(target + DOWN_R)) return 1; break; case EMPTY: printf("Bad color board detect in attacked(): %d",color); assert(0); break; default: printf("Bad color board detect in attacked(): %d",color); assert(0); break; } return 0; }
Bitboard operator ~ () const { #if defined (HAVE_SSE2) || defined (HAVE_SSE4) Bitboard tmp; _mm_store_si128(&tmp.m_, _mm_andnot_si128(this->m_, _mm_set1_epi8(static_cast<char>(0xffu)))); return tmp; #else return Bitboard(~this->p(0), ~this->p(1)); #endif }
ExtMove* generate(const Position& pos, ExtMove* mlist) { assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS); assert(!pos.checkers()); Color us = pos.side_to_move(); Bitboard target = Type == CAPTURES ? pos.pieces(~us) : Type == QUIETS ? ~pos.pieces() : Type == NON_EVASIONS ? ~pos.pieces(us) : Bitboard(); return us == WHITE ? generate_all<WHITE, Type>(pos, mlist, target) : generate_all<BLACK, Type>(pos, mlist, target); }
/** * @return the Bitboard b, bitwise XOR with amount */ inline Bitboard operator^(Bitboard b,UINT_64 amount) { return Bitboard(b.bits.to_ulong() ^ amount); }
/** * @return the Bitboard a, bitwise OR with Bitboard b */ inline Bitboard operator|(Bitboard a,Bitboard b) { return Bitboard(a.bits | b.bits); }
/** * @return the bitwise complement of Bitboard b */ inline Bitboard operator~(Bitboard b) { return Bitboard(~b.bits); }
*/ inline bool operator==(Bitboard a,Bitboard b) { return a.bits == b.bits; } /** * @return whether Bitboard a does not equal Bitboard b */ inline bool operator!=(Bitboard a,Bitboard b) { return a.bits != b.bits; } /** * a Bitboard masking the A rank, e.g. to get a bitboard and ignore * the A rank, do calc_result = calc_result & NOT_A_MASK */ static const Bitboard NOT_A_MASK = Bitboard(0xfefefefefefefefeULL); /** * a Bitboard masking the H rank, e.g. to get a bitboard and ignore * the A rank, do calc_result = calc_result & NOT_H_MASK */ static const Bitboard NOT_H_MASK = Bitboard(0x7f7f7f7f7f7f7f7fULL); // implementations of Bitboard:: bit shifts below inline Bitboard Bitboard::nortOne() { return *this << 8; } inline Bitboard Bitboard::eastOne() { return (*this << 1) & NOT_A_MASK; }
int ThreadPool::activeCount() const { return Bitboard(activeMask & availableMask).bitCount(); }
/* Riporta la scacchiera e le altre strutture dati alla situazione precedente */ void unmakemove() { MOVE m; unsigned char from, to, del; char was; assert(Name(WHITE,0)==king); assert(Name(BLACK,0)==king); Ply--; N_moves--; Change(Side); Change(Xside); Hash = BHash(N_moves); Cste = BCste(N_moves); Cstr = tree.history[N_moves].cast.castle_right; Enp = tree.history[N_moves].enp; tree.fifty = tree.history[N_moves].fifty; Material(Side) = tree.history[N_moves].material[Side]; Material(Xside) = tree.history[N_moves].material[Xside]; m.mi = tree.history[N_moves].m.mi; was = tree.history[N_moves].was; from = m.ms.from; to = m.ms.to; Num_piece(Side, was)++; Num_piece(Side, Piece(to))--; Piece(from) = Piece(to); if (Piece(from)!=was)Piece(from)=was; Color(from) = Color(to); Plist(from) = Plist(to); Position((Color(from)), (Plist(from))) = from; Piece(to) = no_piece; Color(to) = EMPTY; Plist(to) = no_list; Bitboard(Side) = BBitb(N_moves, Side); Pbitboard(Side) = BPBitb(N_moves, Side); Pbitboard(Xside) = BPBitb(N_moves, Xside); if (m.ms.flag & M_CAP) { del = tree.history[N_moves].del; Piece(del) = BCapP(N_moves); Color(del) = BCapC(N_moves); Plist(del) = BCapPos(N_moves); Active((Color(del)), (Plist(del))) = FREE; Position((Color(del)), (Plist(del))) = del; Num_piece(Xside, Piece(del))++; Bitboard(Xside) = BBitb(N_moves, Xside); assert(Name(Side,0)==king); assert(Name(Xside,0)==king); } assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (m.ms.flag & (M_OO | M_OOO)) { switch (m.ms.to) { case C8: from = D8; to = A8; break; case G8: from = F8; to = H8; break; case C1: from = D1; to = A1; break; case G1: from = F1; to = H1; break; default: puts("Bad castle request."); assert(0); } Piece(to) = rook; Color(to) = Side; Plist(to) = Plist(from); Position((Color(to)), (Plist(to))) = to; Piece(from) = no_piece; Color(from) = EMPTY; Plist(from) = no_list; } assert(Name(WHITE,0)==king); assert(Name(BLACK,0)==king); }
/* check_condition() sets tree.check[Side][Ply] if king of side to move is in check and it sets tree.verify[Ply] if it is in check or under 'x-ray' attack */ void check_condition() { int c, from, dir, target, tmp_incheck, tmp_xattack, num_pieces, prob_xattack; unsigned __int64 all; tmp_incheck = 0; tmp_xattack = 0; target = Position(Side, 0); all = Bitboard(BLACK) | Bitboard(WHITE); assert(Name(Side,0)==king); for (c = 0;c < 16;c++) { if (Active(Xside, c)) { assert(Name(Xside,0)==king); if (c>0) assert(Name(Xside,c)!=king); /*controlla se il pezzo puo' attaccare*/ if (Kind(Xside, c)&table_attack[target - Position(Xside, c) + 128]) { /*se e' un pezzo no-slide è sotto scacco*/ if (IsNoSlide(Xside, c)) { tmp_incheck++; break; } /*se e' un pezzo slide dobbiamo controllare*/ if ((all&(bit_ray[Position(Xside, c)][target])) == 0) { tmp_incheck++; break; } from = Position(Xside, c); dir = direction[target - from + 128]; num_pieces = 0; prob_xattack = 0; from += dir; while (from != target) { if (Piece(from) != no_piece) { num_pieces++; if (num_pieces == 1 && Color(from) == Side) prob_xattack = 1; if (num_pieces > 1) break; } from += dir; } if (num_pieces == 1 && prob_xattack == 1) tmp_xattack++; } } } switch (Xside) { case BLACK: if (File(target) != FilaA && IsBPawn(target + UP_L)) { tmp_incheck++; break; } if (File(target) != FilaH && IsBPawn(target + UP_R)) tmp_incheck++; break; case WHITE: if (File(target) != FilaA && IsWPawn(target + DOWN_L)) { tmp_incheck++; break; } if (File(target) != FilaH && IsWPawn(target + DOWN_R)) tmp_incheck++; break; case EMPTY: printf("Bad color board detect in checkcondition(): %d",Xside); assert(0); break; default: printf("Bad color board detect in checkcondition(): %d",Xside); assert(0); break; } /*E' sotto scacco?*/ tree.check[Side][Ply] = tmp_incheck; /*Nella makemove() dobbiamo verificare la legalita'?*/ tree.verify[Ply] = tmp_incheck + tmp_xattack; }
// dataInit() // // Initialization of global data at program startup. // This function should be called only once (or else the mirrored data will be // mirrored back again!!) void dataInit() { unsigned char CHARBITSET[8]; int i, square, rank, file, arank, afile, state, slide, diaga1h8, diaga8h1, attackbit; unsigned char state6Bit, state8Bit, attack8Bit; Move move; board.searchDepth = AI_SEARCH_DEPTH; // default for startup board.maxTime = TIME_PER_MOVE * 1000; // default for startup, milliseconds // BITSET has only one bit set: BITSET[0] = 0x1; for (i = 1; i < 64 ; i++) BITSET[i] = BITSET[i-1] << 1; // BOARDINDEX is used to translate [file][rank] to [square], // Note that file is from 1..8 and rank from 1..8 (not starting from 0) for (rank = 0 ; rank < 9; rank++) for (file = 0 ; file < 9; file++) BOARDINDEX[file][rank] = (rank-1) * 8 + file - 1; // PIECEVALUES are used in quiesence move ordering only: for (i = 0; i < 16 ; i++) PIECEVALUES[i] = 0; PIECEVALUES[WHITE_PAWN] = PAWN_VALUE; PIECEVALUES[WHITE_KNIGHT] = KNIGHT_VALUE; PIECEVALUES[WHITE_BISHOP] = BISHOP_VALUE; PIECEVALUES[WHITE_ROOK] = ROOK_VALUE; PIECEVALUES[WHITE_QUEEN] = QUEEN_VALUE; PIECEVALUES[WHITE_KING] = KING_VALUE; PIECEVALUES[BLACK_PAWN] = PAWN_VALUE; PIECEVALUES[BLACK_KNIGHT] = KNIGHT_VALUE; PIECEVALUES[BLACK_BISHOP] = BISHOP_VALUE; PIECEVALUES[BLACK_ROOK] = ROOK_VALUE; PIECEVALUES[BLACK_QUEEN] = QUEEN_VALUE; PIECEVALUES[BLACK_KING] = KING_VALUE; // initialize MS1BTABLE, used in lastOne (see bitops.cpp) for (i = 0; i < 256; i++) { MS1BTABLE[i] = ( (i > 127) ? 7 : (i > 63) ? 6 : (i > 31) ? 5 : (i > 15) ? 4 : (i > 7) ? 3 : (i > 3) ? 2 : (i > 1) ? 1 : 0 ); } // initialize rank, file and diagonal 6-bit masking Bitboards, to get the // occupancy state, used in the movegenerator (see movegen.ccp) for (square = 0; square < 64; square++) { RANKMASK[square] = 0x0; FILEMASK[square] = 0x0; DIAGA8H1MASK[square] = 0x0; DIAGA1H8MASK[square] = 0x0; FILEMAGIC[square] = 0x0; DIAGA8H1MAGIC[square] = 0x0; DIAGA1H8MAGIC[square] = 0x0; } for (file = 1; file < 9; file++) { for (rank = 1; rank < 9; rank++) { // initialize 6-bit rank mask, used in the movegenerator (see movegen.ccp) RANKMASK[BOARDINDEX[file][rank]] = BITSET[BOARDINDEX[2][rank]] | BITSET[BOARDINDEX[3][rank]] | BITSET[BOARDINDEX[4][rank]] ; RANKMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[5][rank]] | BITSET[BOARDINDEX[6][rank]] | BITSET[BOARDINDEX[7][rank]] ; // initialize 6-bit file mask, used in the movegenerator (see movegen.ccp) FILEMASK[BOARDINDEX[file][rank]] = BITSET[BOARDINDEX[file][2]] | BITSET[BOARDINDEX[file][3]] | BITSET[BOARDINDEX[file][4]] ; FILEMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[file][5]] | BITSET[BOARDINDEX[file][6]] | BITSET[BOARDINDEX[file][7]] ; // initialize diagonal magic multiplication numbers, used in the movegenerator (see movegen.ccp) diaga8h1 = file + rank; // from 2 to 16, longest diagonal = 9 DIAGA8H1MAGIC[BOARDINDEX[file][rank]] = _DIAGA8H1MAGICS[diaga8h1 - 2]; // initialize 6-bit diagonal mask, used in the movegenerator (see movegen.ccp) DIAGA8H1MASK[BOARDINDEX[file][rank]] = 0x0; // lower half, diagonals 2 to 9 if (diaga8h1 < 10) { for (square = 2 ; square < diaga8h1-1 ; square ++) DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][diaga8h1-square]]; } // upper half, diagonals 10 to 16 else { for (square = 2 ; square < 17 - diaga8h1 ; square ++) DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga8h1+square-9][9-square]]; } // initialize diagonal magic multiplication numbers, used in the movegenerator (see movegen.ccp) diaga1h8 = file - rank; // from -7 to +7, longest diagonal = 0 DIAGA1H8MAGIC[BOARDINDEX[file][rank]] = _DIAGA1H8MAGICS[diaga1h8+7]; // initialize 6-bit diagonal mask, used in the movegenerator (see movegen.ccp) DIAGA1H8MASK[BOARDINDEX[file][rank]] = 0x0; // lower half, diagonals 0 to 7 if (diaga1h8 > -1) { for (square = 2 ; square < 8 - diaga1h8 ; square ++) { DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga1h8 + square][square]]; } } else { for (square = 2 ; square < 8 + diaga1h8 ; square ++) { DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][square - diaga1h8]]; } } // initialize file magic multiplication numbers, used in the movegenerator (see movegen.ccp) FILEMAGIC[BOARDINDEX[file][rank]] = _FILEMAGICS[file-1]; } } // Now initialize the GEN_SLIDING_ATTACKS array, used to generate the sliding // attack bitboards. // unsigned char GEN_SLIDING_ATTACKS[8 squares][64 states] holds the attacks // for any file, rank or diagonal - it is going to be usefull when generating the // RANK_ATTACKS[64][64], FILE_ATTACKS[64][64], DIAGA8H1_ATTACKS[64][64] and // DIAGA1H8_ATTACKS[64][64] arrays // initialize CHARBITSET, this array is equivalant to BITSET for bitboards: // 8 chars, each with only 1 bit set. CHARBITSET[0] = 1; for (square = 1; square <= 7; square++) { CHARBITSET[square] = CHARBITSET[square-1] << 1; } // loop over rank, file or diagonal squares for (square = 0; square <= 7; square++) { // loop of occupancy states // state6Bit represents the 64 possible occupancy states of a rank, // except the 2 end-bits, because they don't matter for calculating attacks for (state6Bit = 0; state6Bit < 64; state6Bit++) { state8Bit = state6Bit << 1; // create an 8-bit occupancy state attack8Bit = 0; if (square < 7) { attack8Bit |= CHARBITSET[square + 1]; } slide = square + 2; while (slide <= 7) // slide in '+' direction { if ((~state8Bit) & (CHARBITSET[slide - 1])) attack8Bit |= CHARBITSET[slide]; else break; slide++; } if (square > 0) { attack8Bit |= CHARBITSET[square - 1]; } slide = square - 2; while (slide >= 0) // slide in '-' direction { if ((~state8Bit) & (CHARBITSET[slide + 1])) attack8Bit |= CHARBITSET[slide]; else break; slide--; } GEN_SLIDING_ATTACKS[square][state6Bit] = attack8Bit; } } // initialize all attack Bitboards, used in the movegenerator (see movegen.ccp) for (square = 0; square < 64; square++) { KNIGHT_ATTACKS[square] = 0x0; KING_ATTACKS[square] = 0x0; WHITE_PAWN_ATTACKS[square] = 0x0; WHITE_PAWN_MOVES[square] = 0x0; WHITE_PAWN_DOUBLE_MOVES[square] = 0x0; BLACK_PAWN_ATTACKS[square] = 0x0; BLACK_PAWN_MOVES[square] = 0x0; BLACK_PAWN_DOUBLE_MOVES[square] = 0x0; for (state = 0; state < 64; state++) { RANK_ATTACKS[square][state] = 0x0; FILE_ATTACKS[square][state] = 0x0; DIAGA8H1_ATTACKS[square][state] = 0x0; DIAGA1H8_ATTACKS[square][state] = 0x0; } } // white pawn attacks for (square = 0; square < 64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file - 1; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) WHITE_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) WHITE_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; } // white pawn moves for (square = 0; square <64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) WHITE_PAWN_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]]; if (rank == 2) { afile = file; arank = rank + 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) WHITE_PAWN_DOUBLE_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]]; } } // black pawn attacks for (square = 0; square < 64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file - 1; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) BLACK_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) BLACK_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; } // black pawn moves for (square = 0; square < 64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) BLACK_PAWN_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]]; if (rank == 7) { afile = file; arank = rank - 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) BLACK_PAWN_DOUBLE_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]]; } } // knight attacks for (square = 0; square < 64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file - 2; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file - 1; arank = rank + 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank + 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 2; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 2; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank - 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file - 1; arank = rank - 2; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file - 2; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; } // king attacks for (square = 0; square < 64; square++) { file = FILES[square]; rank = RANKS[square]; afile = file - 1; arank = rank; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file - 1; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank + 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file + 1; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; afile = file - 1; arank = rank - 1; if ((afile >= 1) & (afile <= 8) & (arank >= 1) & (arank <= 8)) KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]]; } // RANK attacks (ROOKS and QUEENS): // use unsigned char GEN_SLIDING_ATTACKS[8 squares][64 states] // to initialize Bitboard RANK_ATTACKS[64 squares][64 states] for (square = 0; square < 64; square++) { for (state6Bit = 0; state6Bit < 64; state6Bit++) { RANK_ATTACKS[square][state6Bit] = 0; RANK_ATTACKS[square][state6Bit] |= Bitboard(GEN_SLIDING_ATTACKS[FILES[square]-1][state6Bit]) << (RANKSHIFT[square] - 1); } } // FILE attacks (ROOKS and QUEENS): // use unsigned char GEN_SLIDING_ATTACKS[8 squares][64 states] // to initialize Bitboard FILE_ATTACKS[64 squares][64 states] // // Occupancy transformation is as follows: // // occupancy state bits of the file: occupancy state bits in GEN_SLIDING_ATTACKS: // // . . . . . . . . MSB LSB MSB // . . . . . A . . => A B C D E F . . // . . . . . B . . // . . . . . C . . // . . . . . D . . // . . . . . E . . // . . . . . F . . // LSB . . . . . . . . // // The reverse transformation is as follows: // // attack bits in GEN_SLIDING_ATTACKS: attack bits in the file: // // LSB MSB . . . . . m . . MSB // m n o p q r s t => . . . . . n . . // . . . . . o . . // . . . . . p . . // . . . . . q . . // . . . . . r . . // . . . . . s . . // LSB . . . . . t . . // for (square = 0; square < 64; square++) { for (state6Bit = 0; state6Bit < 64; state6Bit++) { FILE_ATTACKS[square][state6Bit] = 0x0; // check to see if attackbit'-th bit is set in GEN_SLIDING_ATTACKS, for this combination of square/occupancy state for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB { // conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: "8-RANKS[square]" if (GEN_SLIDING_ATTACKS[8-RANKS[square]][state6Bit] & CHARBITSET[attackbit]) { // the bit is set, so we need to update FILE_ATTACKS accordingly: // conversion of square/attackbit to the corresponding 64 board FILE: FILES[square] // conversion of square/attackbit to the corresponding 64 board RANK: 8-attackbit file = FILES[square]; rank = 8 - attackbit; FILE_ATTACKS[square][state6Bit] |= BITSET[BOARDINDEX[file][rank]]; } } } } // DIAGA8H1_ATTACKS attacks (BISHOPS and QUEENS) for (square = 0; square < 64; square++) { for (state6Bit = 0; state6Bit < 64; state6Bit++) { DIAGA8H1_ATTACKS[square][state6Bit] = 0x0; for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB { // conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: MIN((8-RANKS[square]),(FILES[square]-1)) if (GEN_SLIDING_ATTACKS[(8-RANKS[square]) < (FILES[square]-1) ? (8-RANKS[square]) : (FILES[square]-1)][state6Bit] & CHARBITSET[attackbit]) { // the bit is set, so we need to update FILE_ATTACKS accordingly: // conversion of square/attackbit to the corresponding 64 board file and rank: diaga8h1 = FILES[square] + RANKS[square]; // from 2 to 16, longest diagonal = 9 if (diaga8h1 < 10) { file = attackbit + 1; rank = diaga8h1 - file; } else { rank = 8 - attackbit; file = diaga8h1 - rank; } if ((file > 0) && (file < 9) && (rank > 0) && (rank < 9)) { DIAGA8H1_ATTACKS[square][state6Bit] |= BITSET[BOARDINDEX[file][rank]]; } } } } } // DIAGA1H8_ATTACKS attacks (BISHOPS and QUEENS) for (square = 0; square < 64; square++) { for (state6Bit = 0; state6Bit < 64; state6Bit++) { DIAGA1H8_ATTACKS[square][state6Bit] = 0x0; for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB { // conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: MIN((8-RANKS[square]),(FILES[square]-1)) if (GEN_SLIDING_ATTACKS[(RANKS[square]-1) < (FILES[square]-1) ? (RANKS[square]-1) : (FILES[square]-1)][state6Bit] & CHARBITSET[attackbit]) { // the bit is set, so we need to update FILE_ATTACKS accordingly: // conversion of square/attackbit to the corresponding 64 board file and rank: diaga1h8 = FILES[square] - RANKS[square]; // from -7 to 7, longest diagonal = 0 if (diaga1h8 < 0) { file = attackbit + 1; rank = file - diaga1h8; } else { rank = attackbit + 1; file = diaga1h8 + rank; } if ((file > 0) && (file < 9) && (rank > 0) && (rank < 9)) { DIAGA1H8_ATTACKS[square][state6Bit] |= BITSET[BOARDINDEX[file][rank]]; } } } } } // Masks for castling, index 0 is for white, 1 is for black maskEG[0] = BITSET[E1] | BITSET[F1] | BITSET[G1]; maskEG[1] = BITSET[E8] | BITSET[F8] | BITSET[G8]; maskFG[0] = BITSET[F1] | BITSET[G1]; maskFG[1] = BITSET[F8] | BITSET[G8]; maskBD[0] = BITSET[B1] | BITSET[C1] | BITSET[D1]; maskBD[1] = BITSET[B8] | BITSET[C8] | BITSET[D8]; maskCE[0] = BITSET[C1] | BITSET[D1] | BITSET[E1]; maskCE[1] = BITSET[C8] | BITSET[D8] | BITSET[E8]; // the 4 castling moves can be predefined move.clear(); move.setCapture(EMPTY); move.setPiece(WHITE_KING); move.setPromo(WHITE_KING); move.setFrom(E1); move.setTosq(G1); WHITE_OO_CASTL = move.moveInt; move.setTosq(C1); WHITE_OOO_CASTL = move.moveInt; move.setPiece(BLACK_KING); move.setPromo(BLACK_KING); move.setFrom(E8); move.setTosq(G8); BLACK_OO_CASTL = move.moveInt; move.setTosq(C8); BLACK_OOO_CASTL = move.moveInt; // initialize evaluation data & Bitboards BLACK_SQUARES = 0; for (i = 0; i < 64; i++) { if ((i + RANKS[i]) % 2) BLACK_SQUARES ^= BITSET[i]; } WHITE_SQUARES = ~BLACK_SQUARES; // clear Bitboards for (i = 0; i < 64; i++) { PASSED_WHITE[i] = 0; PASSED_BLACK[i] = 0; ISOLATED_WHITE[i] = 0; ISOLATED_BLACK[i] = 0; BACKWARD_WHITE[i] = 0; BACKWARD_BLACK[i] = 0; KINGSHIELD_STRONG_W[i] = 0; KINGSHIELD_STRONG_B[i] = 0; KINGSHIELD_WEAK_W[i] = 0; KINGSHIELD_WEAK_B[i] = 0; } for (i = 0; i < 64; i++) { // passed white for (rank = RANKS[i] + 1; rank < 8; rank++) { // 3 files if (FILES[i] - 1 > 0) PASSED_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] - 1][rank]]; PASSED_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i]][rank]]; if (FILES[i] + 1 < 9 ) PASSED_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] + 1][rank]]; } // isolated white for (rank = 2; rank < 8; rank++) { // 2 files if (FILES[i] - 1 > 0) ISOLATED_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] - 1][rank]]; if (FILES[i] + 1 < 9 ) ISOLATED_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] + 1][rank]]; } // backward white for (rank = 2; rank <= RANKS[i]; rank++) { // 2 files if (FILES[i] - 1 > 0) BACKWARD_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] - 1][rank]]; if (FILES[i] + 1 < 9 ) BACKWARD_WHITE[i] ^= BITSET[BOARDINDEX[FILES[i] + 1][rank]]; } } // pawn shield Bitboards for king safety, only if the king is on the first 3 ranks for (i = 0; i < 24; i++) { // KINGSHIELD_STRONG_W & KINGSHIELD_WEAK_W KINGSHIELD_STRONG_W[i] ^= BITSET[i + 8]; KINGSHIELD_WEAK_W[i] ^= BITSET[i + 16]; if (FILES[i] > 1) { KINGSHIELD_STRONG_W[i] ^= BITSET[i + 7]; KINGSHIELD_WEAK_W[i] ^= BITSET[i + 15]; } if (FILES[i] < 8) { KINGSHIELD_STRONG_W[i] ^= BITSET[i + 9]; KINGSHIELD_WEAK_W[i] ^= BITSET[i + 17]; } if (FILES[i]== 1) { KINGSHIELD_STRONG_W[i] ^= BITSET[i + 10]; KINGSHIELD_WEAK_W[i] ^= BITSET[i + 18]; } if (FILES[i]== 8) { KINGSHIELD_STRONG_W[i] ^= BITSET[i + 6]; KINGSHIELD_WEAK_W[i] ^= BITSET[i + 14]; } } // DISTANCE array, distance is measured as max of (rank,file)-difference for (i = 0 ; i < 64; i++) { for (square = 0 ; square < 64; square++) { if (abs(RANKS[i] - RANKS[square]) > abs(FILES[i] - FILES[square])) DISTANCE[i][square] = abs(RANKS[i] - RANKS[square]); else DISTANCE[i][square] = abs(FILES[i] - FILES[square]); } } // Initialize MIRRORed data: // Data is supplied as mirrored for WHITE, so it's ready for BLACK to use for (square = 0; square < 64; square++) { PAWNPOS_B[square] = PAWNPOS_W[square]; KNIGHTPOS_B[square] = KNIGHTPOS_W[square]; BISHOPPOS_B[square] = BISHOPPOS_W[square]; ROOKPOS_B[square] = ROOKPOS_W[square]; QUEENPOS_B[square] = QUEENPOS_W[square]; KINGPOS_B[square] = KINGPOS_W[square]; KINGPOS_ENDGAME_B[square] = KINGPOS_ENDGAME_W[square]; } // Complete missing mirrored data for (i = 0; i < 64; i++) { PAWNPOS_W[i] = PAWNPOS_B[MIRROR[i]]; KNIGHTPOS_W[i] = KNIGHTPOS_B[MIRROR[i]]; BISHOPPOS_W[i] = BISHOPPOS_B[MIRROR[i]]; ROOKPOS_W[i] = ROOKPOS_B[MIRROR[i]]; QUEENPOS_W[i] = QUEENPOS_B[MIRROR[i]]; KINGPOS_W[i] = KINGPOS_B[MIRROR[i]]; KINGPOS_ENDGAME_W[i] = KINGPOS_ENDGAME_B[MIRROR[i]]; for (square = 0; square < 64; square ++) { // PASSED_BLACK Bitboards (mirror of PASSED_WHITE // Bitboards) if (PASSED_WHITE[i] & BITSET[square]) PASSED_BLACK[MIRROR[i]] |= BITSET[MIRROR[square]]; // ISOLATED_BLACK Bitboards (mirror of ISOLATED_WHITE // Bitboards) if (ISOLATED_WHITE[i] & BITSET[square]) ISOLATED_BLACK[MIRROR[i]] |= BITSET[MIRROR[square]]; // BACKWARD_BLACK Bitboards (mirror of BACKWARD_WHITE // Bitboards): if (BACKWARD_WHITE[i] & BITSET[square]) BACKWARD_BLACK[MIRROR[i]] |= BITSET[MIRROR[square]]; // KINGSHIELD_STRONG_B Bitboards (mirror of KINGSHIELD_STRONG_W Bitboards): if (KINGSHIELD_STRONG_W[i] & BITSET[square]) KINGSHIELD_STRONG_B[MIRROR[i]] |= BITSET[MIRROR[square]]; // KINGSHIELD_WEAK_B Bitboards (mirror of KINGSHIELD_WEAK_W Bitboards): if (KINGSHIELD_WEAK_W[i] & BITSET[square]) KINGSHIELD_WEAK_B[MIRROR[i]] |= BITSET[MIRROR[square]]; } } NOMOVE.moveInt = 0; KEY.init(); // HEADINGS and RAYS, used in SEE for (i = 0 ; i < 64; i++) { RAY_W[i] = 0; RAY_NW[i] = 0; RAY_N[i] = 0; RAY_NE[i] = 0; RAY_E[i] = 0; RAY_SE[i] = 0; RAY_S[i] = 0; RAY_SW[i] = 0; for (square = 0 ; square < 64; square ++) { HEADINGS[i][square] = 0; } } for (rank = 1 ; rank < 9; rank++) for (file = 1 ; file < 9; file++) { i = BOARDINDEX[file][rank]; // WEST: for (afile = file - 1 ; afile > 0; afile--) { HEADINGS[i][BOARDINDEX[afile][rank]] = WEST; RAY_W[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][rank]]; } // NORTHWEST: for (afile = file - 1, arank = rank + 1 ; (afile > 0) && (arank < 9); afile--, arank++) { HEADINGS[i][BOARDINDEX[afile][arank]] = NORTHWEST; RAY_NW[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][arank]]; } // NORTH: for (arank = rank + 1 ; arank < 9; arank++) { HEADINGS[i][BOARDINDEX[file][arank]] = NORTH; RAY_N[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[file][arank]]; } // NORTHEAST: for (afile = file + 1, arank = rank + 1 ; (afile < 9) && (arank < 9); afile++, arank++) { HEADINGS[i][BOARDINDEX[afile][arank]] = NORTHEAST; RAY_NE[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][arank]]; } // EAST: for (afile = file + 1 ; afile < 9; afile++) { HEADINGS[i][BOARDINDEX[afile][rank]] = EAST; RAY_E[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][rank]]; } // SOUTHEAST: for (afile = file + 1, arank = rank - 1 ; (afile < 9) && (arank > 0); afile++, arank--) { HEADINGS[i][BOARDINDEX[afile][arank]] = SOUTHEAST; RAY_SE[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][arank]]; } // SOUTH: for (arank = rank - 1 ; arank > 0; arank--) { HEADINGS[i][BOARDINDEX[file][arank]] = SOUTH; RAY_S[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[file][arank]]; } // SOUTHWEST: for (afile = file - 1, arank = rank - 1 ; (afile > 0) && (arank > 0); afile--, arank--) { HEADINGS[i][BOARDINDEX[afile][arank]] = SOUTHWEST; RAY_SW[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[afile][arank]]; } } // required for running test suites, to prevent // writing escape characters to a file TO_CONSOLE = 1; // Winboard parameters: XB_NONE = 2; // not 0 or 1 XB_ANALYZE = 3; // not 0, 1, or 2 XB_MODE = false; XB_POST = true; XB_PONDER = false; XB_DO_PENDING = false; XB_NO_TIME_LIMIT = false; }
/*verifica che la mossa è una mossa possibile*/ int verify_move(const MOVE m) { unsigned __int64 all; all = Bitboard(BLACK) | Bitboard(WHITE); if (Color(m.ms.from) != Side) return 0; if (Piece(m.ms.to) == king) return 0; if (Piece(m.ms.from) == out_board || Piece(m.ms.from) == no_piece) return 0; switch (Piece(m.ms.from)) { case no_piece: return 0; case wpawn: if (m.ms.piece != wpawn && ((m.ms.flag & M_PRO)==0)) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==CAPTURED) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if (m.ms.flag & M_PAW) { if (m.ms.flag & M_CAP) { if (m.ms.flag & M_ENP) { if (Piece(m.ms.to + DOWN) != bpawn) return 0; if (Active(Xside,Plist(m.ms.to + DOWN))==CAPTURED) return 0; if (Position(Xside,Plist(m.ms.to + DOWN))!=(m.ms.to + DOWN)) return 0; if (Rank(m.ms.from) != Riga5) return 0; return 1; } if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==CAPTURED) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; if (Color(m.ms.to) != Xside) return 0; if (Piece(m.ms.to) == king) return 0; if (m.ms.to == m.ms.from + UP_R || m.ms.to == m.ms.from + UP_L) return 1; if (m.ms.flag & M_PRO && Rank(m.ms.from) != Riga7) return 0; return 1; } if (Color(m.ms.to) != EMPTY) return 0; if (m.ms.flag & M_DBP) { if (Rank(m.ms.from) != Riga2) return 0; if (Color(m.ms.to + DOWN) != EMPTY) return 0; return 1; } if (m.ms.to == m.ms.from + UP) return 1; return 0; } return 0; case bpawn: if (m.ms.piece != bpawn && ((m.ms.flag & M_PRO)==0)) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if (m.ms.flag & M_PAW) { if (m.ms.flag & M_CAP) { if (m.ms.flag & M_ENP) { if (Piece(m.ms.to + UP) != wpawn) return 0; if (Active(Xside,Plist(m.ms.to + UP))==CAPTURED) return 0; if (Position(Xside,Plist(m.ms.to + UP))!=(m.ms.to + UP)) return 0; if (Rank(m.ms.from) != Riga4) return 0; return 1; } if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; if (Color(m.ms.to) != Xside) return 0; if (Piece(m.ms.to) == king) return 0; if (m.ms.to == m.ms.from + DOWN_R || m.ms.to == m.ms.from + DOWN_L) return 1; if (m.ms.flag & M_PRO && Rank(m.ms.from) != Riga2) return 0; return 1; } if (Color(m.ms.to) != EMPTY) return 0; if (m.ms.flag & M_DBP) { if (Rank(m.ms.from) != Riga7) return 0; if (Color(m.ms.to + UP) != EMPTY) return 0; return 1; } if (m.ms.to == m.ms.from + DOWN) return 1; return 0; } return 0; case knight: if (m.ms.piece != knight) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if ((m.ms.flag == M_STD) && Color(m.ms.to) != EMPTY) return 0; if ((m.ms.flag & M_CAP) && Color(m.ms.to) != Xside) return 0; if ((m.ms.flag & M_CAP) && Piece(m.ms.to) == king) return 0; if (m.ms.flag & M_CAP) { if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; } if (bitn&table_attack[m.ms.to - m.ms.from + 128]) return 1; return 0; case bishop: if (m.ms.piece != bishop) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if ((m.ms.flag == M_STD) && Color(m.ms.to) != EMPTY) return 0; if (m.ms.flag & M_CAP && Color(m.ms.to) != Xside) return 0; if ((m.ms.flag & M_CAP) && Piece(m.ms.to) == king) return 0; if (m.ms.flag & M_CAP) { if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; } if (bitb&table_attack[m.ms.to - m.ms.from + 128]) { if ((all&(bit_ray[m.ms.from][m.ms.to])) == 0) return 1; } return 0; case rook: if (m.ms.piece != rook) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if ((m.ms.flag == M_STD) && Color(m.ms.to) != EMPTY) return 0; if ((m.ms.flag & M_CAP) && Color(m.ms.to) != Xside) return 0; if ((m.ms.flag & M_CAP) && Piece(m.ms.to) == king) return 0; if (m.ms.flag & M_CAP) { if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; } if (bitr&table_attack[m.ms.to - m.ms.from + 128]) { if ((all&(bit_ray[m.ms.from][m.ms.to])) == 0) return 1; } return 0; case queen: if (m.ms.piece != queen) return 0; if (Plist(m.ms.from)==0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if ((m.ms.flag == M_STD) && Color(m.ms.to) != EMPTY) return 0; if ((m.ms.flag & M_CAP) && Color(m.ms.to) != Xside) return 0; if ((m.ms.flag & M_CAP) && Piece(m.ms.to) == king) return 0; if (m.ms.flag & M_CAP) { if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; } if (bitq&table_attack[m.ms.to - m.ms.from + 128]) { if ((all&(bit_ray[m.ms.from][m.ms.to])) == 0) return 1; } return 0; case king: if (m.ms.piece != king) return 0; if (Plist(m.ms.from)!=0) return 0; if (Active(Side,Plist(m.ms.from))==0) return 0; if (Position(Side,Plist(m.ms.from))!=m.ms.from) return 0; if (m.ms.flag & M_KNG) { if (m.ms.flag & M_CAP) { if (Plist(m.ms.to)==0) return 0; if (Active(Xside,Plist(m.ms.to))==0) return 0; if (Position(Xside,Plist(m.ms.to))!=m.ms.to) return 0; if (Color(m.ms.to) != Xside) return 0; if (Piece(m.ms.to) == king) return 0; } else if (Color(m.ms.to) != EMPTY) return 0; if (bitk&table_attack[m.ms.to - m.ms.from + 128]) return 1; return 0; } if (Side == BLACK) { if ((m.ms.flag&M_OO) && (Cstr&cas_boo) && IsEmpty(F8) && IsEmpty(G8)) return 1; if ((m.ms.flag&M_OOO) && (Cstr&cas_booo) && IsEmpty(B8) && IsEmpty(C8) && IsEmpty(D8)) return 1; } else { if ((m.ms.flag&M_OO) && (Cstr&cas_woo) && IsEmpty(F1) && IsEmpty(G1)) return 1; if ((m.ms.flag&M_OOO) && (Cstr&cas_wooo) && IsEmpty(B1) && IsEmpty(C1) && IsEmpty(D1)) return 1; } return 0; default: puts("Unexpected piece name."); assert(0); } return 0; }
/** * @return the Bitboard a, bitwise XOR with Bitboard b */ inline Bitboard operator^(Bitboard a,Bitboard b) { return Bitboard(a.bits ^ b.bits); }
#include "common.hpp" #include "bitboard.hpp" const Bitboard SetMaskBB[SquareNum] = { Bitboard(UINT64_C(1) << 0, 0), // 0 , I9 Bitboard(UINT64_C(1) << 1, 0), // 1 , I8 Bitboard(UINT64_C(1) << 2, 0), // 2 , I7 Bitboard(UINT64_C(1) << 3, 0), // 3 , I6 Bitboard(UINT64_C(1) << 4, 0), // 4 , I5 Bitboard(UINT64_C(1) << 5, 0), // 5 , I4 Bitboard(UINT64_C(1) << 6, 0), // 6 , I3 Bitboard(UINT64_C(1) << 7, 0), // 7 , I2 Bitboard(UINT64_C(1) << 8, 0), // 8 , I1 Bitboard(UINT64_C(1) << 9, 0), // 9 , H9 Bitboard(UINT64_C(1) << 10, 0), // 10, H8 Bitboard(UINT64_C(1) << 11, 0), // 11, H7 Bitboard(UINT64_C(1) << 12, 0), // 12, H6 Bitboard(UINT64_C(1) << 13, 0), // 13, H5 Bitboard(UINT64_C(1) << 14, 0), // 14, H4 Bitboard(UINT64_C(1) << 15, 0), // 15, H3 Bitboard(UINT64_C(1) << 16, 0), // 16, H2 Bitboard(UINT64_C(1) << 17, 0), // 17, H1 Bitboard(UINT64_C(1) << 18, 0), // 18, G9 Bitboard(UINT64_C(1) << 19, 0), // 19, G8 Bitboard(UINT64_C(1) << 20, 0), // 20, G7 Bitboard(UINT64_C(1) << 21, 0), // 21, G6 Bitboard(UINT64_C(1) << 22, 0), // 22, G5 Bitboard(UINT64_C(1) << 23, 0), // 23, G4 Bitboard(UINT64_C(1) << 24, 0), // 24, G3 Bitboard(UINT64_C(1) << 25, 0), // 25, G2 Bitboard(UINT64_C(1) << 26, 0), // 26, G1
#pragma once #include "bitboard.h" const Bitboard Bitboard::LINE_MASK[8] = { Bitboard(0xffffULL << 0, 0), Bitboard(0xffffULL << 16, 0), Bitboard(0xffffULL << 32, 0), Bitboard(0xffffULL << 48, 0), Bitboard(0, 0xffffULL << 0), Bitboard(0, 0xffffULL << 16), Bitboard(0, 0xffffULL << 32), Bitboard(0, 0xffffULL << 48), }; const Bitboard Bitboard::BB_MASK[SQUARE_MAX] = { Bitboard(1ULL << 0, 0), Bitboard(1ULL << 1, 0), Bitboard(1ULL << 2, 0), Bitboard(1ULL << 3, 0), Bitboard(1ULL << 4, 0), Bitboard(1ULL << 5, 0), Bitboard(1ULL << 6, 0), Bitboard(1ULL << 7, 0), Bitboard(1ULL << 8, 0), Bitboard(1ULL << 9, 0), Bitboard(1ULL << 10, 0), Bitboard(1ULL << 11, 0), Bitboard(1ULL << 12, 0), Bitboard(1ULL << 13, 0), Bitboard(1ULL << 14, 0),
/* Aggiorna la scacchiera e le altre strutture dati eseguendo la mossa La verifica di legalita' viene effettuata quando: -la mossa è una mossa di re -il re è sotto scacco -il re è sotto attacco x-ray */ int makemove(const MOVE m, const unsigned char s) { unsigned char from=0; /*da dove parte il pezzo*/ unsigned char to=0; /*dove copiare il pezzo*/ char was=0; /*cosa era il pezzo?*/ char wh=0; unsigned char del=0; /*dove cancellare*/ assert(Name(WHITE,0)==king); assert(Name(BLACK,0)==king); if (Piece(m.ms.to)==king) return 0; /*copia la chiave hash per l'unmake()*/ BHash(N_moves) = Hash; /*copia la castle_exe per l'unmake()*/ BCste(N_moves) = Cste; /*copia la bitboard per l'unmake()*/ BBitb(N_moves, Side) = Bitboard(Side); /*Controlla che l'arrocco sia legale e sposta la torre */ if (m.ms.flag & (M_OO | M_OOO)) { if (tree.check[Side][Ply]) return 0; switch (m.ms.to) { case C8: if (attacked(C8, WHITE) || attacked(D8, WHITE)) return 0; from = A8; to = D8; Cste |= cas_booo; break; case G8: if (attacked(F8, WHITE) || attacked(G8, WHITE)) return 0; from = H8; to = F8; Cste |= cas_boo; break; case C1: if (attacked(C1, BLACK) || attacked(D1, BLACK)) return 0; from = A1; to = D1; Cste |= cas_wooo; break; case G1: if (attacked(F1, BLACK) || attacked(G1, BLACK)) return 0; from = H1; to = F1; Cste |= cas_woo; break; default: puts("Bad castle request."); assert(0); } /*sposta torre aggiornando la chiave hash*/ UpdateHash(from); Piece(to) = Piece(from); Color(to) = Color(from); Plist(to) = Plist(from); Position((Color(to)), (Plist(to))) = to; Piece(from) = no_piece; Color(from) = EMPTY; Plist(from) = no_list; UpdateHash(to); SetBB(Side, to); DelBB(Side, from); } /*sposta il pezzo*/ from = m.ms.from; to = m.ms.to; was = Piece(from); wh = Plist(from); assert(was>=0); assert(was<=king); assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (wh>0){ assert(Name(Side,wh)!=king); } /*Se la mossa e' una cattura cancella il pezzo dalla casella di arrivo*/ if (m.ms.flag & M_CAP) { del = to; /*se è una cattura en passant aggiustiamo casella*/ if (m.ms.flag & M_ENP) { if (Side) del += DOWN; else del += UP; } BCapP(N_moves) = Piece(del); BCapPos(N_moves) = Plist(del); BCapC(N_moves) = Xside; BBitb(N_moves, Xside) = Bitboard(Xside); Active(Xside, (Plist(del))) = CAPTURED; Piece(del) = no_piece; Color(del) = EMPTY; Plist(del) = no_list; DelBB(Xside, del); } Piece(to) = Piece(from); if (m.ms.piece!=was)Piece(to)=m.ms.piece; Color(to) = Side; Plist(to) = wh; Position((Side), (wh)) = to; Piece(from) = no_piece; Color(from) = EMPTY; Plist(from) = no_list; SetBB(Side, to); DelBB(Side, from); /*effettuato il minimo indispensabile verifica, se opportuno, la legalità della mossa*/ assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (wh>0){ assert(Name(Side,wh)!=king); } if ( tree.verify[Ply] || tree.check[Side][Ply] || (m.ms.flag & M_KNG) ||(m.ms.flag & M_ENP)) { if (in_check(Side)) { /*unmake() locale*/ Piece(from) = Piece(to); if (Piece(from)!=was)Piece(from)=was; Color(from) = Side; Plist(from) = wh; Position((Side), (wh)) = from; Piece(to) = no_piece; Color(to) = EMPTY; Plist(to) = no_list; Bitboard(Side) = BBitb(N_moves, Side); if (m.ms.flag & M_CAP) { Piece(del) = BCapP(N_moves); Color(del) = BCapC(N_moves); Plist(del) = BCapPos(N_moves); Active((Xside), (Plist(del))) = FREE; Position((Xside), (Plist(del))) = del; Bitboard(Xside) = BBitb(N_moves, Xside); assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (Plist(del)>0){ assert(Name(Xside,Plist(del))!=king); } } assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (wh>0){ assert(Name(Side,wh)!=king); } return 0; } } /*Selectivity*/ if (s && ((!in_check(Xside)) || ((m.ms.flag& M_CAP)==0))) { /*unmake() locale*/ Piece(from) = Piece(to); if (Piece(from)!=was)Piece(from)=was; Color(from) = Side; Plist(from) = wh; Position((Side), (wh)) = from; Piece(to) = no_piece; Color(to) = EMPTY; Plist(to) = no_list; Bitboard(Side) = BBitb(N_moves, Side); if (m.ms.flag & M_CAP) { Piece(del) = BCapP(N_moves); Color(del) = BCapC(N_moves); Plist(del) = BCapPos(N_moves); Active((Xside), (Plist(del))) = FREE; Position((Xside), (Plist(del))) = del; Bitboard(Xside) = BBitb(N_moves, Xside); assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (Plist(del)>0){ assert(Name(Xside,Plist(del))!=king); } } assert(Name(Side,0)==king); assert(Name(Xside,0)==king); if (wh>0){ assert(Name(Side,wh)!=king); } return 0; } /*back up per l'unmakemove() i dati per la cattura e la hash della posizione sono gia' memorizzati*/ tree.history[N_moves].m.mi = m.mi; tree.history[N_moves].cast.castle_right = Cstr; tree.history[N_moves].enp = Enp; tree.history[N_moves].fifty = tree.fifty; tree.history[N_moves].was = was; tree.history[N_moves].material[Side] = Material(Side); tree.history[N_moves].material[Xside] = Material(Xside); BPBitb(N_moves, Side) = Pbitboard(Side); BPBitb(N_moves, Xside) = Pbitboard(Xside); /*aggiorna diritti arrocco*/ UpdateHashCastle(Cstr); Cstr &= castle_mask[b256to64[from]] & castle_mask[b256to64[to]]; UpdateHashCastle(Cstr); Hash ^= zobrist_enp[b256to64[Enp]]; Enp = 0; tree.fifty++; /*se irreversibile...*/ if (m.ms.flag&(M_PAW | M_CAP)) { tree.fifty = 0; if (m.ms.flag&M_DBP) { if (Side) Enp = to + DOWN; else Enp = to + UP; } if (m.ms.flag&M_PAW) { DelPBB(Side, from); if ((m.ms.flag&M_PRO) == 0) SetPBB(Side, to); } if (m.ms.flag&M_CAP) { tree.history[N_moves].del = del; Hash ^= zobrist[Xside][BCapP(N_moves)][b256to64[del]]; Material(Xside) -= piece_value[BCapP(N_moves)]; Num_piece(Xside, BCapP(N_moves))--; Pbitboard(Xside) &= (~(bit_square[del])); } Material(Side) -= piece_value[was]; Material(Side) += piece_value[m.ms.piece]; Num_piece(Side, was)--; Num_piece(Side, m.ms.piece)++; } Hash ^= zobrist_enp[b256to64[Enp]]; Hash ^= zobrist[Side][was][b256to64[from]]; Hash ^= zobrist[Side][m.ms.piece][b256to64[to]]; Hash ^= zobrist_side; Ply++; N_moves++; Change(Side); Change(Xside); assert(Name(WHITE,0)==king); assert(Name(BLACK,0)==king); return 1; }