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
|
* 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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue