|
|
|
/***************************************************************************
|
|
|
|
begin : Fri May 19 2000
|
|
|
|
copyright : (C) 2000 by Roman Merzlyakov
|
|
|
|
email : roman@sbrf.barrt.ru
|
|
|
|
copyright : (C) 2000 by Roman Razilov
|
|
|
|
email : Roman.Razilov@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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqcolor.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqkeycode.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kpixmap.h>
|
|
|
|
#include <kpixmapeffect.h>
|
|
|
|
|
|
|
|
#include "linesboard.h"
|
|
|
|
#include "linesboard.moc"
|
|
|
|
|
|
|
|
/*
|
|
|
|
Constructs a LinesBoard widget.
|
|
|
|
*/
|
|
|
|
|
|
|
|
LinesBoard::LinesBoard( BallPainter * abPainter, TQWidget* parent, const char* name )
|
|
|
|
: Field( parent, name )
|
|
|
|
{
|
|
|
|
demoLabel = 0;
|
|
|
|
bGameOver = false;
|
|
|
|
anim = ANIM_NO;
|
|
|
|
focusX = -1;
|
|
|
|
focusY = -1;
|
|
|
|
// waypos = 0;
|
|
|
|
// waylen = 0;
|
|
|
|
// jumpingRow = -1;
|
|
|
|
// jumpingCol = -1;
|
|
|
|
painting = 0;
|
|
|
|
way = new Waypoints[NUMCELLSW*NUMCELLSH];
|
|
|
|
|
|
|
|
bPainter = abPainter;
|
|
|
|
|
|
|
|
setFocusPolicy( TQ_NoFocus );
|
|
|
|
setBackgroundColor( gray );
|
|
|
|
|
|
|
|
setMouseTracking( FALSE );
|
|
|
|
setFixedSize(wHint(), hHint());
|
|
|
|
|
|
|
|
timer = new TQTimer(this);
|
|
|
|
connect( timer, TQT_SIGNAL(timeout()), TQT_SLOT(timerSlot()) );
|
|
|
|
timer->start( TIMERCLOCK, FALSE );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Destructor: deallocates memory for contents
|
|
|
|
*/
|
|
|
|
|
|
|
|
LinesBoard::~LinesBoard()
|
|
|
|
{
|
|
|
|
timer->stop();
|
|
|
|
delete timer;
|
|
|
|
delete [] way;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::startDemoMode()
|
|
|
|
{
|
|
|
|
level = DEMO_LEVEL;
|
|
|
|
rnd_demo = KRandomSequence(DEMO_SEQUENCE);
|
|
|
|
bAllowMove = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::adjustDemoMode(bool allowMove, bool off)
|
|
|
|
{
|
|
|
|
bAllowMove = allowMove;
|
|
|
|
if (off)
|
|
|
|
level = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::demoAdjust(int a)
|
|
|
|
{
|
|
|
|
rnd_demo.modulate(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LinesBoard::placeBalls(int pnextBalls[BALLSDROP])
|
|
|
|
{
|
|
|
|
for(int i=0; i < BALLSDROP; i++)
|
|
|
|
nextBalls[i] = pnextBalls[i];
|
|
|
|
|
|
|
|
nextBallToPlace = 0;
|
|
|
|
placeBall();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::placeBall( )
|
|
|
|
{
|
|
|
|
char* xx = (char*)malloc( sizeof(char)*NUMCELLSW*NUMCELLSH );
|
|
|
|
char* yy = (char*)malloc( sizeof(char)*NUMCELLSW*NUMCELLSH );
|
|
|
|
int empty = 0;
|
|
|
|
for(int y=0; y<NUMCELLSH; y++)
|
|
|
|
for(int x=0; x<NUMCELLSW; x++)
|
|
|
|
if( getBall(x,y) == NOBALL )
|
|
|
|
{
|
|
|
|
xx[empty] = x;
|
|
|
|
yy[empty] = y;
|
|
|
|
empty++;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (empty)
|
|
|
|
{
|
|
|
|
int color = nextBalls[nextBallToPlace];
|
|
|
|
int pos = 0;
|
|
|
|
if ((level == DEMO_LEVEL) || (level == 0))
|
|
|
|
{
|
|
|
|
pos = random(empty);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int best_pos = 0;
|
|
|
|
int best_score = level > 0 ? 1000: -1000;
|
|
|
|
int maxtry = level > 0 ? level+1 : 1-level;
|
|
|
|
for(int i=0;i<maxtry;i++)
|
|
|
|
{
|
|
|
|
int pos = random(empty);
|
|
|
|
int score = calcPosScore(xx[pos], yy[pos], color) - calcPosScore(xx[pos], yy[pos], NOBALL);
|
|
|
|
if (((level > 0) && (score < best_score)) ||
|
|
|
|
((level < 0) && (score > best_score)))
|
|
|
|
{
|
|
|
|
best_pos = pos;
|
|
|
|
best_score = score;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = best_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
putBall( xx[pos], yy[pos], color );
|
|
|
|
clearAnim();
|
|
|
|
setAnim( xx[pos], yy[pos], ANIM_BORN );
|
|
|
|
nextBallToPlace++;
|
|
|
|
AnimStart(ANIM_BORN);
|
|
|
|
free(xx);
|
|
|
|
free(yy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free(xx);
|
|
|
|
free(yy);
|
|
|
|
emit endGame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*id LinesBoard::doAfterBalls() {
|
|
|
|
erase5Balls();
|
|
|
|
repaint(FALSE);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
Sets the size of the table
|
|
|
|
*/
|
|
|
|
|
|
|
|
int LinesBoard::width() { return CELLSIZE * NUMCELLSW; }
|
|
|
|
int LinesBoard::height() { return CELLSIZE * NUMCELLSH; }
|
|
|
|
int LinesBoard::wHint() { return width(); }
|
|
|
|
int LinesBoard::hHint() { return height(); }
|
|
|
|
|
|
|
|
void LinesBoard::setGameOver(bool b)
|
|
|
|
{
|
|
|
|
bGameOver = b;
|
|
|
|
focusX = -1;
|
|
|
|
focusY = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LinesBoard::paintEvent( TQPaintEvent* )
|
|
|
|
{
|
|
|
|
TQPainter *paint;
|
|
|
|
KPixmap *pixmap = 0;
|
|
|
|
if (bGameOver)
|
|
|
|
{
|
|
|
|
pixmap = new KPixmap();
|
|
|
|
pixmap->resize(width(), height());
|
|
|
|
paint = new TQPainter( pixmap );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
paint = new TQPainter( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int y=0; y < NUMCELLSH; y++ ){
|
|
|
|
for( int x=0; x < NUMCELLSW; x++ ){
|
|
|
|
if( getBall(x,y) == NOBALL )
|
|
|
|
{
|
|
|
|
paint->drawPixmap(x*CELLSIZE, y*CELLSIZE, bPainter->GetBackgroundPix() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
paint->drawPixmap(x*CELLSIZE, y*CELLSIZE,
|
|
|
|
bPainter->GetBall(getBall(x,y),animstep,getAnim(x,y)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bGameOver)
|
|
|
|
{
|
|
|
|
paint->end();
|
|
|
|
|
|
|
|
KPixmapEffect::fade(*pixmap, 0.5, TQt::black);
|
|
|
|
|
|
|
|
TQPainter p(this);
|
|
|
|
p.drawPixmap(0,0, *pixmap);
|
|
|
|
delete pixmap;
|
|
|
|
|
|
|
|
TQFont gameover_font = font();
|
|
|
|
gameover_font.setPointSize(48);
|
|
|
|
gameover_font.setBold(true);
|
|
|
|
p.setFont(gameover_font);
|
|
|
|
p.setPen(TQt::white);
|
|
|
|
TQString gameover_text = i18n("Game Over");
|
|
|
|
p.drawText(0, 0, width(), height(), AlignCenter|TQt::WordBreak, gameover_text);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((focusX >= 0) && (focusX < NUMCELLSW) &&
|
|
|
|
(focusY >= 0) && (focusY < NUMCELLSH))
|
|
|
|
{
|
|
|
|
TQRect r;
|
|
|
|
r.setX(focusX*CELLSIZE+2);
|
|
|
|
r.setY(focusY*CELLSIZE+2);
|
|
|
|
r.setWidth(CELLSIZE-4);
|
|
|
|
r.setHeight(CELLSIZE-4);
|
|
|
|
paint->setPen(TQPen(TQt::DotLine));
|
|
|
|
paint->drawRect(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete paint;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Handles mouse press events for the LinesBoard widget.
|
|
|
|
*/
|
|
|
|
void LinesBoard::mousePressEvent( TQMouseEvent* e )
|
|
|
|
{
|
|
|
|
if (bGameOver) return;
|
|
|
|
if ((level == DEMO_LEVEL) && (!bAllowMove) && e->spontaneous()) return;
|
|
|
|
|
|
|
|
int curRow = e->y() / CELLSIZE;
|
|
|
|
int curCol = e->x() / CELLSIZE;
|
|
|
|
|
|
|
|
placePlayerBall(curCol, curRow);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::placePlayerBall(int curCol, int curRow)
|
|
|
|
{
|
|
|
|
//check range
|
|
|
|
if (!checkBounds( curCol, curRow ) )
|
|
|
|
return;
|
|
|
|
// if( running || anim != ANIM_NO ) return;
|
|
|
|
if(anim != ANIM_JUMP && anim != ANIM_NO) return;
|
|
|
|
if ( anim == ANIM_JUMP )
|
|
|
|
{
|
|
|
|
if ( getBall(curCol,curRow) == NOBALL )
|
|
|
|
{
|
|
|
|
if(existPath(jumpingCol, jumpingRow, curCol, curRow))
|
|
|
|
{
|
|
|
|
saveRandomState();
|
|
|
|
rnd.modulate(jumpingCol);
|
|
|
|
rnd.modulate(jumpingRow);
|
|
|
|
rnd.modulate(curCol);
|
|
|
|
rnd.modulate(curRow);
|
|
|
|
saveUndo();
|
|
|
|
AnimStart(ANIM_RUN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
AnimJump(curCol,curRow);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
AnimJump(curCol,curRow);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Move focus thingy
|
|
|
|
*/
|
|
|
|
void LinesBoard::moveFocus(int dx, int dy)
|
|
|
|
{
|
|
|
|
if (bGameOver) return;
|
|
|
|
if ((level == DEMO_LEVEL) && (!bAllowMove)) return;
|
|
|
|
if (focusX == -1)
|
|
|
|
{
|
|
|
|
focusX = 0;
|
|
|
|
focusY = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
focusX = (focusX + dx + NUMCELLSW) % NUMCELLSW;
|
|
|
|
focusY = (focusY + dy + NUMCELLSH) % NUMCELLSH;
|
|
|
|
}
|
|
|
|
repaint(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::moveLeft()
|
|
|
|
{
|
|
|
|
moveFocus(-1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::moveRight()
|
|
|
|
{
|
|
|
|
moveFocus(1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::moveUp()
|
|
|
|
{
|
|
|
|
moveFocus(0, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::moveDown()
|
|
|
|
{
|
|
|
|
moveFocus(0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::placePlayerBall()
|
|
|
|
{
|
|
|
|
if (bGameOver) return;
|
|
|
|
if ((level == DEMO_LEVEL) && (!bAllowMove)) return;
|
|
|
|
placePlayerBall(focusX, focusY);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::AnimJump(int x, int y ) {
|
|
|
|
if ( getBall(x,y) != NOBALL )
|
|
|
|
if (!( anim == ANIM_JUMP && jumpingCol == x && jumpingRow == y ))
|
|
|
|
if ( AnimEnd() )
|
|
|
|
{
|
|
|
|
clearAnim();
|
|
|
|
setAnim(x,y,ANIM_JUMP);
|
|
|
|
jumpingCol = x;
|
|
|
|
jumpingRow = y;
|
|
|
|
AnimStart(ANIM_JUMP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void LinesBoard::AnimStart(int panim) {
|
|
|
|
if (anim != ANIM_NO)
|
|
|
|
AnimEnd();
|
|
|
|
animstep = 0;
|
|
|
|
animdelaystart = 1;
|
|
|
|
switch(panim) {
|
|
|
|
case ANIM_NO:
|
|
|
|
break;
|
|
|
|
case ANIM_BORN:
|
|
|
|
animdelaystart=1;
|
|
|
|
animmax = BOOMBALLS;
|
|
|
|
break;
|
|
|
|
case ANIM_JUMP:
|
|
|
|
direction = -1;
|
|
|
|
animstep = 4;
|
|
|
|
animmax = PIXTIME -1;
|
|
|
|
break;
|
|
|
|
case ANIM_RUN:
|
|
|
|
animdelaystart=3;
|
|
|
|
// do first step on next timer;
|
|
|
|
animdelaycount = 0;
|
|
|
|
// animmax already set
|
|
|
|
break;
|
|
|
|
case ANIM_BURN:
|
|
|
|
animdelaystart=1;
|
|
|
|
animmax = FIREBALLS + FIREPIX - 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
anim = panim;
|
|
|
|
animdelaycount = animdelaystart;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LinesBoard::AnimEnd( )
|
|
|
|
{
|
|
|
|
if (anim == ANIM_NO ) return true;
|
|
|
|
int oldanim = anim;
|
|
|
|
anim = ANIM_NO;
|
|
|
|
if (oldanim == ANIM_RUN) {
|
|
|
|
if (animstep != animmax) {
|
|
|
|
moveBall(way[animstep].x,way[animstep].y,way[animmax].x,way[animmax].y);
|
|
|
|
}
|
|
|
|
if ( erase5Balls() == 0 ) {
|
|
|
|
emit endTurn();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( oldanim == ANIM_BURN )
|
|
|
|
{
|
|
|
|
emit eraseLine( deleteAnimatedBalls() );
|
|
|
|
repaint(FALSE);
|
|
|
|
if ( nextBallToPlace < BALLSDROP )
|
|
|
|
{
|
|
|
|
placeBall();
|
|
|
|
// continue with born
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
emit userTurn();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( oldanim == ANIM_BORN )
|
|
|
|
{
|
|
|
|
if ( erase5Balls() == 0 )
|
|
|
|
{
|
|
|
|
if ( freeSpace() > 0)
|
|
|
|
{
|
|
|
|
if ( nextBallToPlace < BALLSDROP )
|
|
|
|
{
|
|
|
|
placeBall();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
emit userTurn();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
emit endGame();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// wait for user input
|
|
|
|
emit userTurn();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
emit userTurn();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::AnimNext() {
|
|
|
|
if ( anim != ANIM_NO )
|
|
|
|
{
|
|
|
|
if ( anim == ANIM_JUMP ) {
|
|
|
|
if ( (direction > 0 && animstep == animmax) || ( direction < 0 && animstep == 0))
|
|
|
|
direction = -direction;
|
|
|
|
animstep += direction;
|
|
|
|
repaint(FALSE);
|
|
|
|
} else {
|
|
|
|
if ( animstep >= animmax )
|
|
|
|
AnimEnd();
|
|
|
|
else {
|
|
|
|
animdelaycount--;
|
|
|
|
if (animdelaycount <= 0) {
|
|
|
|
if ( anim == ANIM_RUN )
|
|
|
|
moveBall(way[animstep].x,way[animstep].y,way[animstep+1].x,way[animstep+1].y);
|
|
|
|
animstep++;
|
|
|
|
animdelaycount = animdelaystart;
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int LinesBoard::getAnim( int x, int y )
|
|
|
|
{
|
|
|
|
return (( Field::getAnim(x,y) != ANIM_NO )? anim : ANIM_NO);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::timerSlot()
|
|
|
|
{
|
|
|
|
AnimNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
int LinesBoard::erase5Balls()
|
|
|
|
{
|
|
|
|
int nb=5; // minimum balls for erasure
|
|
|
|
|
|
|
|
bool bit_erase[NUMCELLSH][NUMCELLSW]; //bool array for balls, that must be erased
|
|
|
|
for(int y=0; y<NUMCELLSH; y++)
|
|
|
|
for(int x=0; x<NUMCELLSW; x++)
|
|
|
|
bit_erase[y][x] = false;
|
|
|
|
|
|
|
|
int color,newcolor;
|
|
|
|
int count;
|
|
|
|
//for horisontal
|
|
|
|
|
|
|
|
for(int y=0; y<NUMCELLSH; y++) {
|
|
|
|
count = 1;
|
|
|
|
color = NOBALL;
|
|
|
|
for(int x=0; x<NUMCELLSW; x++){
|
|
|
|
if ( (newcolor = getBall(x,y)) == color) {
|
|
|
|
if ( color != NOBALL) {
|
|
|
|
count++;
|
|
|
|
if ( count >= nb )
|
|
|
|
if ( count == nb )
|
|
|
|
for (int i = 0; i < nb; i++)
|
|
|
|
bit_erase[y][x-i] = true;
|
|
|
|
else bit_erase[y][x] = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
color = newcolor;
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//for vertical
|
|
|
|
for(int x=0; x<NUMCELLSW; x++) {
|
|
|
|
count = 0;
|
|
|
|
color = NOBALL;
|
|
|
|
for(int y=0; y<NUMCELLSH; y++){
|
|
|
|
if ( (newcolor = getBall(x,y)) == color) {
|
|
|
|
if ( color != NOBALL) {
|
|
|
|
count++;
|
|
|
|
if ( count >= nb )
|
|
|
|
if ( count == nb )
|
|
|
|
for (int i = 0; i < nb; i++)
|
|
|
|
bit_erase[y-i][x] = true;
|
|
|
|
else bit_erase[y][x] = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
color = newcolor;
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//for left-down to rigth-up diagonal
|
|
|
|
for ( int xs = NUMCELLSW-1,ys = NUMCELLSH-nb; xs >= nb-1; ) {
|
|
|
|
count = 0;
|
|
|
|
color = NOBALL;
|
|
|
|
for ( int x = xs, y = ys; x >= 0 && y < NUMCELLSH; x--, y++ ) {
|
|
|
|
if ( (newcolor = getBall(x,y)) == color) {
|
|
|
|
if ( color != NOBALL) {
|
|
|
|
count++;
|
|
|
|
if ( count >= nb )
|
|
|
|
if ( count == nb )
|
|
|
|
for (int i = 0; i < nb; i++)
|
|
|
|
bit_erase[y-i][x+i] = true;
|
|
|
|
else bit_erase[y][x] = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
color = newcolor;
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( ys > 0 ) ys--; else xs--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//for left-up to rigth-down diagonal
|
|
|
|
for ( int xs = 0,ys = NUMCELLSH-nb; xs <= NUMCELLSW-nb; )
|
|
|
|
{
|
|
|
|
count = 0;
|
|
|
|
color = NOBALL;
|
|
|
|
for ( int x = xs, y = ys; x < NUMCELLSW && y < NUMCELLSH; x++, y++ )
|
|
|
|
{
|
|
|
|
if ( (newcolor = getBall(x,y)) == color)
|
|
|
|
{
|
|
|
|
if ( color != NOBALL)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
if ( count >= nb )
|
|
|
|
if ( count == nb )
|
|
|
|
for (int i = 0; i < nb; i++)
|
|
|
|
bit_erase[y-i][x-i] = true;
|
|
|
|
else
|
|
|
|
bit_erase[y][x] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
color = newcolor;
|
|
|
|
count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( ys > 0 ) ys--; else xs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//remove all lines balls, that more than nb
|
|
|
|
int cb=0;
|
|
|
|
for(int y=0; y < NUMCELLSH; y++)
|
|
|
|
for(int x=0; x < NUMCELLSW; x++)
|
|
|
|
{
|
|
|
|
if (bit_erase[y][x])
|
|
|
|
{
|
|
|
|
setAnim(x,y,ANIM_YES);
|
|
|
|
cb++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setAnim(x,y,ANIM_NO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( cb > 0 )
|
|
|
|
{
|
|
|
|
AnimStart(ANIM_BURN);
|
|
|
|
//emit eraseLine(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define GO_EMPTY 4
|
|
|
|
#define GO_A 5
|
|
|
|
#define GO_B 6
|
|
|
|
#define GO_BALL 7
|
|
|
|
|
|
|
|
bool LinesBoard::existPath(int bx, int by, int ax, int ay)
|
|
|
|
{
|
|
|
|
int dx[4]={1,-1, 0, 0};
|
|
|
|
int dy[4]={0, 0, 1,-1};
|
|
|
|
|
|
|
|
if (getBall(ax,ay) != NOBALL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
char pf[NUMCELLSH][NUMCELLSW];
|
|
|
|
for(int y=0; y<NUMCELLSH; y++)
|
|
|
|
for(int x=0; x<NUMCELLSW; x++)
|
|
|
|
pf[y][x] = (getBall(x,y) == NOBALL) ? GO_EMPTY:GO_BALL;
|
|
|
|
|
|
|
|
Waypoints lastchanged[2][NUMCELLSH*NUMCELLSW];
|
|
|
|
|
|
|
|
int lastChangedCount[2];
|
|
|
|
int currentchanged = 0;
|
|
|
|
int nextchanged = 1;
|
|
|
|
lastchanged[currentchanged][0].x = ax;
|
|
|
|
lastchanged[currentchanged][0].y = ay;
|
|
|
|
lastChangedCount[currentchanged] = 1;
|
|
|
|
pf[ay][ax]=GO_A;
|
|
|
|
pf[by][bx]=GO_B;
|
|
|
|
|
|
|
|
// int expanded;
|
|
|
|
bool B_reached = false;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
lastChangedCount[nextchanged] = 0;
|
|
|
|
for(int dir=0; dir<4; dir++)
|
|
|
|
{
|
|
|
|
for ( int i = 0 ; i < lastChangedCount[currentchanged]; i++ )
|
|
|
|
{
|
|
|
|
int nx = lastchanged[currentchanged][i].x + dx[dir];
|
|
|
|
int ny = lastchanged[currentchanged][i].y + dy[dir];
|
|
|
|
if( (nx>=0) && (nx<NUMCELLSW) && (ny>=0) && (ny<NUMCELLSH) )
|
|
|
|
{
|
|
|
|
if( pf[ny][nx]==GO_EMPTY ||( nx==bx && ny==by ))
|
|
|
|
{
|
|
|
|
pf[ny][nx] = dir;
|
|
|
|
lastchanged[nextchanged][lastChangedCount[nextchanged]].x = nx;
|
|
|
|
lastchanged[nextchanged][lastChangedCount[nextchanged]].y = ny;
|
|
|
|
lastChangedCount[nextchanged]++;
|
|
|
|
};
|
|
|
|
if( (nx==bx) && (ny==by) )
|
|
|
|
{
|
|
|
|
B_reached = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nextchanged = nextchanged ^ 1;
|
|
|
|
currentchanged = nextchanged ^ 1;
|
|
|
|
// currentchanged,lastChangedCount[currentchanged]);
|
|
|
|
} while(!B_reached && lastChangedCount[currentchanged] != 0);
|
|
|
|
|
|
|
|
if (B_reached) {
|
|
|
|
AnimStart( ANIM_BLOCK);
|
|
|
|
animmax = 0;
|
|
|
|
// waypos = 0;
|
|
|
|
int x, y,dir;
|
|
|
|
for( x = bx, y = by; (dir = pf[y][x]) != GO_A;x -=dx[dir],y -= dy[dir]) {
|
|
|
|
way[animmax].x = x;
|
|
|
|
way[animmax].y = y;
|
|
|
|
animmax++;
|
|
|
|
}
|
|
|
|
way[animmax].x = x;
|
|
|
|
way[animmax].y = y;
|
|
|
|
}
|
|
|
|
return B_reached;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::undo()
|
|
|
|
{
|
|
|
|
AnimEnd();
|
|
|
|
restoreUndo();
|
|
|
|
restoreRandomState();
|
|
|
|
repaint( FALSE );
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::showDemoText(const TQString &text)
|
|
|
|
{
|
|
|
|
if (!demoLabel)
|
|
|
|
{
|
|
|
|
demoLabel = new TQLabel(0, "demoTip", WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM );
|
|
|
|
demoLabel->setMargin(1);
|
|
|
|
demoLabel->setIndent(0);
|
|
|
|
demoLabel->setAutoMask( FALSE );
|
|
|
|
demoLabel->setFrameStyle( TQFrame::Plain | TQFrame::Box );
|
|
|
|
demoLabel->setLineWidth( 1 );
|
|
|
|
demoLabel->setAlignment( AlignHCenter | AlignTop );
|
|
|
|
demoLabel->setPalette(TQToolTip::palette());
|
|
|
|
demoLabel->polish();
|
|
|
|
}
|
|
|
|
demoLabel->setText(text);
|
|
|
|
demoLabel->adjustSize();
|
|
|
|
TQSize s = demoLabel->sizeHint();
|
|
|
|
TQPoint p = TQPoint(x() + (width()-s.width())/2, y() + (height()-s.height())/2);
|
|
|
|
demoLabel->move(mapToGlobal(p));
|
|
|
|
demoLabel->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::hideDemoText()
|
|
|
|
{
|
|
|
|
if (demoLabel)
|
|
|
|
demoLabel->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::demoClick(int x, int y)
|
|
|
|
{
|
|
|
|
TQPoint lDest = TQPoint(x*CELLSIZE+(CELLSIZE/2), y*CELLSIZE+(CELLSIZE/2));
|
|
|
|
TQPoint dest = mapToGlobal(lDest);
|
|
|
|
TQPoint cur = TQCursor::pos();
|
|
|
|
for(int i = 0; i < 25;)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
TQPoint p = cur + i*(dest-cur) / 25;
|
|
|
|
TQCursor::setPos(p);
|
|
|
|
TQApplication::flushX();
|
|
|
|
TQTimer::singleShot(80, this, TQT_SLOT(demoClickStep()));
|
|
|
|
kapp->enter_loop();
|
|
|
|
}
|
|
|
|
TQCursor::setPos(dest);
|
|
|
|
TQMouseEvent ev(TQEvent::MouseButtonPress, lDest, dest, Qt::LeftButton, Qt::LeftButton);
|
|
|
|
mousePressEvent(&ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LinesBoard::demoClickStep()
|
|
|
|
{
|
|
|
|
kapp->exit_loop();
|
|
|
|
}
|