#endif
// Rider directions
- const std::map<Direction, int> RookDirectionsV { {NORTH, 0}, {SOUTH, 0}};
- const std::map<Direction, int> RookDirectionsH { {EAST, 0}, {WEST, 0} };
- const std::map<Direction, int> BishopDirections { {NORTH_EAST, 0}, {SOUTH_EAST, 0}, {SOUTH_WEST, 0}, {NORTH_WEST, 0} };
- const std::map<Direction, int> LameDabbabaDirections { {2 * NORTH, 0}, {2 * EAST, 0}, {2 * SOUTH, 0}, {2 * WEST, 0} };
- const std::map<Direction, int> HorseDirections { {2 * SOUTH + WEST, 0}, {2 * SOUTH + EAST, 0}, {SOUTH + 2 * WEST, 0}, {SOUTH + 2 * EAST, 0},
- {NORTH + 2 * WEST, 0}, {NORTH + 2 * EAST, 0}, {2 * NORTH + WEST, 0}, {2 * NORTH + EAST, 0} };
- const std::map<Direction, int> ElephantDirections { {2 * NORTH_EAST, 0}, {2 * SOUTH_EAST, 0}, {2 * SOUTH_WEST, 0}, {2 * NORTH_WEST, 0} };
- const std::map<Direction, int> JanggiElephantDirections { {NORTH + 2 * NORTH_EAST, 0}, {EAST + 2 * NORTH_EAST, 0},
- {EAST + 2 * SOUTH_EAST, 0}, {SOUTH + 2 * SOUTH_EAST, 0},
- {SOUTH + 2 * SOUTH_WEST, 0}, {WEST + 2 * SOUTH_WEST, 0},
- {WEST + 2 * NORTH_WEST, 0}, {NORTH + 2 * NORTH_WEST, 0} };
- const std::map<Direction, int> GrasshopperDirectionsV { {NORTH, 1}, {SOUTH, 1}};
- const std::map<Direction, int> GrasshopperDirectionsH { {EAST, 1}, {WEST, 1} };
- const std::map<Direction, int> GrasshopperDirectionsD { {NORTH_EAST, 1}, {SOUTH_EAST, 1}, {SOUTH_WEST, 1}, {NORTH_WEST, 1} };
+ const std::map<DirectionCode, int> RookDirectionsV { {step(1, 0), 0}, {step(-1, 0), 0}};
+ const std::map<DirectionCode, int> RookDirectionsH { {step(0, 1), 0}, {step(0, -1), 0} };
+ const std::map<DirectionCode, int> BishopDirections { {step(1, 1), 0}, {step(-1, 1), 0}, {step(-1, -1), 0}, {step(1, -1), 0} };
+ const std::map<DirectionCode, int> LameDabbabaDirections { {step(2, 0), 0}, {step(0, 2), 0}, {step(-2, 0), 0}, {step(0, -2), 0} };
+ const std::map<DirectionCode, int> HorseDirections { {step(-2, 1), 0}, {step(-2, -1), 0}, {step(-1, 2), 0}, {step(-1, -2), 0},
+ {step(1, -2), 0}, {step(1, 2), 0}, {step(2, -1), 0}, {step(2, 1), 0} };
+ const std::map<DirectionCode, int> ElephantDirections { {step(2, 2), 0}, {step(-2, 2), 0}, {step(-2, -2), 0}, {step(2, -2), 0} };
+ const std::map<DirectionCode, int> JanggiElephantDirections { {step(3, 2), 0}, {step(2, 3), 0},
+ {step(-2, 3), 0}, {step(-3, 2), 0},
+ {step(-3, -2), 0}, {step(-2, -3), 0},
+ {step(2, -3), 0}, {step(3, -2), 0} };
+ const std::map<DirectionCode, int> GrasshopperDirectionsV { {step(1, 0), 0xFFFE}, {step(-1, 0), 0xFFFE}};
+ const std::map<DirectionCode, int> GrasshopperDirectionsH { {step(0, 1), 0xFFFE}, {step(0, -1), 0xFFFE} };
+ const std::map<DirectionCode, int> GrasshopperDirectionsD { {step(1, 1), 0xFFFE}, {step(-1, 1), 0xFFFE},
+ {step(-1, -1), 0xFFFE}, {step(1, -1), 0xFFFE} };
enum MovementType { RIDER, HOPPER, LAME_LEAPER, HOPPER_RANGE };
template <MovementType MT>
#ifdef PRECOMPUTED_MAGICS
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, const Bitboard magicsInit[]);
+ void init_magics(Bitboard table[], Magic magics[], std::map<DirectionCode, int> directions, const Bitboard magicsInit[]);
#else
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions);
+ void init_magics(Bitboard table[], Magic magics[], std::map<DirectionCode, int> directions);
#endif
template <MovementType MT>
- Bitboard sliding_attack(std::map<Direction, int> directions, Square sq, Bitboard occupied, Color c = WHITE) {
+ Bitboard sliding_attack(std::map<DirectionCode, int> directions, Square sq, Bitboard occupied, Color c = WHITE) {
assert(MT != LAME_LEAPER);
Bitboard attack = 0;
- for (auto const& [d, limit] : directions)
+ for (auto const& [v, limit] : directions)
{
int count = 0;
bool hurdle = false;
+ Direction d = board_step(v);
for (Square s = sq + (c == WHITE ? d : -d);
is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2;
s += (c == WHITE ? d : -d))
return attack;
}
- Bitboard lame_leaper_path(Direction d, Square s) {
+ Bitboard lame_leaper_path(DirectionCode d, Square s) {
Direction dr = d > 0 ? NORTH : SOUTH;
- Direction df = (std::abs(d % NORTH) < NORTH / 2 ? d % NORTH : -(d % NORTH)) < 0 ? WEST : EAST;
- Square to = s + d;
+ Direction df = h_step(d) < 0 ? WEST : EAST;
+ Square to = s + board_step(d);
Bitboard b = 0;
if (!is_ok(to) || distance(s, to) >= 4)
return b;
return b;
}
- Bitboard lame_leaper_path(std::map<Direction, int> directions, Square s) {
+ Bitboard lame_leaper_path(std::map<DirectionCode, int> directions, Square s) {
Bitboard b = 0;
for (const auto& i : directions)
b |= lame_leaper_path(i.first, s);
return b;
}
- Bitboard lame_leaper_attack(std::map<Direction, int> directions, Square s, Bitboard occupied) {
+ Bitboard lame_leaper_attack(std::map<DirectionCode, int> directions, Square s, Bitboard occupied) {
Bitboard b = 0;
for (const auto& i : directions)
{
- Square to = s + i.first;
- if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(i.first, s) & occupied))
+ Direction d = board_step(i.first);
+ Direction h = h_step(i.first);
+ Square to = s + d;
+ if (is_ok(to) && file_of(s) + h < FILE_NB && file_of(s) + h >= 0 && !(lame_leaper_path(i.first, s) & occupied))
b |= to;
}
return b;
/// safe_destination() returns the bitboard of target square for the given step
/// from the given square. If the step is off the board, returns empty bitboard.
-inline Bitboard safe_destination(Square s, int step) {
+inline Bitboard safe_destination(Square s, DirectionCode c) {
+ Direction step = board_step(c);
+ Direction h = h_step(c);
Square to = Square(s + step);
- return is_ok(to) && distance(s, to) <= 3 ? square_bb(to) : Bitboard(0);
+ return is_ok(to) && file_of(s) + h >= 0 && file_of(s) + h < FILE_NB ? square_bb(to) : Bitboard(0);
}
leaper = 0;
for (auto const& [d, limit] : pi->steps[initial][modality])
{
- pseudo |= safe_destination(s, c == WHITE ? d : -d);
+ pseudo |= safe_destination(s, DirectionCode(c == WHITE ? d : -d));
if (!limit)
- leaper |= safe_destination(s, c == WHITE ? d : -d);
+ leaper |= safe_destination(s, DirectionCode(c == WHITE ? d : -d));
}
pseudo |= sliding_attack<RIDER>(pi->slider[initial][modality], s, 0, c);
pseudo |= sliding_attack<HOPPER_RANGE>(pi->hopper[initial][modality], s, 0, c);
template <MovementType MT>
#ifdef PRECOMPUTED_MAGICS
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, const Bitboard magicsInit[]) {
+ void init_magics(Bitboard table[], Magic magics[], std::map<DirectionCode, int> directions, const Bitboard magicsInit[]) {
#else
- void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions) {
+ void init_magics(Bitboard table[], Magic magics[], std::map<DirectionCode, int> directions) {
#endif
// Optimal PRNG seeds to pick the correct magics in the shortest time
auto has_dir = [&](std::string s) {
return std::find(directions.begin(), directions.end(), s) != directions.end();
};
- if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("rf") || has_dir("rv") || has_dir("fh") || has_dir("rh") || has_dir("hr"))
- v[Direction(atom.first * FILE_NB + atom.second)] = distance;
- if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("lb") || has_dir("lv") || has_dir("bh") || has_dir("lh") || has_dir("hr"))
- v[Direction(-atom.first * FILE_NB - atom.second)] = distance;
- if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("br") || has_dir("bs") || has_dir("bh") || has_dir("rh") || has_dir("hr"))
- v[Direction(-atom.second * FILE_NB + atom.first)] = distance;
- if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("fl") || has_dir("fs") || has_dir("fh") || has_dir("lh") || has_dir("hr"))
- v[Direction(atom.second * FILE_NB - atom.first)] = distance;
- if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("fr") || has_dir("fs") || has_dir("fh") || has_dir("rh") || has_dir("hl"))
- v[Direction(atom.second * FILE_NB + atom.first)] = distance;
- if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("bl") || has_dir("bs") || has_dir("bh") || has_dir("lh") || has_dir("hl"))
- v[Direction(-atom.second * FILE_NB - atom.first)] = distance;
- if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("rb") || has_dir("rv") || has_dir("bh") || has_dir("rh") || has_dir("hl"))
- v[Direction(-atom.first * FILE_NB + atom.second)] = distance;
- if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("lf") || has_dir("lv") || has_dir("fh") || has_dir("lh") || has_dir("hl"))
- v[Direction(atom.first * FILE_NB - atom.second)] = distance;
+ if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("rf") || has_dir("rv") || has_dir("fh") || has_dir("rh") || has_dir("hr"))
+ v[step(y, x)] = distance;
+ if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("lb") || has_dir("lv") || has_dir("bh") || has_dir("lh") || has_dir("hr"))
+ v[step(-y, -x)] = distance;
+ if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("br") || has_dir("bs") || has_dir("bh") || has_dir("rh") || has_dir("hr"))
+ v[step(-x, y)] = distance;
+ if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("fl") || has_dir("fs") || has_dir("fh") || has_dir("lh") || has_dir("hr"))
+ v[step(x, -y)] = distance;
+ if (directions.size() == 0 || has_dir("rr") || has_dir("ss") || has_dir("fr") || has_dir("fs") || has_dir("fh") || has_dir("rh") || has_dir("hl"))
+ v[step(x, y)] = distance;
+ if (directions.size() == 0 || has_dir("ll") || has_dir("ss") || has_dir("bl") || has_dir("bs") || has_dir("bh") || has_dir("lh") || has_dir("hl"))
+ v[step(-x, -y)] = distance;
+ if (directions.size() == 0 || has_dir("bb") || has_dir("vv") || has_dir("rb") || has_dir("rv") || has_dir("bh") || has_dir("rh") || has_dir("hl"))
+ v[step(-y, x)] = distance;
+ if (directions.size() == 0 || has_dir("ff") || has_dir("vv") || has_dir("lf") || has_dir("lv") || has_dir("fh") || has_dir("lh") || has_dir("hl"))
+ v[step(y, -x)] = distance;
}
}
// Reset state
// Scale down slider value based on distance
-int slider_fraction(std::map<Direction, int> slider) {
+int slider_fraction(std::map<DirectionCode, int> slider) {
int s = 0;
for (auto const& [_, limit] : slider) {
s += limit == 0 ? 100 : 200 * std::min(limit + 1, 8) / 16;
+ (phase == MG ? 100 : 80) * pi->hopper[0][MODALITY_CAPTURE].size()
+ (phase == MG ? 85 : 60) * pi->hopper[0][MODALITY_QUIET].size()
// Rook sliding directions are more valuable, especially in endgame
- + (phase == MG ? 15 : 15) * std::count_if(pi->slider[0][MODALITY_CAPTURE].begin(), pi->slider[0][MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; })
- + (phase == MG ? 30 : 50) * std::count_if(pi->slider[0][MODALITY_QUIET].begin(), pi->slider[0][MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; });
+ + (phase == MG ? 15 : 15) * std::count_if(pi->slider[0][MODALITY_CAPTURE].begin(), pi->slider[0][MODALITY_CAPTURE].end(), [](const std::pair<const DirectionCode, int>& d) { return std::abs(board_step(d.first)) == NORTH || std::abs(board_step(d.first)) == 1; })
+ + (phase == MG ? 30 : 50) * std::count_if(pi->slider[0][MODALITY_QUIET].begin(), pi->slider[0][MODALITY_QUIET].end(), [](const std::pair<const DirectionCode, int>& d) { return std::abs(board_step(d.first)) == NORTH || std::abs(board_step(d.first)) == 1; });
return Value(v0 * exp(double(v0) / 10000));
}
const PieceInfo* pi = pieceMap.find(pt)->second;
bool isSlider = pi->slider[0][MODALITY_QUIET].size() || pi->slider[0][MODALITY_CAPTURE].size() || pi->hopper[0][MODALITY_QUIET].size() || pi->hopper[0][MODALITY_CAPTURE].size();
- bool isPawn = !isSlider && pi->steps[0][MODALITY_QUIET].size() && !std::any_of(pi->steps[0][MODALITY_QUIET].begin(), pi->steps[0][MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return d.first < SOUTH / 2; });
- bool isSlowLeaper = !isSlider && !std::any_of(pi->steps[0][MODALITY_QUIET].begin(), pi->steps[0][MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1; });
+ bool isPawn = !isSlider && pi->steps[0][MODALITY_QUIET].size() && !std::any_of(pi->steps[0][MODALITY_QUIET].begin(), pi->steps[0][MODALITY_QUIET].end(), [](const std::pair<const DirectionCode, int>& d) { return board_step(d.first) < SOUTH / 2; });
+ bool isSlowLeaper = !isSlider && !std::any_of(pi->steps[0][MODALITY_QUIET].begin(), pi->steps[0][MODALITY_QUIET].end(), [](const std::pair<const DirectionCode, int>& d) { return dist(board_step(d.first)) > 1; });
// Scale slider piece values with board size
if (isSlider)
// Increase leapers' value in makpong
else if (v->makpongRule)
{
- if (std::any_of(pi->steps[0][MODALITY_CAPTURE].begin(), pi->steps[0][MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1 && !d.second; }))
+ if (std::any_of(pi->steps[0][MODALITY_CAPTURE].begin(), pi->steps[0][MODALITY_CAPTURE].end(), [](const std::pair<const DirectionCode, int>& d) { return dist(board_step(d.first)) > 1 && !d.second; }))
score = make_score(mg_value(score) * 4200 / (3500 + mg_value(score)),
eg_value(score) * 4700 / (3500 + mg_value(score)));
}