//calculate the heuristic value of a game state with respect to a specific player int GameHeuristic( const GameState& game, int forwhom, const int* heuristic ) const { int result; result = ChangeHeuristic(game.GetPlayerChange( forwhom ), heuristic ); int best = std::numeric_limits<int>::min(); for(int i=0;i!=game.GetPlayerCount();++i){ if (i!=forwhom){ int score = ChangeHeuristic( game.GetPlayerChange( i ), heuristic ); if (score>best){ best = score; } } } return result - best; }
//Get Best Move - //recursive min/max algorithm explores game states and //returns a move and its score, for a specific player MoveScore GetBestMove( const GameState& theGame, const int player_index, int abPrune, const int recursive=1) { const Change& player_change = theGame.GetPlayerChange( theGame.GetCurrentPlayer() ); const Change& pool = theGame.GetGameChange(); int bestScore = (player_index == theGame.GetCurrentPlayer())? std::numeric_limits<int>::min() : std::numeric_limits<int>::max(); Coin bestCoin; Change bestChange; Change::List* someChange; if (recycledChangeLists.empty()){ someChange = new Change::List; } else{ someChange = recycledChangeLists.back(); recycledChangeLists.pop_back(); } //for each coin that can be played for (const Coin *ci=&COINLIST[0];ci!=&COINLIST[COIN_COUNT];++ci){ if (player_change.GetCount(*ci) > 0){ //get all possible sets of change into array GetAllPossibleChange( pool, *ci, *someChange); //for each possible set of change //(reversed iteration improves AB prune by as much as 70%) const Change::List::reverse_iterator end = someChange->rend(); for(Change::List::reverse_iterator i = someChange->rbegin();i!=end;++i){ //create "move" from coin to give, and change to take const Move myMove(*ci,*i); //create gamestate once the move has been played GameState newGame = theGame.PlayMove( myMove ); //get "score" for this move int score; if (recursive>0 && newGame.GetActivePlayers()>1){ //recursivly examine move, get its score score = GetBestMove( newGame, player_index, bestScore, recursive-1).score; } else{ //leaf node - just get heuristic value score = GameHeuristic( newGame, player_index, myHeuristic ); } //Min/Max search if ((player_index == theGame.GetCurrentPlayer() && score > bestScore) || (player_index != theGame.GetCurrentPlayer() && score < bestScore)) { bestScore = score; bestCoin = *ci; bestChange = *i; //Alpha/Beta pruning if ((player_index == theGame.GetCurrentPlayer() && score > abPrune) || (player_index != theGame.GetCurrentPlayer() && score < abPrune)){ goto exit; } } } } } exit: recycledChangeLists.push_back( someChange ); return MoveScore( Move( bestCoin, bestChange ), bestScore ); }