Generalize castling and add archbishop to support capablanca chess.
bench: 4636755
NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
{ SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
{ 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
{ 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
{ SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
{ 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
+ NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
+ { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
{ 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
{}, // silver/khon
{ NORTH, EAST, SOUTH, WEST }, // aiwok
{ NORTH, EAST, SOUTH, WEST }, // bers/dragon
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
{ NORTH, EAST, SOUTH, WEST }, // chancellor
{ NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
{ NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // knibis
{}, // silver/khon
{ NORTH, EAST, SOUTH, WEST }, // aiwok
{ NORTH, EAST, SOUTH, WEST }, // bers/dragon
+ { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
{ NORTH, EAST, SOUTH, WEST }, // chancellor
{ NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
{}, // knibis
0, // silver/khon
FILE_MAX, // aiwok
FILE_MAX, // bers/dragon
+ FILE_MAX, // archbishop
FILE_MAX, // chancellor
FILE_MAX, // amazon
FILE_MAX, // knibis
0, // silver/khon
FILE_MAX, // aiwok
FILE_MAX, // bers/dragon
+ FILE_MAX, // archbishop
FILE_MAX, // chancellor
FILE_MAX, // amazon
0, // knibis
// After castling, the rook and king final positions are the same in Chess960
// as they would be in standard chess.
- Square kfrom = pos.count<KING>(us) ? pos.square<KING>(us) : make_square(FILE_E, us == WHITE ? RANK_1 : RANK_8);
+ 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);
assert(!pos.checkers());
token = char(toupper(token));
if (token == 'K')
- for (rsq = relative_square(c, SQ_H1); piece_on(rsq) != rook; --rsq) {}
+ for (rsq = make_square(FILE_MAX, relative_rank(c, RANK_1, max_rank())); piece_on(rsq) != rook; --rsq) {}
else if (token == 'Q')
- for (rsq = relative_square(c, SQ_A1); piece_on(rsq) != rook; ++rsq) {}
+ for (rsq = make_square(FILE_A, relative_rank(c, RANK_1, max_rank())); piece_on(rsq) != rook; ++rsq) {}
- else if (token >= 'A' && token <= 'H')
- rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1));
+ else if (token >= 'A' && token <= 'A' + max_file())
+ rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1, max_rank()));
else
continue;
bool kingSide = to > from;
rfrom = to; // Castling is encoded as "king captures friendly rook"
- rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
- to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
+ to = make_square(kingSide ? castling_kingside_file() : castling_queenside_file(),
+ us == WHITE ? RANK_1 : max_rank());
+ rto = to + (kingSide ? WEST : EAST);
// Remove both pieces first since squares could overlap in Chess960
Piece castling_piece = piece_on(Do ? from : to);
bool double_step_enabled() const;
bool first_rank_double_steps() const;
bool castling_enabled() const;
+ File castling_kingside_file() const;
+ File castling_queenside_file() const;
bool checking_permitted() const;
bool must_capture() const;
bool piece_drops() const;
return var->castling;
}
+inline File Position::castling_kingside_file() const {
+ assert(var != nullptr);
+ return var->castlingKingsideFile;
+}
+
+inline File Position::castling_queenside_file() const {
+ assert(var != nullptr);
+ return var->castlingQueensideFile;
+}
+
inline bool Position::checking_permitted() const {
assert(var != nullptr);
return var->checking;
Value PieceValue[PHASE_NB][PIECE_NB] = {
{ VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg,
- FersValueMg, AlfilValueMg, SilverValueMg, AiwokValueMg, BersValueMg, ChancellorValueMg,
- AmazonValueMg, KnibisValueMg, BiskniValueMg,
+ FersValueMg, AlfilValueMg, SilverValueMg, AiwokValueMg, BersValueMg,
+ ArchbishopValueMg, ChancellorValueMg, AmazonValueMg, KnibisValueMg, BiskniValueMg,
ShogiPawnValueMg, LanceValueMg, ShogiKnightValueMg, EuroShogiKnightValueMg, GoldValueMg, HorseValueMg,
ClobberPieceValueMg, BreakthroughPieceValueMg, ImmobilePieceValueMg, CommonerValueMg },
{ VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg,
- FersValueEg, AlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg, ChancellorValueEg,
- AmazonValueEg, KnibisValueMg, BiskniValueMg,
+ FersValueEg, AlfilValueEg, SilverValueEg, AiwokValueEg, BersValueEg,
+ ArchbishopValueMg, ChancellorValueEg, AmazonValueEg, KnibisValueMg, BiskniValueMg,
ShogiPawnValueEg, LanceValueEg, ShogiKnightValueEg, EuroShogiKnightValueEg, GoldValueEg, HorseValueEg,
ClobberPieceValueEg, BreakthroughPieceValueEg, ImmobilePieceValueEg, CommonerValueEg }
};
SilverValueMg = 600, SilverValueEg = 600,
AiwokValueMg = 2500, AiwokValueEg = 2500,
BersValueMg = 2000, BersValueEg = 2000,
- ChancellorValueMg = 2500, ChancellorValueEg = 2500,
+ ArchbishopValueMg = 2000, ArchbishopValueEg = 2000,
+ ChancellorValueMg = 2300, ChancellorValueEg = 2300,
AmazonValueMg = 3000, AmazonValueEg = 3000,
KnibisValueMg = 800, KnibisValueEg = 800,
BiskniValueMg = 800, BiskniValueEg = 800,
const int PIECE_TYPE_BITS = 5; // PIECE_TYPE_NB = pow(2, PIECE_TYPE_BITS)
enum PieceType {
- NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK,
- QUEEN, FERS, MET = FERS, ALFIL, SILVER, KHON = SILVER, AIWOK, BERS, DRAGON = BERS, CHANCELLOR,
- AMAZON, KNIBIS, BISKNI, SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, HORSE,
+ NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN,
+ FERS, MET = FERS, ALFIL, SILVER, KHON = SILVER, AIWOK, BERS, DRAGON = BERS,
+ ARCHBISHOP, CHANCELLOR, AMAZON, KNIBIS, BISKNI,
+ SHOGI_PAWN, LANCE, SHOGI_KNIGHT, EUROSHOGI_KNIGHT, GOLD, HORSE,
CLOBBER_PIECE, BREAKTHROUGH_PIECE, IMMOBILE_PIECE, COMMONER, KING,
ALL_PIECES = 0,
return "0000";
if (type_of(m) == CASTLING && !pos.is_chess960())
- to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
+ to = make_square(to > from ? pos.castling_kingside_file() : pos.castling_queenside_file(), rank_of(from));
string move = (type_of(m) == DROP ? std::string{pos.piece_to_char()[type_of(pos.moved_piece(m))],
Options["Protocol"] == "usi" ? '*' : '@'}
v->shogiPawnDropMateIllegal = true;
return v;
} ();
+ const Variant* capablanca = [&]{
+ Variant* v = new Variant();
+ v->maxRank = RANK_8;
+ v->maxFile = FILE_J;
+ v->castlingKingsideFile = FILE_I;
+ v->castlingQueensideFile = FILE_C;
+ v->add_piece(ARCHBISHOP, 'a');
+ v->add_piece(CHANCELLOR, 'c');
+ v->startFen = "rnabqkbcnr/pppppppppp/10/10/10/10/PPPPPPPPPP/RNABQKBCNR w KQkq - 0 1";
+ v->promotionPieceTypes = {ARCHBISHOP, CHANCELLOR, QUEEN, ROOK, BISHOP, KNIGHT};
+ return v;
+ } ();
#endif
// Add to UCI_Variant option
add("tictactoe", tictactoe);
#ifdef LARGEBOARDS
add("shogi", shogi);
+ add("capablanca", capablanca);
#endif
}
bool doubleStep = true;
bool firstRankDoubleSteps = false;
bool castling = true;
+ File castlingKingsideFile = FILE_G;
+ File castlingQueensideFile = FILE_C;
bool checking = true;
bool mustCapture = false;
bool pieceDrops = false;