/**************************************************************************** ** ** Definition of GenericTetris, a generic class for implementing Tetris. ** ** Author : Eirik Eng ** Created : 940126 ** Modified by Nicolas Hadacek ** ** Copyright (C) 1994 by Eirik Eng. All rights reserved. ** **--------------------------------------------------------------------------- ** ** The GenericTetris class is an abstract class that can be used to implement ** the well known game of Tetris. It is totally independent of any hardware ** platform or user interface mechanism. It has no notion of time, so you ** have to supply the timer ticks (or heartbeat) of the game. Apart from ** that this is a complete Tetris implementation. ** ** In the following it is assumed that the reader is familiar with the game ** of Tetris. ** ** The class operates on a grid of squares (referred to as the "board" below), ** where each of the different types of pieces in Tetris covers 4 squares. The ** width and height of the board can be specified in the constructor (default ** is 10x22). The coordinate (0,0) is at the TOP LEFT corner. The class ** assumes that it has total control over the board and uses this to optimize ** drawing of the board. If you need to update parts of the board ** (e.g. if you are using a window system), use the updateBoard() function. ** ** An implementation of the game must subclass from TetrisBoard and must ** implement these abstract functions: ** ** virtual void drawSquare(int x,int y,int value) ** ** This function is called when a square needs to be drawn ** on the Tetris board. A value of 0 means that the square ** should be erased. Values of 1 to 7 indicate the different ** types of pieces. (Thus a minimal implementation can ** draw 0 in one way and 1-7 in a second way). The x and y ** values are coordinates on the Tetris board (see above). ** ** virtual void gameOver() ** ** This function is called when it is impossible to put a new ** piece at the top of the board. ** ** To get a working minimal implementation of Tetris the following functions ** must be called from the user interface: ** ** void startGame() ** ** Clears the board and starts a new game. ** ** void moveLeft() ** void moveRight() ** void rotateLeft() ** void rotateRight() ** ** The standard Tetris controls for moving and rotating the ** falling pieces. ** ** void dropDown(); ** ** Another Tetris control, drops the falling piece and calls the ** virtual function pieceDropped(), whose default implementation is ** to create a new block which appears at the top of the board. ** ** void oneLineDown(); ** ** This is where you supply the timer ticks, or heartbeat, of the ** game. This function moves the current falling piece one line down ** on the board, or, if that cannot be done, calls the virtual ** function pieceDropped() (see dropDown() above). The time between ** each call to this function directly affects the difficulty of the ** game. If you want to pause the game, simply block calls to the ** user control functions above and stop calling this function (you ** might want to call hideBoard() also). ** ** And that's it! There are several other public functions you can call ** and virtual functions you can overload to modify or extend the game. ** ** Do whatever you want with this code (i.e. the files gtetris.h, ** gtetris.cpp, tpiece.h and tpiece.cpp). It is basically a weekend hack ** and it would bring joy to my heart if anyone in any way would find ** it useful. ** ** Nostalgia, comments and/or praise can be sent to: Eirik.Eng@troll.no ** ****************************************************************************/ #ifndef GTETRIS_H #define GTETRIS_H #include #include #include #include class Piece; class BlockInfo; class Block; struct GTInitData { int seed; uint initLevel; }; class KDE_EXPORT GenericTetris { public: GenericTetris(uint width, uint height, bool withPieces, bool graphic); virtual ~GenericTetris(); virtual void copy(const GenericTetris &); void setBlockInfo(BlockInfo *main, BlockInfo *next); virtual void start(const GTInitData &); uint moveLeft(int steps = 1) { return moveTo(KGrid2D::Coord(-steps, 0)); } uint moveRight(int steps = 1) { return moveTo(KGrid2D::Coord(steps, 0)); } bool rotateLeft() { return rotate(true); } bool rotateRight() { return rotate(false); } virtual void oneLineDown(); virtual void dropDown(); KRandomSequence &randomSequence() { return _random; } uint score() const { return _score; } uint level() const { return _level; } uint nbClearLines() const { return _nbClearLines; } uint nbRemoved() const { return _nbRemoved; } bool graphic() const { return _graphic; } uint firstClearLine() const { return _matrix.height() - _nbClearLines; } const KGrid2D::Coord ¤tPos() const { return _currentPos; } const Piece *nextPiece() const { return _nextPiece; } const Piece *currentPiece() const { return _currentPiece; } const KGrid2D::Square &matrix() const { return _matrix; } protected: Piece *_nextPiece, *_currentPiece; virtual void pieceDropped(uint /*dropHeight*/) {} virtual bool newPiece(); // return false if cannot place new piece virtual void gluePiece(); virtual void computeInfos(); virtual void updateRemoved(uint newNbRemoved) { _nbRemoved = newNbRemoved;} virtual void updateScore(uint newScore) { _score = newScore; } virtual void updateLevel(uint newLevel) { _level = newLevel; } void setBlock(const KGrid2D::Coord &, Block *); virtual void removeBlock(const KGrid2D::Coord &); void moveBlock(const KGrid2D::Coord &src, const KGrid2D::Coord &dest); virtual void updateNextPiece() {} virtual void updatePieceConfig() {} void bumpCurrentPiece(int dec); void partialMoveBlock(const KGrid2D::Coord &, const TQPoint &dec); private: TQPoint toPoint(const KGrid2D::Coord &) const; uint moveTo(const KGrid2D::Coord &dec); bool rotate(bool left); void clear(); bool canPosition(const KGrid2D::Coord &newPos, const Piece *newPiece) const; GenericTetris(const GenericTetris &); // disabled uint _score, _level, _nbRemoved; uint _nbClearLines, _initLevel; KGrid2D::Coord _currentPos; BlockInfo *_main; bool _graphic; KGrid2D::Square _matrix; KRandomSequence _random; }; #endif