Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/apiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ inline std::string get_valid_special_chars(const Variant* v) {
validSpecialCharactersFirstField += '+';
if (v->promotionPieceTypes[WHITE] || v->promotionPieceTypes[BLACK])
validSpecialCharactersFirstField += '~';
if (!v->freeDrops && (v->pieceDrops || v->seirawanGating))
if (!v->freeDrops && (v->pieceDrops || v->seirawanGating || v->spellChess))
validSpecialCharactersFirstField += "[-]";
return validSpecialCharactersFirstField;
}
Expand Down Expand Up @@ -1032,7 +1032,7 @@ inline FenValidation validate_fen(const std::string& fen, const Variant* v, bool

// check for pocket
std::string pocket = "";
if (v->pieceDrops || v->seirawanGating)
if (v->pieceDrops || v->seirawanGating || v->spellChess)
{
if (check_pocket_info(fenParts[0], nbRanks, v, pocket) == NOK)
return FEN_INVALID_POCKET_INFO;
Expand Down
115 changes: 110 additions & 5 deletions src/movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ namespace {

*moveList++ = make<T>(from, to, pt);

if (pos.spell_chess())
{
PieceType freezePt = pos.freeze_potion_type();
if ( freezePt != NO_PIECE_TYPE
&& pos.freeze_cd(us) == 0
&& pos.count_in_hand(us, freezePt) > 0)
{
Bitboard origins = square_bb(from);
for (Bitboard centers = pos.board_bb(); centers; )
{
Square center = pop_lsb(centers);
Bitboard zone = (attacks_bb<KING>(center) | square_bb(center)) & pos.board_bb();
if (zone & origins)
continue;
*moveList++ = make_gating<T>(from, to, freezePt, center);
}
}
}

// Gating moves
if (pos.seirawan_gating() && (pos.gates(us) & from))
for (PieceSet ps = pos.piece_types(); ps;)
Expand Down Expand Up @@ -147,7 +166,7 @@ namespace {
const Bitboard doubleStepRegion = pos.double_step_region(Us);
const Bitboard tripleStepRegion = pos.triple_step_region(Us);

const Bitboard pawns = pos.pieces(Us, PAWN);
const Bitboard pawns = pos.pieces(Us, PAWN) & ~pos.freeze_zone(Us);
const Bitboard movable = pos.board_bb(Us, PAWN) & ~pos.pieces();
const Bitboard capturable = pos.board_bb(Us, PAWN) & pos.pieces(Them);

Expand Down Expand Up @@ -291,7 +310,31 @@ namespace {

assert(Pt != KING && Pt != PAWN);

Bitboard bb = pos.pieces(Us, Pt);
Bitboard bb = pos.pieces(Us, Pt) & ~pos.freeze_zone(Us);
Bitboard boardMask = pos.board_bb();
Bitboard occupiedAll = pos.pieces();
Bitboard ourPieces = pos.pieces(Us);

auto advance = [&](Square sq, Direction dir) -> Square {
Square next = Square(int(sq) + int(dir));
if (!is_ok(next) || !(boardMask & square_bb(next)))
return SQ_NONE;
int fileDelta = file_of(next) - file_of(sq);
int rankDelta = rank_of(next) - rank_of(sq);
switch (dir)
{
case NORTH: if (fileDelta != 0 || rankDelta != 1) return SQ_NONE; break;
case SOUTH: if (fileDelta != 0 || rankDelta != -1) return SQ_NONE; break;
case EAST: if (rankDelta != 0 || fileDelta != 1) return SQ_NONE; break;
case WEST: if (rankDelta != 0 || fileDelta != -1) return SQ_NONE; break;
case NORTH_EAST: if (fileDelta != 1 || rankDelta != 1) return SQ_NONE; break;
case NORTH_WEST: if (fileDelta != -1 || rankDelta != 1) return SQ_NONE; break;
case SOUTH_EAST: if (fileDelta != 1 || rankDelta != -1) return SQ_NONE; break;
case SOUTH_WEST: if (fileDelta != -1 || rankDelta != -1) return SQ_NONE; break;
default: break;
}
return next;
};

while (bb)
{
Expand Down Expand Up @@ -366,6 +409,56 @@ namespace {
if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
while (epSquares)
moveList = make_move_and_gating<EN_PASSANT>(pos, moveList, Us, from, pop_lsb(epSquares));

if ( pos.spell_chess()
&& pos.jump_potion_type() != NO_PIECE_TYPE
&& pos.jump_cd(Us) == 0
&& pos.count_in_hand(Us, pos.jump_potion_type()) > 0
&& (Pt == ROOK || Pt == BISHOP || Pt == QUEEN))
{
PieceType jumpPt = pos.jump_potion_type();
Bitboard captureTargets = target;
if constexpr (Type != QUIETS && Type != QUIET_CHECKS)
captureTargets |= pos.pieces(~Us);
auto generate_jump = [&](Direction dir) {
Square sq = advance(from, dir);
Square blocker = SQ_NONE;
while (sq != SQ_NONE)
{
Bitboard sqBB = square_bb(sq);
if (occupiedAll & sqBB)
{
if (blocker == SQ_NONE)
{
blocker = sq;
sq = advance(sq, dir);
continue;
}
if (!(ourPieces & sqBB) && (captureTargets & sqBB))
*moveList++ = make_gating<NORMAL>(from, sq, jumpPt, blocker);
break;
}
if (blocker != SQ_NONE && (target & sqBB))
*moveList++ = make_gating<NORMAL>(from, sq, jumpPt, blocker);
sq = advance(sq, dir);
}
};

if (Pt == ROOK || Pt == QUEEN)
{
generate_jump(NORTH);
generate_jump(SOUTH);
generate_jump(EAST);
generate_jump(WEST);
}
if (Pt == BISHOP || Pt == QUEEN)
{
generate_jump(NORTH_EAST);
generate_jump(NORTH_WEST);
generate_jump(SOUTH_EAST);
generate_jump(SOUTH_WEST);
}
}
}

return moveList;
Expand Down Expand Up @@ -416,7 +509,12 @@ namespace {
Square from = pos.castling_king_square(Us);
for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(cr));
{
Square rookFrom = pos.castling_rook_square(cr);
if (pos.freeze_zone(Us) & (square_bb(from) | square_bb(rookFrom)))
continue;
moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, rookFrom);
}
}

// Special moves
Expand Down Expand Up @@ -453,7 +551,9 @@ namespace {
}

// King moves
if (pos.count<KING>(Us) && (!Checks || pos.blockers_for_king(~Us) & ksq))
if (pos.count<KING>(Us)
&& !(pos.freeze_zone(Us) & square_bb(ksq))
&& (!Checks || pos.blockers_for_king(~Us) & ksq))
{
Bitboard b = ( (pos.attacks_from(Us, KING, ksq) & pos.pieces())
| (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
Expand All @@ -467,7 +567,12 @@ namespace {
if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
if (!pos.castling_impeded(cr) && pos.can_castle(cr))
moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, pos.castling_rook_square(cr));
{
Square rookFrom = pos.castling_rook_square(cr);
if (pos.freeze_zone(Us) & (square_bb(ksq) | square_bb(rookFrom)))
continue;
moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, rookFrom);
}
}

return moveList;
Expand Down
44 changes: 44 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <string>
#include <sstream>
#include <cctype>

#include "apiutil.h"
#include "parser.h"
Expand Down Expand Up @@ -480,6 +481,49 @@ Variant* VariantParser<DoCheck>::parse(Variant* v) {
parse_attribute("wallingRegion", v->wallingRegion[BLACK]);
parse_attribute("wallOrMove", v->wallOrMove);
parse_attribute("seirawanGating", v->seirawanGating);
auto parsePotion = [&](const char* option, PieceType& target) {
if (const auto it = config.find(option); it != config.end())
{
if (it->second.size() != 1)
{
if (DoCheck)
std::cerr << option << " - Invalid piece code: " << it->second << std::endl;
return;
}

char token = it->second[0];
char upper = toupper(token);
if (!isalpha(upper))
{
if (DoCheck)
std::cerr << option << " - Invalid piece code: " << it->second << std::endl;
return;
}
size_t idx = v->pieceToChar.find(upper);
if (idx == std::string::npos)
idx = v->pieceToCharSynonyms.find(upper);

if (idx != std::string::npos)
{
target = type_of(Piece(idx));
return;
}

for (PieceType pt = CUSTOM_PIECES; pt <= CUSTOM_PIECES_END; ++pt)
if (!(v->pieceTypes & piece_set(pt)))
{
v->add_piece(pt, upper, "");
target = pt;
return;
}

if (DoCheck)
std::cerr << option << " - Unable to allocate piece letter: " << token << std::endl;
}
};

parsePotion("freezePotion", v->freezePotionPT);
parsePotion("jumpPotion", v->jumpPotionPT);
parse_attribute("cambodianMoves", v->cambodianMoves);
parse_attribute("diagonalLines", v->diagonalLines);
parse_attribute("pass", v->pass[WHITE]);
Expand Down
Loading
Loading