namespace {
- Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) {
-
- Bitboard attack = 0;
-
- for (int i = 0; i < 4; ++i)
- for (Square s = sq + directions[i];
- is_ok(s) && distance(s, s - directions[i]) == 1;
- s += directions[i])
- {
- attack |= s;
-
- if (occupied & s)
- break;
- }
-
- return attack;
- }
-
-
// init_magics() computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
- // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
- // use the so called "fancy" approach.
+ // www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
+ // called "fancy" approach.
+#ifdef PRECOMPUTED_MAGICS
+ void init_magics(Bitboard table[], Magic magics[], Direction directions[], Bitboard magicsInit[]) {
+#else
void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {
+#endif
// Optimal PRNG seeds to pick the correct magics in the shortest time
+#ifndef PRECOMPUTED_MAGICS
+#ifdef LARGEBOARDS
+ int seeds[][RANK_NB] = { {},
+ { 734, 10316, 55013, 32803, 12281, 15100, 16645, 255, 346, 89123} };
+#else
int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 },
{ 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } };
+#endif
+#endif
+
+ Bitboard* occupancy = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard* reference = new Bitboard[1 << (FILE_NB + RANK_NB - 4)];
+ Bitboard edges, b;
+ int* epoch = new int[1 << (FILE_NB + RANK_NB - 4)]();
+ int cnt = 0, size = 0;
- Bitboard occupancy[4096], reference[4096], edges, b;
- int epoch[4096] = {}, cnt = 0, size = 0;
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ for (Square s = SQ_A1; s <= SQ_MAX; ++s)
{
// Board edges are not considered in the relevant occupancies
- edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
+ edges = ((Rank1BB | rank_bb(RANK_MAX)) & ~rank_bb(s)) | ((FileABB | file_bb(FILE_MAX)) & ~file_bb(s));
// Given a square 's', the mask is the bitboard of sliding attacks from
// 's' computed on an empty board. The index must be big enough to contain
Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safe, restricted;
Score score = SCORE_ZERO;
+ // Bonuses for variants with mandatory captures
+ if (pos.must_capture())
+ {
+ // Penalties for possible captures
+ score -= make_score(100, 100) * popcount(attackedBy[Us][ALL_PIECES] & pos.pieces(Them));
+
+ // Bonus if we threaten to force captures
+ Bitboard moves = 0, piecebb = pos.pieces(Us);
+ while (piecebb)
+ {
+ Square s = pop_lsb(&piecebb);
+ if (type_of(pos.piece_on(s)) != KING)
+ moves |= pos.moves_from(Us, type_of(pos.piece_on(s)), s);
+ }
+ score += make_score(200, 200) * popcount(attackedBy[Them][ALL_PIECES] & moves & ~pos.pieces());
+ score += make_score(200, 200) * popcount(attackedBy[Them][ALL_PIECES] & moves & ~pos.pieces() & ~attackedBy2[Us]);
+ }
+
// Non-pawn enemies
- nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(Them, PAWN, SHOGI_PAWN);
- nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN);
++ nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN, SHOGI_PAWN);
// Squares strongly protected by the enemy, either because they defend the
// square with a pawn, or because they defend the square twice and we don't.
// Find the available squares for our pieces inside the area defined by SpaceMask
Bitboard safe = SpaceMask
- & ~pos.pieces(Us, PAWN)
- & ~attackedBy[Them][PAWN];
+ & ~pos.pieces(Us, PAWN, SHOGI_PAWN)
+ & ~attackedBy[Them][PAWN]
+ & ~attackedBy[Them][SHOGI_PAWN];
+
+ if (pawnsOnly)
+ safe = pos.pieces(Us, PAWN) & ~attackedBy[Them][ALL_PIECES];
// Find all squares which are at most three squares behind some friendly pawn
- Bitboard behind = pos.pieces(Us, PAWN);
- behind |= (Us == WHITE ? behind >> 8 : behind << 8);
- behind |= (Us == WHITE ? behind >> 16 : behind << 16);
+ Bitboard behind = pos.pieces(Us, PAWN, SHOGI_PAWN);
+ behind |= (Us == WHITE ? behind >> NORTH : behind << NORTH);
+ behind |= (Us == WHITE ? behind >> (2 * NORTH) : behind << (2 * NORTH));
+
int bonus = popcount(safe) + popcount(behind & safe);
- int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files();
+ int weight = pos.count<ALL_PIECES>(Us)
+ - 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);
Score score = make_score(bonus * weight * weight / 16, 0);
// After castling, the rook and king final positions are the same in Chess960
// as they would be in standard chess.
- Square kfrom = pos.square<KING>(Us);
+ Square kfrom = pos.count<KING>(Us) ? pos.square<KING>(Us) : make_square(FILE_E, relative_rank(Us, RANK_1, pos.max_rank()));
Square rfrom = pos.castling_rook_square(Cr);
- Square kto = relative_square(Us, KingSide ? SQ_G1 : SQ_C1);
+ Square kto = make_square(KingSide ? pos.castling_kingside_file() : pos.castling_queenside_file(),
+ relative_rank(Us, RANK_1, pos.max_rank()));
- Bitboard enemies = pos.pieces(~Us);
+ Bitboard enemies = pos.pieces(Them);
assert(!pos.checkers());
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
- // Compute our parametrized parameters at compile time, named according to
- // the point of view of white side.
+ // Compute some compile time parameters relative to the white side
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
- constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
- constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
+ constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
/// ButterflyHistory records how often quiet moves have been successful or
/// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by
- /// the move's from and to squares, see chessprogramming.wikispaces.com/Butterfly+Boards
+ /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
-typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
+typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB + 1) * int(SQUARE_NB)> ButterflyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
- /// move, see chessprogramming.wikispaces.com/Countermove+Heuristic
+ /// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
// not attacked more times than defended.
if ( !(stoppers ^ lever ^ leverPush)
&& popcount(support) >= popcount(lever) - 1
- && popcount(phalanx) >= popcount(leverPush))
+ && popcount(phalanx) >= popcount(leverPush))
e->passedPawns[Us] |= s;
- else if ( stoppers == SquareBB[s + Up]
- && relative_rank(Us, s) >= RANK_5)
+ else if ( relative_rank(Them, s, pos.max_rank()) > RANK_1
+ && stoppers == SquareBB[s + Up]
+ && relative_rank(Us, s, pos.max_rank()) >= RANK_5)
{
b = shift<Up>(support) & ~theirPawns;
while (b)