No functional change.
{
const PieceInfo* pi = pieceMap.find(pt)->second;
- // Initialize rider types
- AttackRiderTypes[pt] = NO_RIDER;
- MoveRiderTypes[pt] = NO_RIDER;
-
- for (auto const& [d, limit] : pi->stepsCapture)
- {
- 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 (auto const& [d, limit] : pi->sliderCapture)
+ // Detect rider types
+ for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
{
- if (BishopDirections.find(d) != BishopDirections.end())
- AttackRiderTypes[pt] |= RIDER_BISHOP;
- if (RookDirectionsH.find(d) != RookDirectionsH.end())
- AttackRiderTypes[pt] |= RIDER_ROOK_H;
- if (RookDirectionsV.find(d) != RookDirectionsV.end())
- AttackRiderTypes[pt] |= RIDER_ROOK_V;
- if (HorseDirections.find(d) != HorseDirections.end())
- AttackRiderTypes[pt] |= RIDER_NIGHTRIDER;
- }
- for (auto const& [d, limit] : pi->sliderQuiet)
- {
- if (BishopDirections.find(d) != BishopDirections.end())
- MoveRiderTypes[pt] |= RIDER_BISHOP;
- if (RookDirectionsH.find(d) != RookDirectionsH.end())
- MoveRiderTypes[pt] |= RIDER_ROOK_H;
- if (RookDirectionsV.find(d) != RookDirectionsV.end())
- MoveRiderTypes[pt] |= RIDER_ROOK_V;
- if (HorseDirections.find(d) != HorseDirections.end())
- MoveRiderTypes[pt] |= RIDER_NIGHTRIDER;
- }
- for (auto const& [d, limit] : pi->hopperCapture)
- {
- if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
- AttackRiderTypes[pt] |= RIDER_CANNON_H;
- if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
- AttackRiderTypes[pt] |= RIDER_CANNON_V;
- if (!limit && BishopDirections.find(d) != BishopDirections.end())
- AttackRiderTypes[pt] |= RIDER_CANNON_DIAG;
- }
- for (auto const& [d, limit] : pi->hopperQuiet)
- {
- if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
- MoveRiderTypes[pt] |= RIDER_CANNON_H;
- if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
- MoveRiderTypes[pt] |= RIDER_CANNON_V;
- if (!limit && BishopDirections.find(d) != BishopDirections.end())
- MoveRiderTypes[pt] |= RIDER_CANNON_DIAG;
+ auto& riderTypes = modality == MODALITY_CAPTURE ? AttackRiderTypes[pt] : MoveRiderTypes[pt];
+ riderTypes = NO_RIDER;
+ for (auto const& [d, limit] : pi->steps[modality])
+ {
+ if (limit && HorseDirections.find(d) != HorseDirections.end())
+ riderTypes |= RIDER_HORSE;
+ if (limit && ElephantDirections.find(d) != ElephantDirections.end())
+ riderTypes |= RIDER_ELEPHANT;
+ if (limit && JanggiElephantDirections.find(d) != JanggiElephantDirections.end())
+ riderTypes |= RIDER_JANGGI_ELEPHANT;
+ }
+ for (auto const& [d, limit] : pi->slider[modality])
+ {
+ if (BishopDirections.find(d) != BishopDirections.end())
+ riderTypes |= RIDER_BISHOP;
+ if (RookDirectionsH.find(d) != RookDirectionsH.end())
+ riderTypes |= RIDER_ROOK_H;
+ if (RookDirectionsV.find(d) != RookDirectionsV.end())
+ riderTypes |= RIDER_ROOK_V;
+ if (HorseDirections.find(d) != HorseDirections.end())
+ riderTypes |= RIDER_NIGHTRIDER;
+ }
+ for (auto const& [d, limit] : pi->hopper[modality])
+ {
+ if (!limit && RookDirectionsH.find(d) != RookDirectionsH.end())
+ riderTypes |= RIDER_CANNON_H;
+ if (!limit && RookDirectionsV.find(d) != RookDirectionsV.end())
+ riderTypes |= RIDER_CANNON_V;
+ if (!limit && BishopDirections.find(d) != BishopDirections.end())
+ riderTypes |= RIDER_CANNON_DIAG;
+ }
}
// Initialize move/attack bitboards
{
for (Square s = SQ_A1; s <= SQ_MAX; ++s)
{
- PseudoAttacks[c][pt][s] = 0;
- PseudoMoves[c][pt][s] = 0;
- LeaperAttacks[c][pt][s] = 0;
- LeaperMoves[c][pt][s] = 0;
- for (auto const& [d, limit] : pi->stepsCapture)
- {
- PseudoAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
- if (!limit)
- LeaperAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
- }
- for (auto const& [d, limit] : pi->stepsQuiet)
+ for (auto modality : {MODALITY_QUIET, MODALITY_CAPTURE})
{
- PseudoMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
- if (!limit)
- LeaperMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d);
+ auto& pseudo = modality == MODALITY_CAPTURE ? PseudoAttacks[c][pt][s] : PseudoMoves[c][pt][s];
+ auto& leaper = modality == MODALITY_CAPTURE ? LeaperAttacks[c][pt][s] : LeaperMoves[c][pt][s];
+ pseudo = 0;
+ leaper = 0;
+ for (auto const& [d, limit] : pi->steps[modality])
+ {
+ pseudo |= safe_destination(s, c == WHITE ? d : -d);
+ if (!limit)
+ leaper |= safe_destination(s, c == WHITE ? d : -d);
+ }
+ pseudo |= sliding_attack<RIDER>(pi->slider[modality], s, 0, c);
+ pseudo |= sliding_attack<RIDER>(pi->hopper[modality], s, 0, c);
}
- PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->sliderCapture, s, 0, c);
- PseudoAttacks[c][pt][s] |= sliding_attack<RIDER>(pi->hopperCapture, s, 0, c);
- PseudoMoves[c][pt][s] |= sliding_attack<RIDER>(pi->sliderQuiet, s, 0, c);
- PseudoMoves[c][pt][s] |= sliding_attack<RIDER>(pi->hopperQuiet, s, 0, c);
}
}
}
if (v->flipEnclosedPieces)
std::cerr << "Can not use kings with flipEnclosedPieces." << std::endl;
const PieceInfo* pi = pieceMap.find(v->kingType)->second;
- if (pi->hopperQuiet.size() || pi->hopperCapture.size()
- || std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](const std::pair<const Direction, int>& d) { return d.second; }))
+ if ( pi->hopper[MODALITY_QUIET].size()
+ || pi->hopper[MODALITY_CAPTURE].size()
+ || std::any_of(pi->steps[MODALITY_CAPTURE].begin(), pi->steps[MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return d.second; }))
std::cerr << pi->name << " is not supported as kingType." << std::endl;
}
}
PieceInfo* p = new PieceInfo();
p->name = name;
p->betza = betza;
- std::vector<char> moveTypes = {};
+ std::vector<MoveModality> moveModalities = {};
bool hopper = false;
bool rider = false;
bool lame = false;
for (std::string::size_type i = 0; i < betza.size(); i++)
{
char c = betza[i];
- // Move or capture
+ // Modality
if (c == 'm' || c == 'c')
- moveTypes.push_back(c);
+ moveModalities.push_back(c == 'c' ? MODALITY_CAPTURE : MODALITY_QUIET);
// Hopper
else if (c == 'p' || c == 'g')
{
hopper = true;
+ // Grasshopper
if (c == 'g')
distance = 1;
}
}
if (!rider && lame)
distance = -1;
- // No type qualifier means m+c
- if (moveTypes.size() == 0)
+ // No modality qualifier means m+c
+ if (moveModalities.size() == 0)
{
- moveTypes.push_back('m');
- moveTypes.push_back('c');
+ moveModalities.push_back(MODALITY_QUIET);
+ moveModalities.push_back(MODALITY_CAPTURE);
}
// Define moves
for (const auto& atom : atoms)
else
directions.push_back(s);
// Add moves
- for (char mt : moveTypes)
+ for (auto modality : moveModalities)
{
- auto& v = hopper ? ( mt == 'c' ? p->hopperCapture : p->hopperQuiet)
- : rider ? (mt == 'c' ? p->sliderCapture : p->sliderQuiet)
- : (mt == 'c' ? p->stepsCapture : p->stepsQuiet);
+ auto& v = hopper ? p->hopper[modality]
+ : rider ? p->slider[modality]
+ : p->steps[modality];
auto has_dir = [&](std::string s) {
return std::find(directions.begin(), directions.end(), s) != directions.end();
};
}
}
// Reset state
- moveTypes.clear();
+ moveModalities.clear();
prelimDirections.clear();
hopper = false;
rider = false;
#include "variant.h"
+enum MoveModality {MODALITY_QUIET, MODALITY_CAPTURE, MOVE_MODALITY_NB};
+
/// PieceInfo struct stores information about the piece movements.
struct PieceInfo {
std::string name = "";
std::string betza = "";
- std::map<Direction, int> stepsQuiet = {};
- std::map<Direction, int> stepsCapture = {};
- std::map<Direction, int> sliderQuiet = {};
- std::map<Direction, int> sliderCapture = {};
- std::map<Direction, int> hopperQuiet = {};
- std::map<Direction, int> hopperCapture = {};
+ std::map<Direction, int> steps[MOVE_MODALITY_NB] = {};
+ std::map<Direction, int> slider[MOVE_MODALITY_NB] = {};
+ std::map<Direction, int> hopper[MOVE_MODALITY_NB] = {};
};
struct PieceMap : public std::map<PieceType, const PieceInfo*> {
Value piece_value(Phase phase, PieceType pt)
{
const PieceInfo* pi = pieceMap.find(pt)->second;
- int v0 = (phase == MG ? 55 : 60) * pi->stepsCapture.size()
- + (phase == MG ? 30 : 40) * pi->stepsQuiet.size()
- + (phase == MG ? 185 : 180) * pi->sliderCapture.size()
- + (phase == MG ? 55 : 50) * pi->sliderQuiet.size()
+ int v0 = (phase == MG ? 55 : 60) * pi->steps[MODALITY_CAPTURE].size()
+ + (phase == MG ? 30 : 40) * pi->steps[MODALITY_QUIET].size()
+ + (phase == MG ? 185 : 180) * pi->slider[MODALITY_CAPTURE].size()
+ + (phase == MG ? 55 : 50) * pi->slider[MODALITY_QUIET].size()
// Hoppers are more useful with more pieces on the board
- + (phase == MG ? 100 : 80) * pi->hopperCapture.size()
- + (phase == MG ? 80 : 60) * pi->hopperQuiet.size()
+ + (phase == MG ? 100 : 80) * pi->hopper[MODALITY_CAPTURE].size()
+ + (phase == MG ? 80 : 60) * pi->hopper[MODALITY_QUIET].size()
// Rook sliding directions are more valuable, especially in endgame
- + (phase == MG ? 10 : 30) * std::count_if(pi->sliderCapture.begin(), pi->sliderCapture.end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; })
- + (phase == MG ? 30 : 45) * std::count_if(pi->sliderQuiet.begin(), pi->sliderQuiet.end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; });
+ + (phase == MG ? 10 : 30) * std::count_if(pi->slider[MODALITY_CAPTURE].begin(), pi->slider[MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; })
+ + (phase == MG ? 30 : 45) * std::count_if(pi->slider[MODALITY_QUIET].begin(), pi->slider[MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return std::abs(d.first) == NORTH || std::abs(d.first) == 1; });
return Value(v0 * exp(double(v0) / 10000));
}
}
const PieceInfo* pi = pieceMap.find(pt)->second;
- bool isSlider = pi->sliderQuiet.size() || pi->sliderCapture.size() || pi->hopperQuiet.size() || pi->hopperCapture.size();
- bool isPawn = !isSlider && pi->stepsQuiet.size() && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](const std::pair<const Direction, int>& d) { return d.first < SOUTH / 2; });
- bool isSlowLeaper = !isSlider && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1; });
+ bool isSlider = pi->slider[MODALITY_QUIET].size() || pi->slider[MODALITY_CAPTURE].size() || pi->hopper[MODALITY_QUIET].size() || pi->hopper[MODALITY_CAPTURE].size();
+ bool isPawn = !isSlider && pi->steps[MODALITY_QUIET].size() && !std::any_of(pi->steps[MODALITY_QUIET].begin(), pi->steps[MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return d.first < SOUTH / 2; });
+ bool isSlowLeaper = !isSlider && !std::any_of(pi->steps[MODALITY_QUIET].begin(), pi->steps[MODALITY_QUIET].end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1; });
// Scale slider piece values with board size
if (isSlider)
constexpr int rm = 5;
constexpr int r0 = rm + RANK_8;
int r1 = rm + (v->maxRank + v->maxFile - 2 * v->capturesToHand) / 2;
- int leaper = pi->stepsQuiet.size() + pi->stepsCapture.size();
- int slider = pi->sliderQuiet.size() + pi->sliderCapture.size() + pi->hopperQuiet.size() + pi->hopperCapture.size();
+ int leaper = pi->steps[MODALITY_QUIET].size() + pi->steps[MODALITY_CAPTURE].size();
+ int slider = pi->slider[MODALITY_QUIET].size() + pi->slider[MODALITY_CAPTURE].size() + pi->hopper[MODALITY_QUIET].size() + pi->hopper[MODALITY_CAPTURE].size();
score = make_score(mg_value(score) * (lc * leaper + r1 * slider) / (lc * leaper + r0 * slider),
eg_value(score) * (lc * leaper + r1 * slider) / (lc * leaper + r0 * slider));
}
// Increase leapers' value in makpong
else if (v->makpongRule)
{
- if (std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1 && !d.second; }))
+ if (std::any_of(pi->steps[MODALITY_CAPTURE].begin(), pi->steps[MODALITY_CAPTURE].end(), [](const std::pair<const Direction, int>& d) { return dist(d.first) > 1 && !d.second; }))
score = make_score(mg_value(score) * 4200 / (3500 + mg_value(score)),
eg_value(score) * 4700 / (3500 + mg_value(score)));
}
// For antichess variants, use negative piece values
if (v->extinctionValue == VALUE_MATE)
- score = -make_score(mg_value(score) / 8, eg_value(score) / 8 / (1 + !pi->sliderCapture.size()));
+ score = -make_score(mg_value(score) / 8, eg_value(score) / 8 / (1 + !pi->slider[MODALITY_CAPTURE].size()));
// Override variant piece value
if (v->pieceValue[MG][pt])