Пример #1
0
/*
 * Compute the next move given the opponent's last move. Your AI is
 * expected to keep track of the board on its own. If this is the first move,
 * or if the opponent passed on the last move, then opponentsMove will be NULL.
 *
 * msLeft represents the time your AI has left for the total game, in
 * milliseconds. doMove() must take no longer than msLeft, or your AI will
 * be disqualified! An msLeft value of -1 indicates no time limit.
 *
 * The move returned must be legal; if there are no valid moves for your side,
 * return NULL.
 */
Move *Player::doMove(Move *opponentsMove, int msLeft) {
    // add opponent's move to our board
    gameboard->doMove(opponentsMove, them);
    
    // print opponent move
    if (opponentsMove == NULL)
    {
        cerr << "PASS"<< endl;
    }
    else
    {
        cerr << "Opponent: " << opponentsMove->x << " " << opponentsMove->y << endl;
    }
    
    // implement Minimax
    if (testingMinimax) 
    {
        // make a vector of our moves at current depth
        vector<Move*> Movector = MakeMovector(*gameboard, us); 

        // check edge case
        if (Movector.empty())
        {
            return NULL;
        }

        // if moves exist
        else
        {
            int BestScore = -70; // want lowest value of score
            Move * BestMove = NULL;

            for (unsigned int i = 0; i < Movector.size(); i++)
            {
                Board * gameboardcopy = gameboard->copy();
                gameboardcopy->doMove(Movector[i], us);
                // should make sure to call even number depth
                int score = Minimax(gameboardcopy, them, 4, 1, -70, 70);
                if (score > BestScore)
                {
                    BestMove = Movector[i];
                    BestScore = score;
                }
            }

            // perform our move on our own board
            gameboard->doMove(BestMove, us);

            cerr << "Grace: " << BestMove->x << " " << BestMove->y << endl;
            return BestMove;
        }
    }

    // naive solution (working AI plays random valid moves)
    else 
    {
        if (gameboard->hasMoves(us))
        {
    		for (int i = 0; i < 8; i++) 
            {
                for (int j = 0; j < 8; j++) 
                {
                    Move move(i, j);
                    if (gameboard->checkMove(&move, us))
                    {
                        // perform our move on our own board
                        Move * iMove = new Move(i, j);
                        gameboard->doMove(iMove, us);
                        // return move to actual game
                        return iMove;
                    }
                }
            }
    	}
    }
    
    // shouldn't actually hit this case...
    // std::cerr << "Grace: idk" << std::endl; 
    return NULL;
}
Пример #2
0
/**
 * Get the compuer's input using the Minimax algorithm
 *
 * @param sf::Event event the event that the computer should handle, here it is
 * useless since the computer doesn;t use the mouse/keyboard to make a move
 * @param Board b the current board of the game
 *
 * @return std::pair<unsigned int, unsigned int> a position (row, col)
 * on the board where the computer's move should be made
 */
std::pair<unsigned int, unsigned int> AiPlayer::GetInput(sf::Event, Board b){
    return Minimax(b);
}
Пример #3
0
int Player::Minimax(Board * board, Side side, int depth, int CurrentDepth,
                        int alpha, int beta) {
    
    if (CurrentDepth == depth)
    {
        return FindBoardScore(*board, side);
    }

    // else
    vector<Move*> Movector = MakeMovector(*board, side);
    if (Movector.empty())
    {
        return FindBoardScore(*board, side);
    }

        // else

    // instead of switching checking for min / max every layer,
    // each recursive call looks 2 plays ahead and just returns the max
    if (CurrentDepth % 2 == 0) // parity 0, our side's move, maximize score
    {
        int BestScore = -70; 
        
        for (unsigned int i = 0; i < Movector.size(); i++)
        {
            // create an board one move into future
            Board * boardcopy = board->copy();
            boardcopy->doMove(Movector[i], side);
            
            Side nextside = (side == BLACK) ? WHITE : BLACK;
            
            // recursive call
            int score = Minimax(boardcopy, nextside, depth, CurrentDepth + 1, alpha, beta);
            // update if appropriate
            if (score > BestScore)
                BestScore = score;
            
            if (BestScore > alpha)
                alpha = BestScore;
            
            if (beta <= alpha) // abs(beta) <= alpha
                break;
        }
        return BestScore;
    }

    else // parity 1, opponent's move, minimize score
    {
        int WorstScore = 70;
        for (unsigned int i = 0; i < Movector.size(); i++)
        {
            // create an board one move into future
            Board * boardcopy = board->copy();
            boardcopy->doMove(Movector[i], side);

            Side nextside = (side == BLACK) ? WHITE : BLACK;
            // recursive call
            int score = Minimax(boardcopy, nextside, depth, CurrentDepth + 1, alpha, beta);
            // update if appropriate
            if (score < WorstScore)
            {
                WorstScore = score;
            }
            
            if (WorstScore < beta)
                beta = WorstScore;
                
            if (beta <= alpha) // abs(beta) >= alpha
                break;
        }
        return WorstScore;
    }
}