summaryrefslogtreecommitdiffstats
path: root/libksirtet/lib/mp_interface.h
diff options
context:
space:
mode:
Diffstat (limited to 'libksirtet/lib/mp_interface.h')
-rw-r--r--libksirtet/lib/mp_interface.h246
1 files changed, 246 insertions, 0 deletions
diff --git a/libksirtet/lib/mp_interface.h b/libksirtet/lib/mp_interface.h
new file mode 100644
index 00000000..ad925cba
--- /dev/null
+++ b/libksirtet/lib/mp_interface.h
@@ -0,0 +1,246 @@
+#ifndef MP_INTERFACE_H
+#define MP_INTERFACE_H
+
+#include <qwidget.h>
+#include <qvaluelist.h>
+#include <qptrlist.h>
+
+#include "mp_board.h"
+#include "mp_option.h"
+
+class QHBoxLayout;
+class Local;
+class ConnectionData;
+class RemoteHostData;
+class KeyData;
+class KeyCollection;
+class KKeyDialog;
+class KAction;
+
+struct ActionData {
+ const char *label, *name;
+ const char *slot, *slotRelease; // if slotRelease!=0
+ // : use keyPress/ReleaseEvent mecanism
+};
+
+/**
+ * This structure contains information about the game
+ * configuration.
+ */
+typedef struct {
+ /** The game version id used for identification (e.g. "4").
+ * You should change this id when the game is made incompatible
+ * with previous version. (changes in data for example).
+ */
+ const char *gameId;
+
+ /** Maximum number of local players. */
+ uint maxNbLocalPlayers;
+
+ /** Interval (in msec.) between data exchange. */
+ uint interval;
+
+ /** If there are built-in artificial intelligences that can play. */
+ bool AIAllowed;
+
+ /** Slot for player/AI additional configuration. These must be SLOTs which
+ * take an "int" as parameter. It must open a setting
+ * dialog for the corresponding local player/computer and save the
+ * new settings in the config file. It should probably create a group
+ * with the given number in its name.
+ * If such a pointer is set to 0 : it means there is no perticular
+ * setting.
+ */
+ const char *humanSettingSlot, *AISettingSlot;
+} MPGameInfo;
+
+/**
+ * The MPInterface class is useful for multiplayers game
+ * management. Each game is represented by a class you have inherited
+ * from the @ref MPBoard class.
+ *
+ * Multiplayers games can take place with several (humans or eventually
+ * AIs) players on the same computer (they use the same keyboard and have
+ * each a @ref MPBoard widget on the screen) or/and network players.
+ *
+ * This class is intended to do all the hard work of sending/receiving data
+ * between the players and to send the keyboard events to the right
+ * @ref MPBoard. So multiplayers game should be completely transparent
+ * from your point of view.
+ *
+ * Note : The data exchange is done in background with a timer calling at given
+ * intervals the read/write methods. Obviously this kind of things can be done
+ * easily with threads but I have no experience with thread programming
+ * and not all people have thread libraries and a thread-safe system.
+ */
+class MPInterface : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ /** Constructor which takes a MPGameInfo struct as parameter.
+ */
+ MPInterface(const MPGameInfo &gameInfo,
+ uint nbActions, const ActionData *data,
+ QWidget *parent = 0, const char *name = 0);
+ virtual ~MPInterface();
+
+ public slots:
+ /** Create a single player game for a human being.
+ * Call @ref stop if a game is already created. */
+ void singleHuman() { specialLocalGame(1, 0); }
+ /** Create a local game opposing two human beings.
+ * Call @ref stop if a game is already created. */
+ void humanVsHuman() { specialLocalGame(2, 0); }
+ /** Create a local game opposing a human with an AI.
+ * Call @ref stop if a game is already created. */
+ void humanVsComputer() { specialLocalGame(1, 1); }
+
+ /** Open a dialog to create a multiplayer game.
+ * Call @ref stop if a game is already created. */
+ void dialog();
+
+ public:
+ virtual void addKeys(KKeyDialog &);
+ void saveKeys();
+
+ /** Called when a new game is created. At this point
+ * the number of players is known. */
+ virtual void init() {}
+
+ /** Called just before a new game is created (called by
+ * singleHuman, humanVsHuman, humanVsComputer and dialog). */
+ virtual void stop() {}
+
+ /** Called when the start button of the netmeeting is pressed. */
+ virtual void start() {}
+
+ /**
+ * Set keys configuration for the given number of human players.
+ * The size of the array is the number of defined actions.
+ */
+ void setDefaultKeycodes(uint nbHumans, uint human, const int *keycodes);
+
+ /**
+ * @return the total number of players.
+ * (If called from client : return the number of local boards).
+ */
+ uint nbPlayers() const;
+
+ /**
+ * @return true if the interface is the server.
+ */
+ bool server() const { return _server; }
+
+ /** @return the player name.
+ Do not call from client !
+ */
+ QString playerName(uint i) const;
+
+ /**
+ * Create a new @ref MPBoard.
+ *
+ * @param i is the game index that goes from 0 to the number of
+ * local players : it can be used to retrieve configuration settings.
+ */
+ virtual MPBoard *newBoard(uint i) = 0;
+
+ /**
+ * This method must read data from each client with method
+ * @ref readingStream, do the needed treatement
+ * (for instance which players has lost, which data to be resent, ...) and
+ * then write the useful data to each client with method
+ * @ref writingStream.
+ *
+ * NB: this method is also called for single player games but
+ * you probably only want to check for game over condition (it depends
+ * on game implementation that you really return data to the board).
+ */
+ virtual void treatData() = 0;
+
+ /** @return the reading stream for board #i.
+ * Do not call from client !
+ */
+ QDataStream &readingStream(uint i) const;
+
+ /** @return the writing stream for board #i.
+ */
+ QDataStream &writingStream(uint i) const;
+
+ /**
+ * Read data sent from server to clients "MultiplayersInterface"
+ * (this data is not addressed to boards).
+ * These are meta data that are not directly used in game.
+ * It can be used to display "game over" infos for all
+ * local games.
+ * NB: the use of this method is optional.
+ */
+ virtual void dataFromServer(QDataStream &) {}
+
+ /** Used by the server to write meta data to clients.
+ * NB: the use of this method is optional.
+ * Do not call from client !
+ */
+ QDataStream &dataToClientsStream() const;
+
+ /** Write immediately data to clients and local boards.
+ * It is unlike the normal exchange which is driven
+ * by the timer of the server. Be aware of possible
+ * interactions.
+ */
+ void immediateWrite();
+
+ /**
+ * This method should be overload if an option widget is used in the
+ * the "netmeeting" dialog). By default a
+ * null pointer is returned and so no option widget is shown.
+ * The option widget must be inherited from the @ref MPOptionWidget class.
+ */
+ virtual MPOptionWidget *newOptionWidget() const { return 0; }
+
+ /** Called when a network error occurred or when a host gets disconnected.
+ * The default implementation displays a message and calls singleHumans()
+ * ie it stops the current game. By overloading this method, it is
+ * possible to continue the game at this point with the remaining players.
+ */
+ virtual void hostDisconnected(uint i, const QString &msg);
+
+ protected:
+ void paintEvent(QPaintEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+ private slots:
+ void enableKeys(bool enable);
+ void singleHumanSlot();
+
+ public:
+ class Data {
+ public:
+ Data() {}
+ MPBoard *ptr;
+ int humanIndex;
+ QString name;
+ };
+
+ private:
+ Local *internal;
+ const MPGameInfo gameInfo;
+ QValueList<Data> boards;
+ uint nbLocalHumans;
+ QHBoxLayout *hbl;
+ bool _server, disconnected;
+
+ KeyData *_keyData;
+ QMemArray<KeyCollection *> _keyCol;
+
+ void createServerGame(const QPtrList<RemoteHostData> &);
+ void createClientGame(const RemoteHostData &);
+ void createLocalGame(const ConnectionData &);
+ void specialLocalGame(uint nbHumans, uint nbComputers);
+
+ void clear();
+ void initKeys(uint nbHumans);
+};
+
+#endif // MP_INTERFACE_H