/
expertdaniil
/
Chess
Обзор
Документация
Войти
/
expertdaniil
/
Chess
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Chess_MoveGen.cpp
229 строк
7 KB
expertdaniil
upload files
22 янв 2026, 15:44
Верифицирован
22 янв 2026, 15:44
a081d0c
Код
Авторство
О чём код?
#include "Chess_MoveGen.h" #include "Chess_Attack.h" #include "Chess_Apply.h" static bool isEnemy(const Piece& p, Side s) { return !p.isEmpty() && p.side != s; } static bool isFriend(const Piece& p, Side s){ return !p.isEmpty() && p.side == s; } static void addMove(std::vector<Move>& out, int from, int to, bool capture=false) { Move m; m.from = from; m.to = to; m.isCapture = capture; out.push_back(m); } static void genSteps(const ChessState& st, const PieceDef& def, int from, std::vector<Move>& out) { Side s = st.sideToMove(); int r = ChessState::row(from); int c = ChessState::col(from); for (const auto& d : def.steps) { int rr = r + d.dr; int cc = c + d.dc; if (!ChessState::inBounds(rr, cc)) continue; int to = ChessState::pack(rr, cc); const Piece& t = st.pieceAt(to); if (t.isEmpty()) addMove(out, from, to, false); else if (isEnemy(t, s)) addMove(out, from, to, true); } } static void genRays(const ChessState& st, const PieceDef& def, int from, std::vector<Move>& out) { Side s = st.sideToMove(); int r = ChessState::row(from); int c = ChessState::col(from); for (const auto& dir : def.rays) { int rr = r; int cc = c; for (int step=1; step<=def.maxRaySteps; ++step) { rr += dir.dr; cc += dir.dc; if (!ChessState::inBounds(rr, cc)) break; int to = ChessState::pack(rr, cc); const Piece& t = st.pieceAt(to); if (t.isEmpty()) { addMove(out, from, to, false); } else { if (isEnemy(t, s)) addMove(out, from, to, true); break; } } } } static void genPawn(const ChessState& st, int from, const RulesConfig& rules, std::vector<Move>& out) { const Piece& p = st.pieceAt(from); Side s = p.side; int r = ChessState::row(from); int c = ChessState::col(from); int dir = (s == Side::White) ? +1 : -1; int startRow = (s == Side::White) ? 1 : 6; int promoRow = (s == Side::White) ? 7 : 0; int r1 = r + dir; if (ChessState::inBounds(r1, c)) { int to1 = ChessState::pack(r1, c); if (st.pieceAt(to1).isEmpty()) { if (r1 == promoRow && rules.allowPromotion) { for (PieceKind pk : {PieceKind::Queen, PieceKind::Rook, PieceKind::Bishop, PieceKind::Knight}) { Move m; m.from=from; m.to=to1; m.isPromotion = true; m.promoKind = pk; out.push_back(m); } } else { addMove(out, from, to1, false); } if (r == startRow) { int r2 = r + 2*dir; int to2 = ChessState::pack(r2, c); if (ChessState::inBounds(r2, c) && st.pieceAt(to2).isEmpty()) { Move m; m.from=from; m.to=to2; m.isDoublePush = true; out.push_back(m); } } } } for (int dc : {-1, +1}) { int cc = c + dc; int rr = r + dir; if (!ChessState::inBounds(rr, cc)) continue; int to = ChessState::pack(rr, cc); const Piece& t = st.pieceAt(to); if (!t.isEmpty() && t.side != s) { if (rr == promoRow && rules.allowPromotion) { for (PieceKind pk : {PieceKind::Queen, PieceKind::Rook, PieceKind::Bishop, PieceKind::Knight}) { Move m; m.from=from; m.to=to; m.isCapture = true; m.isPromotion = true; m.promoKind = pk; out.push_back(m); } } else { addMove(out, from, to, true); } } } if (rules.allowEnPassant) { int ep = st.enPassantSquare(); if (ep >= 0) { int epr = ChessState::row(ep); int epc = ChessState::col(ep); if (epr == r + dir && (epc == c - 1 || epc == c + 1)) { Move m; m.from=from; m.to=ep; m.isCapture = true; m.isEnPassant = true; out.push_back(m); } } } } static void genCastling(const ChessState& st, const PieceDefRegistry& reg, const RulesConfig& rules, std::vector<Move>& out) { if (!rules.allowCastling) return; Side s = st.sideToMove(); const CastlingRights& cr = st.castling(); int r = (s == Side::White) ? 0 : 7; int kingFrom = ChessState::pack(r, 4); const Piece& king = st.pieceAt(kingFrom); if (king.isEmpty() || king.kind != PieceKind::King || king.side != s) return; if (IsKingInCheck(st, reg, s)) return; auto empty = [&](int rr,int cc){ return st.pieceAt(ChessState::pack(rr,cc)).isEmpty(); }; auto attacked = [&](int sq){ return IsSquareAttacked(st, reg, sq, Opposite(s)); }; bool canK = (s==Side::White) ? cr.wK : cr.bK; if (canK) { int f = ChessState::pack(r,5); int g = ChessState::pack(r,6); int rookSq = ChessState::pack(r,7); const Piece& rook = st.pieceAt(rookSq); if (!rook.isEmpty() && rook.kind == PieceKind::Rook && rook.side == s) { if (empty(r,5) && empty(r,6) && !attacked(f) && !attacked(g)) { Move m; m.from = kingFrom; m.to = g; m.isCastle = true; out.push_back(m); } } } bool canQ = (s==Side::White) ? cr.wQ : cr.bQ; if (canQ) { int cSq = ChessState::pack(r,2); int dSq = ChessState::pack(r,3); int bSq = ChessState::pack(r,1); int rookSq = ChessState::pack(r,0); const Piece& rook = st.pieceAt(rookSq); if (!rook.isEmpty() && rook.kind == PieceKind::Rook && rook.side == s) { if (empty(r,1) && empty(r,2) && empty(r,3) && !attacked(dSq) && !attacked(cSq)) { Move m; m.from = kingFrom; m.to = cSq; m.isCastle = true; out.push_back(m); } } } } std::vector<Move> ChessMoveGen::GeneratePseudoMoves(const ChessState& st, const PieceDefRegistry& reg, const RulesConfig& rules) { std::vector<Move> out; Side s = st.sideToMove(); for (int sq=0; sq<64; ++sq) { const Piece& p = st.pieceAt(sq); if (p.isEmpty() || p.side != s) continue; if (p.kind == PieceKind::Pawn) { genPawn(st, sq, rules, out); continue; } const PieceDef* def = reg.find(p.kind); if (!def) continue; if (!def->steps.empty()) genSteps(st, *def, sq, out); if (!def->rays.empty()) genRays(st, *def, sq, out); } genCastling(st, reg, rules, out); return out; } std::vector<Move> ChessMoveGen::GenerateLegalMoves(ChessState& st, const PieceDefRegistry& reg, const RulesConfig& rules) { auto pseudo = GeneratePseudoMoves(st, reg, rules); if (!rules.enforceKingSafety) return pseudo; std::vector<Move> legal; legal.reserve(pseudo.size()); Side mover = st.sideToMove(); for (const auto& mv : pseudo) { ChessUndo u = ChessApplier::ApplyMove(st, mv, rules); bool ok = !IsKingInCheck(st, reg, mover); ChessApplier::UndoMove(st, u); if (ok) legal.push_back(mv); } return legal; }