Results: new MasterResults implementation, using the MoveSelector class.

This avoids calling MoveSelector everywhere in the code.
This commit is contained in:
Olivier Teulière 2013-01-17 18:39:03 +01:00
parent adc60c868f
commit 30385abe30
6 changed files with 72 additions and 19 deletions

View file

@ -38,7 +38,6 @@
#include "move.h"
#include "pldrack.h"
#include "results.h"
#include "move_selector.h"
#include "player.h"
#include "cmd/player_move_cmd.h"
#include "cmd/player_rack_cmd.h"
@ -276,7 +275,7 @@ void Duplicate::endTurn()
{
// If nobody played a valid round, we are forced to play a valid move.
// So let's take the best one...
BestResults results;
MasterResults results(getBag());
// Take the first player's rack
const Rack &rack =
m_players[REF_PLAYER_ID]->getLastRack().getRack();
@ -288,9 +287,7 @@ void Duplicate::endTurn()
throw EndGameException(_("No possible move"));
}
// Select a clever master move if possible
MoveSelector selector;
setMasterMove(Move(selector.selectMaster(results)));
setMasterMove(Move(results.get(0)));
}
}

View file

@ -37,7 +37,6 @@
#include "round.h"
#include "pldrack.h"
#include "results.h"
#include "move_selector.h"
#include "player.h"
#include "game.h"
#include "turn_data.h"
@ -452,15 +451,14 @@ PlayedRack Game::helperSetRackRandom(const PlayedRack &iPld,
{
const Rack &rack = pld.getRack();
BestResults res;
MasterResults res(getBag());
res.search(getDic(), getBoard(), rack, getHistory().beforeFirstRound());
if (!res.isEmpty())
{
PlayedRack pldCopy = pld;
// Get the best word
MoveSelector selector;
const Round & bestRound = selector.selectMaster(res);
const Round & bestRound = res.get(0);
LOG_DEBUG("helperSetRackRandom(): initial rack: "
<< lfw(pld.toString()) << " (best word: "
<< lfw(bestRound.getWord()) << ")");

View file

@ -25,10 +25,11 @@
#include <cwctype>
#include <cmath>
#include "results.h"
#include "tile.h"
#include "round.h"
#include "board.h"
#include "results.h"
#include "move_selector.h"
#include "debug.h"
@ -306,3 +307,41 @@ void LimitResults::clear()
m_total = 0;
}
MasterResults::MasterResults(const Bag &iBag)
: m_bag(iBag)
{
}
void MasterResults::search(const Dictionary &iDic, const Board &iBoard,
const Rack &iRack, bool iFirstWord)
{
// Perform the search of the best results
m_bestResults.search(iDic, iBoard, iRack, iFirstWord);
// If the search yields no result, there is nothing else to do
if (m_bestResults.isEmpty())
return;
// Find the best round, according to the heuristics in MoveSelector
MoveSelector selector;
const Round &round = selector.selectMaster(m_bestResults);
m_rounds.push_back(round);
}
void MasterResults::add(const Round &iRound)
{
m_bestResults.add(iRound);
}
void MasterResults::clear()
{
m_rounds.clear();
m_bestResults.clear();
}

View file

@ -32,6 +32,7 @@ using namespace std;
class Dictionary;
class Board;
class Rack;
class Bag;
/**
@ -138,5 +139,27 @@ private:
int m_minScore;
};
/**
* This implementation starts with finding the rounds corresponding to the best
* score, like BestResults would do.
* After that, it uses a series of heuristics to identify the round which
* be best as "master move" in a duplicate game.
* All other rounds are discarded, so the size() method will always
* return 0 (if no round can be played at all) or 1.
*/
class MasterResults: public Results
{
public:
MasterResults(const Bag &iBag);
virtual void search(const Dictionary &iDic, const Board &iBoard,
const Rack &iRack, bool iFirstWord);
virtual void clear();
virtual void add(const Round &iRound);
private:
const Bag &m_bag;
BestResults m_bestResults;
};
#endif

View file

@ -34,7 +34,6 @@
#include "settings.h"
#include "rack.h"
#include "results.h"
#include "move_selector.h"
#include "pldrack.h"
#include "player.h"
#include "turn.h"
@ -221,14 +220,13 @@ void Topping::addPlayer(Player *iPlayer)
Move Topping::getTopMove() const
{
BestResults results;
// Find the most interesting top
MasterResults results(getBag());
results.search(getDic(), getBoard(), getHistory().getCurrentRack().getRack(),
getHistory().beforeFirstRound());
ASSERT(!results.isEmpty(), "No top move found");
// Find the most interesting top
MoveSelector selector;
return Move(selector.selectMaster(results));
return Move(results.get(0));
}

View file

@ -31,7 +31,6 @@
#include "prefs_dialog.h"
#include "public_game.h"
#include "move_selector.h"
#include "player.h"
#include "turn_data.h"
#include "rack.h"
@ -526,7 +525,7 @@ void ArbitAssignments::setDefaultMasterMove()
return;
// Search the best moves
BestResults results;
MasterResults results(m_game->getBag());
results.search(m_game->getDic(), m_game->getBoard(),
m_game->getCurrentRack().getRack(),
m_game->getHistory().beforeFirstRound());
@ -535,8 +534,7 @@ void ArbitAssignments::setDefaultMasterMove()
return;
// Find a good default
MoveSelector selector;
Move move = Move(selector.selectMaster(results));
Move move = Move(results.get(0));
// Assign the master move
m_game->duplicateSetMasterMove(move);