[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Eliot-dev] eliot game/Makefile.am game/ai_percent.cpp game... [cppdic]
From: |
eliot-dev |
Subject: |
[Eliot-dev] eliot game/Makefile.am game/ai_percent.cpp game... [cppdic] |
Date: |
Sun, 23 Dec 2007 23:12:46 +0000 |
CVSROOT: /cvsroot/eliot
Module name: eliot
Branch: cppdic
Changes by: Olivier Teulière <ipkiss> 07/12/23 23:12:46
Modified files:
game : Makefile.am ai_percent.cpp ai_percent.h
ai_player.h board.h duplicate.cpp duplicate.h
freegame.cpp freegame.h game.cpp game.h
game_io.cpp history.cpp history.h player.cpp
player.h results.cpp results.h settings.cpp
settings.h training.cpp training.h turn.cpp
turn.h
po : eliot.pot fr.po
test : freegame_change.input freegame_change.ref
freegame_passing.ref
utils : eliottxt.cpp ncurses.cpp
wxwin : mainframe.cc printout.cc searchpanel.cc
Added files:
game : move.cpp move.h
Log message:
- New Move class. A Move corresponds to any "action" of a player:
* playing a valid round
* trying to play an invalid word/coord pair
* changing letters (freegame mode only)
* simply passing the turn (freegame mode only)
- Use Move objects internally in many places:
* in Turn objects (so in History as well, indirectly)
* in the interfaces (at least multi-player ones)
* in the AIPlayer interface (it simplifies it a lot)
- New settings (duplicate-reject-invalid and freegame-reject-invalid)
to
allow playing invalid moves in duplicate and fregame modes (of
course,
the player will get 0 point when playing an invalid word)
- All the types of moves are now recorded into the game history and
the
players' histories
- Adapted and improved scenarii for freegame mode
- Cleaned the interface of the various game classes, renamed methods,
added and improved comments
- Update of the French translation
Overall, the introduction of Move objects simplifies the code and gives
more
consistency across the various game modes.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/game/Makefile.am?cvsroot=eliot&only_with_tag=cppdic&r1=1.13.2.4&r2=1.13.2.5
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.5.2.2&r2=1.5.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.6.2.1&r2=1.6.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_player.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.7.2.1&r2=1.7.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.12.2.3&r2=1.12.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/duplicate.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.16.2.3&r2=1.16.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/duplicate.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.12.2.2&r2=1.12.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/freegame.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.18.2.6&r2=1.18.2.7
http://cvs.savannah.gnu.org/viewcvs/eliot/game/freegame.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.11.2.1&r2=1.11.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.31.2.10&r2=1.31.2.11
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.29.2.7&r2=1.29.2.8
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_io.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.4.2.5&r2=1.4.2.6
http://cvs.savannah.gnu.org/viewcvs/eliot/game/history.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.10.2.3&r2=1.10.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/history.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.11.2.2&r2=1.11.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/player.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.14.2.3&r2=1.14.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/player.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.18.2.3&r2=1.18.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.10.2.3&r2=1.10.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.8.2.4&r2=1.8.2.5
http://cvs.savannah.gnu.org/viewcvs/eliot/game/settings.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.1&r2=1.1.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/settings.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.1&r2=1.1.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.17.2.4&r2=1.17.2.5
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.15.2.1&r2=1.15.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/turn.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.11.2.2&r2=1.11.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/turn.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.9.2.2&r2=1.9.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/move.cpp?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/move.h?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/po/eliot.pot?cvsroot=eliot&only_with_tag=cppdic&r1=1.6.6.6&r2=1.6.6.7
http://cvs.savannah.gnu.org/viewcvs/eliot/po/fr.po?cvsroot=eliot&only_with_tag=cppdic&r1=1.6.6.6&r2=1.6.6.7
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_change.input?cvsroot=eliot&only_with_tag=cppdic&r1=1.1&r2=1.1.6.1
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_change.ref?cvsroot=eliot&only_with_tag=cppdic&r1=1.2&r2=1.2.4.1
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_passing.ref?cvsroot=eliot&only_with_tag=cppdic&r1=1.3.2.1&r2=1.3.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/eliottxt.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.16.2.10&r2=1.16.2.11
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/ncurses.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.22.2.11&r2=1.22.2.12
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/mainframe.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.21.2.9&r2=1.21.2.10
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/printout.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.10.4.1&r2=1.10.4.2
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/searchpanel.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.15.2.4&r2=1.15.2.5
Patches:
Index: game/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Makefile.am,v
retrieving revision 1.13.2.4
retrieving revision 1.13.2.5
diff -u -b -r1.13.2.4 -r1.13.2.5
--- game/Makefile.am 20 Dec 2007 08:47:07 -0000 1.13.2.4
+++ game/Makefile.am 23 Dec 2007 23:12:42 -0000 1.13.2.5
@@ -34,6 +34,7 @@
game.cpp game.h \
game_factory.cpp game_factory.h \
game_io.cpp \
+ move.cpp move.h \
player.cpp player.h \
pldrack.cpp pldrack.h \
rack.cpp rack.h \
Index: game/ai_percent.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.cpp,v
retrieving revision 1.5.2.2
retrieving revision 1.5.2.3
diff -u -b -r1.5.2.2 -r1.5.2.3
--- game/ai_percent.cpp 20 Dec 2007 08:47:07 -0000 1.5.2.2
+++ game/ai_percent.cpp 23 Dec 2007 23:12:42 -0000 1.5.2.3
@@ -21,6 +21,7 @@
#include "rack.h"
#include "pldrack.h"
#include "round.h"
+#include "move.h"
#include "results.h"
#include "board.h"
#include "ai_percent.h"
@@ -37,24 +38,27 @@
}
-void AIPercent::compute(const Dictionary &iDic, Board &iBoard, int turn)
+void AIPercent::compute(const Dictionary &iDic, Board &iBoard, bool iFirstWord)
{
m_results.clear();
Rack rack;
getCurrentRack().getRack(rack);
- m_results.search(iDic, iBoard, rack, turn);
+ m_results.search(iDic, iBoard, rack, iFirstWord);
}
-bool AIPercent::changesLetters() const
-{
- return (m_results.size() == 0);
-}
-
-
-const Round & AIPercent::getChosenRound() const
+Move AIPercent::getMove() const
{
+ if (m_results.size() == 0)
+ {
+ // If there is no result, simply pass the turn
+ // XXX: it is forbidden in duplicate mode, but well, what else to do?
+ return Move(L"");
+ }
+ else
+ {
+ // If there are results, apply the algorithm
double wantedScore = m_percent * m_results.get(0).getPoints();
// Look for the first round giving at least 'wantedScore' points
// Browse the results 10 by 10 (a dichotomy would be better, but this
@@ -72,13 +76,8 @@
{
--index;
}
- return m_results.get(index);
-}
-
-
-vector<Tile> AIPercent::getChangedLetters() const
-{
- return vector<Tile>();
+ return Move(m_results.get(index));
+ }
}
/// Local Variables:
Index: game/ai_percent.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.h,v
retrieving revision 1.6.2.1
retrieving revision 1.6.2.2
diff -u -b -r1.6.2.1 -r1.6.2.2
--- game/ai_percent.h 14 Dec 2007 18:12:32 -0000 1.6.2.1
+++ game/ai_percent.h 23 Dec 2007 23:12:42 -0000 1.6.2.2
@@ -45,17 +45,15 @@
* This method does the actual computation. It will be called before any
* of the following methods, so it must prepare everything for them.
*/
- virtual void compute(const Dictionary &iDic, Board &iBoard, int turn);
- /// Return true when the AI wants to change letters instead of playing a
word
- virtual bool changesLetters() const;
- /// Return the round played by the AI (if changesLetters() returns false)
- virtual const Round & getChosenRound() const;
- /// Get the letters to change (if changesLetters() returns true)
- virtual vector<Tile> getChangedLetters() const;
+ virtual void compute(const Dictionary &iDic, Board &iBoard, bool
iFirstWord);
+
+ /// Return the move played by the AI
+ virtual Move getMove() const;
private:
/// Percentage used for this player
float m_percent;
+
/// Container for all the found solutions
Results m_results;
};
Index: game/ai_player.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_player.h,v
retrieving revision 1.7.2.1
retrieving revision 1.7.2.2
diff -u -b -r1.7.2.1 -r1.7.2.2
--- game/ai_player.h 15 Oct 2006 11:07:55 -0000 1.7.2.1
+++ game/ai_player.h 23 Dec 2007 23:12:42 -0000 1.7.2.2
@@ -69,22 +69,14 @@
* This method does the actual computation. It will be called before any
* of the following methods, so it must prepare everything for them.
*/
- virtual void compute(const Dictionary &iDic, Board &iBoard, int turn) = 0;
- /**
- * Return true when the AI wants to change letters instead of playing a
- * word.
- * Should return false in duplicate mode, as it is not allowed to change
- * letters.
- */
- virtual bool changesLetters() const = 0;
- /// Return the round played by the AI (if changesLetters() returns false)
- virtual const Round & getChosenRound() const = 0;
- /// Get the letters to change (if changesLetters() returns true)
- virtual vector<Tile> getChangedLetters() const = 0;
+ virtual void compute(const Dictionary &iDic, Board &iBoard, bool
iFirstWord) = 0;
+
+ /// Return the move played by the AI
+ virtual Move getMove() const = 0;
protected:
/// This class is a pure interface, forbid any direct instanciation
- AIPlayer(int iId): Player(iId) {}
+ AIPlayer(unsigned int iId): Player(iId) {}
};
#endif
Index: game/board.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board.h,v
retrieving revision 1.12.2.3
retrieving revision 1.12.2.4
diff -u -b -r1.12.2.3 -r1.12.2.4
--- game/board.h 13 Dec 2007 12:11:06 -0000 1.12.2.3
+++ game/board.h 23 Dec 2007 23:12:42 -0000 1.12.2.4
@@ -21,11 +21,12 @@
#ifndef _BOARD_H_
#define _BOARD_H_
-#include "tile.h"
-#include "cross.h"
#include <string>
#include <vector>
+#include "tile.h"
+#include "cross.h"
+
class Dictionary;
class Rack;
class Round;
Index: game/duplicate.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/duplicate.cpp,v
retrieving revision 1.16.2.3
retrieving revision 1.16.2.4
diff -u -b -r1.16.2.3 -r1.16.2.4
--- game/duplicate.cpp 20 Dec 2007 08:47:07 -0000 1.16.2.3
+++ game/duplicate.cpp 23 Dec 2007 23:12:42 -0000 1.16.2.4
@@ -22,6 +22,7 @@
#include "tile.h"
#include "rack.h"
#include "round.h"
+#include "move.h"
#include "pldrack.h"
#include "results.h"
#include "player.h"
@@ -49,43 +50,52 @@
int Duplicate::play(const wstring &iCoord, const wstring &iWord)
{
- /* Perform all the validity checks, and fill a round */
+ // Perform all the validity checks, and try to fill a round
Round round;
int res = checkPlayedWord(iCoord, iWord, round);
- if (res != 0)
+ if (res != 0 && Settings::Instance().getBool("duplicate-reject-invalid"))
{
return res;
}
- /* Everything is OK, we can play the word */
- playRound(round, m_currPlayer);
+ // If we reach this point, either the move is valid and we can use the
+ // "round" variable, or it is invalid but played nevertheless
+ if (res == 0)
+ {
+ // Everything is OK, we can play the word
+ playMove(Move(round), m_currPlayer);
+ }
+ else
+ {
+ // Record the invalid move of the player
+ playMove(Move(iWord, iCoord), m_currPlayer);
+ }
- /* Next turn */
- // XXX: Should it be done by the interface instead?
- endTurn();
+ // Little hack to handle duplicate games with only AI players.
+ // This will have no effect when there is at least one human player
+ tryEndTurn();
return 0;
}
-void Duplicate::duplicateAI(unsigned int p)
+void Duplicate::playAI(unsigned int p)
{
ASSERT(p < getNPlayers(), "Wrong player number");
- ASSERT(!m_players[p]->isHuman(), "AI requested for a human player");
- AIPlayer *player = static_cast<AIPlayer*>(m_players[p]);
- player->compute(m_dic, m_board, m_history.getSize());
+ AIPlayer *player = dynamic_cast<AIPlayer*>(m_players[p]);
+ ASSERT(player != NULL, "AI requested for a human player");
- if (player->changesLetters())
+ player->compute(m_dic, m_board, m_history.beforeFirstRound());
+ const Move move = player->getMove();
+ if (move.getType() == Move::CHANGE_LETTERS ||
+ move.getType() == Move::PASS)
{
- // The AI player has nothing to play. This should not happen in
- // duplicate mode, otherwise the implementation of the AI is buggy...
- ASSERT(false, "AI player has nothing to play!");
- }
- else
- {
- playRound(player->getChosenRound(), p);
+ // The AI player must be buggy...
+ ASSERT(false, "AI tried to cheat!");
}
+
+ playMove(move, p);
}
@@ -96,119 +106,102 @@
// Arbitrary player, since they should all have the same rack
m_currPlayer = 0;
- /* Complete the rack for the player that just played */
+ // Complete the rack for the player that just played
int res = setRackRandom(m_currPlayer, true, RACK_NEW);
- /* End of the game? */
+ // End of the game?
if (res == 1)
{
- end();
+ endGame();
return 1;
}
const PlayedRack& pld = m_players[m_currPlayer]->getCurrentRack();
- /* All the players have the same rack */
+ // All the players have the same rack
for (unsigned int i = 0; i < getNPlayers(); i++)
{
if (i != m_currPlayer)
{
m_players[i]->setCurrentRack(pld);
}
- /* Nobody has played yet in this round */
+ // Nobody has played yet in this round
m_hasPlayed[i] = false;
}
- /* Next turn */
- // XXX: Should it be done by the interface instead?
- endTurn();
+ // Little hack to handle duplicate games with only AI players.
+ // This will have no effect when there is at least one human player
+ tryEndTurn();
return 0;
}
-/*
- * This function does not terminate the turn itself, but performs some
- * checks to know whether or not it should be terminated (with a call to
- * endTurnForReal()).
- *
- * For the turn to be terminated, all the players must have played.
- * Since the AI players play after the human players, we check whether
- * one of the human players has not played yet:
- * - if so, we have nothing to do (we are waiting for him)
- * - if not (all human players have played), the AI players can play,
- * and we finish the turn.
- */
-int Duplicate::endTurn()
+void Duplicate::tryEndTurn()
{
- unsigned int i;
- for (i = 0; i < getNPlayers(); i++)
+ for (unsigned int i = 0; i < getNPlayers(); i++)
{
if (m_players[i]->isHuman() && !m_hasPlayed[i])
{
- /* A human player has not played... */
+ // A human player has not played...
m_currPlayer = i;
- // XXX: check return code meaning
- return 1;
+ // So we don't finish the turn
+ return;
}
}
- /* If all the human players have played */
- if (i == getNPlayers())
- {
- /* Make AI players play their turn */
- for (i = 0; i < getNPlayers(); i++)
+ // Now that all the human players have played,
+ // make AI players play their turn
+ for (unsigned int i = 0; i < getNPlayers(); i++)
{
if (!m_players[i]->isHuman())
{
- duplicateAI(i);
- }
+ playAI(i);
}
-
- /* Next turn */
- endTurnForReal();
- start();
}
- // XXX: check return code meaning
- return 0;
+ // Next turn
+ endTurn();
}
-void Duplicate::playRound(const Round &iRound, unsigned int p)
+void Duplicate::playMove(const Move &iMove, unsigned int p)
{
ASSERT(p < getNPlayers(), "Wrong player number");
// Update the rack and the score of the playing player
- m_players[p]->endTurn(iRound, m_history.getSize());
+ m_players[p]->endTurn(iMove, m_history.getSize());
m_hasPlayed[p] = true;
}
-void Duplicate::endTurnForReal()
+void Duplicate::endTurn()
{
// Find the player with the best score
unsigned int imax = 0;
for (unsigned int i = 1; i < getNPlayers(); i++)
{
- if (m_players[i]->getLastRound().getPoints() >
- m_players[imax]->getLastRound().getPoints())
+ if (m_players[i]->getLastMove().getScore() >
+ m_players[imax]->getLastMove().getScore())
{
imax = i;
}
}
+ // TODO: do something if nobody played a valid round!
+
// Handle solo bonus
- // First check whetherf there are enough players in the game for the
+ // First check whether there are enough players in the game for the
// bonus to apply
int minNbPlayers = Settings::Instance().getInt("duplicate-solo-players");
- if (getNPlayers() >= (unsigned int)minNbPlayers)
+ if (getNPlayers() >= (unsigned int)minNbPlayers &&
+ m_players[imax]->getLastMove().getType() == Move::VALID_ROUND)
{
+ int maxScore = m_players[imax]->getLastMove().getScore();
// Find whether other players than imax have the same score
bool otherWithSameScore = false;
for (unsigned int i = imax + 1; i < getNPlayers(); i++)
{
- if (m_players[i]->getLastRound().getPoints() >=
- m_players[imax]->getLastRound().getPoints())
+ if (m_players[i]->getLastMove().getScore() >= maxScore)
{
otherWithSameScore = true;
break;
@@ -225,7 +218,7 @@
}
// Play the best word on the board
- helperPlayRound(imax, m_players[imax]->getLastRound());
+ helperPlayMove(imax, m_players[imax]->getLastMove());
// Leave the same reliquate to all players
// This is required by the start() method which will be called to
@@ -238,10 +231,13 @@
m_players[i]->setCurrentRack(pld);
}
}
+
+ // Start next turn...
+ start();
}
-void Duplicate::end()
+void Duplicate::endGame()
{
m_finished = true;
}
@@ -251,7 +247,7 @@
{
ASSERT(p < getNPlayers(), "Wrong player number");
- /* Forbid switching to an AI player */
+ // Forbid switching to an AI player
if (!m_players[p]->isHuman())
return 1;
Index: game/duplicate.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/duplicate.h,v
retrieving revision 1.12.2.2
retrieving revision 1.12.2.3
diff -u -b -r1.12.2.2 -r1.12.2.3
--- game/duplicate.h 20 Dec 2007 08:47:07 -0000 1.12.2.2
+++ game/duplicate.h 23 Dec 2007 23:12:42 -0000 1.12.2.3
@@ -34,7 +34,7 @@
* and rack are updated. He cannot change his word afterwards.
* - if there is still a human player who has not played for the current
* turn, we wait for him
- * - if all the human players have played, it's the turn to the AI players
+ * - if all the human players have played, it's the turn of the AI players
* (currently handled in a loop, but we could imagine that they are running
* in their own thread).
* - once all the players have played, we can really end the turn:
@@ -60,15 +60,28 @@
/**
* In Duplicate mode, the start() method starts a new turn, and is
* automatically called when the previous turn is finished.
- * It has an important pre-requisite: all the players must have the
- * same rack when calling this function
+ *
+ * Pre-requisite: all the players must have the same rack when this
+ * method is called
*/
virtual int start();
- virtual int setRackRandom(unsigned int, bool, set_rack_mode);
+
+ /**
+ * See description of Game::play() for the possible return values.
+ * Note that if the "duplicate-reject-invalid" setting is set to false
+ * the method always returns 0 (the player will have 0 for this turn)
+ */
virtual int play(const wstring &iCoord, const wstring &iWord);
- virtual int endTurn();
- int setPlayer(unsigned int);
+ /**
+ * Set the current player, given its ID.
+ * The given player ID must correspond to a human player, which did not
+ * play yet for this turn.
+ * Possible return values:
+ * 0: everything went fine
+ * 1: the player is not human
+ */
+ int setPlayer(unsigned int p);
/// Switch to the previous human player who has not played yet
void prevHumanPlayer();
@@ -80,20 +93,38 @@
// Private constructor to force using the GameFactory class
Duplicate(const Dictionary &iDic);
- void playRound(const Round &iRound, unsigned int p);
+ void playMove(const Move &iMove, unsigned int p);
+ int setRackRandom(unsigned int, bool, set_rack_mode);
+
+ /// Make the AI player whose ID is p play its turn
+ void playAI(unsigned int p);
+
+ /**
+ * This function does not terminate the turn itself, but performs some
+ * checks to know whether or not it should be terminated (with a call to
+ * endTurn()).
+ *
+ * For the turn to be terminated, all the players must have played.
+ * Since the AI players play after the human players, we check whether
+ * one of the human players has not played yet:
+ * - if so, we have nothing to do (we are waiting for him/her)
+ * - if not (all human players have played), the AI players can play,
+ * and we finish the turn.
+ */
+ void tryEndTurn();
/**
* This function really changes the turn, i.e. the best word is played,
* the game history is updated, a "solo" bonus is given if needed, and
- * all racks are made equal to the one of the player which played the best
- * move.
- * We suppose here that all the players have finished to play for this turn
- * (this should have been checked by endturn())
+ * all racks are made equal to the one of the player who played the
+ * best move.
+ * We suppose here that all the players have finished to play for this
+ * turn (this should have been checked by tryEndturn())
*/
- void endTurnForReal();
+ void endTurn();
- void end();
- void duplicateAI(unsigned int p);
+ /// Finish the game
+ void endGame();
// m_hasPlayed[p] is true iff player p has played for this turn
map<int, bool> m_hasPlayed;
Index: game/freegame.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/freegame.cpp,v
retrieving revision 1.18.2.6
retrieving revision 1.18.2.7
diff -u -b -r1.18.2.6 -r1.18.2.7
--- game/freegame.cpp 20 Dec 2007 08:47:08 -0000 1.18.2.6
+++ game/freegame.cpp 23 Dec 2007 23:12:42 -0000 1.18.2.7
@@ -19,25 +19,24 @@
#include <iomanip>
#include <wctype.h>
+
+#include "freegame.h"
#include "dic.h"
#include "tile.h"
#include "rack.h"
#include "round.h"
+#include "move.h"
#include "pldrack.h"
#include "results.h"
#include "player.h"
#include "ai_player.h"
-#include "freegame.h"
+#include "settings.h"
#include "debug.h"
-FreeGame::FreeGame(const Dictionary &iDic): Game(iDic)
-{
-}
-
-
-FreeGame::~FreeGame()
+FreeGame::FreeGame(const Dictionary &iDic)
+ : Game(iDic)
{
}
@@ -55,51 +54,64 @@
int FreeGame::play(const wstring &iCoord, const wstring &iWord)
{
- /* Perform all the validity checks, and fill a round */
+ // Perform all the validity checks, and try to fill a round
Round round;
-
int res = checkPlayedWord(iCoord, iWord, round);
- if (res != 0)
+ if (res != 0 && Settings::Instance().getBool("freegame-reject-invalid"))
{
return res;
}
- /* Update the rack and the score of the current player */
- m_players[m_currPlayer]->endTurn(round, m_history.getSize());
+ // If we reach this point, either the move is valid and we can use the
+ // "round" variable, or it is invalid but played nevertheless
+ if (res == 0)
+ {
+ Move move(round);
+
+ // Update the rack and the score of the current player
+ m_players[m_currPlayer]->endTurn(move, m_history.getSize());
+
+ // Everything is OK, we can play the word
+ helperPlayMove(m_currPlayer, move);
+ }
+ else
+ {
+ Move move(iWord, iCoord);
+
+ // Record the invalid move of the player
+ m_players[m_currPlayer]->endTurn(move, m_history.getSize());
- /* Everything is OK, we can play the word */
- helperPlayRound(m_currPlayer, round);
+ // Update the game
+ helperPlayMove(m_currPlayer, move);
+ }
- /* Next turn */
- // XXX: Should it be done by the interface instead?
+ // Next turn
endTurn();
return 0;
}
-void FreeGame::freegameAI(unsigned int p)
+void FreeGame::playAI(unsigned int p)
{
ASSERT(p < getNPlayers(), "Wrong player number");
ASSERT(!m_players[p]->isHuman(), "AI requested for a human player");
AIPlayer *player = static_cast<AIPlayer*>(m_players[p]);
- player->compute(m_dic, m_board, m_history.getSize());
- if (player->changesLetters())
+ player->compute(m_dic, m_board, m_history.beforeFirstRound());
+ const Move move = player->getMove();
+ if (move.getType() == Move::CHANGE_LETTERS ||
+ move.getType() == Move::PASS)
{
- helperPass(player->getChangedLetters(), p);
- endTurn();
+ ASSERT(checkPass(move.getChangedLetters(), p) == 0, "AI tried to
cheat!");
}
- else
- {
- const Round &round = player->getChosenRound();
- /* Update the rack and the score of the current player */
- player->endTurn(round, m_history.getSize());
- helperPlayRound(p, round);
+ // Update the rack and the score of the current player
+ player->endTurn(move, m_history.getSize());
+
+ helperPlayMove(p, move);
endTurn();
- }
}
@@ -107,19 +119,18 @@
{
ASSERT(getNPlayers(), "Cannot start a game without any player");
- /* Set the initial racks of the players */
+ // Set the initial racks of the players
for (unsigned int i = 0; i < getNPlayers(); i++)
{
setRackRandom(i, false, RACK_NEW);
}
- // XXX
m_currPlayer = 0;
- /* If the first player is an AI, make it play now */
- if (!m_players[0]->isHuman())
+ // If the first player is an AI, make it play now
+ if (!m_players[m_currPlayer]->isHuman())
{
- freegameAI(0);
+ playAI(m_currPlayer);
}
return 0;
@@ -128,21 +139,21 @@
int FreeGame::endTurn()
{
- /* Complete the rack for the player that just played */
+ // Complete the rack for the player that just played
if (setRackRandom(m_currPlayer, false, RACK_NEW) == 1)
{
- /* End of the game */
- end();
+ // End of the game
+ endGame();
return 1;
}
- /* Next player */
+ // Next player
nextPlayer();
- /* If this player is an AI, make it play now */
+ // If this player is an AI, make it play now
if (!m_players[m_currPlayer]->isHuman())
{
- freegameAI(m_currPlayer);
+ playAI(m_currPlayer);
}
return 0;
@@ -150,7 +161,7 @@
// Adjust the scores of the players with the points of the remaining tiles
-void FreeGame::end()
+void FreeGame::endGame()
{
vector<Tile> tiles;
@@ -163,7 +174,7 @@
// We currently handle case 1, and cannot handle case 3 until timers are
// implemented.
// For case 2, we need both to detect a blocked situation (not easy...) and
- // to handle it in the end() method (very easy).
+ // to handle it in the endGame() method (very easy).
/* Add the points of the remaining tiles to the score of the current
* player (i.e. the first player with an empty rack), and remove them
@@ -182,45 +193,23 @@
}
}
- /* Lock game */
+ // Lock game
m_finished = true;
}
-int FreeGame::pass(const wstring &iToChange, unsigned int p)
+int FreeGame::checkPass(const wstring &iToChange, unsigned int p) const
{
+ ASSERT(p < getNPlayers(), "Wrong player number");
+
+ // Check that the game is not finished
if (m_finished)
return 3;
+ // Check that the letters are valid for the current dictionary
if (!m_dic.validateLetters(iToChange))
return 4;
- // According to the rules in the ODS, it is allowed to pass its turn (no
- // need to change letters for that).
- // TODO: However, if all the players pass their turn, the first one has to
- // play, or change at least one letter. To implement this behaviour, we
- // must also take care of blocked positions, where no one _can_ play (see
- // also comment in the end() method).
-
- // Convert the string into tiles
- vector<Tile> tilesVect;
- for (unsigned int i = 0; i < iToChange.size(); i++)
- {
- Tile tile(towupper(iToChange[i]));
- tilesVect.push_back(tile);
- }
-
- int res = helperPass(tilesVect, p);
- if (res == 0)
- endTurn();
- return res;
-}
-
-
-int FreeGame::helperPass(const vector<Tile> &iToChange, unsigned int p)
-{
- ASSERT(p < getNPlayers(), "Wrong player number");
-
// It is forbidden to change letters when the bag does not contain at
// least 7 letters (this is explicitly stated in the ODS). But it is
// still allowed to pass
@@ -231,28 +220,46 @@
return 1;
}
+ // Check that the letters are all present in the player's rack
Player *player = m_players[p];
PlayedRack pld = player->getCurrentRack();
Rack rack;
pld.getRack(rack);
-
for (unsigned int i = 0; i < iToChange.size(); i++)
{
- /* Remove the letter from the rack */
- if (!rack.in(iToChange[i]))
+ // Remove the letter from the rack
+ if (!rack.in(Tile(iToChange[i])))
{
return 2;
}
- rack.remove(iToChange[i]);
+ rack.remove(Tile(iToChange[i]));
}
- pld.reset();
- pld.setOld(rack);
+ // According to the rules in the ODS, it is allowed to pass its turn (no
+ // need to change letters for that).
+ // TODO: However, if all the players pass their turn, the first one has to
+ // play, or change at least one letter. To implement this behaviour, we
+ // must also take care of blocked positions, where no one _can_ play (see
+ // also comment in the endGame() method).
- player->setCurrentRack(pld);
+ return 0;
+}
- // FIXME: the letters to change should not be in the bag while generating
- // the new rack!
+
+int FreeGame::pass(const wstring &iToChange)
+{
+ int res = checkPass(iToChange, m_currPlayer);
+ if (res != 0)
+ return res;
+
+ Move move(iToChange);
+ // End the player's turn
+ m_players[m_currPlayer]->endTurn(move, m_history.getSize());
+ // Update the game
+ helperPlayMove(m_currPlayer, move);
+
+ // Next game turn
+ endTurn();
return 0;
}
Index: game/freegame.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/freegame.h,v
retrieving revision 1.11.2.1
retrieving revision 1.11.2.2
diff -u -b -r1.11.2.1 -r1.11.2.2
--- game/freegame.h 17 Dec 2007 11:27:41 -0000 1.11.2.1
+++ game/freegame.h 23 Dec 2007 23:12:43 -0000 1.11.2.2
@@ -48,20 +48,56 @@
/*************************
* Game handling
*************************/
+ /**
+ * Start the game.
+ * Possible return values:
+ * 0: everything went fine
+ */
virtual int start();
- virtual int setRackRandom(unsigned int, bool, set_rack_mode);
+
+ /**
+ * See description of Game::play() for the possible return values.
+ * Note that if the "freegame-reject-invalid" setting is set to false
+ * the method always returns 0 (the player will have 0 for this turn)
+ */
virtual int play(const wstring &iCoord, const wstring &iWord);
- virtual int endTurn();
- int pass(const wstring &iToChange, unsigned int p);
+
+ /**
+ * Pass the turn, changing the letters listed in iToChange.
+ * If you simply want to pass the turn without changing any letter,
+ * provide an empty string.
+ *
+ * Possible return values:
+ * 0: everything went fine
+ * 1: changing letters is not allowed if there are less than 7 tiles
+ * left in the bag
+ * 2: the rack of the current player does not contain all the
+ * listed letters
+ * 3: the game is already finished
+ * 4: some letters are invalid for the current dictionary
+ */
+ int pass(const wstring &iToChange);
private:
- // Private constructor and destructor to force using the GameFactory class
+ // Private constructor to force using the GameFactory class
FreeGame(const Dictionary &iDic);
- virtual ~FreeGame();
- void freegameAI(unsigned int p);
- void end();
- int helperPass(const vector<Tile> &iToChange, unsigned int p);
+ int setRackRandom(unsigned int, bool, set_rack_mode);
+
+ /// Make the AI player whose ID is p play its turn
+ void playAI(unsigned int p);
+
+ /// Finish the current turn
+ int endTurn();
+
+ /// Finish the game
+ void endGame();
+
+ /**
+ * Check whether it is legal to change the letters of iToChange.
+ * The return codes are the same as the ones on the pass() method
+ */
+ int checkPass(const wstring &iToChange, unsigned int p) const;
};
#endif /* _FREEGAME_H_ */
Index: game/game.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.cpp,v
retrieving revision 1.31.2.10
retrieving revision 1.31.2.11
diff -u -b -r1.31.2.10 -r1.31.2.11
--- game/game.cpp 20 Dec 2007 08:47:08 -0000 1.31.2.10
+++ game/game.cpp 23 Dec 2007 23:12:43 -0000 1.31.2.11
@@ -63,22 +63,28 @@
}
-void Game::helperPlayRound(unsigned int iPlayerId, const Round &iRound)
+void Game::helperPlayMove(unsigned int iPlayerId, const Move &iMove)
{
- /*
- * We remove tiles from the bag only when they are played
- * on the board. When going back in the game, we must only
- * replace played tiles.
- * We test a rack when it is set but tiles are left in the bag.
- */
-
// History of the game
m_history.setCurrentRack(getPlayer(iPlayerId).getLastRack());
- m_history.playRound(iPlayerId, m_history.getSize(), iRound);
+ m_history.playMove(iPlayerId, m_history.getSize(), iMove);
- debug(" helper: %d points\n",iRound.getPoints());
- m_points += iRound.getPoints();
+ // Points
+ debug(" helper: %d points\n", iMove.getScore());
+ m_points += iMove.getScore();
+ // For moves corresponding to a valid round, we have much more
+ // work to do...
+ if (iMove.getType() == Move::VALID_ROUND)
+ {
+ helperPlayRound(iPlayerId, iMove.getRound());
+ }
+}
+
+
+
+void Game::helperPlayRound(unsigned int iPlayerId, const Round &iRound)
+{
// Before updating the bag and the board, if we are playing a "joker game",
// we replace in the round the joker by the letter it represents
// This is currently done by a succession of ugly hacks :-/
@@ -133,7 +139,11 @@
}
}
- // Update the bag and the board
+ // Update the bag
+ // We remove tiles from the bag only when they are played
+ // on the board. When going back in the game, we must only
+ // replace played tiles.
+ // We test a rack when it is set but tiles are left in the bag.
for (unsigned int i = 0; i < iRound.getWordLen(); i++)
{
if (iRound.isPlayedFromRack(i))
@@ -148,6 +158,8 @@
}
}
}
+
+ // Update the board
m_board.addRound(m_dic, iRound);
}
@@ -162,7 +174,12 @@
for (unsigned int i = 0; i < n; i++)
{
prevPlayer();
- const Round &lastround = m_history.getPreviousTurn().getRound();
+ const Move &lastMove = m_history.getPreviousTurn().getMove();
+ // Nothing to cancel if the move was not a valid round
+ if (lastMove.getType() != Move::VALID_ROUND)
+ continue;
+
+ const Round &lastround = lastMove.getRound();
debug("Game::back last round %s\n",
convertToMb(lastround.toString()).c_str());
/* Remove the word from the board, and put its letters back
@@ -445,6 +462,7 @@
void Game::addAIPlayer()
{
+ // TODO: allow other percentages, and even other types of AI
m_players.push_back(new AIPercent(getNPlayers(), 1));
}
@@ -477,13 +495,9 @@
ASSERT(getNPlayers() != 0, "Expected at least one player");
if (!m_dic.validateLetters(iWord))
- return 12;
-
- int res;
- vector<Tile> tiles;
- Tile t;
+ return 1;
- /* Init the round with the given coordinates */
+ // Init the round with the given coordinates
oRound.init();
oRound.accessCoord().setFromString(iCoord);
if (!oRound.getCoord().isValid())
@@ -492,16 +506,17 @@
return 2;
}
- /* Check the existence of the word */
+ // Check the existence of the word
if (!m_dic.searchWord(iWord))
{
return 3;
}
- /* Set the word */
+ // Set the word
// TODO: make this a Round_ function (Round_setwordfromchar for example)
// or a Tiles_ function (to transform a char* into a vector<Tile>)
// Adding a getter on the word could help too...
+ vector<Tile> tiles;
for (unsigned int i = 0; i < iWord.size(); i++)
{
tiles.push_back(Tile(iWord[i]));
@@ -513,19 +528,20 @@
oRound.setJoker(i);
}
- /* Check the word position, compute its points,
- * and specify the origin of each letter (board or rack) */
- res = m_board.checkRound(oRound, m_history.getSize() == 0);
+ // Check the word position, compute its points,
+ // and specify the origin of each letter (board or rack)
+ int res = m_board.checkRound(oRound, m_history.getSize() == 0);
if (res != 0)
return res + 4;
- /* Check that the word can be formed with the tiles in the rack:
- * we first create a copy of the rack, then we remove the tiles
- * one by one */
+ // Check that the word can be formed with the tiles in the rack:
+ // we first create a copy of the rack, then we remove the tiles
+ // one by one
Rack rack;
Player *player = m_players[m_currPlayer];
player->getCurrentRack().getRack(rack);
+ Tile t;
for (unsigned int i = 0; i < oRound.getWordLen(); i++)
{
if (oRound.isPlayedFromRack(i))
Index: game/game.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.h,v
retrieving revision 1.29.2.7
retrieving revision 1.29.2.8
diff -u -b -r1.29.2.7 -r1.29.2.8
--- game/game.h 20 Dec 2007 08:47:08 -0000 1.29.2.7
+++ game/game.h 23 Dec 2007 23:12:43 -0000 1.29.2.8
@@ -119,25 +119,32 @@
***************/
/**
- * Start the game, and make the AI players play.
- * If the game only has AI players, it will play completely.
+ * Start the game.
+ * AI players are handled automatically, so if the game only has AI
+ * players, it will play until the end.
*/
virtual int start() = 0;
/**
* Method used by human players to play the word iWord at coordinates
* iCoord, and end the turn (if possible)
+ * Possible return values:
+ * 0: correct word, the Round can be used by the caller
+ * 1: one letter of the word is invalid in the current dictionary
+ * 2: invalid coordinates (unreadable or out of the board)
+ * 3: word not present in the dictionary
+ * 4: not enough letters in the rack to play the word
+ * 5: word is part of a longer one
+ * 6: word overwriting an existing letter
+ * 7: invalid crosscheck, or word going out of the board
+ * 8: word already present on the board (no new letter from the rack)
+ * 9: isolated word (not connected to the rest)
+ * 10: first word not horizontal
+ * 11: first word not covering the H8 square
*/
virtual int play(const wstring &iCoord, const wstring &iWord) = 0;
/**
- * End the current turn. This method is automatically called by start()
- * and by play(), so should not be called directly
- * FIXME: Do not make it public then!
- */
- virtual int endTurn() = 0;
-
- /**
* Go back to turn iTurn.
* We must have: iTurn < getHistory().getSize()
* Possible return values:
@@ -218,8 +225,8 @@
* Helper functions
*********************************************************/
- /** Play a round on the board */
- void helperPlayRound(unsigned int iPlayerId, const Round &iRound);
+ /** Play a Move for the given player, updating game history */
+ void helperPlayMove(unsigned int iPlayerId, const Move &iMove);
/**
* Set the rack randomly for the player p
@@ -271,20 +278,7 @@
* This function checks whether it is legal to play the given word at the
* given coordinates. If so, the function fills a Round object, also given
* as a parameter.
- * Possible return values:
- * 0: correct word, the Round can be used by the caller
- * 1: no dictionary set
- * 2: invalid coordinates (unreadable or out of the board)
- * 3: word not present in the dictionary
- * 4: not enough letters in the rack to play the word
- * 5: word is part of a longer one
- * 6: word overwriting an existing letter
- * 7: invalid crosscheck, or word going out of the board
- * 8: word already present on the board (no new letter from the rack)
- * 9: isolated word (not connected to the rest)
- * 10: first word not horizontal
- * 11: first word not covering the H8 square
- * 12: one letter of the word is invalid in the current dictionary
+ * Possible return values: same as the play() method
*/
int checkPlayedWord(const wstring &iCoord,
const wstring &iWord, Round &oRound);
@@ -313,6 +307,12 @@
private:
+ /**
+ * Play a round on the board.
+ * This should only be called by helperPlayMove().
+ */
+ void helperPlayRound(unsigned int iPlayerId, const Round &iRound);
+
};
#endif /* _GAME_H_ */
Index: game/game_io.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_io.cpp,v
retrieving revision 1.4.2.5
retrieving revision 1.4.2.6
diff -u -b -r1.4.2.5 -r1.4.2.6
--- game/game_io.cpp 20 Dec 2007 08:47:08 -0000 1.4.2.5
+++ game/game_io.cpp 23 Dec 2007 23:12:43 -0000 1.4.2.6
@@ -500,15 +500,17 @@
{
const Turn& turn = m_history.getTurn(i);
wstring rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
- wstring word = turn.getRound().getWord();
- string coord =
convertToMb(turn.getRound().getCoord().toString(Coord::COORD_MODE_LONG));
+ // FIXME: this will not work if the move does not correspond to a
played round!
+ const Round &round = turn.getMove().getRound();
+ wstring word = round.getWord();
+ string coord =
convertToMb(round.getCoord().toString(Coord::COORD_MODE_LONG));
// rack [space] word [space] bonus points coord
sprintf(line,"%s%s%c%4d %s",
padAndConvert(rack, 12, false).c_str(),
padAndConvert(word, 16, false).c_str(),
- turn.getRound().getBonus() ? '*' : ' ',
- turn.getRound().getPoints(),
+ round.getBonus() ? '*' : ' ',
+ round.getPoints(),
coord.c_str()
);
@@ -550,16 +552,65 @@
{
const Turn& turn = m_history.getTurn(i);
wstring rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
- wstring word = turn.getRound().getWord();
- string coord = convertToMb(turn.getRound().getCoord().toString());
+ const Move &move = turn.getMove();
+ switch (move.getType())
+ {
+ case Move::VALID_ROUND:
+ {
+ const Round &round = move.getRound();
+ wstring word = round.getWord();
+ string coord = convertToMb(round.getCoord().toString());
sprintf(line, "%2d | %s | %s | %3s | %3d | %1d | %c",
i + 1,
padAndConvert(rack, 8).c_str(), /* pldrack */
padAndConvert(word, 15, false).c_str(), /* word */
coord.c_str(), /* coord */
- turn.getRound().getPoints(),
+ move.getScore(),
turn.getPlayer(),
- turn.getRound().getBonus() ? '*' : ' ');
+ round.getBonus() ? '*' : ' ');
+ break;
+ }
+ case Move::INVALID_WORD:
+ {
+ wstring word = move.getBadWord();
+ string coord = convertToMb(move.getBadCoord());
+ sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+ i + 1,
+ padAndConvert(rack, 8).c_str(), /* pldrack
*/
+ padAndConvert(word, 15, false).c_str(), /* word
*/
+ coord.c_str(), /* coord
*/
+ move.getScore(),
+ turn.getPlayer());
+ break;
+ }
+ case Move::PASS:
+ {
+ string action = "(PASS)";
+ string coord = " - ";
+ sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+ i + 1,
+ padAndConvert(rack, 8).c_str(), /* pldrack
*/
+ truncOrPad(action, 15, ' ').c_str(), /* word
*/
+ coord.c_str(), /* coord
*/
+ move.getScore(),
+ turn.getPlayer());
+ break;
+ }
+ case Move::CHANGE_LETTERS:
+ {
+ wstring action = L"(-" + move.getChangedLetters() + L")";
+ string coord = " - ";
+ sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+ i + 1,
+ padAndConvert(rack, 8).c_str(), /* pldrack
*/
+ padAndConvert(action, 15, false).c_str(), /* word
*/
+ coord.c_str(), /* coord
*/
+ move.getScore(),
+ turn.getPlayer());
+ break;
+ }
+
+ }
out << decal << line << endl;
}
Index: game/history.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/history.cpp,v
retrieving revision 1.10.2.3
retrieving revision 1.10.2.4
diff -u -b -r1.10.2.3 -r1.10.2.4
--- game/history.cpp 17 Dec 2007 11:27:41 -0000 1.10.2.3
+++ game/history.cpp 23 Dec 2007 23:12:43 -0000 1.10.2.4
@@ -27,7 +27,7 @@
#include <string>
#include "rack.h"
#include "pldrack.h"
-#include "round.h"
+#include "move.h"
#include "turn.h"
#include "history.h"
#include "encoding.h"
@@ -90,20 +90,34 @@
}
-void History::playRound(unsigned int player, unsigned int turn, const Round&
round)
+bool History::beforeFirstRound() const
+{
+ for (unsigned int i = 0; i < m_history.size() - 1; i++)
+ {
+ if (m_history[i]->getMove().getType() == Move::VALID_ROUND)
+ return false;
+ }
+ return true;
+}
+
+
+void History::playMove(unsigned int iPlayer, unsigned int iTurn, const Move
&iMove)
{
Turn * current_turn = m_history.back();
- /* set the number and the round */
- current_turn->setNum(turn);
- current_turn->setPlayer(player);
- current_turn->setRound(round);
+ // Set the number and the round
+ current_turn->setNum(iTurn);
+ current_turn->setPlayer(iPlayer);
+ current_turn->setMove(iMove);
- /* get what was the rack for the current turn */
+ // Get what was the rack for the current turn
Rack rack;
current_turn->getPlayedRack().getRack(rack);
- /* remove the played tiles from the rack */
+ if (iMove.getType() == Move::VALID_ROUND)
+ {
+ // Remove the played tiles from the rack
+ const Round &round = iMove.getRound();
for (unsigned int i = 0; i < round.getWordLen(); i++)
{
if (round.isPlayedFromRack(i))
@@ -114,8 +128,18 @@
rack.remove(round.getTile(i));
}
}
+ }
+ else if (iMove.getType() == Move::CHANGE_LETTERS)
+ {
+ // Remove the changed tiles from the rack
+ const wstring & changed = iMove.getChangedLetters();
+ for (unsigned int i = 0; i < changed.size(); ++i)
+ {
+ rack.remove(Tile(changed[i]));
+ }
+ }
- /* create a new turn */
+ // Create a new turn
Turn * next_turn = new Turn();
PlayedRack pldrack;
pldrack.setOld(rack);
@@ -140,7 +164,7 @@
Turn *t = m_history.back();
t->setNum(0);
t->setPlayer(0);
- t->setRound(Round());
+ //t->setRound(Round());
#ifdef BACK_REMOVE_RACK_NEW_PART
t->getPlayedRound().setNew(Rack());
#endif
Index: game/history.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/history.h,v
retrieving revision 1.11.2.2
retrieving revision 1.11.2.3
diff -u -b -r1.11.2.2 -r1.11.2.3
--- game/history.h 17 Dec 2007 11:27:41 -0000 1.11.2.2
+++ game/history.h 23 Dec 2007 23:12:43 -0000 1.11.2.3
@@ -33,7 +33,7 @@
using std::wstring;
using std::vector;
-class Round;
+class Move;
class Turn;
class PlayedRack;
@@ -77,11 +77,19 @@
const Turn& getTurn(unsigned int) const;
/**
- * Update the history with the given round and complete the turn.
+ * Return true if the history doesn't contain at least one move
+ * corresponding to a valid round, false otherwise.
+ * Said differently, this method checks whether a word was already played
+ * on the board.
+ */
+ bool beforeFirstRound() const;
+
+ /**
+ * Update the history with the given move and complete the turn.
* A new turn is created with the unplayed letters in the rack
* 03 sept 2000: We have to sort the tiles according to the new rules
*/
- void playRound(unsigned int player, unsigned int turn, const Round& round);
+ void playMove(unsigned int player, unsigned int turn, const Move &iMove);
/// Remove last turn
void removeLastTurn();
Index: game/player.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/player.cpp,v
retrieving revision 1.14.2.3
retrieving revision 1.14.2.4
diff -u -b -r1.14.2.3 -r1.14.2.4
--- game/player.cpp 20 Dec 2007 08:47:08 -0000 1.14.2.3
+++ game/player.cpp 23 Dec 2007 23:12:44 -0000 1.14.2.4
@@ -55,22 +55,22 @@
}
-const Round & Player::getLastRound() const
+const Move & Player::getLastMove() const
{
- return m_history.getPreviousTurn().getRound();
+ return m_history.getPreviousTurn().getMove();
}
-void Player::endTurn(const Round &iRound, unsigned int iTurn)
+void Player::endTurn(const Move &iMove, unsigned int iTurn)
{
- addPoints(iRound.getPoints());
- m_history.playRound(m_id, iTurn, iRound);
+ addPoints(iMove.getScore());
+ m_history.playMove(m_id, iTurn, iMove);
}
void Player::removeLastTurn()
{
// Remove points of the last turn
- addPoints(- m_history.getPreviousTurn().getRound().getPoints());
+ addPoints(- m_history.getPreviousTurn().getMove().getScore());
m_history.removeLastTurn();
}
Index: game/player.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/player.h,v
retrieving revision 1.18.2.3
retrieving revision 1.18.2.4
diff -u -b -r1.18.2.3 -r1.18.2.4
--- game/player.h 20 Dec 2007 08:47:08 -0000 1.18.2.3
+++ game/player.h 23 Dec 2007 23:12:44 -0000 1.18.2.4
@@ -48,8 +48,8 @@
const PlayedRack & getCurrentRack() const;
// Get the previous rack
const PlayedRack & getLastRack() const;
- // Get the previous round (corresponding to the previous rack...)
- const Round & getLastRound() const;
+ /// Get the previous move (corresponding to the previous rack...)
+ const Move & getLastMove() const;
void setCurrentRack(const PlayedRack &iPld);
@@ -66,11 +66,12 @@
int getPoints() const { return m_score; }
/**
- * Update the player "history", with the given round.
+ * Update the player "history", with the given move.
* A new rack is created with the remaining letters.
- * The points of the rack are added to the player's score.
+ * The score of the player is updated with the one of the move, if it is
+ * meaningful.
*/
- void endTurn(const Round &iRound, unsigned int iTurn);
+ void endTurn(const Move &iMove, unsigned int iTurn);
wstring toString() const;
Index: game/results.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.cpp,v
retrieving revision 1.10.2.3
retrieving revision 1.10.2.4
diff -u -b -r1.10.2.3 -r1.10.2.4
--- game/results.cpp 20 Dec 2007 08:47:08 -0000 1.10.2.3
+++ game/results.cpp 23 Dec 2007 23:12:44 -0000 1.10.2.4
@@ -54,11 +54,11 @@
void Results::search(const Dictionary &iDic, Board &iBoard,
- const Rack &iRack, unsigned int iTurn)
+ const Rack &iRack, bool iFirstWord)
{
clear();
- if (iTurn == 0)
+ if (iFirstWord)
{
iBoard.searchFirst(iDic, iRack, *this);
}
Index: game/results.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.h,v
retrieving revision 1.8.2.4
retrieving revision 1.8.2.5
diff -u -b -r1.8.2.4 -r1.8.2.5
--- game/results.h 20 Dec 2007 08:47:09 -0000 1.8.2.4
+++ game/results.h 23 Dec 2007 23:12:44 -0000 1.8.2.5
@@ -51,9 +51,9 @@
void clear() { m_rounds.clear(); }
const Round & get(unsigned int) const;
- // Perform a search on the board
+ /// Perform a search on the board
void search(const Dictionary &iDic, Board &iBoard,
- const Rack &iRack, unsigned int iTurn);
+ const Rack &iRack, bool iFirstWord);
// FIXME: This method is used to fill the container with the rounds,
// but it should not be part of the public interface
Index: game/settings.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Attic/settings.cpp,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -b -r1.1.2.1 -r1.1.2.2
--- game/settings.cpp 20 Dec 2007 08:47:09 -0000 1.1.2.1
+++ game/settings.cpp 23 Dec 2007 23:12:44 -0000 1.1.2.2
@@ -18,7 +18,6 @@
*****************************************************************************/
#include "settings.h"
-// TMP
#include <stdlib.h>
@@ -44,11 +43,46 @@
Settings::Settings()
{
+ // ============== General options ==============
+
+
+ // ============== Training mode options ==============
+
+
+ // ============== Duplicate mode options ==============
+
// Minimum number of players in a duplicate game needed to apply a "solo"
bonus
// (16 is the ODS value)
m_intHandler.addOption("duplicate-solo-players", 16);
// Number of points granted for a solo (10 is the ODS value)
m_intHandler.addOption("duplicate-solo-value", 10);
+
+ // If true, Eliot complains when the player does something illegal
+ // If false, the word is accepted (with a score of 0) and the player does
+ // not get a second chance
+ m_boolHandler.addOption("duplicate-reject-invalid", false);
+
+
+ // ============== Freegame mode options ==============
+
+ // If true, Eliot complains when the player does something illegal
+ // If false, the word is accepted (with a score of 0) and the player does
+ // not get a second chance.
+ // Trying to change letters or to pass the turn in an incorrect way will
+ // be rejected in any case.
+ m_boolHandler.addOption("freegame-reject-invalid", false);
+}
+
+
+void Settings::setBool(const string &iName, bool iValue)
+{
+ m_boolHandler.setOption(iName, iValue);
+}
+
+
+bool Settings::getBool(const string &iName) const
+{
+ return m_boolHandler.getOption(iName);
}
Index: game/settings.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Attic/settings.h,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -u -b -r1.1.2.1 -r1.1.2.2
--- game/settings.h 20 Dec 2007 08:47:09 -0000 1.1.2.1
+++ game/settings.h 23 Dec 2007 23:12:44 -0000 1.1.2.2
@@ -47,10 +47,12 @@
/// Destroy the singleton cleanly
static void Destroy();
+ void setBool(const string &iName, bool iValue);
+ bool getBool(const string &iName) const;
+
void setInt(const string &iName, int iValue);
int getInt(const string &iName) const;
-
private:
/**
Index: game/training.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.cpp,v
retrieving revision 1.17.2.4
retrieving revision 1.17.2.5
diff -u -b -r1.17.2.4 -r1.17.2.5
--- game/training.cpp 20 Dec 2007 08:47:09 -0000 1.17.2.4
+++ game/training.cpp 23 Dec 2007 23:12:44 -0000 1.17.2.5
@@ -24,6 +24,7 @@
#include "tile.h"
#include "rack.h"
#include "round.h"
+#include "move.h"
#include "pldrack.h"
#include "player.h"
#include "training.h"
@@ -38,22 +39,16 @@
}
-Training::~Training()
-{
-}
-
-
int Training::setRackRandom(bool iCheck, set_rack_mode mode)
{
#define MAX_RANDOM_TRY 5
int res;
int try_number = 0;
- unsigned int p = m_currPlayer;
m_results.clear();
do
{
- res = helperSetRackRandom(p, iCheck, mode);
+ res = helperSetRackRandom(m_currPlayer, iCheck, mode);
try_number ++;
} while (res == 2 && try_number < MAX_RANDOM_TRY);
// 0 : ok
@@ -65,18 +60,14 @@
int Training::setRackManual(bool iCheck, const wstring &iLetters)
{
- int res;
- unsigned int p = m_currPlayer;
- wstring::iterator it;
- wstring upperLetters = iLetters;
// 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
- upperLetters = iLetters;
+ wstring upperLetters = iLetters;
std::transform(upperLetters.begin(), upperLetters.end(),
upperLetters.begin(), towupper);
- res = helperSetRackManual(p, iCheck, upperLetters);
+ int res = helperSetRackManual(m_currPlayer, iCheck, upperLetters);
// 0: ok
// 1: not enough tiles
// 2: check failed (number of vowels before round 15)
@@ -108,7 +99,7 @@
int Training::play(const wstring &iCoord, const wstring &iWord)
{
- /* Perform all the validity checks, and fill a round */
+ // Perform all the validity checks, and fill a round
Round round;
int res = checkPlayedWord(iCoord, iWord, round);
@@ -118,20 +109,21 @@
return res;
}
- /* Update the rack and the score of the current player */
debug("play: %s %s %d\n",
convertToMb(round.getWord()).c_str(),
convertToMb(round.getCoord().toString()).c_str(),
round.getPoints());
- // Player::endTurn() must be called before Game::helperPlayRound().
+ Move move(round);
+ // Update the rack and the score of the current player
+ // Player::endTurn() must be called before Game::helperPlayMove().
// See the big comment in game.cpp, line 96
- m_players[m_currPlayer]->endTurn(round, m_history.getSize());
+ m_players[m_currPlayer]->endTurn(move, m_history.getSize());
- /* Everything is OK, we can play the word */
- helperPlayRound(m_currPlayer, round);
+ // Everything is OK, we can play the word
+ helperPlayMove(m_currPlayer, move);
- /* Next turn */
+ // Next turn
endTurn();
return 0;
@@ -150,10 +142,9 @@
}
-int Training::endTurn()
+void Training::endTurn()
{
- // Nothing to do?
- return 0;
+ // Nothing to do, but this method is kept for consistency with other modes
}
@@ -163,7 +154,7 @@
Rack r;
m_players[m_currPlayer]->getCurrentRack().getRack(r);
debug("Training::search for %s\n", convertToMb(r.toString()).c_str());
- m_results.search(m_dic, m_board, r, m_history.getSize());
+ m_results.search(m_dic, m_board, r, m_history.beforeFirstRound());
}
@@ -171,16 +162,16 @@
{
if (n >= m_results.size())
return 2;
- const Round &round = m_results.get(n);
- /* Update the rack and the score of the current player */
- m_players[m_currPlayer]->endTurn(round, m_history.getSize());
+ Move move(m_results.get(n));
+ // Update the rack and the score of the current player
+ m_players[m_currPlayer]->endTurn(move, m_history.getSize());
- helperPlayRound(m_currPlayer, round);
+ // Update the game
+ helperPlayMove(m_currPlayer, move);
m_results.clear();
- /* Next turn */
- // XXX: Should it be done by the interface instead?
+ // Next turn
endTurn();
return 0;
@@ -201,9 +192,9 @@
}
-void Training::testPlay(int num)
+void Training::testPlay(unsigned int num)
{
- ASSERT(0 <= num && num < m_results.size(), "Wrong result number");
+ ASSERT(num < m_results.size(), "Wrong result number");
m_testRound = m_results.get(num);
m_board.testRound(m_results.get(num));
}
Index: game/training.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.h,v
retrieving revision 1.15.2.1
retrieving revision 1.15.2.2
diff -u -b -r1.15.2.1 -r1.15.2.2
--- game/training.h 20 Dec 2007 08:47:09 -0000 1.15.2.1
+++ game/training.h 23 Dec 2007 23:12:44 -0000 1.15.2.2
@@ -24,6 +24,7 @@
#include <string>
#include "game.h"
+#include "round.h"
#include "results.h"
using std::string;
@@ -34,6 +35,7 @@
* This class handles the logic specific to a training game.
* As its name indicates, it is not a game in the literal meaning of the word,
* in particular because the rack can be set at will.
+ *
* Note: No player should be added to this game, a human player is added
* automatically (in the start() method)
*/
@@ -48,9 +50,12 @@
* Game handling
*************************/
virtual int start();
+
+ /// See description of Game::play()
virtual int play(const wstring &iCoord, const wstring &iWord);
- virtual int endTurn();
+
void search();
+ const Results& getResults() const { return m_results; };
int playResult(unsigned int);
int setRackRandom(bool, set_rack_mode);
@@ -59,7 +64,7 @@
/*************************
* Override the default behaviour of these methods, because in training
- * we only want a human player
+ * mode we only want a human player
*************************/
virtual void addHumanPlayer();
virtual void addAIPlayer();
@@ -68,23 +73,25 @@
* Functions to access the current search results
* The int parameter should be 0 <= int < getNResults
*************************/
- const Results& getResults() const { return m_results; };
- /// Place a temporary word on the board for preview purpose
- void testPlay(int);
- /// Remove the temporary word(s)
+ /// Place a temporary word on the board for preview purposes
+ void testPlay(unsigned int);
+ /// Remove the temporary word
void removeTestPlay();
/// Get the temporary word
wstring getTestPlayWord() const;
private:
- // Private constructor and destructor to force using the GameFactory class
+ /// Private constructor and destructor to force using the GameFactory class
Training(const Dictionary &iDic);
- virtual ~Training();
- // Search results, with all the possible rounds
- Round m_testRound;
+ void endTurn();
+
+ /// Search results, with all the possible rounds
Results m_results;
+
+ /// Round corresponding to the last test play (if any)
+ Round m_testRound;
};
#endif /* _TRAINING_H_ */
Index: game/turn.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/turn.cpp,v
retrieving revision 1.11.2.2
retrieving revision 1.11.2.3
diff -u -b -r1.11.2.2 -r1.11.2.3
--- game/turn.cpp 17 Dec 2007 11:27:42 -0000 1.11.2.2
+++ game/turn.cpp 23 Dec 2007 23:12:44 -0000 1.11.2.3
@@ -19,38 +19,37 @@
/**
* \file turn.cpp
- * \brief Game turn (= id + pldrack + round)
+ * \brief Game turn (= id + pldrack + move)
* \author Antoine Fraboulet
* \date 2005
*/
-#include <string>
-#include "pldrack.h"
-#include "round.h"
#include "turn.h"
+// FIXME: move set to an invalid value. It would be better to get rid of this
+// constructor completely
Turn::Turn()
- : m_num(0), m_playerId(0)
+ : m_num(0), m_playerId(0), m_move(L"", L"")
{
}
Turn::Turn(unsigned int iNum, unsigned int iPlayerId,
- const PlayedRack& iPldRack, const Round& iRound)
- : m_num(iNum), m_playerId(iPlayerId), m_pldrack(iPldRack), m_round(iRound)
+ const PlayedRack& iPldRack, const Move& iMove)
+ : m_num(iNum), m_playerId(iPlayerId), m_pldrack(iPldRack), m_move(iMove)
{
}
wstring Turn::toString(bool iShowExtraSigns) const
{
- wstring rs = L"";
+ wstring rs;
if (iShowExtraSigns)
{
// TODO
}
- rs = rs + m_pldrack.toString() + L" " + m_round.toString();
+ rs = rs + m_pldrack.toString() + L" " + m_move.toString();
return rs;
}
Index: game/turn.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/turn.h,v
retrieving revision 1.9.2.2
retrieving revision 1.9.2.3
diff -u -b -r1.9.2.2 -r1.9.2.3
--- game/turn.h 17 Dec 2007 11:27:42 -0000 1.9.2.2
+++ game/turn.h 23 Dec 2007 23:12:44 -0000 1.9.2.3
@@ -19,7 +19,7 @@
/**
* \file turn.h
- * \brief Game turn (= id + pldrack + round)
+ * \brief Game turn (= id + pldrack + move)
* \author Antoine Fraboulet
* \date 2005
*/
@@ -28,13 +28,15 @@
#define _TURN_H
#include <string>
+#include "pldrack.h"
+#include "move.h"
using std::wstring;
/**
* A Turn is the information about one 'move' done by a player.
- * It consists of the player who played, the rack, and the played round.
+ * It consists of the player who played, the rack, and the actual move.
* A turn also has an id (XXX: currently never read)
*
* This class has no logic, it is merely there to aggregate corresponding
@@ -45,17 +47,17 @@
public:
Turn();
Turn(unsigned int iNum, unsigned int iPlayerId,
- const PlayedRack& iPldRack, const Round& iRound);
+ const PlayedRack& iPldRack, const Move& iMove);
void setNum(unsigned int iNum) { m_num = iNum; }
void setPlayer(unsigned int iPlayerId) { m_playerId = iPlayerId; }
void setPlayedRack(const PlayedRack& iPldRack) { m_pldrack = iPldRack; }
- void setRound(const Round& iRound) { m_round = iRound; }
+ void setMove(const Move& iMove) { m_move = iMove; }
unsigned int getNum() const { return m_num; }
unsigned int getPlayer() const { return m_playerId; }
const PlayedRack& getPlayedRack() const { return m_pldrack; }
- const Round& getRound() const { return m_round; }
+ const Move& getMove() const { return m_move; }
wstring toString(bool iShowExtraSigns = false) const;
@@ -63,8 +65,7 @@
unsigned int m_num;
unsigned int m_playerId;
PlayedRack m_pldrack;
- Round m_round;
-
+ Move m_move;
};
#endif
Index: po/eliot.pot
===================================================================
RCS file: /cvsroot/eliot/eliot/po/eliot.pot,v
retrieving revision 1.6.6.6
retrieving revision 1.6.6.7
diff -u -b -r1.6.6.6 -r1.6.6.7
--- po/eliot.pot 16 Dec 2007 18:20:55 -0000 1.6.6.6
+++ po/eliot.pot 23 Dec 2007 23:12:45 -0000 1.6.6.7
@@ -8,7 +8,7 @@
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-12-16 19:18+0100\n"
+"POT-Creation-Date: 2007-12-23 23:08+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <address@hidden>\n"
"Language-Team: LANGUAGE <address@hidden>\n"
@@ -286,125 +286,129 @@
msgid "Search results"
msgstr ""
-#: utils/ncurses.cpp:344
+#: utils/ncurses.cpp:345
msgid "History of the game"
msgstr ""
-#: utils/ncurses.cpp:350
+#: utils/ncurses.cpp:351
msgid " N | RACK | SOLUTION | REF | PTS | P | BONUS"
msgstr ""
-#: utils/ncurses.cpp:384
+#: utils/ncurses.cpp:390
+msgid "(PASS)"
+msgstr ""
+
+#: utils/ncurses.cpp:416
msgid "Help"
msgstr ""
-#: utils/ncurses.cpp:388
+#: utils/ncurses.cpp:420
msgid "[Global]"
msgstr ""
-#: utils/ncurses.cpp:389
+#: utils/ncurses.cpp:421
msgid " h, H, ? Show/hide help box"
msgstr ""
-#: utils/ncurses.cpp:390
+#: utils/ncurses.cpp:422
msgid " y, Y Show/hide history of the game"
msgstr ""
-#: utils/ncurses.cpp:391
+#: utils/ncurses.cpp:423
msgid ""
" b, B Show/hide contents of the bag (including letters of the "
"racks)"
msgstr ""
-#: utils/ncurses.cpp:392
+#: utils/ncurses.cpp:424
msgid " e, E Show/hide dots on empty squares of the board"
msgstr ""
-#: utils/ncurses.cpp:393
+#: utils/ncurses.cpp:425
msgid " d, D Check the existence of a word in the dictionary"
msgstr ""
-#: utils/ncurses.cpp:394
+#: utils/ncurses.cpp:426
msgid " j, J Play a word"
msgstr ""
-#: utils/ncurses.cpp:395
+#: utils/ncurses.cpp:427
msgid " s, S Save the game"
msgstr ""
-#: utils/ncurses.cpp:396
+#: utils/ncurses.cpp:428
msgid " l, L Load a game"
msgstr ""
-#: utils/ncurses.cpp:397
+#: utils/ncurses.cpp:429
msgid " q, Q Quit"
msgstr ""
-#: utils/ncurses.cpp:400
+#: utils/ncurses.cpp:432
msgid "[Training mode]"
msgstr ""
-#: utils/ncurses.cpp:401
+#: utils/ncurses.cpp:433
msgid " * Take a random rack"
msgstr ""
-#: utils/ncurses.cpp:402
+#: utils/ncurses.cpp:434
msgid " + Complete the current rack randomly"
msgstr ""
-#: utils/ncurses.cpp:403
+#: utils/ncurses.cpp:435
msgid " t, T Set the rack manually"
msgstr ""
-#: utils/ncurses.cpp:404
+#: utils/ncurses.cpp:436
msgid " c, C Compute all the possible words"
msgstr ""
-#: utils/ncurses.cpp:405
+#: utils/ncurses.cpp:437
msgid " r, R Show/hide search results"
msgstr ""
-#: utils/ncurses.cpp:408
+#: utils/ncurses.cpp:440
msgid "[Duplicate mode]"
msgstr ""
-#: utils/ncurses.cpp:409
+#: utils/ncurses.cpp:441
msgid " n, N Switch to the next human player"
msgstr ""
-#: utils/ncurses.cpp:412
+#: utils/ncurses.cpp:444
msgid "[Free game mode]"
msgstr ""
-#: utils/ncurses.cpp:413
+#: utils/ncurses.cpp:445
msgid " p, P Pass your turn (with or without changing letters)"
msgstr ""
-#: utils/ncurses.cpp:416
+#: utils/ncurses.cpp:448
msgid "[Miscellaneous]"
msgstr ""
-#: utils/ncurses.cpp:417
+#: utils/ncurses.cpp:449
msgid " <up>, <down> Navigate in a box line by line"
msgstr ""
-#: utils/ncurses.cpp:418
+#: utils/ncurses.cpp:450
msgid " <pgup>, <pgdown> Navigate in a box page by page"
msgstr ""
-#: utils/ncurses.cpp:419
+#: utils/ncurses.cpp:451
msgid " Ctrl-l Refresh the screen"
msgstr ""
-#: utils/ncurses.cpp:430 wxwin/auxframes.cc:148
+#: utils/ncurses.cpp:462 wxwin/auxframes.cc:148
msgid "Bag"
msgstr ""
-#: utils/ncurses.cpp:437
+#: utils/ncurses.cpp:469
msgid " LETTER | POINTS | FREQUENCY | REMAINING"
msgstr ""
-#: utils/ncurses.cpp:490
+#: utils/ncurses.cpp:522
msgid "Play a word"
msgstr ""
@@ -412,115 +416,115 @@
#. "Coordinates:". For example:
#. Pl. word :
#. Coordinates:
-#: utils/ncurses.cpp:491 utils/ncurses.cpp:499
+#: utils/ncurses.cpp:523 utils/ncurses.cpp:531
msgid "Played word:"
msgstr ""
-#: utils/ncurses.cpp:492 utils/ncurses.cpp:500
+#: utils/ncurses.cpp:524 utils/ncurses.cpp:532
msgid "Coordinates:"
msgstr ""
-#: utils/ncurses.cpp:514
+#: utils/ncurses.cpp:546
msgid "Incorrect or misplaced word"
msgstr ""
-#: utils/ncurses.cpp:524
+#: utils/ncurses.cpp:556
msgid "Dictionary"
msgstr ""
-#: utils/ncurses.cpp:525
+#: utils/ncurses.cpp:557
msgid "Enter the word to check:"
msgstr ""
-#: utils/ncurses.cpp:534
+#: utils/ncurses.cpp:566
#, c-format
msgid "The word '%ls' exists"
msgstr ""
-#: utils/ncurses.cpp:536
+#: utils/ncurses.cpp:568
#, c-format
msgid "The word '%ls' does not exist"
msgstr ""
-#: utils/ncurses.cpp:546 wxwin/mainframe.cc:464 wxwin/mainframe.cc:472
+#: utils/ncurses.cpp:578 wxwin/mainframe.cc:460 wxwin/mainframe.cc:468
msgid "Save the game"
msgstr ""
-#: utils/ncurses.cpp:547 utils/ncurses.cpp:576
+#: utils/ncurses.cpp:579 utils/ncurses.cpp:609
msgid "Enter the file name:"
msgstr ""
-#: utils/ncurses.cpp:557
+#: utils/ncurses.cpp:589
#, c-format
msgid "Cannot open file %ls for writing"
msgstr ""
-#: utils/ncurses.cpp:564
+#: utils/ncurses.cpp:597
#, c-format
-msgid "Game saved in %ls"
+msgid "Game saved in '%ls'"
msgstr ""
-#: utils/ncurses.cpp:575 wxwin/mainframe.cc:268 wxwin/mainframe.cc:389
-#: wxwin/mainframe.cc:413
+#: utils/ncurses.cpp:608 wxwin/mainframe.cc:269 wxwin/mainframe.cc:390
+#: wxwin/mainframe.cc:414
msgid "Load a game"
msgstr ""
-#: utils/ncurses.cpp:586
+#: utils/ncurses.cpp:619
#, c-format
-msgid "Cannot open file %ls for reading"
+msgid "Cannot open file '%ls' for reading"
msgstr ""
-#: utils/ncurses.cpp:594
+#: utils/ncurses.cpp:627
#, c-format
msgid "Invalid saved game"
msgstr ""
-#: utils/ncurses.cpp:598
+#: utils/ncurses.cpp:632
#, c-format
msgid "Game loaded"
msgstr ""
-#: utils/ncurses.cpp:613
+#: utils/ncurses.cpp:647
msgid "Pass your turn"
msgstr ""
-#: utils/ncurses.cpp:614
+#: utils/ncurses.cpp:648
msgid "Enter the letters to change:"
msgstr ""
-#: utils/ncurses.cpp:623
+#: utils/ncurses.cpp:657
msgid "Cannot pass the turn"
msgstr ""
-#: utils/ncurses.cpp:633
+#: utils/ncurses.cpp:667
msgid "Set rack"
msgstr ""
-#: utils/ncurses.cpp:634
+#: utils/ncurses.cpp:668
msgid "Enter the new letters:"
msgstr ""
-#: utils/ncurses.cpp:643
+#: utils/ncurses.cpp:677
msgid "Cannot take these letters from the bag"
msgstr ""
-#: utils/ncurses.cpp:1037
+#: utils/ncurses.cpp:1071
msgid "Training mode"
msgstr ""
-#: utils/ncurses.cpp:1039
+#: utils/ncurses.cpp:1073
msgid "Free game mode"
msgstr ""
-#: utils/ncurses.cpp:1041
+#: utils/ncurses.cpp:1075
msgid "Duplicate mode"
msgstr ""
-#: utils/ncurses.cpp:1044
+#: utils/ncurses.cpp:1078
msgid "Joker game"
msgstr ""
-#: utils/ncurses.cpp:1045
+#: utils/ncurses.cpp:1079
msgid "[h for help]"
msgstr ""
@@ -556,8 +560,8 @@
msgid "Copy"
msgstr ""
-#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:491 wxwin/mainframe.cc:511
-#: wxwin/mainframe.cc:542
+#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:487 wxwin/mainframe.cc:507
+#: wxwin/mainframe.cc:538
msgid "No on going game"
msgstr ""
@@ -569,11 +573,11 @@
msgid "Rack: "
msgstr ""
-#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:318
+#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:319
msgid "Game history"
msgstr ""
-#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:320
+#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:321
msgid "Results"
msgstr ""
@@ -685,7 +689,7 @@
msgid "Nb"
msgstr ""
-#: wxwin/configdb.cc:323 wxwin/mainframe.cc:173
+#: wxwin/configdb.cc:323 wxwin/mainframe.cc:174
msgid "Rack"
msgstr ""
@@ -721,396 +725,396 @@
msgid "Results of the search"
msgstr ""
-#: wxwin/mainframe.cc:204
+#: wxwin/mainframe.cc:205
msgid " Rack "
msgstr ""
-#: wxwin/mainframe.cc:205
+#: wxwin/mainframe.cc:206
msgid " Complement "
msgstr ""
-#: wxwin/mainframe.cc:206
+#: wxwin/mainframe.cc:207
msgid " Search "
msgstr ""
-#: wxwin/mainframe.cc:207
+#: wxwin/mainframe.cc:208
msgid " Back "
msgstr ""
-#: wxwin/mainframe.cc:208
+#: wxwin/mainframe.cc:209
msgid " Play "
msgstr ""
-#: wxwin/mainframe.cc:210
+#: wxwin/mainframe.cc:211
msgid "Random rack"
msgstr ""
-#: wxwin/mainframe.cc:211
+#: wxwin/mainframe.cc:212
msgid "Random complement of the rack"
msgstr ""
-#: wxwin/mainframe.cc:212
+#: wxwin/mainframe.cc:213
msgid "Search with the current rack"
msgstr ""
-#: wxwin/mainframe.cc:213
+#: wxwin/mainframe.cc:214
msgid "Go back one turn"
msgstr ""
-#: wxwin/mainframe.cc:214
+#: wxwin/mainframe.cc:215
msgid "Play the selected word"
msgstr ""
-#: wxwin/mainframe.cc:265
+#: wxwin/mainframe.cc:266
msgid "&New game\tctrl+n"
msgstr ""
-#: wxwin/mainframe.cc:265
+#: wxwin/mainframe.cc:266
msgid "Start a new game"
msgstr ""
-#: wxwin/mainframe.cc:266
+#: wxwin/mainframe.cc:267
msgid "New &joker game\tctrl+j"
msgstr ""
-#: wxwin/mainframe.cc:266
+#: wxwin/mainframe.cc:267
msgid "Start a new joker game"
msgstr ""
-#: wxwin/mainframe.cc:268
+#: wxwin/mainframe.cc:269
msgid "&Load...\tctrl+l"
msgstr ""
-#: wxwin/mainframe.cc:269
+#: wxwin/mainframe.cc:270
msgid "&Save as...\tctrl+s"
msgstr ""
-#: wxwin/mainframe.cc:269
+#: wxwin/mainframe.cc:270
msgid "Save the current game"
msgstr ""
-#: wxwin/mainframe.cc:271
+#: wxwin/mainframe.cc:272
msgid "&Print...\tctrl+p"
msgstr ""
-#: wxwin/mainframe.cc:271
+#: wxwin/mainframe.cc:272
msgid "Print this game"
msgstr ""
-#: wxwin/mainframe.cc:272
+#: wxwin/mainframe.cc:273
msgid "Print pre&view..."
msgstr ""
-#: wxwin/mainframe.cc:272
+#: wxwin/mainframe.cc:273
msgid "Print preview of the game"
msgstr ""
-#: wxwin/mainframe.cc:274
+#: wxwin/mainframe.cc:275
msgid "Print in PostS&cript..."
msgstr ""
-#: wxwin/mainframe.cc:274
+#: wxwin/mainframe.cc:275
msgid "Print in a PostScript file"
msgstr ""
-#: wxwin/mainframe.cc:277
+#: wxwin/mainframe.cc:278
msgid "&Quit"
msgstr ""
-#: wxwin/mainframe.cc:277
+#: wxwin/mainframe.cc:278
msgid "Quit Eliot"
msgstr ""
-#: wxwin/mainframe.cc:280
+#: wxwin/mainframe.cc:281
msgid "&Dictionary..."
msgstr ""
-#: wxwin/mainframe.cc:280 wxwin/mainframe.cc:593
+#: wxwin/mainframe.cc:281 wxwin/mainframe.cc:589
msgid "Choose a dictionary"
msgstr ""
-#: wxwin/mainframe.cc:281
+#: wxwin/mainframe.cc:282
msgid "&Search..."
msgstr ""
-#: wxwin/mainframe.cc:281
+#: wxwin/mainframe.cc:282
msgid "Search options"
msgstr ""
-#: wxwin/mainframe.cc:284
+#: wxwin/mainframe.cc:285
msgid "&Background..."
msgstr ""
-#: wxwin/mainframe.cc:284
+#: wxwin/mainframe.cc:285
msgid "Background color"
msgstr ""
-#: wxwin/mainframe.cc:285
+#: wxwin/mainframe.cc:286
msgid "L&ines..."
msgstr ""
-#: wxwin/mainframe.cc:285
+#: wxwin/mainframe.cc:286
msgid "Color of the lines"
msgstr ""
-#: wxwin/mainframe.cc:287
+#: wxwin/mainframe.cc:288
msgid "&Played letters..."
msgstr ""
-#: wxwin/mainframe.cc:287
+#: wxwin/mainframe.cc:288
msgid "Color of the letters played on the board"
msgstr ""
-#: wxwin/mainframe.cc:288
+#: wxwin/mainframe.cc:289
msgid "&Temporary letters..."
msgstr ""
-#: wxwin/mainframe.cc:288
+#: wxwin/mainframe.cc:289
msgid "Color of the letters of the temporary word"
msgstr ""
-#: wxwin/mainframe.cc:289
+#: wxwin/mainframe.cc:290
msgid "B&ackground of played letters..."
msgstr ""
-#: wxwin/mainframe.cc:289
+#: wxwin/mainframe.cc:290
msgid "Background color of the letters played on the board"
msgstr ""
-#: wxwin/mainframe.cc:290
+#: wxwin/mainframe.cc:291
msgid "Ba&ckground of temporary letters..."
msgstr ""
-#: wxwin/mainframe.cc:290
+#: wxwin/mainframe.cc:291
msgid "Background color of the temporary letters on the board"
msgstr ""
-#: wxwin/mainframe.cc:292
+#: wxwin/mainframe.cc:293
msgid "Double &letter..."
msgstr ""
-#: wxwin/mainframe.cc:292
+#: wxwin/mainframe.cc:293
msgid "Color of the \"double letter\" squares"
msgstr ""
-#: wxwin/mainframe.cc:293
+#: wxwin/mainframe.cc:294
msgid "Triple l&etter..."
msgstr ""
-#: wxwin/mainframe.cc:293
+#: wxwin/mainframe.cc:294
msgid "Color of the \"triple letter\" squares"
msgstr ""
-#: wxwin/mainframe.cc:294
+#: wxwin/mainframe.cc:295
msgid "Double &word..."
msgstr ""
-#: wxwin/mainframe.cc:294
+#: wxwin/mainframe.cc:295
msgid "Color of the \"double word\" squares"
msgstr ""
-#: wxwin/mainframe.cc:295
+#: wxwin/mainframe.cc:296
msgid "Triple w&ord..."
msgstr ""
-#: wxwin/mainframe.cc:295
+#: wxwin/mainframe.cc:296
msgid "Color of the \"triple word\" squares"
msgstr ""
-#: wxwin/mainframe.cc:297
+#: wxwin/mainframe.cc:298
msgid "&Default colors"
msgstr ""
-#: wxwin/mainframe.cc:297
+#: wxwin/mainframe.cc:298
msgid "Restore the default colors"
msgstr ""
-#: wxwin/mainframe.cc:300
+#: wxwin/mainframe.cc:301
msgid "&Search letters..."
msgstr ""
-#: wxwin/mainframe.cc:300
+#: wxwin/mainframe.cc:301
msgid "Font for the search"
msgstr ""
-#: wxwin/mainframe.cc:303 wxwin/mainframe.cc:327
+#: wxwin/mainframe.cc:304 wxwin/mainframe.cc:328
msgid "&Game"
msgstr ""
-#: wxwin/mainframe.cc:303
+#: wxwin/mainframe.cc:304
msgid "Configuration of the game"
msgstr ""
-#: wxwin/mainframe.cc:304
+#: wxwin/mainframe.cc:305
msgid "&Fonts"
msgstr ""
-#: wxwin/mainframe.cc:304
+#: wxwin/mainframe.cc:305
msgid "Configuration of the fonts"
msgstr ""
-#: wxwin/mainframe.cc:305
+#: wxwin/mainframe.cc:306
msgid "&Colors"
msgstr ""
-#: wxwin/mainframe.cc:305
+#: wxwin/mainframe.cc:306
msgid "Configuration of the colors"
msgstr ""
-#: wxwin/mainframe.cc:306
+#: wxwin/mainframe.cc:307
msgid "&Printing..."
msgstr ""
-#: wxwin/mainframe.cc:306
+#: wxwin/mainframe.cc:307
msgid "Configuration of the printing parameters"
msgstr ""
-#: wxwin/mainframe.cc:309
+#: wxwin/mainframe.cc:310
msgid "&Board"
msgstr ""
-#: wxwin/mainframe.cc:309
+#: wxwin/mainframe.cc:310
msgid "Game board"
msgstr ""
-#: wxwin/mainframe.cc:310
+#: wxwin/mainframe.cc:311
msgid "Ba&g"
msgstr ""
-#: wxwin/mainframe.cc:310
+#: wxwin/mainframe.cc:311
msgid "Remaining letters in the bag"
msgstr ""
-#: wxwin/mainframe.cc:311
+#: wxwin/mainframe.cc:312
msgid "&Check"
msgstr ""
-#: wxwin/mainframe.cc:311
+#: wxwin/mainframe.cc:312
msgid "Check a word in the dictionary"
msgstr ""
-#: wxwin/mainframe.cc:312
+#: wxwin/mainframe.cc:313
msgid "&Search"
msgstr ""
-#: wxwin/mainframe.cc:312
+#: wxwin/mainframe.cc:313
msgid "Search in the dictionary"
msgstr ""
-#: wxwin/mainframe.cc:314
+#: wxwin/mainframe.cc:315
msgid "&Rack + 1"
msgstr ""
-#: wxwin/mainframe.cc:314
+#: wxwin/mainframe.cc:315
msgid "Letters of the rack plus one"
msgstr ""
-#: wxwin/mainframe.cc:315
+#: wxwin/mainframe.cc:316
msgid "R&accords"
msgstr ""
-#: wxwin/mainframe.cc:315
+#: wxwin/mainframe.cc:316
msgid "Raccords on a word of the search"
msgstr ""
-#: wxwin/mainframe.cc:316
+#: wxwin/mainframe.cc:317
msgid "&Benjamins"
msgstr ""
-#: wxwin/mainframe.cc:316
+#: wxwin/mainframe.cc:317
msgid "Benjamins on a word of the search"
msgstr ""
-#: wxwin/mainframe.cc:318
+#: wxwin/mainframe.cc:319
msgid "Game &history"
msgstr ""
-#: wxwin/mainframe.cc:320
+#: wxwin/mainframe.cc:321
msgid "R&esults"
msgstr ""
-#: wxwin/mainframe.cc:324
+#: wxwin/mainframe.cc:325
msgid "&About..."
msgstr ""
-#: wxwin/mainframe.cc:324 wxwin/mainframe.cc:722
+#: wxwin/mainframe.cc:325 wxwin/mainframe.cc:718
msgid "About Eliot"
msgstr ""
-#: wxwin/mainframe.cc:328
+#: wxwin/mainframe.cc:329
msgid "&Settings"
msgstr ""
-#: wxwin/mainframe.cc:329
+#: wxwin/mainframe.cc:330
msgid "&Windows"
msgstr ""
-#: wxwin/mainframe.cc:330
+#: wxwin/mainframe.cc:331
msgid "&Help"
msgstr ""
-#: wxwin/mainframe.cc:354 wxwin/mainframe.cc:392
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393
msgid "No dictionary selected"
msgstr ""
-#: wxwin/mainframe.cc:354 wxwin/mainframe.cc:392 wxwin/mainframe.cc:491
-#: wxwin/mainframe.cc:511 wxwin/mainframe.cc:542
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393 wxwin/mainframe.cc:487
+#: wxwin/mainframe.cc:507 wxwin/mainframe.cc:538
msgid "Eliot: error"
msgstr ""
-#: wxwin/mainframe.cc:412
+#: wxwin/mainframe.cc:413
msgid "Cannot open "
msgstr ""
-#: wxwin/mainframe.cc:424 wxwin/mainframe.cc:433
+#: wxwin/mainframe.cc:425 wxwin/mainframe.cc:434
msgid "Error while loading the game"
msgstr ""
-#: wxwin/mainframe.cc:425
+#: wxwin/mainframe.cc:426
msgid "Invalid game"
msgstr ""
-#: wxwin/mainframe.cc:434
+#: wxwin/mainframe.cc:435
msgid "The game is empty"
msgstr ""
-#: wxwin/mainframe.cc:471
+#: wxwin/mainframe.cc:467
msgid "Cannot create "
msgstr ""
-#: wxwin/mainframe.cc:500 wxwin/mainframe.cc:564
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:560
msgid "Printing not done"
msgstr ""
-#: wxwin/mainframe.cc:500 wxwin/mainframe.cc:528
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:524
msgid "Printing"
msgstr ""
-#: wxwin/mainframe.cc:523
+#: wxwin/mainframe.cc:519
msgid "Print preview problem.\n"
msgstr ""
-#: wxwin/mainframe.cc:524
+#: wxwin/mainframe.cc:520
msgid "The printer may not be correctly initialized"
msgstr ""
-#: wxwin/mainframe.cc:525
+#: wxwin/mainframe.cc:521
msgid "Print preview"
msgstr ""
-#: wxwin/mainframe.cc:546
+#: wxwin/mainframe.cc:542
msgid "Print to a PostScript file"
msgstr ""
-#: wxwin/mainframe.cc:565 wxwin/mainframe.cc:571
+#: wxwin/mainframe.cc:561 wxwin/mainframe.cc:567
msgid "PostScript printing"
msgstr ""
-#: wxwin/mainframe.cc:570
+#: wxwin/mainframe.cc:566
msgid "Cannot initialize PostScript printer"
msgstr ""
-#: wxwin/mainframe.cc:718
+#: wxwin/mainframe.cc:714
msgid ""
"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 "
@@ -1118,52 +1122,57 @@
"any later version."
msgstr ""
-#: wxwin/mainframe.cc:916
+#: wxwin/mainframe.cc:912
msgid "turn:"
msgstr ""
-#: wxwin/mainframe.cc:917
+#: wxwin/mainframe.cc:913
msgid "points:"
msgstr ""
-#: wxwin/mainframe.cc:954
+#: wxwin/mainframe.cc:948
msgid ""
"The bag doesn't contain enough letters\n"
"for a new rack."
msgstr ""
-#: wxwin/mainframe.cc:955 wxwin/mainframe.cc:959 wxwin/mainframe.cc:963
+#: wxwin/mainframe.cc:949 wxwin/mainframe.cc:953 wxwin/mainframe.cc:957
msgid "Rack validation"
msgstr ""
-#: wxwin/mainframe.cc:958
+#: wxwin/mainframe.cc:952
msgid "The rack must contain at least 2 consonants and 2 vowels."
msgstr ""
-#: wxwin/mainframe.cc:962
+#: wxwin/mainframe.cc:956
msgid "The rack contains invalid letters for the current dictionary"
msgstr ""
-#: wxwin/mainframe.cc:966
+#: wxwin/mainframe.cc:960
msgid "The rack has been modified manually"
msgstr ""
-#: wxwin/searchpanel.cc:303
+#: wxwin/searchpanel.cc:146 wxwin/searchpanel.cc:190
+#, c-format
+msgid "The search is limited to %d letters"
+msgstr ""
+
+#: wxwin/searchpanel.cc:301
msgid "Minimum length"
msgstr ""
-#: wxwin/searchpanel.cc:305
+#: wxwin/searchpanel.cc:303
msgid "Maximum length"
msgstr ""
-#: wxwin/searchpanel.cc:368
+#: wxwin/searchpanel.cc:366
msgid "Cross words"
msgstr ""
-#: wxwin/searchpanel.cc:369
+#: wxwin/searchpanel.cc:367
msgid "Plus 1"
msgstr ""
-#: wxwin/searchpanel.cc:370
+#: wxwin/searchpanel.cc:368
msgid "Regular expressions"
msgstr ""
Index: po/fr.po
===================================================================
RCS file: /cvsroot/eliot/eliot/po/fr.po,v
retrieving revision 1.6.6.6
retrieving revision 1.6.6.7
diff -u -b -r1.6.6.6 -r1.6.6.7
--- po/fr.po 16 Dec 2007 18:20:55 -0000 1.6.6.6
+++ po/fr.po 23 Dec 2007 23:12:45 -0000 1.6.6.7
@@ -8,7 +8,7 @@
msgstr ""
"Project-Id-Version: eliot 1.4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-12-16 19:18+0100\n"
+"POT-Creation-Date: 2007-12-23 23:08+0100\n"
"PO-Revision-Date: 2005-02-06 20:03+0100\n"
"Last-Translator: Olivier Teuliere <address@hidden>\n"
"Language-Team: French <address@hidden>\n"
@@ -302,31 +302,35 @@
msgid "Search results"
msgstr "Résultats de la recherche"
-#: utils/ncurses.cpp:344
+#: utils/ncurses.cpp:345
msgid "History of the game"
msgstr "Historique de la partie"
-#: utils/ncurses.cpp:350
+#: utils/ncurses.cpp:351
msgid " N | RACK | SOLUTION | REF | PTS | P | BONUS"
msgstr " N | TIRAGE | SOLUTION | REF | PTS | J | BONUS"
-#: utils/ncurses.cpp:384
+#: utils/ncurses.cpp:390
+msgid "(PASS)"
+msgstr "(PASSE)"
+
+#: utils/ncurses.cpp:416
msgid "Help"
msgstr "Aide"
-#: utils/ncurses.cpp:388
+#: utils/ncurses.cpp:420
msgid "[Global]"
msgstr "[Général]"
-#: utils/ncurses.cpp:389
+#: utils/ncurses.cpp:421
msgid " h, H, ? Show/hide help box"
msgstr " h, H, ? Afficher/cacher la boîte d'aide"
-#: utils/ncurses.cpp:390
+#: utils/ncurses.cpp:422
msgid " y, Y Show/hide history of the game"
msgstr " y, Y Afficher/cacher l'historique de la partie"
-#: utils/ncurses.cpp:391
+#: utils/ncurses.cpp:423
msgid ""
" b, B Show/hide contents of the bag (including letters of the "
"racks)"
@@ -334,98 +338,98 @@
" b, B Afficher/cacher le contenu du sac (avec les lettres des "
"tirages)"
-#: utils/ncurses.cpp:392
+#: utils/ncurses.cpp:424
msgid " e, E Show/hide dots on empty squares of the board"
msgstr ""
" e, E Afficher/cacher les points sur les cases vides du "
"plateau de jeu"
-#: utils/ncurses.cpp:393
+#: utils/ncurses.cpp:425
msgid " d, D Check the existence of a word in the dictionary"
msgstr " d, D Vérifier l'existence d'un mot dans le
dictionnaire"
-#: utils/ncurses.cpp:394
+#: utils/ncurses.cpp:426
msgid " j, J Play a word"
msgstr " j, J Jouer un mot"
-#: utils/ncurses.cpp:395
+#: utils/ncurses.cpp:427
msgid " s, S Save the game"
msgstr " s, S Sauvegarder la partie"
-#: utils/ncurses.cpp:396
+#: utils/ncurses.cpp:428
msgid " l, L Load a game"
msgstr " l, L Charger une partie"
-#: utils/ncurses.cpp:397
+#: utils/ncurses.cpp:429
msgid " q, Q Quit"
msgstr " q, Q Quitter"
-#: utils/ncurses.cpp:400
+#: utils/ncurses.cpp:432
msgid "[Training mode]"
msgstr "[Mode entraînement]"
-#: utils/ncurses.cpp:401
+#: utils/ncurses.cpp:433
msgid " * Take a random rack"
msgstr " * Tirage aléatoire"
-#: utils/ncurses.cpp:402
+#: utils/ncurses.cpp:434
msgid " + Complete the current rack randomly"
msgstr " + Compléter le tirage courant de manière
aléatoire"
-#: utils/ncurses.cpp:403
+#: utils/ncurses.cpp:435
msgid " t, T Set the rack manually"
msgstr " t, T Entrer le tirage manuellement"
-#: utils/ncurses.cpp:404
+#: utils/ncurses.cpp:436
msgid " c, C Compute all the possible words"
msgstr " c, C Calculer tous les mots possibles"
-#: utils/ncurses.cpp:405
+#: utils/ncurses.cpp:437
msgid " r, R Show/hide search results"
msgstr " r, R Afficher/cacher les résultats de la recherche"
-#: utils/ncurses.cpp:408
+#: utils/ncurses.cpp:440
msgid "[Duplicate mode]"
msgstr "[Mode duplicate]"
-#: utils/ncurses.cpp:409
+#: utils/ncurses.cpp:441
msgid " n, N Switch to the next human player"
msgstr " n, N Passer au joueur humain suivant"
-#: utils/ncurses.cpp:412
+#: utils/ncurses.cpp:444
msgid "[Free game mode]"
msgstr "[Mode partie libre]"
-#: utils/ncurses.cpp:413
+#: utils/ncurses.cpp:445
msgid " p, P Pass your turn (with or without changing letters)"
msgstr ""
" p, P Passer son tour (en changeant ou pas certaines lettres)"
-#: utils/ncurses.cpp:416
+#: utils/ncurses.cpp:448
msgid "[Miscellaneous]"
msgstr "[Divers]"
-#: utils/ncurses.cpp:417
+#: utils/ncurses.cpp:449
msgid " <up>, <down> Navigate in a box line by line"
msgstr " <haut>, <bas> Naviguer dans une boîte ligne par ligne"
-#: utils/ncurses.cpp:418
+#: utils/ncurses.cpp:450
msgid " <pgup>, <pgdown> Navigate in a box page by page"
msgstr " <pgup>, <pgdown> Naviguer dans une boîte page par page"
-#: utils/ncurses.cpp:419
+#: utils/ncurses.cpp:451
msgid " Ctrl-l Refresh the screen"
msgstr " Ctrl-l Rafraîchir l'écran"
-#: utils/ncurses.cpp:430 wxwin/auxframes.cc:148
+#: utils/ncurses.cpp:462 wxwin/auxframes.cc:148
msgid "Bag"
msgstr "Sac"
-#: utils/ncurses.cpp:437
+#: utils/ncurses.cpp:469
msgid " LETTER | POINTS | FREQUENCY | REMAINING"
msgstr " LETTRE | POINTS |Â FREQUENCE | RESTANT"
-#: utils/ncurses.cpp:490
+#: utils/ncurses.cpp:522
msgid "Play a word"
msgstr "Jouer un mot"
@@ -433,115 +437,115 @@
#. "Coordinates:". For example:
#. Pl. word :
#. Coordinates:
-#: utils/ncurses.cpp:491 utils/ncurses.cpp:499
+#: utils/ncurses.cpp:523 utils/ncurses.cpp:531
msgid "Played word:"
msgstr "Mot joué :"
-#: utils/ncurses.cpp:492 utils/ncurses.cpp:500
+#: utils/ncurses.cpp:524 utils/ncurses.cpp:532
msgid "Coordinates:"
msgstr "Coordonnées :"
-#: utils/ncurses.cpp:514
+#: utils/ncurses.cpp:546
msgid "Incorrect or misplaced word"
msgstr "Mot incorrect ou mal placé"
-#: utils/ncurses.cpp:524
+#: utils/ncurses.cpp:556
msgid "Dictionary"
msgstr "Dictionnaire"
-#: utils/ncurses.cpp:525
+#: utils/ncurses.cpp:557
msgid "Enter the word to check:"
msgstr "Entrer le mot à vérifier:"
-#: utils/ncurses.cpp:534
+#: utils/ncurses.cpp:566
#, c-format
msgid "The word '%ls' exists"
msgstr "Le mot '%ls' existe"
-#: utils/ncurses.cpp:536
+#: utils/ncurses.cpp:568
#, c-format
msgid "The word '%ls' does not exist"
msgstr "Le mot '%ls' n'existe pas"
-#: utils/ncurses.cpp:546 wxwin/mainframe.cc:464 wxwin/mainframe.cc:472
+#: utils/ncurses.cpp:578 wxwin/mainframe.cc:460 wxwin/mainframe.cc:468
msgid "Save the game"
msgstr "Sauvegarder la partie"
-#: utils/ncurses.cpp:547 utils/ncurses.cpp:576
+#: utils/ncurses.cpp:579 utils/ncurses.cpp:609
msgid "Enter the file name:"
msgstr "Entrer le nom du fichier :"
-#: utils/ncurses.cpp:557
+#: utils/ncurses.cpp:589
#, c-format
msgid "Cannot open file %ls for writing"
msgstr "Impossible d'ouvrir le fichier %ls en écriture"
-#: utils/ncurses.cpp:564
+#: utils/ncurses.cpp:597
#, c-format
-msgid "Game saved in %ls"
-msgstr "Partie sauvée dans %ls"
+msgid "Game saved in '%ls'"
+msgstr "Partie sauvée dans '%ls'"
-#: utils/ncurses.cpp:575 wxwin/mainframe.cc:268 wxwin/mainframe.cc:389
-#: wxwin/mainframe.cc:413
+#: utils/ncurses.cpp:608 wxwin/mainframe.cc:269 wxwin/mainframe.cc:390
+#: wxwin/mainframe.cc:414
msgid "Load a game"
msgstr "Charger une partie"
-#: utils/ncurses.cpp:586
+#: utils/ncurses.cpp:619
#, c-format
-msgid "Cannot open file %ls for reading"
-msgstr "Impossible d'ouvrir le fichier %ls en lecture"
+msgid "Cannot open file '%ls' for reading"
+msgstr "Impossible d'ouvrir le fichier '%ls' en lecture"
-#: utils/ncurses.cpp:594
+#: utils/ncurses.cpp:627
#, c-format
msgid "Invalid saved game"
msgstr "Partie sauvée invalide"
-#: utils/ncurses.cpp:598
+#: utils/ncurses.cpp:632
#, c-format
msgid "Game loaded"
msgstr "Partie chargée"
-#: utils/ncurses.cpp:613
+#: utils/ncurses.cpp:647
msgid "Pass your turn"
msgstr "Passer son tour"
-#: utils/ncurses.cpp:614
+#: utils/ncurses.cpp:648
msgid "Enter the letters to change:"
msgstr "Entrer les lettres à changer:"
-#: utils/ncurses.cpp:623
+#: utils/ncurses.cpp:657
msgid "Cannot pass the turn"
msgstr "Impossible de passer le tour"
-#: utils/ncurses.cpp:633
+#: utils/ncurses.cpp:667
msgid "Set rack"
msgstr "Choix du tirage"
-#: utils/ncurses.cpp:634
+#: utils/ncurses.cpp:668
msgid "Enter the new letters:"
msgstr "Entrer les nouvelles lettres:"
-#: utils/ncurses.cpp:643
+#: utils/ncurses.cpp:677
msgid "Cannot take these letters from the bag"
msgstr "Impossible de retirer ces lettres du sac"
-#: utils/ncurses.cpp:1037
+#: utils/ncurses.cpp:1071
msgid "Training mode"
msgstr "Mode entraînement"
-#: utils/ncurses.cpp:1039
+#: utils/ncurses.cpp:1073
msgid "Free game mode"
msgstr "Mode partie libre"
-#: utils/ncurses.cpp:1041
+#: utils/ncurses.cpp:1075
msgid "Duplicate mode"
msgstr "Mode duplicate"
-#: utils/ncurses.cpp:1044
+#: utils/ncurses.cpp:1078
msgid "Joker game"
msgstr "Partie joker"
-#: utils/ncurses.cpp:1045
+#: utils/ncurses.cpp:1079
msgid "[h for help]"
msgstr "[h pour l'aide]"
@@ -577,8 +581,8 @@
msgid "Copy"
msgstr "Copier"
-#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:491 wxwin/mainframe.cc:511
-#: wxwin/mainframe.cc:542
+#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:487 wxwin/mainframe.cc:507
+#: wxwin/mainframe.cc:538
msgid "No on going game"
msgstr "Pas de partie en cours"
@@ -590,11 +594,11 @@
msgid "Rack: "
msgstr "Tirage :"
-#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:318
+#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:319
msgid "Game history"
msgstr "Historique de la partie"
-#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:320
+#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:321
msgid "Results"
msgstr "Résultats"
@@ -706,7 +710,7 @@
msgid "Nb"
msgstr "Num"
-#: wxwin/configdb.cc:323 wxwin/mainframe.cc:173
+#: wxwin/configdb.cc:323 wxwin/mainframe.cc:174
msgid "Rack"
msgstr "Tirage"
@@ -742,396 +746,396 @@
msgid "Results of the search"
msgstr "Résultats de la recherche"
-#: wxwin/mainframe.cc:204
+#: wxwin/mainframe.cc:205
msgid " Rack "
msgstr " Tirage "
-#: wxwin/mainframe.cc:205
+#: wxwin/mainframe.cc:206
msgid " Complement "
msgstr " Complément "
-#: wxwin/mainframe.cc:206
+#: wxwin/mainframe.cc:207
msgid " Search "
msgstr " Rechercher "
-#: wxwin/mainframe.cc:207
+#: wxwin/mainframe.cc:208
msgid " Back "
msgstr " Arrière "
-#: wxwin/mainframe.cc:208
+#: wxwin/mainframe.cc:209
msgid " Play "
msgstr " Jouer "
-#: wxwin/mainframe.cc:210
+#: wxwin/mainframe.cc:211
msgid "Random rack"
msgstr "Tirage aléatoire"
-#: wxwin/mainframe.cc:211
+#: wxwin/mainframe.cc:212
msgid "Random complement of the rack"
msgstr "Complément aléatoire du tirage"
-#: wxwin/mainframe.cc:212
+#: wxwin/mainframe.cc:213
msgid "Search with the current rack"
msgstr "Recherche sur le tirage courant"
-#: wxwin/mainframe.cc:213
+#: wxwin/mainframe.cc:214
msgid "Go back one turn"
msgstr "Revenir un coup en arrière"
-#: wxwin/mainframe.cc:214
+#: wxwin/mainframe.cc:215
msgid "Play the selected word"
msgstr "Jouer le mot selectionné"
-#: wxwin/mainframe.cc:265
+#: wxwin/mainframe.cc:266
msgid "&New game\tctrl+n"
msgstr "&Nouvelle partie\tctrl+n"
-#: wxwin/mainframe.cc:265
+#: wxwin/mainframe.cc:266
msgid "Start a new game"
msgstr "Démarrer une nouvelle partie"
-#: wxwin/mainframe.cc:266
+#: wxwin/mainframe.cc:267
msgid "New &joker game\tctrl+j"
msgstr "Nouvelle partie &joker\tctrl+j"
-#: wxwin/mainframe.cc:266
+#: wxwin/mainframe.cc:267
msgid "Start a new joker game"
msgstr "Démarrer une nouvelle partie joker"
-#: wxwin/mainframe.cc:268
+#: wxwin/mainframe.cc:269
msgid "&Load...\tctrl+l"
msgstr "&Charger...\tctrl+l"
-#: wxwin/mainframe.cc:269
+#: wxwin/mainframe.cc:270
msgid "&Save as...\tctrl+s"
msgstr "&Enregistrer sous...\tctrl+s"
-#: wxwin/mainframe.cc:269
+#: wxwin/mainframe.cc:270
msgid "Save the current game"
msgstr "Sauvegarder la partie en cours"
-#: wxwin/mainframe.cc:271
+#: wxwin/mainframe.cc:272
msgid "&Print...\tctrl+p"
msgstr "&Imprimer...\tctrl+p"
-#: wxwin/mainframe.cc:271
+#: wxwin/mainframe.cc:272
msgid "Print this game"
msgstr "Imprimer la partie en cours"
-#: wxwin/mainframe.cc:272
+#: wxwin/mainframe.cc:273
msgid "Print pre&view..."
msgstr "&Aperçu avant impression..."
-#: wxwin/mainframe.cc:272
+#: wxwin/mainframe.cc:273
msgid "Print preview of the game"
msgstr "Aperçu avant impression de la partie"
-#: wxwin/mainframe.cc:274
+#: wxwin/mainframe.cc:275
msgid "Print in PostS&cript..."
msgstr "Imprimer au format &PostScript..."
-#: wxwin/mainframe.cc:274
+#: wxwin/mainframe.cc:275
msgid "Print in a PostScript file"
msgstr "Imprimer dans un fichier PostScript"
-#: wxwin/mainframe.cc:277
+#: wxwin/mainframe.cc:278
msgid "&Quit"
msgstr "&Quitter"
-#: wxwin/mainframe.cc:277
+#: wxwin/mainframe.cc:278
msgid "Quit Eliot"
msgstr "Quitter Eliot"
-#: wxwin/mainframe.cc:280
+#: wxwin/mainframe.cc:281
msgid "&Dictionary..."
msgstr "&Dictionnaire..."
-#: wxwin/mainframe.cc:280 wxwin/mainframe.cc:593
+#: wxwin/mainframe.cc:281 wxwin/mainframe.cc:589
msgid "Choose a dictionary"
msgstr "Choisir un dictionnaire"
-#: wxwin/mainframe.cc:281
+#: wxwin/mainframe.cc:282
msgid "&Search..."
msgstr "&Recherche..."
-#: wxwin/mainframe.cc:281
+#: wxwin/mainframe.cc:282
msgid "Search options"
msgstr "Options de recherche"
-#: wxwin/mainframe.cc:284
+#: wxwin/mainframe.cc:285
msgid "&Background..."
msgstr "&Fond..."
-#: wxwin/mainframe.cc:284
+#: wxwin/mainframe.cc:285
msgid "Background color"
msgstr "Couleur de fond"
-#: wxwin/mainframe.cc:285
+#: wxwin/mainframe.cc:286
msgid "L&ines..."
msgstr "L&ignes..."
-#: wxwin/mainframe.cc:285
+#: wxwin/mainframe.cc:286
msgid "Color of the lines"
msgstr "Couleur des lignes"
-#: wxwin/mainframe.cc:287
+#: wxwin/mainframe.cc:288
msgid "&Played letters..."
msgstr "Lettres &jouées..."
-#: wxwin/mainframe.cc:287
+#: wxwin/mainframe.cc:288
msgid "Color of the letters played on the board"
msgstr "Couleur des lettres jouées sur la grille"
-#: wxwin/mainframe.cc:288
+#: wxwin/mainframe.cc:289
msgid "&Temporary letters..."
msgstr "Lettres &temporaires..."
-#: wxwin/mainframe.cc:288
+#: wxwin/mainframe.cc:289
msgid "Color of the letters of the temporary word"
msgstr "Couleur des lettres du mot temporaire"
-#: wxwin/mainframe.cc:289
+#: wxwin/mainframe.cc:290
msgid "B&ackground of played letters..."
msgstr "Fo&nd des lettres jouées..."
-#: wxwin/mainframe.cc:289
+#: wxwin/mainframe.cc:290
msgid "Background color of the letters played on the board"
msgstr "Couleur de fond des lettres jouées sur la grille"
-#: wxwin/mainframe.cc:290
+#: wxwin/mainframe.cc:291
msgid "Ba&ckground of temporary letters..."
msgstr "Fon&d des lettres temporaires..."
-#: wxwin/mainframe.cc:290
+#: wxwin/mainframe.cc:291
msgid "Background color of the temporary letters on the board"
msgstr "Couleur de fond des lettres temporaires sur la grille"
-#: wxwin/mainframe.cc:292
+#: wxwin/mainframe.cc:293
msgid "Double &letter..."
msgstr "&Lettre compte double..."
-#: wxwin/mainframe.cc:292
+#: wxwin/mainframe.cc:293
msgid "Color of the \"double letter\" squares"
msgstr "Couleur des cases \"mot compte double\""
-#: wxwin/mainframe.cc:293
+#: wxwin/mainframe.cc:294
msgid "Triple l&etter..."
msgstr "L&ettre compte triple..."
-#: wxwin/mainframe.cc:293
+#: wxwin/mainframe.cc:294
msgid "Color of the \"triple letter\" squares"
msgstr "Couleur des cases \"mot compte triple\""
-#: wxwin/mainframe.cc:294
+#: wxwin/mainframe.cc:295
msgid "Double &word..."
msgstr "&Mot compte double..."
-#: wxwin/mainframe.cc:294
+#: wxwin/mainframe.cc:295
msgid "Color of the \"double word\" squares"
msgstr "Couleur des cases \"mot compte double\""
-#: wxwin/mainframe.cc:295
+#: wxwin/mainframe.cc:296
msgid "Triple w&ord..."
msgstr "M&ot compte triple..."
-#: wxwin/mainframe.cc:295
+#: wxwin/mainframe.cc:296
msgid "Color of the \"triple word\" squares"
msgstr "Couleur des cases \"mot compte triple\""
-#: wxwin/mainframe.cc:297
+#: wxwin/mainframe.cc:298
msgid "&Default colors"
msgstr "&Couleurs d'origine"
-#: wxwin/mainframe.cc:297
+#: wxwin/mainframe.cc:298
msgid "Restore the default colors"
msgstr "Restaurer les couleurs d'origine"
-#: wxwin/mainframe.cc:300
+#: wxwin/mainframe.cc:301
msgid "&Search letters..."
msgstr "&Lettres de recherche..."
-#: wxwin/mainframe.cc:300
+#: wxwin/mainframe.cc:301
msgid "Font for the search"
msgstr "Police de caractères pour la recherche"
-#: wxwin/mainframe.cc:303 wxwin/mainframe.cc:327
+#: wxwin/mainframe.cc:304 wxwin/mainframe.cc:328
msgid "&Game"
msgstr "&Partie"
-#: wxwin/mainframe.cc:303
+#: wxwin/mainframe.cc:304
msgid "Configuration of the game"
msgstr "Configuration de la partie"
-#: wxwin/mainframe.cc:304
+#: wxwin/mainframe.cc:305
msgid "&Fonts"
msgstr "P&olices de caractères"
-#: wxwin/mainframe.cc:304
+#: wxwin/mainframe.cc:305
msgid "Configuration of the fonts"
msgstr "Configuration des polices de caractères"
-#: wxwin/mainframe.cc:305
+#: wxwin/mainframe.cc:306
msgid "&Colors"
msgstr "&Couleurs"
-#: wxwin/mainframe.cc:305
+#: wxwin/mainframe.cc:306
msgid "Configuration of the colors"
msgstr "Configuration des couleurs"
-#: wxwin/mainframe.cc:306
+#: wxwin/mainframe.cc:307
msgid "&Printing..."
msgstr "&Impression..."
-#: wxwin/mainframe.cc:306
+#: wxwin/mainframe.cc:307
msgid "Configuration of the printing parameters"
msgstr "Configuration des paramètres d'impression"
-#: wxwin/mainframe.cc:309
+#: wxwin/mainframe.cc:310
msgid "&Board"
msgstr "&Grille"
-#: wxwin/mainframe.cc:309
+#: wxwin/mainframe.cc:310
msgid "Game board"
msgstr "Plateau de jeu"
-#: wxwin/mainframe.cc:310
+#: wxwin/mainframe.cc:311
msgid "Ba&g"
msgstr "&Sac"
-#: wxwin/mainframe.cc:310
+#: wxwin/mainframe.cc:311
msgid "Remaining letters in the bag"
msgstr "Lettres restantes dans le sac"
-#: wxwin/mainframe.cc:311
+#: wxwin/mainframe.cc:312
msgid "&Check"
msgstr "&Vérification"
-#: wxwin/mainframe.cc:311
+#: wxwin/mainframe.cc:312
msgid "Check a word in the dictionary"
msgstr "Vérifier l'existence d'un mot dans le dictionnaire"
-#: wxwin/mainframe.cc:312
+#: wxwin/mainframe.cc:313
msgid "&Search"
msgstr "&Recherche"
-#: wxwin/mainframe.cc:312
+#: wxwin/mainframe.cc:313
msgid "Search in the dictionary"
msgstr "Recherche dans le dictionnaire"
-#: wxwin/mainframe.cc:314
+#: wxwin/mainframe.cc:315
msgid "&Rack + 1"
msgstr "&Tirage + 1"
-#: wxwin/mainframe.cc:314
+#: wxwin/mainframe.cc:315
msgid "Letters of the rack plus one"
msgstr "Lettres du tirage plus une"
-#: wxwin/mainframe.cc:315
+#: wxwin/mainframe.cc:316
msgid "R&accords"
msgstr "R&accords"
-#: wxwin/mainframe.cc:315
+#: wxwin/mainframe.cc:316
msgid "Raccords on a word of the search"
msgstr "Raccords sur un mot de la recherche"
-#: wxwin/mainframe.cc:316
+#: wxwin/mainframe.cc:317
msgid "&Benjamins"
msgstr "&Benjamins"
-#: wxwin/mainframe.cc:316
+#: wxwin/mainframe.cc:317
msgid "Benjamins on a word of the search"
msgstr "Benjamins sur un mot de la recherche"
-#: wxwin/mainframe.cc:318
+#: wxwin/mainframe.cc:319
msgid "Game &history"
msgstr "&Historique de la partie"
-#: wxwin/mainframe.cc:320
+#: wxwin/mainframe.cc:321
msgid "R&esults"
msgstr "Ré&sultats"
-#: wxwin/mainframe.cc:324
+#: wxwin/mainframe.cc:325
msgid "&About..."
msgstr "Ã &propos..."
-#: wxwin/mainframe.cc:324 wxwin/mainframe.cc:722
+#: wxwin/mainframe.cc:325 wxwin/mainframe.cc:718
msgid "About Eliot"
msgstr "Ã propos d'Eliot"
-#: wxwin/mainframe.cc:328
+#: wxwin/mainframe.cc:329
msgid "&Settings"
msgstr "&Paramètres"
-#: wxwin/mainframe.cc:329
+#: wxwin/mainframe.cc:330
msgid "&Windows"
msgstr "&Fenêtres"
-#: wxwin/mainframe.cc:330
+#: wxwin/mainframe.cc:331
msgid "&Help"
msgstr "&Aide"
-#: wxwin/mainframe.cc:354 wxwin/mainframe.cc:392
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393
msgid "No dictionary selected"
msgstr "Pas de dictionnaire sélectionné"
-#: wxwin/mainframe.cc:354 wxwin/mainframe.cc:392 wxwin/mainframe.cc:491
-#: wxwin/mainframe.cc:511 wxwin/mainframe.cc:542
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393 wxwin/mainframe.cc:487
+#: wxwin/mainframe.cc:507 wxwin/mainframe.cc:538
msgid "Eliot: error"
msgstr "Eliot : erreur"
-#: wxwin/mainframe.cc:412
+#: wxwin/mainframe.cc:413
msgid "Cannot open "
msgstr "Impossible d'ouvrir "
-#: wxwin/mainframe.cc:424 wxwin/mainframe.cc:433
+#: wxwin/mainframe.cc:425 wxwin/mainframe.cc:434
msgid "Error while loading the game"
msgstr "Erreur pendant le chargement de la partie"
-#: wxwin/mainframe.cc:425
+#: wxwin/mainframe.cc:426
msgid "Invalid game"
msgstr "Partie invalide"
-#: wxwin/mainframe.cc:434
+#: wxwin/mainframe.cc:435
msgid "The game is empty"
msgstr "La partie est vide"
-#: wxwin/mainframe.cc:471
+#: wxwin/mainframe.cc:467
msgid "Cannot create "
msgstr "Impossible de créer "
-#: wxwin/mainframe.cc:500 wxwin/mainframe.cc:564
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:560
msgid "Printing not done"
msgstr "Impression non effectuée"
-#: wxwin/mainframe.cc:500 wxwin/mainframe.cc:528
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:524
msgid "Printing"
msgstr "Impression"
-#: wxwin/mainframe.cc:523
+#: wxwin/mainframe.cc:519
msgid "Print preview problem.\n"
msgstr "Problème avec l'aperçu avant impression.\n"
-#: wxwin/mainframe.cc:524
+#: wxwin/mainframe.cc:520
msgid "The printer may not be correctly initialized"
msgstr "Il se peut que l'imprimante soit mal initialisée"
-#: wxwin/mainframe.cc:525
+#: wxwin/mainframe.cc:521
msgid "Print preview"
msgstr "Aperçu avant impression"
-#: wxwin/mainframe.cc:546
+#: wxwin/mainframe.cc:542
msgid "Print to a PostScript file"
msgstr "Imprimer dans un fichier PostScript"
-#: wxwin/mainframe.cc:565 wxwin/mainframe.cc:571
+#: wxwin/mainframe.cc:561 wxwin/mainframe.cc:567
msgid "PostScript printing"
msgstr "Impression PostScript"
-#: wxwin/mainframe.cc:570
+#: wxwin/mainframe.cc:566
msgid "Cannot initialize PostScript printer"
msgstr "Impossible d'initialiser l'impression PostScript"
-#: wxwin/mainframe.cc:718
+#: wxwin/mainframe.cc:714
msgid ""
"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 "
@@ -1143,15 +1147,15 @@
"publiée par la Free Software Fundation ; soit la version 2 de la Licence, "
"soit (comme vous le préférez), n'importe quelle version ultérieure."
-#: wxwin/mainframe.cc:916
+#: wxwin/mainframe.cc:912
msgid "turn:"
msgstr "coup :"
-#: wxwin/mainframe.cc:917
+#: wxwin/mainframe.cc:913
msgid "points:"
msgstr "points :"
-#: wxwin/mainframe.cc:954
+#: wxwin/mainframe.cc:948
msgid ""
"The bag doesn't contain enough letters\n"
"for a new rack."
@@ -1159,40 +1163,45 @@
"Le sac ne contient pas assez de lettres\n"
"pour un nouveau tirage."
-#: wxwin/mainframe.cc:955 wxwin/mainframe.cc:959 wxwin/mainframe.cc:963
+#: wxwin/mainframe.cc:949 wxwin/mainframe.cc:953 wxwin/mainframe.cc:957
msgid "Rack validation"
msgstr "Validation du tirage"
-#: wxwin/mainframe.cc:958
+#: wxwin/mainframe.cc:952
msgid "The rack must contain at least 2 consonants and 2 vowels."
msgstr "Le tirage doit contenir au moins 2 consonnes et 2 voyelles."
-#: wxwin/mainframe.cc:962
+#: wxwin/mainframe.cc:956
msgid "The rack contains invalid letters for the current dictionary"
msgstr ""
"Le tirage contient des lettres incorrectes pour le dictionnaire courant"
-#: wxwin/mainframe.cc:966
+#: wxwin/mainframe.cc:960
msgid "The rack has been modified manually"
msgstr "Le tirage a été modifié manuellement"
-#: wxwin/searchpanel.cc:303
+#: wxwin/searchpanel.cc:146 wxwin/searchpanel.cc:190
+#, c-format
+msgid "The search is limited to %d letters"
+msgstr "La recherche est limitée à %d lettres"
+
+#: wxwin/searchpanel.cc:301
msgid "Minimum length"
msgstr "Longueur minimum"
-#: wxwin/searchpanel.cc:305
+#: wxwin/searchpanel.cc:303
msgid "Maximum length"
msgstr "Longueur maximum"
-#: wxwin/searchpanel.cc:368
+#: wxwin/searchpanel.cc:366
msgid "Cross words"
msgstr "Mots croisés"
-#: wxwin/searchpanel.cc:369
+#: wxwin/searchpanel.cc:367
msgid "Plus 1"
msgstr "Plus 1"
-#: wxwin/searchpanel.cc:370
+#: wxwin/searchpanel.cc:368
msgid "Regular expressions"
msgstr "Expressions régulières"
Index: test/freegame_change.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_change.input,v
retrieving revision 1.1
retrieving revision 1.1.6.1
diff -u -b -r1.1 -r1.1.6.1
--- test/freegame_change.input 16 Apr 2005 15:47:59 -0000 1.1
+++ test/freegame_change.input 23 Dec 2007 23:12:45 -0000 1.1.6.1
@@ -10,6 +10,7 @@
a T
p KEEEAAI
a T
+a p
q
q
Index: test/freegame_change.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_change.ref,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -u -b -r1.2 -r1.2.4.1
--- test/freegame_change.ref 24 Dec 2005 17:50:11 -0000 1.2
+++ test/freegame_change.ref 23 Dec 2007 23:12:45 -0000 1.2.4.1
@@ -25,6 +25,24 @@
commande> a T
Joueur 0: EENNTOD
Joueur 1: UNLEUSS
+commande> a p
+Eliot 1.5
+
+Game type: Free game
+Player 0: Human
+Player 1: Human
+
+ N | RACK | SOLUTION | REF | PTS | P | BONUS
+ ===|==========|=================|=====|=====|===|======
+ 1 | NEIJEDN | (-JID) | - | 0 | 0 |
+ 2 | UUEALEO | (-AUOUEL) | - | 0 | 1 |
+ 3 | EENN+WTA | (-WA) | - | 0 | 0 |
+ 4 | E+EAKEIA | (-KEEEAAI) | - | 0 | 1 |
+
+ Total: 0
+
+Rack 0: EENNT+OD
+Rack 1: UNLEUSS
commande> q
fin du mode partie libre
commande> q
Index: test/freegame_passing.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_passing.ref,v
retrieving revision 1.3.2.1
retrieving revision 1.3.2.2
diff -u -b -r1.3.2.1 -r1.3.2.2
--- test/freegame_passing.ref 14 Dec 2007 18:12:33 -0000 1.3.2.1
+++ test/freegame_passing.ref 23 Dec 2007 23:12:45 -0000 1.3.2.2
@@ -47,29 +47,52 @@
N | RACK | SOLUTION | REF | PTS | P | BONUS
===|==========|=================|=====|=====|===|======
- 1 | RENLOHL | HERON | H4 | 24 | 1 |
- 2 | LL+XUORC | OCREUX | 5E | 34 | 1 |
- 3 | LL+NAECT | CALLENT | I7 | 73 | 1 | *
- 4 | ?EMTOEO | ENTOlOME | 12H | 70 | 1 | *
- 5 | MLZESLS | MEZES | O11 | 45 | 1 |
- 6 | LLS+IUEG | GOUILLES | E4 | 68 | 1 | *
- 7 | TVAWLAE | AWELE | 10A | 34 | 1 |
- 8 | ATV+PUFA | PAVAT | A7 | 30 | 1 |
- 9 | AFU+AIAE | FA | G7 | 24 | 1 |
- 10 | AAEIU+YU | YEUX | J2 | 42 | 1 |
- 11 | AAIU+TEN | NEZ | 13M | 31 | 1 |
- 12 | AAITU+IR | AUTRE | 14K | 21 | 1 |
- 13 | AII+MPNA | PAMAI | 15G | 26 | 1 |
- 14 | IN+IUURE | TUNES | 11A | 20 | 1 |
- 15 | IIRU+RNF | NIF | 11K | 24 | 1 |
- 16 | IRRU+OEI | HOUER | 4H | 18 | 1 |
- 17 | IIRU+TSE | YETIS | 2J | 28 | 1 |
- 18 | IRU+ETHO | HERE | 3I | 27 | 1 |
- 19 | IOTU+?JN | SUJeTION | N2 | 66 | 1 | *
- 20 | SEVDQIR | DEVENIRS | C7 | 36 | 1 |
- 21 | Q+BAKIAE | KABIG | 4A | 54 | 1 |
- 22 | AEQ | QUE | 6D | 18 | 1 |
- 23 | A | KA | A4 | 11 | 1 |
+ 1 | TISSUEG | (PASS) | - | 0 | 0 |
+ 2 | RENLOHL | HERON | H4 | 24 | 1 |
+ 3 | EGISSTU | (PASS) | - | 0 | 0 |
+ 4 | LL+XUORC | OCREUX | 5E | 34 | 1 |
+ 5 | EGISSTU | (-UIET) | - | 0 | 0 |
+ 6 | LL+NAECT | CALLENT | I7 | 73 | 1 | *
+ 7 | GSS+DIDB | (PASS) | - | 0 | 0 |
+ 8 | ?EMTOEO | ENTOlOME | 12H | 70 | 1 | *
+ 9 | BDDGISS | (PASS) | - | 0 | 0 |
+ 10 | MLZESLS | MEZES | O11 | 45 | 1 |
+ 11 | BDDGISS | (PASS) | - | 0 | 0 |
+ 12 | LLS+IUEG | GOUILLES | E4 | 68 | 1 | *
+ 13 | BDDGISS | (PASS) | - | 0 | 0 |
+ 14 | TVAWLAE | AWELE | 10A | 34 | 1 |
+ 15 | BDDGISS | (PASS) | - | 0 | 0 |
+ 16 | ATV+PUFA | PAVAT | A7 | 30 | 1 |
+ 17 | BDDGISS | (PASS) | - | 0 | 0 |
+ 18 | AFU+AIAE | FA | G7 | 24 | 1 |
+ 19 | BDDGISS | (PASS) | - | 0 | 0 |
+ 20 | AAEIU+YU | YEUX | J2 | 42 | 1 |
+ 21 | BDDGISS | (PASS) | - | 0 | 0 |
+ 22 | AAIU+TEN | NEZ | 13M | 31 | 1 |
+ 23 | BDDGISS | (PASS) | - | 0 | 0 |
+ 24 | AAITU+IR | AUTRE | 14K | 21 | 1 |
+ 25 | BDDGISS | (PASS) | - | 0 | 0 |
+ 26 | AII+MPNA | PAMAI | 15G | 26 | 1 |
+ 27 | BDDGISS | (PASS) | - | 0 | 0 |
+ 28 | IN+IUURE | TUNES | 11A | 20 | 1 |
+ 29 | BDDGISS | (PASS) | - | 0 | 0 |
+ 30 | IIRU+RNF | NIF | 11K | 24 | 1 |
+ 31 | BDDGISS | (PASS) | - | 0 | 0 |
+ 32 | IRRU+OEI | HOUER | 4H | 18 | 1 |
+ 33 | BDDGISS | (PASS) | - | 0 | 0 |
+ 34 | IIRU+TSE | YETIS | 2J | 28 | 1 |
+ 35 | BDDGISS | (PASS) | - | 0 | 0 |
+ 36 | IRU+ETHO | HERE | 3I | 27 | 1 |
+ 37 | BDDGISS | (PASS) | - | 0 | 0 |
+ 38 | IOTU+?JN | SUJeTION | N2 | 66 | 1 | *
+ 39 | BDDGISS | (PASS) | - | 0 | 0 |
+ 40 | SEVDQIR | DEVENIRS | C7 | 36 | 1 |
+ 41 | BDDGISS | (PASS) | - | 0 | 0 |
+ 42 | Q+BAKIAE | KABIG | 4A | 54 | 1 |
+ 43 | BDDGISS | (PASS) | - | 0 | 0 |
+ 44 | AEQ | QUE | 6D | 18 | 1 |
+ 45 | BDDGISS | (PASS) | - | 0 | 0 |
+ 46 | A | KA | A4 | 11 | 1 |
Total: 824
Index: utils/eliottxt.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/eliottxt.cpp,v
retrieving revision 1.16.2.10
retrieving revision 1.16.2.11
diff -u -b -r1.16.2.10 -r1.16.2.11
--- utils/eliottxt.cpp 5 Dec 2007 10:36:00 -0000 1.16.2.10
+++ utils/eliottxt.cpp 23 Dec 2007 23:12:45 -0000 1.16.2.11
@@ -643,7 +643,7 @@
if (token == NULL)
token = L"";
- if (iGame.pass(token, iGame.currPlayer()) != 0)
+ if (iGame.pass(token) != 0)
break;
break;
case L's':
@@ -744,10 +744,14 @@
help_duplicate();
else
{
+ int n = _wtoi(token);
+ if (n < 0 || n >= (int)iGame.getNPlayers())
+ {
+ fprintf(stderr, "Numéro de joueur invalide\n");
+ break;
+ }
int res = iGame.setPlayer(_wtoi(token));
if (res == 1)
- fprintf(stderr, "Numéro de joueur invalide\n");
- else if (res == 2)
fprintf(stderr, "Impossible de choisir un joueur
non humain\n");
}
break;
Index: utils/ncurses.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/ncurses.cpp,v
retrieving revision 1.22.2.11
retrieving revision 1.22.2.12
diff -u -b -r1.22.2.11 -r1.22.2.12
--- utils/ncurses.cpp 20 Dec 2007 08:47:10 -0000 1.22.2.11
+++ utils/ncurses.cpp 23 Dec 2007 23:12:45 -0000 1.22.2.12
@@ -358,7 +358,11 @@
i < (int)m_game->getHistory().getSize() && i < ioBox.getLastLine();
i++)
{
const Turn& t = m_game->getHistory().getTurn(i);
- const Round& r = t.getRound();
+ const Move& m = t.getMove();
+ if (m.getType() == Move::VALID_ROUND)
+ {
+ // The move corresponds to a played round: display it
+ const Round &r = m.getRound();
wstring coord = r.getCoord().toString();
ioBox.printDataLine(i, x,
" %2d %s %s %s %3d %1d %c",
@@ -367,6 +371,33 @@
padAndConvert(coord, 3).c_str(), r.getPoints(),
t.getPlayer(), r.getBonus() ? '*' : ' ');
}
+ else if (m.getType() == Move::INVALID_WORD)
+ {
+ // The move corresponds to an invalid word: display it
+ wstring invWord = L"<" + m.getBadWord() + L">";
+ ioBox.printDataLine(i, x,
+ " %2d %s %s %s %3d %1d",
+ i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
+ padAndConvert(invWord, 15, false).c_str(),
+ padAndConvert(m.getBadCoord(), 3).c_str(), m.getScore(),
+ t.getPlayer());
+ }
+ else
+ {
+ // The move corresponds to a passed turn or changed letters
+ wstring action;
+ if (m.getType() == Move::PASS)
+ action = convertToWc(_("(PASS)"));
+ else if (m.getType() == Move::CHANGE_LETTERS)
+ action = L"(-" + m.getChangedLetters() + L")";
+
+ ioBox.printDataLine(i, x,
+ " %2d %s %s %s %3d %1d",
+ i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
+ padAndConvert(action, 15, false).c_str(),
+ " - ", m.getScore(), t.getPlayer());
+ }
+ }
int nbLines = min(i + 2 - ioBox.getFirstLine(),
ioBox.getLastLine() - ioBox.getFirstLine() + 2);
mvwvline(m_win, y, x + 4, ACS_VLINE, nbLines);
@@ -620,7 +651,7 @@
wstring letters;
if (readString(win, y + 2, x + 2, 7, letters))
{
- int res = iGame.pass(letters, m_game->currPlayer());
+ int res = iGame.pass(letters);
if (res)
{
drawStatus(win, _("Cannot pass the turn"));
Index: wxwin/mainframe.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/mainframe.cc,v
retrieving revision 1.21.2.9
retrieving revision 1.21.2.10
diff -u -b -r1.21.2.9 -r1.21.2.10
--- wxwin/mainframe.cc 20 Dec 2007 08:47:10 -0000 1.21.2.9
+++ wxwin/mainframe.cc 23 Dec 2007 23:12:46 -0000 1.21.2.10
@@ -929,7 +929,6 @@
void
MainFrame::SetRack(Game::set_rack_mode mode, wxString srack)
{
- int res = 0;
wxString msg;
bool check = config.getRackChecking();
@@ -938,8 +937,7 @@
return;
}
static_cast<Training*>(m_game)->removeTestPlay();
- std::wstring str = srack.c_str();
- res = static_cast<Training*>(m_game)->setRack(mode, check, str);
+ int res = static_cast<Training*>(m_game)->setRack(mode, check,
srack.c_str());
switch (res)
{
Index: wxwin/printout.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/printout.cc,v
retrieving revision 1.10.4.1
retrieving revision 1.10.4.2
diff -u -b -r1.10.4.1 -r1.10.4.2
--- wxwin/printout.cc 11 Nov 2007 19:57:01 -0000 1.10.4.1
+++ wxwin/printout.cc 23 Dec 2007 23:12:46 -0000 1.10.4.2
@@ -176,14 +176,14 @@
DIM(2);
if ((numline > 0) && (numline <= NRounds))
{
- str = wxU(m_game.getHistory().getTurn(numline -
1).getRound().getWord().c_str());
+ str = wxU(m_game.getHistory().getTurn(numline -
1).getMove().getRound().getWord().c_str());
DRW(2);
}
// pos
DIM(3);
if ((numline > 0) && (numline <= NRounds))
{
- str = wxU(m_game.getHistory().getTurn(numline -
1).getRound().getCoord().toString().c_str());
+ str = wxU(m_game.getHistory().getTurn(numline -
1).getMove().getRound().getCoord().toString().c_str());
DRW(3);
}
// pts
@@ -191,7 +191,7 @@
if ((numline > 0) && (numline <= NRounds))
{
str = wxT("");
- str << m_game.getHistory().getTurn(numline - 1).getRound().getPoints();
+ str << m_game.getHistory().getTurn(numline -
1).getMove().getRound().getPoints();
DRW(4);
}
// total points
Index: wxwin/searchpanel.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/searchpanel.cc,v
retrieving revision 1.15.2.4
retrieving revision 1.15.2.5
diff -u -b -r1.15.2.4 -r1.15.2.5
--- wxwin/searchpanel.cc 11 Dec 2007 14:07:16 -0000 1.15.2.4
+++ wxwin/searchpanel.cc 23 Dec 2007 23:12:46 -0000 1.15.2.5
@@ -142,9 +142,8 @@
if (t->GetValue().Len() >= DIC_WORD_MAX)
{
- wxString msg = wxT("");
- // XXX: msg << wxT("La recherche est limitée à ") << DIC_WORD_MAX
- 1 << wxT(" lettres");
- msg << wxT("La recherche est limitee a ") << DIC_WORD_MAX - 1 << wxT("
lettres");
+ wxString msg;
+ msg.Printf(_("The search is limited to %d letters"), DIC_WORD_MAX - 1);
l->Append(msg);
return;
}
@@ -187,9 +186,8 @@
if (t->GetValue().Len() >= DIC_WORD_MAX)
{
- wxString msg = wxT("");
- // XXX: msg << wxT("La recherche est limitée à ") << DIC_WORD_MAX
- 1 << wxT(" lettres");
- msg << wxT("La recherche est limitee a ") << DIC_WORD_MAX - 1 << wxT("
lettres");
+ wxString msg;
+ msg.Printf(_("The search is limited to %d letters"), DIC_WORD_MAX - 1);
l->Append(msg);
return;
}
Index: game/move.cpp
===================================================================
RCS file: game/move.cpp
diff -N game/move.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ game/move.cpp 23 Dec 2007 23:12:43 -0000 1.1.2.1
@@ -0,0 +1,106 @@
+/*****************************************************************************
+ * Copyright (C) 2007 Eliot
+ * Authors: Olivier Teuliere <address@hidden>
+ *
+ * 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 <algorithm>
+#include <wctype.h>
+
+#include "move.h"
+
+
+Move::Move(const Round &iRound)
+ : m_score(0), m_round(iRound)
+{
+ m_type = VALID_ROUND;
+ m_score = m_round.getPoints();
+}
+
+
+Move::Move(const wstring &iWord, const wstring &iCoord)
+ : m_word(iWord), m_coord(iCoord)
+{
+ m_type = INVALID_WORD;
+ m_score = 0;
+}
+
+
+Move::Move(const wstring &iLetters)
+ : m_score(0), m_letters(iLetters)
+{
+ // Make the letters uppercase
+ std::transform(m_letters.begin(), m_letters.end(),
+ m_letters.begin(), towupper);
+
+ if (m_letters.empty())
+ m_type = PASS;
+ else
+ m_type = CHANGE_LETTERS;
+}
+
+
+const Round & Move::getRound() const
+{
+ if (m_type != VALID_ROUND)
+ {
+ // FIXME: throw an exception object instead
+ throw 1;
+ }
+ return m_round;
+}
+
+
+const wstring & Move::getBadWord() const
+{
+ if (m_type != INVALID_WORD)
+ {
+ // FIXME: throw an exception object instead
+ throw 1;
+ }
+ return m_word;
+}
+
+
+const wstring & Move::getBadCoord() const
+{
+ if (m_type != INVALID_WORD)
+ {
+ // FIXME: throw an exception object instead
+ throw 1;
+ }
+ return m_coord;
+}
+
+
+const wstring & Move::getChangedLetters() const
+{
+ if (m_type != CHANGE_LETTERS &&
+ m_type != PASS)
+ {
+ // FIXME: throw an exception object instead
+ throw 1;
+ }
+ return m_letters;
+}
+
+
+wstring Move::toString() const
+{
+ // TODO
+ return L"";
+}
+
Index: game/move.h
===================================================================
RCS file: game/move.h
diff -N game/move.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ game/move.h 23 Dec 2007 23:12:44 -0000 1.1.2.1
@@ -0,0 +1,133 @@
+/*****************************************************************************
+ * Copyright (C) 2007 Eliot
+ * Authors: Olivier Teuliere <address@hidden>
+ *
+ * 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
+ *****************************************************************************/
+
+#ifndef _MOVE_H
+#define _MOVE_H
+
+#include <string>
+
+#include "round.h"
+
+using std::wstring;
+
+
+/**
+ * A Move is what a player can do during the game:
+ * - play a valid word
+ * - play an invalid or misplaced word
+ * - pass the turn (freegame only)
+ * - change letters (freegame only)
+ * - play nothing (timeout) (not supported yet)
+ *
+ * Moves are useful to record what happened, even if the board doesn't keep
+ * a trace of the move (e.g.: an invalid move which was rejected will still
+ * be remembered in the player history).
+ *
+ * Currently, moves are not used by the interfaces (they are only used
+ * internally), but this could change in the future.
+ */
+class Move
+{
+ public:
+ /**
+ * Constructor taking a (valid) round
+ */
+ explicit Move(const Round &iRound);
+
+ /**
+ * Constructor taking a word and its coordinates, corresponding
+ * to an invalid move by the player (invalid word, invalid coordinates,
+ * letters not corresponding to the rack, ...)
+ */
+ explicit Move(const wstring &iWord, const wstring &iCoord);
+
+ /**
+ * Constructor taking letters to change.
+ * An empty string means that the player simply passes without
+ * changing any letter.
+ * The given letters must have been already validated for correctness.
+ */
+ explicit Move(const wstring &iLetters);
+
+ enum Type
+ {
+ VALID_ROUND,
+ INVALID_WORD,
+ PASS,
+ CHANGE_LETTERS
+ };
+
+ /// Return the type of move
+ Type getType() const { return m_type; }
+
+ /// Get the score of this move (0 unless the round is valid)
+ int getScore() const { return m_score; };
+
+ /**
+ * Return the round associated with the move, or throw an exception
+ * if this move was not constructed from a valid round
+ */
+ const Round & getRound() const;
+
+ /**
+ * Return the word played at this move associated with the move, or
+ * throw an exception if this move was not constructed from an invalid
+ * pair (word, coord)
+ */
+ const wstring & getBadWord() const;
+
+ /**
+ * Return the coordinates of the (incorrect) word played at this move,
+ * or throw an exception if this move was not constructed from an
+ * invalid pair (cord, coord)
+ */
+ const wstring & getBadCoord() const;
+
+ /**
+ * Return the changed letters (possibly an empty string if the player
+ * simply wanted to pass the turn), or throw an exception if this move
+ * does not correspond to a passed turn
+ */
+ const wstring & getChangedLetters() const;
+
+ /// To help debugging
+ wstring toString() const;
+
+ private:
+ /// Type of move
+ Type m_type;
+
+ /// Score associated with this move
+ int m_score;
+
+ /// Round played at this turn
+ Round m_round;
+
+ /// Word played (incorrectly)
+ wstring m_word;
+
+ /// Coordinates of the word played (incorrectly)
+ wstring m_coord;
+
+ /// Changed letters (or empty string for passed turn)
+ wstring m_letters;
+};
+
+#endif
+