You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/libksirtet/base/gtetris.cpp

242 lines
5.7 KiB

#include "gtetris.h"
#include "piece.h"
using namespace KGrid2D;
GenericTetris::GenericTetris(uint width, uint height, bool withPieces,
bool graphic)
: _nextPiece(0), _currentPiece(0), _score(0), _nbRemoved(0),
_nbClearLines(height), _main(0),
_graphic(graphic), _matrix(width, height)
{
if (withPieces) {
_nextPiece = new Piece;
_currentPiece = new Piece;
}
_matrix.fill(0);
}
void GenericTetris::copy(const GenericTetris &g)
{
Q_ASSERT(_currentPiece);
// copy to non graphic
_score = g._score;
_level = g._level;
_nbRemoved = g._nbRemoved;
_nbClearLines = g._nbClearLines;
_currentPos = g._currentPos;
_nextPiece->copy(g._nextPiece);
_currentPiece->copy(g._currentPiece);
for (uint i=0; i<_matrix.size(); i++) {
Coord c = _matrix.coord(i);
delete _matrix[c];
if ( g._matrix[c] ) _matrix[c] = new Block(g._matrix[c]->value());
else _matrix[c] = 0;
}
}
void GenericTetris::clear()
{
_currentPos = Coord(0, -1);
for (uint i=0; i<_matrix.size(); i++) removeBlock(_matrix.coord(i));
computeInfos();
}
GenericTetris::~GenericTetris()
{
// everything should already be done by setBlockInfo(0, 0);
}
void GenericTetris::setBlockInfo(BlockInfo *main, BlockInfo *next)
{
Q_ASSERT( _graphic );
if (main) {
_main = main;
if (_currentPiece) {
Q_ASSERT(next);
_nextPiece->setBlockInfo(next);
_currentPiece->setBlockInfo(main);
}
} else { // before destruction
clear();
delete _currentPiece;
delete _nextPiece;
}
}
void GenericTetris::start(const GTInitData &data)
{
Q_ASSERT( _graphic );
_random.setSeed(data.seed);
_initLevel = data.initLevel;
updateScore(0);
updateLevel(_initLevel);
updateRemoved(0);
clear();
if (_nextPiece) {
_nextPiece->setRandomSequence(&_random);
_nextPiece->generateNext();
newPiece();
}
}
void GenericTetris::dropDown()
{
uint dropHeight = moveTo(Coord(0, -_currentPos.second));
pieceDropped(dropHeight);
}
void GenericTetris::oneLineDown()
{
if ( moveTo(Coord(0, -1))==0 ) pieceDropped(0);
}
bool GenericTetris::newPiece()
{
Q_ASSERT(_currentPiece);
Coord min = _nextPiece->min();
_currentPos.second = _matrix.height() - 1 + min.second;
_currentPos.first = (_matrix.width() - _nextPiece->size().first)/2
- min.first;
if ( !canPosition(_currentPos, _nextPiece)) {
_currentPos.second = -1;
return false;
}
_currentPiece->copy(_nextPiece);
if (_graphic) {
_currentPiece->move(toPoint(_currentPos));
_currentPiece->show(true);
updatePieceConfig();
}
_nextPiece->generateNext();
if (_graphic) {
_nextPiece->moveCenter();
_nextPiece->show(true);
updateNextPiece();
}
return true;
}
bool GenericTetris::canPosition(const Coord &pos, const Piece *piece) const
{
for(uint k=0; k<piece->nbBlocks(); k++) {
Coord c(piece->pos(k, pos));
if ( !_matrix.inside(c) || _matrix[c]!=0 )
return false; // outside or something in the way
}
return true;
}
uint GenericTetris::moveTo(const Coord &dec)
{
Q_ASSERT(_currentPiece);
Q_ASSERT(dec.first==0 || dec.second==0);
Coord newPos = _currentPos;
Coord d(0, 0);
uint n, i;
if (dec.first) {
d.first = (dec.first<0 ? -1 : 1);
n = kAbs(dec.first);
} else {
d.second = (dec.second<0 ? -1 : 1);
n = kAbs(dec.second);
}
for (i=0; i<n; i++) {
if ( !canPosition(newPos + d, _currentPiece) ) break;
newPos = newPos + d;
}
if ( i!=0 ) { // piece can be moved
_currentPos = newPos;
if (_graphic) {
_currentPiece->move(toPoint(newPos));
updatePieceConfig();
}
}
return i;
}
bool GenericTetris::rotate(bool left)
{
Q_ASSERT(_currentPiece);
Piece tmp;
tmp.copy(_currentPiece);
TQPoint p(0, 0);
tmp.rotate(left, p);
if ( canPosition(_currentPos, &tmp) ) {
if (_graphic) p = toPoint(_currentPos);
_currentPiece->rotate(left, p);
if (_graphic) updatePieceConfig();
return true;
}
return false;
}
void GenericTetris::computeInfos()
{
_nbClearLines = 0;
for (uint j=_matrix.height(); j>0; j--) {
for (uint i=0; i<_matrix.width(); i++)
if ( _matrix[Coord(i, j-1)]!=0 ) return;
_nbClearLines++;
}
}
void GenericTetris::setBlock(const Coord &c, Block *b)
{
Q_ASSERT( b && _matrix[c]==0 );
_matrix[c] = b;
if (_graphic) {
TQPoint p = toPoint(c);
b->sprite()->move(p.x(), p.y());
}
}
void GenericTetris::removeBlock(const Coord &c)
{
delete _matrix[c];
_matrix[c] = 0;
}
void GenericTetris::moveBlock(const Coord &src, const Coord &dest)
{
Q_ASSERT( _matrix[dest]==0 );
if ( _matrix[src] ) {
setBlock(dest, _matrix[src]);
_matrix[src] = 0;
}
}
TQPoint GenericTetris::toPoint(const Coord &c) const
{
return _main->toPoint(Coord(c.first, _matrix.height() - 1 - c.second));
}
void GenericTetris::gluePiece()
{
Q_ASSERT(_currentPiece);
for(uint k=0; k<_currentPiece->nbBlocks(); k++)
setBlock(_currentPiece->pos(k, _currentPos),
_currentPiece->takeBlock(k));
computeInfos();
}
void GenericTetris::bumpCurrentPiece(int dec)
{
Q_ASSERT( _graphic && _currentPiece );
_currentPiece->move(toPoint(_currentPos) + TQPoint(0, dec));
}
void GenericTetris::partialMoveBlock(const Coord &c, const TQPoint &dec)
{
Q_ASSERT( _graphic && _matrix[c]!=0 );
TQPoint p = toPoint(c) + dec;
_matrix[c]->sprite()->move(p.x(), p.y());
}