File indexing completed on 2024-12-01 03:46:41
0001 /* 0002 This file is part of the KDE games library 0003 SPDX-FileCopyrightText: 2001 Martin Heni (kde at heni-online.de) 0004 SPDX-FileCopyrightText: 2001 Andreas Beckermann (b_mann@gmx.de) 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #ifndef __KGAMEPROCESS_H_ 0010 #define __KGAMEPROCESS_H_ 0011 0012 // KDEGames 0013 #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API 0014 #include <libkdegamesprivate/kgame/kgamemessage.h> 0015 #include <libkdegamesprivate/kgame/kmessageio.h> 0016 // Qt 0017 #include <QFile> 0018 #include <QObject> 0019 0020 class QRandomGenerator; 0021 0022 class KPlayer; 0023 class KMessageFilePipe; 0024 class KGameProcessPrivate; 0025 0026 class KMessageFilePipe : public KMessageIO 0027 { 0028 Q_OBJECT 0029 0030 public: 0031 explicit KMessageFilePipe(QObject *parent, QFile *readFile, QFile *writeFile); 0032 ~KMessageFilePipe() override; 0033 bool isConnected() const override; 0034 void send(const QByteArray &msg) override; 0035 void exec(); 0036 0037 /** 0038 @return FALSE as this is no network IO. 0039 */ 0040 bool isNetwork() const override 0041 { 0042 return false; 0043 } 0044 0045 /** 0046 * The runtime identification 0047 */ 0048 int rtti() const override 0049 { 0050 return 4; 0051 } 0052 0053 private: 0054 QFile *mReadFile; 0055 QFile *mWriteFile; 0056 QByteArray mReceiveBuffer; 0057 int mReceiveCount; 0058 }; 0059 0060 /** 0061 * \class KGameProcess kgameprocess.h <KGame/KGameProcess> 0062 * 0063 * This is the process class used on the computer player 0064 * side to communicate with its counterpart KProcessIO class. 0065 * Using these two classes will give fully transparent communication 0066 * via QDataStreams. 0067 */ 0068 class KGameProcess : public QObject 0069 { 0070 Q_OBJECT 0071 0072 public: 0073 /** 0074 * Creates a KGameProcess class. Done only in the computer 0075 * player. To activate the communication you have to call 0076 * the exec function of this class which will listen 0077 * to the communication and emit signals to notify you of 0078 * any incoming messages. 0079 * Note: This function will only return after you set 0080 * setTerminate(true) in one of the received signals. 0081 * So you can not do any computer calculation after the exec function. 0082 * Instead you react on the signals which are emitted after a 0083 * message is received and perform the calculations there! 0084 * Example: 0085 * \code 0086 * int main(int argc ,char * argv[]) 0087 * { 0088 * KGameProcess proc; 0089 * connect(&proc,SIGNAL(signalCommand(QDataStream &,int ,int ,int )), 0090 * this,SLOT(slotCommand(QDataStream & ,int ,int ,int ))); 0091 * connect(&proc,SIGNAL(signalInit(QDataStream &,int)), 0092 * this,SLOT(slotInit(QDataStream & ,int ))); 0093 * connect(&proc,SIGNAL(signalTurn(QDataStream &,bool )), 0094 * this,SLOT(slotTurn(QDataStream & ,bool ))); 0095 * return proc.exec(argc,argv); 0096 * } 0097 * \endcode 0098 */ 0099 KGameProcess(); 0100 /** 0101 * Destruct the process 0102 */ 0103 ~KGameProcess() override; 0104 0105 /** 0106 * Enters the event loop of the computer process. Does only 0107 * return on setTerminate(true)! 0108 */ 0109 bool exec(); 0110 0111 /** 0112 * Should the computer process leave its exec function? 0113 * Activated if you setTerminate(true); 0114 * 0115 * @return true/false 0116 */ 0117 bool terminate() const 0118 { 0119 return mTerminate; 0120 } 0121 0122 /** 0123 * Set this to true if the computer process should end, ie 0124 * leave its exec function. 0125 * 0126 * @param b true for exit the exec function 0127 */ 0128 void setTerminate(bool b) 0129 { 0130 mTerminate = b; 0131 } 0132 0133 /** 0134 * Sends a message to the corresponding KGameIO 0135 * device. Works like the sendSystemMessage but 0136 * for user id's 0137 * 0138 * @param stream the QDataStream containing the message 0139 * @param msgid the message id for the message 0140 * @param receiver unused 0141 */ 0142 void sendMessage(QDataStream &stream, int msgid, quint32 receiver = 0); 0143 0144 /** 0145 * Sends a system message to the corresponding KGameIO device. 0146 * This will normally be either a performed move or a query 0147 * (IdProcessQuery). The query option is a way to communicate 0148 * with the KGameIO at the other side and e.g. retrieve some 0149 * game relevant data from here. 0150 * Example for a query: 0151 * \code 0152 * QByteArray buffer; 0153 * QDataStream out(buffer,QIODevice::WriteOnly); 0154 * int msgid=KGameMessage::IdProcessQuery; 0155 * out << (int)1; 0156 * proc.sendSystemMessage(out,msgid,0); 0157 * \endcode 0158 * 0159 * @param stream the QDataStream containing the message 0160 * @param msgid the message id for the message 0161 * @param receiver unused 0162 */ 0163 void sendSystemMessage(QDataStream &stream, int msgid, quint32 receiver = 0); 0164 0165 /** 0166 * Returns a pointer to a QRandomGenerator. You can generate 0167 * random numbers via e.g. 0168 * \code 0169 * random()->bounded(100); 0170 * \endcode 0171 * 0172 * @return QRandomGenerator pointer 0173 */ 0174 QRandomGenerator *random(); 0175 0176 protected Q_SLOTS: 0177 /** 0178 * A message is received via the interprocess connection. The 0179 * appropriate signals are called. 0180 */ 0181 void receivedMessage(const QByteArray &receiveBuffer); 0182 0183 Q_SIGNALS: 0184 /** 0185 * The generic communication signal. You have to connect to this 0186 * signal to generate a valid computer response onto arbitrary messages. 0187 * All signals but IdIOAdded and IdTurn end up here! 0188 * Example: 0189 * \code 0190 * void Computer::slotCommand(int &msgid,QDataStream &in,QDataStream &out) 0191 * { 0192 * qint32 data,move; 0193 * in >> data; 0194 * // compute move ... 0195 * move=data*2; 0196 * out << move; 0197 * } 0198 * \endcode 0199 * 0200 * @param inputStream the incoming data stream 0201 * @param msgid the message id of the message which got transmitted to the computer 0202 * @param receiver the id of the receiver 0203 * @param sender the id of the sender 0204 */ 0205 void signalCommand(QDataStream &inputStream, int msgid, int receiver, int sender); 0206 0207 /** 0208 * This signal is emitted if the computer player should perform a turn. 0209 * Calculations can be made here and the move can then be send back with 0210 * sendSystemMessage with the message id KGameMessage::IdPlayerInput. 0211 * These must provide a move which complies to your other move syntax as 0212 * e.g. produces by keyboard or mouse input. 0213 * Additional data which have been written into the stream from the 0214 * ProcessIO's signal signalPrepareTurn can be retrieved from the 0215 * stream here. 0216 * Example: 0217 * \code 0218 * void slotTurn(QDataStream &in,bool turn) 0219 * { 0220 * int id; 0221 * int recv; 0222 * QByteArray buffer; 0223 * QDataStream out(buffer,QIODevice::WriteOnly); 0224 * if (turn) 0225 * { 0226 * // Create a move - the format is yours to decide 0227 * // It arrives exactly as this in the kgame inputMove function!! 0228 * qint8 x1,y1,pl; 0229 * pl=-1; 0230 * x1=proc.random()->bounded(8); 0231 * y1=proc.random()->bounded(8); 0232 * // Stream it 0233 * out << pl << x1 << y1; 0234 * id=KGameMessage::IdPlayerInput; 0235 * proc.sendSystemMessage(out,id,0); 0236 * } 0237 * } 0238 * \endcode 0239 * 0240 * @param stream The datastream which contains user data 0241 * @param turn True or false whether the turn is activated or deactivated 0242 * 0243 */ 0244 void signalTurn(QDataStream &stream, bool turn); 0245 0246 /** 0247 * This signal is emitted when the process is initialized, i.e. added 0248 * to a KPlayer. Initial initialization can be performed here be reacting 0249 * to the KProcessIO signal signalIOAdded and retrieving the data here 0250 * from the stream. 0251 * It works just as the signalTurn() but is only send when the player is 0252 * added to the game, i.e. it needs some initialization data 0253 * 0254 * @param stream The datastream which contains user data 0255 * @param userid The userId of the player. (Careful to rely on it yet) 0256 */ 0257 void signalInit(QDataStream &stream, int userid); 0258 0259 protected: 0260 bool mTerminate; 0261 KMessageFilePipe *mMessageIO; 0262 0263 private: 0264 friend class KGameProcessPrivate; 0265 KGameProcessPrivate *const d; 0266 0267 Q_DISABLE_COPY(KGameProcess) 0268 }; 0269 #endif