/***************************************************************************** * Eliot * Copyright (C) 2005-2009 Olivier Teulière * Authors: Olivier Teulière * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *****************************************************************************/ #include #include // For transform #include // For towupper #include "arbitration.h" #include "rack.h" #include "player.h" #include "turn_cmd.h" #include "game_rack_cmd.h" #include "results.h" #include "settings.h" #include "encoding.h" #include "debug.h" INIT_LOGGER(game, Arbitration); Arbitration::Arbitration(const GameParams &iParams) : Duplicate(iParams) { } void Arbitration::setRackRandom() { undoCurrentRack(); const PlayedRack &newRack = helperSetRackRandom(getHistory().getCurrentRack(), true, RACK_NEW); setGameAndPlayersRack(newRack); } void Arbitration::setRackManual(const wstring &iLetters) { undoCurrentRack(); // Letters can be lowercase or uppercase as they are // coming from user input. We do not consider a lowercase // letter to be a joker which has been assigned to a letter. // As a result, we simply make all the letters uppercase wstring upperLetters = iLetters; std::transform(upperLetters.begin(), upperLetters.end(), upperLetters.begin(), towupper); const PlayedRack &newRack = helperSetRackManual(false, upperLetters); setGameAndPlayersRack(newRack); } void Arbitration::search(LimitResults &oResults) { const Rack &rack = getHistory().getCurrentRack().getRack(); LOG_DEBUG("Performing search for rack " + lfw(rack.toString())); int limit = Settings::Instance().getInt("arbitration.search-limit"); oResults.setLimit(limit); oResults.search(getDic(), getBoard(), rack, getHistory().beforeFirstRound()); LOG_DEBUG("Found " << oResults.size() << " results"); } Move Arbitration::checkWord(const wstring &iWord, const wstring &iCoords) const { Round round; int res = checkPlayedWord(iCoords, iWord, round); if (res == 0) return Move(round); return Move(iWord, iCoords); } void Arbitration::assignMove(unsigned int iPlayerId, const Move &iMove) { ASSERT(iPlayerId < getNPlayers(), "Wrong player number"); Player &player = *m_players[iPlayerId]; if (hasPlayed(iPlayerId)) { LOG_INFO("Re-assigning move for player " << iPlayerId); replacePlayerMove(player, iMove); } else { recordPlayerMove(player, iMove); } } void Arbitration::finalizeTurn() { // Assign a default empty move to the human players which have // not played yet, to be able to end the turn. BOOST_FOREACH(Player *player, m_players) { if (player->isHuman() && !hasPlayed(player->getId())) { LOG_INFO("Assigning a default move to player " << player->getId()); recordPlayerMove(*player, Move()); } } tryEndTurn(); } void Arbitration::undoCurrentRack() { // The interface is supposed to make sure we are never in this case ASSERT(getNavigation().isLastTurn(), "Cannot change rack for an old turn"); // TODO // Find the PlayerMoveCmd we want to undo const GameRackCmd *cmd = getNavigation().getCurrentTurn().findMatchingCmd(); ASSERT(cmd != 0, "No matching GameRackCmd found"); accessNavigation().dropFrom(*cmd); }