Exemple #1
0
    public ScoringMove MTD(AIBoard board)
    {
        int         gamma, guess = globalGuess;
        ScoringMove scoringMove = null;

        maximumExploredDepth = 0;

        string output = "";

        for (byte i = 0; i < MAX_ITERATIONS; i++)
        {
            gamma       = guess;
            scoringMove = Test(board, 0, gamma - 1);
            guess       = scoringMove.score;
            if (guess == gamma)
            {
                globalGuess = guess;
                output     += "guess encontrado en iteracion " + i;
                //MTDPathTest.text = output;
                return(scoringMove);
            }
        }

        output     += "guess no encontrado";
        globalGuess = guess;
        //MTDPathTest.text = output;
        return(scoringMove);
    }
Exemple #2
0
    void ObserveBoard()
    {
        board = new AIBoard(physicBoard);

        for (byte row = 0; row < 9; row++)
        {
            int maxColumn = board.supBoard.cells[row].Length;

            for (byte column = 0; column < maxColumn; column++)
            {
                //Text spaceText = buttonList[row, column];
                if (board.supBoard.cells[row][column].Marble == null)
                {
                    board.spaces[row][column] = PLAYER_COLOR.NONE;
                }
                else
                {
                    if (board.supBoard.cells[row][column].Marble.isWhite)
                    {
                        board.spaces[row][column] = PLAYER_COLOR.WHITE;
                    }
                    else
                    {
                        board.spaces[row][column] = PLAYER_COLOR.BLACK;
                    }
                }
            }
        }

        board.activePlayer = this.activePlayer;
        board.zobristKeys  = this.zobristKeys;
        board.calculateHashValue();
    }
Exemple #3
0
        /// <summary>
        /// Makes a list of all the moves player of code 'code' can make'.
        /// </summary>
        // XXX: TODO - optimize this.
        private static IEnumerable <Move> _findMoves(AIBoard board, int code)
        {
            int ocode = code == 1 ? 2 : 1;

            // Go through all possible moves of each piece of code 'code' on the board
            foreach (var gp in board.GetPieces(code))
            {
                for (int i = 0; i < 16; i++)
                {
                    int xto = gp.Item1 + positioncheck[i][0], yto = gp.Item2 + positioncheck[i][1];

                    if (xto >= Board.SIZE_X || xto < 0 || yto >= Board.SIZE_Y || yto < 0)
                    {
                        continue;
                    }
                    if (board[xto, yto] != 0)
                    {
                        continue;
                    }

                    // Count conversions
                    int gain = board.Gain(xto, yto, ocode);
                    if (i < 8)
                    {
                        gain += 1;
                    }

                    yield return(new Move(gp.Item1, gp.Item2, xto, yto, i >= 8, gain));
                    //yield return new Move(gp.x, gp.y, xto, yto, i >= 8, 0); // Conversion count is never used, so 0 is used as a placeholder
                }
            }
        }
Exemple #4
0
        private List <float> GetHardWeights(AIBoard board)
        {
            float p1spWeight = 1f;
            float p2spWeight = 1f;

            //Variables used in weight calculations.
            int playerOneSP            = BoardAnalysis.FindShortestPath(board, true);
            int playerTwoSP            = BoardAnalysis.FindShortestPath(board, true);
            int playerTwoNumWalls      = CurrentBoard.GetPlayerTwoNumWalls();
            int distanceBetweenPlayers = BoardAnalysis.FindDistanceBetween(CurrentBoard, CurrentBoard.GetPlayerOnePos(), CurrentBoard.GetPlayerTwoPos());

            if (playerOneSP - playerTwoSP > 2)
            {
                p1spWeight = 5;
            }
            else if (playerOneSP < 5)
            {
                p1spWeight = 2;
            }


            List <float> w = new List <float> {
                p1spWeight, p2spWeight
            };

            return(w);
        }
Exemple #5
0
        /// <summary>
        /// Add or update a entry in the hashtable.
        /// </summary>
        private void _updateOrAddHash(AIBoard cur, int code, int depth, StateInfo.ValueType flag, int value, Move best)
        {
            if (!this.transTable.ContainsKey(cur))
            {
                this.transTable[cur] = new StateInfo()
                {
                    CodeToMove = code, Depth = depth, Flag = flag, Value = value, Best = best
                };
                return;
            }

            var entry = this.transTable[cur];

            if (depth < entry.Depth)             // Don't overwrite w/ shallower entries.
            {
                return;
            }

            entry.CodeToMove = code;
            entry.Depth      = depth;
            entry.Flag       = flag;
            entry.Value      = value;

            if (best != null || entry.Best == null)
            {
                entry.Best = best;
            }
        }
Exemple #6
0
    void NewMove(int x, int y, GameObject piece, Board previousGameBoard)
    {
        Tile          potentialMoveTile = tiles[x, y];
        PotentialMove newMove           = new PotentialMove();

        newMove.tile  = potentialMoveTile;
        newMove.piece = piece;

        AIBoard potentialNewBoard = new AIBoard();

        Board potentialBoard = new Board();

        foreach (GameObject whiteAdd in previousGameBoard.white)
        {
            potentialBoard.white.Add(whiteAdd);
        }
        foreach (GameObject blackAdd in previousGameBoard.black)
        {
            potentialBoard.black.Add(blackAdd);
        }
        if (newMove.tile.piece != null)
        {
            if (newMove.tile.piece.GetComponent <UnitInfo>().colour == 0)
            {
                potentialBoard.white.Remove(newMove.tile.piece);
            }
            else
            {
                potentialBoard.black.Remove(newMove.tile.piece);
            }
        }
        potentialBoard.GetBoardValue(currentTurn);
        newMove.ResultingBoard = potentialBoard;
        potentialMoves.Add(newMove);
    }
 public WallDiffNode(AIBoard copy)
 {
     Board    = new AIBoard(copy);
     Depth    = 0;
     MoveMade = "rootnode";
     Diff     = BoardAnalysis.FindShortestPath(Board, true) - BoardAnalysis.FindShortestPath(Board, false);
 }
 //Used for creating children
 public WallDiffNode(WallDiffNode n, string move)
 {
     MoveMade = move;
     Board    = new AIBoard(n.Board);
     Board.MakeMove(move);
     Depth        = n.Depth + 1;
     PreviousDiff = n.Diff;
 }
Exemple #9
0
    public AIBoard GenerateNewBoardFromMove(List <MoveMarble> move)
    {
        AIBoard newBoard = this.DuplicateBoard();

        newBoard.Move(move, activePlayer);
        newBoard.activePlayer = Opponent(newBoard.activePlayer);
        return(newBoard);
    }
Exemple #10
0
        public ShotResult PlayPlayerMove(string userShotKey)
        {
            var shotResult = AIBoard.ShootAt(userShotKey);

            PlayerBoard.AddShotResult(shotResult);

            return(shotResult);
        }
Exemple #11
0
        public ShotResult PlayAIMove(GameField gameField = null)
        {
            gameField ??= _aiPlayer.GetGameFieldToShoot();

            var shotResult = PlayerBoard.ShootAt(gameField);

            AIBoard.AddShotResult(shotResult);

            return(shotResult);
        }
Exemple #12
0
        public WinnerType GetWinner()
        {
            if (AIBoard.AllShipsAreSunk())
            {
                return(WinnerType.Player);
            }

            if (PlayerBoard.AllShipsAreSunk())
            {
                return(WinnerType.Computer);
            }

            return(WinnerType.None);
        }
Exemple #13
0
        //Heuristic utility used to check if a direct path to the end of the board exists.
        public static bool HasDirectPath(AIBoard board, bool isPlayerOne, string space)
        {
            bool           pathExists   = true;
            string         currentPoint = space;
            HashSet <Move> badMoves     = board.GetInvalidPawnMoves();

            if (isPlayerOne)
            {
                string nextPoint = new string(new char[] { currentPoint[0], (char)(currentPoint[1] + 1) });

                int i = 0;
                while (i < 10)
                {
                    i++;
                    if (badMoves.Contains(new Move(currentPoint, nextPoint)))
                    {
                        pathExists = false;
                        break;
                    }
                    else
                    {
                        currentPoint = nextPoint;
                        nextPoint    = new string(new char[] { currentPoint[0], (char)(currentPoint[1] + 1) });
                    }
                }
            }
            else
            {
                string nextPoint = new string(new char[] { currentPoint[0], (char)(currentPoint[1] - 1) });

                int i = 0;
                while (i < 10)
                {
                    i++;
                    if (badMoves.Contains(new Move(currentPoint, nextPoint)))
                    {
                        pathExists = false;
                        break;
                    }
                    else
                    {
                        currentPoint = nextPoint;
                        nextPoint    = new string(new char[] { currentPoint[0], (char)(currentPoint[1] - 1) });
                    }
                }
            }
            return(pathExists);
        }
        //This returns all walls adjacent to the wall move made in
        public List <WallDiffNode> GetChildren()
        {
            List <WallDiffNode> children      = new List <WallDiffNode>();
            List <string>       adjacentWalls = DictionaryLookup.PerformWallsOfInterestLookup(MoveMade);

            foreach (string wall in adjacentWalls)
            {
                AIBoard tempBoard = new AIBoard(Board);
                tempBoard.MakeMove(wall);
                if (BoardAnalysis.CheckPathExists(tempBoard, true) && BoardAnalysis.CheckPathExists(tempBoard, false))
                {
                    children.Add(new WallDiffNode(this, wall));
                }
            }
            return(children);
        }
Exemple #15
0
        //If risk is very high will return 1, low risk is higher return value.
        private int GetMoveRisk(string move)
        {
            int     riskValue = 100;
            AIBoard tempBoard = new AIBoard(CurrentBoard);

            tempBoard.MakeMove(move);
            WallDiffNode rootNode = new WallDiffNode(tempBoard);

            List <string> wallPlacements = tempBoard.GetWallMoves();

            foreach (string wall in wallPlacements)
            {
                riskValue = Math.Min(riskValue, RiskIterate(new WallDiffNode(rootNode, wall), 0));
            }

            return(riskValue);
        }
Exemple #16
0
    public AIBoard DuplicateBoard()
    {
        AIBoard newBoard = new AIBoard(this.supBoard);

        for (byte row = 0; row < rows; row++)
        {
            int maxcolumn = spaces[row].Length;

            for (byte column = 0; column < maxcolumn; column++)
            {
                newBoard.spaces[row][column] = this.spaces[row][column];
            }
        }

        newBoard.activePlayer = this.activePlayer;
        return(newBoard);
    }
Exemple #17
0
        //Uses a depth first search to find any path that reaches the end goal
        public static bool CheckPathExists(AIBoard board, bool isPlayerOne)
        {
            //Moves to be visited is used to prevent the revisiting of nodes by another branch.
            HashSet <string>   movesToBeVisited = new HashSet <string>();
            Stack <SearchNode> spaces           = new Stack <SearchNode>();
            bool result = false;

            //Adds the appropriate starting node depending on specified player.
            if (isPlayerOne)
            {
                spaces.Push(new SearchNode(board.GetPlayerOnePos()));
            }
            else
            {
                spaces.Push(new SearchNode(board.GetPlayerTwoPos()));
            }



            while (spaces.Count != 0 && !result)
            {
                SearchNode currentNode = spaces.Pop();

                //Check the win conditions of the appropriate player.
                if (HasDirectPath(board, isPlayerOne, currentNode.space))
                {
                    result = true;
                    break;
                }

                //Get the possible moves from the space of the current node.
                List <string> movesFromSpace = board.GetAdjacentMoves(currentNode.space);
                //Adds the appropriate nodes to the stack to be searched.
                foreach (string move in movesFromSpace)
                {
                    if (!movesToBeVisited.Contains(move))
                    {
                        spaces.Push(new SearchNode(move, currentNode.depth));
                        movesToBeVisited.Add(move);
                    }
                }
            }
            return(result);
        }
Exemple #18
0
        //Finds shortest path for the chosen player to the end of the board and returns it.
        public static int FindShortestPath(AIBoard board, bool isPlayerOne)
        {
            Queue <SearchNode> spaces           = new Queue <SearchNode>();
            HashSet <string>   movesToBeVisited = new HashSet <string>();
            int result = -1;

            if (isPlayerOne)
            {
                spaces.Enqueue(new SearchNode(board.GetPlayerOnePos()));
            }
            else
            {
                spaces.Enqueue(new SearchNode(board.GetPlayerTwoPos()));
            }
            movesToBeVisited.Add(spaces.Peek().space);

            //Will exit after all paths return without finding end or
            //break out of loop when first path to finish is found.
            while (spaces.Count != 0 && result == -1)
            {
                SearchNode currentNode = spaces.Dequeue();

                //Checks for easy direct path
                if (HasDirectPath(board, isPlayerOne, currentNode.space))
                {
                    result = currentNode.depth + FindDirectDistance(currentNode.space, isPlayerOne);
                    break;
                }

                //Get a list of moves from the current node location.
                //If the node has not already been visited by this branch it is added to the queue.
                List <string> movesFromSpace = board.GetAdjacentMoves(currentNode.space);
                foreach (string move in movesFromSpace)
                {
                    if (!movesToBeVisited.Contains(move))
                    {
                        spaces.Enqueue(new SearchNode(move, currentNode.depth));
                        movesToBeVisited.Add(move);
                    }
                }
            }
            return(result);
        }
Exemple #19
0
        //Constructs a list of treenodes that result from every move made that is possible.
        //Pruning function (SetNodesOfInterest) will cut of many nodes that are not of interest.
        public List <TreeNode> GetChildren()
        {
            List <TreeNode> children = new List <TreeNode>();

            foreach (string move in Board.GetPawnMoves())
            {
                //This checks to make sure walls are valid
                AIBoard tempBoard = new AIBoard(Board);
                tempBoard.MakeMove(move);
                children.Add(new TreeNode(tempBoard, move));
            }

            //This gets only valid walls but is done here so that it will only check walls of interest.
            //This avoids checking if a ton of walls are valid that we don't care about.
            //This is why we do not just call GetWallMoves()
            if ((Board.GetIsPlayerOneTurn() && Board.GetPlayerOneNumWalls() == 0) ||
                (!Board.GetIsPlayerOneTurn() && Board.GetPlayerTwoNumWalls() == 0))
            {
            }
            else
            {
                HashSet <string> wallMoves = Board.GetAllValidWalls();
                SetNodesOfInterest(ref wallMoves);
                foreach (string wall in wallMoves)
                {
                    //This checks to make sure walls are valid
                    AIBoard tempBoard = new AIBoard(Board);
                    tempBoard.MakeMove(wall);
                    if (BoardAnalysis.CheckPathExists(tempBoard, true) && BoardAnalysis.CheckPathExists(tempBoard, false))
                    {
                        children.Add(new TreeNode(tempBoard, wall));
                    }
                }
            }

            //end of wall selection

            return(children);
        }
Exemple #20
0
        /// <summary>
        /// Heuristic evaluation of a board state for 'goodness'.
        /// </summary>
        private static int _score(AIBoard b, int code, int othercode)
        {
            // If b is in a game over state, return a score that represents a win or loss
            if (b.GameOver)
            {
                if (b.Count(code) > b.Count(othercode))
                {
                    return(int.MaxValue - 10);
                }
                else
                {
                    return(-(int.MaxValue - 10));
                }
            }

            // There are 3 major components to a good board state:
            //	- A small perimeter (not many spaces next to friendly pieces, which indicates a good structure)
            //	- The number of pieces within capturing range of an enemy
            //	- The friendly piece count
            int perimeter = 0, pieces = b.Count(code), vulnpieces = 0;

            // First find all friendly pieces
            foreach (var gp in b.GetPieces(code))
            {
                // For each space next to this piece empty, add to the perimeter sum.
                perimeter += b.EmptyAdjacent(gp.Item1, gp.Item2);

                // If piece can be captured, add to vulnerable pieces.
                if (b.IsVulnerable(gp.Item1, gp.Item2, othercode))
                {
                    vulnpieces++;
                }
            }

            // Bring together the scores and apply math to generate the best representative score of the board
            return(25 * pieces - 8 * vulnpieces - 2 * perimeter);            // Mess around with coefficients until ai works
        }
Exemple #21
0
    ScoringMove Test(AIBoard board, byte depth, int gamma)
    {
        // Devuelve el score del tablero y la jugada con la que se llega a él.
        List <MoveMarble> bestMove = new List <MoveMarble>();
        int bestScore = 0;

        ScoringMove scoringMove; // score, movimiento
        AIBoard     newBoard;
        Record      record;

        if (depth > maximumExploredDepth)
        {
            maximumExploredDepth = depth;
        }

        record = transpositionTable.GetRecord(board.hashValue);

        if (record != null)
        {
            if (record.depth > MAX_DEPTH - depth)
            {
                if (record.minScore > gamma)
                {
                    scoringMove = new ScoringMove(record.minScore, record.bestMove);
                    return(scoringMove);
                }

                if (record.maxScore < gamma)
                {
                    scoringMove = new ScoringMove(record.maxScore, record.bestMove);
                    return(scoringMove);
                }
            }
        }
        else
        {
            record           = new Record();
            record.hashValue = board.hashValue;
            record.depth     = MAX_DEPTH - depth;
            record.minScore  = MINUS_INFINITE;
            record.maxScore  = INFINITE;
        }

        // Comprobar si hemos terminado de hacer recursión
        if (board.IsEndOfGame() || depth == MAX_DEPTH)
        {
            if (depth % 2 == 0)
            {
                record.maxScore = board.Evaluate(activePlayer);
            }
            else
            {
                record.maxScore = -board.Evaluate(activePlayer);
            }

            record.minScore = record.maxScore;
            transpositionTable.SaveRecord(record);

            scoringMove = new ScoringMove(record.maxScore);
        }
        else
        {
            bestScore = MINUS_INFINITE;

            //modificar AIBoard.possibleMoves() para que devuelva los posibles movimientos
            List <MoveMarble>[] possibleMoves;
            possibleMoves = board.PossibleMoves();
            foreach (List <MoveMarble> move in possibleMoves)
            {
                //newBoard = board.GenerateNewBoardFromMove(move);
                newBoard = board.HashGenerateNewBoardFromMove(move);//cambiar

                // Recursividad
                scoringMove = Test(newBoard, (byte)(depth + 1), -gamma);

                int invertedScore = -scoringMove.score;

                // Actualizar mejor score
                if (invertedScore > bestScore)
                {
                    bestScore       = invertedScore;
                    bestMove        = move;//cambiar
                    record.bestMove = move;
                }

                if (bestScore < gamma)
                {
                    record.maxScore = bestScore;
                }
                else
                {
                    record.minScore = bestScore;
                }
            }
            transpositionTable.SaveRecord(record);
            scoringMove = new ScoringMove(bestScore, bestMove);
        }
        return(scoringMove);
    }
Exemple #22
0
        // Makes the AI choose and execute a move
        public override void MakeMove()
        {
            transTable.Clear();
            repetitionCheck.Clear();

            moveNum++;

            // Set up root of tree.
            this.gameTree.Root = new Tree <Move, AIBoard> .Node();

            this.workingBoard = new AIBoard(board);

            // TODO -
            int  best           = int.MinValue;
            int  adjusted_depth = SEARCH_DEPTH;
            Move move           = null;

            startT = DateTime.Now;
            for (int d = 1; d <= adjusted_depth; d++)
            {
                // Initialize state.
                List <Move> pv = new List <Move>();
                depthStart = DateTime.Now;
#if DEBUG
                nodeCnt = 0; transHits = 0; transCuts = 0; evalCalls = 0;
#endif

                // Perform bounded depth-first search for the best move score.
                best = -_search(this.gameTree.Root, d, -int.MaxValue, int.MaxValue, true, pv);

                // If we finished our last ply fast enough (<MAX_PLY_TIME), and we're not in mid-game, go for another.
                // If the game's over, though, don't bother.
                if (d == adjusted_depth && moveNum > 25 && (DateTime.Now - depthStart).TotalSeconds < MAX_PLY_TIME &&
                    best < 10000 && best > -10000)
                {
                    adjusted_depth++;
                }

                // WE GOT CALLED TO MAKE A MOVE BUT HAVE NO MOVES TO MAKE. WAT.
                if (this.gameTree.Root.Count == 0)
                {
                    return;
                }

                if (pv.Count > 0)
                {
                    move = pv[0];
                }
#if DEBUG
                _trace("[SEARCH] d={0}, n={1}, tHit={2} ({3}%), tCut={4} ({5}%), e={6} ({7}%)", d, nodeCnt, transHits,
                       Math.Round((double)transHits / nodeCnt, 2) * 100, transCuts,
                       Math.Round((double)transCuts / nodeCnt, 2) * 100, evalCalls,
                       Math.Round((double)evalCalls / nodeCnt, 2) * 100);
                _trace("         t={0}s ({1} n/s), PV={2}", Math.Round((DateTime.Now - depthStart).TotalMilliseconds / 1000, 3),
                       Math.Round(nodeCnt / ((DateTime.Now - depthStart).TotalMilliseconds / 1000), 0),
                       pv.Aggregate("", new Func <string, Move, string>((a, b) => a + b + " ")).Trim());
#endif
            }

            Debug.Assert(move != null, "No move! Endgame condition without our notification?");

#if DEBUG
            _trace("[EXEC] {0}", move);
#endif
            _executeMove(this.board, move, aicode, notaicode);
        }
Exemple #23
0
 //Used for creating a rootnode.
 //This will determine who the max player is for this node and all future children.
 //Max is equal to whose turn it is at this point.
 public TreeNode(AIBoard copy)
 {
     Board    = new AIBoard(copy);
     MoveMade = "rootnode";
     value    = 0;
 }
Exemple #24
0
 //Used in the creating of children of a treenode.
 public TreeNode(AIBoard copy, string move)
 {
     Board    = new AIBoard(copy);
     MoveMade = move;
     value    = 0;
 }
Exemple #25
0
 public HardAI()
 {
     CurrentBoard = new AIBoard();
 }
Exemple #26
0
 public AI()
 {
     CurrentBoard = new AIBoard();
     timer        = new Stopwatch();
 }