private void Chessboard_MouseUp(object sender, MouseEventArgs e) { Cursor = Cursors.Default; if (DragDropOperation.DraggedPiece != null && DragDropOperation.DraggedPiece.Kind != ChessPieceKind.None) { if (e.X > DigitAreaWidth && e.X < this.Width && e.Y < Height - LetterAreaHeight && e.Y > 0) { // Drops a piece on the board var destinationSquare = (BoardDirection == BoardDirection.BlackOnTop ? new ChessSquare((ChessFile)((e.X - DigitAreaWidth) / SquareWidth), (ChessRank)(7 - (e.Y / SquareHeight))) : new ChessSquare((ChessFile)(7 - (e.X - DigitAreaWidth) / SquareWidth), (ChessRank)(e.Y / SquareHeight))); var moveValidationResult = ChessEngine.GetMoveValidity(DragDropOperation.Origin, destinationSquare); if (moveValidationResult.IsValid) { var promotionCancelled = false; if (moveValidationResult.MoveKind.HasFlag(ChessMoveType.Promotion)) { var pieceChooser = new FrmPromotion(ChessEngine.Turn); promotionCancelled = pieceChooser.ShowDialog() != DialogResult.OK; moveValidationResult.PromotedTo = pieceChooser.ChoosePiece; } if (!promotionCancelled) { moveValidationResult.ToSAN = ChessEngine.MoveToSAN(moveValidationResult); // Update the SAN after promotion MovePiece(moveValidationResult); OnPieceMoved?.Invoke(this, moveValidationResult); if (ChessEngine.IsCheckmate) { OnCheckmate?.Invoke(this, new EventArgs()); } else if (ChessEngine.IsCheck) { OnCheck?.Invoke(this, new EventArgs()); } else if (ChessEngine.IsDraw) { OnDraw?.Invoke(this, new EventArgs()); } } else { Invalidate(); } } else { Invalidate(); } } else { // Drops a piece outside of the board ChessEngine.RemovePieceAt(DragDropOperation.Origin); Invalidate(); OnPieceRemoved?.Invoke(this, DragDropOperation.Origin, DragDropOperation.DraggedPiece, e.Location); } } DragDropOperation = new DragOperation(null, null); OnSquareUnselected?.Invoke(this, new EventArgs()); }
/// <summary> /// Checks whether a move is valid and give the type of move (normal, capture, promotion). /// In case the move is a promotion, set the <see cref="ChessMove.PromotedTo"/> property accordingly before to pass the return object to the <see cref="MovePiece(ChessMove)"/> method. /// </summary> /// <param name="from">Square the piece move from.</param> /// <param name="to">Square the piece move to.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="from"/> or <paramref name="to"/> are null.</exception> public ChessMove CheckMoveValidity(ChessSquare from, ChessSquare to) { return(ChessEngine.GetMoveValidity(from, to)); }