/// <summary> /// Handles the next button click. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> private void NextClick(Object sender, EventArgs e) { Int32 move = _pv[_pvIndex++]; _position.Make(move); UpdateGuiState(); VisualPosition.Make(move); }
/// <summary> /// Handles a mouse up event in the main window. The selected piece /// in the analysis control panel is set at the mouse position on the /// board. This is an unusual thing to do, so this method has to /// handle the nuances of position state itself. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> public void WindowMouseUpHandler(MouseEventArgs e) { if (_isSearching) { return; } Int32 square = VisualPosition.SquareAt(e.Location); if (_selectedPiece == ArrowCode) { if (_selectedSquare == Position.InvalidSquare) { if (_position.Square[square] != Piece.Empty) { _selectedSquare = square; } } else if (_selectedSquare == square) { _selectedSquare = Position.InvalidSquare; } else { Int32 initialSquare = _selectedSquare; SetPieceAt(_position.Square[initialSquare], square); SetPieceAt(Piece.Empty, initialSquare); _selectedSquare = Position.InvalidSquare; UpdatePosition(_position); VisualPosition.Make(TMove.Create(_position, initialSquare, square)); } } else { SetPieceAt(_selectedPiece, square); UpdatePosition(_position); VisualPosition.Set(_position); } }
/// <summary> /// Starts play between the two players on the current position for the game. /// This method is non-blocking and does not modify the given position. /// </summary> /// <param name="p">The position to start playing from.</param> private void Play(Position p) { Position position = p.DeepClone(); VisualPosition.Set(position); _state = GameState.Ingame; _waitForStop.Reset(); new Thread(new ThreadStart(() => { while (true) { IPlayer player = (position.SideToMove == Colour.White) ? White : Black; List <Int32> legalMoves = position.LegalMoves(); // Adjudicate checkmate and stalemate. if (legalMoves.Count == 0) { if (position.InCheck(position.SideToMove)) { _message = "Checkmate. " + Stringify.Colour(1 - position.SideToMove) + " wins!"; _state = player.Equals(White) ? GameState.BlackWon : GameState.WhiteWon; } else { _message = "Stalemate. It's a draw!"; _state = GameState.Draw; } } // Adjudicate draw. if (position.InsufficientMaterial()) { _message = "Draw by insufficient material!"; _state = GameState.Draw; } if (player is IEngine && player.AcceptsDraw) { if (position.FiftyMovesClock >= 100) { _message = "Draw by fifty-move rule!"; _state = GameState.Draw; } if (position.HasRepeated(3)) { _message = "Draw by threefold repetition!"; _state = GameState.Draw; } } // Consider game end. if (_state != GameState.Ingame) { _waitForStop.Set(); return; } // Get move from player. Position copy = position.DeepClone(); Int32 move = player.GetMove(copy); if (!position.Equals(copy)) { Terminal.WriteLine("Board modified!"); } // Consider game stop. if (_state != GameState.Ingame) { _waitForStop.Set(); return; } // Make the move. position.Make(move); VisualPosition.Make(move); _moves.Add(move); _types.Add(player.GetType()); } })) { IsBackground = true }.Start(); }