File indexing completed on 2024-05-19 07:52:02

0001 /*
0002     This file is part of the game 'KJumpingCube'
0003 
0004     SPDX-FileCopyrightText: 1998-2000 Matthias Kiefer <matthias.kiefer@gmx.de>
0005     SPDX-FileCopyrightText: 2012-2013 Ian Wadham <iandw.au@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #ifndef GAME_H
0011 #define GAME_H
0012 
0013 #include "ai_globals.h"
0014 
0015 #include <QObject>
0016 #include <QTime> // IDW test.
0017 
0018 #include <QUrl>
0019 #include <QList>
0020 
0021 class KConfigGroup;
0022 class KCubeBoxWidget;
0023 class SettingsWidget;
0024 class AI_Main;
0025 class AI_Box;
0026 
0027 /**
0028 * Codes for actions available to users of the Game class.
0029 */
0030 enum Action {NEW, HINT, BUTTON, UNDO, REDO, SAVE, SAVE_AS, LOAD};
0031 
0032 class Game : public QObject
0033 {
0034    Q_OBJECT
0035    friend class KJumpingCube;
0036 
0037 public:
0038    explicit Game (const int dim, KCubeBoxWidget * view, QWidget * parent = nullptr);
0039 
0040    ~Game() override;
0041 
0042    /**
0043     * Make sure all animation and AI activity is over before closing a game.
0044     * */
0045    void shutdown();
0046 
0047 public Q_SLOTS:
0048 
0049    /**
0050     * Perform one of the game-actions listed in enum type Action.
0051     *
0052     * @param action  The action to be performed, taken from enum Action.
0053     *                This parameter must be of type int because KJumpingCube
0054     *                invokes gameActions() via a QSignalMapper of int type.
0055     */
0056    void gameActions (const int action);
0057 
0058 private:
0059    /**
0060     * Show the winner when the game ends, either after a move or a redo.
0061     */
0062    void showWinner();
0063 
0064 private Q_SLOTS:
0065    /**
0066     * Pop up the settings/preferences/configuration dialog window.
0067     */
0068    void showSettingsDialog (bool show = true);
0069 
0070    /**
0071     * Check changes in the user's preferences or settings.  Some settings can
0072     * be used immediately, some must wait until the start of the next turn and
0073     * a change in box size may require the user's OK (or not) to abandon a game
0074     * in progress and start a new game.
0075     */
0076    void newSettings();
0077 
0078    /**
0079    * Check if cube at [x, y] is available to the current (human) player.
0080    * If it is, make a move using doMove() and the cube at [x, y], animating
0081    * the move, if required.
0082    */
0083    void startHumanMove (int x, int y);
0084 
0085 private:
0086    /**
0087    * Check if the current player is a computer player and, if so, start the
0088    * next move or perhaps wait for the user to click the button to show that
0089    * he or she is ready.  Otherwise, wait for a human player to move.
0090    */
0091    void setUpNextTurn();
0092 
0093    /**
0094     * Starts calculating a computer move or hint (using asynchronous AI thread).
0095     */
0096    void computeMove();
0097 
0098 private Q_SLOTS:
0099    /**
0100     * Deliver a computer-move or hint calculated by the AI thread and start an
0101     * animation to show which cube is to move.
0102     *
0103     * @param index  The position of the move in the array of cubes. If the box
0104     *               has n x n cubes, index = x * n + y for co-ordinates [x, y].
0105     */
0106    void moveCalculationDone (int index);
0107 
0108 private:
0109    /**
0110     * Finish showing a computer move or hint. If it is a computer move, use
0111     * doMove() to make the actual move and animate it, if required.
0112     */
0113    void showingDone (int index);
0114 
0115    /**
0116    * Increase the cube at 'index' and start the animation loop, if required.
0117    */
0118    void   doMove (int index);
0119 
0120    /**
0121     * Perform and display one or more steps of a move, with breaks for animation
0122     * if required, finishing when all steps have been done or the current player
0123     * has won the game. If there is no animation or if the user clicks the
0124     * action button to interrupt the animation, perform all steps at full speed.
0125     */
0126    void   doStep();
0127 
0128    /**
0129     * Finish one step of a move, if animating, and use doStep() to continue.
0130     */
0131    void stepAnimationDone (int index);
0132 
0133    /**
0134     * Finish an entire move.
0135     */
0136    void moveDone();
0137 
0138    /**
0139     * Switch to the other player, human or computer, after a non-winning move.
0140     */
0141    Player changePlayer();
0142 
0143    /**
0144     * Initiate or interrupt computer-move or animation activities. This is used
0145     * when the computer is first to move or when the user wishes to interrupt
0146     * or step through moves, as in a computer v. computer game or a complex
0147     * series of cascade moves.
0148     */
0149    void buttonClick();
0150 
0151    /**
0152     * Set the action-button to be red, enabled and with text relevant to
0153     * stopping the current activity (AI v AI game OR computing, showing or
0154     * animating a move).
0155     */
0156    void setStopAction();
0157 
0158    /**
0159     * Act on changes in settings that can be used immediately.  Color changes
0160     * can take effect when control returns to the event loop, the other settings
0161     * next time they are used.  They include animation settings, AI players and
0162     * their skill levels.
0163     */
0164    void loadImmediateSettings();
0165 
0166    /**
0167     * Act on changes in the user's choice of players and computer-player pause.
0168     * These can take effect only at the start of a turn.
0169     */
0170    void loadPlayerSettings();
0171 
0172 private Q_SLOTS:
0173    /**
0174     * Indicate that showing a move or animating a move-step has finished.
0175     *
0176     * @param index  The position of the move in the array of cubes. If the box
0177     *               has n x n cubes, index = x * n + y for co-ordinates [x, y].
0178     */
0179    void animationDone (int index);
0180 
0181 Q_SIGNALS:
0182    /**
0183     * Request that the current player be shown in the KJumpingCube main window.
0184     *
0185     * @param player   The ID of the player (= 1 or 2).
0186     */
0187    void playerChanged (int newPlayer);
0188 
0189    /**
0190     * Request a change of appearance or text of the general-purpose action
0191     * button in the KJumpingCube main window.
0192     *
0193     * @param enabled  True = button is active, false = button is inactive.
0194     * @param stop     If active, true = use STOP style, false = use GO style.
0195     * @param caption  Translated text to appear on the button.
0196     */
0197    void buttonChange  (bool enabled, bool stop = false,
0198                        const QString & caption = QLatin1String(""));
0199 
0200    /**
0201     * Request enabling or disabling of an action by KJumpingCube main window.
0202     *
0203     * @param a      The game-action to be enabled or disabled.
0204     * @param onOff  True = enable the action, false = disable it.
0205     */
0206    void setAction     (const Action a, const bool onOff);
0207 
0208    /**
0209     * Request display of a status message.
0210     *
0211     * @param message  The message to be displayed (translated).
0212     * @param timed    If true, display the message for a limited time.
0213     */
0214    void statusMessage (const QString & message, bool timed);
0215 
0216 protected:
0217    void saveProperties(KConfigGroup&);
0218    void readProperties(const KConfigGroup&);
0219 
0220 private:
0221    void loadSavedSettings (const KConfigGroup& config);
0222 
0223 private:
0224    QTime t; // IDW test.
0225 
0226    enum Activity     {Idle, Computing, Stopping, Aborting,
0227                       ShowingMove, AnimatingMove};
0228    enum WaitingState {Nil, WaitingToStep, ComputerToMove};
0229 
0230    Activity         m_activity;     // Current computer activity.
0231    WaitingState     m_waitingState; // Current pause state.
0232    bool             m_waitingToMove;    // If true, AI paused or human to move.
0233    int              m_moveNo;       // Current move number, 0 = not started.
0234    int              m_endMoveNo;    // Winning move number, if game is over.
0235    bool             m_interrupting; // If user has interrupted AI v. AI.
0236    bool             m_newSettings;  // If new player settings during a move.
0237 
0238    QWidget *        m_parent;       // Game object's parent (main window).
0239    KCubeBoxWidget * m_view;     // Displayed cubes.
0240 
0241    // A pointer to the Settings widget defined in Qt Designer, when the
0242    // Preferences dialog is first created by Game::showSettingsDialog().
0243    SettingsWidget * m_settingsPage; // Displayed settings, 0 = not yet used.
0244 
0245    AI_Box *         m_box;      // Game engine's cubes.
0246    int              m_side;     // Cube box size, from Prefs::cubeDim().
0247    Player           m_currentPlayer;    // Current player: One or Two.
0248    QList<int> *     m_steps;        // Steps in a move to be displayed.
0249 
0250    AI_Main *        m_ai;       // Current computer player.
0251 
0252    int              m_index;        // Location of move.
0253    bool             m_fullSpeed;    // If true, no animation of moves.
0254 
0255    bool             computerPlOne;  // If true, Player 1 is an AI.
0256    bool             computerPlTwo;  // If true, Player 2 is an AI.
0257 
0258    bool             m_pauseForComputer; // If true, pause before each AI move.
0259    bool             m_pauseForStep; // If true, pause before animation step.
0260 
0261    QUrl             m_gameURL;      // Location of load/save file.
0262 
0263 private Q_SLOTS:
0264    void   newGame();            // Slot needed for queued invocation.
0265 
0266 private:
0267    void   saveGame (bool saveAs);   // Standard save-game action.
0268    void   loadGame();           // Standard load-game action.
0269    void   undo();           // Standard undo-move action.
0270    void   redo();           // Standard redo-move action.
0271 
0272    /**
0273     * Check if it is OK to start a new game, maybe ending a current game.
0274     */
0275    bool   newGameOK();
0276 
0277    /**
0278    * Reset cubebox for a new game.
0279    */
0280    void reset();
0281 
0282    /**
0283     * Undo or redo a move.
0284     *
0285     * @param   change  -1 = undo, +1 = redo
0286     *
0287     * @return  true = More moves to undo/redo, false = No more to undo/redo.
0288     */
0289    bool undoRedo (int change);
0290 
0291    /**
0292    * Set the number of cubes in a row or column.  If the number has changed,
0293    * delete the existing set of cubes and create a new one.
0294    */
0295    virtual void setDim (int dim);
0296 
0297    /**
0298     * Returns true if the player is a computer player.
0299     */
0300    bool isComputer (Player player) const;
0301 
0302    inline void restoreGame(const KConfigGroup&c) { readProperties(c); }
0303 };
0304 
0305 #endif // GAME_H