public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int priv = ply == 1 ? gameHistory[Game.GameMoveNumber] : privs[ply - 1]; if (Game.CurrentSide == 0 && (priv & 1) == 1) { foreach (int direction in directions) { int square = Board.NextSquare(direction, kingSquare[0]); if (square >= 0 && Board[square] == null) { list.BeginMoveAdd(MoveType.StandardMove, kingSquare[0], square); Piece king = list.AddPickup(kingSquare[0]); list.AddDrop(king, square); list.EndMoveAdd(500); } } } else if (Game.CurrentSide == 1 && (priv & 2) == 2) { foreach (int direction in directions) { int square = Board.NextSquare(direction, kingSquare[1]); if (square >= 0 && Board[square] == null) { list.BeginMoveAdd(MoveType.StandardMove, kingSquare[1], square); Piece king = list.AddPickup(kingSquare[1]); list.AddDrop(king, square); list.EndMoveAdd(500); } } } } }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { Piece movingPiece = Board[from]; if (movingPiece.TypeNumber == promotingTypeNumber) { Location loc = Board.SquareToLocation(Board.PlayerSquare(movingPiece.Player, to)); PromotionOption option = condition(loc); if (option != PromotionOption.CannotPromote) { // enemy piece being captured (if any) Piece capturedEnemyPiece = Board[to]; // if promotion is optional, add move without promotion if (option == PromotionOption.CanPromote) { if (capturedEnemyPiece == null) { moves.AddMove(from, to, true); } else { moves.AddCapture(from, to, true); } } List <int> pieceTypesFound = new List <int>(); List <Piece> capturedPieces = Game.GetCapturedPieceList(movingPiece.Player); foreach (Piece capturedFriendlyPiece in capturedPieces) { if (capturedFriendlyPiece.TypeNumber != movingPiece.TypeNumber && !pieceTypesFound.Contains(capturedFriendlyPiece.TypeNumber)) { if (capturedEnemyPiece == null) { moves.BeginMoveAdd(MoveType.MoveReplace, from, to, capturedFriendlyPiece.TypeNumber); moves.AddPickup(from); moves.AddDrop(capturedFriendlyPiece, to); moves.EndMoveAdd(5000 + capturedFriendlyPiece.PieceType.MidgameValue); } else { moves.BeginMoveAdd(MoveType.CaptureReplace, from, to, capturedFriendlyPiece.TypeNumber); moves.AddPickup(from); moves.AddPickup(to); moves.AddDrop(capturedFriendlyPiece, to); moves.EndMoveAdd(5000 + capturedFriendlyPiece.PieceType.MidgameValue + capturedEnemyPiece.PieceType.MidgameValue); } pieceTypesFound.Add(capturedFriendlyPiece.TypeNumber); } } return(MoveEventResponse.Handled); } } return(MoveEventResponse.NotHandled); }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { Piece movingPiece = Board[from]; if (movingPiece == null) { throw new System.Exception("ex"); } if (movingPiece.TypeNumber == promotingTypeNumber) { // check the from-square condition (if any, usually there isn't) if (origLocationCondition != null) { Location fromLocation = Board.SquareToLocation(Board.PlayerSquare(movingPiece.Player, from)); if (!origLocationCondition(fromLocation)) { return(MoveEventResponse.NotHandled); } } // check the to-square condition Location toLocation = Board.SquareToLocation(Board.PlayerSquare(movingPiece.Player, to)); if (destLocationCondition(toLocation)) { // this is a promotion; add one move for each promotion type Piece capturedPiece = Board[to]; if (capturedPiece == null) { foreach (PieceType promoteTo in promotionTypes) { moves.BeginMoveAdd(MoveType.MoveWithPromotion, from, to); moves.AddPickup(from); moves.AddDrop(movingPiece, to, promoteTo); moves.EndMoveAdd(5000 + promoteTo.MidgameValue); } } else { foreach (PieceType promoteTo in promotionTypes) { moves.BeginMoveAdd(MoveType.CaptureWithPromotion, from, to); moves.AddPickup(from); moves.AddPickup(to); moves.AddDrop(movingPiece, to, promoteTo); moves.EndMoveAdd(5000 + promoteTo.MidgameValue + capturedPiece.PieceType.MidgameValue); } } return(MoveEventResponse.Handled); } } return(MoveEventResponse.NotHandled); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { int epSquare = ply == 1 ? gameHistory[Game.GameMoveNumber] : epSquares[ply - 1]; if (epSquare > 0) { int nd = Game.PlayerDirection(Game.CurrentSide ^ 1, NDirection); int sq = Board.NextSquare(nd, epSquare); Piece pawn = Board[sq]; for (int ndir = 0; ndir < nAttackDirections; ndir++) { int nextSquare = Board.NextSquare(attackDirections[Game.CurrentSide ^ 1, ndir], epSquare); if (nextSquare >= 0) { Piece piece = Board[nextSquare]; if (piece != null && piece.PieceType == PawnType && piece.Player == Game.CurrentSide) { // find square of pawn being captured. we may have to make several // steps for large-board games where pawns make more than two steps // and can still be captured e.p. int captureSquare = Board.NextSquare(nd, epSquare); while (Board[captureSquare] == null) { captureSquare = Board.NextSquare(nd, captureSquare); } // this piece can capture en passant int nSquaresFirstBoard = Board.NumSquares / 2; if (epSquare > nSquaresFirstBoard) { list.BeginMoveAdd(MoveType.EnPassant, nextSquare, epSquare - nSquaresFirstBoard); list.AddPickup(nextSquare); list.AddPickup(captureSquare); list.AddDrop(piece, epSquare - nSquaresFirstBoard, null); list.EndMoveAdd(120); } else { list.BeginMoveAdd(MoveType.EnPassant, nextSquare, epSquare + nSquaresFirstBoard); list.AddPickup(nextSquare); list.AddPickup(captureSquare); list.AddDrop(piece, epSquare + nSquaresFirstBoard, null); list.EndMoveAdd(120); } } } } } }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { int nSquaresOnFirstBoard = Board.NumSquares / 2; if (type == MoveType.StandardMove) { if (to >= nSquaresOnFirstBoard) { if (Board[to - nSquaresOnFirstBoard] == null) { moves.AddMove(from, to - nSquaresOnFirstBoard, true); } } else { if (Board[to + nSquaresOnFirstBoard] == null) { moves.AddMove(from, to + nSquaresOnFirstBoard, true); } } return(MoveEventResponse.Handled); } else if (type == MoveType.StandardCapture) { if (to >= nSquaresOnFirstBoard) { moves.BeginMoveAdd(MoveType.StandardCapture, from, to - nSquaresOnFirstBoard); Piece pieceBeingMoved = moves.AddPickup(from); Piece pieceBeingCaptured = moves.AddPickup(to); moves.AddDrop(pieceBeingMoved, to - nSquaresOnFirstBoard); moves.EndMoveAdd(3000 + pieceBeingCaptured.PieceType.MidgameValue - (pieceBeingMoved.PieceType.MidgameValue / 16)); } else { moves.BeginMoveAdd(MoveType.StandardCapture, from, to + nSquaresOnFirstBoard); Piece pieceBeingMoved = moves.AddPickup(from); Piece pieceBeingCaptured = moves.AddPickup(to); moves.AddDrop(pieceBeingMoved, to + nSquaresOnFirstBoard); moves.EndMoveAdd(3000 + pieceBeingCaptured.PieceType.MidgameValue - (pieceBeingMoved.PieceType.MidgameValue / 16)); } return(MoveEventResponse.Handled); } return(MoveEventResponse.NotHandled); }
// *** OVERRIDES *** // public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { BitBoard pawns = Board.GetPieceTypeBitboard(Game.CurrentSide, PawnType.TypeNumber); while (pawns) { int pawnSquare = pawns.ExtractLSB(); int nextSquare = Board.NextSquare(PredefinedDirections.N + Game.CurrentSide, pawnSquare); if (nextSquare >= 0 && Board[nextSquare] != null && Board[nextSquare].TypeNumber == PawnType.TypeNumber && Board[nextSquare].Player != Game.CurrentSide) { Piece enemyPawn = Board[nextSquare]; // we can only perform the swap if the enemyPawn is not // currently attacking any piece of the current side int attackSquare1 = Board.NextSquare(PredefinedDirections.E, pawnSquare); int attackSquare2 = Board.NextSquare(PredefinedDirections.W, pawnSquare); if ((attackSquare1 < 0 || Board[attackSquare1] == null || Board[attackSquare1].Player != Game.CurrentSide) && (attackSquare2 < 0 || Board[attackSquare2] == null || Board[attackSquare2].Player != Game.CurrentSide)) { // swap move is legal - add it now list.BeginMoveAdd(MoveType.Swap, pawnSquare, nextSquare); Piece myPawn = list.AddPickup(pawnSquare); enemyPawn = list.AddPickup(nextSquare); list.AddDrop(myPawn, nextSquare); list.AddDrop(enemyPawn, pawnSquare); list.EndMoveAdd(25); } } } } }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { if (currentState >= 4) { // Handle the automatic drops of the silver and gold generals at the beginning of the game if (Board[from].PieceType != pawnType || Game.StartingPieceSquares[Board[from].Player, from] == 0) { return(MoveEventResponse.IllegalMove); } //PieceType dropType = currentState < 6 ? silverGeneralType : goldGeneralType; moves.BeginMoveAdd(MoveType.StandardMove, from, to); Piece pawn = moves.AddPickup(from); moves.AddDrop(pawn, to); moves.AddDrop(generals[currentState - 4], from); moves.EndMoveAdd(pawnType.GetMidgamePST(Board.PlayerSquare(Board[from].Player, to))); return(MoveEventResponse.Handled); } else { // Don't allow to move the same piece twice in a row unless it is a king if (Board[from] == pieceLastMoved[searchStateHistoryIndex - 1] && Board[from].PieceType != kingType) { return(MoveEventResponse.IllegalMove); } } return(MoveEventResponse.NotHandled); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int king = Board.GetPieceTypeBitboard(Game.CurrentSide, kingType.TypeNumber).LSB; if (!IsSquareAttacked(king, Game.CurrentSide ^ 1)) { for (int dir = 0; dir < 8; dir++) { int nextSquare = Board.NextSquare(dir, king); if (nextSquare >= 0 && Board[nextSquare] != null && Board[nextSquare].Player == Game.CurrentSide && Board[nextSquare].PieceType != pawnType) { // The king can swap with this piece. We won't bother // to see if the target square is attacked because the // CheckmateRule is going to verify that anyway and we // don't want to perform that operation twice. list.BeginMoveAdd(MoveType.Swap, king, nextSquare); Piece kingpiece = list.AddPickup(king); Piece otherpiece = list.AddPickup(nextSquare); list.AddDrop(kingpiece, nextSquare); list.AddDrop(otherpiece, king); list.EndMoveAdd(0); } } } } }
// *** EVENT HANDLERS *** // public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { if (Board[from].PieceType == PieceType) { int direction = Board.DirectionLookup(from, to); if (direction >= 0) { int nextStep = Board.NextSquare(direction, to); if (nextStep >= 0 && nextStep < Board.NumSquares) { Piece pieceOnNextSquare = Board[nextStep]; Piece pieceOnLandingSquare = Board[to]; if (pieceOnNextSquare != null && pieceOnNextSquare.Player != Board[from].Player) { // we can capture by advance moves.BeginMoveAdd(pieceOnLandingSquare == null ? MoveType.BaroqueCapture : MoveType.ExtraCapture, from, to, nextStep); Piece pieceBeingMoved = moves.AddPickup(from); Piece pieceBeingCaptured = moves.AddPickup(nextStep); if (pieceOnLandingSquare != null) { moves.AddPickup(to); } moves.AddDrop(pieceBeingMoved, to); moves.EndMoveAdd(pieceOnLandingSquare == null ? (3000 + pieceBeingCaptured.PieceType.MidgameValue - (pieceBeingMoved.PieceType.MidgameValue / 16)) : (4000 + pieceBeingCaptured.PieceType.MidgameValue + pieceOnLandingSquare.PieceType.MidgameValue - (pieceBeingMoved.PieceType.MidgameValue / 16))); return(MoveEventResponse.Handled); } } } } return(base.MoveBeingGenerated(moves, from, to, type)); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { int epCaptureSquare = ply == 1 ? (Game.GameMoveNumber == 0 ? epCaptureSquares[0] : gameHistoryCaptureSquares[Game.GameMoveNumber - 1]) : epCaptureSquares[ply - 1]; if (epCaptureSquare > 0) { int targetSquare = ply == 1 ? (Game.GameMoveNumber == 0 ? epMoverSquares[0] : gameHistoryMoverSquares[Game.GameMoveNumber - 1]) : epMoverSquares[ply - 1]; int victimPawnMoveDirection = Board.DirectionLookup(epCaptureSquare, targetSquare); Piece targetPawn = Board[targetSquare]; while (epCaptureSquare != targetSquare) { int s = Board.NextSquare(captureDirections[targetPawn.Player], epCaptureSquare); Piece attacker = Board[Board.NextSquare(captureDirections[targetPawn.Player], epCaptureSquare)]; if (attacker.PieceType == PawnType) { // this is a valid en passant attack list.BeginMoveAdd(MoveType.EnPassant, attacker.Square, epCaptureSquare); list.AddPickup(attacker.Square); list.AddPickup(targetPawn.Square); list.AddDrop(attacker, epCaptureSquare, null); list.EndMoveAdd(3000); } epCaptureSquare = Board.NextSquare(victimPawnMoveDirection, epCaptureSquare); } } }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { Piece movingPiece = Board[from]; foreach (var change in changes) { if (change.PieceType == movingPiece.PieceType) { bool capturing = (type & MoveType.CaptureProperty) != 0; if ((capturing && change.ChangeOnCapture) || (!capturing && change.ChangeOnMove)) { Piece capturedPiece = Board[to]; if (capturedPiece != null) { // does capture have to be of a specific type? if (change.RequiredCaptureType != null && // and is this the wrong type? capturedPiece.PieceType != change.RequiredCaptureType) { // this change rule is not applicable continue; } moves.BeginMoveAdd(type, from, to); moves.AddPickup(from); moves.AddPickup(to); moves.AddDrop(movingPiece, to, change.NewType); moves.EndMoveAdd(change.NewType.MidgameValue - change.PieceType.MidgameValue + change.NewType.GetMidgamePST(from) - change.PieceType.GetMidgamePST(to) + capturedPiece.PieceType.MidgameValue + 1000); } else { moves.BeginMoveAdd(type, from, to); moves.AddPickup(from); moves.AddDrop(movingPiece, to, change.NewType); moves.EndMoveAdd(change.NewType.MidgameValue - change.PieceType.MidgameValue + change.NewType.GetMidgamePST(from) - change.PieceType.GetMidgamePST(to)); } return(MoveEventResponse.Handled); } continue; } } return(MoveEventResponse.NotHandled); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { int kingSquare = Board.GetPieceTypeBitboard(Game.CurrentSide, kingType.TypeNumber).LSB; BitBoard potentialAttackers = Board.GetPieceTypeBitboard(Game.CurrentSide ^ 1, chasingType.TypeNumber); while (potentialAttackers) { int sq = potentialAttackers.ExtractLSB(); int direction = Board.DirectionLookup(sq, kingSquare); if (direction >= 0 && chasingType.AttackRangePerDirection[direction] >= Board.GetDistance(sq, kingSquare)) { // King is attacked by appropriate chasing type. // Allow him to flee two squares in any direction. for (int nDir = 0; nDir < 8; nDir++) { int nextSquare = Board.NextSquare(nDir, kingSquare); if (nextSquare >= 0 && Board[nextSquare] == null) { nextSquare = Board.NextSquare(nDir, nextSquare); if (nextSquare >= 0) { Piece pieceOnSquare = Board[nextSquare]; if (pieceOnSquare == null) { list.BeginMoveAdd(MoveType.StandardMove, kingSquare, nextSquare); Piece king = list.AddPickup(kingSquare); list.AddDrop(king, nextSquare); list.EndMoveAdd(150); } else if (pieceOnSquare.Player != Game.CurrentSide) { list.BeginMoveAdd(MoveType.StandardCapture, kingSquare, nextSquare); Piece king = list.AddPickup(kingSquare); list.AddPickup(nextSquare); list.AddDrop(king, nextSquare); list.EndMoveAdd(3000 + pieceOnSquare.PieceType.MidgameValue); } } } } } } }
public static bool CustomMoveGenerationHandler(PieceType pieceType, Piece piece, MoveList moveList, bool capturesOnly) { MoveCapability[] moves; int nMoves = pieceType.GetMoveCapabilities(out moves); for (int nMove = 0; nMove < nMoves; nMove++) { MoveCapability move = moves[nMove]; int step = 1; int nextSquare = piece.Board.NextSquare(piece.Player, move.NDirection, piece.Square); while (nextSquare >= 0 && step <= move.MaxSteps) { Piece pieceOnSquare = piece.Board[nextSquare]; if (pieceOnSquare != null) { if (step >= move.MinSteps && move.CanCapture && pieceOnSquare.Player != piece.Player) { moveList.AddCapture(piece.Square, nextSquare); } else if (step >= move.MinSteps && pieceOnSquare.Player == piece.Player && piece.PieceType != pieceOnSquare.PieceType) { // self-capture move allowing relocation of friendly piece int currentSquare = piece.Square; while (currentSquare != nextSquare) { moveList.BeginMoveAdd(MoveType.MoveRelay, piece.Square, nextSquare, currentSquare); moveList.AddPickup(piece.Square); moveList.AddPickup(nextSquare); moveList.AddDrop(piece, nextSquare); moveList.AddDrop(pieceOnSquare, currentSquare); moveList.EndMoveAdd(piece.PieceType.GetMidgamePST(nextSquare) - piece.PieceType.GetMidgamePST(piece.Square) + pieceOnSquare.PieceType.GetMidgamePST(currentSquare) - pieceOnSquare.PieceType.GetMidgamePST(nextSquare)); currentSquare = piece.Board.NextSquare(piece.Player, move.NDirection, currentSquare); } } nextSquare = -1; } else { if (step >= move.MinSteps && !move.MustCapture && !capturesOnly) { moveList.AddMove(piece.Square, nextSquare); } nextSquare = piece.Board.NextSquare(piece.Player, move.NDirection, nextSquare); step++; } } } return(false); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int pocketSquare = pocketSquares[Game.CurrentSide]; Piece pieceInPocket = Board[pocketSquare]; if (pieceInPocket != null) { for (int square = 0; square < Board.NumSquares; square++) { if (Board[square] == null) { list.BeginMoveAdd(MoveType.Drop, pocketSquare, square); Piece piece = list.AddPickup(pocketSquare); list.AddDrop(piece, square, pieceInPocket.PieceType); list.EndMoveAdd(piece.PieceType.GetMidgamePST(square) - 10); } } } } }
// *** OVERRIDES *** // public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int nSquaresFirstBoard = Board.NumSquares / 2; int castlingPriv = ply == 1 ? gameHistoryPrivs[Game.GameMoveNumber] : searchStackPrivs[ply - 1]; for (int x = 0; x < nCastlingMoves[Game.CurrentSide]; x++) { if ((castlingMoves[Game.CurrentSide, x].RequiredPriv & castlingPriv) != 0) { // make sure final landing squares on the other board are free if (castlingMoves[Game.CurrentSide, x].KingFromSquare < nSquaresFirstBoard) { // going from first board to second if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard] != null || Board[castlingMoves[Game.CurrentSide, x].OtherToSquare + nSquaresFirstBoard] != null) { // occupied - castling not possible continue; } } else { // going from second board to first if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard] != null || Board[castlingMoves[Game.CurrentSide, x].OtherToSquare - nSquaresFirstBoard] != null) { // occupied - castling not possible continue; } } // find the left-most square that needs to be free on the board castling FROM int minSquare = castlingMoves[Game.CurrentSide, x].KingFromSquare; minSquare = castlingMoves[Game.CurrentSide, x].KingToSquare < minSquare ? castlingMoves[Game.CurrentSide, x].KingToSquare : minSquare; minSquare = castlingMoves[Game.CurrentSide, x].OtherFromSquare < minSquare ? castlingMoves[Game.CurrentSide, x].OtherFromSquare : minSquare; minSquare = castlingMoves[Game.CurrentSide, x].OtherToSquare < minSquare ? castlingMoves[Game.CurrentSide, x].OtherToSquare : minSquare; // find the right-most square that needs to be free on the board castling FROM int maxSquare = castlingMoves[Game.CurrentSide, x].KingFromSquare; maxSquare = castlingMoves[Game.CurrentSide, x].KingToSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].KingToSquare : maxSquare; maxSquare = castlingMoves[Game.CurrentSide, x].OtherFromSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].OtherFromSquare : maxSquare; maxSquare = castlingMoves[Game.CurrentSide, x].OtherToSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].OtherToSquare : maxSquare; // make sure the squares are empty bool squaresEmpty = true; for (int file = Board.GetFile(minSquare); squaresEmpty && file <= Board.GetFile(maxSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(minSquare); if (sq != castlingMoves[Game.CurrentSide, x].KingFromSquare && sq != castlingMoves[Game.CurrentSide, x].OtherFromSquare && Board[sq] != null) { // the path is blocked by a piece other than those involved in castling squaresEmpty = false; } } if (squaresEmpty) { // make sure squares the King is passes through are not attacked bool squaresAttacked = false; if (castlingMoves[Game.CurrentSide, x].KingFromSquare < castlingMoves[Game.CurrentSide, x].KingToSquare) { for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file <= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } } else { for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file >= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file--) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } } if (!squaresAttacked) { // required squares are empty and not attacked so the move is legal - add it if (castlingMoves[Game.CurrentSide, x].KingFromSquare < nSquaresFirstBoard) { // going from first board to second list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].OtherToSquare + nSquaresFirstBoard, null); list.EndMoveAdd(1000); } else { // going from second board to first list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].OtherToSquare - nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } } } } } }
public override MoveEventResponse MoveBeingGenerated(MoveList moves, int from, int to, MoveType type) { Piece movingPiece = Board[from]; foreach (PromotionCapability promotion in promotionCapabilities) { if (movingPiece.TypeNumber == promotion.PromotingTypeNumber) { Location toLocation = Board.SquareToLocation(Board.PlayerSquare(movingPiece.Player, to)); PromotionOption option = promotion.FromAndToConditionDelegate != null ? promotion.FromAndToConditionDelegate(Board.SquareToLocation(Board.PlayerSquare(movingPiece.Player, from)), toLocation) : promotion.ConditionDelegate(toLocation); if (option != PromotionOption.CannotPromote) { for (int x = 0; x < Game.MAX_PIECE_TYPES; x++) { typesUsed[x] = false; } // enemy piece being captured (if any) Piece capturedPiece = Board[to]; // if promotion is optional, add move without promotion if (option == PromotionOption.CanPromote) { if (capturedPiece == null) { moves.AddMove(from, to, true); } else { moves.AddCapture(from, to, true); } } // handle traditional promotion if (promotion.PromotionTypes != null) { if (capturedPiece == null) { foreach (PieceType promoteTo in promotion.PromotionTypes) { moves.BeginMoveAdd(MoveType.MoveWithPromotion, from, to); moves.AddPickup(from); moves.AddDrop(movingPiece, to, promoteTo); moves.EndMoveAdd(5000 + promoteTo.MidgameValue); typesUsed[promoteTo.TypeNumber] = true; } } else { foreach (PieceType promoteTo in promotion.PromotionTypes) { moves.BeginMoveAdd(MoveType.CaptureWithPromotion, from, to); moves.AddPickup(from); moves.AddPickup(to); moves.AddDrop(movingPiece, to, promoteTo); moves.EndMoveAdd(5000 + promoteTo.MidgameValue + capturedPiece.PieceType.MidgameValue); typesUsed[promoteTo.TypeNumber] = true; } } } // handle promotion by replacement if (promotion.ReplacementPromotionTypes != null) { List <Piece> capturedPieces = Game.GetCapturedPieceList(movingPiece.Player); foreach (Piece capturedFriendlyPiece in capturedPieces) { if (capturedFriendlyPiece.TypeNumber != movingPiece.TypeNumber && !typesUsed[capturedFriendlyPiece.TypeNumber] && promotion.ReplacementPromotionTypes.Contains(capturedFriendlyPiece.PieceType)) { if (capturedPiece == null) { moves.BeginMoveAdd(MoveType.MoveReplace, from, to, capturedFriendlyPiece.TypeNumber); moves.AddPickup(from); moves.AddDrop(capturedFriendlyPiece, to); moves.EndMoveAdd(5000 + capturedFriendlyPiece.PieceType.MidgameValue); } else { moves.BeginMoveAdd(MoveType.CaptureReplace, from, to, capturedFriendlyPiece.TypeNumber); moves.AddPickup(from); moves.AddPickup(to); moves.AddDrop(capturedFriendlyPiece, to); moves.EndMoveAdd(5000 + capturedFriendlyPiece.PieceType.MidgameValue + capturedPiece.PieceType.MidgameValue); } typesUsed[capturedFriendlyPiece.TypeNumber] = true; } } } return(MoveEventResponse.Handled); } } } return(MoveEventResponse.NotHandled); }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int nSquaresFirstBoard = Board.NumSquares / 2; int castlingPriv = ply == 1 ? gameHistoryPrivs[Game.GameMoveNumber] : searchStackPrivs[ply - 1]; for (int x = 0; x < nCastlingMoves[Game.CurrentSide]; x++) { if ((castlingMoves[Game.CurrentSide, x].RequiredPriv & castlingPriv) != 0) { if (castlingMoves[Game.CurrentSide, x].KingFromSquare < castlingMoves[Game.CurrentSide, x].KingToSquare) { bool squaresEmpty = true; for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare) + 1; squaresEmpty && (file <= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare) || file <= Board.GetFile(castlingMoves[Game.CurrentSide, x].OtherFromSquare)); file++) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (sq != castlingMoves[Game.CurrentSide, x].OtherFromSquare && Board[sq] != null) { squaresEmpty = false; } } if (squaresEmpty) { bool squaresAttacked = false; for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file <= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } if (!squaresAttacked) { if (castlingMoves[Game.CurrentSide, x].KingToSquare < nSquaresFirstBoard) { // moving from first board to second board if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard] == null && Board[castlingMoves[Game.CurrentSide, x].KingToSquare - Board.NumRanks + nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].KingToSquare - Board.NumRanks + nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } else { // moving from second board to first board if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard] == null && Board[castlingMoves[Game.CurrentSide, x].OtherToSquare - nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].KingToSquare - Board.NumRanks - nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare) + 1; !squaresAttacked && file < Board.GetFile(castlingMoves[Game.CurrentSide, x].OtherFromSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); squaresAttacked = Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1); if (!squaresAttacked) { if (castlingMoves[Game.CurrentSide, x].KingToSquare < nSquaresFirstBoard) { // moving from first board to second board if (Board[sq + nSquaresFirstBoard] == null && Board[sq - Board.NumRanks + nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, sq + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, sq + nSquaresFirstBoard, null); list.AddDrop(other, sq - Board.NumRanks + nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } else { // moving from second board to first board if (Board[sq - nSquaresFirstBoard] == null && Board[sq - Board.NumRanks - nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, sq - nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, sq - nSquaresFirstBoard, null); list.AddDrop(other, sq - Board.NumRanks - nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } } } } } } else { bool squaresEmpty = true; for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare) - 1; squaresEmpty && (file >= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare) || file >= Board.GetFile(castlingMoves[Game.CurrentSide, x].OtherFromSquare)); file--) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (sq != castlingMoves[Game.CurrentSide, x].OtherFromSquare && Board[sq] != null) { squaresEmpty = false; } } if (squaresEmpty) { bool squaresAttacked = false; for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file >= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file--) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } if (!squaresAttacked) { if (castlingMoves[Game.CurrentSide, x].KingToSquare < nSquaresFirstBoard) { // moving from first board to second board if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard] == null && Board[castlingMoves[Game.CurrentSide, x].KingToSquare + Board.NumRanks + nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].KingToSquare + Board.NumRanks + nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } else { // moving from second board to first board if (Board[castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard] == null && Board[castlingMoves[Game.CurrentSide, x].KingToSquare + Board.NumRanks - nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare - nSquaresFirstBoard, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].KingToSquare + Board.NumRanks - nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare) - 1; !squaresAttacked && file > Board.GetFile(castlingMoves[Game.CurrentSide, x].OtherFromSquare); file--) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); squaresAttacked = Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1); if (!squaresAttacked) { if (castlingMoves[Game.CurrentSide, x].KingToSquare < nSquaresFirstBoard) { // moving from first board to second board if (Board[sq + nSquaresFirstBoard] == null && Board[sq + Board.NumRanks + nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, sq + nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, sq + nSquaresFirstBoard, null); list.AddDrop(other, sq + Board.NumRanks + nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } else { // moving from second board to first board if (Board[sq - nSquaresFirstBoard] == null && Board[sq + Board.NumRanks - nSquaresFirstBoard] == null) { list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, sq - nSquaresFirstBoard); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, sq - nSquaresFirstBoard, null); list.AddDrop(other, sq + Board.NumRanks - nSquaresFirstBoard, null); list.EndMoveAdd(1000); } } } } } } } } } } }
public static bool CustomMoveGenerationHandler(PieceType pieceType, Piece piece, MoveList moveList, bool capturesOnly) { MoveCapability[] moves; int nMoves = pieceType.GetMoveCapabilities(out moves); for (int nMove = 0; nMove < nMoves; nMove++) { MoveCapability move = moves[nMove]; int step = 1; int nextSquare = piece.Board.NextSquare(piece.Player, move.NDirection, piece.Square); while (nextSquare >= 0 && step <= move.MaxSteps) { Piece pieceOnSquare = piece.Board[nextSquare]; if (pieceOnSquare != null) { if (step >= move.MinSteps && move.CanCapture && pieceOnSquare.Player != piece.Player) { moveList.AddCapture(piece.Square, nextSquare); for (int x = 0; x < 8; x++) { int targetSquare = piece.Board.NextSquare(x, nextSquare); if (targetSquare >= 0 && piece.Board[targetSquare] != null && piece.Board[targetSquare].Player != piece.Player) { moveList.BeginMoveAdd(MoveType.ExtraCapture, piece.Square, nextSquare, targetSquare); moveList.AddPickup(piece.Square); moveList.AddPickup(nextSquare); moveList.AddPickup(targetSquare); moveList.AddDrop(piece, nextSquare); moveList.EndMoveAdd(4000 + piece.Board[nextSquare].PieceType.MidgameValue + piece.Board[targetSquare].PieceType.MidgameValue); } } } nextSquare = -1; } else { if (step >= move.MinSteps && !move.MustCapture) { if (!capturesOnly) { moveList.AddMove(piece.Square, nextSquare); } for (int x = 0; x < 8; x++) { int targetSquare = piece.Board.NextSquare(x, nextSquare); if (targetSquare >= 0 && piece.Board[targetSquare] != null && piece.Board[targetSquare].Player != piece.Player) { moveList.BeginMoveAdd(MoveType.ExtraCapture, piece.Square, nextSquare, targetSquare); moveList.AddPickup(piece.Square); moveList.AddPickup(targetSquare); moveList.AddDrop(piece, nextSquare); moveList.EndMoveAdd(3000 + piece.Board[targetSquare].PieceType.MidgameValue); } } } nextSquare = piece.Board.NextSquare(piece.Player, move.NDirection, nextSquare); step++; } } } return(false); }
protected void generatePermutations(MoveList moves, int from, int to, int pendingBits, int activeBits) { if (pendingBits == 0) { // here is where we generate a move, capturing whichever pieces // are indicated by activeBits if (activeBits != 0) { // Determine whether activeBits has only one bit set. // If it has only one, the type of generated move will // be MoveType.ExtraCapture (a move type inherrently // understood by the framework.) If more than one // bit is set, we have multiple indirect captures and // we will need to use a custom MoveType MoveType moveType = (activeBits & (activeBits - 1)) == 0 ? MoveType.ExtraCapture : MoveType.CustomMove; // Calculate the evaluation for the move (we will add to // it as we pick up other pieces int eval = 2000 + (Board[to] != null ? Board[to].MidgameValue : 0); // Add the move moves.BeginMoveAdd(moveType, from, to, activeBits); Piece movingPiece = moves.AddPickup(from); if (Board[to] != null) { moves.AddPickup(to); } // Step through the intervening squares picking up // the appropriate pieces int direction = Board.DirectionLookup(from, to); int nSteps = 1; int nextSquare = Board.NextSquare(direction, from); while (nextSquare != to && activeBits != 0) { if ((activeBits & (1 << (nSteps - 1))) != 0) { moves.AddPickup(nextSquare); if (moveType == MoveType.ExtraCapture) { moves.SetMoveTag(nextSquare); } eval += Board[nextSquare].MidgameValue; activeBits ^= 1 << (nSteps - 1); } nextSquare = Board.NextSquare(direction, nextSquare); nSteps++; } moves.AddDrop(movingPiece, to); moves.EndMoveAdd(eval); } } else { // get the next bit from pendingBits and recursively call this // function both with and without that bit in activeBits int newPendingBits = pendingBits ^ (pendingBits & -pendingBits); int currentBit = pendingBits ^ newPendingBits; generatePermutations(moves, from, to, newPendingBits, activeBits); generatePermutations(moves, from, to, newPendingBits, activeBits | currentBit); } }
public override void GenerateSpecialMoves(MoveList list, bool capturesOnly, int ply) { if (!capturesOnly) { int castlingPriv = ply == 1 ? gameHistoryPrivs[Game.GameMoveNumber] : searchStackPrivs[ply - 1]; for (int x = 0; x < nCastlingMoves[Game.CurrentSide]; x++) { if ((castlingMoves[Game.CurrentSide, x].RequiredPriv & castlingPriv) != 0) { // find the left-most square that needs to be free int minSquare = castlingMoves[Game.CurrentSide, x].KingFromSquare; minSquare = castlingMoves[Game.CurrentSide, x].KingToSquare < minSquare ? castlingMoves[Game.CurrentSide, x].KingToSquare : minSquare; minSquare = castlingMoves[Game.CurrentSide, x].OtherFromSquare < minSquare ? castlingMoves[Game.CurrentSide, x].OtherFromSquare : minSquare; minSquare = castlingMoves[Game.CurrentSide, x].OtherToSquare < minSquare ? castlingMoves[Game.CurrentSide, x].OtherToSquare : minSquare; // find the right-most square that needs to be free int maxSquare = castlingMoves[Game.CurrentSide, x].KingFromSquare; maxSquare = castlingMoves[Game.CurrentSide, x].KingToSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].KingToSquare : maxSquare; maxSquare = castlingMoves[Game.CurrentSide, x].OtherFromSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].OtherFromSquare : maxSquare; maxSquare = castlingMoves[Game.CurrentSide, x].OtherToSquare > maxSquare ? castlingMoves[Game.CurrentSide, x].OtherToSquare : maxSquare; // make sure the squares are empty bool squaresEmpty = true; for (int file = Board.GetFile(minSquare); squaresEmpty && file <= Board.GetFile(maxSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(minSquare); if (sq != castlingMoves[Game.CurrentSide, x].KingFromSquare && sq != castlingMoves[Game.CurrentSide, x].OtherFromSquare && Board[sq] != null) { // the path is blocked by a piece other than those involved in castling squaresEmpty = false; } } if (squaresEmpty) { // make sure squares the King is passes through are not attacked bool squaresAttacked = false; // if this game doesn't have check/checkmate, we don't care if the squares are attacked if (hasCheckmateRule) { if (castlingMoves[Game.CurrentSide, x].KingFromSquare < castlingMoves[Game.CurrentSide, x].KingToSquare) { for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file <= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file++) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } } else { for (int file = Board.GetFile(castlingMoves[Game.CurrentSide, x].KingFromSquare); !squaresAttacked && file >= Board.GetFile(castlingMoves[Game.CurrentSide, x].KingToSquare); file--) { int sq = file * Board.NumRanks + Board.GetRank(castlingMoves[Game.CurrentSide, x].KingFromSquare); if (Game.IsSquareAttacked(sq, Game.CurrentSide ^ 1)) { squaresAttacked = true; } } } } if (!squaresAttacked) { // required squares are empty and not attacked so the move is legal - add it if (Board[castlingMoves[Game.CurrentSide, x].KingFromSquare] == null) { throw new Exception("!"); } list.BeginMoveAdd(MoveType.Castling, castlingMoves[Game.CurrentSide, x].KingFromSquare, castlingMoves[Game.CurrentSide, x].KingToSquare); Piece king = list.AddPickup(castlingMoves[Game.CurrentSide, x].KingFromSquare); Piece other = list.AddPickup(castlingMoves[Game.CurrentSide, x].OtherFromSquare); list.AddDrop(king, castlingMoves[Game.CurrentSide, x].KingToSquare, null); list.AddDrop(other, castlingMoves[Game.CurrentSide, x].OtherToSquare, null); list.EndMoveAdd(100); } } } } } }