eliot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Eliot-dev] eliot game/Makefile.am qt/Makefile.am qt/bag_wi...


From: Olivier Teulière
Subject: [Eliot-dev] eliot game/Makefile.am qt/Makefile.am qt/bag_wi...
Date: Sun, 30 Nov 2008 20:53:46 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Changes by:     Olivier Teulière <ipkiss>      08/11/30 20:53:46

Modified files:
        game           : Makefile.am 
        qt             : Makefile.am bag_widget.cpp bag_widget.h 
                         board_widget.cpp board_widget.h 
                         history_widget.cpp history_widget.h 
                         main_window.cpp main_window.h new_game.cpp 
                         new_game.h player_widget.cpp player_widget.h 
                         score_widget.cpp score_widget.h 
                         training_widget.cpp training_widget.h 
        utils          : eliottxt.cpp game_io.cpp game_io.h ncurses.cpp 
                         ncurses.h 
Added files:
        game           : public_game.cpp public_game.h 

Log message:
         - New PublicGame class, intended to be used by the interfaces instead 
of accessing Game directly
         - Migrated the text, Qt and ncurses interfaces to the new PublicGame 
API.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/game/Makefile.am?cvsroot=eliot&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/eliot/game/public_game.cpp?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/public_game.h?cvsroot=eliot&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/Makefile.am?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/bag_widget.cpp?cvsroot=eliot&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/bag_widget.h?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/board_widget.cpp?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/board_widget.h?cvsroot=eliot&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/history_widget.cpp?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/history_widget.h?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/main_window.cpp?cvsroot=eliot&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/main_window.h?cvsroot=eliot&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/new_game.cpp?cvsroot=eliot&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/new_game.h?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/player_widget.cpp?cvsroot=eliot&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/player_widget.h?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/score_widget.cpp?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/score_widget.h?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/training_widget.cpp?cvsroot=eliot&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/eliot/qt/training_widget.h?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/eliottxt.cpp?cvsroot=eliot&r1=1.29&r2=1.30
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/game_io.cpp?cvsroot=eliot&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/game_io.h?cvsroot=eliot&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/ncurses.cpp?cvsroot=eliot&r1=1.29&r2=1.30
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/ncurses.h?cvsroot=eliot&r1=1.7&r2=1.8

Patches:
Index: game/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- game/Makefile.am    23 Nov 2008 16:55:28 -0000      1.21
+++ game/Makefile.am    30 Nov 2008 20:53:44 -0000      1.22
@@ -50,6 +50,7 @@
     duplicate.cpp duplicate.h \
     freegame.cpp freegame.h \
     training.cpp training.h \
+    public_game.cpp public_game.h \
     game_factory.cpp game_factory.h \
     game_io.cpp \
     debug.h

Index: qt/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/Makefile.am,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- qt/Makefile.am      23 Sep 2008 17:26:19 -0000      1.8
+++ qt/Makefile.am      30 Nov 2008 20:53:45 -0000      1.9
@@ -68,8 +68,8 @@
     score_widget.cpp score_widget.h \
     board_widget.cpp board_widget.h \
     history_widget.cpp history_widget.h \
-    player_widget.cpp player_widget.h \
     training_widget.cpp training_widget.h \
+    player_widget.cpp player_widget.h \
     prefs_dialog.cpp prefs_dialog.h \
     aux_window.cpp aux_window.h \
     main_window.cpp main_window.h \

Index: qt/bag_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/bag_widget.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- qt/bag_widget.cpp   22 Nov 2008 13:09:31 -0000      1.4
+++ qt/bag_widget.cpp   30 Nov 2008 20:53:45 -0000      1.5
@@ -25,7 +25,7 @@
 
 #include "bag_widget.h"
 #include "qtcommon.h"
-#include "game.h"
+#include "public_game.h"
 #include "dic.h"
 #include "tile.h"
 #include "bag.h"
@@ -53,7 +53,7 @@
 }
 
 
-void BagWidget::setGame(const Game *iGame)
+void BagWidget::setGame(const PublicGame *iGame)
 {
     m_game = iGame;
     updateModel();

Index: qt/bag_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/bag_widget.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- qt/bag_widget.h     22 Jan 2008 15:30:20 -0000      1.2
+++ qt/bag_widget.h     30 Nov 2008 20:53:45 -0000      1.3
@@ -24,7 +24,7 @@
 #include <QtGui/QTreeView>
 
 
-class Game;
+class PublicGame;
 class QStandardItemModel;
 
 class BagWidget: public QTreeView
@@ -35,7 +35,7 @@
     explicit BagWidget(QWidget *parent = 0);
 
 public slots:
-    void setGame(const Game *iGame);
+    void setGame(const PublicGame *iGame);
     void refresh();
 
 protected:
@@ -44,7 +44,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    const Game *m_game;
+    const PublicGame *m_game;
 
     /// Model of the bag
     QStandardItemModel *m_model;

Index: qt/board_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/board_widget.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- qt/board_widget.cpp 7 Sep 2008 21:06:17 -0000       1.6
+++ qt/board_widget.cpp 30 Nov 2008 20:53:45 -0000      1.7
@@ -24,7 +24,7 @@
 
 #include "board_widget.h"
 #include "qtcommon.h"
-#include "game.h"
+#include "public_game.h"
 #include "tile.h"
 #include "board.h"
 
@@ -53,7 +53,7 @@
 }
 
 
-void BoardWidget::setGame(const Game *iGame)
+void BoardWidget::setGame(const PublicGame *iGame)
 {
     m_game = iGame;
     refresh();

Index: qt/board_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/board_widget.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- qt/board_widget.h   7 Sep 2008 21:06:17 -0000       1.4
+++ qt/board_widget.h   30 Nov 2008 20:53:45 -0000      1.5
@@ -24,7 +24,7 @@
 #include <QtGui/QFrame>
 
 
-class Game;
+class PublicGame;
 class QTreeView;
 
 class BoardWidget: public QFrame
@@ -35,7 +35,7 @@
     explicit BoardWidget(QWidget *parent = 0);
 
 public slots:
-    void setGame(const Game *iGame);
+    void setGame(const PublicGame *iGame);
     void refresh();
 
 protected:
@@ -46,7 +46,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    const Game *m_game;
+    const PublicGame *m_game;
 
     /// Define a few background colours
     //@{

Index: qt/history_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/history_widget.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- qt/history_widget.cpp       27 Jan 2008 20:17:10 -0000      1.6
+++ qt/history_widget.cpp       30 Nov 2008 20:53:45 -0000      1.7
@@ -28,7 +28,7 @@
 #include "history_widget.h"
 #include "prefs_dialog.h"
 #include "qtcommon.h"
-#include "game.h"
+#include "public_game.h"
 #include "player.h"
 #include "history.h"
 #include "turn.h"
@@ -58,7 +58,7 @@
 
 
 void HistoryWidget::setHistory(const History *iHistory,
-                               const Game *iGame,
+                               const PublicGame *iGame,
                                bool iIsForPlayer)
 {
     m_history = iHistory;
@@ -181,7 +181,7 @@
 }
 
 
-void HistoryTabWidget::setGame(const Game *iGame)
+void HistoryTabWidget::setGame(const PublicGame *iGame)
 {
     m_game = iGame;
 
@@ -210,11 +210,11 @@
                          m_gameHistoryWidget, SLOT(refresh()));
 
         // In training mode, the players history is completely useless
-        if (m_game->getMode() == Game::kTRAINING)
+        if (m_game->getMode() == PublicGame::kTRAINING)
             return;
 
         // Add one history tab per player
-        for (unsigned int i = 0; i < m_game->getNPlayers(); ++i)
+        for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
         {
             const Player &player = m_game->getPlayer(i);
             HistoryWidget *h = new HistoryWidget(NULL);

Index: qt/history_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/history_widget.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- qt/history_widget.h 26 Jan 2008 16:58:47 -0000      1.3
+++ qt/history_widget.h 30 Nov 2008 20:53:45 -0000      1.4
@@ -26,7 +26,7 @@
 
 
 class History;
-class Game;
+class PublicGame;
 class QStandardItemModel;
 class QTabWidget;
 
@@ -38,7 +38,7 @@
     explicit HistoryWidget(QWidget *parent = 0);
 
     void setHistory(const History *iHistory,
-                    const Game *iGame = NULL,
+                    const PublicGame *iGame = NULL,
                     bool iIsForPlayer = false);
 
 public slots:
@@ -49,7 +49,7 @@
     const History *m_history;
 
     /// Corresponding game (used to retrieve the players names) can be NULL
-    const Game *m_game;
+    const PublicGame *m_game;
 
     /**
      * Flag to avoid displaying the "players" column when the History object
@@ -73,7 +73,7 @@
     explicit HistoryTabWidget(QWidget *parent = NULL);
 
 public slots:
-    void setGame(const Game *iGame);
+    void setGame(const PublicGame *iGame);
     void refresh();
 
 signals:
@@ -84,7 +84,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    const Game *m_game;
+    const PublicGame *m_game;
 
     /**
      * HistoryWidget for the game: we reuse it instead of creating and

Index: qt/main_window.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/main_window.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- qt/main_window.cpp  30 Nov 2008 20:51:06 -0000      1.20
+++ qt/main_window.cpp  30 Nov 2008 20:53:45 -0000      1.21
@@ -39,7 +39,7 @@
 #include "header.h"
 #include "game_factory.h"
 #include "game.h"
-#include "freegame.h"
+#include "public_game.h"
 #include "player.h"
 #include "history.h"
 #include "turn.h"
@@ -84,8 +84,8 @@
     cout << "Rand seed: " << val << endl;
 #endif
 
-    QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                     this, SLOT(updateForGame(const Game*)));
+    QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                     this, SLOT(updateForGame(const PublicGame*)));
     QObject::connect(this, SIGNAL(gameUpdated()),
                      this, SLOT(refresh()));
     refresh();
@@ -100,8 +100,8 @@
 
     // Board
     BoardWidget *boardWidget = new BoardWidget;
-    QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                     boardWidget, SLOT(setGame(const Game*)));
+    QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                     boardWidget, SLOT(setGame(const PublicGame*)));
     QObject::connect(this, SIGNAL(gameUpdated()),
                      boardWidget, SLOT(refresh()));
 
@@ -120,8 +120,8 @@
 
     // History
     HistoryTabWidget *historyTab = new HistoryTabWidget;
-    QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                     historyTab, SLOT(setGame(const Game*)));
+    QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                     historyTab, SLOT(setGame(const PublicGame*)));
     QObject::connect(this, SIGNAL(gameUpdated()),
                      historyTab, SLOT(refresh()));
     QHBoxLayout *hlayout2 = new QHBoxLayout;
@@ -132,8 +132,8 @@
     m_ui.groupBoxPlayers->hide();
     PlayerTabWidget *players = new PlayerTabWidget(NULL);
     m_ui.groupBoxPlayers->layout()->addWidget(players);
-    QObject::connect(this, SIGNAL(gameChangedNonConst(Game*)),
-                     players, SLOT(setGame(Game*)));
+    QObject::connect(this, SIGNAL(gameChangedNonConst(PublicGame*)),
+                     players, SLOT(setGame(PublicGame*)));
     QObject::connect(this, SIGNAL(gameUpdated()), players, SLOT(refresh()));
 
     QObject::connect(players, SIGNAL(gameUpdated()), this, 
SIGNAL(gameUpdated()));
@@ -144,8 +144,8 @@
 
     // Players score
     ScoreWidget *scores = new ScoreWidget;
-    QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                     scores, SLOT(setGame(const Game*)));
+    QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                     scores, SLOT(setGame(const PublicGame*)));
     QObject::connect(this, SIGNAL(gameUpdated()),
                      scores, SLOT(refresh()));
     m_ui.groupBoxPlayers->layout()->addWidget(scores);
@@ -204,8 +204,8 @@
 {
     if (m_game != NULL)
     {
-        bool isFirstTurn = m_game->getNavigation().isFirstTurn();
-        bool isLastTurn = m_game->getNavigation().isLastTurn();
+        bool isFirstTurn = m_game->isFirstTurn();
+        bool isLastTurn = m_game->isLastTurn();
         m_actionHistoryFirstTurn->setEnabled(!isFirstTurn);
         m_actionHistoryPrevTurn->setEnabled(!isFirstTurn);
         m_actionHistoryNextTurn->setEnabled(!isLastTurn);
@@ -213,13 +213,13 @@
         m_actionHistoryReplayTurn->setEnabled(!isLastTurn);
 #ifdef DEBUG
         cout << endl << endl;
-        m_game->getNavigation().print();
+        m_game->printTurns();
 #endif
     }
 }
 
 
-void MainWindow::updateForGame(const Game *iGame)
+void MainWindow::updateForGame(const PublicGame *iGame)
 {
     if (iGame == NULL)
     {
@@ -235,12 +235,12 @@
     else
     {
         m_actionGamePrint->setEnabled(true);
-        if (iGame->getMode() == Game::kTRAINING)
+        if (iGame->getMode() == PublicGame::kTRAINING)
         {
             m_actionGameSaveAs->setEnabled(true);
             setWindowTitle(_q("Training mode") + " - Eliot");
         }
-        else if (iGame->getMode() == Game::kDUPLICATE)
+        else if (iGame->getMode() == PublicGame::kDUPLICATE)
         {
             m_actionGameSaveAs->setEnabled(false);
             setWindowTitle(_q("Duplicate game") + " - Eliot");
@@ -456,12 +456,13 @@
     if (fileName != "")
     {
         destroyCurrentGame();
-        m_game = GameFactory::Instance()->load(qtl(fileName), *m_dic);
-        if (m_game == NULL)
+        Game *tmpGame = GameFactory::Instance()->load(qtl(fileName), *m_dic);
+        if (tmpGame == NULL)
         {
             displayErrorMsg(_q("Error while loading the game"));
             return;
         }
+        m_game = new PublicGame(*tmpGame);
         m_ui.groupBoxPlayers->show();
         emit gameChangedNonConst(m_game);
         emit gameChanged(m_game);
@@ -701,8 +702,8 @@
         bag->setGame(m_game);
         m_bagWindow = new AuxWindow(*bag, _q("Bag"), "BagWindow",
                                     m_actionWindowsBag);
-        QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                         bag, SLOT(setGame(const Game*)));
+        QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                         bag, SLOT(setGame(const PublicGame*)));
         QObject::connect(this, SIGNAL(gameUpdated()),
                          bag, SLOT(refresh()));
     }
@@ -719,8 +720,8 @@
         board->setGame(m_game);
         m_boardWindow = new AuxWindow(*board, _q("Board"), "BoardWindow",
                                       m_actionWindowsBoard);
-        QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                         board, SLOT(setGame(const Game*)));
+        QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                         board, SLOT(setGame(const PublicGame*)));
         QObject::connect(this, SIGNAL(gameUpdated()),
                          board, SLOT(refresh()));
     }
@@ -737,8 +738,8 @@
         history->setGame(m_game);
         m_historyWindow = new AuxWindow(*history, _q("History"), 
"HistoryWindow",
                                         m_actionWindowsHistory);
-        QObject::connect(this, SIGNAL(gameChanged(const Game*)),
-                         history, SLOT(setGame(const Game*)));
+        QObject::connect(this, SIGNAL(gameChanged(const PublicGame*)),
+                         history, SLOT(setGame(const PublicGame*)));
         QObject::connect(this, SIGNAL(gameUpdated()),
                          history, SLOT(refresh()));
     }
@@ -787,10 +788,10 @@
     if (m_game == NULL)
         return;
 
-    m_game->accessNavigation().firstTurn();
+    m_game->firstTurn();
     emit gameUpdated();
-    unsigned int currTurn = m_game->getNavigation().getCurrTurn();
-    unsigned int nbTurns = m_game->getNavigation().getNbTurns();
+    unsigned int currTurn = m_game->getCurrTurn();
+    unsigned int nbTurns = m_game->getNbTurns();
     displayInfoMsg(_q("Turn %1/%2").arg(currTurn).arg(nbTurns));
 }
 
@@ -800,10 +801,10 @@
     if (m_game == NULL)
         return;
 
-    m_game->accessNavigation().prevTurn();
+    m_game->prevTurn();
     emit gameUpdated();
-    unsigned int currTurn = m_game->getNavigation().getCurrTurn();
-    unsigned int nbTurns = m_game->getNavigation().getNbTurns();
+    unsigned int currTurn = m_game->getCurrTurn();
+    unsigned int nbTurns = m_game->getNbTurns();
     displayInfoMsg(_q("Turn %1/%2").arg(currTurn).arg(nbTurns));
 }
 
@@ -813,10 +814,10 @@
     if (m_game == NULL)
         return;
 
-    m_game->accessNavigation().nextTurn();
+    m_game->nextTurn();
     emit gameUpdated();
-    unsigned int currTurn = m_game->getNavigation().getCurrTurn();
-    unsigned int nbTurns = m_game->getNavigation().getNbTurns();
+    unsigned int currTurn = m_game->getCurrTurn();
+    unsigned int nbTurns = m_game->getNbTurns();
     displayInfoMsg(_q("Turn %1/%2").arg(currTurn).arg(nbTurns));
 }
 
@@ -826,10 +827,10 @@
     if (m_game == NULL)
         return;
 
-    m_game->accessNavigation().lastTurn();
+    m_game->lastTurn();
     emit gameUpdated();
-    unsigned int currTurn = m_game->getNavigation().getCurrTurn();
-    unsigned int nbTurns = m_game->getNavigation().getNbTurns();
+    unsigned int currTurn = m_game->getCurrTurn();
+    unsigned int nbTurns = m_game->getNbTurns();
     displayInfoMsg(_q("Turn %1/%2").arg(currTurn).arg(nbTurns));
 }
 
@@ -849,7 +850,7 @@
     if (ret != QMessageBox::Ok)
         return;
 
-    m_game->accessNavigation().clearFuture();
+    m_game->clearFuture();
     emit gameUpdated();
     displayInfoMsg(_q("Future turns deleted"));
 }

Index: qt/main_window.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/main_window.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- qt/main_window.h    29 Nov 2008 16:41:00 -0000      1.13
+++ qt/main_window.h    30 Nov 2008 20:53:45 -0000      1.14
@@ -30,7 +30,7 @@
 class Bag;
 class Board;
 class History;
-class Game;
+class PublicGame;
 class NewGame;
 class PrefsDialog;
 class AuxWindow;
@@ -47,8 +47,8 @@
 
 signals:
     void dicChanged(const Dictionary *iDic);
-    void gameChanged(const Game *iGame);
-    void gameChangedNonConst(Game *iGame);
+    void gameChanged(const PublicGame *iGame);
+    void gameChangedNonConst(PublicGame *iGame);
     void gameUpdated();
 
 public slots:
@@ -87,7 +87,7 @@
      * Perform several updates when the game changes (title bar, status bar,
      * grey out some menu items, ...)
      */
-    void updateForGame(const Game *iGame);
+    void updateForGame(const PublicGame *iGame);
 
     /// Update the status bar contents
     void updateStatusBar(const Dictionary *iDic);
@@ -97,7 +97,7 @@
     const Dictionary *m_dic;
 
     /// Current game
-    Game *m_game;
+    PublicGame *m_game;
 
     /// The UI file generated with Qt Designer
     Ui::MainWindow m_ui;

Index: qt/new_game.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/new_game.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- qt/new_game.cpp     3 Sep 2008 17:28:28 -0000       1.5
+++ qt/new_game.cpp     30 Nov 2008 20:53:45 -0000      1.6
@@ -28,6 +28,7 @@
 #include "qtcommon.h"
 #include "game_factory.h"
 #include "game.h"
+#include "public_game.h"
 #include "training.h"
 #include "freegame.h"
 #include "duplicate.h"
@@ -90,16 +91,17 @@
 }
 
 
-Game * NewGame::createGame(const Dictionary &iDic) const
+PublicGame * NewGame::createGame(const Dictionary &iDic) const
 {
     // Create the game
-    Game *game = NULL;
+    Game *tmpGame = NULL;
     if (comboBoxMode->currentText() == _q("Training"))
-        game = GameFactory::Instance()->createTraining(iDic);
+        tmpGame = GameFactory::Instance()->createTraining(iDic);
     else if (comboBoxMode->currentText() == _q("Free game"))
-        game = GameFactory::Instance()->createFreeGame(iDic);
+        tmpGame = GameFactory::Instance()->createFreeGame(iDic);
     else
-        game = GameFactory::Instance()->createDuplicate(iDic);
+        tmpGame = GameFactory::Instance()->createDuplicate(iDic);
+    PublicGame *game = new PublicGame(*tmpGame);
 
     // Add the players
     if (comboBoxMode->currentText() != _q("Training"))
@@ -142,7 +144,7 @@
 
     // Joker game?
     if (checkBoxJoker->isChecked())
-        game->setVariant(Game::kJOKER);
+        game->setVariant(PublicGame::kJOKER);
 
     return game;
 }

Index: qt/new_game.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/new_game.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- qt/new_game.h       3 Sep 2008 17:28:28 -0000       1.3
+++ qt/new_game.h       30 Nov 2008 20:53:45 -0000      1.4
@@ -28,7 +28,7 @@
 
 
 class Dictionary;
-class Game;
+class PublicGame;
 class QStandardItemModel;
 
 class NewGame: public QDialog, private Ui::NewGameDialog
@@ -46,7 +46,7 @@
      * Create and return a game object from the information of the dialog.
      * The Game object is always valid
      */
-    Game * createGame(const Dictionary& iDic) const;
+    PublicGame * createGame(const Dictionary& iDic) const;
 
 private slots:
     void enableLevelSpinBox(int);

Index: qt/player_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/player_widget.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- qt/player_widget.cpp        4 Nov 2008 21:31:14 -0000       1.10
+++ qt/player_widget.cpp        30 Nov 2008 20:53:45 -0000      1.11
@@ -26,9 +26,7 @@
 #include "player_widget.h"
 #include "training_widget.h"
 #include "qtcommon.h"
-#include "game.h"
-#include "freegame.h"
-#include "duplicate.h"
+#include "public_game.h"
 #include "player.h"
 #include "pldrack.h"
 #include "coord.h"
@@ -73,7 +71,7 @@
 };
 
 
-PlayerWidget::PlayerWidget(QWidget *parent, unsigned int iPlayerNb, Game 
*iGame)
+PlayerWidget::PlayerWidget(QWidget *parent, unsigned int iPlayerNb, PublicGame 
*iGame)
     : QWidget(parent), m_game(iGame), m_player(iPlayerNb)
 {
     setupUi(this);
@@ -97,9 +95,9 @@
             setEnabled(false);
 
         // Changing the rack is authorized only in training mode
-        lineEditRack->setReadOnly(m_game->getMode() != Game::kTRAINING);
+        lineEditRack->setReadOnly(m_game->getMode() != PublicGame::kTRAINING);
     }
-    if (m_game == NULL || m_game->getMode() != Game::kFREEGAME)
+    if (m_game == NULL || m_game->getMode() != PublicGame::kFREEGAME)
     {
         // Hide the freegame-specific controls
         labelChange->hide();
@@ -193,7 +191,7 @@
     }
 
     QString coords = lineEditCoords->text();
-    int res = m_game->play(qtw(coords), qtw(word));
+    int res = m_game->play(qtw(word), qtw(coords));
     if (res == 0)
     {
         emit gameUpdated();
@@ -253,13 +251,12 @@
 
 void PlayerWidget::on_lineEditChange_returnPressed()
 {
-    FreeGame *free = dynamic_cast<FreeGame*>(m_game);
-    ASSERT(free != NULL,
+    ASSERT(m_game->getMode() == PublicGame::kFREEGAME,
            "Trying to pass or change letters while not in free game mode");
 
     // Pass the turn (and possibly change letters)
     QString letters = lineEditChange->text();
-    int res = free->pass(qtw(letters));
+    int res = m_game->freeGamePass(qtw(letters));
     if (res == 0)
         emit gameUpdated();
     else
@@ -378,7 +375,7 @@
 }
 
 
-void PlayerTabWidget::setGame(Game *iGame)
+void PlayerTabWidget::setGame(PublicGame *iGame)
 {
     m_game = iGame;
 
@@ -396,7 +393,7 @@
     if (iGame != NULL)
     {
         // Training mode: use a dedicated widget
-        if (iGame->getMode() == Game::kTRAINING)
+        if (iGame->getMode() == PublicGame::kTRAINING)
         {
             const Player &player = iGame->getPlayer(0);
             TrainingWidget *trWidget = new TrainingWidget;
@@ -415,7 +412,7 @@
         else
         {
             // Add one tab per player
-            for (unsigned int i = 0; i < iGame->getNPlayers(); ++i)
+            for (unsigned int i = 0; i < iGame->getNbPlayers(); ++i)
             {
                 const Player &player = iGame->getPlayer(i);
                 PlayerWidget *p = new PlayerWidget(NULL, i, iGame);
@@ -431,7 +428,7 @@
                 if (!player.isHuman())
                     setTabEnabled(i, false);
             }
-            setCurrentIndex(iGame->currPlayer());
+            setCurrentIndex(iGame->getCurrentPlayer().getId());
         }
     }
 }
@@ -440,7 +437,7 @@
 void PlayerTabWidget::refresh()
 {
     if (m_game)
-        setCurrentIndex(m_game->currPlayer());
+        setCurrentIndex(m_game->getCurrentPlayer().getId());
     emit refreshSignal();
 }
 
@@ -449,10 +446,10 @@
 {
     // Change the active player when the active tab changes
     // (only in duplicate mode)
-    Duplicate *dupli = dynamic_cast<Duplicate*>(m_game);
-    if (dupli && widget(p)->isEnabled())
+    if (m_game->getMode() == PublicGame::kDUPLICATE &&
+        widget(p)->isEnabled())
     {
-        dupli->setPlayer(p);
+        m_game->duplicateSetPlayer(p);
     }
 }
 

Index: qt/player_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/player_widget.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- qt/player_widget.h  4 Nov 2008 21:31:14 -0000       1.7
+++ qt/player_widget.h  30 Nov 2008 20:53:45 -0000      1.8
@@ -27,7 +27,7 @@
 
 
 class QLineEdit;
-class Game;
+class PublicGame;
 
 class PlayerWidget: public QWidget, private Ui::PlayerWidget
 {
@@ -36,7 +36,7 @@
 public:
     explicit PlayerWidget(QWidget *parent = 0,
                           unsigned int iPlayerNb = 0,
-                          Game *iGame = NULL);
+                          PublicGame *iGame = NULL);
 
 signals:
     void gameUpdated();
@@ -63,7 +63,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    Game *m_game;
+    PublicGame *m_game;
 
     /// Encapsulated player, valid iff m_game is not NULL
     unsigned int m_player;
@@ -79,7 +79,7 @@
     explicit PlayerTabWidget(QWidget *parent = 0);
 
 public slots:
-    void setGame(Game *iGame);
+    void setGame(PublicGame *iGame);
     void refresh();
 
 signals:
@@ -93,7 +93,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    Game *m_game;
+    PublicGame *m_game;
 };
 
 #endif

Index: qt/score_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/score_widget.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- qt/score_widget.cpp 24 Jan 2008 20:18:01 -0000      1.3
+++ qt/score_widget.cpp 30 Nov 2008 20:53:45 -0000      1.4
@@ -23,13 +23,13 @@
 
 #include "score_widget.h"
 #include "qtcommon.h"
-#include "game.h"
+#include "public_game.h"
 #include "player.h"
 
 using namespace std;
 
 
-ScoreWidget::ScoreWidget(QWidget *parent, const Game *iGame)
+ScoreWidget::ScoreWidget(QWidget *parent, const PublicGame *iGame)
     : QTreeView(parent), m_game(iGame)
 {
     // Create the tree view
@@ -49,7 +49,7 @@
 }
 
 
-void ScoreWidget::setGame(const Game *iGame)
+void ScoreWidget::setGame(const PublicGame *iGame)
 {
     m_game = iGame;
     updateModel();
@@ -71,7 +71,7 @@
     if (m_game == NULL)
         return;
 
-    for (unsigned int i = 0; i < m_game->getNPlayers(); ++i)
+    for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
     {
         const Player &p = m_game->getPlayer(i);
         int rowNum = m_model->rowCount();

Index: qt/score_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/score_widget.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- qt/score_widget.h   22 Jan 2008 15:30:22 -0000      1.2
+++ qt/score_widget.h   30 Nov 2008 20:53:45 -0000      1.3
@@ -24,7 +24,7 @@
 #include <QtGui/QTreeView>
 
 
-class Game;
+class PublicGame;
 class QStandardItemModel;
 
 class ScoreWidget: public QTreeView
@@ -32,10 +32,10 @@
     Q_OBJECT;
 
 public:
-    explicit ScoreWidget(QWidget *parent = 0, const Game *iGame = NULL);
+    explicit ScoreWidget(QWidget *parent = 0, const PublicGame *iGame = NULL);
 
 public slots:
-    void setGame(const Game *iGame = NULL);
+    void setGame(const PublicGame *iGame = NULL);
     void refresh();
 
 protected:
@@ -44,7 +44,7 @@
 
 private:
     /// Encapsulated game, can be NULL
-    const Game *m_game;
+    const PublicGame *m_game;
 
     /// Model of the game
     QStandardItemModel *m_model;

Index: qt/training_widget.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/training_widget.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- qt/training_widget.cpp      22 Nov 2008 13:09:32 -0000      1.5
+++ qt/training_widget.cpp      30 Nov 2008 20:53:46 -0000      1.6
@@ -24,9 +24,9 @@
 #include "training_widget.h"
 #include "qtcommon.h"
 #include "dic.h"
-#include "game.h"
+#include "bag.h"
+#include "public_game.h"
 #include "game_exception.h"
-#include "training.h"
 #include "player.h"
 #include "results.h"
 
@@ -83,9 +83,9 @@
 }
 
 
-void TrainingWidget::setGame(Game *iGame)
+void TrainingWidget::setGame(PublicGame *iGame)
 {
-    m_game = dynamic_cast<Training*>(iGame);
+    m_game = iGame;
     if (m_game != NULL)
         m_validator->setBag(&m_game->getBag());
     else
@@ -126,7 +126,7 @@
     // Consider that there is nothing to do if the number of lines is correct
     // This avoids problems when the game is updated for a test play
     if (m_game != NULL &&
-        m_game->getResults().size() == (unsigned int)m_model->rowCount())
+        m_game->trainingGetResults().size() == (unsigned 
int)m_model->rowCount())
     {
         return;
     }
@@ -136,9 +136,10 @@
     if (m_game == NULL)
         return;
 
-    for (unsigned int i = 0; i < m_game->getResults().size(); ++i)
+    const Results &results = m_game->trainingGetResults();
+    for (unsigned int i = 0; i < results.size(); ++i)
     {
-        const Round &r = m_game->getResults().get(i);
+        const Round &r = results.get(i);
         int rowNum = m_model->rowCount();
         m_model->insertRow(rowNum);
         m_model->setData(m_model->index(rowNum, 0), qfw(r.getWord()));
@@ -174,13 +175,13 @@
 void TrainingWidget::showPreview(const QItemSelection &iSelected,
                                  const QItemSelection &)
 {
-    m_game->removeTestPlay();
+    m_game->trainingRemoveTestPlay();
     if (!iSelected.indexes().empty())
     {
         // Use the hidden column to get the result number
         const QModelIndex &index =
             m_model->index(iSelected.indexes().first().row(), 5);
-        m_game->testPlay(m_model->data(index).toUInt());
+        m_game->trainingTestPlay(m_model->data(index).toUInt());
         emit gameUpdated();
     }
 }
@@ -189,7 +190,7 @@
 void TrainingWidget::on_lineEditRack_textEdited(const QString &iText)
 {
     // FIXME: first parameter is hardcoded
-    int res = m_game->setRackManual(false, qtw(iText));
+    int res = m_game->trainingSetRackManual(false, qtw(iText));
     if (res == 0)
     {
         pushButtonSearch->setEnabled(m_model->rowCount() == 0 &&
@@ -204,10 +205,10 @@
 void TrainingWidget::on_pushButtonRack_clicked()
 {
     // FIXME: first parameter is hardcoded
-    m_game->removeTestPlay();
+    m_game->trainingRemoveTestPlay();
     try
     {
-        m_game->setRackRandom(true, Game::RACK_ALL);
+        m_game->trainingSetRackRandom(true, PublicGame::kRACK_ALL);
         emit gameUpdated();
     }
     catch (GameException &e)
@@ -220,10 +221,10 @@
 void TrainingWidget::on_pushButtonComplement_clicked()
 {
     // FIXME: first parameter is hardcoded
-    m_game->removeTestPlay();
+    m_game->trainingRemoveTestPlay();
     try
     {
-        m_game->setRackRandom(true, Game::RACK_NEW);
+        m_game->trainingSetRackRandom(true, PublicGame::kRACK_NEW);
         emit gameUpdated();
     }
     catch (GameException &e)
@@ -235,9 +236,9 @@
 
 void TrainingWidget::on_pushButtonSearch_clicked()
 {
-    m_game->removeTestPlay();
+    m_game->trainingRemoveTestPlay();
     emit notifyInfo(_q("Searching with rack 
'%1'...").arg(lineEditRack->text()));
-    m_game->search();
+    m_game->trainingSearch();
     emit notifyInfo(_q("Search done"));
     emit gameUpdated();
 }
@@ -257,10 +258,10 @@
 {
     if (!iIndex.isValid())
         return;
-    m_game->removeTestPlay();
+    m_game->trainingRemoveTestPlay();
     // Use the hidden column to get the result number
     const QModelIndex &index = m_model->index(iIndex.row(), 5);
-    m_game->playResult(m_model->data(index).toUInt());
+    m_game->trainingPlayResult(m_model->data(index).toUInt());
     emit gameUpdated();
 }
 

Index: qt/training_widget.h
===================================================================
RCS file: /cvsroot/eliot/eliot/qt/training_widget.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- qt/training_widget.h        4 Nov 2008 21:31:18 -0000       1.3
+++ qt/training_widget.h        30 Nov 2008 20:53:46 -0000      1.4
@@ -25,8 +25,7 @@
 #include "ui/training_widget.ui.h"
 
 
-class Game;
-class Training;
+class PublicGame;
 class RackValidator;
 class QStandardItemModel;
 class QString;
@@ -39,7 +38,7 @@
     explicit TrainingWidget(QWidget *parent = 0);
 
 public slots:
-    void setGame(Game *iGame);
+    void setGame(PublicGame *iGame);
     void refresh();
 
 signals:
@@ -65,7 +64,7 @@
 
 private:
     /// Encapsulated training game, can be NULL
-    Training *m_game;
+    PublicGame *m_game;
 
     /// Model of the search results
     QStandardItemModel *m_model;

Index: utils/eliottxt.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/eliottxt.cpp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- utils/eliottxt.cpp  23 Nov 2008 18:18:59 -0000      1.29
+++ utils/eliottxt.cpp  30 Nov 2008 20:53:46 -0000      1.30
@@ -38,6 +38,7 @@
 #include "dic_exception.h"
 #include "game_io.h"
 #include "game_factory.h"
+#include "public_game.h"
 #include "training.h"
 #include "duplicate.h"
 #include "freegame.h"
@@ -310,7 +311,7 @@
 }
 
 
-void display_data(const Game &iGame, const wchar_t *delim, wchar_t **state)
+void display_data(const PublicGame &iGame, const wchar_t *delim, wchar_t 
**state)
 {
     const wchar_t *token;
 
@@ -346,7 +347,7 @@
             }
             break;
         case L'j':
-            cout << "Joueur " << iGame.currPlayer() << endl;
+            cout << "Joueur " << iGame.getCurrentPlayer().getId() << endl;
             break;
         case L'l':
             GameIO::printNonPlayed(cout, iGame);
@@ -355,7 +356,7 @@
             switch (token[1])
                 {
                 case '\0':
-                    iGame.save(cout,Game::FILE_FORMAT_ADVANCED);
+                    iGame.save(cout,PublicGame::kFILE_FORMAT_ADVANCED);
                     break;
                 case 'd':
                     GameIO::printGameDebug(cout, iGame);
@@ -365,17 +366,17 @@
                 }
             break;
         case L'P':
-            iGame.save(cout,Game::FILE_FORMAT_STANDARD);
+            iGame.save(cout,PublicGame::kFILE_FORMAT_STANDARD);
             break;
         case L'r':
             token = next_token_digit(NULL, delim, state);
             if (token == NULL)
                 GameIO::printSearchResults(cout,
-                                           static_cast<const Training&>(iGame),
+                                           iGame.trainingGetResults(),
                                            10);
             else
                 GameIO::printSearchResults(cout,
-                                           static_cast<const Training&>(iGame),
+                                           iGame.trainingGetResults(),
                                            _wtoi(token));
             break;
         case L's':
@@ -397,7 +398,7 @@
 }
 
 
-void loop_training(Training &iGame)
+void loop_training(PublicGame &iGame)
 {
     const wchar_t *token;
     wchar_t *state;
@@ -506,7 +507,7 @@
                                 help_training();
                                 break;
                             }
-                            if ((res = iGame.play(coord, token)) != 0)
+                            if ((res = iGame.play(token, coord)) != 0)
                             {
                                 fprintf(stdout, "Mot incorrect ou mal placé 
(%i)\n",
                                         res);
@@ -523,24 +524,30 @@
                             int n = _wtoi(token);
                             if (n <= 0)
                             {
-                                iGame.back(n == 0 ? 1 : -n);
+                                if (n == 0)
+                                    n = -1;
+                                if ((unsigned int)-n > 
iGame.getHistory().getSize())
+                                    throw GameException("Cannot go back that 
far");
+                                for (int i = 0; i < -n; ++i)
+                                    iGame.prevTurn();
+                                iGame.clearFuture();
                             }
                             else
                             {
-                                if (iGame.playResult(--n))
+                                if (iGame.trainingPlayResult(--n))
                                     printf("mauvais argument\n");
                             }
                         }
                         break;
                     case L'r':
-                        iGame.search();
+                        iGame.trainingSearch();
                         break;
                     case L't':
                         token = next_token_alphaplusjoker(NULL, delim, &state);
                         if (token == NULL)
                             help_training();
                         else
-                            if (iGame.setRackManual(0, token))
+                            if (iGame.trainingSetRackManual(0, token))
                                 printf("le sac ne contient pas assez de 
lettres\n");
                         break;
                     case L'x':
@@ -551,10 +558,10 @@
                             eliottxt_get_cross(iGame.getDic(), token);
                         break;
                     case L'*':
-                        iGame.setRackRandom(false, Game::RACK_ALL);
+                        iGame.trainingSetRackRandom(false, 
PublicGame::kRACK_ALL);
                         break;
                     case L'+':
-                        iGame.setRackRandom(false, Game::RACK_NEW);
+                        iGame.trainingSetRackRandom(false, 
PublicGame::kRACK_NEW);
                         break;
                     case L's':
                         token = next_token_filename(NULL, delim, &state);
@@ -579,16 +586,16 @@
                             switch (token[0])
                             {
                                 case L'p':
-                                    iGame.accessNavigation().prevTurn();
+                                    iGame.prevTurn();
                                     break;
                                 case L'n':
-                                    iGame.accessNavigation().nextTurn();
+                                    iGame.nextTurn();
                                     break;
                                 case L'f':
-                                    iGame.accessNavigation().firstTurn();
+                                    iGame.firstTurn();
                                     break;
                                 case L'l':
-                                    iGame.accessNavigation().lastTurn();
+                                    iGame.lastTurn();
                                     break;
                             }
                         }
@@ -611,7 +618,7 @@
 }
 
 
-void loop_freegame(FreeGame &iGame)
+void loop_freegame(PublicGame &iGame)
 {
     const wchar_t *token;
     wchar_t *state;
@@ -668,7 +675,7 @@
                                 help_freegame();
                                 break;
                             }
-                            if ((res = iGame.play(coord, token)) != 0)
+                            if ((res = iGame.play(token, coord)) != 0)
                             {
                                 fprintf(stdout, "Mot incorrect ou mal placé 
(%i)\n",
                                         res);
@@ -682,7 +689,7 @@
                         if (token == NULL)
                             token = L"";
 
-                        if (iGame.pass(token) != 0)
+                        if (iGame.freeGamePass(token) != 0)
                             break;
                         break;
                     case L's':
@@ -708,16 +715,16 @@
                             switch (token[0])
                             {
                                 case L'p':
-                                    iGame.accessNavigation().prevTurn();
+                                    iGame.prevTurn();
                                     break;
                                 case L'n':
-                                    iGame.accessNavigation().nextTurn();
+                                    iGame.nextTurn();
                                     break;
                                 case L'f':
-                                    iGame.accessNavigation().firstTurn();
+                                    iGame.firstTurn();
                                     break;
                                 case L'l':
-                                    iGame.accessNavigation().lastTurn();
+                                    iGame.lastTurn();
                                     break;
                             }
                         }
@@ -740,7 +747,7 @@
 }
 
 
-void loop_duplicate(Duplicate &iGame)
+void loop_duplicate(PublicGame &iGame)
 {
     const wchar_t *token;
     wchar_t *state;
@@ -797,7 +804,7 @@
                                 help_duplicate();
                                 break;
                             }
-                            if ((res = iGame.play(coord, token)) != 0)
+                            if ((res = iGame.play(token, coord)) != 0)
                             {
                                 fprintf(stdout, "Mot incorrect ou mal placé 
(%i)\n",
                                         res);
@@ -812,12 +819,12 @@
                         else
                         {
                             int n = _wtoi(token);
-                            if (n < 0 || n >= (int)iGame.getNPlayers())
+                            if (n < 0 || n >= (int)iGame.getNbPlayers())
                             {
                                 fprintf(stderr, "Numéro de joueur invalide\n");
                                 break;
                             }
-                            int res = iGame.setPlayer(_wtoi(token));
+                            int res = iGame.duplicateSetPlayer(_wtoi(token));
                             if (res == 1)
                                 fprintf(stderr, "Impossible de choisir un 
joueur non humain\n");
                         }
@@ -845,16 +852,16 @@
                             switch (token[0])
                             {
                                 case L'p':
-                                    iGame.accessNavigation().prevTurn();
+                                    iGame.prevTurn();
                                     break;
                                 case L'n':
-                                    iGame.accessNavigation().nextTurn();
+                                    iGame.nextTurn();
                                     break;
                                 case L'f':
-                                    iGame.accessNavigation().firstTurn();
+                                    iGame.firstTurn();
                                     break;
                                 case L'l':
-                                    iGame.accessNavigation().lastTurn();
+                                    iGame.lastTurn();
                                     break;
                             }
                         }
@@ -1000,36 +1007,40 @@
                     else
                     {
                         string filename = convertToMb(token);
-                        Game *game = GameFactory::Instance()->load(filename, 
iDic);
-                        if (game == NULL)
+                        Game *tmpGame = 
GameFactory::Instance()->load(filename, iDic);
+                        if (tmpGame == NULL)
                         {
                             printf("erreur pendant le chargement de la 
partie\n");
                         }
                         else
                         {
+                            PublicGame *game = new PublicGame(*tmpGame);
                             switch (game->getMode())
                                 {
-                                case Game::kTRAINING:
-                                    loop_training((Training&)*game);
+                                case PublicGame::kTRAINING:
+                                    loop_training(*game);
                                     break;
-                                case Game::kFREEGAME:
-                                    loop_freegame((FreeGame&)*game);
+                                case PublicGame::kFREEGAME:
+                                    loop_freegame(*game);
                                     break;
-                                case Game::kDUPLICATE:
-                                    loop_duplicate((Duplicate&)*game);
+                                case PublicGame::kDUPLICATE:
+                                    loop_duplicate(*game);
                                     break;
                                 }
+                            //GameFactory::Instance()->releaseGame(*game);
+                            delete game;
                         }
-                        GameFactory::Instance()->releaseGame(*game);
                     }
                     break;
                 case L'e':
                 {
                     // New training game
-                    Training *game = 
GameFactory::Instance()->createTraining(iDic);
+                    Training *tmpGame = 
GameFactory::Instance()->createTraining(iDic);
+                    PublicGame *game = new PublicGame(*tmpGame);
                     game->start();
                     loop_training(*game);
-                    GameFactory::Instance()->releaseGame(*game);
+                    //GameFactory::Instance()->releaseGame(*game);
+                    delete game;
                     break;
                 }
                 case L'd':
@@ -1042,7 +1053,8 @@
                         help();
                         break;
                     }
-                    Duplicate *game = 
GameFactory::Instance()->createDuplicate(iDic);
+                    Duplicate *tmpGame = 
GameFactory::Instance()->createDuplicate(iDic);
+                    PublicGame *game = new PublicGame(*tmpGame);
                     for (i = 0; i < _wtoi(token); i++)
                         game->addPlayer(new HumanPlayer);
                     token = next_token_digit(NULL, delim, &state);
@@ -1055,7 +1067,8 @@
                         game->addPlayer(new AIPercent(1));
                     game->start();
                     loop_duplicate(*game);
-                    GameFactory::Instance()->releaseGame(*game);
+                    //GameFactory::Instance()->releaseGame(*game);
+                    delete game;
                     break;
                 }
                 case L'l':
@@ -1068,7 +1081,8 @@
                         help();
                         break;
                     }
-                    FreeGame *game = 
GameFactory::Instance()->createFreeGame(iDic);
+                    FreeGame *tmpGame = 
GameFactory::Instance()->createFreeGame(iDic);
+                    PublicGame *game = new PublicGame(*tmpGame);
                     for (i = 0; i < _wtoi(token); i++)
                         game->addPlayer(new HumanPlayer);
                     token = next_token_digit(NULL, delim, &state);
@@ -1081,29 +1095,34 @@
                         game->addPlayer(new AIPercent(1));
                     game->start();
                     loop_freegame(*game);
-                    GameFactory::Instance()->releaseGame(*game);
+                    //GameFactory::Instance()->releaseGame(*game);
+                    delete game;
                     break;
                 }
                 case L'D':
                 {
                     // New duplicate game
-                    Duplicate *game = 
GameFactory::Instance()->createDuplicate(iDic);
+                    Duplicate *tmpGame = 
GameFactory::Instance()->createDuplicate(iDic);
+                    PublicGame *game = new PublicGame(*tmpGame);
                     game->addPlayer(new HumanPlayer);
                     game->addPlayer(new AIPercent(1));
                     game->start();
                     loop_duplicate(*game);
-                    GameFactory::Instance()->releaseGame(*game);
+                    //GameFactory::Instance()->releaseGame(*game);
+                    delete game;
                     break;
                 }
                 case L'L':
                 {
                     // New free game
-                    FreeGame *game = 
GameFactory::Instance()->createFreeGame(iDic);
+                    FreeGame *tmpGame = 
GameFactory::Instance()->createFreeGame(iDic);
+                    PublicGame *game = new PublicGame(*tmpGame);
                     game->addPlayer(new HumanPlayer);
                     game->addPlayer(new AIPercent(1));
                     game->start();
                     loop_freegame(*game);
-                    GameFactory::Instance()->releaseGame(*game);
+                    //GameFactory::Instance()->releaseGame(*game);
+                    delete game;
                     break;
                 }
                 case L'x':

Index: utils/game_io.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/game_io.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- utils/game_io.cpp   22 Nov 2008 13:09:32 -0000      1.14
+++ utils/game_io.cpp   30 Nov 2008 20:53:46 -0000      1.15
@@ -26,8 +26,10 @@
 
 #include <dic.h>
 #include "game_io.h"
-#include "game.h"
-#include "training.h"
+#include "public_game.h"
+#include "bag.h"
+#include "board.h"
+#include "results.h"
 #include "player.h"
 #include "encoding.h"
 
@@ -35,7 +37,7 @@
 
 #define __UNUSED__ __attribute__((unused))
 
-void GameIO::printBoard(ostream &out, const Game &iGame)
+void GameIO::printBoard(ostream &out, const PublicGame &iGame)
 {
     int row, col;
 
@@ -59,7 +61,7 @@
 }
 
 /* this mode is used for regression tests */
-void GameIO::printBoardDebug(ostream &out, const Game &iGame)
+void GameIO::printBoardDebug(ostream &out, const PublicGame &iGame)
 {
     int row, col;
 
@@ -85,7 +87,7 @@
     }
 }
 
-void GameIO::printBoardJoker(ostream &out, const Game &iGame)
+void GameIO::printBoardJoker(ostream &out, const PublicGame &iGame)
 {
     int row,col;
 
@@ -112,7 +114,7 @@
 }
 
 
-void GameIO::printBoardMultipliers(ostream &out, const Game &iGame)
+void GameIO::printBoardMultipliers(ostream &out, const PublicGame &iGame)
 {
     int row, col;
 
@@ -147,7 +149,7 @@
 }
 
 
-void GameIO::printBoardMultipliers2(ostream &out, const Game &iGame)
+void GameIO::printBoardMultipliers2(ostream &out, const PublicGame &iGame)
 {
     int row, col;
 
@@ -178,7 +180,7 @@
 }
 
 
-void GameIO::printNonPlayed(ostream &out, const Game &iGame)
+void GameIO::printNonPlayed(ostream &out, const PublicGame &iGame)
 {
     const Bag &bag = iGame.getBag();
     BOOST_FOREACH(const Tile &tile, iGame.getDic().getAllTiles())
@@ -197,15 +199,15 @@
 }
 
 
-void GameIO::printPlayedRack(ostream &out, const Game &iGame, int __UNUSED__ n)
+void GameIO::printPlayedRack(ostream &out, const PublicGame &iGame, int 
__UNUSED__ n)
 {
     out << 
convertToMb(iGame.getCurrentPlayer().getCurrentRack().toString(PlayedRack::RACK_SIMPLE))
 << endl;
 }
 
 
-void GameIO::printAllRacks(ostream &out, const Game &iGame)
+void GameIO::printAllRacks(ostream &out, const PublicGame &iGame)
 {
-    for (unsigned int j = 0; j < iGame.getNPlayers(); j++)
+    for (unsigned int j = 0; j < iGame.getNbPlayers(); j++)
     {
         out << "Joueur " << j << ": ";
         out << 
convertToMb(iGame.getPlayer(j).getCurrentRack().toString(PlayedRack::RACK_SIMPLE))
 << endl;
@@ -213,11 +215,10 @@
 }
 
 
-static void searchResultLine(ostream &out, const Training &iGame, int num)
+static void searchResultLine(ostream &out, const Results &iResults, int num)
 {
-    const Results &res = iGame.getResults();
-    Round r = res.get(num);
-    wstring word = r.getWord();
+    const Round &r = iResults.get(num);
+    const wstring &word = r.getWord();
     if (word.size() == 0)
         return;
     out << convertToMb(word) << string(16 - word.size(), ' ')
@@ -227,27 +228,26 @@
 }
 
 
-void GameIO::printSearchResults(ostream &out, const Training &iGame, int num)
+void GameIO::printSearchResults(ostream &out, const Results &iResults, int num)
 {
-    int size = (int) iGame.getResults().size();
-    for (int i = 0; i < num && i < size; i++)
+    for (int i = 0; i < num && i < (int)iResults.size(); i++)
     {
         out << setw(3) << i + 1 << ": ";
-        searchResultLine(out, iGame, i);
+        searchResultLine(out, iResults, i);
         out << endl;
     }
 }
 
 
-void GameIO::printPoints(ostream &out, const Game &iGame)
+void GameIO::printPoints(ostream &out, const PublicGame &iGame)
 {
     out << iGame.getPlayer(0).getPoints() << endl;
 }
 
 
-void GameIO::printAllPoints(ostream &out, const Game &iGame)
+void GameIO::printAllPoints(ostream &out, const PublicGame &iGame)
 {
-    for (unsigned int i = 0; i < iGame.getNPlayers(); i++)
+    for (unsigned int i = 0; i < iGame.getNbPlayers(); i++)
     {
         out << "Joueur " << i << ": "
             << setw(4) << iGame.getPlayer(i).getPoints() << endl;
@@ -255,24 +255,24 @@
 }
 
 
-void GameIO::printGameDebug(ostream &out, const Game &iGame)
+void GameIO::printGameDebug(ostream &out, const PublicGame &iGame)
 {
-    out << "Game:: joueur en cours " << iGame.currPlayer() << " sur " << 
iGame.getNPlayers() << endl;
+    out << "Game:: joueur en cours " << iGame.getCurrentPlayer().getId()
+        << " sur " << iGame.getNbPlayers() << endl;
     out << "Game:: mode " << iGame.getModeAsString() << endl;
     out << "Game:: variante ";
     switch (iGame.getVariant())
     {
-        case Game::kNONE:
+        case PublicGame::kNONE:
             out << "aucune" << endl;
             break;
-        case Game::kJOKER:
+        case PublicGame::kJOKER:
             out << "joker" << endl;
             break;
         default:
             out << "inconnu" << endl;
             break;
     }
-    out << "Game:: rack size " << iGame.RACK_SIZE << endl;
     out << "Game:: history --" << endl;
     out << convertToMb(iGame.getHistory().toString());
     out << "--" << endl;

Index: utils/game_io.h
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/game_io.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- utils/game_io.h     23 Dec 2006 13:57:08 -0000      1.5
+++ utils/game_io.h     30 Nov 2008 20:53:46 -0000      1.6
@@ -23,8 +23,8 @@
 
 #include <iostream>
 
-class Game;
-class Training;
+class PublicGame;
+class Results;
 
 using std::ostream;
 
@@ -40,20 +40,20 @@
 class GameIO
 {
 public:
-    static void printBoard(ostream &out, const Game &iGame);
-    static void printBoardDebug(ostream &out, const Game &iGame);
-    static void printBoardJoker(ostream &out, const Game &iGame);
-    static void printBoardMultipliers(ostream &out, const Game &iGame);
-    static void printBoardMultipliers2(ostream &out, const Game &iGame);
-
-    static void printNonPlayed(ostream &out, const Game &iGame);
-    static void printPlayedRack(ostream &out, const Game &iGame, int n);
-    static void printAllRacks(ostream &out, const Game &iGame);
-    static void printSearchResults(ostream &out, const Training &iGame, int);
-    static void printPoints(ostream &out, const Game &iGame);
-    static void printAllPoints(ostream &out, const Game &iGame);
+    static void printBoard(ostream &out, const PublicGame &iGame);
+    static void printBoardDebug(ostream &out, const PublicGame &iGame);
+    static void printBoardJoker(ostream &out, const PublicGame &iGame);
+    static void printBoardMultipliers(ostream &out, const PublicGame &iGame);
+    static void printBoardMultipliers2(ostream &out, const PublicGame &iGame);
+
+    static void printNonPlayed(ostream &out, const PublicGame &iGame);
+    static void printPlayedRack(ostream &out, const PublicGame &iGame, int n);
+    static void printAllRacks(ostream &out, const PublicGame &iGame);
+    static void printSearchResults(ostream &out, const Results &iResults, int);
+    static void printPoints(ostream &out, const PublicGame &iGame);
+    static void printAllPoints(ostream &out, const PublicGame &iGame);
 
-    static void printGameDebug(ostream &out, const Game &iGame);
+    static void printGameDebug(ostream &out, const PublicGame &iGame);
 
 private:
     /// This class is a toolbox, and should not be instanciated

Index: utils/ncurses.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/ncurses.cpp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- utils/ncurses.cpp   30 Nov 2008 20:51:42 -0000      1.29
+++ utils/ncurses.cpp   30 Nov 2008 20:53:46 -0000      1.30
@@ -36,9 +36,9 @@
 #include "ncurses.h"
 #include "dic.h"
 #include "game_factory.h"
-#include "training.h"
-#include "duplicate.h"
-#include "freegame.h"
+#include "game.h"
+#include "public_game.h"
+#include "results.h"
 #include "player.h"
 #include "history.h"
 #include "turn.h"
@@ -175,7 +175,7 @@
 }
 
 
-CursesIntf::CursesIntf(WINDOW *win, Game& iGame)
+CursesIntf::CursesIntf(WINDOW *win, PublicGame& iGame)
     : m_win(win), m_game(&iGame), m_state(DEFAULT), m_dying(false),
     m_box(win, 0, 0, 0, 0), m_showDots(false)
 {
@@ -184,7 +184,8 @@
 
 CursesIntf::~CursesIntf()
 {
-    GameFactory::Instance()->releaseGame(*m_game);
+    //GameFactory::Instance()->releaseGame(*m_game);
+    delete m_game;
     GameFactory::Destroy();
 }
 
@@ -273,56 +274,57 @@
 {
     // Compute the longest player name
     size_t longest = 0;
-    for (unsigned int i = 0; i < m_game->getNPlayers(); i++)
+    for (unsigned int i = 0; i < m_game->getNbPlayers(); i++)
     {
         longest = std::max(longest, m_game->getPlayer(i).getName().size());
     }
 
-    Box box(win, y, x, m_game->getNPlayers() + 2, 25);
+    Box box(win, y, x, m_game->getNbPlayers() + 2, 25);
     box.draw(_("Scores"));
     // Magic formula to truncate too long names
     unsigned int maxForScores =
         std::min(longest,
                  box.getWidth() - strlen(_("%s: %d")) - 1);
-    for (unsigned int i = 0; i < m_game->getNPlayers(); i++)
+    unsigned int currId = m_game->getCurrentPlayer().getId();
+    for (unsigned int i = 0; i < m_game->getNbPlayers(); i++)
     {
-        if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
+        if (m_game->getMode() != PublicGame::kTRAINING && i == currId)
             attron(A_BOLD);
         mvwprintw(win, y + i + 1, x + 2, _("%s: %d"),
                   truncOrPad(convertToMb(m_game->getPlayer(i).getName()),
                              maxForScores).c_str(),
                   m_game->getPlayer(i).getPoints());
-        if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
+        if (m_game->getMode() != PublicGame::kTRAINING && i == currId)
             attroff(A_BOLD);
     }
 
     // Distance between the 2 boxes
-    unsigned int yOff = m_game->getNPlayers() + 3;
+    unsigned int yOff = m_game->getNbPlayers() + 3;
 
-    Box box2(win, y + yOff, x, m_game->getNPlayers() + 2, 25);
+    Box box2(win, y + yOff, x, m_game->getNbPlayers() + 2, 25);
     box2.draw(_("Racks"));
     // Magic formula to truncate too long names
     unsigned int maxForRacks =
         std::min(longest,
                  box.getWidth() - strlen(_("%s: %ls")) - 4);
-    for (unsigned int i = 0; i < m_game->getNPlayers(); i++)
+    for (unsigned int i = 0; i < m_game->getNbPlayers(); i++)
     {
-        if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
+        if (m_game->getMode() != PublicGame::kTRAINING && i == currId)
             attron(A_BOLD);
         wstring rack = 
m_game->getPlayer(i).getCurrentRack().toString(PlayedRack::RACK_SIMPLE);
         mvwprintw(win, y + yOff + i + 1, x + 2, _("%s: %ls"),
                   truncOrPad(convertToMb(m_game->getPlayer(i).getName()),
                              maxForRacks).c_str(),
                   rack.c_str());
-        if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
+        if (m_game->getMode() != PublicGame::kTRAINING && i == currId)
             attroff(A_BOLD);
         // Force to refresh the whole rack
         whline(win, ' ', 7 - rack.size());
     }
 
     // Display a message when the search is complete
-    if (m_game->getMode() == Game::kTRAINING &&
-        static_cast<Training*>(m_game)->getResults().size())
+    if (m_game->getMode() == PublicGame::kTRAINING &&
+        m_game->trainingGetResults().size())
     {
         mvwprintw(win, y + 2*yOff - 1, x + 2, _("Search complete"));
     }
@@ -333,15 +335,14 @@
 
 void CursesIntf::drawResults(Box &ioBox) const
 {
-    if (m_game->getMode() != Game::kTRAINING)
+    if (m_game->getMode() != PublicGame::kTRAINING)
         return;
-    Training *tr_game = static_cast<Training*>(m_game);
 
     ioBox.draw(_("Search results"));
-    ioBox.setDataSize(tr_game->getResults().size());
+    const Results& res = m_game->trainingGetResults();
+    ioBox.setDataSize(res.size());
 
     unsigned int i;
-    const Results& res = tr_game->getResults();
     int x = ioBox.getLeft();
     for (i = (unsigned int)ioBox.getFirstLine();
          i < res.size() && i < (unsigned int)ioBox.getLastLine(); i++)
@@ -564,7 +565,7 @@
     if (readString(win, y + 1, x + xOff, 15, word) &&
         readString(win, y + 2, x + xOff, 3, coord))
     {
-        int res = m_game->play(coord, word);
+        int res = m_game->play(word, coord);
         if (res)
         {
             drawStatus(win, _("Incorrect or misplaced word"));
@@ -616,7 +617,7 @@
         }
         else
         {
-            m_game->save(fout, Game::FILE_FORMAT_ADVANCED);
+            m_game->save(fout, PublicGame::kFILE_FORMAT_ADVANCED);
             fout.close();
             snprintf(s, 100, _("Game saved in '%ls'"), filename.c_str());
             drawStatus(win, s, false);
@@ -645,7 +646,7 @@
         }
         else
         {
-            Game *loaded = Game::load(fin, m_game->getDic());
+            PublicGame *loaded = PublicGame::load(fin, m_game->getDic());
             if (loaded == NULL)
             {
                 snprintf(s, 100, _("Invalid saved game"));
@@ -654,7 +655,8 @@
             else
             {
                 snprintf(s, 100, _("Game loaded"));
-                GameFactory::Instance()->releaseGame(*m_game);
+                //GameFactory::Instance()->releaseGame(*m_game);
+                delete m_game;
                 m_game = loaded;
                 drawStatus(win, s, false);
             }
@@ -665,7 +667,7 @@
 }
 
 
-void CursesIntf::passTurn(WINDOW *win, int y, int x, FreeGame &iGame)
+void CursesIntf::passTurn(WINDOW *win, int y, int x, PublicGame &iGame)
 {
     Box box(win, y, x, 4, 32);
     box.draw(_("Pass your turn"));
@@ -675,7 +677,7 @@
     wstring letters;
     if (readString(win, y + 2, x + 2, 7, letters))
     {
-        int res = iGame.pass(letters);
+        int res = iGame.freeGamePass(letters);
         if (res)
         {
             drawStatus(win, _("Cannot pass the turn"));
@@ -685,7 +687,7 @@
 }
 
 
-void CursesIntf::setRack(WINDOW *win, int y, int x, Training &iGame)
+void CursesIntf::setRack(WINDOW *win, int y, int x, PublicGame &iGame)
 {
     Box box(win, y, x, 4, 32);
     box.draw(_("Set rack"));
@@ -695,7 +697,7 @@
     wstring letters;
     if (readString(win, y + 2, x + 2, 7, letters, kJOKER))
     {
-        int res = iGame.setRackManual(false, letters);
+        int res = iGame.trainingSetRackManual(false, letters);
         if (res)
         {
             drawStatus(win, _("Cannot take these letters from the bag"));
@@ -830,7 +832,7 @@
 }
 
 
-int CursesIntf::handleKeyForGame(int iKey, Training &iGame)
+int CursesIntf::handleKeyForTraining(int iKey, PublicGame &iGame)
 {
     switch (iKey)
     {
@@ -840,7 +842,7 @@
                 setState(DEFAULT);
                 redraw(m_win);
             }
-            iGame.setRackRandom(false, Game::RACK_ALL);
+            iGame.trainingSetRackRandom(false, PublicGame::kRACK_ALL);
             return 1;
 
         case '+':
@@ -849,7 +851,7 @@
                 setState(DEFAULT);
                 redraw(m_win);
             }
-            iGame.setRackRandom(false, Game::RACK_NEW);
+            iGame.trainingSetRackRandom(false, PublicGame::kRACK_NEW);
             return 1;
 
         case 't':
@@ -864,7 +866,7 @@
 
         case 'c':
         case 'C':
-            iGame.search();
+            iGame.trainingSearch();
             return 1;
 
         default:
@@ -873,7 +875,7 @@
 }
 
 
-int CursesIntf::handleKeyForGame(int iKey, Duplicate &iGame)
+int CursesIntf::handleKeyForDuplicate(int iKey, PublicGame &iGame)
 {
     switch (iKey)
     {
@@ -882,7 +884,7 @@
         {
             // Get the human players who have not played yet
             set<unsigned int> humans;
-            for (unsigned int id = 0; id < iGame.getNPlayers(); ++id)
+            for (unsigned int id = 0; id < iGame.getNbPlayers(); ++id)
             {
                 if (iGame.getPlayer(id).isHuman() && !iGame.hasPlayed(id))
                     humans.insert(id);
@@ -891,9 +893,9 @@
             // Try to find a player with a bigger ID
             set<unsigned int>::const_iterator it = humans.upper_bound(currId);
             if (it != humans.end())
-                iGame.setPlayer(*it);
+                iGame.duplicateSetPlayer(*it);
             else
-                iGame.setPlayer(*humans.begin());
+                iGame.duplicateSetPlayer(*humans.begin());
             return 1;
         }
 
@@ -903,7 +905,7 @@
 }
 
 
-int CursesIntf::handleKeyForGame(int iKey, FreeGame &iGame)
+int CursesIntf::handleKeyForFreeGame(int iKey, PublicGame &iGame)
 {
     switch (iKey)
     {
@@ -926,17 +928,17 @@
 
     // Handle game-specific keys
     int res;
-    if (m_game->getMode() == Game::kTRAINING)
+    if (m_game->getMode() == PublicGame::kTRAINING)
     {
-        res = handleKeyForGame(iKey, (Training&)*m_game);
+        res = handleKeyForTraining(iKey, *m_game);
     }
-    else if (m_game->getMode() == Game::kDUPLICATE)
+    else if (m_game->getMode() == PublicGame::kDUPLICATE)
     {
-        res = handleKeyForGame(iKey, (Duplicate&)*m_game);
+        res = handleKeyForDuplicate(iKey, *m_game);
     }
     else
     {
-        res = handleKeyForGame(iKey, (FreeGame&)*m_game);
+        res = handleKeyForFreeGame(iKey, *m_game);
     }
     if (res != 2)
         return res;
@@ -988,7 +990,7 @@
         // Toggle results (training mode only)
         case 'r':
         case 'R':
-            if (m_game->getMode() != Game::kTRAINING)
+            if (m_game->getMode() != PublicGame::kTRAINING)
             {
                 beep();
                 return 0;
@@ -1106,14 +1108,14 @@
     // Title
     attron(A_REVERSE);
     string mode;
-    if (m_game->getMode() == Game::kTRAINING)
+    if (m_game->getMode() == PublicGame::kTRAINING)
         mode = _("Training mode");
-    else if (m_game->getMode() == Game::kFREEGAME)
+    else if (m_game->getMode() == PublicGame::kFREEGAME)
         mode = _("Free game mode");
-    else if (m_game->getMode() == Game::kDUPLICATE)
+    else if (m_game->getMode() == PublicGame::kDUPLICATE)
         mode = _("Duplicate mode");
     string variant = "";
-    if (m_game->getVariant() == Game::kJOKER)
+    if (m_game->getVariant() == PublicGame::kJOKER)
         variant = string(" - ") + _("Joker game");
     string title = "Eliot (" + mode + variant + ") " + _("[h for help]");
 
@@ -1153,12 +1155,13 @@
 
     srand(time(NULL));
 
-    Game *game = GameFactory::Instance()->createFromCmdLine(argc, argv);
-    if (game == NULL)
+    Game *realGame = GameFactory::Instance()->createFromCmdLine(argc, argv);
+    if (realGame == NULL)
     {
         GameFactory::Destroy();
         return 1;
     }
+    PublicGame *game = new PublicGame(*realGame);
 
     game->start();
 

Index: utils/ncurses.h
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/ncurses.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- utils/ncurses.h     8 Jan 2008 13:52:42 -0000       1.7
+++ utils/ncurses.h     30 Nov 2008 20:53:46 -0000      1.8
@@ -23,10 +23,7 @@
 #include <ncursesw/curses.h>
 #include <string>
 
-class Game;
-class Training;
-class Duplicate;
-class FreeGame;
+class PublicGame;
 
 using std::string;
 using std::wstring;
@@ -104,7 +101,7 @@
     // Pre-requisite: the given Game object MUST have been allocated with new
     // (in particular: not on the stack)
     // This class also takes the responsability of destroying the Game object.
-    CursesIntf(WINDOW *win, Game& iGame);
+    CursesIntf(WINDOW *win, PublicGame& iGame);
     ~CursesIntf();
     bool isDying() const { return m_dying; }
     int handleKey(int iKey);
@@ -142,8 +139,8 @@
     void checkWord(WINDOW *win, int y, int x);
     void saveGame(WINDOW *win, int y, int x);
     void loadGame(WINDOW *win, int y, int x);
-    void passTurn(WINDOW *win, int y, int x, FreeGame &iGame);
-    void setRack(WINDOW *win, int y, int x, Training &iGame);
+    void passTurn(WINDOW *win, int y, int x, PublicGame &iGame);
+    void setRack(WINDOW *win, int y, int x, PublicGame &iGame);
 
     // Get a string from the user, with a maximum length
     // The string is validated if the user presses Enter (return value: true)
@@ -158,17 +155,17 @@
     static const unsigned int kFILENAME = 1 << 1;
 
     // Handle the key in Training mode
-    int handleKeyForGame(int iKey, Training &iGame);
+    int handleKeyForTraining(int iKey, PublicGame &iGame);
     // Handle the key in Duplicate mode
-    int handleKeyForGame(int iKey, Duplicate &iGame);
+    int handleKeyForDuplicate(int iKey, PublicGame &iGame);
     // Handle the key in FreeGame mode
-    int handleKeyForGame(int iKey, FreeGame &iGame);
+    int handleKeyForFreeGame(int iKey, PublicGame &iGame);
 
     // Main window for drawing
     WINDOW *m_win;
     // Current game
-    // Invariant: the pointer will always point to a valid Game object
-    Game *m_game;
+    // Invariant: the pointer will always point to a valid PublicGame object
+    PublicGame *m_game;
     // Interface state
     State m_state;
     // True when the user requested to quit

Index: game/public_game.cpp
===================================================================
RCS file: game/public_game.cpp
diff -N game/public_game.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/public_game.cpp        30 Nov 2008 20:53:44 -0000      1.1
@@ -0,0 +1,329 @@
+/*******************************************************************
+ * Eliot
+ * Copyright (C) 2008 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * 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 "public_game.h"
+#include "game.h"
+#include "training.h"
+#include "duplicate.h"
+#include "freegame.h"
+#include "game_exception.h"
+
+
+PublicGame::PublicGame(Game &iGame)
+    : m_game(iGame)
+{
+}
+
+
+PublicGame::~PublicGame()
+{
+    delete &m_game;
+}
+
+
+PublicGame::GameMode PublicGame::getMode() const
+{
+    if (dynamic_cast<Duplicate*>(&m_game))
+        return kDUPLICATE;
+    else if (dynamic_cast<FreeGame*>(&m_game))
+        return kFREEGAME;
+    else
+        return kTRAINING;
+}
+
+
+string PublicGame::getModeAsString() const
+{
+    return m_game.getModeAsString();
+}
+
+
+void PublicGame::setVariant(GameVariant iVariant)
+{
+    if (iVariant == kJOKER)
+        m_game.setVariant(Game::kJOKER);
+    else
+        m_game.setVariant(Game::kNONE);
+}
+
+
+PublicGame::GameVariant PublicGame::getVariant() const
+{
+    if (m_game.getVariant() == Game::kJOKER)
+        return kJOKER;
+    else
+        return kNONE;
+}
+
+
+const Dictionary & PublicGame::getDic() const
+{
+    return m_game.getDic();
+}
+
+
+const Board& PublicGame::getBoard() const
+{
+    return m_game.getBoard();
+}
+
+
+const Bag& PublicGame::getBag() const
+{
+    return m_game.getBag();
+}
+
+
+const History& PublicGame::getHistory() const
+{
+    return m_game.getHistory();
+}
+
+
+void PublicGame::addPlayer(Player *iPlayer)
+{
+    m_game.addPlayer(iPlayer);
+}
+
+
+const Player& PublicGame::getPlayer(unsigned int iNum) const
+{
+    return m_game.getPlayer(iNum);
+}
+
+
+const Player& PublicGame::getCurrentPlayer() const
+{
+    return m_game.getCurrentPlayer();
+}
+
+
+unsigned int PublicGame::getNbPlayers() const
+{
+    return m_game.getNPlayers();
+}
+
+
+unsigned int PublicGame::getNbHumanPlayers() const
+{
+    return m_game.getNHumanPlayers();
+}
+
+
+bool PublicGame::hasPlayed(unsigned int player) const
+{
+    return m_game.hasPlayed(player);
+}
+
+void PublicGame::start()
+{
+    m_game.start();
+}
+
+
+int PublicGame::play(const wstring &iWord, const wstring &iCoord)
+{
+    return m_game.play(iCoord, iWord);
+}
+
+
+void PublicGame::shuffleRack()
+{
+    m_game.shuffleRack();
+}
+
+/***************************/
+
+static Training & getTrainingGame(Game &iGame)
+{
+    Training *trGame = dynamic_cast<Training *>(&iGame);
+    if (trGame == NULL)
+    {
+        throw GameException("Invalid game type");
+    }
+    return *trGame;
+}
+
+void PublicGame::trainingSearch()
+{
+    getTrainingGame(m_game).search();
+}
+
+
+const Results& PublicGame::trainingGetResults() const
+{
+    return getTrainingGame(m_game).getResults();
+}
+
+
+int PublicGame::trainingPlayResult(unsigned int iResultIndex)
+{
+    return getTrainingGame(m_game).playResult(iResultIndex);
+}
+
+
+void PublicGame::trainingSetRackRandom(bool iCheck, RackMode iRackMode)
+{
+    if (iRackMode == kRACK_NEW)
+        getTrainingGame(m_game).setRackRandom(iCheck, Game::RACK_NEW);
+    else
+        getTrainingGame(m_game).setRackRandom(iCheck, Game::RACK_ALL);
+}
+
+
+int PublicGame::trainingSetRackManual(bool iCheck, const wstring &iLetters)
+{
+    return getTrainingGame(m_game).setRackManual(iCheck, iLetters);
+}
+
+
+void PublicGame::trainingTestPlay(unsigned int iResultIndex)
+{
+    getTrainingGame(m_game).testPlay(iResultIndex);
+}
+
+
+void PublicGame::trainingRemoveTestPlay()
+{
+    getTrainingGame(m_game).removeTestPlay();
+}
+
+
+wstring PublicGame::trainingGetTestPlayWord() const
+{
+    return getTrainingGame(m_game).getTestPlayWord();
+}
+
+/***************************/
+
+static Duplicate & getDuplicateGame(Game &iGame)
+{
+    Duplicate *dupGame = dynamic_cast<Duplicate *>(&iGame);
+    if (dupGame == NULL)
+    {
+        throw GameException("Invalid game type");
+    }
+    return *dupGame;
+}
+
+
+int PublicGame::duplicateSetPlayer(unsigned int p)
+{
+    return getDuplicateGame(m_game).setPlayer(p);
+}
+
+/***************************/
+
+static FreeGame & getFreeGameGame(Game &iGame)
+{
+    FreeGame *frGame = dynamic_cast<FreeGame *>(&iGame);
+    if (frGame == NULL)
+    {
+        throw GameException("Invalid game type");
+    }
+    return *frGame;
+}
+
+
+int PublicGame::freeGamePass(const wstring &iToChange)
+{
+    return getFreeGameGame(m_game).pass(iToChange);
+}
+
+/***************************/
+
+PublicGame *PublicGame::load(FILE *fin, const Dictionary &iDic)
+{
+    Game *game = Game::load(fin, iDic);
+    if (game == NULL)
+        return NULL;
+    return new PublicGame(*game);
+}
+
+
+void PublicGame::save(ostream &out, GameFileFormat format) const
+{
+    if (format == kFILE_FORMAT_ADVANCED)
+        m_game.save(out, Game::FILE_FORMAT_ADVANCED);
+    else
+        m_game.save(out, Game::FILE_FORMAT_STANDARD);
+}
+
+/***************************/
+
+unsigned int PublicGame::getCurrTurn() const
+{
+    return m_game.getNavigation().getCurrTurn();
+}
+
+
+unsigned int PublicGame::getNbTurns() const
+{
+    return m_game.getNavigation().getNbTurns();
+}
+
+
+bool PublicGame::isFirstTurn() const
+{
+    return m_game.getNavigation().isFirstTurn();
+}
+
+
+bool PublicGame::isLastTurn() const
+{
+    return m_game.getNavigation().isLastTurn();
+}
+
+
+void PublicGame::firstTurn()
+{
+    m_game.accessNavigation().firstTurn();
+}
+
+
+void PublicGame::prevTurn()
+{
+    m_game.accessNavigation().prevTurn();
+}
+
+
+void PublicGame::nextTurn()
+{
+    m_game.accessNavigation().nextTurn();
+}
+
+
+void PublicGame::lastTurn()
+{
+    m_game.accessNavigation().lastTurn();
+}
+
+
+void PublicGame::clearFuture()
+{
+    m_game.accessNavigation().clearFuture();
+}
+
+
+void PublicGame::printTurns() const
+{
+    m_game.getNavigation().print();
+}
+

Index: game/public_game.h
===================================================================
RCS file: game/public_game.h
diff -N game/public_game.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/public_game.h  30 Nov 2008 20:53:44 -0000      1.1
@@ -0,0 +1,310 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2008 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * 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 _PUBLIC_GAME_H_
+#define _PUBLIC_GAME_H_
+
+#include <string>
+
+class Game;
+#if 0
+#include <vector>
+#include <iostream>
+#include "bag.h"
+#include "board.h"
+#include "history.h"
+#include "navigation.h"
+#include "command.h"
+#endif
+
+class Dictionary;
+class Bag;
+class Board;
+class History;
+class Player;
+class Navigation;
+class Results;
+
+using namespace std;
+
+
+/**
+ * This class is a wrapper around a Game object (Façade design pattern).
+ *
+ * Game objects are not meant for direct use outside of the game library,
+ * because they expose too many internal members.
+ * A PublicGame provides a cleaner interface to implement a UI, avoiding
+ * the need to know too much about the Game internals.
+ */
+class PublicGame
+{
+public:
+    /**
+     * Build a PublicGame from a Game object
+     * The PublicGame takes the ownership of the Game object.
+     */
+    // XXX: should be private?
+    PublicGame(Game &iGame);
+    ~PublicGame();
+
+    /***************
+     * Game type
+     ***************/
+
+    // XXX: should not be in Game?
+    /// Game mode: each one of these modes is implemented in an inherited class
+    enum GameMode
+    {
+        kTRAINING,
+        kFREEGAME,
+        kDUPLICATE
+    };
+    GameMode getMode() const;
+    string getModeAsString() const;
+
+    /// Game variant: it slightly modifies the rules of the game
+    enum GameVariant
+    {
+        kNONE,      // Normal game rules
+        kJOKER      // Joker game
+    };
+
+    /**
+     * Accessors for the variant of the game.
+     * The variant can be changed during a game without any problem
+     * (though it seems rather useless...)
+     */
+    void setVariant(GameVariant iVariant);
+    GameVariant getVariant() const;
+
+    /***************
+     * Various getters
+     ***************/
+
+    /**
+     * Get the dictionary associated with the game.
+     * You should never create a new dictionary object while a Game
+     * object still exists
+     */
+    const Dictionary & getDic() const;
+
+    /// Get the board
+    const Board& getBoard() const;
+    /// Get the bag
+    const Bag& getBag() const;
+
+    /// Get the history of the game */
+    const History& getHistory() const;
+
+    /***************
+     * Methods to access players.
+     ***************/
+
+    /**
+     * Add a player to the game.
+     * The Game object takes ownership of the given player
+     */
+    void addPlayer(Player *iPlayer);
+
+    const Player& getPlayer(unsigned int iNum) const;
+    const Player& getCurrentPlayer() const;
+    unsigned int getNbPlayers() const;
+    unsigned int getNbHumanPlayers() const;
+
+    /// Return true if the player has played for the current turn
+    // XXX: not very nice API, should be a player property...
+    bool hasPlayed(unsigned int player) const;
+
+    /***************
+     * Game handling
+     ***************/
+
+    /**
+     * Start the game.
+     * AI players are handled automatically, so if the game only has AI
+     * players, it will play until the end.
+     */
+    void start();
+
+    /**
+     * 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
+     *  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: word going out of the board
+     */
+    int play(const wstring &iWord, const wstring &iCoord);
+
+    /**
+     * Go back to turn iTurn.
+     * We must have: iTurn < getHistory().getSize()
+     * Possible return values:
+     *  0: everything went fine
+     *  1: iTurn is invalid
+     */
+    //int back(unsigned int iTurn);
+
+    /// Shuffle the rack of the current player
+    void shuffleRack();
+
+    /***************
+     * Training games
+     * These methods throw an exception if the current game is not in
+     * the Training mode.
+     ***************/
+
+    void trainingSearch();
+    const Results& trainingGetResults() const;
+    int trainingPlayResult(unsigned int iResultIndex);
+
+    enum RackMode
+    {
+        kRACK_NEW, // Only new tiles
+        kRACK_ALL  // All tiles
+    };
+
+    /**
+     * Complete (or reset) the rack randomly.
+     * @exception EndGameException if it is impossible to complete the rack
+     * for some reason...
+     */
+    void trainingSetRackRandom(bool iCheck, RackMode iRackMode);
+
+    int trainingSetRackManual(bool iCheck, const wstring &iLetters);
+
+    /// Place a temporary word on the board for preview purposes
+    void trainingTestPlay(unsigned int iResultIndex);
+    /// Remove the temporary word
+    void trainingRemoveTestPlay();
+    /// Get the temporary word
+    wstring trainingGetTestPlayWord() const;
+
+    /***************
+     * Duplicate games
+     * These methods throw an exception if the current game is not in
+     * the Duplicate mode.
+     ***************/
+
+    /**
+     * 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 duplicateSetPlayer(unsigned int p);
+
+    /***************
+     * FreeGame games
+     * These methods throw an exception if the current game is not in
+     * the FreeGame mode.
+     ***************/
+
+    /**
+     * 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 freeGamePass(const wstring &iToChange);
+
+    /***************
+     * Saved games handling
+     ***************/
+
+    /**
+     * Possible formats for the saved games
+     */
+    enum GameFileFormat
+    {
+        kFILE_FORMAT_STANDARD,
+        kFILE_FORMAT_ADVANCED
+    };
+
+    /**
+     * load() returns the loaded game, or NULL if there was a problem
+     * load() does need some more work to be robust enough to
+     * handle "hand written" files
+     */
+    static PublicGame * load(FILE *fin, const Dictionary &iDic);
+
+    /**
+     * Save a game to a file
+     * Standard format is used for training games so that it is compatible
+     * with previous versions of Eliot.
+     *
+     * Saving can be forced to advanced format for training games by
+     * setting the last parameter to kFILE_FORMAT_ADVANCED
+     */
+    void save(ostream &out, GameFileFormat format = kFILE_FORMAT_STANDARD) 
const;
+
+    /***************
+     * Navigation in the game history
+     ***************/
+
+    unsigned int getCurrTurn() const;
+    unsigned int getNbTurns() const;
+    bool isFirstTurn() const;
+    bool isLastTurn() const;
+
+    void firstTurn();
+    void prevTurn();
+    void nextTurn();
+    void lastTurn();
+
+    /**
+     * Get rid of the future turns of the game, the current turn
+     * becoming the last one.
+     */
+    void clearFuture();
+
+    /**
+     * Print the contents of the commands history, to ease debugging
+     */
+    void printTurns() const;
+
+private:
+    /// Wrapped game
+    Game &m_game;
+};
+
+#endif
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]