|
|
|
#ifndef MP_INTERFACE_H
|
|
|
|
#define MP_INTERFACE_H
|
|
|
|
|
|
|
|
#include <tqwidget.h>
|
|
|
|
#include <tqvaluelist.h>
|
|
|
|
#include <tqptrlist.h>
|
|
|
|
|
|
|
|
#include "mp_board.h"
|
|
|
|
#include "mp_option.h"
|
|
|
|
|
|
|
|
class TQHBoxLayout;
|
|
|
|
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 TQWidget
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
/** Constructor which takes a MPGameInfo struct as parameter.
|
|
|
|
*/
|
|
|
|
MPInterface(const MPGameInfo &gameInfo,
|
|
|
|
uint nbActions, const ActionData *data,
|
|
|
|
TQWidget *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 !
|
|
|
|
*/
|
|
|
|
TQString 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 !
|
|
|
|
*/
|
|
|
|
TQDataStream &readingStream(uint i) const;
|
|
|
|
|
|
|
|
/** @return the writing stream for board #i.
|
|
|
|
*/
|
|
|
|
TQDataStream &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(TQDataStream &) {}
|
|
|
|
|
|
|
|
/** Used by the server to write meta data to clients.
|
|
|
|
* NB: the use of this method is optional.
|
|
|
|
* Do not call from client !
|
|
|
|
*/
|
|
|
|
TQDataStream &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 TQString &msg);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void paintEvent(TQPaintEvent *);
|
|
|
|
void keyPressEvent(TQKeyEvent *);
|
|
|
|
void keyReleaseEvent(TQKeyEvent *);
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void enableKeys(bool enable);
|
|
|
|
void singleHumanSlot();
|
|
|
|
|
|
|
|
public:
|
|
|
|
class Data {
|
|
|
|
public:
|
|
|
|
Data() {}
|
|
|
|
MPBoard *ptr;
|
|
|
|
int humanIndex;
|
|
|
|
TQString name;
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
Local *internal;
|
|
|
|
const MPGameInfo gameInfo;
|
|
|
|
TQValueList<Data> boards;
|
|
|
|
uint nbLocalHumans;
|
|
|
|
TQHBoxLayout *hbl;
|
|
|
|
bool _server, disconnected;
|
|
|
|
|
|
|
|
KeyData *_keyData;
|
|
|
|
TQMemArray<KeyCollection *> _keyCol;
|
|
|
|
|
|
|
|
void createServerGame(const TQPtrList<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
|