#endif
// Rider directions
- const std::set<Direction> RookDirectionsV { NORTH, SOUTH};
- const std::set<Direction> RookDirectionsH { EAST, WEST };
- const std::set<Direction> BishopDirections { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
- const std::set<Direction> HorseDirections { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
- NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST };
- const std::set<Direction> ElephantDirections { 2 * NORTH_EAST, 2 * SOUTH_EAST, 2 * SOUTH_WEST, 2 * NORTH_WEST };
- const std::set<Direction> JanggiElephantDirections { NORTH + 2 * NORTH_EAST, EAST + 2 * NORTH_EAST,
- EAST + 2 * SOUTH_EAST, SOUTH + 2 * SOUTH_EAST,
- SOUTH + 2 * SOUTH_WEST, WEST + 2 * SOUTH_WEST,
- WEST + 2 * NORTH_WEST, NORTH + 2 * NORTH_WEST };
+ 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> 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} };
enum MovementType { RIDER, HOPPER, LAME_LEAPER };
template <MovementType MT>
#ifdef PRECOMPUTED_MAGICS
- void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions, Bitboard magicsInit[]);
+ void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, Bitboard magicsInit[]);
#else
- void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions);
+ void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions);
#endif
template <MovementType MT>
- Bitboard sliding_attack(std::set<Direction> directions, Square sq, Bitboard occupied, Color c = WHITE) {
+ Bitboard sliding_attack(std::map<Direction, int> directions, Square sq, Bitboard occupied, Color c = WHITE) {
assert(MT != LAME_LEAPER);
Bitboard attack = 0;
- for (Direction d : directions)
+ for (auto const& [d, limit] : directions)
{
+ int count = 0;
bool hurdle = false;
for (Square s = sq + (c == WHITE ? d : -d);
is_ok(s) && distance(s, s - (c == WHITE ? d : -d)) <= 2;
s += (c == WHITE ? d : -d))
{
if (MT != HOPPER || hurdle)
+ {
attack |= s;
+ if (limit && ++count >= limit)
+ break;
+ }
if (occupied & s)
{
return b;
}
- Bitboard lame_leaper_path(std::set<Direction> directions, Square s) {
+ Bitboard lame_leaper_path(std::map<Direction, int> directions, Square s) {
Bitboard b = 0;
- for (Direction d : directions)
- b |= lame_leaper_path(d, s);
+ for (const auto& i : directions)
+ b |= lame_leaper_path(i.first, s);
return b;
}
- Bitboard lame_leaper_attack(std::set<Direction> directions, Square s, Bitboard occupied) {
+ Bitboard lame_leaper_attack(std::map<Direction, int> directions, Square s, Bitboard occupied) {
Bitboard b = 0;
- for (Direction d : directions)
+ for (const auto& i : directions)
{
- Square to = s + d;
- if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(d, s) & occupied))
+ Square to = s + i.first;
+ if (is_ok(to) && distance(s, to) < 4 && !(lame_leaper_path(i.first, s) & occupied))
b |= to;
}
return b;
AttackRiderTypes[pt] = NO_RIDER;
MoveRiderTypes[pt] = NO_RIDER;
- if (pi->lameLeaper)
+ for (auto const& [d, limit] : pi->stepsCapture)
{
- for (Direction d : pi->stepsCapture)
- {
- if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
- AttackRiderTypes[pt] |= RIDER_HORSE;
- if (std::find(ElephantDirections.begin(), ElephantDirections.end(), d) != ElephantDirections.end())
- AttackRiderTypes[pt] |= RIDER_ELEPHANT;
- if (std::find(JanggiElephantDirections.begin(), JanggiElephantDirections.end(), d) != JanggiElephantDirections.end())
- AttackRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
- }
- for (Direction d : pi->stepsQuiet)
- {
- if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
- MoveRiderTypes[pt] |= RIDER_HORSE;
- if (std::find(ElephantDirections.begin(), ElephantDirections.end(), d) != ElephantDirections.end())
- MoveRiderTypes[pt] |= RIDER_ELEPHANT;
- if (std::find(JanggiElephantDirections.begin(), JanggiElephantDirections.end(), d) != JanggiElephantDirections.end())
- MoveRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
- }
+ if (limit && HorseDirections.find(d) != HorseDirections.end())
+ AttackRiderTypes[pt] |= RIDER_HORSE;
+ if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+ AttackRiderTypes[pt] |= RIDER_ELEPHANT;
+ if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+ AttackRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
+ }
+ for (auto const& [d, limit] : pi->stepsQuiet)
+ {
+ if (limit && HorseDirections.find(d) != HorseDirections.end())
+ MoveRiderTypes[pt] |= RIDER_HORSE;
+ if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+ MoveRiderTypes[pt] |= RIDER_ELEPHANT;
+ if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+ MoveRiderTypes[pt] |= RIDER_JANGGI_ELEPHANT;
}
- for (Direction d : pi->sliderCapture)
+ for (auto const& [d, limit] : pi->sliderCapture)
{
- if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+ if (BishopDirections.find(d) != BishopDirections.end())
AttackRiderTypes[pt] |= RIDER_BISHOP;
- if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+ if (RookDirectionsH.find(d) != RookDirectionsH.end())
AttackRiderTypes[pt] |= RIDER_ROOK_H;
- if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+ if (RookDirectionsV.find(d) != RookDirectionsV.end())
AttackRiderTypes[pt] |= RIDER_ROOK_V;
- if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
+ if (HorseDirections.find(d) != HorseDirections.end())
AttackRiderTypes[pt] |= RIDER_NIGHTRIDER;
}
- for (Direction d : pi->sliderQuiet)
+ for (auto const& [d, limit] : pi->sliderQuiet)
{
- if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+ if (BishopDirections.find(d) != BishopDirections.end())
MoveRiderTypes[pt] |= RIDER_BISHOP;
- if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+ if (RookDirectionsH.find(d) != RookDirectionsH.end())
MoveRiderTypes[pt] |= RIDER_ROOK_H;
- if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+ if (RookDirectionsV.find(d) != RookDirectionsV.end())
MoveRiderTypes[pt] |= RIDER_ROOK_V;
- if (std::find(HorseDirections.begin(), HorseDirections.end(), d) != HorseDirections.end())
+ if (HorseDirections.find(d) != HorseDirections.end())
MoveRiderTypes[pt] |= RIDER_NIGHTRIDER;
}
- for (Direction d : pi->hopperCapture)
+ for (auto const& [d, limit] : pi->hopperCapture)
{
- if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+ if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
AttackRiderTypes[pt] |= RIDER_CANNON_H;
- if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+ if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
AttackRiderTypes[pt] |= RIDER_CANNON_V;
- if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+ if (!limit && BishopDirections.find(d) != BishopDirections.end())
AttackRiderTypes[pt] |= RIDER_CANNON_DIAG;
}
- for (Direction d : pi->hopperQuiet)
+ for (auto const& [d, limit] : pi->hopperQuiet)
{
- if (std::find(RookDirectionsH.begin(), RookDirectionsH.end(), d) != RookDirectionsH.end())
+ if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
MoveRiderTypes[pt] |= RIDER_CANNON_H;
- if (std::find(RookDirectionsV.begin(), RookDirectionsV.end(), d) != RookDirectionsV.end())
+ if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
MoveRiderTypes[pt] |= RIDER_CANNON_V;
- if (std::find(BishopDirections.begin(), BishopDirections.end(), d) != BishopDirections.end())
+ if (!limit && BishopDirections.find(d) != BishopDirections.end())
MoveRiderTypes[pt] |= RIDER_CANNON_DIAG;
}
PseudoMoves[c][pt][s] = 0;
LeaperAttacks[c][pt][s] = 0;
LeaperMoves[c][pt][s] = 0;
- for (Direction d : pi->stepsCapture)
+ for (auto const& [d, limit] : pi->stepsCapture)
{
PseudoAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
- if (!pi->lameLeaper)
+ if (!limit)
LeaperAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
}
- for (Direction d : pi->stepsQuiet)
+ for (auto const& [d, limit] : pi->stepsQuiet)
{
PseudoMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
- if (!pi->lameLeaper)
+ if (!limit)
LeaperMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
}
PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->sliderCapture, s, 0, c);
template <MovementType MT>
#ifdef PRECOMPUTED_MAGICS
- void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions, Bitboard magicsInit[]) {
+ void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions, Bitboard magicsInit[]) {
#else
- void init_magics(Bitboard table[], Magic magics[], std::set<Direction> directions) {
+ void init_magics(Bitboard table[], Magic magics[], std::map<Direction, int> directions) {
#endif
// Optimal PRNG seeds to pick the correct magics in the shortest time
std::vector<char> moveTypes = {};
bool hopper = false;
bool rider = false;
+ bool lame = false;
+ int distance = 0;
std::vector<std::string> prelimDirections = {};
for (std::string::size_type i = 0; i < betza.size(); i++)
{
if (c == 'm' || c == 'c')
moveTypes.push_back(c);
// Hopper
- else if (c == 'p')
+ else if (c == 'p' || c == 'g')
+ {
hopper = true;
+ if (c == 'g')
+ distance = 1;
+ }
// Lame leaper
else if (c == 'n')
- p->lameLeaper = true;
+ lame = true;
// Directional modifiers
else if (verticals.find(c) != std::string::npos || horizontals.find(c) != std::string::npos)
{
rider = true;
// limited distance riders
if (isdigit(betza[i+1]))
- {
- // TODO: not supported
- }
+ distance = betza[i+1] - '0';
i++;
}
+ if (!rider && lame)
+ distance = -1;
// No type qualifier means m+c
if (moveTypes.size() == 0)
{
// Add moves
for (char mt : moveTypes)
{
- std::set<Direction>& v = hopper ? (mt == 'c' ? p->hopperCapture : p->hopperQuiet)
- : rider ? (mt == 'c' ? p->sliderCapture : p->sliderQuiet)
- : (mt == 'c' ? p->stepsCapture : p->stepsQuiet);
+ auto& v = hopper ? ( mt == 'c' ? p->hopperCapture : p->hopperQuiet)
+ : rider ? (mt == 'c' ? p->sliderCapture : p->sliderQuiet)
+ : (mt == 'c' ? p->stepsCapture : p->stepsQuiet);
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.insert(Direction(atom.first * FILE_NB + atom.second));
+ 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.insert(Direction(-atom.first * FILE_NB - atom.second));
+ 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("lh") || has_dir("hr"))
- v.insert(Direction(-atom.second * FILE_NB + atom.first));
+ 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("rh") || has_dir("hr"))
- v.insert(Direction(atom.second * FILE_NB - atom.first));
+ 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.insert(Direction(atom.second * FILE_NB + atom.first));
+ 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.insert(Direction(-atom.second * FILE_NB - atom.first));
+ 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.insert(Direction(-atom.first * FILE_NB + atom.second));
+ 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.insert(Direction(atom.first * FILE_NB - atom.second));
+ v[Direction(atom.first * FILE_NB - atom.second)] = distance;
}
}
// Reset state
}
// Special multi-leg betza description for Janggi elephant
PieceInfo* janggi_elephant_piece() {
- PieceInfo* p = new PieceInfo();
- p->name = "janggiElephant";
- p->betza = "mafsmafW";
- p->stepsQuiet = {SOUTH + 2 * SOUTH_WEST, SOUTH + 2 * SOUTH_EAST,
- WEST + 2 * SOUTH_WEST, EAST + 2 * SOUTH_EAST,
- WEST + 2 * NORTH_WEST, EAST + 2 * NORTH_EAST,
- NORTH + 2 * NORTH_WEST, NORTH + 2 * NORTH_EAST};
- p->stepsCapture = {SOUTH + 2 * SOUTH_WEST, SOUTH + 2 * SOUTH_EAST,
- WEST + 2 * SOUTH_WEST, EAST + 2 * SOUTH_EAST,
- WEST + 2 * NORTH_WEST, EAST + 2 * NORTH_EAST,
- NORTH + 2 * NORTH_WEST, NORTH + 2 * NORTH_EAST};
- p->lameLeaper = true;
+ PieceInfo* p = from_betza("nZ", "");
+ p->betza = "mafsmafW"; // for compatiblity with XBoard/Winboard
return p;
}
}