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.
755 lines
17 KiB
755 lines
17 KiB
15 years ago
|
/***************************************************************************
|
||
|
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 <qpainter.h>
|
||
|
#include <qcolor.h>
|
||
|
#include <qcursor.h>
|
||
|
#include <qkeycode.h>
|
||
|
#include <qtooltip.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, QWidget* 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( NoFocus );
|
||
|
setBackgroundColor( gray );
|
||
|
|
||
|
setMouseTracking( FALSE );
|
||
|
setFixedSize(wHint(), hHint());
|
||
|
|
||
|
timer = new QTimer(this);
|
||
|
connect( timer, SIGNAL(timeout()), 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( QPaintEvent* )
|
||
|
{
|
||
|
QPainter *paint;
|
||
|
KPixmap *pixmap = 0;
|
||
|
if (bGameOver)
|
||
|
{
|
||
|
pixmap = new KPixmap();
|
||
|
pixmap->resize(width(), height());
|
||
|
paint = new QPainter( pixmap );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
paint = new QPainter( 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, Qt::black);
|
||
|
|
||
|
QPainter p(this);
|
||
|
p.drawPixmap(0,0, *pixmap);
|
||
|
delete pixmap;
|
||
|
|
||
|
QFont gameover_font = font();
|
||
|
gameover_font.setPointSize(48);
|
||
|
gameover_font.setBold(true);
|
||
|
p.setFont(gameover_font);
|
||
|
p.setPen(Qt::white);
|
||
|
QString gameover_text = i18n("Game Over");
|
||
|
p.drawText(0, 0, width(), height(), AlignCenter|Qt::WordBreak, gameover_text);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ((focusX >= 0) && (focusX < NUMCELLSW) &&
|
||
|
(focusY >= 0) && (focusY < NUMCELLSH))
|
||
|
{
|
||
|
QRect r;
|
||
|
r.setX(focusX*CELLSIZE+2);
|
||
|
r.setY(focusY*CELLSIZE+2);
|
||
|
r.setWidth(CELLSIZE-4);
|
||
|
r.setHeight(CELLSIZE-4);
|
||
|
paint->setPen(QPen(Qt::DotLine));
|
||
|
paint->drawRect(r);
|
||
|
}
|
||
|
}
|
||
|
delete paint;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Handles mouse press events for the LinesBoard widget.
|
||
|
*/
|
||
|
void LinesBoard::mousePressEvent( QMouseEvent* 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 QString &text)
|
||
|
{
|
||
|
if (!demoLabel)
|
||
|
{
|
||
|
demoLabel = new QLabel(0, "demoTip", WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM );
|
||
|
demoLabel->setMargin(1);
|
||
|
demoLabel->setIndent(0);
|
||
|
demoLabel->setAutoMask( FALSE );
|
||
|
demoLabel->setFrameStyle( QFrame::Plain | QFrame::Box );
|
||
|
demoLabel->setLineWidth( 1 );
|
||
|
demoLabel->setAlignment( AlignHCenter | AlignTop );
|
||
|
demoLabel->setPalette(QToolTip::palette());
|
||
|
demoLabel->polish();
|
||
|
}
|
||
|
demoLabel->setText(text);
|
||
|
demoLabel->adjustSize();
|
||
|
QSize s = demoLabel->sizeHint();
|
||
|
QPoint p = QPoint(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)
|
||
|
{
|
||
|
QPoint lDest = QPoint(x*CELLSIZE+(CELLSIZE/2), y*CELLSIZE+(CELLSIZE/2));
|
||
|
QPoint dest = mapToGlobal(lDest);
|
||
|
QPoint cur = QCursor::pos();
|
||
|
for(int i = 0; i < 25;)
|
||
|
{
|
||
|
i++;
|
||
|
QPoint p = cur + i*(dest-cur) / 25;
|
||
|
QCursor::setPos(p);
|
||
|
QApplication::flushX();
|
||
|
QTimer::singleShot(80, this, SLOT(demoClickStep()));
|
||
|
kapp->enter_loop();
|
||
|
}
|
||
|
QCursor::setPos(dest);
|
||
|
QMouseEvent ev(QEvent::MouseButtonPress, lDest, dest, LeftButton, LeftButton);
|
||
|
mousePressEvent(&ev);
|
||
|
}
|
||
|
|
||
|
void LinesBoard::demoClickStep()
|
||
|
{
|
||
|
kapp->exit_loop();
|
||
|
}
|