예제 #1
0
 /// <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);
     }
 }
예제 #2
0
        /// <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();
        }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
 /// <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);
 }
예제 #7
0
 /// <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);
         }
     }
 }
예제 #8
0
        /// <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);
            }
        }
예제 #9
0
 /// <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());
         }
     }
 }
예제 #10
0
        /// <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();
                }
            }
        }
예제 #11
0
        /// <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);
            }
        }
예제 #12
0
        /// <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());
        }
예제 #13
0
 /// <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);
 }
예제 #14
0
 /// <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);
 }
예제 #15
0
        /// <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();
        }