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); }
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); }
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); }
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); }
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())); }
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); }
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); } }
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); } }
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); }
public MoveEvaluation(MoveViewer move, double score) { Move = move; Score = score; }
public MoveAppliedEventArgs(MoveViewer move, GameState gameState, int evaluation) { this.Move = move; this.GameState = gameState; this.Evaluation = evaluation; }
public MovePerft(MoveViewer move, int nodes) { Move = move; Nodes = nodes; }
/// <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; } }
public string GetBestMoveString() { var move = new MoveViewer(this.CurrentMove); return($"Move: {move.GetNotation()} Evaluation: {this.Score}"); }
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); }
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)); }