/*************************************************************************** Description : KPuzzle - A KDE Jigsaw Puzzle Game Version : 0.2 Copyright : (C) 2000-2001 by Michael Wand EMail : mwand@gmx.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KPUZZLEGAME_H #define KPUZZLEGAME_H #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include class KPuzzleView; class CPicview; #include "piece.h" /* Game Types - these seem to be subject to change */ /* You have got one clock counting the overall playing time. */ #define STD_GAME 1 /* You have got a certain amount of time for every piece */ #define PIECE_TIME_GAME 2 /* You have a certain amount of allowed misplacements for every piece */ #define PIECE_FAULTS_GAME 3 /* You have a certain amount of allowed misplacements of pieces * for the entire game */ #define FAULTS_SUM_GAME 4 /* You have got a limited time for every piece, then the next piece is shown * (but there are various rounds) */ #define UNBEARABLE_GAME 5 /* Ways to turn a piece */ #define TURN_LR 1 #define TURN_UD 2 /* Game status */ #define GS_NOT_STARTED 1 #define GS_RUNNING 2 #define GS_SHOW_LARGE 3 #define GS_PAUSED 4 #define GS_WINNING 10 #define GS_SHOW_LARGE_WINNING 11 #define GS_LOSING 20 #define GS_SHOW_LARGE_LOSING 21 #define GS_SHOW_HIGHSCORES 30 /* Reasons to terminate */ #define TM_WON 1 #define TM_LOST 2 #define TM_QUIT 3 #define TM_FORCE 4 class KPuzzleGame; /* An instance of this class contains all * scoring information which applies to the * current game. */ class ScoreData { public: int _maxTime; /* You get ->this score if you stay below */ int _timeScore1; /* this time */ int _score1Time; int _timeScore2; int _score2Time; int _timeScore3; int _score3Time; int _rightPieceScore; int _wrongPieceScore; /* Bonus for completing a game */ int _bonus; /* PIECE_FAULTS_GAME or FAULTS_SUM_GAME */ int _maxFaults; /* PIECE_TIME_GAME or UNBEARABLE_GAME (time for every round) */ int _maxPieceTime; /* UNBEARABLE_GAME */ int _maxRounds; /* Save all data contained in this class */ bool save(QDataStream* f) const; /* Load all data contained in this class */ bool load(QDataStream* f); /* The active KPuzzleGame object this data object * belongs to */ KPuzzleGame* _owner; }; /* An instance of this class contains all game data which * does not change during a game. */ class GameData { public: /* Name of the pixmap file of this game. */ QString _filename; /* True if the pixmap should be saved into the game file when * this game is saved the next time. This substantially increases * the size of a level file, of course, and is only useful * if the game file might be used on another computer. */ bool _savePixmap; /* XXX */ QSize _originalPixmapSize; /* Annotation describing this game. May be set in the Save... * dialog. */ QString _annotation; /* Game type, as defined above */ char _gameType; /* The piece size as chosen in the "New Game" dialog, ranging * from 0 to 4. */ char _dialog_pieceSize; /* The difficulty of this game, as chosen in the game dialog, * ranging from 0 (easy) to 2 (hard). */ char _difficulty; /* XXX (may be unused) */ bool _scale; /* True if the pieces should be shaped like real jigsaw * puzzle pieces. */ bool _useMask; /* The number which has to be added to the piece size *in * every direction* to get the real size of a piece pixmap. * This is positive if and only if we are playing with * _useMask == true. */ int _displace; /* The basic size of a piece, *not* taking into account the additional * space needed for the jigsaw puzzle-like shape of the pieces. */ QSize _pieceSize; /* The number of pieces (horizontally/vertically). */ QSize _piecesCount; /* Save all data contained in this class */ bool save(QDataStream* f) const; /* Load all data contained in this class */ bool load(QDataStream* f); /* The active KPuzzleGame object this data object * belongs to */ KPuzzleGame* _owner; }; /* An instance of this class contains all game data which * does change during a game. */ class CurrentData { public: /* The pixmap of the current piece. */ QPixmap* _currentPiecePixmap; /* The CPiece structure of the current piece. */ CPiece* _currentPieceData; /* The list of pieces. A piece remains in this list * even if it has already been placed. */ QPtrList* _pieceList; /* The iterator denotes the current piece. */ QPtrListIterator* _pieceListIterator; /* Current score. */ int _score; /* Elapsed faults. */ int _faults; /* Elapsed rounds. */ int _rounds; /* False if the game has been terminated (e.g. by the signal "won", * but the game data structures are not yet destructed. */ bool _running; /* Elapsed timer ticks. */ int _elapsed; /* True if the game cannot be won any more. */ bool _dirty; /* Save all data contained in this class */ bool save(QDataStream* f) const; /* Load all data contained in this class */ bool load(QDataStream* f); /* The active KPuzzleGame object this data object * belongs to */ KPuzzleGame* _owner; }; /* This class represents exactly one game. There is only one instance of this * class (except during the process of the creation of a new game). * This class is initialized from the KPuzzleView object, which is ugly. */ class KPuzzleGame : public QObject { Q_OBJECT public: /* Constructor */ KPuzzleGame(KPuzzleView* view); /* Initialization (parts which must be done outside the * constructor). Common init function called by initializeNew/ * initializeLoad. */ bool initialize(); /* Initialization (parts which must be done outside the * constructor). This init function is called by * KPuzzleView::slotNewGame when a *new* game is created, */ bool initializeNew(); /* Initialization (parts which must be done outside the * constructor). This init function is called by * KPuzzleView::slotOpenGame when a game is opened. */ bool initializeLoad(); /* Called by the KPuzzleView object, calls initializeNew */ bool createNewGame(); /* Called by the KPuzzleView object, calls initializeLoad */ bool createLoadedGame(); /* Called from the destructor before the object is destroyed */ void done(); /* Destructor. Calls done(). */ virtual ~KPuzzleGame(); /* Initializes all game data which must not be saved */ void initGameData(); /* Calculate the number of pieces in the game. Called by initializeNew. */ void calcPiecesCount(); /* Scale the main pixmap, according to the size of the pieces. * Returns true if the size of the pixmap has changed. */ bool scalePixmap(); /* Data */ public: /* The main widget of this application. */ KPuzzleView* mainWidget() const { return _mainWidget; } /* Set the main widget. */ void setMainWidget(KPuzzleView* w) { _mainWidget = w; } /* The complete pixmap which is played with in this game. */ QPixmap* mainPixmap() const { return _mainPixmap; } /* The pixmap as the player has put it together. */ QPixmap* gamePixmap() const { return _gamePixmap; } /* XXX */ // QPixmap* largePxm() const { return _largePxm; } /* The path of the file in which this game was saved. */ QString gameFilename() const { return _gameFilename; } /* The score data of the player. */ ScoreData* scoreData() const { return _scoreData; } /* The game data (the data which does not change). */ GameData* gameData() const { return _gameData; } /* The game type (see above) */ int gameType() const { return gameData()->_gameType; } /* The size of the game pixmap */ QSize pixmapSize() const { return mainPixmap()->size(); } /* The basic size of a piece (which does *not* take * into account the additional space needed for the * jigsaw puzzle-like shape of a piece). */ QSize pieceSize() const { return gameData()->_pieceSize; } /* The piece size taking into account the additional space * needed for the jigsaw puzzle-like shape of a piece). */ QSize pieceSizeDisp() const { return pieceSize() + QSize(2 * displace(),2 * displace()); } /* Returns whether we are playing with pieces in * jigsaw puzzle-like shape. */ bool maskedPieces() const { return gameData()->_useMask; } /* The number which has to be added to the piece size *in * every direction* to get the real size of a piece pixmap. * This is positive if and only if we are playing with * _useMask == true. */ int displace() const { return gameData()->_displace; } /* Data which *does* change during the game (see above) */ CurrentData* currentData() const { return _currentData; } /* The pixmap of the current piece. */ QPixmap* currentPiecePixmap() const { return currentData()->_currentPiecePixmap; } /* The CPiece structure of the current piece. */ CPiece* currentPieceData() const { return currentData()->_currentPieceData; } /* The current piece pixmap, turned in one of the four possible * directions. The current direction is saved along with each piece, */ QPixmap* currentPieceTurned() const; /* The number of pieces (horizontally/vertically). */ QSize piecesCount() const { return gameData()->_piecesCount; } /* The total number of pieces. */ int piecesTotal() const { return piecesCount().width() * piecesCount().height(); } /* The list of pieces. */ QPtrList* pieceList() const { return currentData()->_pieceList; } /* This iterator points to the current piece * in the piece list. */ QPtrListIterator* pieceListIterator() const { return currentData()->_pieceListIterator; } /* The game status (one GS_XXX constant, * as defined above). */ int status() const { return _status; } /* True if the game is paused. */ bool paused() const { return status() == GS_PAUSED; } /* True if the game is running. */ bool running() const { return currentData()->_running; } /* The score the player has achieved in this moment. */ int score() const { return currentData()->_score; } protected: /* (Globally) elapsed timer ticks. */ int elapsed() const { return currentData()->_elapsed; } /* Sets a new score */ void setScore(int s) { currentData()->_score = s; emit sigScore(s); } /* The name of the file in which this game was saved * the last time. May be null if this game has never been * saved before. */ QString& gameFilename() { return _gameFilename; } /* Sub-widgets */ protected: /* Pointer to the central widget of this application */ KPuzzleView* _mainWidget; /* Pointer to the small picture of the puzzle pixmap * as the player has put it together until now. */ CPicview* _picview; /* Pointer to the small picture of the *complete puzzle * pixmap. */ CPicview* _fullview; /* The global game timer. Note that every piece may have got its * own timer, according to the game type. */ QTimer _timer; /* The *complete* pixmap we are trying to put together. */ QPixmap* _mainPixmap; /* XXX */ QPixmap* _gamePixmap; /* XXX */ // QPixmap* _largePxm; /* The name of the file in which this game was saved * the last time. May be null if this game has never been * saved before. */ QString _gameFilename; /* The game status (one GS_XXX constant, * as defined above). */ int _status; /* Pointer to the score data structure (see above). */ ScoreData* _scoreData; /* Pointer to the game data structure (see above). */ GameData* _gameData; /* Pointer to the current data structure (see above). */ CurrentData* _currentData; /* Implementation */ public: /* Switch to next piece. The information about the current * piece (turned in which direction, elapsed time for this piece) * will be preserved. */ bool setNextPiece(); /* Switch to previous piece. */ bool setPrevPiece(); /* Try to place a piece at the current position. If sucessful, * return true. This function seems to be able to terminate the * game. */ bool setPiece(QPoint pos); /* Called by CPiece when the time allowed for one piece * has run out. */ void hidePiece(); /* Mirror the piece on a vertical axis. */ void changeLRTurn() { currentPieceData()->turn() ^= TURN_LR; } /* Mirror the piece on a horizontal axis. */ void changeUDTurn() { currentPieceData()->turn() ^= TURN_UD; } /* Turn the piece "clockwise", in a manner that every possible * position is reached if this function is called repeatedly. */ void turnCW() { if (++(currentPieceData()->turn()) > 3) currentPieceData()->turn() = 0; } /* Turn the piece "counter-clockwise", in a manner that every possible * position is reached if this function is called repeatedly. */ void turnCCW() { if (--(currentPieceData()->turn()) < 0) currentPieceData()->turn() = 3; } /* Resize the game pixmap (the one which the player is * trying to put together) so that it has got the size * of the game window, and return the resized pixmap. */ QPixmap getLargePixmap(QSize size) const; /* Resize the main pixmap (the one which is * complete) so that it has got the size * of the game window, and return the resized pixmap. */ QPixmap getLargeMainPixmap(QSize size) const; /* Set the status of the game (one of the GS_XXX variables defined * above). Enable/disable menu entries accordingly. Show * a status line text, if necessary. */ void setStatus(int s); /* Pause the game if p is true. Resume the game if * p is false. */ void pause(bool p); /* Start the main game timer. */ void startTimer() { _timer.start(1000); } /* Return true if the main game timer is active. */ bool timerActive() const { return _timer.isActive(); } /* Stop the main game timer. */ void stopTimer() { _timer.stop(); } /* Update the entire widget. */ void updateAll(); /* Stop the game. */ void stopGame(int why) { emit sigTerm(why); } protected: /* Writes pixmap of piece pc or of the current piece to pxm * or _currentData->_currentPiecePixmap. */ void getPiecePixmap(CPiece* pc = NULL,QPixmap* pxm = NULL) const; /* Mingle pieces, create the CPiece objects and insert them into the * _pieceList. */ void minglePieces(); /* Change the score of the player. The reason is one of the SC_XXX * constants defined in kpuzzlegame.cpp. */ void changeScore(char reason); /* Show the highscore dialog. */ void showHighscoreDialog() const; /* Save this game to a file */ bool save(QDataStream* f) const; /* Load a game from a file (must be called by createLoadedGame). */ bool load(QDataStream* f); public slots: /* Slot for the "Save" menu entry. Will call slotSaveGameAs * if this game has never been saved before (i.e. there is no * default filename). */ void slotSaveGame(); /* Slot for the "Save As" menu entry. The player will be prompted for * a filename to save to. */ void slotSaveGameAs(); /* Slot for the "Terminate Game" menu entry. */ void slotStopGame() { stopGame(TM_QUIT); } /* Slot for the "Pause" menu entry. */ void slotPause(); /* Slot for the "Show large image" menu entry. */ void slotShowLarge(); /* Slot for the "Show full image" menu entry. */ void slotShowMainPixmap(); /* Slot for the timer of the current piece (necessary for * updating the time counter widget). */ void slotPieceTimer(int sec); /* Slot for the global game timer. */ void slotTimer(); /* Slot to terminate the game. */ void slotTerm(int reason); signals: void sigPiecePlaced(); void sigWinning(); void sigTerm(int); /* Emitted when this game object has "done" what it should have done * and must be destroyed. */ void sigDone(); /* This signal is emitted when the player score has changed. It is * primarily intended to change the score display on the screen. */ void sigScore(int); void sigUpdate(); }; #endif /* KPUZZLEGAME_H */