File indexing completed on 2024-11-03 06:55:26

0001 /*
0002     SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com>
0003     SPDX-FileCopyrightText: 2013 Denis Kuplaykov <dener.kup@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef KREVERSI_GAME_H
0009 #define KREVERSI_GAME_H
0010 
0011 #include <QObject>
0012 #include <QStack>
0013 #include <QTimer>
0014 
0015 #include "Engine.h"
0016 #include "commondefs.h"
0017 #include "kreversiplayer.h"
0018 
0019 class Engine;
0020 class KReversiPlayer;
0021 
0022 /**
0023  *  KReversiGame incapsulates all of the game logic.
0024  *  Whenever the board state changes it emits corresponding signals.
0025  *  The idea is also to abstract from any graphic representation of the game
0026  *  process
0027  *
0028  *  KReversiGame receives signals from KReversiPlayer classes.
0029  *  I.e. it receives commands and emits events when it's internal state changes
0030  *  due to this commands dispatching.
0031  *
0032  *  See KReversiView, KReversiPlayer, KReversiHumanPlayer
0033  *  and KReversiComputerPlayer for example of working with KReversiGame
0034  *
0035  *  @see KReversiView, KReversiPlayer, KReversiHumanPlayer
0036  */
0037 class KReversiGame : public QObject
0038 {
0039     Q_OBJECT
0040 public:
0041     /**
0042      * Constructs game with two specified players.
0043      */
0044     KReversiGame(KReversiPlayer *blackPlayer, KReversiPlayer *whitePlayer);
0045     ~KReversiGame() override;
0046     /**
0047      *  @return if undo is possible
0048      */
0049     bool canUndo() const;
0050     /**
0051      *  Undoes all the opponent of current player moves and one his move
0052      *  (so after calling this function it will be still current player turn)
0053      *  @return number of undone moves
0054      */
0055     int undo();
0056     /**
0057      *  @return score (number of chips) of the @p player
0058      */
0059     int playerScore(ChipColor player) const;
0060     /**
0061      *  @return color of the chip at position @p pos
0062      */
0063     ChipColor chipColorAt(KReversiPos pos) const;
0064     /**
0065      *  @return a hint to current player
0066      */
0067     KReversiMove getHint() const;
0068     /**
0069      *  @return last move made
0070      */
0071     KReversiMove getLastMove() const;
0072     /**
0073      *  @return a list of chips which were changed during last move.
0074      *  First of them will be the move itself, and the rest - chips which
0075      *  were turned by that move
0076      */
0077     MoveList changedChips() const {
0078         return m_changedChips;
0079     }
0080     /**
0081      *  @return a list of possible moves for current player
0082      */
0083     MoveList possibleMoves() const;
0084     /**
0085      *  @return whether the game is already over
0086      */
0087     bool isGameOver() const;
0088     /**
0089      *  @return whether any player move is at all possible
0090      */
0091     bool isAnyPlayerMovePossible(ChipColor player) const;
0092     /**
0093      *  @return a color of the current player
0094      */
0095     ChipColor currentPlayer() const {
0096         return m_curPlayer;
0097     }
0098     /**
0099      *  Sets animation times from players to @p delay milliseconds
0100      */
0101     void setDelay(int delay);
0102     /**
0103      *  Get wait time for given cell before animating. Used for sequental turning of chips
0104      */
0105     int getPreAnimationDelay(KReversiPos pos) const;
0106     /**
0107      *  @return History of moves as MoveList
0108      */
0109     MoveList getHistory() const;
0110 
0111     /**
0112      *  @return Is hint allowed for current player
0113      */
0114     bool isHintAllowed() const;
0115 private Q_SLOTS:
0116     /**
0117      *  Starts next player's turn.
0118      */
0119     void startNextTurn();
0120     /**
0121      *  Slot used to handle moves from black player
0122      *  @param move Move of black player
0123      */
0124     void blackPlayerMove(KReversiMove move);
0125     /**
0126      *  Slot used to handle moves from white player
0127      *  @param move Move of white player
0128      */
0129     void whitePlayerMove(KReversiMove move);
0130     /**
0131      *  Slot to handle end of animations with m_delayTimer
0132      */
0133     void onDelayTimer();
0134     /**
0135      *  Slot to handle ready-status of black player
0136      */
0137     void blackReady();
0138     /**
0139      *  Slot to handle ready-status of white player
0140      */
0141     void whiteReady();
0142 
0143 Q_SIGNALS:
0144     void gameOver();
0145     void boardChanged();
0146     void moveFinished();
0147     void whitePlayerCantMove();
0148     void blackPlayerCantMove();
0149     void whitePlayerTurn();
0150     void blackPlayerTurn();
0151 private:
0152     // predefined direction arrays for easy implementation
0153     static const int DIRECTIONS_COUNT = 8;
0154     static const int DX[];
0155     static const int DY[];
0156     /**
0157      *  Used to make player think about his move again after unpossible move
0158      */
0159     void kickCurrentPlayer();
0160     /**
0161      *  This will make the player @p move
0162      *  If that is possible, of course
0163      */
0164     void makeMove(KReversiMove move);
0165     /**
0166      * This function will tell you if the move is possible.
0167      */
0168     bool isMovePossible(KReversiMove move) const;
0169     /**
0170      *  Searches for "chunk" in direction @p dirNum for @p move.
0171      *  As my English-skills are somewhat limited, let me introduce
0172      *  new terminology ;).
0173      *  I'll define a "chunk" of chips for color "C" as follows:
0174      *  (let "O" be the color of the opponent for color "C")
0175      *  CO[O]C <-- this is a chunk
0176      *  where [O] is one or more opponent's pieces
0177      */
0178     bool hasChunk(int dirNum, KReversiMove move) const;
0179     /**
0180      *  Performs @p move, i.e. marks all the chips that player wins with
0181      *  this move with current player color
0182      */
0183     void turnChips(KReversiMove move);
0184     /**
0185      *  Sets the type of chip according to @p move
0186      */
0187     void setChipColor(KReversiMove move);
0188     /**
0189      *  Delay time
0190      */
0191     int m_delay;
0192     /**
0193      *  Status flags used to know when both players are ready
0194      */
0195     bool m_isReady[2];
0196     /**
0197      *  Last player who has made a move. Cannot be NoColor after the first move
0198      */
0199     ChipColor m_lastPlayer;
0200     /**
0201      *  The board itself
0202      */
0203     ChipColor m_cells[8][8];
0204     /**
0205      *  Score of each player
0206      */
0207     int m_score[2];
0208     /**
0209      *  AI to give hints
0210      */
0211     Engine *m_engine;
0212     /**
0213      *  Color of the current player.
0214      *  @c NoColor if it is interchange for animations
0215      */
0216     ChipColor m_curPlayer;
0217     /**
0218      *  This list holds chips that were changed/added during last move
0219      *  First of them will be the chip added to the board by the player
0220      *  during last move. The rest of them - chips that were turned by that
0221      *  move.
0222      */
0223     MoveList m_changedChips;
0224     /**
0225      *  This is an undo stack.
0226      *  It contains a lists of chips changed with each turn.
0227      *  @see m_changedChips
0228      */
0229     QStack<MoveList> m_undoStack;
0230     /**
0231      *  Used to handle end of player's animations or other stuff
0232      */
0233     QTimer m_delayTimer;
0234 
0235     /**
0236      *  Actual players, who play the game
0237      */
0238     KReversiPlayer *m_player[2];
0239 };
0240 #endif