public CastleRule() { RuleParameter = new CastleRuleParameter[nSides]; newCastleRuleSides(); Clear(); }
private void newCastleRuleSides() { foreach (var parameter in Parameter) { var nSide = (Int32)parameter.SideName; RuleParameter[nSide] = new CastleRuleParameter(parameter); } }
private Boolean canOOO( BoardSide friend, BoardSide foe, CastleRuleParameter friendRule) { var bLegal = ((friend.FlagsHi & HiFlags.CanOOO) != 0) && ((friendRule.OOOPath & RankPiece) == 0) && friendRule.OOOSafe.HasValue && !isAttacked(foe, friendRule.OOOSafe.Value); return(bLegal); }
// //[Chess 960]Certain castling configurations require that both the King and the Rook // be removed before either is added back in their new positions. Orthodox Castling // does not require this; but one or even both of the From squares may coincide with // the castling partner To square in Chess 960. // private void rookCastles(BoardSide side, CastleRuleParameter rule, Int32 nTo) { if (nTo == rule.KingOOTo) { raisePiece(side, rule, vR6, rule.RookOOFrom.Value); lowerPiece(side, vR6, rule.RookOOTo); } else if (nTo == rule.KingOOOTo) { raisePiece(side, rule, vR6, rule.RookOOOFrom.Value); lowerPiece(side, vR6, rule.RookOOOTo); } }
// // Set EP flags only if an EP would be legal // private void tryEP( BoardSide friend, BoardSide foe, CastleRuleParameter friendRule, CastleRuleParameter foeRule, Int32 nMovedTo, Int32 nEnPassant) { if (!friend.KingPos.HasValue) { throw new ArgumentException(nameof(friend.KingPos), "Invalid King Position"); } var vKing = friend.KingPos.Value; var qpCaptureFrom = passed(friend, nEnPassant); while (qpCaptureFrom != 0) { var nCaptureFrom = RemoveLo(ref qpCaptureFrom); // // Test for legality, were Friend to play EP: // // 1) Remove the Friend Pawn from its nCaptureFrom square; // 2) And place it on the nEnPassant square. // 3) Remove the Foe Pawn from its nMovedTo square. // 4) Note whether the resulting position would be legal. // 5) Restore the Foe Pawn to its nMovedTo square. // 6) Remove the Friend Pawn placed on nEnPassant; // 7) And restore the Pawn to its nCaptureFrom square. // 8) If EP was Legal setEPFile(nEnPassant) and break. // raisePiece(friend, friendRule, vP6, nCaptureFrom); lowerPiece(friend, vP6, nEnPassant); //[Speed]Remove Not Needed, because material balance will be restored below. raisePiece(foe, foeRule, vP6, nMovedTo); //[Note]buildPawnAtx() is not needed to find Ray Checks var bLegal = (foe.Piece & DiagPiece & diagAtx(vKing)) == 0 && (foe.Piece & RectPiece & rectAtx(vKing)) == 0; //[Speed]placePiece Not Needed, because a Remove was not performed. lowerPiece(foe, vP6, nMovedTo); raisePiece(friend, friendRule, vP6, nEnPassant); lowerPiece(friend, vP6, nCaptureFrom); if (bLegal) { setEPFile(nEnPassant); break; } } }
protected void addCastles(BoardSide friend, CastleRuleParameter friendRule, BoardSide foe) { Debug.Assert(!InCheck(), "addCastles() called while InCheck"); if (canOO(friend, foe, friendRule)) { #if DebugMoveColor PseudoCastles.Add(Move.WTM | friendRule.OO); #else PseudoCastles.Add(friendRule.OO); #endif } if (canOOO(friend, foe, friendRule)) { #if DebugMoveColor PseudoCastles.Add(Move.WTM | friendRule.OOO); #else PseudoCastles.Add(friendRule.OOO); #endif } }
protected void removePiece(BoardSide side, CastleRuleParameter rule, Byte vPiece, Int32 nFrom) { var bLite = raisePiece(side, rule, vPiece, nFrom); decSideCount(side, vPiece); // // Update BishopMask, assuming DiagPiece is up to date // if (vPiece == vB6) { var qpBishop = side.Piece & Bishop; if (bLite) { if ((qpBishop & LiteSquare) == 0) { side.FlagsHi &= ~HiFlags.Lite; } } else if ((qpBishop & DarkSquare) == 0) { side.FlagsHi &= ~HiFlags.Dark; } #if HashPieces var u = (UInt32)(side.FlagsHi & HiFlags.Pair) >> nBishopPairBit; setTwoBits(ref side.PieceHash, 0, u); // Piece == vHF #endif } #if HashPieces if (vP6 < vPiece && vPiece < vK6) { var u = nibble(side.Counts >> vPiece * nPerNibble); setTwoBits(ref side.PieceHash, vPiece - vHF, u % vMod4); } #endif }
private Boolean raisePiece(BoardSide side, CastleRuleParameter rule, Byte vPiece, Int32 nFrom) { hashPiece(side, vPiece, nFrom); var qp = BIT0 << nFrom; #if VerifySquarePiece if ((qp & RankPiece) == 0) { var sb = new StringBuilder($"Square empty where {side.Parameter.SideName} Piece was expected at") .AppendSquares(qp); throw new MoveException(sb.ToString()); } else if ((qp & side.Piece) == 0) { var sb = new StringBuilder($"{side.Parameter.SideName} Piece was expected at") .AppendSquares(qp); throw new MoveException(sb.ToString()); } #endif clrPiece(side, qp); #if !Magic clrRotations(nFrom); #endif var bLite = false; switch (vPiece) { case vP6: Pawn &= ~qp; break; case vR6: RectPiece &= ~qp; if (nFrom == rule.RookOOFrom) { side.FlagsHi &= ~HiFlags.CanOO; } else if (nFrom == rule.RookOOOFrom) { side.FlagsHi &= ~HiFlags.CanOOO; } break; case vN6: Knight &= ~qp; break; case vB6: DiagPiece &= ~qp; bLite = (qp & LiteSquare) != 0; break; case vQ6: DiagPiece &= ~qp; RectPiece &= ~qp; break; case vK6: King &= ~qp; side.FlagsHi &= ~HiFlags.CanCastleMask; break; default: throw new PieceException("Unexpected Piece [raiseSide]"); } return(bLite); }
// Capture: ~6.3 MHz, Simple: ~10.5 MHz, Pawn: ~9.5 MHz protected void movePiece( BoardSide friend, BoardSide foe, CastleRuleParameter friendRule, CastleRuleParameter foeRule, ref Move move) { unpack2(move, out Int32 nFrom, out Int32 nTo, out UInt32 uPiece, out UInt32 uPromotion, out Boolean bCastles, out Boolean bCapture); var vPiece = pieceIndex(uPiece); var bSupplied = uPromotion > 0; #if VerifyPromotion //[PACN] var qpMoveTo = BIT0 << nTo; var bPromote = (friend.Parameter.RankLast & qpMoveTo) != 0; var bRequired = vPiece == vP6 && bPromote; Trace.Assert(bRequired == bSupplied, "Invalid Promotion"); #endif if (bSupplied) { removePiece(friend, friendRule, vPiece, nFrom); } else { raisePiece(friend, friendRule, vPiece, nFrom); } if (bCapture) { HalfMoveClock = 0; // HalfMoveClock Reset due to Capture var vCapture = captureIndex(nTo, ref move, out Boolean bEnPassant); var nCaptureFrom = bEnPassant ? nTo + foe.Parameter.ShiftRank : nTo; removePiece(foe, foeRule, vCapture, nCaptureFrom); if (vCapture == vP6) { resetPawnAtx(foe); } } else if (bCastles) { rookCastles(friend, friendRule, nTo); } if (bSupplied) { placePiece(friend, pieceIndex(uPromotion), nTo); } else { lowerPiece(friend, vPiece, nTo); } if (vPiece == vP6) { if (nTo - nFrom == 2 * friend.Parameter.ShiftRank) { var nEnPassant = nTo - friend.Parameter.ShiftRank; tryEP(foe, friend, foeRule, friendRule, nTo, nEnPassant); } HalfMoveClock = 0; // HalfMoveClock Reset due to Pawn Move resetPawnAtx(friend); } }