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; }
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; }
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); }
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); } }
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; }
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]; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
public void Setup() { _board = new Board(true); _board.SetPlayer(Player.Light); }
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; }
public Board Get() { var board = new Board(); board.Initialize(); return board; }
public Move GetNextMove(Board board) { var newBoard = board.Copy(); return MiniMax(board, _maxDepth, _minScore, _maxScore, true).Move; }
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; }
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 }; }
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); }
public void Setup() { _board = new Board(); }
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 }; }
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; }