Exemple #1
0
    /// <summary>
    /// Gets a lightweight logical map of the board's current state.
    /// </summary>
    /// <returns>The board.</returns>
    public BGBoardMap GetBoardMap()
    {
        BGBoardMap boardMap = new BGBoardMap();

        foreach (Point point in Points)
        {
            boardMap.SetPoint(point.ID, ((point.Count == 0) ? BGPlayerID.None : point.CurrentChecker.Owner.ID), point.Count);
        }

        boardMap.SetPoint(HomeP1.ID, ((HomeP1.Count == 0) ? BGPlayerID.None : HomeP1.CurrentChecker.Owner.ID), HomeP1.Count);
        boardMap.SetPoint(HomeP2.ID, ((HomeP2.Count == 0) ? BGPlayerID.None : HomeP2.CurrentChecker.Owner.ID), HomeP2.Count);
        boardMap.SetPoint(JailP1.ID, ((JailP1.Count == 0) ? BGPlayerID.None : JailP1.CurrentChecker.Owner.ID), JailP1.Count);
        boardMap.SetPoint(JailP2.ID, ((JailP2.Count == 0) ? BGPlayerID.None : JailP2.CurrentChecker.Owner.ID), JailP2.Count);

        return(boardMap);
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="BGState"/> class.
    /// </summary>
    /// <param name="boardMap">Board map.</param>
    /// <param name="moveOptions">Move options.</param>
    /// <param name="diceRoll">Dice roll.</param>
    public BGState(BGBoardMap boardMap, BGMoveOptions moveOptions, BGDiceRoll diceRoll)
    {
        BoardMap   = boardMap;
        Moves      = new List <BGMove>();
        NextStates = new Dictionary <BGMove, BGState>();

        foreach (BGMove move in moveOptions.Moves)
        {
            BGBoardMap newBoardMap = boardMap.Copy();
            newBoardMap.Use(move);

            BGDiceRoll newDiceRoll = diceRoll.Copy();
            newDiceRoll.Use(move);

            BGMoveOptions newMoveOptions = new BGMoveOptions(BGPlayerID.Player2, newBoardMap, newDiceRoll);

            Moves.Add(move);
            NextStates[move] = new BGState(newBoardMap, newMoveOptions, newDiceRoll);
        }
    }
Exemple #3
0
 /// <summary>
 /// Gets the AI perceived value for the specified board.
 /// </summary>
 /// <param name="board"></param>
 /// <returns></returns>
 protected abstract float GetScore(BGBoardMap board);
Exemple #4
0
    /// <summary>
    /// Determines which move to use given the current board map, move options and available dice rolls.
    /// </summary>
    /// <param name="boardMap"></param>
    /// <param name="moveOptions"></param>
    /// <returns></returns>
    public List <BGMove> GetMove(BGBoardMap boardMap, BGMoveOptions moveOptions, BGDiceRoll diceRoll)
    {
        Evaluate(new BGState(boardMap, moveOptions, diceRoll));

        return(m_BestMoves);
    }
Exemple #5
0
    /// <summary>
    /// Gets the AI perceived value for the specified board.
    /// </summary>
    /// <param name="board"></param>
    /// <returns></returns>
    protected override float GetScore(BGBoardMap board)
    {
        if (board.IsRunOut())
        {
            // If the board is a run out:
            //  1) Focus on getting checkers into the inner board as fast as possible and pick up as many checkers as possible.
            //  2) Penalize the score severely for each checker outside the inner table.
            //     - The farther away the checker is, the more severe the penalty.

            float score = 2000000;

            score += (board.GetPoint(BGPointID.HomeP2).Count * 10000);

            for (BGPointID id = BGPointID.Point24; id >= BGPointID.Point19; id--)
            {
                BGPoint point = board.GetPoint(id);

                if (point.Player == BGPlayerID.Player2)
                {
                    score += (point.Count * Mathf.Pow((int)id, 2));
                }
            }

            for (BGPointID id = BGPointID.Point18; id >= BGPointID.Point7; id--)
            {
                BGPoint point = board.GetPoint(id);

                if (point.Player == BGPlayerID.Player2)
                {
                    score -= (10 * point.Count * Mathf.Pow(24 + (int)(BGPointID.Point18 - id), 2));
                }
            }

            for (BGPointID id = BGPointID.Point6; id >= BGPointID.Point1; id--)
            {
                BGPoint point = board.GetPoint(id);

                if (point.Player == BGPlayerID.Player2)
                {
                    score -= (100 * point.Count * Mathf.Pow(24 + (17 - (int)id), 2));
                }
            }

            return(score);
        }
        else if (board.CanBearOff(BGPlayerID.Player2))
        {
            // If player 2 can bear off:
            //  1) Focus on picking up as many checkers as possible.
            //  2) If player 1 is jailed, penalize the score severely for each vulnerable checker.

            float score = 1000000;

            score += (board.GetPoint(BGPointID.HomeP2).Count * 10000);

            for (BGPointID id = BGPointID.Point24; id >= BGPointID.Point19; id--)
            {
                BGPoint point = board.GetPoint(id);

                if (point.Player == BGPlayerID.Player2)
                {
                    if (point.Count == 1 && board.GetJail(BGPlayerID.Player1).Count > 0)
                    {
                        score -= (10000 * point.Count * Mathf.Pow((int)id, 2));
                    }
                    else
                    {
                        score += (point.Count * Mathf.Pow((int)id, 2));
                    }
                }
            }

            return(score);
        }
        else
        {
            float score         = 0;
            int   stackingPower = 0;

            for (BGPointID id = BGPointID.Point24; id >= BGPointID.Point1; id--)
            {
                BGPoint point = board.GetPoint(id);

                if (point.Player == BGPlayerID.Player2)
                {
                    if (point.Count > 2)
                    {
                        stackingPower++;
                        score += Mathf.Pow((int)id, 2);
                    }
                    else if (point.Count == 2)
                    {
                        stackingPower++;
                        score += (5 * Mathf.Pow((int)id, 2));
                    }
                    else if (point.Count == 1)
                    {
                        score -= (10 * Mathf.Pow((int)id, 2) * board.GetVulnerability(point.ID));
                    }
                }
                else if (point.Player == BGPlayerID.Player1)
                {
                    if (point.Count == 1)
                    {
                        score -= Mathf.Pow(BGPointID.Point24 - id, 2);
                    }
                }

                if (!(point.Player == BGPlayerID.Player2 && point.Count >= 2))
                {
                    if (stackingPower > 1)
                    {
                        score += (Mathf.Pow(stackingPower - 1, 2) * 1000);
                    }

                    stackingPower = 0;
                }
            }

            score += (board.GetPoint(BGPointID.HomeP2).Count * 10000);

            return(score);
        }
    }
    /// <summary>
    /// Gets a list of all moves that can be made for the specified player with the specified board and dice roll.
    /// </summary>
    private List <BGMove> GetMoves(BGPlayerID player, BGBoardMap board, BGDiceRoll diceRoll)
    {
        List <BGMove> moves = new List <BGMove>();

        if (player == BGPlayerID.None)
        {
            return(moves);
        }

        BGPoint home = board.GetHome(player);
        BGPoint jail = board.GetJail(player);

        BGPoint[] innerTable = board.GetInnerTable(player);
        BGPoint[] outerTable = board.GetOuterTable(player);

        // Find available moves.

        if (jail.Count > 0)
        {
            for (int roll = 1; roll <= 6; roll++)
            {
                if (diceRoll.CanUse(roll) && !outerTable[roll - 1].IsBlocking(player))
                {
                    moves.Add(new BGMove(jail, outerTable[roll - 1], roll));
                }
            }
        }
        else
        {
            for (int roll = 1; roll <= 6; roll++)
            {
                if (diceRoll.CanUse(roll))
                {
                    for (BGPointID point = BGPointID.Point1; point <= BGPointID.Point24; point++)
                    {
                        BGPoint from = board.GetPoint(point);

                        if (from.IsOccupiedBy(player))
                        {
                            BGPoint to = null;

                            if (player == BGPlayerID.Player1 && ((point - roll) >= BGPointID.Point1))
                            {
                                to = board.GetPoint(point - roll);
                            }
                            else if (player == BGPlayerID.Player2 && ((point + roll) <= BGPointID.Point24))
                            {
                                to = board.GetPoint(point + roll);
                            }

                            if (to != null && !to.IsBlocking(player))
                            {
                                moves.Add(new BGMove(from, to, roll));
                            }
                        }
                    }
                }
            }

            if (!outerTable.Any(point => point.IsOccupiedBy(player)))
            {
                // Get max distance from home.

                int maxDistance = 0;

                for (int i = 0; i < innerTable.Length; i++)
                {
                    if (innerTable[i].IsOccupiedBy(player))
                    {
                        maxDistance = i + 1;
                    }
                }

                // Find moves that can be used to bear off.

                for (int roll = 1; roll <= 6; roll++)
                {
                    if (diceRoll.CanUse(roll))
                    {
                        if (innerTable[roll - 1].IsOccupiedBy(player))
                        {
                            moves.Add(new BGMove(innerTable[roll - 1], home, roll));
                        }
                        else if (maxDistance > 0 && innerTable[maxDistance - 1].IsOccupiedBy(player) && roll >= maxDistance)
                        {
                            moves.Add(new BGMove(innerTable[maxDistance - 1], home, roll));
                        }
                    }
                }
            }
        }

        return(moves);
    }