mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2024-12-25 21:59:30 +01:00
MoveSelector: add another heuristic
This commit is contained in:
parent
075dbaa2fb
commit
a53d99a8d3
3 changed files with 55 additions and 4 deletions
|
@ -18,10 +18,13 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*****************************************************************************/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "move_selector.h"
|
||||
#include "round.h"
|
||||
#include "results.h"
|
||||
#include "bag.h"
|
||||
#include "rack.h"
|
||||
|
||||
#include "dic.h"
|
||||
#include "debug.h"
|
||||
|
@ -30,11 +33,16 @@
|
|||
INIT_LOGGER(game, MoveSelector);
|
||||
|
||||
#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
|
||||
|
||||
|
||||
MoveSelector::MoveSelector(const Bag &iBag, const Dictionary &iDic)
|
||||
: m_bag(iBag), m_dic(iDic)
|
||||
MoveSelector::MoveSelector(const Bag &iBag, const Dictionary &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;
|
||||
score += evalForJokersInRack(iRound);
|
||||
score += evalForRemainingLetters(iRound);
|
||||
// Deactivated for now, as it breaks a few non-regression tests,
|
||||
// and I don't have time to fix them at the moment... :)
|
||||
#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
|
||||
{
|
||||
// Find front and back extensions to the given round
|
||||
|
|
|
@ -27,6 +27,8 @@ class Round;
|
|||
class BestResults;
|
||||
class Bag;
|
||||
class Dictionary;
|
||||
class Board;
|
||||
class Rack;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -40,7 +42,8 @@ class MoveSelector
|
|||
DEFINE_LOGGER();
|
||||
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.
|
||||
|
@ -58,9 +61,12 @@ public:
|
|||
private:
|
||||
const Bag &m_bag;
|
||||
const Dictionary &m_dic;
|
||||
const Board &m_board;
|
||||
const Rack &m_rack;
|
||||
|
||||
int evalScore(const Round &iRound) const;
|
||||
int evalForJokersInRack(const Round &iRound) const;
|
||||
int evalForRemainingLetters(const Round &iRound) const;
|
||||
int evalForExtensions(const Round &iRound) const;
|
||||
|
||||
};
|
||||
|
|
|
@ -326,7 +326,7 @@ void MasterResults::search(const Dictionary &iDic, const Board &iBoard,
|
|||
return;
|
||||
|
||||
// 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);
|
||||
m_rounds.push_back(round);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue