public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance posDelta = new PositionDistance(origin, destination); if (posDelta.DistanceX != posDelta.DistanceY) { return(false); } bool increasingRank = destination.Rank > origin.Rank; bool increasingFile = (int)destination.File > (int)origin.File; for (int f = (int)origin.File + (increasingFile ? 1 : -1), r = origin.Rank + (increasingRank ? 1 : -1); increasingFile?f <(int)destination.File : f> (int) destination.File; f += increasingFile ? 1 : -1, r += increasingRank ? 1 : -1) { if (game.GetPieceAt((File)f, r) != null) { return(false); } } return(true); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance distance = new PositionDistance(origin, destination); if (((distance.DistanceX == 1 && distance.DistanceY == 1) || (distance.DistanceX == 0 && distance.DistanceY == 1) || (distance.DistanceX == 1 && distance.DistanceY == 0)) && (game.GetPieceAt(destination) == null || game.GetPieceAt(destination).Owner == ChessUtilities.GetOpponentOf(move.Player))) { return(true); } if (distance.DistanceX == 2) { if (move.Player == Player.White) { if (origin.Rank != 1 || destination.Rank != 1) { return(false); } if (game.InitialWhiteKingFile == File.E && game.InitialWhiteRookFileKingsideCastling == File.H && destination.File == File.G) { return(CanCastle(origin, new Position(File.H, 1), game)); } if (game.InitialWhiteKingFile == File.E && game.InitialWhiteRookFileQueensideCastling == File.A && destination.File == File.C) { return(CanCastle(origin, new Position(File.A, 1), game)); } } else { if (origin.Rank != 8 || destination.Rank != 8) { return(false); } if (game.InitialBlackKingFile == File.E && game.InitialBlackRookFileKingsideCastling == File.H && destination.File == File.G) { return(CanCastle(origin, new Position(File.H, 8), game)); } if (game.InitialBlackKingFile == File.E && game.InitialBlackRookFileQueensideCastling == File.A && destination.File == File.C) { return(CanCastle(origin, new Position(File.A, 8), game)); } } } if (game.GetPieceAt(destination) is Rook) { return(CanCastle(origin, destination, game)); } else { return(false); } }
public bool UpdateAndCheckIfRedrawRequired() { if (_showSceneControl.RenderSetup == null) { return(false); } // Stop all transitions when switching between camera-ops if (_showSceneControl.RenderSetup.CurrentCameraOp != _cameraOperator) { _cameraOperator = _showSceneControl.RenderSetup.CurrentCameraOp; _cameraPositionGoal = _showSceneControl.RenderSetup.CameraPosition; _cameraTargetGoal = _showSceneControl.RenderSetup.CameraTarget; MoveVelocity = Vector3.Zero; _isTransitionActive = false; } // This is an extremely unfortunate solution to check if the camera has been manipulated from the // outside (e.g. by another view, parameters or animation) if (!_isTransitionActive && (PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD)) { _cameraPositionGoal = _showSceneControl.RenderSetup.CameraPosition; _cameraTargetGoal = _showSceneControl.RenderSetup.CameraTarget; return(true); } var redrawRequired = false; UpdateRawMouseData(); if (_lockInteraction) { return(false); } _lockInteraction = true; // Manipulation... redrawRequired |= ManipulateGizmos(); if (_showSceneControl.RenderSetup.TransformGizmo.State != TransformGizmo.TransformGizmo.GizmoStates.Dragged) { ManipulateCameraByMouse(); } _manipulatedByKeyboard = ManipulateCameraByKeyboard(); _spaceMouse.ManipulateCamera(); // Transition... redrawRequired |= ComputeCameraMovement(); _lockInteraction = false; return(redrawRequired); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance posDelta = new PositionDistance(origin, destination); if ((posDelta.DistanceX != 2 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 1 || posDelta.DistanceY != 2)) return false; return true; }
public static void TestPositionDistance() { Position position1 = new Position(File.A, 2); Position position2 = new Position(File.A, 3); PositionDistance distance1 = new PositionDistance(position1, position2); Assert.AreEqual(0, distance1.DistanceX); Assert.AreEqual(1, distance1.DistanceY); PositionDistance distance2 = new PositionDistance(position2, position1); Assert.AreEqual(0, distance2.DistanceX); Assert.AreEqual(1, distance2.DistanceY); }
public static void TestPositionDistance() { Position position1 = new Position(File.A, Rank.Two); Position position2 = new Position(File.A, Rank.Three); PositionDistance distance1 = new PositionDistance(position1, position2); Assert.AreEqual(0, distance1.DistanceX); Assert.AreEqual(1, distance1.DistanceY); PositionDistance distance2 = new PositionDistance(position2, position1); Assert.AreEqual(0, distance2.DistanceX); Assert.AreEqual(1, distance2.DistanceY); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance posDelta = new PositionDistance(origin, destination); if ((posDelta.DistanceX != 2 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 1 || posDelta.DistanceY != 2)) { return(false); } return(true); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance distance = new PositionDistance(origin, destination); if ((distance.DistanceX != 1 || distance.DistanceY != 1) && (distance.DistanceX != 0 || distance.DistanceY != 1) && (distance.DistanceX != 1 || distance.DistanceY != 0) && (distance.DistanceX != 2 || distance.DistanceY != 0)) return false; if (distance.DistanceX != 2) return true; return CanCastle(origin, destination, game); }
/* * Returns false if camera didn't move */ private bool ComputeCameraMovement() { var frameDurationFactor = (float)(App.Current.TimeSinceLastFrame) / FRAME_DURATION_AT_60_FPS; if (PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD || MoveVelocity.Length() > STOP_DISTANCE_THRESHOLD || _lookingAroundDelta.Length() > STOP_DISTANCE_THRESHOLD || _manipulatedByMouseWheel || _orbitDelta.Length() > 0.001f || _manipulatedByKeyboard) { if (_orbitDelta.Length() > 0.001f) { OrbitByAngle(_orbitDelta); _orbitDelta *= new Vector2(ORBIT_HORIZONTAL_FRICTION, ORBIT_VERTICAL_FRICTION) / frameDurationFactor; } if (MoveVelocity.Length() > MaxMoveVelocity) { MoveVelocity *= MaxMoveVelocity / MoveVelocity.Length(); } else if (!_manipulatedByKeyboard) { MoveVelocity *= (1 - _frictionKeyboardManipulation) / frameDurationFactor; } _cameraPositionGoal += MoveVelocity; _cameraTargetGoal += MoveVelocity + _lookingAroundDelta; _lookingAroundDelta = Vector3.Zero; PositionDistance *= CAMERA_MOVE_FRICTION / frameDurationFactor; TargetDistance *= CAMERA_MOVE_FRICTION / frameDurationFactor; _isTransitionActive = true; _manipulatedByMouseWheel = false; return(true); } else { StopTransitionOfPositionTarget(); _isTransitionActive = false; return(false); } }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, nameof(move)); ChessUtilities.ThrowIfNull(game, nameof(game)); Position origin = move.OriginalPosition; Position destination = move.NewPosition; var posDelta = new PositionDistance(origin, destination); if (posDelta.DistanceX != 0 && posDelta.DistanceY != 0) { return(false); } bool increasingRank = destination.Rank > origin.Rank; bool increasingFile = (int)destination.File > (int)origin.File; if (posDelta.DistanceX == 0) { int f = (int)origin.File; for (int r = origin.Rank + (increasingRank ? 1 : -1); increasingRank?r <destination.Rank : r> destination.Rank; r += increasingRank ? 1 : -1) { if (game.GetPieceAt((File)f, r) != null) { return(false); } } } else // (posDelta.DeltaY == 0) { int r = origin.Rank; for (int f = (int)origin.File + (increasingFile ? 1 : -1); increasingFile?f <(int)destination.File : f> (int) destination.File; f += increasingFile ? 1 : -1) { if (game.GetPieceAt((File)f, r) != null) { return(false); } } } return(true); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; PositionDistance posDelta = new PositionDistance(origin, destination); if (posDelta.DistanceX != 0 && posDelta.DistanceY != 0) return false; bool increasingRank = destination.Rank > origin.Rank; bool increasingFile = (int)destination.File > (int)origin.File; if (posDelta.DistanceX == 0) { int f = (int)origin.File; for (int r = origin.Rank + (increasingRank ? 1 : -1); increasingRank ? r < destination.Rank : r > destination.Rank; r += increasingRank ? 1 : -1) { if (game.GetPieceAt((File)f, r) != null) { return false; } } } else // (posDelta.DeltaY == 0) { int r = origin.Rank; for (int f = (int)origin.File + (increasingFile ? 1 : -1); increasingFile ? f < (int)destination.File : f > (int)destination.File; f += increasingFile ? 1 : -1) { if (game.GetPieceAt((File)f, r) != null) { return false; } } } return true; }
/** * WPF will discard some mouse-wheel events on slow framerates which leads to a laggy * interaction in complex scenes. For that reason, we include the framerate into the zoom-speed * and -- sadly -- avoid transitions for for zooming. */ public void HandleMouseWheel(float delta) { var transitionActive = PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD; var viewDirection = transitionActive ? _cameraPositionGoal - _cameraTargetGoal : _showSceneControl.RenderSetup.CameraPosition - _showSceneControl.RenderSetup.CameraTarget; var frameDurationFactor = (float)(App.Current.TimeSinceLastFrame) / FRAME_DURATION_AT_60_FPS; var zoomFactorForCurrentFramerate = 1 + (ZOOM_SPEED * frameDurationFactor); if (delta < 0) { viewDirection *= zoomFactorForCurrentFramerate; } else { viewDirection /= zoomFactorForCurrentFramerate; } _showSceneControl.RenderSetup.CameraPosition = _cameraPositionGoal = _cameraTargetGoal + viewDirection; _manipulatedByMouseWheel = true; }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; Piece promotion = null; if (move.Promotion.HasValue && ValidPromotionPieces.Contains(move.Promotion.Value)) { promotion = game.MapPgnCharToPiece(char.ToUpper(move.Promotion.Value), move.Player); } PositionDistance posDelta = new PositionDistance(origin, destination); if ((posDelta.DistanceX != 0 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 1 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 0 || posDelta.DistanceY != 2)) { return(false); } if (Owner == Player.White) { if (origin.Rank > destination.Rank) { return(false); } if (destination.Rank == 8) { if (promotion == null) { return(false); } if (promotion.Owner != Player.White) { return(false); } if (!ValidPromotionPieces.Contains(promotion.GetFenCharacter())) { return(false); } } } if (Owner == Player.Black) { if (origin.Rank < destination.Rank) { return(false); } if (destination.Rank == 1) { if (promotion == null) { return(false); } if (promotion.Owner != Player.Black) { return(false); } if (!ValidPromotionPieces.Contains(promotion.GetFenCharacter())) { return(false); } } } bool checkEnPassant = false; if (posDelta.DistanceY == 2) { if ((origin.Rank != 2 && Owner == Player.White) || (origin.Rank != 7 && Owner == Player.Black)) { return(false); } if (origin.Rank == 2 && game.GetPieceAt(origin.File, 3) != null) { return(false); } if (origin.Rank == 7 && game.GetPieceAt(origin.File, 6) != null) { return(false); } } Piece pieceAtDestination = game.GetPieceAt(destination); if (posDelta.DistanceX == 0 && (posDelta.DistanceY == 1 || posDelta.DistanceY == 2)) { if (pieceAtDestination != null) { return(false); } } else { if (pieceAtDestination == null) { checkEnPassant = true; } else if (pieceAtDestination.Owner == Owner) { return(false); } } if (checkEnPassant) { ReadOnlyCollection <DetailedMove> _moves = game.Moves; if (_moves.Count == 0) { return(false); } if ((origin.Rank != 5 && Owner == Player.White) || (origin.Rank != 4 && Owner == Player.Black)) { return(false); } Move latestMove = _moves[_moves.Count - 1]; if (latestMove.NewPosition == null) { return(false); } if (latestMove.Player != ChessUtilities.GetOpponentOf(Owner)) { return(false); } if (!(game.GetPieceAt(latestMove.NewPosition) is Pawn)) { return(false); } if (game.GetPieceAt(latestMove.NewPosition).Owner == Owner) { return(false); } if (Owner == Player.White) { if (latestMove.OriginalPosition.Rank != 7 || latestMove.NewPosition.Rank != 5) { return(false); } } else // (m.Player == Players.Black) { if (latestMove.OriginalPosition.Rank != 2 || latestMove.NewPosition.Rank != 4) { return(false); } } if (destination.File != latestMove.NewPosition.File) { return(false); } } return(true); }
public override bool IsValidMove(Move move, ChessGame game) { ChessUtilities.ThrowIfNull(move, "move"); ChessUtilities.ThrowIfNull(game, "game"); Position origin = move.OriginalPosition; Position destination = move.NewPosition; Piece promotion = null; if (move.Promotion.HasValue && ValidPromotionPieces.Contains(move.Promotion.Value)) { promotion = game.MapPgnCharToPiece(char.ToUpper(move.Promotion.Value), move.Player); } PositionDistance posDelta = new PositionDistance(origin, destination); if ((posDelta.DistanceX != 0 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 1 || posDelta.DistanceY != 1) && (posDelta.DistanceX != 0 || posDelta.DistanceY != 2)) return false; if (Owner == Player.White) { if (origin.Rank > destination.Rank) return false; if (destination.Rank == 8) { if (promotion == null) return false; if (promotion.Owner != Player.White) return false; if (!ValidPromotionPieces.Contains(promotion.GetFenCharacter())) return false; } } if (Owner == Player.Black) { if (origin.Rank < destination.Rank) return false; if (destination.Rank == 1) { if (promotion == null) return false; if (promotion.Owner != Player.Black) return false; if (!ValidPromotionPieces.Contains(promotion.GetFenCharacter())) return false; } } bool checkEnPassant = false; if (posDelta.DistanceY == 2) { if ((origin.Rank != 2 && Owner == Player.White) || (origin.Rank != 7 && Owner == Player.Black)) return false; if (origin.Rank == 2 && game.GetPieceAt(origin.File, 3) != null) return false; if (origin.Rank == 7 && game.GetPieceAt(origin.File, 6) != null) return false; } Piece pieceAtDestination = game.GetPieceAt(destination); if (posDelta.DistanceX == 0 && (posDelta.DistanceY == 1 || posDelta.DistanceY == 2)) { if (pieceAtDestination != null) return false; } else { if (pieceAtDestination == null) checkEnPassant = true; else if (pieceAtDestination.Owner == Owner) return false; } if (checkEnPassant) { ReadOnlyCollection<DetailedMove> _moves = game.Moves; if (_moves.Count == 0) { return false; } if ((origin.Rank != 5 && Owner == Player.White) || (origin.Rank != 4 && Owner == Player.Black)) return false; Move latestMove = _moves[_moves.Count - 1]; if (latestMove.Player != ChessUtilities.GetOpponentOf(Owner)) return false; if (!(game.GetPieceAt(latestMove.NewPosition) is Pawn)) return false; if (game.GetPieceAt(latestMove.NewPosition).Owner == Owner) return false; if (Owner == Player.White) { if (latestMove.OriginalPosition.Rank != 7 || latestMove.NewPosition.Rank != 5) return false; } else // (m.Player == Players.Black) { if (latestMove.OriginalPosition.Rank != 2 || latestMove.NewPosition.Rank != 4) return false; } if (destination.File != latestMove.NewPosition.File) return false; } return true; }
public SubmittedMoveResponse SubmitMove(Move move) { SubmittedMoveResponse response = new SubmittedMoveResponse(); MoveType type = Game.ApplyMove(move, false); if (type == MoveType.Invalid) { response.Success = false; response.Error = "Invalid move."; response.Correct = -3; return(response); } response.Success = true; response.Check = Game.IsInCheck(Game.WhoseTurn) ? Game.WhoseTurn.ToString().ToLowerInvariant() : null; response.FEN = Game.GetFen(); if (Game.IsWinner(ChessUtilities.GetOpponentOf(Game.WhoseTurn))) { response.Correct = 1; return(response); } else if (Game.IsWinner(Game.WhoseTurn)) { response.Correct = -3; return(response); } else if (Game.DrawCanBeClaimed) { response.Correct = -1; return(response); } else if (Game.IsStalemated(Game.WhoseTurn)) { response.Correct = -2; return(response); } response.Correct = 0; Move chosen = null; if (Game is AtomicChessGame) { Position whiteKing = null; Position blackKing = null; for (int i = 0; i < 8; i++) { for (int j = 1; j < 9; j++) { if (Game.GetPieceAt((File)i, j) == new King(Player.White)) { whiteKing = new Position((File)i, j); } if (Game.GetPieceAt((File)i, j) == new King(Player.Black)) { blackKing = new Position((File)i, j); } if (whiteKing != null && blackKing != null) { break; } } } ReadOnlyCollection <Move> validKingMoves = Game.GetValidMoves(blackKing); List <Move> validKingMovesToAdjacentKings = new List <Move>(); foreach (Move validMove in validKingMoves) { PositionDistance distance = new PositionDistance(whiteKing, validMove.NewPosition); if (distance.DistanceX <= 1 && distance.DistanceY <= 1) { validKingMovesToAdjacentKings.Add(validMove); } } if (validKingMovesToAdjacentKings.Count > 0) { chosen = validKingMovesToAdjacentKings[rnd.Next(0, validKingMovesToAdjacentKings.Count)]; } else { chosen = validKingMoves[rnd.Next(0, validKingMoves.Count)]; } } else // (Game is AntichessGame) { ReadOnlyCollection <Move> validMovesBlack = Game.GetValidMoves(Player.Black); foreach (Move validMove in validMovesBlack) { AntichessGame copy = new AntichessGame(Game.GetFen()); copy.ApplyMove(validMove, true); ReadOnlyCollection <Move> validMovesWhite = copy.GetValidMoves(Player.White); if (validMovesWhite.Any(x => copy.GetPieceAt(x.NewPosition) != null)) { chosen = validMove; break; } if (chosen == null) { bool thisOne = true; foreach (Move vmWhite in validMovesWhite) { AntichessGame copy2 = new AntichessGame(copy.GetFen()); copy2.ApplyMove(vmWhite, true); ReadOnlyCollection <Move> validMovesBlackStep2 = copy2.GetValidMoves(Player.Black); if (validMovesBlackStep2.Any(x => copy2.GetPieceAt(x.NewPosition) != null)) { thisOne = false; } } if (thisOne) { chosen = validMove; } } } if (chosen == null) { chosen = validMovesBlack[rnd.Next(0, validMovesBlack.Count)]; } } Game.ApplyMove(chosen, true); response.CheckAfterAutoMove = Game.IsInCheck(Game.WhoseTurn) ? Game.WhoseTurn.ToString().ToLowerInvariant() : null; response.WinAfterAutoMove = Game.IsWinner(Game.WhoseTurn); response.FenAfterPlay = Game.GetFen(); response.Moves = Game.GetValidMoves(Game.WhoseTurn); response.LastMove = new string[2] { chosen.OriginalPosition.ToString().ToLowerInvariant(), chosen.NewPosition.ToString().ToLowerInvariant() }; if (Game.DrawCanBeClaimed) { response.DrawAfterAutoMove = true; } else { response.DrawAfterAutoMove = false; } return(response); }