1 /*
2     This file is part of the KDE games kwin4 program
3     SPDX-FileCopyrightText: 2006 Martin Heni <kde@heni-online.de>
4 
5     SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef KWIN4DOC_H
9 #define KWIN4DOC_H
10 
11 // own
12 #include "kwin4global.h"
13 #include "kwin4player.h"
14 #include "aiboard.h"
15 #include "kgamepropertyarray.h"
16 // KDEGames
17 #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API
18 #include <libkdegamesprivate/kgame/kgame.h>
19 #include <libkdegamesprivate/kgame/kgameio.h>
20 // KF
21 #include <KConfig>
22 // Qt
23 #include <QList>
24 #include <QVector>
25 
26 class KWin4View;
27 class Score;
28 
29 
30 /**
31  * The game document or game engine. It is derived from the KGame framework.
32  */
33 class KWin4Doc : public KGame
34 {
35   Q_OBJECT
36 
37   public:
38     /** Constructor.
39       * @param parent The parent widget
40       */
41     explicit KWin4Doc(QWidget *parent);
42 
43     /** The destructor.
44       */
45     ~KWin4Doc() override;
46 
47     /** Adds a view to the document which displays the document contents.
48       * @param view The view to add
49       */
50     void setView(KWin4View *view);
51 
52     /** Initializes the KGame derived players.
53       */
54     void initPlayers();
55 
56     /** Save the document in the datastrem. This is a KGame function.
57       * @param stream  The data stream to use
58       * @param network Is the saving via the network (a network game)
59       * @param reset   Reset parameter forward to KGame
60       * @return True on success, false otherwise.
61       */
62     bool loadgame(QDataStream &stream, bool network, bool reset) override;
63 
64     /** Read the game config from the config file.
65       * @param config The config
66       */
67     void readConfig(KConfig* config);
68 
69     /** Write the game config to the config file.
70       * @param config The config
71       */
72     void writeConfig(KConfig* config);
73 
74 
75     /** End a game. Update statistic and forward end game to view.
76       * @param mode Indicate how the game ended for the current player [TWin, TLost, TRemis, TBrk]
77       */
78     void endGame(TABLE mode);
79 
80     /** Reset all the player stats.
81       */
82     void resetStatistic();
83 
84     /** Redoes a move if possible.
85       * @return True on success.
86       */
87     bool redoMove();
88 
89     /** Undoes a move if possible.
90       * @return True on success.
91       */
92     bool undoMove();
93 
94     /** Generate a computer AI move and show it to the player as hint.
95       */
96     void calculateHint();
97 
98     /** Returns the all time statistics for player of given color
99       * The mode determines what statistics to access.
100       * @param col  The player color
101       * @param mode The type of data to retrieve [TWin, TRemis, TLost, TBrk, TSum]
102       * @return The amount of the queried category.
103       */
104     int getStatistic(COLOUR col, TABLE mode);
105 
106     /** Retrieve the name of the player of the given color.
107       * @param col The color
108       * @return The name.
109       */
110     QString getName(COLOUR col);
111 
112     /** Set the name of the player of the given color.
113       * @param col The color
114       * @param n   The new name
115       */
116     void setName(COLOUR col, const QString& n);
117 
118     /** Query the IO mode of player og the given color.
119       * @param col The color
120       * @return The input device mode.
121       */
122     KGameIO::IOMode playedBy(int col);
123 
124     /** Sets the input device mode for the given player color.
125       * @param col  The color
126       * @param mode The input device code (Mouse, Key, ...)
127       */
128     void setPlayedBy(int col,KGameIO::IOMode mode);
129 
130     /** Retrieve the player object for the given player colour.
131       * @param col The player color
132       * @return The player object.
133       */
134     KWin4Player* getPlayer(COLOUR col);
135 
136     /** Swap the start player so that the game is started alternatingly.
137       * @return The new start player color.
138       */
139     COLOUR switchStartPlayer();
140 
141     /** Sets the current player.
142       * @param no The current player
143       */
144     void setCurrentPlayer(COLOUR no);
145 
146     /** Retrieve the player whose turn it is next.
147       * @return The current player.
148       */
149     COLOUR getCurrentPlayer();
150 
151     /** Retrieve the current move number.
152       * @return The amount [0..42]
153       */
154     int getCurrentMove();
155 
156     /** Retrieve the maximum move which has been made before undos.
157       * @return The amount [0..42]
158       */
159     int getMaxMove();
160 
161     /** Retrieve the amount of moves in the undo/redo history.
162       * @return The amount [0..42]
163       */
164     int getHistoryCnt();
165 
166     /** Find the name of the AI process executable file.
167       * @return The filename
168       */
169     QString findProcessName();
170 
171 
172   protected:
173     /** Create and add an KGameIO device to an given player.
174       * The old ones have to be removed manually before.
175       * @param player The player to modify
176       * @param io     The IO mode (Mouse, AI, Keyboard, ...)
177       */
178     void createIO(KPlayer* player, KGameIO::IOMode io);
179 
180     /** Create a player of a given type (here only one type possible)
181       * and equip it with a given KGameIO device. Virtual players
182       * are remote network players.
183       * @param rtti  Unused
184       * @param io    The IO mode
185       * @param isvirtual True for network players (without physical IO)
186       */
187     KPlayer* createPlayer(int rtti, int io, bool isvirtual) override;
188 
189     /** KGame function to determine the next player. In KWin4 players alternate.
190       * @param last      The last player to move
191       * @param exclusive unused
192       */
193     KPlayer* nextPlayer(KPlayer* last, bool exclusive=true) override;
194 
195     /** This is also an overwritten function of KGame. It is
196       * called in the game negotiation upon connect. Here
197       * the games have to determine what player is remote and
198       * what is local.
199       * @param list     Unused
200       * @param newList  List of new players
201       * @param inactive List of inactive players
202       */
203     void newPlayersJoin(KGamePlayerList* list, KGamePlayerList* newList, QList<int>& inactive) override;
204 
205     /** Reset the whole game to the beginning (clear board, ...)
206       * @param initview  If true also reset the view
207       */
208     void resetGame(bool initview);
209 
210     /** Make a game move to the given position and return a status.
211       * Also displays it in the view.
212       * @param x    The position to move to
213       * @param mode The mode of the move (0: normal move: 1: redo move)
214       * @return The movement status (allowed, normal, ...)
215       */
216     MOVESTATUS makeMove(int x,int mode);
217 
218     /** Perform a game move. Calls makeMove().
219       *  @param x  The position to move to
220       *  @param id The player id
221       *  @return True if the move was successful.
222       */
223     bool doMove(int x, int id);
224 
225     /** Check whether the field has a game over situation. KGame standard
226       * function.
227       * @param player The current player
228       * @return -1: draw, 1: won, 0: continue game
229       */
230     int checkGameOver(KPlayer *player) override;
231 
232     /** Check whether the field has a game over situation. Called by
233       * above standard KGame function but with more suitable parameters.
234       * @param x   The position of the last move
235       * @param col The color of the last move
236       */
237     int checkGameOver(int x, COLOUR col);
238 
239     /** Pack the current game into a data stream so that it can be
240       * send to the computer AI.
241       * @param stream The data stream to write to
242       * @param pl     The player id
243       */
244     void prepareGameMessage(QDataStream& stream, qint32 pl);
245 
246     /** Main function to handle player input. This function is
247       * the central input for all player inputs. Mouse, Keyboard
248       * AI or network end here in the same format. A move is
249       * initiated here.
250       * @param msg    The game move message
251       * @param player The sender player
252       */
253     bool playerInput(QDataStream& msg, KPlayer* player) override;
254 
255     /** Set the IO devices new.
256       */
257     void recalcIO();
258 
259     /** Set the turn of the current player to true so that
260       * he can move.
261       */
262     void activateCurrentPlayer();
263 
264     /** Set the score value of the AI.
265       * @param value The score value.
266       */
267     void setScore(long value);
268 
269     /** Set the colour of a position on the game board.
270       * @param x The x position [0-6]
271       * @param y The y position [0-5]
272       * @param c The color [Red, Yellow, Nobody]
273       */
274     void setColour(int x,int y,COLOUR c);
275 
276     /** Retrieve the colour of a position on the game board.
277       * @param x The x position [0-6]
278       * @param y The y position [0-5]
279       * @return The color [Red, Yellow, Nobody]
280       */
281     COLOUR getColour(int x,int y);
282 
283     /** Retrieve the color of the i-th player. Player 0 is the start
284       * player and player 1 the follow up player.
285       * @param player The player number [0,1]
286       * @return The color of the player.
287       */
288     COLOUR getPlayerColour(int player);
289 
290   public Q_SLOTS:
291     /** Indication from the view that a move has been displayed. Now
292       * The next player can be switched.
293       * @param mode A user defined (unused) mode
294       */
295     void moveDone(int mode);
296 
297     /** Load the game properties from the settings. Either the config file
298       * or the config dialog call this.
299       */
300     void loadSettings();
301 
302   protected Q_SLOTS:
303     /** Initiate a repeat of the move. This happens if somehow the player
304       * input created an invalid move. The same player has to input again.
305       */
306     void repeatMove();
307 
308     /** An AI command was received from the computer AI _hint_ process. Process it.
309       * Currently this is only the hint move.
310       * @param in The input stream from the process
311       * @param io The io device
312       */
313     void processAIHintCommand(QDataStream& in, KGameProcessIO *io);
314 
315     /** An AI command was received from the computer AI _input device_ process. Process it.
316       * Currently this is only the move score value.
317       * @param in The input stream from the process
318       * @param io The io device
319       */
320     void processAICommand(QDataStream& in, KGameProcessIO* io);
321 
322     /** This slot is called by the signal of KGame to indicated
323      * that the network connection is done and a new client is
324      * connected
325      * @param cid Is the id of the client connected. If this is equal gameId() WE are the client.
326      * @param me  The game
327      */
328     void clientConnected(quint32 cid, KGame* me);
329 
330     /** This slot is called by the KGame input device when we should prepare a message
331       * to the AI process.
332       * @param stream   The message stream
333       * @param b        True if it is our turn
334       * @param input    The input device
335       * @param eatevent Set to true if a message has been send
336       */
337     void prepareAITurn(QDataStream &stream,bool b,KGameIO *input,bool *eatevent);
338 
339     /** Debug: Listen to network messages.
340       * @param id       The message id
341       * @param sender   The sender
342       * @param receiver The receiver
343       */
344     void networkMessageUpdate(int id, quint32 sender, quint32 receiver);
345 
346     /** Called by KGame when a player property has changed.
347       * We check whether the name changed and then update the score widget.
348       * @param prop   The property
349       * @param player The affected player
350       */
351     void playerPropertyChanged(KGamePropertyBase* prop, KPlayer* player);
352 
353     /** Called by KGame when a game property has changed. We update the game
354       * status etc.
355       * @param prop  The property
356       * @param me    The game
357       */
358     void gamePropertyChanged(KGamePropertyBase* prop, KGame* me);
359 
360     /** Received a debug message from the AI (debug only)
361       * @param s The message
362       */
363     void receivedStderr(const QString &s);
364 
365   Q_SIGNALS:
366     /** Emitted if the game status changes to run.
367       */
368     void signalGameRun();
369 
370     /** Emitted if the chat origin changes.
371       * @param player The affected player
372       */
373     void signalChatChanged(KWin4Player* player);
374 
375     /** Emitted when the next players move is due.
376       * @param playerNumber The number of the player
377       */
378     void signalNextPlayer(int playerNumber);
379 
380   private:
381     // The view
382     KWin4View *pView;
383 
384     // Last x position moved to
385     KGamePropertyInt mLastColumn;
386 
387     // Colour of last move
388     KGamePropertyInt mLastColour;
389 
390     // Amount of info in history
391     KGamePropertyInt mHistoryCnt;
392 
393     // 42 pieces construct the game board
394     KGamePropertyArray<int> mField;
395 
396     // Player who started game
397     KGamePropertyInt mStartPlayer;
398 
399     // Player's to move
400     KGamePropertyInt mAmzug;
401 
402     // Maximal move made in a game before undo
403     KGamePropertyInt mMaxMove;
404 
405     // Current move number in the game
406     KGamePropertyInt mCurrentMove;
407 
408     // To what height is a column filled
409     KGamePropertyArray<int> mFieldFilled;
410 
411     // Position of last hint given
412     KGamePropertyInt mLastHint;
413 
414     // Computer score value (position estimation)
415     KGamePropertyInt mScore;
416 
417     // History of all moves (x positions)
418     KGamePropertyArray<int> mHistory;
419 
420     // Input device of players
421     KGameIO::IOMode mPlayedBy[2];
422 
423     // Process AI for hints
424     KGameProcessIO *mHintProcess;
425 
426     // Score and status storage to communicate with view
427     Score* mStatus;
428 
429     // Keep AI move values
430     QVector<long> mAIValues;
431 };
432 
433 #endif // KWIN4DOC_H
434 
435