00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <qpainter.h>
00020 #include <stdlib.h>
00021
00022 #include "linesboard.h"
00023
00024
00025
00026
00027
00028 LinesBoard::LinesBoard( BallPainter * abPainter, QWidget* parent, const char* name )
00029 : Field( parent, name )
00030 {
00031 anim = ANIM_NO;
00032
00033
00034
00035
00036 painting = 0;
00037 way = new Waypoints[NUMCELLSW*NUMCELLSH];
00038
00039 bPainter = abPainter;
00040
00041 setFocusPolicy( NoFocus );
00042 setBackgroundColor( gray );
00043
00044 setMouseTracking( FALSE );
00045 setFixedSize(wHint(), hHint());
00046
00047 timer = new QTimer(this);
00048 connect( timer, SIGNAL(timeout()), SLOT(timerSlot()) );
00049 timer->start( TIMERCLOCK, FALSE );
00050
00051 }
00052
00053
00054
00055
00056
00057 LinesBoard::~LinesBoard()
00058 {
00059
00060 timer->stop();
00061 delete timer;
00062 delete []way;
00063 }
00064
00065
00066 void LinesBoard::placeBalls(int pnextBalls[BALLSDROP])
00067 {
00068 debug("LinesBoard::placeBalls( )");
00069 for(int i=0; i < BALLSDROP; i++){
00070 nextBalls[i] = pnextBalls[i];
00071 }
00072 nextBallToPlace = 0;
00073 placeBall();
00074 debug("LinesBoard::placeBalls End ");
00075 }
00076 void LinesBoard::placeBall( )
00077 {
00078 int color = nextBalls[nextBallToPlace];
00079 debug("LinesBoard::placeBall( ) color=%i, nextBallToPlace = %i", color, nextBallToPlace);
00080 char* xx = (char*)malloc( sizeof(char)*NUMCELLSW*NUMCELLSH );
00081 char* yy = (char*)malloc( sizeof(char)*NUMCELLSW*NUMCELLSH );
00082
00083
00084 int empty=0;
00085 for(int y=0; y<NUMCELLSH; y++)
00086 for(int x=0; x<NUMCELLSW; x++)
00087 if( getBall(x,y) == NOBALL )
00088 {
00089 xx[empty] = x;
00090 yy[empty] = y;
00091 empty++;
00092 };
00093
00094 if ( empty > 0)
00095 {
00096 int pos = rand()%empty;
00097 putBall( xx[pos], yy[pos], color );
00098 clearAnim();
00099 setAnim( xx[pos], yy[pos], ANIM_BORN );
00100 nextBallToPlace++;
00101 AnimStart(ANIM_BORN);
00102 free(xx);
00103 free(yy);
00104 }
00105 else
00106 {
00107 free(xx);
00108 free(yy);
00109 emit endGame();
00110 }
00111 debug("LinesBoard::placeBall END");
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 int LinesBoard::width() { return CELLSIZE * NUMCELLSW; }
00125 int LinesBoard::height() { return CELLSIZE * NUMCELLSH; }
00126 int LinesBoard::wHint() { return width(); }
00127 int LinesBoard::hHint() { return height(); }
00128
00129
00130
00131 void LinesBoard::paintEvent( QPaintEvent* )
00132 {
00133
00134 QPixmap pixmap(width(), height());
00135 QPainter paint(&pixmap, this);
00136
00137 for( int y=0; y < NUMCELLSH; y++ ){
00138 for( int x=0; x < NUMCELLSW; x++ ){
00139 if( getBall(x,y) == NOBALL )
00140 {
00141
00142 paint.drawPixmap(x*CELLSIZE, y*CELLSIZE, *(bPainter->GetBackgroundPix()) );
00143 }
00144 else
00145 {
00146
00147 paint.drawPixmap(x*CELLSIZE, y*CELLSIZE,
00148 *(bPainter->GetBall(getBall(x,y),animstep,getAnim(x,y))));
00149 }
00150 }
00151 }
00152
00153 bitBlt(this, 0,0, &pixmap, 0,0, width(), height(), CopyROP);
00154 }
00155
00156
00157
00158
00159 void LinesBoard::mousePressEvent( QMouseEvent* e )
00160 {
00161 debug("LinesBoard::mousePressEvent START");
00162 int curRow = e->y() / CELLSIZE;
00163 int curCol = e->x() / CELLSIZE;
00164
00165 debug("Mouse pressed: curRow=%i, curCol=%i", curRow, curCol);
00166
00167
00168 if (!checkBounds( curCol, curRow ) )
00169 return;
00170
00171 if(anim != ANIM_JUMP && anim != ANIM_NO) return;
00172 if ( anim == ANIM_JUMP )
00173 {
00174 if ( getBall(curCol,curRow) == NOBALL )
00175 {
00176 if(existPath(jumpingCol, jumpingRow, curCol, curRow))
00177 {
00178 saveUndo();
00179 AnimStart(ANIM_RUN);
00180 }
00181 }
00182 else
00183 AnimJump(curCol,curRow);
00184 }
00185 else
00186 AnimJump(curCol,curRow);
00187 debug("LinesBoard::mousePressEvent END");
00188 }
00189 void LinesBoard::AnimJump(int x, int y ) {
00190 debug("LinesBoard::AnimJump( %i,%i)", x,y );
00191 if ( getBall(x,y) != NOBALL )
00192 if (!( anim == ANIM_JUMP && jumpingCol == x && jumpingRow == y ))
00193 if ( AnimEnd() )
00194 {
00195 clearAnim();
00196 setAnim(x,y,ANIM_JUMP);
00197 jumpingCol = x;
00198 jumpingRow = y;
00199 AnimStart(ANIM_JUMP);
00200 }
00201 debug("LinesBoard::AnimJump END");
00202 }
00203 void LinesBoard::AnimStart(int panim) {
00204 debug("LinesBoard::AnimStart( %i )", panim);
00205 if (anim != ANIM_NO)
00206 AnimEnd();
00207 animstep = 0;
00208 animdelaystart = 1;
00209 switch(panim) {
00210 case ANIM_NO:
00211 break;
00212 case ANIM_BORN:
00213 debug("LinesBoard::AnimStart( ANIM_BORN )");
00214 animdelaystart=1;
00215 animmax = BOOMBALLS;
00216 break;
00217 case ANIM_JUMP:
00218 direction = -1;
00219 animstep = 4;
00220 animmax = PIXTIME -1;
00221 break;
00222 case ANIM_RUN:
00223 animdelaystart=3;
00224
00225 animdelaycount = 0;
00226
00227 break;
00228 case ANIM_BURN:
00229 animdelaystart=1;
00230 animmax = FIREBALLS + FIREPIX - 1;
00231 break;
00232 default:
00233 ;
00234 }
00235 anim = panim;
00236 animdelaycount = animdelaystart;
00237 debug("LinesBoard::AnimStart END");
00238 }
00239 int LinesBoard::AnimEnd( )
00240 {
00241 debug("LinesBoard::AnimEnd( %i )",anim );
00242 if (anim == ANIM_NO ) return true;
00243 int oldanim = anim;
00244 anim = ANIM_NO;
00245 if (oldanim == ANIM_RUN) {
00246 if (animstep != animmax) {
00247 moveBall(way[animstep].x,way[animstep].y,way[animmax].x,way[animmax].y);
00248 }
00249 if ( erase5Balls() == 0 ) {
00250
00251 emit endTurn();
00252 debug("LinesBoard::AnimEnd END true 1");
00253 return true;
00254 }
00255 else
00256 debug("LinesBoard::AnimEnd END false 2");
00257 return false;
00258 } else if ( oldanim == ANIM_BURN )
00259 {
00260 emit eraseLine( deleteAnimatedBalls() );
00261 repaint(FALSE);
00262 if ( nextBallToPlace < BALLSDROP )
00263 {
00264 placeBall();
00265
00266 debug("LinesBoard::AnimEnd END false 3");
00267 return false;
00268 }
00269 else
00270 {
00271
00272 debug("LinesBoard::AnimEnd END true 4");
00273 return true;
00274 }
00275 } else if ( oldanim == ANIM_BORN )
00276 {
00277 if ( erase5Balls() == 0 )
00278 {
00279 if ( freeSpace() > 0)
00280 {
00281 if ( nextBallToPlace < BALLSDROP )
00282 {
00283 placeBall();
00284 debug("LinesBoard::AnimEnd END false 5");
00285 return false;
00286 }
00287 else
00288 {
00289 debug("LinesBoard::AnimEnd END true 6");
00290 return true;
00291 }
00292 }
00293 else
00294 {
00295 debug("emit endGame");
00296 emit endGame();
00297 debug("LinesBoard::AnimEnd END false 7");
00298 return false;
00299 }
00300 }
00301 else
00302 {
00303
00304 debug("LinesBoard::AnimEnd END true 8");
00305 return true;
00306 }
00307 }
00308 else
00309 {
00310 debug("LinesBoard::AnimEnd END true");
00311 return true;
00312 }
00313 return true;
00314 }
00315 void LinesBoard::AnimNext() {
00316 if ( anim != ANIM_NO )
00317 {
00318 debug("LinesBoard::AnimNext( ) anim %i animstep %i",anim,animstep);
00319 if ( anim == ANIM_JUMP ) {
00320 if ( (direction > 0 && animstep == animmax) || ( direction < 0 && animstep == 0))
00321 direction = -direction;
00322 animstep += direction;
00323 repaint(FALSE);
00324 } else {
00325 if ( animstep >= animmax )
00326 AnimEnd();
00327 else {
00328 animdelaycount--;
00329 if (animdelaycount <= 0) {
00330 debug("LinesBoard::AnimNext step %i", animstep);
00331 if ( anim == ANIM_RUN )
00332 moveBall(way[animstep].x,way[animstep].y,way[animstep+1].x,way[animstep+1].y);
00333 animstep++;
00334 animdelaycount = animdelaystart;
00335 repaint( FALSE );
00336 }
00337 }
00338 }
00339 debug("LinesBoard::AnimNext END");
00340 }
00341 }
00342 int LinesBoard::getAnim( int x, int y )
00343 {
00344
00345 return (( Field::getAnim(x,y) != ANIM_NO )? anim : ANIM_NO);
00346 }
00347
00348 void LinesBoard::timerSlot()
00349 {
00350
00351 AnimNext();
00352 }
00353
00354 int LinesBoard::erase5Balls()
00355 {
00356
00357 debug("LinesBoard::erase5Balls()");
00358
00359 int nb=5;
00360
00361 bool bit_erase[NUMCELLSH][NUMCELLSW];
00362 for(int y=0; y<NUMCELLSH; y++)
00363 for(int x=0; x<NUMCELLSW; x++)
00364 bit_erase[y][x] = false;
00365
00366 int color,newcolor;
00367 int count;
00368
00369
00370
00371 for(int y=0; y<NUMCELLSH; y++) {
00372 count = 1;
00373 color = NOBALL;
00374 for(int x=0; x<NUMCELLSW; x++){
00375 if ( (newcolor = getBall(x,y)) == color) {
00376 if ( color != NOBALL) {
00377 count++;
00378 if ( count >= nb )
00379 if ( count == nb )
00380 for (int i = 0; i < nb; i++)
00381 bit_erase[y][x-i] = true;
00382 else bit_erase[y][x] = true;
00383 }
00384 } else {
00385 color = newcolor;
00386 count = 1;
00387 }
00388 }
00389 }
00390
00391
00392
00393 for(int x=0; x<NUMCELLSW; x++) {
00394 count = 0;
00395 color = NOBALL;
00396 for(int y=0; y<NUMCELLSH; y++){
00397 if ( (newcolor = getBall(x,y)) == color) {
00398 if ( color != NOBALL) {
00399 count++;
00400 if ( count >= nb )
00401 if ( count == nb )
00402 for (int i = 0; i < nb; i++)
00403 bit_erase[y-i][x] = true;
00404 else bit_erase[y][x] = true;
00405 }
00406 } else {
00407 color = newcolor;
00408 count = 1;
00409 }
00410 }
00411 }
00412
00413
00414
00415
00416 for ( int xs = NUMCELLSW-1,ys = NUMCELLSH-nb; xs >= nb-1; ) {
00417 count = 0;
00418 color = NOBALL;
00419 for ( int x = xs, y = ys; x >= 0 && y < NUMCELLSH; x--, y++ ) {
00420 if ( (newcolor = getBall(x,y)) == color) {
00421 if ( color != NOBALL) {
00422 count++;
00423 if ( count >= nb )
00424 if ( count == nb )
00425 for (int i = 0; i < nb; i++)
00426 bit_erase[y-i][x+i] = true;
00427 else bit_erase[y][x] = true;
00428 }
00429 } else {
00430 color = newcolor;
00431 count = 1;
00432 }
00433 }
00434 if ( ys > 0 ) ys--; else xs--;
00435 }
00436
00437
00438
00439
00440 for ( int xs = 0,ys = NUMCELLSH-nb; xs <= NUMCELLSW-nb; )
00441 {
00442 count = 0;
00443 color = NOBALL;
00444 for ( int x = xs, y = ys; x < NUMCELLSW && y < NUMCELLSH; x++, y++ )
00445 {
00446 if ( (newcolor = getBall(x,y)) == color)
00447 {
00448 if ( color != NOBALL)
00449 {
00450 count++;
00451 if ( count >= nb )
00452 if ( count == nb )
00453 for (int i = 0; i < nb; i++)
00454 bit_erase[y-i][x-i] = true;
00455 else
00456 bit_erase[y][x] = true;
00457 }
00458 }
00459 else
00460 {
00461 color = newcolor;
00462 count = 1;
00463 }
00464 }
00465 if ( ys > 0 ) ys--; else xs++;
00466 }
00467
00468
00469 int cb=0;
00470 for(int y=0; y < NUMCELLSH; y++)
00471 for(int x=0; x < NUMCELLSW; x++)
00472 {
00473 if (bit_erase[y][x])
00474 {
00475 setAnim(x,y,ANIM_YES);
00476 cb++;
00477 }
00478 else
00479 {
00480 setAnim(x,y,ANIM_NO);
00481 }
00482 }
00483
00484 debug("LinesBoard::erase5Balls marked %i balls", cb);
00485 if ( cb > 0 )
00486 {
00487 AnimStart(ANIM_BURN);
00488
00489 }
00490
00491
00492 debug("LinesBoard::erase5Balls END");
00493 return cb;
00494 }
00495
00496
00497 #define GO_EMPTY 4
00498 #define GO_A 5
00499 #define GO_B 6
00500 #define GO_BALL 7
00501
00502 bool LinesBoard::existPath(int bx, int by, int ax, int ay)
00503 {
00504 debug("LinesBoard::existPath( %i, %i, %i, %i )", bx, by, ax, ay);
00505 int dx[4]={1,-1, 0, 0};
00506 int dy[4]={0, 0, 1,-1};
00507
00508
00509 if (getBall(ax,ay) != NOBALL)
00510 return false;
00511
00512 char pf[NUMCELLSH][NUMCELLSW];
00513 for(int y=0; y<NUMCELLSH; y++)
00514 for(int x=0; x<NUMCELLSW; x++)
00515 pf[y][x] = (getBall(x,y) == NOBALL) ? GO_EMPTY:GO_BALL;
00516
00517 Waypoints lastchanged[2][NUMCELLSH*NUMCELLSW];
00518
00519 int lastChangedCount[2];
00520 int currentchanged = 0;
00521 int nextchanged = 1;
00522 lastchanged[currentchanged][0].x = ax;
00523 lastchanged[currentchanged][0].y = ay;
00524 lastChangedCount[currentchanged] = 1;
00525 pf[ay][ax]=GO_A;
00526 pf[by][bx]=GO_B;
00527
00528
00529 bool B_reached = false;
00530
00531 do
00532 {
00533 lastChangedCount[nextchanged] = 0;
00534 for(int dir=0; dir<4; dir++)
00535 {
00536 for ( int i = 0 ; i < lastChangedCount[currentchanged]; i++ )
00537 {
00538 int nx = lastchanged[currentchanged][i].x + dx[dir];
00539 int ny = lastchanged[currentchanged][i].y + dy[dir];
00540 if( (nx>=0) && (nx<NUMCELLSW) && (ny>=0) && (ny<NUMCELLSH) )
00541 {
00542 if( pf[ny][nx]==GO_EMPTY ||( nx==bx && ny==by ))
00543 {
00544 pf[ny][nx] = dir;
00545 lastchanged[nextchanged][lastChangedCount[nextchanged]].x = nx;
00546 lastchanged[nextchanged][lastChangedCount[nextchanged]].y = ny;
00547 lastChangedCount[nextchanged]++;
00548 };
00549 if( (nx==bx) && (ny==by) )
00550 {
00551 B_reached = true;
00552 break;
00553 }
00554 }
00555 }
00556 }
00557 nextchanged = nextchanged ^ 1;
00558 currentchanged = nextchanged ^ 1;
00559
00560
00561 } while(!B_reached && lastChangedCount[currentchanged] != 0);
00562
00563
00564 if (B_reached) {
00565 AnimStart( ANIM_BLOCK);
00566 animmax = 0;
00567
00568 int x, y,dir;
00569 for( x = bx, y = by,dir; (dir = pf[y][x]) != GO_A;x -=dx[dir],y -= dy[dir]) {
00570 way[animmax].x = x;
00571 way[animmax].y = y;
00572
00573 animmax++;
00574 }
00575 way[animmax].x = x;
00576 way[animmax].y = y;
00577 }
00578 debug("LinesBoard::existPath END %s", B_reached?"true":"false" );
00579 return B_reached;
00580 }
00581
00582 void LinesBoard::undo()
00583 {
00584 AnimEnd();
00585 restoreUndo();
00586 repaint( FALSE );
00587 }
00588