Exemple #1
0
        /// <summary>
        /// Check GameState
        /// </summary>
        /// <param name="player"></param>
        /// <param name="board"></param>
        /// <returns></returns>
        public GameState GetGameState(Player player, Board board)
        {
            var rule = new Rules();

            var numberplayerPieces = rule.NumberOfPlayerPieces(board, player);
            var isplayerBlocked = rule.IsPlayerBlocked(board, player);
            if (numberplayerPieces == 0 || isplayerBlocked)
            {
                return GameState.Lost;
            }
            var numberopponentPieces = rule.NumberOfPlayerPieces(board, board.GetOpponent(player));
            var isopponentBlocked = rule.IsPlayerBlocked(board, board.GetOpponent(player));
            if (numberopponentPieces == 0 || isopponentBlocked)
            {
                return GameState.Won;
            }
            else
            {
                return GameState.Undetermined;
            }
        }
        /// <summary>
        /// returns the number of ways in which soldier on coord can be captured;
        /// </summary>
        /// <param name="board"></param>
        /// <param name="coord"></param>
        /// <param name="player"></param>
        /// <returns></returns>
        public int CanBeCaptured(Board board, Coordinate coord, Player player)
        {
            int num = 0;
            Rules rule = new Rules();
            IList<Coordinate> optionalCoords = rule.OptionalMoves(board, coord, player);
            IList<Coordinate> coordsInDir = rule.GetMovesInDirection(board, coord, player);

            //collect all coords behind coord
            IList<Coordinate> coordsfrombehind = optionalCoords.Where(opCor => !coordsInDir.Contains(opCor)).ToList();
            foreach (var cid in coordsInDir)
            {
                if (board.GetPlayer(board[cid.X, cid.Y]) == board.GetOpponent(player) &&
                    rule.CoordsToCaptureAndDest(board, cid, coord, board.GetOpponent(player)).Count > 0)
                    num++;
            }

            foreach (var cfb in coordsfrombehind)
            {
                if (board.GetPlayer(board[cfb.X, cfb.Y]) == board.GetOpponent(player) && board.IsKing(coord) &&
                    rule.CoordsToCaptureAndDest(board, cfb, coord, board.GetOpponent(player)).Count > 0)
                    num++;
            }
            return num;
        }
Exemple #3
0
        /// <summary>
        /// Pc VS Pc
        /// </summary>
        /// <returns> </returns>
        public void StartGameWithPc(Board board)
        {
            int countmovesforDraw = 0;
            var rule = new Rules();
            var print = new PrintBoardState();
            int depth;
            Coordinate srcCoord = new Coordinate();
            Coordinate destCoord = new Coordinate();

            //Create the file engine who Read\write to file all moves
            FileEngine file = new FileEngine();

            //define that file will be created in the root folder under the name sync.txt
            string path = "sync.txt";

            //define colors.
            Console.WriteLine("Opponent color is white? [Yes/No]");
            Opponet:
            string opponentColor = Console.ReadLine();
            if (!(opponentColor == "Yes" || opponentColor == "yes" || opponentColor == "No" || opponentColor == "no"))
            {
                Console.WriteLine("Invalid input,please try again");
                goto Opponet;
            }
            Player oppColor = (opponentColor == "Yes" || opponentColor == "yes") ? Player.White : Player.Black;
            Player pcColor = oppColor == Player.White ? Player.Black : Player.White;

            //define who starts.
            Console.WriteLine("Opponent Starts? [Yes/No]");
            Start:
            string opponentStarts = Console.ReadLine();
            if (
                !(opponentStarts == "Yes" || opponentStarts == "yes" || opponentStarts == "No" || opponentStarts == "no"))
            {
                Console.WriteLine("Invalid input,please try again");
                goto Start;
            }
            if (opponentStarts == "Yes" || opponentStarts == "yes")
                goto OppTurn;
            goto MyTurn;

            //oppoenent tuen
            OppTurn:
            try
            {
                //open file in path with read permision and no sharing
                using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    ShowPlayerChange(oppColor);
                    Player color = Player.None;
                    bool capMove = false;
                    IList<Coordinate> oppMove = new List<Coordinate>();
                    //read moves and captures (if exists)
                    while (oppMove.Count == 0)
                    {
                        oppMove = file.ReadFromFile(stream, board, path, out color);
                    }
                    //Source
                    srcCoord = oppMove.First();
                    oppMove.RemoveAt(0);
                    //Destination
                    destCoord = oppMove[0];
                    oppMove.RemoveAt(0);
                    //Captures list
                    var capturesOppdid = oppMove;
                    //if move is not oppoent move or source piece is not opponenet color return to read file
                    if ((color != oppColor) || (board.GetPlayer(srcCoord) != oppColor))
                    {
                        goto OppTurn;
                    }

                    //Find captures
                    IDictionary<IList<Coordinate>, IList<Coordinate>> capturesAvailable = rule.FindCaptures(board,
                                                                                                            oppColor);
                    if (capturesAvailable.Count > 0)
                    {
                        var boolean = rule.MapContainsCoordsOfCaptures(capturesAvailable, srcCoord, destCoord,
                                                                       capturesOppdid);
                        if (!boolean)
                        {
                            Console.WriteLine("You must capture maximum opponent soldiers on board");
                            goto OppTurn;
                        }
                        else
                        {
                            foreach (var coordinate in capturesOppdid)
                            {
                                board[coordinate.X, coordinate.Y].Status = Piece.None;
                                board.UpdateCapturedSoldiers(coordinate, pcColor);
                                capMove = true;
                            }
                        }
                    }
                    if (capMove || rule.IsValidMove(board, srcCoord, destCoord, oppColor))
                    {
                        board.UpdateBoard(srcCoord, destCoord);
                        rule.IsBecameAKing(board, board[destCoord.X, destCoord.Y]);
                        print.DrawBoard(board);
                    }
                    else
                    {
                        Console.WriteLine("This is not a valid move, please enter again");
                        goto OppTurn;
                    }

                    //check if game has been determined
                    GameState game = GetGameState(oppColor, board);
                    if (GameState.Draw ==
                        CheckDraw(board, board[destCoord.X, destCoord.Y], capMove, ref countmovesforDraw))
                    {
                        Console.WriteLine("Draw");
                        return;
                    }
                    if (game == GameState.Lost)
                    {
                        Console.WriteLine("{0} Lost the game and {1} won", oppColor.ToString(), pcColor.ToString());
                        return;
                    }
                    if (game == GameState.Won)
                    {
                        Console.WriteLine("{0} Won", oppColor.ToString());
                        return;
                    }
                }
            }
            catch (Exception)
            {
                goto OppTurn;
            }

            //local turn
            MyTurn:
            try
            {
                using (var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    ShowPlayerChange(pcColor);
                    var alphaBeta = new Alphabeta();
                    Board temp = new Board();
                    IList<Coordinate> tempCaptures = new List<Coordinate>();
                    depth = rule.DefineDepth(board);
                    alphaBeta.AlphaBeta(board, depth, Int32.MinValue, Int32.MaxValue, pcColor, true, ref srcCoord,
                                        ref destCoord,
                                        ref temp, ref tempCaptures);
                    if ((rule.InBounds(board, srcCoord.X, srcCoord.Y)) &&
                        (rule.InBounds(board, destCoord.X, destCoord.Y)))
                    {
                        board = temp.Copy();
                        print.DrawBoard(board);
                    }

                    //write move to file
                    file.WriteToFile(stream, srcCoord, destCoord, tempCaptures, path, pcColor);

                    //check if game has been determined
                    bool pcCaptured = tempCaptures.Count > 0;
                    GameState game = GetGameState(oppColor, board);
                    if (GameState.Draw ==
                        CheckDraw(board, board[destCoord.X, destCoord.Y], pcCaptured, ref countmovesforDraw))
                    {
                        Console.WriteLine("Draw");
                        return;
                    }
                    if (game == GameState.Lost)
                    {
                        Console.WriteLine("{0} Lost the game and {1} won", oppColor.ToString(), pcColor.ToString());
                        return;
                    }
                    if (game == GameState.Won)
                    {
                        Console.WriteLine("{0} Won", oppColor.ToString());
                        return;
                    }
                }
                Thread.Sleep(5000);
                goto OppTurn;
            }
            catch (Exception)
            {
                goto MyTurn;
            }
        }
Exemple #4
0
        /// <summary>
        /// Human VS PC
        /// </summary>
        /// <param name="board"></param>
        public void StartGameWithHuman(Board board)
        {
            int countmovesforDraw = 0;
            var humanColor = Player.None;
            var pcColor = Player.None;
            bool firstTurn = true;
            var rule = new Rules();
            var print = new PrintBoardState();
            while (true)
            {
                //first turn is always the human's
                Console.WriteLine("Your turn, please enter a move in format 'from cell number' 'to cell number'");
                HumanTurn:
                bool capMove = false;
                var input = Console.ReadLine();
                IList<Coordinate> coords = ParseStrToCoords(input, board);
                //If there is no input
                if (coords == null)
                {
                    Console.WriteLine("Wrong Input, please try again");
                    goto HumanTurn;
                }

                var srcCoord = coords.First();
                var destCoord = coords.Last();
                if (firstTurn)
                {
                    humanColor = board.GetPlayer(srcCoord);
                    pcColor = board.GetOpponent(humanColor);
                    firstTurn = false;
                }
                    //if select coordinate is not your coordinate then show error message
                else if (humanColor != board.GetPlayer(srcCoord))
                {
                    Console.WriteLine(
                        "This is not your piece , please enter cell number which allocated with your piece color");
                    goto HumanTurn;
                }

                //Fins captures
                IDictionary<IList<Coordinate>, IList<Coordinate>> capturesAvailable = rule.FindCaptures(board,
                                                                                                        humanColor);
                //if there are any captures
                if (capturesAvailable.Count > 0)
                {
                    //check if they are contained in captured dictionary by looking on source and destination
                    IList<Coordinate> captures = rule.MapContainsCoords(capturesAvailable, srcCoord, destCoord);
                    //id they are not contained show error message
                    if (captures.Count == 0)
                    {
                        Console.WriteLine("You must capture maximum opponent soldiers on board");
                        goto HumanTurn;
                    }
                    else
                    {
                        //if there are captures and source and destination are corrrect, update board with move and captures
                        foreach (var coordinate in captures)
                        {
                            board[coordinate.X, coordinate.Y].Status = Piece.None;
                            board.UpdateCapturedSoldiers(coordinate, pcColor);
                            capMove = true;
                        }
                    }
                }
                //update board
                if (capMove || rule.IsValidMove(board, srcCoord, destCoord, humanColor))
                {
                    board.UpdateBoard(srcCoord, destCoord);
                    rule.IsBecameAKing(board, board[destCoord.X, destCoord.Y]);
                    print.DrawBoard(board);
                }
                else
                {
                    Console.WriteLine("This is not a valid move, please enter again");
                    goto HumanTurn;
                }

                //check if game is finish by checking if players draw,lost or won
                GameState game = GetGameState(humanColor, board);
                if (GameState.Draw == CheckDraw(board, board[destCoord.X, destCoord.Y], capMove, ref countmovesforDraw))
                {
                    Console.WriteLine("Draw");
                    break;
                }
                if (game == GameState.Lost)
                {
                    Console.WriteLine("{0} Lost the game and {1} won", humanColor.ToString(), pcColor.ToString());
                    break;
                }
                if (game == GameState.Won)
                {
                    Console.WriteLine("{0} Won", humanColor.ToString());
                    break;
                }

                //switch to opponent (PC)
                ShowPlayerChange(pcColor);
                var alphaBeta = new Alphabeta();
                Board temp = new Board();
                IList<Coordinate> tempCaptures = new List<Coordinate>();
                //Define depth
                int depth = rule.DefineDepth(board);
                //Calling alpha-beta algorithm which return the best move in addition, return source,destination coordinates and a list of captures
                alphaBeta.AlphaBeta(board, depth, Int32.MinValue, Int32.MaxValue, pcColor, true, ref srcCoord,
                                    ref destCoord, ref temp, ref tempCaptures);

                //Verify the move is in bounds, if yes update the board with it
                if ((rule.InBounds(board, srcCoord.X, srcCoord.Y)) && (rule.InBounds(board, destCoord.X, destCoord.Y)))
                {
                    board = temp.Copy();
                    print.DrawBoard(board);
                }
                // check if there were any captures. if yes check for draw
                bool pcCaptured = tempCaptures.Count > 0;
                //check if game was determined
                game = GetGameState(humanColor, board);
                if (GameState.Draw ==
                    CheckDraw(board, board[destCoord.X, destCoord.Y], pcCaptured, ref countmovesforDraw))
                {
                    Console.WriteLine("Draw");
                    break;
                }
                if (game == GameState.Lost)
                {
                    Console.WriteLine("{0} Lost the game and {1} won", humanColor.ToString(), pcColor.ToString());
                    break;
                }
                if (game == GameState.Won)
                {
                    Console.WriteLine("{0} Won", humanColor.ToString());
                    break;
                }
            }
        }
        /// <summary>
        /// alpha beta algorithm
        /// boardcoordlist- each item in this map contains a new board (representing a new state) and a list of 2 coords representing the move that brought to this new state
        /// mapBoardSrcDestCap- each item in this map contains the new board and source- dest coords (like above) and a list of captured coordinate (in case the new board is a result of a capture)
        /// </summary>
        /// <param name="board"></param>
        /// <param name="depth"></param>
        /// <param name="alpha"></param>
        /// <param name="beta"></param>
        /// <param name="player"></param>
        /// <param name="maxplayer"></param>
        /// <param name="srcCoord"></param>
        /// <param name="destCoord"></param>
        /// <param name="updateBoard"></param>
        /// <param name="captures"></param>
        /// <returns></returns>
        public int AlphaBeta(Board board, int depth, int alpha, int beta, Player player, bool maxplayer,
            ref Coordinate srcCoord, ref Coordinate destCoord, ref Board updateBoard,
            ref IList<Coordinate> captures)
        {
            var robj = new Rules();
            if (depth == 0 || rule.IsBoardLeaf(player, board)) // is node a terminal node
            {
                var obj = new HeuristicFunction();
                return obj.Evaluate(board, player); //return Heurisitic value of node
            }

            //Finds if there are any captures
            IDictionary<IList<Coordinate>, IList<Coordinate>> capturesAvailable = robj.FindCaptures(board, player);
            IDictionary<Board, IList<Coordinate>> boardCoordsList;

            //Calculating board according to current state (with or without captures)
            if (capturesAvailable.Count > 0)
            {
                boardCoordsList = robj.CreateNewBoards(board, capturesAvailable);
            }
            else
            {
                boardCoordsList = robj.CalculateNewBoardsFromCoordinates(board, player);
            }

            //values which save capture list , source, detination on the chosen move
            var minsrcCoord = new Coordinate();
            var mindestCoord = new Coordinate();
            var maxsrcCoord = new Coordinate();
            var maxdestCoord = new Coordinate();
            var maxCapturesList = new List<Coordinate>();
            var minCapturesList = new List<Coordinate>();
            var minBoard = new Board();
            var maxBoard = new Board();

            //player
            if (maxplayer)
            {
                foreach (var newState in boardCoordsList)
                {
                    Coordinate newSrcCoord = newState.Value[0];
                    Coordinate newDestCoord = newState.Value[1];
                    IList<Coordinate> capturesList = robj.MapContainsCoords(capturesAvailable, newSrcCoord, newDestCoord);
                    IList<Coordinate> tempCapList = new List<Coordinate>();
                    int res = AlphaBeta(newState.Key, depth - 1, alpha, beta, board.GetOpponent(player), !maxplayer,
                                        ref newSrcCoord, ref newDestCoord, ref updateBoard, ref tempCapList);
                    if (res > alpha)
                    {
                        alpha = res;
                        maxsrcCoord = newState.Value[0];
                        maxdestCoord = newState.Value[1];
                        maxBoard = newState.Key.Copy();
                        maxCapturesList = new List<Coordinate>(capturesList);
                    }
                    if (beta <= alpha)
                    {
                        break;
                    }
                    if (capturesList.Count > 0)
                    {
                        capturesAvailable.Remove(capturesList);
                    }
                }
                srcCoord = maxsrcCoord;
                destCoord = maxdestCoord;
                updateBoard = maxBoard.Copy();
                captures = maxCapturesList;
                return alpha;
            }

                //opponent
            else
            {
                foreach (var newState in boardCoordsList)
                {
                    Coordinate newSrcCoord = newState.Value[0];
                    Coordinate newDestCoord = newState.Value[1];
                    IList<Coordinate> capturesList = robj.MapContainsCoords(capturesAvailable, newSrcCoord, newDestCoord);
                    IList<Coordinate> tempCapList = new List<Coordinate>();
                    int res = AlphaBeta(newState.Key, depth - 1, alpha, beta, board.GetOpponent(player), !maxplayer,
                                        ref newSrcCoord, ref newDestCoord, ref updateBoard, ref tempCapList);
                    if (res < beta)

                    {
                        beta = res;
                        minsrcCoord = newState.Value[0];
                        mindestCoord = newState.Value[1];
                        minBoard = newState.Key.Copy();
                        minCapturesList = new List<Coordinate>(capturesList);
                    }
                    if (beta <= alpha)
                    {
                        break;
                    }
                    if (capturesList.Count > 0)
                    {
                        capturesAvailable.Remove(capturesList);
                    }
                }
                srcCoord = minsrcCoord;
                destCoord = mindestCoord;
                updateBoard = minBoard.Copy();
                captures = minCapturesList;
                return beta;
            }
        }
 /// <summary>
 /// Constructor which perform alphabeta algorithm and set soruce ,destinationn coordinate and return captures list if exists
 /// </summary>
 /// <param name="board"></param>
 /// <param name="player"></param>
 /// <param name="depth"></param>
 public Move(IBoardState board, Player player, int depth)
 {
     Rules rule = new Rules();
     board.Board = board.ConvertBoardStateToBoard(board);
     var alphaBeta = new Alphabeta();
     Board temp = new Board();
     var srcCoord = new Coordinate();
     var destCoord = new Coordinate();
     IList<Coordinate> tempCaptures = new List<Coordinate>();
     if (depth%2 != 0)
         depth++;
     alphaBeta.AlphaBeta(board.Board, depth, Int32.MinValue, Int32.MaxValue, player, true, ref srcCoord, ref destCoord, ref temp, ref tempCaptures);
     if ((rule.InBounds(board.Board, srcCoord.X, srcCoord.Y)) && (rule.InBounds(board.Board, destCoord.X, destCoord.Y)))
     {
         board.Board = temp.Copy();
         board.BoardCells = board.ConvertBoardToBoardState(board.Board);
         Board = board;
     }
     bool pcCaptured = tempCaptures.Count > 0;
     board.DrawGame = board.CheckDraw(board.Board, board.Board[destCoord.X, destCoord.Y], pcCaptured);
 }
        /// <summary>
        /// Returns current board state after moveType from position
        /// </summary>
        /// <param name="player"></param>
        /// <param name="moveType"></param>
        /// <param name="position"></param>
        /// <param name="needToContinueEating"></param>
        /// <param name="mustCapture"></param>
        /// <returns></returns>
        public IBoardState GetBoardState(Player player, MoveType moveType, Point position, out bool needToContinueEating,out bool mustCapture)
        {
            Rules rule= new Rules();
            bool lastmovewasACaptured = false;
            needToContinueEating = false;
            this.Board = ConvertBoardStateToBoard(this);
            var destPoint = ConvertMoveTypeToCoordinate(position, moveType); //returns type point
            var srcPoint = ConvertPointToCoordinate(position.X, position.Y);          // returns type point
            var srcCoord = new Coordinate { X = srcPoint.X, Y = srcPoint.Y, Status = Board.PieceColor(Board[srcPoint.X, srcPoint.Y]) };
            var oppCoord = new Coordinate { X = destPoint.X, Y = destPoint.Y, Status = Board.PieceColor(Board[destPoint.X, destPoint.Y]) };

            if (!CheckValidPieceColor(this.Board, srcPoint.X, srcPoint.Y, player))
            {
                needToContinueEating = false;
                mustCapture = false;
                return null;
            }
            if (!IsEmptyCoord(Board, destPoint.X, destPoint.Y) && CheckValidPieceColor(Board, destPoint.X, destPoint.Y, player))
            {
                needToContinueEating = false;
                mustCapture = false;
                return null;
            }
            if (!IsEmptyCoord(Board, destPoint.X, destPoint.Y) &&
                !CheckValidPieceColor(Board, destPoint.X, destPoint.Y, player))
            {
                var captures = rule.CoordsToCaptureAndDest(Board, srcCoord, oppCoord, player);
                if (captures.Count > 0)
                {
                    foreach (var listOfCap in captures.Keys)
                    {
                        if (listOfCap.Last() == oppCoord)
                        {
                            int length = listOfCap.Count;
                            Coordinate newDestCoord = rule.FindDestByCap(Board, srcCoord, oppCoord);
                            this.Board.UpdateBoard(srcCoord, newDestCoord);
                            this.Board.UpdateCapturedSoldiers(oppCoord, Board.GetOpponent(player));
                            rule.IsBecameAKing(Board, newDestCoord);
                            Board[oppCoord.X, oppCoord.Y].Status = Piece.None;
                            this.BoardCells = ConvertBoardToBoardState(Board);
                            lastmovewasACaptured = true;
                            drawGame = CheckDraw(Board, Board[newDestCoord.X,newDestCoord.Y], lastmovewasACaptured);
                            if (length > 1)
                                needToContinueEating =true;
                            mustCapture = false;
                            return this;
                        }
                    }
                    mustCapture = true;
                    return null;
                }

            }
            //check if player doesnt have any availble captures- if he does then this move isn't valid
            var capturesAvaileble = rule.FindCaptures(Board, player);
            if (capturesAvaileble.Count == 0 )
            {
                if(!rule.IsValidMove(Board, srcCoord, Board[destPoint.X,destPoint.Y],player))
                {
                     mustCapture = false;
                     return null;
                }
                Board.UpdateBoard(Board[srcPoint.X, srcPoint.Y], Board[destPoint.X, destPoint.Y]);
                rule.IsBecameAKing(Board, Board[destPoint.X, destPoint.Y]);
                this.BoardCells = ConvertBoardToBoardState(Board);
                mustCapture = false;
                drawGame = CheckDraw(Board, Board[destPoint.X, destPoint.Y], lastmovewasACaptured);
                return this;
            }
            mustCapture = true;
            return null;
        }
        /// <summary>
        /// Check the safeness of a coordinate (can be captured). if the sold is on boundary than safe (4) else return the 
        /// delta between number of player soldiers and number of Opp soldiers around the coord. 
        /// </summary>
        /// <param name="board"></param>
        /// <param name="coord"></param>
        /// <param name="player"></param>
        /// <returns></returns>
        private int Safeness(Board board, Coordinate coord, Player player)
        {
            int playerCoords = 0;
            int opponentCoords = 0;
            Rules rule = new Rules();
            if (coord.X == 1 || coord.X == 8 || coord.Y == 1 || coord.Y == 8)
            {
                return 4;
            }
            IList<Coordinate> coordinates = rule.OptionalMoves(board, coord, player);
            foreach (var coordinate in coordinates)
            {
                if (player == board.GetPlayer(coordinate))
                {
                    playerCoords++;
                }
                else if (board.GetOpponent(player) == board.GetPlayer(coordinate))
                {
                    opponentCoords++;
                }
            }

            return playerCoords - opponentCoords;
        }
 /// <summary>
 /// Checkes whether the coordinate can capture
 /// </summary>
 /// <param name="board"></param>
 /// <param name="coordinate"></param>
 /// <param name="player"></param>
 /// <returns></returns>
 private int CanCapture(Board board, Coordinate coordinate, Player player)
 {
     Rules rule = new Rules();
     IList<Coordinate> coordinatesinDirection = rule.GetMovesInDirection(board, coordinate, player);
     int max = 0;
     foreach (var cid in coordinatesinDirection)
     {
         if (board.IsOpponentPiece(player, cid))
         {
             IDictionary<IList<Coordinate>, Coordinate> captures = rule.CoordsToCaptureAndDest(board, coordinate,
                                                                                               cid, player);
             if (captures.Count > 0)
             {
                 if (captures.ElementAt(0).Key.Count > max)
                 {
                     max = captures.ElementAt(0).Key.Count;
                 }
             }
         }
     }
     return max;
 }