summaryrefslogtreecommitdiffstats
path: root/libtdegames/kgame/kplayer.h
blob: 910781f3f78f8e1e53ea0ba9f5338fe28a98fb79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/*
    This file is part of the KDE games library
    Copyright (C) 2001 Martin Heni ([email protected])
    Copyright (C) 2001 Andreas Beckermann ([email protected])

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#ifndef __KPLAYER_H_
#define __KPLAYER_H_

#include <tqstring.h>
#include <tqobject.h>
#include <tqptrlist.h>

#include "kgameproperty.h"
#include <kdemacros.h>

class KGame;
class KGameIO;
class KGamePropertyBase;
class KGamePropertyHandler;

class KPlayerPrivate;

/**
 * @short Base class for a game player
 *
 * The KPlayer class is the central player object. It holds
 * information about the player and is responsible for any
 * input the player does. For this arbitrary many KGameIO
 * modules can be plugged into it. Main features are:
 * - Handling of IO devices
 * - load/save (mostly handled by KGamePropertyHandler)
 * - Turn handling (turn based, asynchronous)
 *
 * A KPlayer depends on a KGame object. Call KGame::addPlayer() to plug
 * a KPlayer into a KGame object. Note that you cannot do much with a
 * KPlayer object before it has been plugged into a KGame. This is because
 * most properties of KPlayer are KGameProperty which need to send messages
 * through a KGame object to be changed. 
 *
 * A KGameIO represents the input methods of a player and you should make all
 * player inputs through it. So call something like playerInput->move(4);
 * instead which should call KGameIO::sendInput() to actually move. This way
 * you gain a *very* big advantage: you can exchange a KGameIO whenever you
 * want! You can e.g. remove the KGameIO of a local (human) player and just
 * replace it by a computerIO on the fly! So from that point on all playerInputs
 * are done by the computerIO instead of the human player. You also can replace
 * all network players by computer players when the network connection is broken
 * or a player wants to quit. 
 * So remember: use KGameIO whenever possible! A KPlayer should just
 * contain all data of the player (KGameIO must not!) and several common
 * functions which are shared by all of your KGameIOs.
 *
 */
class KDE_EXPORT KPlayer : public TQObject
{
  Q_OBJECT
  TQ_OBJECT

public:
      typedef TQPtrList<KGameIO> KGameIOList;

      // KPlayer(KGame *,KGameIO * input=0);
      /**
       * Create a new player object. It will be automatically
       * deleted if the game it belongs to is deleted.
       */
      KPlayer();

      /**
       * Create a new player object. It will be automatically
       * deleted if the game it belongs to is deleted. This constructor
       * automatically adds the player to the game using KGame::addPlayer()
       */
      KPlayer(KGame* game);

      virtual ~KPlayer();

      /**
      * The idendification of the player. Overwrite this in
      * classes inherting KPlayer to run time identify them.
      *
      * @return 0 for default KPlayer.
      */
      virtual int rtti() const {return 0;}

      /**
      * Gives debug output of the game status
      */
      void Debug();

      // properties
      /**
       * Returns a list of input devices 
       *
       * @return list of devices
       */
      KGameIOList *ioList() {return &mInputList;}

      /**
       * sets the game the player belongs to. This
       * is usually automatically done when adding a
       * player
       *
       * @param game the game
       */
      void setGame(KGame *game) {mGame=game;}

      /**
       * Query to which game the player belongs to
       *
       * @return the game
       */
      KGame *game() const {return mGame;}

      /**
       * Set whether this player can make turns/input
       * all the time (true) or only when it is its
       * turn (false) as it is used in turn based games
       *
       * @param a async=true turn based=false
       */
      void setAsyncInput(bool a) {mAsyncInput = a;}

      /**
       * Query whether this player does asynchronous 
       * input
       *
       * @return true/false
       */
      bool asyncInput() const {return mAsyncInput.value();}

      /**
       * Is this player a virtual player, ie is it 
       * created by mirroring a real player from another
       * network game. This mirroring is done autmatically
       * as soon as a network connection is build and it affects
       * all players regardless what type
       *
       * @return true/false
       */
      bool isVirtual() const;

      /**
       * @internal
       * Sets whether this player is virtual. This is internally
       * called
       *
       * @param v virtual true/false
       */
      void setVirtual(bool v);

      /**
       * Is this player an active player. An player is usually
       * inactivated if it is replaced by a network connection.
       * But this could also be called manually
       *
       * @return true/false
       */
      bool isActive() const {return mActive;}

      /**
       * Set an player as active (true) or inactive (false)
       *
       * @param v true=active, false=inactive
       */
      void setActive(bool v) {mActive=v;}

      /**
       * Returns the id of the player
       *
       * @return the player id
       */
      TQ_UINT32 id() const; 

      /* Set the players id. This is done automatically by
       * the game object when adding a new player!
       *
       * @param i the player id
       */
      void setId(TQ_UINT32 i);

      /**
       * Returns the user defined id of the player
       * This value can be used arbitrary by you to
       * have some user idendification for your player,
       * e.g. 0 for a white chess player, 1 for a black 
       * one. This value is more reliable than the player 
       * id whcih can even change when you make a network 
       * connection.
       *
       * @return the user defined player id
       */
      int userId() const {return mUserId.value();} 

      /* Set the user defined players id.
       *
       * @param i the user defined player id
       */
      void setUserId(int i) {mUserId = i;}

      /**
       * Returns whether this player can be replaced by a network
       * connection player. The name of this function can be 
       * improved ;-) If you do not overwrite the function to 
       * select what players shall play in a network the KGame
       * does an automatic selection based on the networkPriority
       * This is not a terrible important function at the moment.
       *
       * @return true/false
       */
      int networkPriority() const;

      /**
       * Set whether this player can be replaced by a network
       * player. There are to possible games. The first type
       * of game has arbitrary many players. As soon as a network
       * players connects the game runs with more players (not tagged
       * situation). The other type is e.g. games like chess which
       * require a constant player number. In a network game situation
       * you would tag one or both players of all participants. As
       * soon as the connect the tagged player will then be replaced
       * by the network partner and it is then controlled over the network.
       * On connection loss the old situation is automatically restored.
       *
       * The name of this function can be improved;-)
       *
       * @param b should this player be tagged
       */
      void setNetworkPriority(int b);

      /**
       * Returns the player which got inactivated to allow
       * this player to be set up via network. Mostly internal
       * function
       */
      KPlayer *networkPlayer() const;

      /**
       * Sets this network player replacement. Internal stuff 
       */
      void setNetworkPlayer(KPlayer *p);

      // A name and group the player belongs to
      /**
       * A group the player belongs to. This
       * Can be set arbitrary by you.
       */
      void setGroup(const TQString& group);

      /**
       * Query the group the player belongs to.
       */
      virtual const TQString& group() const;

      /**
       * Sets the name of the player.
       * This can be chosen arbitrary.
       * @param name The player's name
       */
      void setName(const TQString& name);

      /**
       * @return The name of the player.
       */
      virtual const TQString& name() const;


      // set devices
      /**
       * Adds an IO device for the player. Possible KGameIO devices
       * can either be taken from the existing ones or be self written.
       * Existing are e.g. Keyboard, Mouse, Computerplayer
       *
       * @param input the inut device
       * @return true if ok
       */
      bool addGameIO(KGameIO *input);

      /**
       * remove (and delete) a game IO device
       *
       * The remove IO(s) is/are deleted by default. If
       * you do not want this set the parameter deleteit to false
       *
       * @param input the device to be removed or 0 for all devices
       * @param deleteit true (default) to delete the device otherwisse just remove it
       * @return true on ok
       */
      bool removeGameIO(KGameIO *input=0,bool deleteit=true);

      /**
       * Finds the KGameIO devies with the given rtti code.
       * E.g. find the mouse or network device
       *
       * @param rtti the rtti code to be searched for
       * @return the KGameIO device
       */
      KGameIO *findRttiIO(int rtti) const;

      /**
       * Checks whether this player has a IO device of the
       * given rtti type
       *
       * @param rtti the rtti typed to be checked for
       * @return true if it exists
       */
      bool hasRtti(int rtti) const  {return findRttiIO(rtti)!=0;}

      // Message exchange
      /**
       * Forwards input to the game object..internal use only
       *
       * This method is used by KGameIO::sendInput(). Use that function
       * instead to send player inputs!
       *
       * This function forwards a player input (see KGameIO classes) to the
       * game object, see KGame, either to KGame::sendPlayerInput() (if
       * transmit=true, ie the message has just been created) or to
       * KGame::playerInput() (if player=false, ie the message *was* sent through
       * KGame::sendPlayerInput).
       */
      virtual bool forwardInput(TQDataStream &msg,bool transmit=true, TQ_UINT32 sender=0);

      /**
       * Forwards Message to the game object..internal use only
       */
      virtual bool forwardMessage(TQDataStream &msg,int msgid,TQ_UINT32 receiver=0,TQ_UINT32 sender=0);

      // Game logic
      /**
       * is it my turn to go
       *
       * @return true/false
       */
      bool myTurn() const {return mMyTurn.value();}

      /**
       * Sets whether this player is the next to turn.
       * If exclusive is given all other players are set
       * to setTurn(false) and only this player can move
       *
       * @param b true/false
       * @param exclusive true (default)/ false
       * @return should be void
       */
      bool setTurn(bool b,bool exclusive=true);


      // load/save
     /**
      * Load a saved player, from file OR network. By default all 
      * KGameProperty objects in the dataHandler of this player are loaded
      * and saved when using load or save. If you need to save/load more
      * you have to replace this function (and save). You will probably
      * still want to call the default implementation additionally!
      * 
      * @param stream a data stream where you can stream the player from
      *
      * @return true?
      */
      virtual bool load(TQDataStream &stream);

     /**
      * Save a player to a file OR to network. See also load
      *
      * @param stream a data stream to load the player from
      *
      * @return true?
      */
      virtual bool save(TQDataStream &stream);

      /**
       * Receives a message
       * @param msgid The kind of the message. See messages.txt for further
       * information
       * @param stream The message itself
       * @param sender 
       **/
      void networkTransmission(TQDataStream &stream,int msgid,TQ_UINT32 sender);

      /**
       * Searches for a property of the player given its id. 
       * @param id The id of the property
       * @return The property with the specified id
       **/
      KGamePropertyBase* findProperty(int id) const;

      /**
       * Adds a property to a player. You would add all
       * your player specific game data as KGameProperty and
       * they are automatically saved and exchanged over network.
       *
       * @param data The property to be added. Must have an unique id!
       * @return false if the given id is not valid (ie another property owns
       * the id) or true if the property could be added successfully
       **/
      bool addProperty(KGamePropertyBase* data);

      /**
       * Calculates a checksum over the IO devices. Can be used to
       * restore the IO handlers. The value returned is the 'or'ed
       * value of the KGameIO rtti's. 
       * this is itnernally used for saving and restorign a player.
       */
      int calcIOValue();

       /**
        * @return the property handler
        */
       KGamePropertyHandler* dataHandler();

signals:
      /**
       *  The player object got a message which was targeted
       *  at it but has no default method to process it. This
       *  means probably a user message. Connecting to this signal
       *  allowed to process it.
       */
       void signalNetworkData(int msgid, const TQByteArray& buffer, TQ_UINT32 sender, KPlayer *me);

       /**
        * This signal is emmited if a player property changes its value and
        * the property is set to notify this change. This is an
        * important signal as you should base the actions on a reaction
        * to this property changes.
        */
       void signalPropertyChanged(KGamePropertyBase *property,KPlayer *me);

protected slots:
      /**
       * Called by KGameProperty only! Internal function!
       **/
      void sendProperty(int msgid, TQDataStream& stream, bool* sent);
      /**
       * Called by KGameProperty only! Internal function!
       **/
      void emitSignal(KGamePropertyBase *me);


private:
      void init();

private:
      KGame *mGame;
      bool mActive;      // active player
      KGameIOList mInputList;

      // GameProperty // AB: I think we can't move them to KPlayerPrivate - inline
      // makes sense here
      KGamePropertyBool mAsyncInput;  // async input allowed
      KGamePropertyBool mMyTurn;      // Is it my turn to play (only useful if not async)?
      KGamePropertyInt  mUserId;      // a user defined id

      KPlayerPrivate* d;
};

#endif