コード例 #1
0
        private void Update(MoveViewer move, GameState gameState)
        {
            this.currentGameState = gameState ?? throw new ArgumentNullException(nameof(gameState));

            this.isThinking = false;

            IllegalMoveLabel.Visibility = Visibility.Collapsed;
            ThinkingLabel.Visibility    = Visibility.Collapsed;
            DrawLabel.Visibility        = Visibility.Collapsed;
            CheckmateLabel.Visibility   = Visibility.Collapsed;

            BoardCanvas.Children.Clear();

            var board = this.currentGameState;

            this.AddPieces(Colour.White, PieceType.Pawn, board.WhitePawns, GridSizeInPixels);
            this.AddPieces(Colour.White, PieceType.Rook, board.WhiteRooks, GridSizeInPixels);
            this.AddPieces(Colour.White, PieceType.Knight, board.WhiteKnights, GridSizeInPixels);
            this.AddPieces(Colour.White, PieceType.Bishop, board.WhiteBishops, GridSizeInPixels);
            this.AddPieces(Colour.White, PieceType.Queen, board.WhiteQueens, GridSizeInPixels);
            this.AddPieces(Colour.White, PieceType.King, board.WhiteKing, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.Pawn, board.BlackPawns, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.Rook, board.BlackRooks, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.Knight, board.BlackKnights, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.Bishop, board.BlackBishops, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.Queen, board.BlackQueens, GridSizeInPixels);
            this.AddPieces(Colour.Black, PieceType.King, board.BlackKing, GridSizeInPixels);
        }
コード例 #2
0
        public List <MovePerft> Go(Board board, Colour colour, ushort depth)
        {
            var depthMoves = new List <uint> [64];

            for (var i = 0; i <= depth; i++)
            {
                depthMoves[i] = new List <uint>(256);
            }

            var nodeMoves = depthMoves[depth];

            MoveGenerator.Generate(board, colour, nodeMoves);

            var count = 0;

            var movePerfts = new List <MovePerft>(64);

            foreach (var move in nodeMoves)
            {
                var moveView = new MoveViewer(move);

                board.MakeMove(move);

                var nodes = InnerPerft(board, colour.Opposite(), (ushort)(depth - 1), depthMoves);

                count += nodes;

                movePerfts.Add(new MovePerft(moveView, nodes));

                board.UnMakeMove(move);
            }

            return(movePerfts);
        }
コード例 #3
0
        private int InnerPerft(Board board, Colour colour, ushort depth, List <uint>[] depthMoves)
        {
            if (depth == 0)
            {
                return(1);
            }

            var nodeMoves = depthMoves[depth];

            // Must wipe any existing moves each time we enter a depth
            nodeMoves.Clear();

            var count = 0;

            foreach (var move in MoveGenerator.GenerateStream(depth, board, colour))
            {
                var moveView = new MoveViewer(move);

                board.MakeMove(move);

                var nodes = InnerPerft(board, colour.Opposite(), (ushort)(depth - 1), depthMoves);

                count += nodes;

                board.UnMakeMove(move);
            }

            return(count);
        }
コード例 #4
0
        public List <MovePerft> Go(BitBoard board, Colour colour, int depth)
        {
            var moves = new List <uint>(256);

            MoveGenerator.Generate(board, colour, moves);

            var count = 0;

            var movesView = moves.Select(x => new MoveViewer(x));

            var movePerfts = new List <MovePerft>();

            foreach (var move in moves)
            {
                var moveView = new MoveViewer(move);

                board.MakeMove(move);

                var checkers = GetCheckers(board, colour);

                var nodes = InnerPerft(board, colour.Opposite(), depth - 1);

                count += nodes;

                movePerfts.Add(new MovePerft(moveView, nodes));

                board.UnMakeMove(move);
            }

            return(movePerfts);
        }
コード例 #5
0
ファイル: Game.cs プロジェクト: gregstanley/ChessSharp
        private void ApplyMove(Board board, Colour colour, MoveViewer move)
        {
            board.MakeMove(move.Value);

            Ply++;

            if (move.PieceType == PieceType.Pawn || move.CapturePieceType != PieceType.None)
            {
                HalfMoveClock = 0;
            }
            else
            {
                ++HalfMoveClock;
            }

            var gameState = GetGameState();

            var currentState = board.CurrentState;

            var historyItem = new GameHistoryNode(currentState, gameState);

            history.Push(historyItem);

            if (historyItem.IsIrreversible)
            {
                drawBuffer.Clear();
            }
            else
            {
                drawBuffer.Add(historyItem);
            }

            var isDrawn = IsDrawn(HalfMoveClock, drawBuffer);

            if (isDrawn)
            {
                Draw?.Invoke(this, new MoveAppliedEventArgs(move, gameState, Evaluate()));

                return;
            }

            var moves = new List <uint>();

            moveGenerator.Generate(board, colour.Opposite(), moves);

            AvailableMoves = moves.Select(x => new MoveViewer(x));

            if (!AvailableMoves.Any())
            {
                Checkmate?.Invoke(this, new MoveAppliedEventArgs(move, gameState, Evaluate()));

                return;
            }

            MoveApplied?.Invoke(this, new MoveAppliedEventArgs(move, gameState, Evaluate()));
        }
コード例 #6
0
ファイル: Game.cs プロジェクト: gregstanley/ChessSharp
        public MoveViewer TryMove(int fromSquareIndex, int toSquareIndex, PieceType promotionType = PieceType.None)
        {
            MoveViewer move = null;

            // Second entry into function where the promotion type has now been defined
            if (promotionType != PieceType.None)
            {
                move = TryFindMove(fromSquareIndex, toSquareIndex, promotionType);

                if (move.Value == 0)
                {
                    InvalidMove?.Invoke(this, new InvalidMoveEventArgs(fromSquareIndex, toSquareIndex));

                    return(new MoveViewer(0));
                }

                ApplyMove(board, HumanColour, move);

                return(move);
            }

            var isPawnPromotion = IsMovePromotion(fromSquareIndex, toSquareIndex);

            if (isPawnPromotion)
            {
                // If it is then we have to stop and get the desired promotion type before continuing
                PromotionTypeRequired?.Invoke(this, new PromotionTypeRequiredEventArgs(fromSquareIndex, toSquareIndex));

                return(new MoveViewer(0));
            }

            move = TryFindMove(fromSquareIndex, toSquareIndex);

            if (move.Value == 0)
            {
                InvalidMove?.Invoke(this, new InvalidMoveEventArgs(fromSquareIndex, toSquareIndex));

                return(new MoveViewer(0));
            }

            ApplyMove(board, HumanColour, move);

            return(move);
        }
コード例 #7
0
        private void InnerPerft(BitBoard board, Colour colour, int depth, List <uint>[] moves, IDictionary <int, PerftMetrics> metrics)
        {
            if (depth == 0)
            {
                return;
            }

            //var moves = new List<uint>(256);
            var nodeMoves    = moves[depth];
            var depthMetrics = metrics[depth];

            // Must wipe any existing moves each time we enter a depth
            nodeMoves.Clear();

            MoveGenerator.Generate(board, colour, nodeMoves);

            var movesView = nodeMoves.Select(x => new MoveViewer(x));

            var captures = nodeMoves.Where(x => x.GetCapturePieceType() != PieceType.None);

            depthMetrics.Legal             += nodeMoves.Count();
            depthMetrics.Captures          += nodeMoves.Where(x => x.GetCapturePieceType() != PieceType.None).Count();
            depthMetrics.EnPassantCaptures += nodeMoves.Where(x => x.GetMoveType() == MoveType.EnPassant).Count();
            depthMetrics.Castles           += nodeMoves.Where(x => x.GetMoveType() == MoveType.CastleKing).Count();
            depthMetrics.Castles           += nodeMoves.Where(x => x.GetMoveType() == MoveType.CastleQueen).Count();

            foreach (var move in nodeMoves)
            {
                var moveView = new MoveViewer(move);

                if (!depthMetrics.Moves.Where(x => x.Value == move).Any())
                {
                    depthMetrics.Moves.Add(moveView);
                }

                board.MakeMove(move);

                var checkers = GetCheckers(board, colour);

                InnerPerft(board, colour.Opposite(), depth - 1, moves, metrics);

                board.UnMakeMove(move);
            }
        }
コード例 #8
0
        public void Go(BitBoard board, Colour colour, int depth, IDictionary <int, PerftMetrics> metrics)
        {
            //var moves = new List<uint>(256);
            var moves = new List <uint> [256];

            for (var i = 0; i <= depth; i++)
            {
                moves[i]   = new List <uint>(256);
                metrics[i] = new PerftMetrics();
            }

            var nodeMoves    = moves[depth];
            var depthMetrics = metrics[depth];

            MoveGenerator.Generate(board, colour, moves[depth]);

            var movesView = nodeMoves.Select(x => new MoveViewer(x));

            depthMetrics.Legal             += nodeMoves.Count();
            depthMetrics.Captures          += nodeMoves.Where(x => x.GetCapturePieceType() != PieceType.None).Count();
            depthMetrics.EnPassantCaptures += nodeMoves.Where(x => x.GetMoveType() == MoveType.EnPassant).Count();
            depthMetrics.Castles           += nodeMoves.Where(x => x.GetMoveType() == MoveType.CastleKing).Count();
            depthMetrics.Castles           += nodeMoves.Where(x => x.GetMoveType() == MoveType.CastleQueen).Count();

            foreach (var move in nodeMoves)
            {
                var moveView = new MoveViewer(move);

                if (!depthMetrics.Moves.Where(x => x.Value == move).Any())
                {
                    depthMetrics.Moves.Add(moveView);
                }

                board.MakeMove(move);

                var checkers = GetCheckers(board, colour);

                InnerPerft(board, colour.Opposite(), depth - 1, moves, metrics);

                board.UnMakeMove(move);
            }
        }
コード例 #9
0
        private int InnerPerft(BitBoard board, Colour colour, int depth)
        {
            if (depth == 0)
            {
                return(1);
            }

            var moves = new List <uint>(256);

            MoveGenerator.Generate(board, colour, moves);

            var count = 0;

            var movesView = moves.Select(x => new MoveViewer(x));
            var captures  = moves.Where(x => x.GetCapturePieceType() != PieceType.None);

            var movePerfts = new List <MovePerft>();

            foreach (var move in moves)
            {
                var moveView = new MoveViewer(move);

                board.MakeMove(move);

                var checkers = GetCheckers(board, colour);

                var nodes = InnerPerft(board, colour.Opposite(), depth - 1);

                count += nodes;

                movePerfts.Add(new MovePerft(moveView, nodes));

                board.UnMakeMove(move);
            }

            return(count);
        }
コード例 #10
0
 public MoveEvaluation(MoveViewer move, double score)
 {
     Move  = move;
     Score = score;
 }
コード例 #11
0
 public MoveAppliedEventArgs(MoveViewer move, GameState gameState, int evaluation)
 {
     this.Move       = move;
     this.GameState  = gameState;
     this.Evaluation = evaluation;
 }
コード例 #12
0
ファイル: MovePerft.cs プロジェクト: gregstanley/ChessSharp
 public MovePerft(MoveViewer move, int nodes)
 {
     Move  = move;
     Nodes = nodes;
 }
コード例 #13
0
 /// <summary>
 /// Called when a move is selected from the MoveViewer
 /// </summary>
 /// <param name="sender">   Sender object</param>
 /// <param name="e">        Event handler</param>
 void m_moveViewer_NewMoveSelected(object sender, MoveViewer.NewMoveSelectedEventArg e) {
     ChessBoard.MoveResultE  eResult;
     bool                    bSucceed;
     
     if (PlayingMode == PlayingModeE.PlayerAgainstPlayer) {
         eResult = m_chessCtl.SelectMove(e.NewIndex, out bSucceed);
         DisplayMessage(eResult, MessageModeE.Verbose);
         e.Cancel = !bSucceed;
     } else {
         e.Cancel = true;
     }
 }
コード例 #14
0
ファイル: InfoNewPv.cs プロジェクト: gregstanley/ChessSharp
        public string GetBestMoveString()
        {
            var move = new MoveViewer(this.CurrentMove);

            return($"Move: {move.GetNotation()} Evaluation: {this.Score}");
        }
コード例 #15
0
        private void Game_MoveApplied(object sender, MoveAppliedEventArgs args)
        {
            FullTurnNumberLabel.Content = args.GameState.FullTurn;
            HalfTurnCountLabel.Content  = args.GameState.HalfMoveClock;

            var score = Math.Round(args.Evaluation * 0.01, 2);

            EvaluationLabel.Content = score;

            WhiteCastleKingSide.Visibility = args.GameState.WhiteCanCastleKingSide
                ? Visibility.Visible
                : Visibility.Collapsed;

            WhiteCastleQueenSide.Visibility = args.GameState.WhiteCanCastleQueenSide
                ? Visibility.Visible
                : Visibility.Collapsed;

            BlackCastleKingSide.Visibility = args.GameState.BlackCanCastleKingSide
                ? Visibility.Visible
                : Visibility.Collapsed;

            BlackCastleQueenSide.Visibility = args.GameState.BlackCanCastleQueenSide
                ? Visibility.Visible
                : Visibility.Collapsed;

            var history = Game.History
                          .Reverse()
                          .Skip(1)
                          .Select(x => x);

            var sb = new StringBuilder();

            var count = 0;

            MovesListBox.Items.Clear();

            TurnItemUserControl item = null;

            foreach (var snapshot in history)
            {
                var notation = new MoveViewer(snapshot.Move).GetNotation();

                if (count % 2 == 0)
                {
                    var turnNumber = (count / 2) + 1;

                    item = new TurnItemUserControl();

                    item.BlackMoveButton.Visibility = Visibility.Collapsed;

                    item.TurnNumberLabel.Content = turnNumber;

                    sb.Append($"{turnNumber}.");

                    item.WhiteMoveButton.Content = notation;

                    MovesListBox.Items.Add(item);
                }
                else
                {
                    item.BlackMoveButton.Visibility = Visibility.Visible;

                    item.BlackMoveButton.Content = notation;
                }

                sb.Append($" {notation}");

                if (count % 2 == 1)
                {
                    sb.AppendLine();
                }

                ++count;
            }

            MovesListBox.SelectedIndex = MovesListBox.Items.Count - 1;
            MovesListBox.ScrollIntoView(MovesListBox.SelectedItem);
        }
コード例 #16
0
        public SearchResults Go(Board board, Colour colour, int maxDepth)
        {
            stopWatch.Restart();

            PositionCount = 0;

            transpositionTable.NextIteration();

            var transpositionKey = board.Key;

            var nodeMoves = new List <uint>(256);

            moveGenerator.Generate(board, colour, nodeMoves);

            var moveEvaluations = new List <MoveEvaluation>(128);

            // http://mediocrechess.blogspot.com/2006/12/programming-extracting-principal.html
            var principalVariations = new uint[maxDepth][];

            for (var i = 0; i < maxDepth; ++i)
            {
                principalVariations[i] = new uint[i + 1];
            }

            if (!nodeMoves.Any())
            {
                return(new SearchResults(PositionCount, new List <long>(), moveEvaluations, principalVariations, transpositionTable));
            }

            var existingTransposition = transpositionTable.Find(transpositionKey);

            if (existingTransposition.Key != 0)
            {
                if (existingTransposition.BestMove != 0)
                {
                    if (nodeMoves.First() != existingTransposition.BestMove)
                    {
                        nodeMoves.Remove(existingTransposition.BestMove);
                        nodeMoves.Insert(0, existingTransposition.BestMove);
                    }
                }
            }

            var currentMaxDepth = 1;

            var lap = stopWatch.ElapsedMilliseconds;

            var iterationLaps = new List <long>();

            Info info;

            while (currentMaxDepth <= maxDepth)
            {
                var masterPrincipalVariation = principalVariations[currentMaxDepth - 1];

                var principalVariation = new uint[64];

                moveEvaluations.Clear();

                var bestScore = int.MinValue;
                var bestMove  = 0u;

                foreach (var move in nodeMoves)
                {
                    var nextDepth = (byte)(currentMaxDepth - 1);

                    var moveView = new MoveViewer(move);

                    board.MakeMove(move);

                    var evaluatedScore = -PrincipalVariationSearch(board, colour.Opposite(), nextDepth, 1, int.MinValue, int.MaxValue, principalVariation);

                    board.UnMakeMove(move);

                    if (evaluatedScore > bestScore)
                    {
                        bestMove  = move;
                        bestScore = evaluatedScore;

                        UpdatePrincipalVariation(principalVariation, masterPrincipalVariation, 0, move);

                        info = new InfoNewPv(PositionCount, stopWatch.ElapsedMilliseconds, currentMaxDepth, bestMove, bestScore, transpositionTable);

                        Info?.Invoke(this, new InfoEventArgs(info));
                    }

                    moveEvaluations.Add(new MoveEvaluation(moveView, evaluatedScore));
                }

                nodeMoves = moveEvaluations
                            .OrderByDescending(x => x.Score)
                            .Select(x => x.Move.Value)
                            .ToList();

                transpositionTable.Set(transpositionKey, (byte)currentMaxDepth, colour, bestScore, bestMove);

                var iterationLength = stopWatch.ElapsedMilliseconds - lap;

                lap = stopWatch.ElapsedMilliseconds;

                iterationLaps.Add(iterationLength);

                info = new InfoDepthComplete(PositionCount, stopWatch.ElapsedMilliseconds, currentMaxDepth, masterPrincipalVariation, transpositionTable);

                Info?.Invoke(this, new InfoEventArgs(info));

                ++currentMaxDepth;
            }

            stopWatch.Reset();

            return(new SearchResults(PositionCount, iterationLaps, moveEvaluations, principalVariations, transpositionTable));
        }