示例#1
0
 // the public interface to other classes, kicks off threaded
 // task, then returns to caller. caller polls AI.Done to see
 // if threaded task is done
 public void SelectMove(GameBoard board)
 {
     m_Done = false;
     m_Move = 0;
     m_Status = 0;
     m_ThreadParam.Board = board;
     m_ThreadParam.Depth = Depth;
     Thread task = new Thread(SelectMoveTask);
     task.Start();
 }
        // examine every valid move, trying to maximize Player.One's score
        private int Max(GameBoard board, int depth, int alpha, int beta, ref int move)
        {
            // have we recursed far enough?
            if (depth <= 0)
            {
                return Evaluate(board);
            }

            for (int index = 0; index < board.ValidMoves.Count; index++)
            {
                // report status if we're at top-most recursion depth
                if (depth == Depth)
                {
                    m_Status = (double)index / (double)board.ValidMoves.Count;
                }

                // copy current board
                GameBoard board2 = new GameBoard(board);
                // make move based on ValidMoves[index]
                board2.MakeMove(index);

                // get best move that opponent can make
                int val = Min(board2, depth - 1, alpha, beta, ref move);

                if (val >= beta)
                {
                    // already found a better branch than this can possibly be
                    return beta;
                }

                if (val > alpha)
                {
                    // found a better score!
                    alpha = val;
                    if (depth == Depth)
                    {
                        // udpate move if this is top-level
                        move = index;
                    }
                }
            }

            // return best score found
            return alpha;
        }
示例#3
0
        // called by base class from seperate thread
        protected override int SelectMoveRecursive(GameBoard board, int depth)
        {
            // assume first move is the best
            int move = 0;

            // best score, based on player
            if (board.CurrentPlayer == Player.One)
            {
                move = FindBestMove(board, true, int.MinValue);
            }
            else if (board.CurrentPlayer == Player.Two)
            {
                move = FindBestMove(board, false, int.MaxValue);
            }

            // return selected move
            return move;
        }
示例#4
0
        // called by base class from seperate thread
        protected override int SelectMoveRecursive(GameBoard board, int depth)
        {
            // default to the first valid move
            int move = 0;

            // select min or max method based on player
            if (board.CurrentPlayer == Player.One)
            {
                int score = Max(board, Depth, ref move);
            }
            else if (board.CurrentPlayer == Player.Two)
            {
                int score = Min(board, Depth, ref move);
            }

            // return selected move (may have been updated by Min or Max)
            return move;
        }
示例#5
0
        // examine every valid move, trying to maximize Player.One's score
        private int Max(GameBoard board, int depth, ref int move)
        {
            // have we recursed far enough?
            if (depth <= 0)
            {
                return Evaluate(board);
            }

            // start with rediculously low score so that first
            // inspection will result in a match
            int score = int.MinValue;

            // for each ValidMove ...
            for (int index = 0; index < board.ValidMoves.Count; index++)
            {
                // report status if we're at top-most recursion depth
                if (depth == Depth)
                {
                    m_Status = (double)index / (double)board.ValidMoves.Count;
                }
                // copy current board
                GameBoard board2 = new GameBoard(board);
                // make move based on ValidMoves[index]
                board2.MakeMove(index);

                // get best move that opponent can make
                int val = Min(board2, depth - 1, ref move);
                if (val > score)
                {
                    // found a better score!
                    score = val;
                    if (depth == Depth)
                    {
                        // udpate move if this is top-level
                        move = index;
                    }
                }
            }

            // return best score found
            return score;
        }
示例#6
0
        protected int FindBestMove(GameBoard board, bool isPlayerOne, int score)
        {
            // assume first move is the best
            int move = 0;

            // scan valid moves, looking for best score
            for (int index = 0; index < board.ValidMoves.Count; index++)
            {
                // create copy of current board to play with
                GameBoard board2 = new GameBoard(board);

                // make the next valid move
                board2.MakeMove(index);

                // what's the score?
                int val = Evaluate(board2);

                // best score for player one is positive,
                // best score for player two is negative
                if (isPlayerOne)
                {
                    if (val > score)
                    {
                        score = val;
                        move = index;
                    }
                }
                else
                {
                    if (val < score)
                    {
                        score = val;
                        move = index;
                    }
                }
            }

            // report findings to the caller
            return move;
        }
        // called by base class from seperate thread
        protected override int SelectMoveRecursive(GameBoard board, int depth)
        {
            // default to the first valid move
            int move = 0;

            // select min or max method based on player
            if (board.CurrentPlayer == Player.One)
            {
                // start with rediculously low alpha and high beta so that first
                // inspection will result in a match
                int score = Max(board, Depth, int.MinValue, int.MaxValue, ref move);
            }
            else if (board.CurrentPlayer == Player.Two)
            {
                // start with rediculously low alpha and high beta so that first
                // inspection will result in a match
                int score = Min(board, Depth, int.MinValue, int.MaxValue, ref move);
            }

            // return selected move (may have been updated by Min or Max)
            return move;
        }
示例#8
0
 // copy another board's state data to this board
 public void Copy(GameBoard board)
 {
     InitGrid(board.GridWidth, board.GridHeight);
     for (int y = 0; y < GridHeight; y++)
     {
         for (int x = 0; x < GridWidth; x++)
         {
             Grid[x, y] = board.Grid[x, y];
         }
     }
     CurrentPlayer = board.CurrentPlayer;
     UpdateListOfValidMoves();
 }
示例#9
0
 // copy constructor
 public GameBoard(GameBoard board)
 {
     Copy(board);
 }
示例#10
0
 // as simple as AI gets -- random selection
 protected override int SelectMoveRecursive(GameBoard board, int depth)
 {
     // randomly select a move from the list of valid moves
     return m_rand.Next(board.ValidMoves.Count);
 }
示例#11
0
        // actually process the input
        private void ProcessInput(GamePadState pad, KeyboardState kbd)
        {
            bool pressed;

            // move to previous valid move
            pressed = pad.Triggers.Left > 0;
            pressed |= pad.DPad.Left == ButtonState.Pressed;
            pressed |= pad.ThumbSticks.Left.X < 0;
            pressed |= kbd.IsKeyDown(Keys.Left);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard.PreviousValidMove();
            }

            // move to next valid move
            pressed = pad.Triggers.Right > 0;
            pressed |= pad.DPad.Right == ButtonState.Pressed;
            pressed |= pad.ThumbSticks.Left.X > 0;
            pressed |= kbd.IsKeyDown(Keys.Right);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard.NextValidMove();
            }

            // commit selection as your move
            pressed = pad.Buttons.A == ButtonState.Pressed;
            pressed |= kbd.IsKeyDown(Keys.Space);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard.MakeMove();
            }

            // start a new game
            // only works when it's a human's turn so that AI threads
            // (if any) have time to complete
            pressed = pad.Buttons.Start == ButtonState.Pressed;
            pressed |= kbd.IsKeyDown(Keys.Enter);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard = new GameBoard();
            }

            // pick previous player two type
            pressed = pad.Buttons.LeftShoulder == ButtonState.Pressed;
            pressed |= kbd.IsKeyDown(Keys.PageUp);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard.PreviousPlayerType();
            }

            // pick next player two type
            pressed = pad.Buttons.RightShoulder == ButtonState.Pressed;
            pressed |= kbd.IsKeyDown(Keys.PageDown);
            if (pressed && m_PressDelay <= 0)
            {
                m_PressDelay = PRESS_DELAY;
                m_GameBoard.NextPlayerType();
            }
        }
示例#12
0
 // helper method to generate a simple heuristic for a given GameBoard
 // add 1 for each piece owned by Player.One, subtract 1 for each piece
 // owned by Player.Two. Larger sums favor Player.One, smaller sums
 // favor Player.Two.
 protected int Evaluate(GameBoard board)
 {
     return board.Score(Player.One) - board.Score(Player.Two);
 }
示例#13
0
 // this method must be implemented by any actual AIs that derive
 // from this base class. the threaded method calls this method,
 // which only exists in derived classes. that way, this base
 // class can handle the nitty-gritty threading and synchronization
 // tasks, and leave the actual AI processing to the derived classes.
 protected abstract int SelectMoveRecursive(GameBoard board, int depth);