private static void generate_castle(CastlingSide Side, bool OnlyChecks, Position pos, MoveStack[] ms, ref int mpos, Color us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side))==0) ) return; // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); Square rfrom = pos.castle_rook_square(us, Side); Square kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); Bitboard enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); for (Square s = Math.Min(kfrom, kto), e = Math.Max(kfrom, kto); s <= e; s++) if (s != kfrom // We are not in check && ((pos.attackers_to(s) & enemies) != 0)) return; // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) return; Move m = Utils.make_castle(kfrom, rfrom); if (OnlyChecks) { CheckInfo ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); bool givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) return; } ms[mpos++].move = m; }
/// move_to_san() takes a position and a move as input, where it is assumed /// that the move is a legal move for the position. The return value is /// a string containing the move in short algebraic notation. internal static string move_to_san(Position pos, Move m) { if (m == MoveC.MOVE_NONE) return "(none)"; if (m == MoveC.MOVE_NULL) return "(null)"; Debug.Assert(is_ok_M(m)); Bitboard attackers; bool ambiguousMove, ambiguousFile, ambiguousRank; Square sq, from = from_sq(m); Square to = to_sq(m); PieceType pt = type_of(pos.piece_moved(m)); StringBuilder san = new StringBuilder(); if (is_castle(m)) san.Append((to_sq(m) < from_sq(m) ? "O-O-O" : "O-O")); else { if (pt != PieceTypeC.PAWN) { san.Append(piece_type_to_char(pt).ToString()); // Disambiguation if we have more then one piece with destination 'to' // note that for pawns is not needed because starting file is explicit. attackers = pos.attackers_to(to) & pos.pieces_PTC(pt, pos.sideToMove); xor_bit(ref attackers, from); ambiguousMove = ambiguousFile = ambiguousRank = false; while (attackers != 0) { sq = pop_1st_bit(ref attackers); // Pinned pieces are not included in the possible sub-set if (!pos.pl_move_is_legal(make_move(sq, to), pos.pinned_pieces())) continue; if (file_of(sq) == file_of(from)) ambiguousFile = true; if (rank_of(sq) == rank_of(from)) ambiguousRank = true; ambiguousMove = true; } if (ambiguousMove) { if (!ambiguousFile) san.Append(file_to_char(file_of(from))); else if (!ambiguousRank) san.Append(rank_to_char(rank_of(from))); else san.Append(square_to_string(from)); } } if (pos.is_capture(m)) { if (pt == PieceTypeC.PAWN) san.Append(file_to_char(file_of(from))); san.Append('x'); } san.Append(square_to_string(to)); if (is_promotion(m)) { san.Append('='); san.Append(piece_type_to_char(promotion_type(m))); } } CheckInfo ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); if (pos.move_gives_check(m, ci)) { StateInfo st = new StateInfo(); pos.do_move(m, st); MList mlist = MListBroker.GetObject(); mlist.pos = 0; Movegen.generate_legal(pos, mlist.moves, ref mlist.pos); san.Append(mlist.pos > 0 ? "+" : "#"); MListBroker.Free(); pos.undo_move(m); } CheckInfoBroker.Free(); return san.ToString(); }
private static void generate_castle( int Side, bool Checks, Position pos, MoveStack[] ms, ref int mpos, int us) { if (pos.castle_impeded(us, Side) || (pos.can_castle_CR(Utils.make_castle_right(us, Side)) == 0)) { return; } // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. var kfrom = pos.king_square(us); var rfrom = pos.castle_rook_square(us, Side); var kto = Utils.relative_square(us, Side == CastlingSideC.KING_SIDE ? SquareC.SQ_G1 : SquareC.SQ_C1); var enemies = pos.pieces_C(us ^ 1); Debug.Assert(!pos.in_check()); int K = pos.chess960 ? kto > kfrom ? -1 : 1 : Side == CastlingSideC.KING_SIDE ? -1 : 1; for (Square s = kto; s != kfrom; s += (Square)K) { if ((pos.attackers_to(s) & enemies) != 0) { return; } } // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (pos.chess960 && ((pos.attackers_to(kto, Utils.xor_bit(pos.occupied_squares, rfrom)) & enemies) != 0)) { return; } var m = Utils.make(kfrom, rfrom, MoveTypeC.CASTLING); if (Checks) { var ci = CheckInfoBroker.GetObject(); ci.CreateCheckInfo(pos); var givesCheck = pos.move_gives_check(m, ci); CheckInfoBroker.Free(); if (!givesCheck) { return; } } ms[mpos++].move = m; }