mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-18 10:26:15 +01:00
Arbitration: new option to handle solos automatically.
The option is not yet accessible from the interface.
This commit is contained in:
parent
4d38c99336
commit
19a93988ad
4 changed files with 109 additions and 32 deletions
|
@ -221,6 +221,15 @@ void Arbitration::assignMove(unsigned int iPlayerId, const Move &iMove)
|
|||
{
|
||||
ASSERT(iPlayerId < getNPlayers(), "Wrong player number");
|
||||
recordPlayerMove(*m_players[iPlayerId], iMove);
|
||||
|
||||
// Automatically update the solos if requested
|
||||
bool useSoloAuto = Settings::Instance().getBool("arbitration.solo-auto");
|
||||
if (useSoloAuto)
|
||||
{
|
||||
unsigned minNbPlayers = Settings::Instance().getInt("arbitration.solo-players");
|
||||
int soloValue = Settings::Instance().getInt("arbitration.solo-value");
|
||||
setSoloAuto(minNbPlayers, soloValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "ai_player.h"
|
||||
#include "navigation.h"
|
||||
#include "turn.h"
|
||||
#include "turn_data.h"
|
||||
#include "settings.h"
|
||||
#include "encoding.h"
|
||||
#include "debug.h"
|
||||
|
@ -288,37 +289,21 @@ void Duplicate::endTurn()
|
|||
}
|
||||
}
|
||||
|
||||
// Handle solo bonus (not in arbitration mode, because we may not have all
|
||||
// the moves to decide whether a solo can be attributed).
|
||||
// Handle solo bonus
|
||||
if (!isArbitrationGame())
|
||||
{
|
||||
// First check whether there are enough players in the game for the
|
||||
// bonus to apply
|
||||
unsigned int minNbPlayers = Settings::Instance().getInt("duplicate.solo-players");
|
||||
// Find the player with the best score
|
||||
Player *bestPlayer = findBestPlayer();
|
||||
if (getNPlayers() >= minNbPlayers && bestPlayer != NULL)
|
||||
unsigned minNbPlayers = Settings::Instance().getInt("duplicate.solo-players");
|
||||
int soloValue = Settings::Instance().getInt("duplicate.solo-value");
|
||||
setSoloAuto(minNbPlayers, soloValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool useSoloAuto = Settings::Instance().getBool("arbitration.solo-auto");
|
||||
if (useSoloAuto)
|
||||
{
|
||||
int bestScore = bestPlayer->getLastMove().getScore();
|
||||
// Find whether other players than imax have the same score
|
||||
bool otherWithSameScore = false;
|
||||
BOOST_FOREACH(const Player *player, m_players)
|
||||
{
|
||||
if (player != bestPlayer &&
|
||||
player->getLastMove().getScore() >= bestScore &&
|
||||
player->getLastMove().isValid())
|
||||
{
|
||||
otherWithSameScore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!otherWithSameScore)
|
||||
{
|
||||
// Give the bonus to the player of the best move
|
||||
int bonus = Settings::Instance().getInt("duplicate.solo-value");
|
||||
Command *pCmd = new PlayerEventCmd(*bestPlayer, PlayerEventCmd::SOLO, bonus);
|
||||
accessNavigation().addAndExecute(pCmd);
|
||||
}
|
||||
unsigned minNbPlayers = Settings::Instance().getInt("arbitration.solo-players");
|
||||
int soloValue = Settings::Instance().getInt("arbitration.solo-value");
|
||||
setSoloAuto(minNbPlayers, soloValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,6 +420,67 @@ void Duplicate::setGameAndPlayersRack(const PlayedRack &iRack)
|
|||
}
|
||||
|
||||
|
||||
void Duplicate::setSoloAuto(unsigned int minNbPlayers, int iSoloValue)
|
||||
{
|
||||
// Remove all existing solos
|
||||
BOOST_FOREACH(const Player *player, m_players)
|
||||
{
|
||||
const PlayerEventCmd *cmd = getPlayerEvent(player->getId(), PlayerEventCmd::SOLO);
|
||||
if (cmd != 0)
|
||||
{
|
||||
accessNavigation().dropCommand(*cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether there are enough players in the game for the
|
||||
// solo to apply. We count only the "active" players, i.e. the ones
|
||||
// which have played at least one word during the game, even if they
|
||||
// have left the game since then, or have arrived after the beginning.
|
||||
unsigned countActive = 0;
|
||||
BOOST_FOREACH(const Player *player, m_players)
|
||||
{
|
||||
for (unsigned i = 0; i < player->getHistory().getSize(); ++i)
|
||||
{
|
||||
if (!player->getHistory().getTurn(i).getMove().isNull())
|
||||
{
|
||||
++countActive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (countActive < minNbPlayers)
|
||||
return;
|
||||
|
||||
// Find the player with the best score
|
||||
Player *bestPlayer = findBestPlayer();
|
||||
if (bestPlayer != NULL)
|
||||
{
|
||||
int bestScore = bestPlayer->getLastMove().getScore();
|
||||
|
||||
// Find whether other players than imax have the same score
|
||||
bool otherWithSameScore = false;
|
||||
BOOST_FOREACH(const Player *player, m_players)
|
||||
{
|
||||
if (player != bestPlayer &&
|
||||
player->getLastMove().getScore() >= bestScore &&
|
||||
player->getLastMove().isValid())
|
||||
{
|
||||
otherWithSameScore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!otherWithSameScore)
|
||||
{
|
||||
// Give the bonus to the player of the best move
|
||||
LOG_INFO("Giving a solo of " << iSoloValue << " to player " << bestPlayer->getId());
|
||||
Command *pCmd = new PlayerEventCmd(*bestPlayer, PlayerEventCmd::SOLO, iSoloValue);
|
||||
accessNavigation().insertCommand(pCmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Predicate to help retrieving commands
|
||||
struct MatchingPlayerAndEventType : public unary_function<PlayerEventCmd, bool>
|
||||
{
|
||||
|
|
|
@ -141,6 +141,16 @@ protected:
|
|||
const PlayerEventCmd * getPlayerEvent(unsigned iPlayerId,
|
||||
int iEventType) const;
|
||||
|
||||
/**
|
||||
* Automatically set the solo for the current turn.
|
||||
* First, all the existing solos (there could be several, in arbitration
|
||||
* mode with a crazy arbitrator...) are removed. Then, a solo is given to
|
||||
* the player deserving it, if any.
|
||||
* Note that the minimum number of players specified in the preferences
|
||||
* must be reached for the solo to be applicable.
|
||||
*/
|
||||
void setSoloAuto(unsigned int minNbPlayers, int iSoloValue);
|
||||
|
||||
private: // Used by friend classes
|
||||
void innerSetMasterMove(const Move &iMove);
|
||||
bool isArbitrationGame() const;
|
||||
|
|
|
@ -233,8 +233,12 @@ Settings::Settings()
|
|||
// If true, a random rack is defined, otherwise the rack is left untouched
|
||||
arbitration.add("fill-rack", Setting::TypeBoolean) = true;
|
||||
|
||||
// Number of search results kept in a search
|
||||
arbitration.add("search-limit", Setting::TypeInt) = 100;
|
||||
// If true, solos are automatically given when appropriate
|
||||
// If false, the arbitrator has full control (but must do everything manually)
|
||||
arbitration.add("solo-auto", Setting::TypeBoolean) = true;
|
||||
// Minimum number of players in a duplicate game needed to apply a "solo" bonus
|
||||
// (16 is the ODS value)
|
||||
arbitration.add("solo-players", Setting::TypeInt) = 16;
|
||||
|
||||
// Number of points granted for a solo (10 is the ODS value)
|
||||
arbitration.add("solo-value", Setting::TypeInt) = 10;
|
||||
|
@ -245,6 +249,9 @@ Settings::Settings()
|
|||
// Maximum number of warnings before getting penalties
|
||||
arbitration.add("warnings-limit", Setting::TypeInt) = 3;
|
||||
|
||||
// Number of search results kept in a search
|
||||
arbitration.add("search-limit", Setting::TypeInt) = 100;
|
||||
|
||||
// Try to read the values from the configuration file
|
||||
try
|
||||
{
|
||||
|
@ -260,13 +267,16 @@ Settings::Settings()
|
|||
copySetting<bool>(tmpConf, *m_conf, "freegame.reject-invalid");
|
||||
copySetting<bool>(tmpConf, *m_conf, "arbitration.fill-rack");
|
||||
copySetting<int>(tmpConf, *m_conf, "arbitration.search-limit");
|
||||
copySetting<bool>(tmpConf, *m_conf, "arbitration.solo-auto");
|
||||
copySetting<int>(tmpConf, *m_conf, "arbitration.solo-players");
|
||||
copySetting<int>(tmpConf, *m_conf, "arbitration.solo-value");
|
||||
copySetting<int>(tmpConf, *m_conf, "arbitration.penalty-value");
|
||||
copySetting<int>(tmpConf, *m_conf, "arbitration.warnings-limit");
|
||||
}
|
||||
catch (...)
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
// Ignore the exception
|
||||
// Only log the exception
|
||||
LOG_ERROR("Error reading config file: " << e.what());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -347,6 +357,8 @@ int Settings::getInt(const string &iName) const
|
|||
return 10;
|
||||
else if (iName == "arbitration.search-limit")
|
||||
return 100;
|
||||
else if (iName == "arbitration.solo-players")
|
||||
return 16;
|
||||
else if (iName == "arbitration.solo-value")
|
||||
return 5;
|
||||
else if (iName == "arbitration.penalty-value")
|
||||
|
|
Loading…
Reference in a new issue