コード例 #1
0
ファイル: King.cs プロジェクト: jasgrg/ChessApi
        public bool IsUnderAttack(Board board)
        {
            var underAttack = IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(0, 1))), PieceType.Rook, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(1, 0))), PieceType.Rook, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(0, -1))), PieceType.Rook, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(-1, 0))), PieceType.Rook, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(1, 1))), PieceType.Bishop, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(-1, -1))), PieceType.Bishop, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(-1, 1))), PieceType.Bishop, PieceType.Queen);
            underAttack = underAttack || IsResultValid(TryAttackAlongSlope(board, new Move(Location, new Coordinate(1, -1))), PieceType.Bishop, PieceType.Queen);

            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 2, Location.Y - 1))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 2, Location.Y + 1))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 2, Location.Y - 1))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 2, Location.Y + 1))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 1, Location.Y + 2))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 1, Location.Y + 2))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 1, Location.Y - 2))), PieceType.Knight);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 1, Location.Y - 2))), PieceType.Knight);

            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 1, Location.Y + Direction))), PieceType.King, PieceType.Pawn);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X, Location.Y + Direction))), PieceType.King);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 1, Location.Y + Direction))), PieceType.King, PieceType.Pawn);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 1, Location.Y))), PieceType.King);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 1, Location.Y))), PieceType.King);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X - 1, Location.Y - Direction))), PieceType.King);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X, Location.Y - Direction))), PieceType.King);
            underAttack = underAttack || IsResultValid(TryAttackSquare(board, new Move(Location, new Coordinate(Location.X + 1, Location.Y - Direction))), PieceType.King);

            return underAttack;
        }
コード例 #2
0
ファイル: King.cs プロジェクト: jasgrg/ChessApi
        public IEnumerable<Move> GetPossibleMoves(Board board)
        {
            var result = new List<Move>();
            short x = -1;
            short y = -1;

            for (x = -1; x <= 1; x++)
            {
                for (y = -1; y <= 1; y++)
                {
                    if (!(x == 0 && y == 0))
                    {
                        TryMoveToSquare(board, result, new Move(this.Location, new Coordinate(Location.X + x, Location.Y + y)), MoveType.CanAttack);
                    }
                }
            }

            if (!HasMoved)
            {
                // Can't move to escape check
                if (!IsUnderAttack(board))
                {
                    var oneRight = new Coordinate(Location.X + 1, Location.Y);
                    var twoRight = new Coordinate(Location.X + 2, Location.Y);
                    var rook = board.GetPiece((short)(Location.X + 3), Location.Y);

                    if(board.GetPiece(oneRight.X, oneRight.Y) == null && board.GetPiece(twoRight.X, twoRight.Y) == null &&
                        rook != null && rook.PieceType == PieceType.Rook && rook.HasMoved == false)
                    {
                        if(!board.CheckMoveForCheck(new Move(Location, oneRight)) &&
                            !board.CheckMoveForCheck(new Move(Location, twoRight)))
                        {
                            result.Add(new Move(Location, twoRight, rook.Location, oneRight));
                        }
                    }

                    var oneLeft = new Coordinate(Location.X - 1, Location.Y);
                    var twoLeft = new Coordinate(Location.X - 2, Location.Y);
                    var threeLeft = new Coordinate(Location.X - 3, Location.Y);
                    rook = board.GetPiece((short)(Location.X - 4), Location.X);
                    if (board.GetPiece(oneLeft.X, oneLeft.Y) == null && board.GetPiece(twoLeft.X, twoLeft.Y) == null && board.GetPiece(threeLeft.X, threeLeft.Y) == null
                        && rook != null && rook.PieceType == PieceType.Rook && rook.HasMoved == false)
                    {
                        if (!board.CheckMoveForCheck(new Move(Location, oneLeft)) &&
                            !board.CheckMoveForCheck(new Move(Location, twoLeft)) &&
                            !board.CheckMoveForCheck(new Move(Location, threeLeft)))
                        {
                            result.Add(new Move(Location, twoLeft, rook.Location, oneLeft));
                        }
                    }
                }
            }
            return result;
        }
コード例 #3
0
ファイル: MiniMaxService.cs プロジェクト: jasgrg/ChessApi
        private TreeNode MiniMax(Board board, Double depth, Double alpha, Double beta, Boolean maximizer)
        {
            if(depth == 0)
            {
                return GetLeafNode(board, maximizer);
            }
            var pieces = board.GetPiecesForPlayer(board.PlayerTurn);
            var bestScore = maximizer ? _minScore : _maxScore;
            var bestMove = default(Move);

            var moves = pieces.SelectMany(x => x.GetPossibleMoves(board));
            if (!moves.Any())
            {
                if (board.PlayerHasCheck(board.PlayerTurn))
                {
                    return new TreeNode(null, maximizer ? _maxScore : _minScore);
                }
            }

            foreach (var mv in moves)
            {
                var newBoard = board.Copy();
                newBoard.MakeMove(mv);
                var newNode = MiniMax(newBoard, depth - 1, alpha, beta, !maximizer);
                if (maximizer)
                {
                    if(newNode.Score > bestScore)
                    {
                        bestScore = newNode.Score;
                        bestMove = mv;
                    }
                    alpha = Math.Max(alpha, bestScore);
                    if(beta <= alpha)
                    {
                        return new TreeNode(bestMove, bestScore);
                    }
                }
                else
                {
                    if(newNode.Score < bestScore)
                    {
                        bestScore = newNode.Score;
                        bestMove = mv;
                    }
                    beta = Math.Min(beta, bestScore);
                    if(beta <= alpha)
                    {
                        return new TreeNode(bestMove, bestScore);
                    }
                }
            }
            return new TreeNode(bestMove, bestScore);
        }
コード例 #4
0
        public void GetNextMoveMustNotAlterBoard()
        {
            _board = new Board();
            _board.Initialize();

            for(int i = 0; i < 10; i++)
            {
                var origBoard = _board.Copy();
                var mv = _miniMaxService.GetNextMove(_board);
                Assert.IsTrue(_board.Equals(origBoard));
                _board.MakeMove(mv);
            }
        }
コード例 #5
0
ファイル: Rook.cs プロジェクト: jasgrg/ChessApi
 public IEnumerable<Move> GetPossibleMoves(Board board)
 {
     var result = new List<Move>();
     //straight forward
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(0, 1)));
     // straight left
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(-1, 0)));
     //straight right
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(1, 0)));
     //straigh back
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(0, -1)));
     return result;
 }
コード例 #6
0
ファイル: RandomMoveService.cs プロジェクト: jasgrg/ChessApi
        public Move GetNextMove(Board board)
        {
            var allMoves = new List<Move>();
            var pcs = board.GetPiecesForPlayer(board.PlayerTurn);
            foreach(var pc in pcs)
            {
                var moves = pc.GetPossibleMoves(board);
                allMoves.AddRange(moves);
            }

            var randomIndex = new Random().Next(allMoves.Count);
            return allMoves[randomIndex];
        }
コード例 #7
0
ファイル: Bishop.cs プロジェクト: jasgrg/ChessApi
 public IEnumerable<Move> GetPossibleMoves(Board board)
 {
     var result = new List<Move>();
     //diag forward left;
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(-1, 1)));
     //diag forward right;
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(1, 1)));
     //diag backward left;
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(-1, -1)));
     //diag backward right;
     TryMoveAlongSlope(board, result, new Move(Location, new Coordinate(1, -1)));
     return result;
 }
コード例 #8
0
        private double GetScore(List<IPiece> playerPieces, Board board)
        {
            Dictionary<short, short> pawnCoords = new Dictionary<short, short>();

            Double score = 0;
            foreach (var pc in playerPieces)
            {
                switch (pc.PieceType)
                {
                    case PieceType.Queen:
                        score += queenMaterial;
                        score += queenKingProximity * (7 - GetChebyShevDistance(pc.Location, board.GetKingPosition(board.OpposingPlayer())));
                        score += queenCenterProximity * (3 - GetChebyShevDistance(pc.Location, board.GetCenter()));
                        break;
                    case PieceType.Bishop:
                        score += bishopMaterial;
                        score += bishopDistanceToCenterWeight * (4 - GetChebyShevDistance(pc.Location, board.GetCenter()));
                        // mobility and xray mobility
                        break;
                    case PieceType.Knight:
                        score += knightMaterial;
                        score += knightDistanceToKingWeight * GetManhattanDistance(pc.Location, board.GetKingPosition(board.OpposingPlayer()));
                        score += knightDistanceToKingWeight * GetManhattanDistance(pc.Location, board.GetKingPosition(board.PlayerTurn));
                        score += knightDistanceToCenterWeight * (4 - GetChebyShevDistance(pc.Location, board.GetCenter()));
                        break;
                    case PieceType.Rook:
                        score += rookMaterial;
                        score += rookKingProximity * (14 - GetManhattanDistance(pc.Location, board.GetKingPosition(board.OpposingPlayer())));
                        //mobility and xray mobility
                        // friendly pawns.
                        break;
                    case PieceType.Pawn:
                        score += pawnMaterial;
                        score += pawnRankWeight * pc.Rank;
                        if (pawnCoords.ContainsKey(pc.Location.X))
                        {
                            pawnCoords[pc.Location.X] = Math.Min(pc.Location.Y, pawnCoords[pc.Location.X]);
                            score -= doubledPawnPenalty;
                        }
                        else
                        {
                            pawnCoords.Add(pc.Location.X, pc.Location.Y);
                        }
                        break;
                }
            }

            score += IsolatedPawns(pawnCoords);

            return score;
        }
コード例 #9
0
ファイル: Pawn.cs プロジェクト: jasgrg/ChessApi
        public IEnumerable<Move> GetPossibleMoves(Board board)
        {
            var result = new List<Move>();

            if (TryMoveToSquare(board, result, new Move(this.Location, new Coordinate(Location.X, Location.Y + Direction)), MoveType.CannotAttack).Type == MoveResultType.Move) {
                if ((Player == Player.Light && Location.Y == 6)|| (Player == Player.Dark && Location.Y == 1))
                {
                    TryMoveToSquare(board, result, new Move(this.Location, new Coordinate(Location.X, Location.Y + (2 * Direction))), MoveType.CannotAttack);
                }
            }
            TryMoveToSquare(board, result, new Move(this.Location, new Coordinate(Location.X - 1, Location.Y + Direction)), MoveType.MustAttack);
            TryMoveToSquare(board, result, new Move(this.Location, new Coordinate(Location.X + 1, Location.Y + Direction)), MoveType.MustAttack);

            return result;
        }
コード例 #10
0
ファイル: Knight.cs プロジェクト: jasgrg/ChessApi
        public IEnumerable<Move> GetPossibleMoves(Board board)
        {
            var result = new List<Move>();

            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X - 1, Location.Y + 2)), MoveType.CanAttack);
            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X + 1, Location.Y + 2)), MoveType.CanAttack);

            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X - 1, Location.Y - 2)), MoveType.CanAttack);
            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X + 1, Location.Y - 2)), MoveType.CanAttack);

            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X - 2, Location.Y + 1)), MoveType.CanAttack);
            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X - 2, Location.Y - 1)), MoveType.CanAttack);

            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X + 2, Location.Y + 1)), MoveType.CanAttack);
            TryMoveToSquare(board, result, new Move(Location, new Coordinate(Location.X + 2, Location.Y - 1)), MoveType.CanAttack);
            return result;
        }
コード例 #11
0
        public void GetNextMoveMustReturnIn15Seconds()
        {
            var totalMoves = 3d;
            _board = new Board();
            _board.Initialize();

            var stopWatch = new Stopwatch();
            stopWatch.Start();
            for (int i = 0; i < totalMoves; i++)
            {
                var mv = _miniMaxService.GetNextMove(_board);
                _board.MakeMove(mv);
            }

            stopWatch.Stop();
            var secondsPer = stopWatch.ElapsedMilliseconds / totalMoves / 1000d;
            Assert.IsTrue(secondsPer < 15);
        }
コード例 #12
0
ファイル: MiniMaxService.cs プロジェクト: jasgrg/ChessApi
        private TreeNode GetLeafNode(Board board, Boolean maximizer)
        {
            var status = board.GetBoardStatus();
            var score = 0d;

            if (status == Enums.BoardStatus.Checkmate)
            {
                score = maximizer ? _maxScore : _minScore;
            }
            else if (status == Enums.BoardStatus.Stalemate)
            {
                score = 0;
            }
            else
            {
                score = _evalService.Evaluate(board);
            }
            return new TreeNode(null, score);
        }
コード例 #13
0
        public double Evaluate(Board board)
        {
            Double score = 0;

            var playerPieces = board.GetPiecesForPlayer(board.PlayerTurn);
            var opposingPieces = board.GetPiecesForPlayer(board.OpposingPlayer());

            score = GetScore(playerPieces, board);
            score -= GetScore(opposingPieces, board);

            //score = 200 * (CountPiecesByType(playerPieces, PieceType.King) - CountPiecesByType(opposingPieces, PieceType.King));
            //score += 9 * (CountPiecesByType(playerPieces, PieceType.Queen) - CountPiecesByType(opposingPieces, PieceType.Queen));
            //score += 5 * (CountPiecesByType(playerPieces, PieceType.Rook) - CountPiecesByType(opposingPieces, PieceType.Rook));
            //score += 3 * ((CountPiecesByType(playerPieces, PieceType.Bishop) - CountPiecesByType(opposingPieces, PieceType.Bishop)) +
            //                (CountPiecesByType(playerPieces, PieceType.Knight) - CountPiecesByType(opposingPieces, PieceType.Knight)));
            //score += 1 * (CountPiecesByType(playerPieces, PieceType.Pawn) - (CountPiecesByType(opposingPieces, PieceType.Pawn)));

            //score -= .5 * ((DoubledPawns(playerPieces) - DoubledPawns(opposingPieces)) +
            //                (BlockedPawns(playerPieces) - BlockedPawns(opposingPieces)) +
            //                (IsolatedPawns(playerPieces) - IsolatedPawns(opposingPieces)));
            //score += .1 * (CountMoves(board, playerPieces) - CountMoves(board, opposingPieces));
            return score;
        }
コード例 #14
0
ファイル: KingTests.cs プロジェクト: jasgrg/ChessApi
 public void Setup()
 {
     _board = new Board(true);
     _board.SetPlayer(Player.Light);
 }
コード例 #15
0
ファイル: Board.cs プロジェクト: jasgrg/ChessApi
 public Board Copy()
 {
     var dest = new Board();
     foreach (var sq in Squares)
     {
         IPiece pc = null;
         if (sq.Piece != null)
         {
             pc = Piece.GetPiece(sq.Piece.PieceType, sq.Piece.Player, sq.Piece.Location);
             pc.HasMoved = sq.Piece.HasMoved;
         }
         dest.AddPieceToBoard(sq.Location.X, sq.Location.Y, pc);
     }
     dest.PlayerTurn = PlayerTurn;
     return dest;
 }
コード例 #16
0
ファイル: BoardController.cs プロジェクト: jasgrg/ChessApi
 public Board Get()
 {
     var board = new Board();
     board.Initialize();
     return board;
 }
コード例 #17
0
ファイル: MiniMaxService.cs プロジェクト: jasgrg/ChessApi
        public Move GetNextMove(Board board)
        {
            var newBoard = board.Copy();

            return MiniMax(board, _maxDepth, _minScore, _maxScore, true).Move;
        }
コード例 #18
0
ファイル: Board.cs プロジェクト: jasgrg/ChessApi
        public bool Equals(Board brd)
        {
            if (PlayerTurn != brd.PlayerTurn) { return false; }

            for (short y = 0; y < 8; y++)
            {
                for (short x = 0; x < 8; x++)
                {
                    var o = GetSquare(x, y);
                    var n = brd.GetSquare(x, y);

                    if (o.Piece == null && n.Piece == null)
                    {
                        continue;
                    }

                    if (o.Piece == null || n.Piece == null)
                    {
                        return false;
                    }
                    if ((o.Piece.PieceType != n.Piece.PieceType) || (o.Piece.HasMoved != n.Piece.HasMoved) ||
                        (o.Piece.Location.X != n.Piece.Location.X) || (o.Piece.Location.Y != n.Piece.Location.Y) ||
                        (o.Piece.Player != n.Piece.Player))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
コード例 #19
0
ファイル: Piece.cs プロジェクト: jasgrg/ChessApi
 protected MoveResult TryAttackSquare(Board board, Move move)
 {
     if (move.To.IsValid)
     {
         var targetPiece = board.GetPiece(move.To.X, move.To.Y);
         if(targetPiece != null)
         {
             if(targetPiece.Player != Player)
             {
                 return new MoveResult() { Type = MoveResultType.Attack, CapturedPiece = targetPiece };
             }
         }
         else
         {
             return new MoveResult() { Type = MoveResultType.Move };
         }
     }
     return new MoveResult() { Type = MoveResultType.Invalid };
 }
コード例 #20
0
ファイル: Piece.cs プロジェクト: jasgrg/ChessApi
 protected void TryMoveAlongSlope(Board board, List<Move> possibleMoves, Move slope)
 {
     var curX = slope.From.X;
     var curY = slope.From.Y;
     do
     {
         curX += slope.To.X;
         curY += slope.To.Y;
     } while (TryMoveToSquare(board, possibleMoves, new Move(slope.From, new Coordinate(curX, curY)), MoveType.CanAttack).Type == MoveResultType.Move);
 }
コード例 #21
0
ファイル: BoardTests.cs プロジェクト: jasgrg/ChessApi
 public void Setup()
 {
     _board = new Board();
 }
コード例 #22
0
ファイル: Piece.cs プロジェクト: jasgrg/ChessApi
 protected MoveResult TryMoveToSquare(Board board, List<Move> possibleMoves, Move move, MoveType moveType)
 {
     if (move.To.IsValid)
     {
         var targetPiece = board.GetPiece(move.To.X, move.To.Y);
         if (moveType != MoveType.MustAttack && targetPiece == null)
         {
             if(!board.CheckMoveForCheck(move))
             {
                 possibleMoves.Add(move);
             }
             return new MoveResult() { Type = MoveResultType.Move };
         }
         else if(moveType != MoveType.CannotAttack && targetPiece != null && targetPiece.Player != Player)
         {
             if(!board.CheckMoveForCheck(move))
             {
                 possibleMoves.Add(move);
             }
             return new MoveResult() { Type = MoveResultType.Attack, CapturedPiece = targetPiece };
         }
     }
     return new MoveResult() { Type = MoveResultType.Invalid };
 }
コード例 #23
0
ファイル: Piece.cs プロジェクト: jasgrg/ChessApi
 protected MoveResult TryAttackAlongSlope(Board board, Move slope)
 {
     var curX = slope.From.X;
     var curY = slope.From.Y;
     var result = default(MoveResult);
     do
     {
         curX += slope.To.X;
         curY += slope.To.Y;
         result = TryAttackSquare(board, new Move(slope.From, new Coordinate(curX, curY)));
     } while (result.Type == MoveResultType.Move);
     return result;
 }