Пример #1
0
        //As autofinish plays for both colors, currentAiLegalMoves will represent human color options.
        //every second run through the loop.
        private void AutoFinish()
        {
            PieceID     playerToMove = dvonnGame.humanPlayerColor;
            List <Move> currentAiLegalMoves;
            List <Move> opponentLegalMoves;

            Console.WriteLine();
            Console.WriteLine("AI will now finish the game");
            WaitForUser();

            do
            {
                currentAiLegalMoves = dvonnBoard.FindLegalMoves(playerToMove);
                if (currentAiLegalMoves.Count > 0)
                {
                    Move randomMove = PickRandomMove(currentAiLegalMoves);
                    dvonnBoard.MakeMove(randomMove);
                    dvonnGame.gameMoveList.Add(randomMove);
                    dvonnBoard.CheckDvonnCollapse(randomMove, false);
                }
                opponentLegalMoves = dvonnBoard.FindLegalMoves(playerToMove.ToOpposite());

                if (currentAiLegalMoves.Count == 0 && opponentLegalMoves.Count > 0)
                {
                    dvonnGame.gameMoveList.Add(new Move(playerToMove, true));
                }

                playerToMove = playerToMove.ToOpposite();
            } while ((currentAiLegalMoves.Count == 0 && opponentLegalMoves.Count == 0) == false);

            dvonnBoard.VisualizeBoard();
            DoEndOFGameRoutine();
        }
Пример #2
0
    //Returns properties of the specified piece
    public ChessPieceProperties GetPieceProperties(Team team, PieceID id)
    {
        TileIndex location = GetPieceLocation(team, id);

        if (location == TileIndex.Null)
        {
            return(null);
        }

        return(GetTilePiecePropertiesAt(location));
    }
Пример #3
0
        public static PieceID ToOpposite(this PieceID id)
        {
            if (id == PieceID.White)
            {
                return(PieceID.Black);
            }
            if (id == PieceID.Black)
            {
                return(PieceID.White);
            }

            throw new ArgumentException("Unexpected piece id received: " + id.ToString());
        }
Пример #4
0
 //Returns the specified pieces location on the board.
 public TileIndex GetPieceLocation(Team team, PieceID id)
 {
     if (team == Team.White)
     {
         return(wPieceLocations[(int)id]);
     }
     else if (team == Team.Black)
     {
         return(bPieceLocations[(int)id]);
     }
     else
     {
         return(TileIndex.Null);
     }
 }
Пример #5
0
        private char GetChar(PieceID pieceColor)
        {
            if (pieceColor == PieceID.Black)
            {
                return('B');
            }
            if (pieceColor == PieceID.White)
            {
                return('W');
            }
            if (pieceColor == PieceID.Dvonn)
            {
                return('D');
            }

            throw new ArgumentException("Unexpected piece id received: " + pieceColor.ToString());
        }
Пример #6
0
        public Game(PieceID humanPlayerColor, string humanPlayerName, string aiEngineName, string aiEngineVersion)
        {
            this.humanPlayerColor = humanPlayerColor;
            this.aiEngineName     = aiEngineName;
            this.aiEngineVersion  = aiEngineVersion;

            if (humanPlayerColor == PieceID.White)
            {
                whitePlayerName = humanPlayerName;
                blackPlayerName = aiEngineName + " (v. " + aiEngineVersion + " )";
            }
            else
            {
                blackPlayerName = humanPlayerName;
                whitePlayerName = aiEngineName + " (v. " + aiEngineVersion + " )";
            }
        }
Пример #7
0
        public static char ToChar(this PieceID id)
        {
            if (id == PieceID.Dvonn)
            {
                return('D');
            }
            if (id == PieceID.White)
            {
                return('W');
            }
            if (id == PieceID.Black)
            {
                return('B');
            }

            throw new ArgumentException("Unexpected piece id received: " + id.ToString());
        }
Пример #8
0
        public List <int> ControlledStacks(PieceID color)
        {
            List <int> controlledStacks = new List <int>();

            for (int i = 0; i < 49; i++)
            {
                if (entireBoard[i].stack.Count == 0)
                {
                    continue;
                }
                if (entireBoard[i].TopPiece().pieceType == color)
                {
                    controlledStacks.Add(i);
                }
            }
            return(controlledStacks);
        }
Пример #9
0
        public int GetScore(PieceID color)
        {
            int score = 0;

            for (int i = 0; i < 49; i++)
            {
                int stackCount = stacks[i].Length;
                if (stackCount == 0)
                {
                    continue;
                }
                if (TopPiece(i) == color.ToChar())
                {
                    score += stackCount;
                }
            }
            return(score);
        }
Пример #10
0
        public int GetScore(PieceID color)
        {
            int scoreCounter = 0;

            for (int i = 0; i < 49; i++)
            {
                Field chosenField = entireBoard[i];
                if (chosenField.stack.Count == 0)
                {
                    continue;
                }
                if (chosenField.TopPiece().pieceType == color)
                {
                    scoreCounter += chosenField.stack.Count;
                }
            }
            return(scoreCounter);
        }
Пример #11
0
    //Sets the object reference held at the provided index
    public void SetTilePieceAt(int row, int column, GameObject obj, PieceID id = PieceID.None, bool isInitial = false)
    {
        ChessPieceProperties properties = obj.GetComponent <ChessPieceProperties>();

        pieces[this.Index2DToIndex(row, column)] = properties;

        if (isInitial)
        {
            properties.SetId(id);
        }


        if (properties.Team == Team.White)
        {
            wPieceLocations[(int)properties.Id] = new TileIndex(row, column);
        }
        if (properties.Team == Team.Black)
        {
            bPieceLocations[(int)properties.Id] = new TileIndex(row, column);
        }

        //Debug.Log("Piece: " + obj.name +
        //    " ID: " + properties.Id.ToString() +
        //    " Location: " + Utils.Index2DToIndex(properties.Team==Team.White ? wPieceLocations[(int)properties.Id]:bPieceLocations[(int)properties.Id]));

        if (properties.Type == PieceType.King)
        {
            if (properties.Team == Team.White)
            {
                wKingIndex = new TileIndex(row, column);
            }
            else if (properties.Team == Team.Black)
            {
                bKingIndex = new TileIndex(row, column);
            }
            else
            {
                Debug.LogError("Team tag for Object named King did not match.");
            }
        }

        properties.isHasMoved = !isInitial;
    }
Пример #12
0
        char?GetChar(PieceID pieceColor)
        {
            if (pieceColor == PieceID.Black)
            {
                return('B');
            }
            if (pieceColor == PieceID.White)
            {
                return('W');
            }
            if (pieceColor == PieceID.Dvonn)
            {
                return('D');
            }

            else
            {
                return(null);
            }
        }
Пример #13
0
        Position DistributePieces(Position position, int pieceCount, PieceID pieceColor)
        {
            Random rGen = new Random();

            for (int i = 0; i < pieceCount; i++)
            {
                int rNum = rGen.Next(0, 49);

                if (position.stacks[rNum].Length == 0)
                {
                    position.stacks[rNum] += GetChar(pieceColor);
                }
                else
                {
                    pieceCount++;  //the field was occupied, run the loop once again.
                }
            }

            return(position);
        }
Пример #14
0
        private List <int> LegalSources(PieceID colorToMove)
        {
            List <int> notEmptyStacks = FindNotEmptyStacks();
            List <int> legalSources   = new List <int>();

            foreach (int fieldID in notEmptyStacks)
            {
                if (entireBoard[fieldID].TopPiece().pieceType != colorToMove)
                {
                    continue;
                }
                else if (EnclosureCondition(fieldID) == true)
                {
                    continue;
                }
                else
                {
                    legalSources.Add(fieldID);
                }
            }
            return(legalSources);
        }
Пример #15
0
        public List <Move> RepeatedRandomMove(List <Move> aiMoves)
        {
            List <Move> playerLegalMoves;
            List <Move> aiLegalMoves = aiMoves;
            PieceID     humanColor   = dvonnGame.humanPlayerColor;
            PieceID     aiColor      = humanColor.ToOpposite();

            Console.WriteLine("Human player has no legal moves, computer will continue playing");
            do
            {
                WaitForUser();
                Move randomMove = PickRandomMove(aiLegalMoves);
                dvonnBoard.MakeMove(randomMove);
                dvonnGame.gameMoveList.Add(randomMove);
                dvonnBoard.VisualizeBoard();
                typeWriter.MoveComment(randomMove, aiColor);
                dvonnBoard.CheckDvonnCollapse(randomMove, true);

                aiLegalMoves     = dvonnBoard.FindLegalMoves(aiColor);
                playerLegalMoves = dvonnBoard.FindLegalMoves(humanColor);

                if (aiLegalMoves.Count == 0 && playerLegalMoves.Count == 0)
                {
                    return(null);
                }
                else if (aiLegalMoves.Count == 0)
                {
                    break;
                }

                //Add pass move for human player:
                dvonnGame.gameMoveList.Add(new Move(humanColor, true));
            } while (playerLegalMoves.Count == 0);

            return(playerLegalMoves);
        }
Пример #16
0
        public List <Move> FindLegalMoves(PieceID color)
        {
            List <Move> legalMoves     = new List <Move>();
            List <int>  notEmptyStacks = FindNotEmptyStacks();
            List <int>  sources        = LegalSources(color);

            foreach (int sourceID in sources)
            {
                int pieceCount = entireBoard[sourceID].stack.Count;

                foreach (int targetID in notEmptyStacks)
                {
                    if (targetID == sourceID)
                    {
                        continue;
                    }
                    if (BoardProperties.allPrincipalMoves.ContainsKey(Tuple.Create(sourceID, targetID, pieceCount)))
                    {
                        legalMoves.Add(new Move(sourceID, targetID, color));
                    }
                }
            }
            return(legalMoves);
        }
Пример #17
0
        private bool BranchEndpoints(int maxEndPoints)
        {
            int         newNodeCounter      = 0;
            int         gameOverMoveCounter = 0;
            bool        gameOver            = false;
            List <Node> allLeaves           = dvonnTree.GetOuterLeaves();

            //Console.WriteLine();
            //Console.WriteLine("AI: Branching begun at depth " + depthCounter);
            //Console.WriteLine("AI: Color to move: " + tempPlayerToMove.ToString());
            //Console.WriteLine("AI: Endpoints found: " + allLeaves.Count);

            foreach (Node endPoint in allLeaves)
            {
                //if endpoint is already a 'gameOverMove' the move will be copied as the only child
                if (endPoint.move != null && endPoint.move.isGameOverMove)
                {
                    Move gameOverMove = new Move(true, endPoint.move.whiteScore, endPoint.move.blackScore);
                    gameOverMove.gameOverMoveDepth = endPoint.move.gameOverMoveDepth;
                    dvonnTree.InsertChild(new Node(gameOverMove), endPoint);
                    newNodeCounter++;
                    gameOverMoveCounter++;
                    if (gameOverMoveCounter == allLeaves.Count)
                    {
                        Console.WriteLine();
                        Console.WriteLine("AI: stopping branching. All endpoints are 'game over moves'.");
                        gameOver = true;
                    }
                    continue;
                }

                //Checks for dvonn collapse and saves it to endpoint position.
                aiBoard.ReceivePosition(endPoint.resultingPosition);
                if (endPoint == dvonnTree.root)
                {
                    aiBoard.CheckDvonnCollapse(null, false);
                }
                else
                {
                    aiBoard.CheckDvonnCollapse(endPoint.move, false);
                }
                endPoint.resultingPosition = aiBoard.SendPosition();

                List <Move> playerLegalMoves   = aiBoard.FindLegalMoves(tempPlayerToMove);
                List <Move> opponentLegalMoves = aiBoard.FindLegalMoves(tempPlayerToMove.ToOpposite());

                //Check if neither players have any legal moves, if yes, a game over move is created
                if (playerLegalMoves.Count == 0 && opponentLegalMoves.Count == 0)
                {
                    int  whiteScore   = endPoint.resultingPosition.GetScore(PieceID.White);
                    int  blackScore   = endPoint.resultingPosition.GetScore(PieceID.Black);
                    Move gameOverMove = new Move(true, whiteScore, blackScore);
                    gameOverMove.gameOverMoveDepth = endPoint.depth + 1;
                    dvonnTree.InsertChild(new Node(gameOverMove), endPoint);
                    newNodeCounter++;
                    continue;
                }

                //Check if moving player has no legal moves, if yes, a pass move is inserted in the tree
                if (playerLegalMoves.Count == 0)
                {
                    Move passMove = new Move(tempPlayerToMove, true);
                    dvonnTree.InsertChild(new Node(passMove, endPoint.resultingPosition), endPoint);
                    newNodeCounter++;
                    continue;
                }

                foreach (Move move in playerLegalMoves)
                {
                    Position newPosition = new Position();
                    newPosition.Copy(endPoint.resultingPosition);
                    newPosition.MakeMove(move);

                    dvonnTree.InsertChild(new Node(move, newPosition), endPoint);
                    newNodeCounter++;
                }
            }

            Console.WriteLine("AI: Branching for depth level " + depthCounter + " is complete.");
            Console.WriteLine("AI: added total number of nodes: " + newNodeCounter);

            tempPlayerToMove = tempPlayerToMove.ToOpposite();
            depthCounter++;

            return(newNodeCounter == 0 || newNodeCounter > maxEndPoints || gameOver);
        }
Пример #18
0
        public void RunGameMenu()
        {
            bool        gamerunning = true;
            List <Move> playerLegalMoves;
            List <Move> aiLegalMoves;
            PieceID     humanColor = dvonnGame.humanPlayerColor;
            PieceID     aiColor    = humanColor.ToOpposite();

            if (humanColor == PieceID.Black)
            {
                Console.WriteLine();
                Console.WriteLine("Computer is ready to start game. Press any key to launch action.");
                WaitForUser();

                Move aiMove = aiAgent.ComputeAiMove(dvonnGame.openingPosition, aiColor);
                dvonnBoard.MakeMove(aiMove);
                dvonnGame.gameMoveList.Add(aiMove);
                dvonnBoard.VisualizeBoard();
                typeWriter.MoveComment(aiMove, aiColor);

                playerLegalMoves = dvonnBoard.FindLegalMoves(PieceID.Black);
                aiLegalMoves     = dvonnBoard.FindLegalMoves(PieceID.White);
            }
            else
            {
                playerLegalMoves = dvonnBoard.FindLegalMoves(PieceID.White);
                aiLegalMoves     = dvonnBoard.FindLegalMoves(PieceID.Black);
            }


            while (gamerunning)
            {
                typeWriter.MenuText();

                string input = Console.ReadLine();

                switch (input)
                {
                case "1":     // Enter move ...

                    Move chosenMove = GetUserMoveInput(playerLegalMoves);
                    //Move chosenMove = PickRandomMove(playerLegalMoves);

                    if (chosenMove.source == 0 && chosenMove.target == 0)     // a special situation, where user wants to go back to menu
                    {
                        dvonnBoard.VisualizeBoard();
                        break;
                    }
                    else
                    {
                        // else, if user doesn't want to go back to menu, execute move...
                        dvonnBoard.MakeMove(chosenMove);
                        dvonnGame.gameMoveList.Add(chosenMove);
                        dvonnBoard.VisualizeBoard();
                        typeWriter.MoveComment(chosenMove, humanColor);
                    }
                    //Do a check for dvonn collapse, and if true, execute and make comment.
                    dvonnBoard.CheckDvonnCollapse(chosenMove, true);

                    //After White's move both players' options need to be analyzed.
                    playerLegalMoves = dvonnBoard.FindLegalMoves(humanColor);
                    aiLegalMoves     = dvonnBoard.FindLegalMoves(aiColor);

                    //Check whether game has ended.
                    if (aiLegalMoves.Count == 0 && playerLegalMoves.Count == 0)
                    {
                        DoEndOFGameRoutine();
                        gamerunning = false;
                        break;     // when returned, close console
                    }

                    //Check if computer has any legal moves
                    if (aiLegalMoves.Count == 0)
                    {
                        dvonnGame.gameMoveList.Add(new Move(aiColor, true));
                        Console.WriteLine();
                        Console.WriteLine("Computer has no legal moves. It's your turn again.");
                        break;
                    }
                    // else computer gets to move:
                    Console.WriteLine();
                    Console.WriteLine(aiColor + " is ready to move");
                    WaitForUser();

                    Move aiMove = aiAgent.ComputeAiMove(dvonnBoard.SendPosition(), aiColor);
                    dvonnBoard.MakeMove(aiMove);
                    dvonnGame.gameMoveList.Add(aiMove);
                    dvonnBoard.VisualizeBoard();
                    typeWriter.MoveComment(aiMove, aiColor);
                    dvonnBoard.CheckDvonnCollapse(aiMove, true);

                    //After ai engine move both players' options need to be analyzed.
                    playerLegalMoves = dvonnBoard.FindLegalMoves(humanColor);
                    aiLegalMoves     = dvonnBoard.FindLegalMoves(aiColor);

                    //Again, this time after blacks move, check whether game has ended.
                    if (aiLegalMoves.Count == 0 && playerLegalMoves.Count == 0)
                    {
                        DoEndOFGameRoutine();
                        gamerunning = false;
                        break;     // when returned, close console
                    }

                    //Check if human has any legal moves
                    if (playerLegalMoves.Count == 0)
                    {
                        dvonnGame.gameMoveList.Add(new Move(humanColor, true));

                        List <Move> newMoves = RepeatedRandomMove(aiLegalMoves);
                        if (newMoves == null)
                        {
                            DoEndOFGameRoutine();
                            gamerunning = false;     // when returned, close console
                            break;
                        }
                        else
                        {
                            // If white should have gotten a new opportunity to move, return to main menu...
                            playerLegalMoves = newMoves;
                            break;
                        }
                    }
                    break;

                //Inspect stack:
                case "2":
                    Console.WriteLine("Please enter stack field to inspect:");
                    string request = Console.ReadLine().ToUpper();

                    while (request.Length != 2)
                    {
                        Console.WriteLine("Entered fieldname is not two characters. Please enter fieldnames like this: 'a0' or 'A0'");
                        request = Console.ReadLine().ToUpper();
                    }

                    while (!dvonnBoard.entireBoard.Any(field => field.fieldName == request))
                    {
                        Console.WriteLine("Field ID is not valid");
                        request = Console.ReadLine().ToUpper();
                    }

                    stackInspector.InspectStack(request);
                    break;

                case "3":
                    Console.WriteLine("If game was to end now, the score would be: ");
                    Console.WriteLine("White: {0} \t Black: {1}", dvonnBoard.GetScore(PieceID.White), dvonnBoard.GetScore(PieceID.Black));
                    Console.WriteLine();
                    break;

                case "4":     // Visualize board
                    dvonnBoard.VisualizeBoard();
                    break;

                case "5":     //Read the rules
                    typeWriter.Rules();
                    break;

                case "6":     //Exit
                    gamerunning = false;
                    break;

                case "7":     // "Secret" option that lets developer create endgame scenario for test purposes
                    dvonnBoard.ClearBoard();
                    //Position partialDvonnGame = dvonnGame.RandomPopulate(3, 8, 8);
                    Position partialDvonnGame = new Position();

                    partialDvonnGame.stacks[12] = "WBB";
                    partialDvonnGame.stacks[15] = "DW";
                    partialDvonnGame.stacks[16] = "W";
                    partialDvonnGame.stacks[21] = "BB";
                    partialDvonnGame.stacks[22] = "BB";
                    partialDvonnGame.stacks[26] = "WWW";
                    partialDvonnGame.stacks[27] = "W";
                    partialDvonnGame.stacks[32] = "DB";
                    partialDvonnGame.stacks[33] = "WB";
                    partialDvonnGame.stacks[35] = "BBWB";
                    partialDvonnGame.stacks[37] = "WB";
                    partialDvonnGame.stacks[41] = "W";
                    partialDvonnGame.stacks[44] = "B";
                    partialDvonnGame.stacks[45] = "D";


                    dvonnBoard.ReceivePosition(partialDvonnGame);
                    playerLegalMoves = dvonnBoard.FindLegalMoves(PieceID.White);
                    dvonnBoard.VisualizeBoard();
                    dvonnBoard.CheckDvonnCollapse(null, false);
                    break;

                case "8":     //Auto finish
                    AutoFinish();
                    gamerunning = false;
                    break;

                default:
                    Console.WriteLine("Unable to read input, please try again.");
                    break;
                }
            }
        }
Пример #19
0
        //Position is evaluated through the options of both 'next player' (after the move has been executed).
        //If the resulting position gives the next player many options and a good position, the evaluation will be positive and high.
        //If the position gives equal chances to both players, it will be evaluated to 0.
        //IMPORTANT: finally, the evaluation is biased according to the generation depth. This means that if the responsible color is equal to class variable 'playerToMove'
        //the evaluation will be multiplied by -1; But if the responsible color is equal to 'next player', the evaluation will remain unaltered.
        //
        // 'aiResponsibleColor' is the responsible color of the moves of the children of the root of current position tree. Could be human color, if eg. autofinishing game or suggesting hint.
        public int EvaluatePosition(Node endPoint, GamePhase gamePhase, PieceID aiResponsibleColor)
        {
            Move     move = endPoint.move;
            Position resultingPosition = endPoint.resultingPosition;
            int      thisEval          = 0;

            if (move.isGameOverMove)
            {
                thisEval = ComputeGameOverValue(move, aiResponsibleColor);
                return(thisEval);
            }

            //Checks for dvonn collapse and saves result in the node.
            evaluatorBoard.ReceivePosition(resultingPosition);
            evaluatorBoard.CheckDvonnCollapse(move, false);
            endPoint.resultingPosition = evaluatorBoard.SendPosition();

            PieceID movingColor = move.responsibleColor;
            PieceID nextPlayer  = move.responsibleColor.ToOpposite();

            List <Move> nextPlayerLegalMoves = evaluatorBoard.FindLegalMoves(nextPlayer);
            List <Move> samePlayerLegalMoves = evaluatorBoard.FindLegalMoves(movingColor);


            if (gamePhase == GamePhase.EarlyGame)
            {
                //bonus for controlledstacks
                List <int> controlledStacks = evaluatorBoard.ControlledStacks(nextPlayer);
                thisEval += controlledStacks.Count * 100;

                //bonus for single stacks
                List <int> singles = evaluatorBoard.GetSingles(controlledStacks);
                thisEval += singles.Count * 250;

                //bonus for singles that land on dvonn
                List <int> dvonnLanders = evaluatorBoard.DvonnLanders(nextPlayerLegalMoves);
                foreach (int single in singles)
                {
                    if (dvonnLanders.Contains(single))
                    {
                        thisEval += 800;
                    }
                }

                //bonus for dvonn landers in general
                thisEval += dvonnLanders.Count * 300;

                //bonus for double dvonn landers
                var dvonnLandersGrouping = dvonnLanders.GroupBy(i => i);
                foreach (var grp in dvonnLandersGrouping)
                {
                    if (grp.Count() > 1)
                    {
                        thisEval += 800;
                    }
                }

                //bonus for dvonn dominance (per dvonn tower)
                List <int> dvonnTowers = evaluatorBoard.GetDvonnStacks();
                foreach (int tower in dvonnTowers)
                {
                    List <int> nextPlayerLanders = evaluatorBoard.GetLanders(tower, nextPlayerLegalMoves);
                    List <int> samePlayerLanders = evaluatorBoard.GetLanders(tower, samePlayerLegalMoves);

                    if (nextPlayerLanders.Count > samePlayerLanders.Count)
                    {
                        thisEval += 2000;
                    }
                    else if (nextPlayerLanders.Count == samePlayerLanders.Count)
                    {
                        thisEval += 1000;
                    }
                }
            }

            if (gamePhase == GamePhase.Apex || gamePhase == GamePhase.PostApex)
            {
                //bonus for controlledstacks
                List <int> controlledStacks = evaluatorBoard.ControlledStacks(nextPlayer);
                thisEval += controlledStacks.Count * 100;

                //bonus for legal moves
                thisEval += nextPlayerLegalMoves.Count * 200;

                //bonus for single stacks
                List <int> singles = evaluatorBoard.GetSingles(controlledStacks);
                thisEval += singles.Count * 250;

                //bonus for singles that land on dvonn
                List <int> dvonnLanders = evaluatorBoard.DvonnLanders(nextPlayerLegalMoves);
                foreach (int single in singles)
                {
                    if (dvonnLanders.Contains(single))
                    {
                        thisEval += 800;
                    }
                }

                //bonus for dvonn landers in general
                thisEval += dvonnLanders.Count * 300;

                //bonus for landers of landers
                List <int> dvonnLandersLanders = new List <int>();
                foreach (int lander in dvonnLanders)
                {
                    List <int> landerLanders = evaluatorBoard.GetLanders(lander, nextPlayerLegalMoves);
                    dvonnLandersLanders.AddRange(landerLanders);
                    thisEval += landerLanders.Count * 100;
                }

                //bonus for dvonn dominance (per dvonn tower)
                List <int> dvonnTowers = evaluatorBoard.GetDvonnStacks();
                foreach (int tower in dvonnTowers)
                {
                    List <int> nextPlayerLanders = evaluatorBoard.GetLanders(tower, nextPlayerLegalMoves);
                    List <int> samePlayerLanders = evaluatorBoard.GetLanders(tower, samePlayerLegalMoves);

                    if (nextPlayerLanders.Count > samePlayerLanders.Count)
                    {
                        thisEval += 2000;
                    }
                    else if (nextPlayerLanders.Count == samePlayerLanders.Count)
                    {
                        thisEval += 1000;
                    }
                }

                //bonus for dead tower dominance
                List <int> deadTowers = evaluatorBoard.DeadTowers();
                foreach (int deadTower in deadTowers)
                {
                    List <int> nextPlayerLanders = evaluatorBoard.GetLanders(deadTower, nextPlayerLegalMoves);
                    List <int> samePlayerLanders = evaluatorBoard.GetLanders(deadTower, samePlayerLegalMoves);

                    if (nextPlayerLanders.Count > samePlayerLanders.Count)
                    {
                        thisEval += 200 * evaluatorBoard.entireBoard[deadTower].stack.Count;
                    }
                    else if (nextPlayerLanders.Count == samePlayerLanders.Count)
                    {
                        thisEval += 75 * evaluatorBoard.entireBoard[deadTower].stack.Count;
                    }
                }
            }

            if (gamePhase == GamePhase.EndGame)
            {
                //bonus for legal moves
                thisEval += nextPlayerLegalMoves.Count * 200;

                //bonus for dead tower dominance
                List <int> deadTowers = evaluatorBoard.DeadTowers();
                foreach (int deadTower in deadTowers)
                {
                    List <int> nextPlayerLanders = evaluatorBoard.GetLanders(deadTower, nextPlayerLegalMoves);
                    List <int> samePlayerLanders = evaluatorBoard.GetLanders(deadTower, samePlayerLegalMoves);

                    if (nextPlayerLanders.Count > samePlayerLanders.Count)
                    {
                        thisEval += 200 * evaluatorBoard.entireBoard[deadTower].stack.Count;
                    }
                    else if (nextPlayerLanders.Count == samePlayerLanders.Count)
                    {
                        thisEval += 75 * evaluatorBoard.entireBoard[deadTower].stack.Count;
                    }
                }
            }

            int biasMultiplier = 0;

            if (aiResponsibleColor == movingColor)
            {
                biasMultiplier = -1;
            }
            else
            {
                biasMultiplier = 1;
            }

            if (thisEval == int.MaxValue && biasMultiplier == -1)
            {
                return(int.MinValue);
            }
            if (thisEval == int.MaxValue && biasMultiplier == 1)
            {
                return(int.MaxValue);
            }
            if (thisEval == int.MinValue && biasMultiplier == -1)
            {
                return(int.MaxValue);
            }
            if (thisEval == int.MinValue && biasMultiplier == 1)
            {
                return(int.MinValue);
            }

            return(thisEval * biasMultiplier);
        }
Пример #20
0
 public Move(PieceID responsibleColor, bool isPassMove)
 {
     this.isPassMove       = isPassMove;
     this.responsibleColor = responsibleColor; //that is, the 'hand' that has executes the move
 }
Пример #21
0
 public Move(int source, int target, PieceID responsibleColor)
 {
     this.source           = source;
     this.target           = target;
     this.responsibleColor = responsibleColor; //that is, the 'hand' that has executes the move
 }
Пример #22
0
 public TreeCrawler(PositionTree tree, GamePhase gamePhase, PieceID aiResponsibleColor)
 {
     this.tree               = tree;
     this.gamePhase          = gamePhase;
     this.aiResponsibleColor = aiResponsibleColor;
 }
Пример #23
0
        public int ComputeGameOverValue(Move move, PieceID aiResponsibleColor)
        {
            int  thisEval            = 0;
            bool isMaximumGeneration = move.gameOverMoveDepth % 2 != 0;

            if (move.whiteScore == move.blackScore)
            {
                thisEval = 0;
            }

            if (move.whiteScore > move.blackScore)
            {
                if (isMaximumGeneration)
                {
                    if (aiResponsibleColor == PieceID.White)
                    {
                        thisEval = int.MaxValue;
                    }
                    else
                    {
                        thisEval = int.MinValue;
                    }
                }
                else
                {
                    if (aiResponsibleColor == PieceID.White)
                    {
                        thisEval = int.MinValue;
                    }
                    else
                    {
                        thisEval = int.MaxValue;
                    }
                }
            }
            if (move.whiteScore < move.blackScore)
            {
                if (isMaximumGeneration)
                {
                    if (aiResponsibleColor == PieceID.White)
                    {
                        thisEval = int.MinValue;
                    }
                    else
                    {
                        thisEval = int.MaxValue;
                    }
                }
                else
                {
                    if (aiResponsibleColor == PieceID.White)
                    {
                        thisEval = int.MaxValue;
                    }
                    else
                    {
                        thisEval = int.MinValue;
                    }
                }
            }
            return(thisEval);
        }
Пример #24
0
 public Piece(PieceID pieceType)
 {
     this.pieceType = pieceType;
 }
Пример #25
0
 public void MoveComment(Move thisMove, PieceID Color)
 {
     Console.WriteLine();
     Console.WriteLine(Color.ToString() + " move, " + BoardProperties.fieldCoordinates[thisMove.source] + " / " + BoardProperties.fieldCoordinates[thisMove.target] + " has been executed.");
 }
Пример #26
0
        public Move ComputeAiMove(Position currentPosition, PieceID playerToMove)
        {
            Move chosenMove = new Move();

            depthCounter      = 0;
            this.playerToMove = playerToMove;
            tempPlayerToMove  = playerToMove;
            dvonnTree         = new PositionTree(currentPosition);
            aiBoard.ReceivePosition(currentPosition);
            int legalMoveCount  = aiBoard.FindLegalMoves(playerToMove).Count;
            int emptyStackCount = 49 - aiBoard.FindNotEmptyStacks().Count;

            currentGamePhase = DetermineGamePhase(emptyStackCount);

            Console.WriteLine();
            Console.WriteLine("AI: Legal moves count: " + legalMoveCount);
            Console.WriteLine("AI: Empty stacks count: " + emptyStackCount);
            Console.WriteLine("AI: Game Phase: " + currentGamePhase);
            Console.WriteLine();
            Console.WriteLine("AI: Computation begun.");
            var watch_1 = System.Diagnostics.Stopwatch.StartNew();

            if (currentGamePhase == GamePhase.EarlyGame)
            {
                CreateTree(3, 8000);
                PruneAndEvaluate();
                dvonnTree.RefreshAlphaBeta();
                if (dvonnTree.GetAllLeaves().Count < 1500)
                {
                    CreateTree(2, 8000);
                    PruneAndEvaluate();
                }
                chosenMove = PerformMiniMax();
            }

            if (currentGamePhase == GamePhase.Apex)
            {
                CreateTree(3, 7000);
                PruneAndEvaluate();
                dvonnTree.RefreshAlphaBeta();
                if (dvonnTree.GetAllLeaves().Count < 1000)
                {
                    CreateTree(2, 5000);
                    PruneAndEvaluate();
                }
                chosenMove = PerformMiniMax();
            }

            if (currentGamePhase == GamePhase.PostApex)
            {
                int allLeavesCount;
                do
                {
                    CreateTree(3, 9000);
                    PruneAndEvaluate();
                    dvonnTree.RefreshAlphaBeta();
                    allLeavesCount = dvonnTree.GetAllLeaves().Count;
                } while (allLeavesCount < 2500);

                int percentage = (int)((allLeavesCount - 1000) * 100 / (float)allLeavesCount);
                Console.WriteLine("AI: Hard prune percentage set to: " + percentage);
                HardPrune(percentage);
                dvonnTree.RemoveAllStubs();
                CreateTree(2, 3500);
                PruneAndEvaluate();
                chosenMove = PerformMiniMax();
            }

            if (currentGamePhase == GamePhase.EndGame)
            {
                CreateTree(15, 10000);
                EvaluateEndPoints();

                chosenMove = PerformMiniMax();
            }

            watch_1.Stop();
            var elapsedMs_1 = watch_1.ElapsedMilliseconds;

            Console.WriteLine("AI: Computation ended.");
            Console.WriteLine("AI: Total computation took: " + elapsedMs_1 + " milliseconds");
            Console.WriteLine("Outer endpoint depth: " + dvonnTree.GetDepthReach());
            WaitForUser();

            return(chosenMove);
        }
Пример #27
0
        public void SecondaryEvaluation(Node endPoint, GamePhase gamePhase, PieceID aiResponsibleColor, Position beforePosition)
        {
            Move thisMove = endPoint.move;

            if (gamePhase == GamePhase.EarlyGame)
            {
                if (beforePosition.TopPiece(thisMove.target) == aiResponsibleColor.ToOpposite().ToChar())
                {
                    thisMove.secondaryEvaluation += 1000;
                }
                else if (beforePosition.TopPiece(thisMove.target) == 'D')
                {
                    thisMove.secondaryEvaluation += 500;
                }

                evaluatorBoard.ReceivePosition(beforePosition);
                int beforeDvonnDistance = evaluatorBoard.ShortestDistanceToDvonn(thisMove.source);
                evaluatorBoard.ReceivePosition(endPoint.resultingPosition);
                int afterDvonnDistance = evaluatorBoard.ShortestDistanceToDvonn(thisMove.target);
                thisMove.secondaryEvaluation += (beforeDvonnDistance - afterDvonnDistance) * 400;
            }

            if (gamePhase == GamePhase.Apex || gamePhase == GamePhase.PostApex)
            {
                if (beforePosition.TopPiece(thisMove.target) == aiResponsibleColor.ToOpposite().ToChar())
                {
                    thisMove.secondaryEvaluation += 800;
                }
                else if (beforePosition.TopPiece(thisMove.target) == 'D')
                {
                    thisMove.secondaryEvaluation += 800;
                }

                evaluatorBoard.ReceivePosition(beforePosition);
                int beforeDvonnDistance = evaluatorBoard.ShortestDistanceToDvonn(thisMove.source);
                evaluatorBoard.ReceivePosition(endPoint.resultingPosition);
                int afterDvonnDistance = evaluatorBoard.ShortestDistanceToDvonn(thisMove.target);
                thisMove.secondaryEvaluation += (beforeDvonnDistance - afterDvonnDistance) * 800;
            }

            if (gamePhase == GamePhase.EndGame)
            {
                int playerColorScore;
                int opponentScore;
                if (endPoint.move.isGameOverMove)
                {
                    if (endPoint.move.whiteScore == endPoint.move.blackScore)
                    {
                        thisMove.secondaryEvaluation = 0;
                        return;
                    }
                    if (aiResponsibleColor == PieceID.White)
                    {
                        playerColorScore = endPoint.move.whiteScore;
                        opponentScore    = endPoint.move.blackScore;
                    }
                    else
                    {
                        playerColorScore = endPoint.move.blackScore;
                        opponentScore    = endPoint.move.whiteScore;
                    }
                }
                else
                {
                    playerColorScore = endPoint.resultingPosition.GetScore(aiResponsibleColor);
                    opponentScore    = endPoint.resultingPosition.GetScore(aiResponsibleColor.ToOpposite());
                }
                thisMove.secondaryEvaluation += playerColorScore - opponentScore;
            }
        }
Пример #28
0
 public void SetId(PieceID id)
 {
     _id = id;
 }