/// <summary> /// Draws the player's graphical elements. /// </summary> /// <param name="g">The drawing surface.</param> public void Draw(Graphics g) { if (_isMoving && _initialSquare != Position.InvalidSquare) { VisualPosition.DrawSquare(g, SelectionBrush, _initialSquare); } }
/// <summary> /// Constructs an AnalysisBox. /// </summary> public AnalysisBox() { InitializeComponent(); // Initialize event handlers. MouseUp += MouseUpHandler; Paint += DrawHandler; // Close the application when the window is closed. FormClosed += (sender, e) => { Application.Exit(); }; BackColor = VisualPosition.LightColor; StartingPositionKey = _position.ZobristKey; VisualPosition.Set(_position); Restrictions.PrincipalVariations = 16; // Start draw thread. new Thread(new ThreadStart(() => { while (true) { Invalidate(); Thread.Sleep(DrawInterval); } })) { IsBackground = true }.Start(); }
/// <summary> /// Draws the Window. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The paint event.</param> private void DrawHandler(Object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighSpeed; g.PixelOffsetMode = PixelOffsetMode.HighSpeed; g.CompositingQuality = CompositingQuality.HighSpeed; // Translate down so the chessboard can be draw from (0, 0). g.TranslateTransform(0, MenuHeight); if (Game != null) { Game.Draw(g); } else if (AnalysisBox != null) { AnalysisBox.DrawWindow(g); } else { VisualPosition.DrawDarkSquares(g); VisualPosition.DrawPieces(g); } }
/// <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 the previous button click. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> private void PreviousClick(object sender, EventArgs e) { Int32 move = _pv[--_pvIndex]; _position.Unmake(move); UpdateGuiState(); VisualPosition.Unmake(move); }
/// <summary> /// Draw the main window. /// </summary> /// <param name="g">The drawing surface.</param> public void DrawWindow(Graphics g) { VisualPosition.DrawDarkSquares(g); if (_selectedSquare != Position.InvalidSquare) { VisualPosition.DrawSquare(g, WindowSelectionBrush, _selectedSquare); } VisualPosition.DrawPieces(g); }
/// <summary> /// Handles changes to the FEN text box. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> private void FenTextBoxChanged(Object sender, EventArgs e) { if (fenTextBox.Focused) { Position position = Position.Create(fenTextBox.Text); if (position != null) { _position = position; UpdateGuiStateWithoutFenTextBox(); VisualPosition.Set(_position); } } }
/// <summary> /// Draws the position and animations associated with the game. /// </summary> /// <param name="g">The drawing surface.</param> public void Draw(Graphics g) { VisualPosition.DrawDarkSquares(g); White.Draw(g); Black.Draw(g); VisualPosition.DrawPieces(g); if (_state != GameState.Ingame && _state != GameState.Stopped) { g.FillRectangle(OverlayBrush, 0, 0, VisualPosition.Width, VisualPosition.Width); g.DrawString(_message, MessageFont, MessageBrush, 20, 20); } }
/// <summary> /// Draws the player's graphical elements. /// </summary> /// <param name="g">The drawing surface.</param> public void Draw(Graphics g) { if (!_abortSearch) { List <Int32> pv = _pv; for (Int32 i = 0; i < pv.Count; i++) { Pen pen = (i % 2 == 0) ? ArrowPen : EnemyArrowPen; Brush brush = (i % 2 == 0) ? LabelBrush : EnemyLabelBrush; VisualPosition.DrawArrow(g, pen, pv[i], brush, (i + 1).ToString()); } } }
/// <summary> /// Handles a mouse up event. /// </summary> /// <param name="e">The mouse event.</param> public void MouseUpHandler(MouseEventArgs e) { if (_isMoving) { Int32 square = VisualPosition.SquareAt(e.Location); Int32 piece = _currentPosition.Square[square]; if (piece != Piece.Empty && (piece & Colour.Mask) == _currentPosition.SideToMove) { _initialSquare = (_initialSquare == square) ? Position.InvalidSquare : square; } else { _finalSquare = square; _waitForMove.Set(); } } }
/// <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> /// Begins the test with the given positions. /// </summary> /// <param name="epd">A list of positions in EPD format.</param> public static void Run(List <String> epd) { // Perform testing on a background thread. new Thread(new ThreadStart(() => { IEngine engine = new Zero(); Restrictions.Output = OutputType.None; Int32 totalPositions = 0; Int32 totalSolved = 0; Int64 totalNodes = 0; Double totalTime = 0; Terminal.WriteLine(ResultFormat, "Position", "Result", "Time", "Nodes"); Terminal.WriteLine("-----------------------------------------------------------------------"); foreach (String line in epd) { List <String> terms = new List <String>(line.Replace(";", " ;").Split(' ')); // Strip everything to get the FEN. Int32 bmIndex = line.IndexOf("bm "); bmIndex = bmIndex < 0 ? Int32.MaxValue : bmIndex; Int32 amIndex = line.IndexOf("am "); amIndex = amIndex < 0 ? Int32.MaxValue : amIndex; String fen = line.Remove(Math.Min(bmIndex, amIndex)); // Get the best moves. List <String> solutions = new List <String>(); for (Int32 i = terms.IndexOf("bm") + 1; i >= 0 && i < terms.Count && terms[i] != ";"; i++) { solutions.Add(terms[i]); } // Get the ID of the position. Int32 idIndex = line.IndexOf("id ") + 3; String id = line.Substring(idIndex, line.IndexOf(';', idIndex) - idIndex).Replace(@"\", ""); if (id.Length > IDWidthLimit) { id = id.Remove(IDWidthLimit) + ".."; } // Set the position and invoke a search on it. Position position = new Position(fen); VisualPosition.Set(position); engine.Reset(); Stopwatch stopwatch = Stopwatch.StartNew(); Int32 move = engine.GetMove(position); stopwatch.Stop(); Double elapsed = stopwatch.Elapsed.TotalMilliseconds; totalPositions++; totalTime += elapsed; totalNodes += engine.Nodes; // Determine whether the engine found a solution. String result = "fail"; if (solutions.Contains(Stringify.MoveAlgebraically(position, move))) { result = "pass"; totalSolved++; } // Print the result for the search on the position. Terminal.WriteLine(ResultFormat, id, result, String.Format("{0:0} ms", elapsed), engine.Nodes); } // Print final results after all positions have been searched. Terminal.WriteLine("-----------------------------------------------------------------------"); Terminal.WriteLine("Result {0} / {1}", totalSolved, totalPositions); Terminal.WriteLine("Time {0:0} ms", totalTime); Terminal.WriteLine("Average nodes {0:0}", (Double)totalNodes / totalPositions); })) { IsBackground = true }.Start(); // Open the GUI window to draw positions. Application.Run(new Window()); }
/// <summary> /// Handles the Clear Board button click. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> private void ClearBoardClick(Object sender, EventArgs e) { UpdatePosition(Position.Create("/ w")); VisualPosition.Set(_position); }
/// <summary> /// Handles the Reset Board button click. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The mouse event.</param> private void ResetBoardClick(Object sender, EventArgs e) { UpdatePosition(Position.Create(Position.StartingFEN)); 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(); }