/// <summary>
        /// Gets all the possible nodes for a given position
        /// </summary>
        /// <param name="position">Positional node</param>
        public List <PositionNode> GetNodes(Position position, sbyte team)
        {
            List <PositionNode> nodes = new List <PositionNode>();

            sbyte winner = -1;

            if (position.IsWon(out winner))
            {
                return(nodes);
            }

            DiceRoll[] rolls = GetRollsQueue(position, team);
            for (int r = 0; r < rolls.Length; r++)
            {
                MoveCollection collection = GetMoves(position, rolls[r], team);
                if (collection != null)
                {
                    PositionNode[] pnodes = new PositionNode[collection.Count];
                    for (int i = 0; i < collection.Count; i++)
                    {
                        Position node = position.Clone();
                        PerformMove(node, collection[i]);

                        pnodes[i] = new PositionNode(node, collection[i], rolls[r]);
                    }

                    nodes.AddRange(pnodes);
                }
            }

            return(nodes);
        }
        /// <summary>
        /// Thinks about the current position given the dice roll and calculates the best move
        /// </summary>
        /// <param name="algorithm">Evaluation algorithm to use</param>
        /// <param name="roll">Roll</param>
        /// <param name="team">Team to think for</param>
        /// <param name="depth">Depth to think</param>
        public Move ThinkBest(Algorithm algorithm, DiceRoll roll, sbyte team, int ms)
        {
            MoveCollection collection = GetMoves(roll, team);

            if (collection.Count == 0)
            {
                return(null);
            }
            else if (collection.Count == 1)
            {
                return(collection[0]);
            }
            else if (ms < 0)
            {
                return(collection[random.Next(collection.Count)]);
            }

            PositionNode[] nodes = new PositionNode[collection.Count];
            for (int i = 0; i < collection.Count; i++)
            {
                Position node = new Position(this.quadrants);
                PerformMove(node, collection[i]);

                nodes[i] = new PositionNode(node, collection[i], roll);
            }

            algorithm.Player = team;
            Vector4[] evaluations = new Vector4[nodes.Length];
            for (int j = 0; j < nodes.Length; j++)
            {
                PositionNode currentRootMoveNode = nodes[j];
                algorithm.Root = currentRootMoveNode;

                Vector4 moveEval = algorithm.Go(ms / collection.Count);
                evaluations[j] = moveEval;
            }

            int    highIndex = 0;
            double high      = evaluations[0].GetMagnitude(team);

            for (int i = 1; i < evaluations.Length; i++)
            {
                double curMag = evaluations[i].GetMagnitude(team);
                if (curMag > high)
                {
                    high      = curMag;
                    highIndex = i;
                }
            }

            return(collection[highIndex]);
        }
        /// <summary>
        /// Checks if the move is a possible move for a human (called by Engine)
        /// </summary>
        /// <param name="move">Move move</param>
        public bool IsPossibleMove(DiceRoll roll, Move move, out Move orderCorrect)
        {
            MoveCollection collection = GetMoves(roll, move.Team);

            for (int j = 0; j < collection.Count; j++)
            {
                if (collection[j].Equals(move))
                {
                    orderCorrect = collection[j];
                    return(true);
                }
            }

            orderCorrect = null;
            return(false);
        }
        public MoveCollection ThinkAll(Algorithm algorithm, DiceRoll roll, sbyte team, int ms, out Vector4[] scores)
        {
            MoveCollection collection = GetMoves(roll, team);

            if (collection.Count == 0)
            {
                scores = null;
                return(null);
            }
            else if (collection.Count == 1)
            {
                scores = new Vector4[1] {
                    algorithm.Eval(this.GetPosition(), roll.IsDoubles() ? team : Board.NO_PLAYER)
                };
                return(collection);
            }
            if (ms < 0)
            {
                throw new ArgumentException();
            }

            PositionNode[] nodes = new PositionNode[collection.Count];
            for (int i = 0; i < collection.Count; i++)
            {
                Position node = new Position(this.quadrants);
                PerformMove(node, collection[i]);

                nodes[i] = new PositionNode(node, collection[i], roll);
            }

            algorithm.Player = team;
            Vector4[] evaluations = new Vector4[nodes.Length];
            for (int j = 0; j < nodes.Length; j++)
            {
                PositionNode currentRootMoveNode = nodes[j];
                algorithm.Root = currentRootMoveNode;

                Vector4 moveEval = algorithm.Go(ms / collection.Count);
                evaluations[j] = moveEval;
            }

            SortDecreasing(evaluations, collection, team);
            scores = evaluations;
            return(collection);
        }
        /// <summary>
        /// Checks if the piece move is part of a valid move
        /// </summary>
        /// <param name="roll">Current roll</param>
        /// <param name="move">Move to check</param>
        /// <param name="team">Team</param>
        public bool IsPossibleTreeMove(DiceRoll roll, PieceMove move, sbyte team)
        {
            MoveCollection collection = GetMoves(roll, team);

            for (int j = 0; j < collection.Count; j++)
            {
                PieceMove[] moves = collection[j].PieceMoves;
                for (int i = 0; i < moves.Length; i++)
                {
                    if (moves[i].Equals(move))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Starts thinking
        /// </summary>
        public void Think(DiceRoll roll, Board board)
        {
            int       timeThink = Difficulty.TimeThink;
            Algorithm algorithm = GetAlgorithm();

            if (timeThink < 0)
            {
                base.SetMove(board.ThinkBest(algorithm, roll, Team, timeThink));
                return;
            }

            int blunderValue = Board.Next(100);

            if (blunderValue < Difficulty.BlunderPercent)
            {
                //Worst move
                Vector4[]      scores;
                MoveCollection moves = board.ThinkAll(algorithm, roll, Team, ComputerPlayer.Difficulties[ComputerPlayer.Difficulties.Length - 1].TimeThink, out scores);
                LastEvaluation = GetVariations(moves, scores);

                if (moves != null)
                {
                    base.SetMove(moves[moves.Count - 1]);
                    return;
                }
            }
            else
            {
                //Best move
                Vector4[]      scores;
                MoveCollection moves = board.ThinkAll(algorithm, roll, Team, Difficulty.TimeThink, out scores);
                LastEvaluation = GetVariations(moves, scores);

                if (moves != null)
                {
                    base.SetMove(moves[0]);
                    return;
                }
            }

            base.SetMove(null);
        }
        /// <summary>
        /// Stable insertion sort
        /// </summary>
        /// <param name="input">Input of move evaluations</param>
        /// <param name="collection">Move values</param>
        /// <param name="team">Team to sort by</param>
        private void SortDecreasing(Vector4[] input, MoveCollection collection, sbyte team)
        {
            for (int i = 1; i < input.Length; i++)
            {
                double  key       = input[i].GetMagnitude(team);
                Vector4 keyValue  = input[i];
                Move    moveValue = collection[i];

                int j = i - 1;
                while (j >= 0 && input[j].GetMagnitude(team) < key)
                {
                    input[j + 1]      = input[j];
                    collection[j + 1] = collection[j];
                    j--;
                }

                input[j + 1]      = keyValue;
                collection[j + 1] = moveValue;
            }
        }
        private Variation[] GetVariations(MoveCollection moves, Vector4[] scores)
        {
            if (scores == null)
            {
                return(null);
            }

            if (moves.Count != scores.Length)
            {
                throw new ArgumentException();
            }

            Variation[] vars = new Variation[moves.Count];
            for (int i = 0; i < moves.Count; i++)
            {
                vars[i] = new Variation(moves[i], scores[i]);
            }

            return(vars);
        }
Exemple #9
0
        private double Iterate(Position pos, sbyte us, sbyte evaluating_team, int time)
        {
            Stopwatch sw = Stopwatch.StartNew();

            double wins   = 0;
            double losses = 0;

            Board board = new Board();

            sbyte team = NextTeam(us);

            int   doublesCount = 0;
            sbyte lastTeam     = 0;

            int turns = 0;

            do
            {
                //Reset board
                board.SetPosition(pos);

                //Pick random nodes and play out game
                while (!board.IsGameOver())
                {
                    lastTeam = team;

                    DiceRoll roll = board.GetRandomRoll();

                    MoveCollection moves = board.GetMoves(roll, team);

                    if (moves.Count != 0)
                    {
                        Move m = moves[Board.Next(moves.Count)];
                        if (m != null)
                        {
                            board.PerformMove(m);
                        }
                    }

                    if (roll.IsDoubles())
                    {
                        doublesCount++;
                        if (doublesCount >= 3)
                        {
                            board.RemoveFrontMarble(team);
                            doublesCount = 0;
                            team         = board.NextPlayer(team);
                            turns++;
                        }
                    }
                    else
                    {
                        doublesCount = 0;
                        team         = board.NextPlayer(team);
                        turns++;
                    }
                }

                if (lastTeam == evaluating_team)
                {
                    wins++;
                }
                else
                {
                    losses++;
                }
            }while (sw.ElapsedMilliseconds < time);

            return(wins / losses);
        }
Exemple #10
0
        /// <summary>
        /// Gets all the possible moves for a team given a dice roll
        /// </summary>
        /// <param name="roll">Dice roll</param>
        /// <param name="team">Marble team</param>
        public MoveCollection GetMoves(Position position, DiceRoll roll, sbyte team)
        {
            if (team < 0 || team > TEAM_COUNT)
            {
                return(null);
            }

            sbyte winner = -1;

            if (position.IsWon(out winner))
            {
                return(null);
            }

            MoveCollection moves = new MoveCollection(this, position);

            Square[] marbleSquares = GetMarbles(position, team);

            bool hasMarbleOnSpawn = position.Get(new Square(team, 0)) == team;
            int  activePieces     = GetActivePiecesCount(marbleSquares);

            //Loop until a marble in our base is found
            for (int i = 0; i < marbleSquares.Length; i++)
            {
                //If marble is at start square
                if (marbleSquares[i] == null)
                {
                    //If no team marble is on spawn square
                    if (!hasMarbleOnSpawn)
                    {
                        int[] takeOut = roll.CanTakeOutWith();
                        if (takeOut.Length > 0)
                        {
                            for (int j = 0; j < takeOut.Length; j++)
                            {
                                Square target = new Square(team, takeOut[j]);
                                if (position.Get(target) != team)
                                {
                                    moves.Add(new Move(new PieceMove(null, target), team));
                                }
                            }
                        }
                    }

                    //Add a special case for taking out a piece and using the other die value on another marble
                    if (activePieces > 0)
                    {
                        int[]     combinations = roll.GetDoublesTakeOutCombinations();
                        PieceMove takeOutCombo = new PieceMove(null, new Square(team, 0));
                        for (int p = 0; p < activePieces; p++)
                        {
                            for (int pc = 0; pc < combinations.Length; pc++)
                            {
                                PieceMove correspondant = new PieceMove(marbleSquares[p], marbleSquares[p].Add(combinations[pc], team));

                                if (hasMarbleOnSpawn && !correspondant.From.Equals(takeOutCombo.To))
                                {
                                    continue;
                                }

                                moves.Add(new Move(new PieceMove[] { correspondant, takeOutCombo }, team));
                            }
                        }
                    }

                    break;
                }
            }

            List <int[]> pieceCombinations = GetPieceCombinations(activePieces);

            for (int c = 0; c < pieceCombinations.Count; c++)
            {
                int     pieces      = pieceCombinations[c].Length;
                int[][] pieceValues = roll.GetValues(pieces);
                for (int k = 0; k < pieceValues.Length; k++)
                {
                    PieceMove[] pieceMoves = new PieceMove[pieces];

                    for (int j = 0; j < pieces; j++)
                    {
                        Square marblePiece = marbleSquares[pieceCombinations[c][j]];
                        pieceMoves[j] = new PieceMove(marblePiece, marblePiece.Add(pieceValues[k][j], team));

                        if (j > 0)
                        {
                            if (pieceMoves[j].From.Equals(pieceMoves[j - 1].To))
                            {
                                //Swap the move order
                                PieceMove current = pieceMoves[j];
                                pieceMoves[j]     = pieceMoves[j - 1];
                                pieceMoves[j - 1] = current;
                            }
                        }
                    }

                    Move move = new Move(pieceMoves, team);
                    moves.Add(move);
                }
            }

            return(moves);
        }
Exemple #11
0
        /// <summary>
        /// Updates the view of the board
        /// </summary>
        /// <param name="gameTime">Current GameTime</param>
        public void Update(GameTime gameTime)
        {
            //Update logic
            KeyboardState kState = Keyboard.GetState();
            MouseState    mState = MouseHandle.GetState();

            //Updates squares
            UpdateSquares();

            if (Playing)
            {
                //Update current animation
                if (currentAnimation != null)
                {
                    currentAnimation.Update(gameTime);
                }

                if (kState.IsKeyDown(Keys.Q) && rollOver)
                {
                    for (int i = 0; i < currentMove.Count; i++)
                    {
                        if (currentMove[i].IsTakingOutMarble)
                        {
                            PutBackMarble(currentPlayer.Team);
                        }
                    }

                    RemoveMove();
                }

                if (!currentPlayer.IsThinking && CanRoll())
                {
                    if (!currentPlayer.IsHuman)
                    {
                        rollOver = false;
                        RollDice(gameTime);
                    }
                    else if (!isDiceRolling && kState.IsKeyDown(Keys.R)) //Check for user starting a roll
                    {
                        rollOver = false;
                        RollDice(gameTime);
                    }
                }

                //Check if dice are done rolling
                if (die1 != -1 && die2 != -1 && !rollOver)
                {
                    currentRoll = new DiceRoll(die1, die2);
                    OnRollFinished();
                }

                //Check if dice have rolled for too long
                if (rollStartTime.HasValue)
                {
                    TimeSpan timeElapsed   = gameTime.TotalGameTime.Subtract(rollStartTime.Value);
                    double   timeElapsedMs = timeElapsed.TotalMilliseconds;
                    if (timeElapsedMs >= 10000)
                    {
                        StopDice();
                        UpdateDie(die1Body, ref die1, true);
                        UpdateDie(die2Body, ref die2, true);

                        if (die1 != -1 && die2 != -1)
                        {
                            currentRoll = new DiceRoll(die1, die2);
                            OnRollFinished();
                        }
                    }
                }

                //If the player is a human and hasnt rolled yet, disallow any movement of marbles
                if (!CanRoll())
                {
                    //Update drag
                    UpdateDrag(mState);

                    ////Handle user submitting move
                    if (rollOver && kState.IsKeyDown(Keys.Enter) && currentPlayer.IsHuman)
                    {
                        if (!HasMove)
                        {
                            //Pressed enter without making a move
                            MoveCollection collection = board.GetMoves(currentRoll, currentPlayer.Team);

                            if (collection.Count == 0)
                            {
                                //End the player step
                                ProcessRoll();
                                SetReadyForRoll();
                                //
                            }
                        }
                        else
                        {
                            if (currentRoll == null)
                            {
                                RemoveMove();
                            }
                            else
                            {
                                Move move = GetMove(currentPlayer.Team);
                                if (board.IsPossibleMove(currentRoll, move, out move))
                                {
                                    currentPlayer.SetMove(move);
                                }
                                else
                                {
                                    for (int i = 0; i < currentMove.Count; i++)
                                    {
                                        if (currentMove[i].IsTakingOutMarble)
                                        {
                                            PutBackMarble(currentPlayer.Team);
                                        }
                                    }

                                    RemoveMove();
                                }
                            }
                        }
                    }
                }

                if (currentPlayer.HasMove)
                {
                    OnMoveFound(currentPlayer.GetMove());
                }

                //Update dice
                UpdateDie(die1Body, ref die1, IsNearlyZero(die1Body.LinearVelocity));
                UpdateDie(die2Body, ref die2, IsNearlyZero(die2Body.LinearVelocity));

                if (!Resizing)
                {
                    world.Step(1 / 30f, false);
                    //world.Step((float)gameTime.TotalGameTime.TotalSeconds, false, (float)gameTime.ElapsedGameTime.TotalSeconds, 1);
                }
            }
        }