MoveSelector: add another heuristic

This commit is contained in:
Olivier Teulière 2013-01-17 19:52:49 +01:00
parent 075dbaa2fb
commit a53d99a8d3
3 changed files with 55 additions and 4 deletions

View file

@ -18,10 +18,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/ *****************************************************************************/
#include <boost/foreach.hpp>
#include "move_selector.h" #include "move_selector.h"
#include "round.h" #include "round.h"
#include "results.h" #include "results.h"
#include "bag.h" #include "bag.h"
#include "rack.h"
#include "dic.h" #include "dic.h"
#include "debug.h" #include "debug.h"
@ -30,11 +33,16 @@
INIT_LOGGER(game, MoveSelector); INIT_LOGGER(game, MoveSelector);
#define PLAYED_JOKER (-1000) #define PLAYED_JOKER (-1000)
#define LETTER_REPEATED_3_TIMES (-3)
#define LETTER_REPEATED_4_TIMES (-12)
#define LETTER_REPEATED_5_TIMES (-40)
#define LETTER_REPEATED_6_TIMES (-100)
#define EXTENSION_1 50 #define EXTENSION_1 50
MoveSelector::MoveSelector(const Bag &iBag, const Dictionary &iDic) MoveSelector::MoveSelector(const Bag &iBag, const Dictionary &iDic,
: m_bag(iBag), m_dic(iDic) const Board &iBoard, const Rack &iRack)
: m_bag(iBag), m_dic(iDic), m_board(iBoard), m_rack(iRack)
{ {
} }
@ -69,6 +77,7 @@ int MoveSelector::evalScore(const Round &iRound) const
{ {
int score = 0; int score = 0;
score += evalForJokersInRack(iRound); score += evalForJokersInRack(iRound);
score += evalForRemainingLetters(iRound);
// Deactivated for now, as it breaks a few non-regression tests, // Deactivated for now, as it breaks a few non-regression tests,
// and I don't have time to fix them at the moment... :) // and I don't have time to fix them at the moment... :)
#if 0 #if 0
@ -85,6 +94,42 @@ int MoveSelector::evalForJokersInRack(const Round &iRound) const
} }
int MoveSelector::evalForRemainingLetters(const Round &iRound) const
{
// Compute the rack remaining after playing the round
Rack remaining = m_rack;
for (unsigned i = 0; i < iRound.getWordLen(); ++i)
{
if (iRound.isPlayedFromRack(i))
{
remaining.remove(iRound.isJoker(i) ? Tile::Joker() : iRound.getTile(i));
}
}
// If a letter is present at least 3 times in the rack, consider it bad
// Note: the repetitions are only relevant if the rack is not rejected for
// lack of vowels and/or consonants...
int score = 0;
BOOST_FOREACH(const Tile &t, m_dic.getAllTiles())
{
const int count = remaining.count(t);
if (count >= 3)
{
if (count == 3)
score += LETTER_REPEATED_3_TIMES;
else if (count == 4)
score += LETTER_REPEATED_4_TIMES;
else if (count == 5)
score += LETTER_REPEATED_5_TIMES;
else if (count == 6)
score += LETTER_REPEATED_6_TIMES;
}
}
return score;
}
int MoveSelector::evalForExtensions(const Round &iRound) const int MoveSelector::evalForExtensions(const Round &iRound) const
{ {
// Find front and back extensions to the given round // Find front and back extensions to the given round

View file

@ -27,6 +27,8 @@ class Round;
class BestResults; class BestResults;
class Bag; class Bag;
class Dictionary; class Dictionary;
class Board;
class Rack;
/** /**
@ -40,7 +42,8 @@ class MoveSelector
DEFINE_LOGGER(); DEFINE_LOGGER();
public: public:
MoveSelector(const Bag &iBag, const Dictionary &iDic); MoveSelector(const Bag &iBag, const Dictionary &iDic,
const Board &iBoard, const Rack &iRack);
/** /**
* Return a move to be used as "master move" in a duplicate game. * Return a move to be used as "master move" in a duplicate game.
@ -58,9 +61,12 @@ public:
private: private:
const Bag &m_bag; const Bag &m_bag;
const Dictionary &m_dic; const Dictionary &m_dic;
const Board &m_board;
const Rack &m_rack;
int evalScore(const Round &iRound) const; int evalScore(const Round &iRound) const;
int evalForJokersInRack(const Round &iRound) const; int evalForJokersInRack(const Round &iRound) const;
int evalForRemainingLetters(const Round &iRound) const;
int evalForExtensions(const Round &iRound) const; int evalForExtensions(const Round &iRound) const;
}; };

View file

@ -326,7 +326,7 @@ void MasterResults::search(const Dictionary &iDic, const Board &iBoard,
return; return;
// Find the best round, according to the heuristics in MoveSelector // Find the best round, according to the heuristics in MoveSelector
MoveSelector selector(m_bag, iDic); MoveSelector selector(m_bag, iDic, iBoard, iRack);
const Round &round = selector.selectMaster(m_bestResults); const Round &round = selector.selectMaster(m_bestResults);
m_rounds.push_back(round); m_rounds.push_back(round);
} }