• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kmahjongg

boardwidget.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 1997 Mathias Mueller   <in5y158@public.uni-hamburg.de>
00003     Copyright (C) 2006 Mauricio Piacentini   <mauricio@tabuleiro.com>
00004 
00005     Kmahjongg is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 */
00019 
00020 #include "boardwidget.h"
00021 #include "prefs.h"
00022 
00023 #include <kmessagebox.h>
00024 #include <krandom.h>
00025 #include <QTimer>
00026 #include <qpainter.h>
00027 #include <klocale.h>
00028 #include <kstandarddirs.h>
00029 #include <qapplication.h>
00030 #include <kconfig.h>
00031 #include <kglobal.h>
00032 #include <KDebug>
00033 
00038 BoardWidget::BoardWidget( QWidget* parent )
00039   : KGameCanvasWidget( parent ), theTiles()
00040 {
00041     QPalette palette;
00042     palette.setColor( backgroundRole(), Qt::black );
00043     setPalette(palette);
00044 
00045     timer = new QTimer(this);
00046     connect( timer, SIGNAL(timeout()),
00047              this, SLOT(helpMoveTimeout()) );
00048 
00049     TimerState = Stop;
00050     gamePaused = false;
00051     iTimerStep = 0;
00052     matchCount = 0;
00053     showMatch = false;
00054     showHelp = false;
00055 
00056     //memset( &Game->Mask, 0, sizeof( Game->Mask ) );
00057     gameGenerationNum = 0;
00058     m_angle = NE;
00059 
00060     // Load layout first
00061     loadBoardLayout(Prefs::layout());
00062 
00063     //Initialize our Game structure
00064     Game = new GameData(theBoardLayout.board());
00065 
00066     MouseClickPos1.e = Game->m_depth;     // mark tile position as invalid
00067     MouseClickPos2.e = Game->m_depth;
00068 
00069     //Animation timers
00070     animateForwardTimer = new QTimer(this);
00071     animateForwardTimer->setSingleShot(true);
00072     animateForwardTimer->setInterval(100);
00073     connect(animateForwardTimer, SIGNAL(timeout()), SLOT(animatingMoveListForward()));
00074     animateForwardTimer->stop();
00075     
00076     animateBackwardsTimer = new QTimer(this);
00077     animateBackwardsTimer->setSingleShot(true);
00078     animateBackwardsTimer->setInterval(100);
00079     connect(animateBackwardsTimer, SIGNAL(timeout()), SLOT(animatingMoveListBackwards()));
00080     animateBackwardsTimer->stop();
00081     
00082     loadSettings();
00083 }
00084 
00085 BoardWidget::~BoardWidget(){
00086   if (Game) delete Game;
00087 }
00088 
00089 void BoardWidget::loadSettings(){
00090     // Load tileset. First try to load the last use tileset
00091 
00092     if (!loadTileset(Prefs::tileSet())){
00093       kDebug() << "An error occurred when loading the tileset" << Prefs::tileSet() <<"KMahjongg will continue with the default tileset.";
00094     }
00095 
00096     // Load background
00097     if( ! loadBackground(Prefs::background(), false ) )
00098     {
00099       kDebug() << "An error occurred when loading the background" << Prefs::background() <<"KMahjongg will continue with the default background.";
00100     }
00101     setShowMatch( Prefs::showMatchingTiles() );
00102     
00103     if (QString::compare(Prefs::layout(), theBoardLayout.path(), Qt::CaseSensitive)!=0) {
00104       //TODO: WARN USER HERE ABOUT DESTRUCTIVE OPERATION!!!
00105       loadBoardLayout(Prefs::layout());
00106       calculateNewGame();
00107     }
00108     setDisplayedWidth();
00109     drawBoard(true);
00110     //Store our updated settings, some values might have been changed to defaults
00111     saveSettings();
00112 }
00113 
00114 void BoardWidget::resizeEvent ( QResizeEvent * event )
00115 {
00116     if (event->spontaneous()) return;
00117     resizeTileset(event->size());
00118     theBackground.sizeChanged(requiredWidth(), requiredHeight());
00119     drawBoard(true);
00120 }
00121 
00122 void BoardWidget::resizeTileset ( const QSize & wsize )
00123 {
00124     QSize newtiles = theTiles.preferredTileSize(wsize, requiredHorizontalCells(), requiredVerticalCells());
00125 
00126     theTiles.reloadTileset(newtiles);
00127     stopMatchAnimation();
00128 }
00129 
00130 
00131 
00132 void BoardWidget::saveSettings(){
00133   Prefs::setTileSet(theTiles.path());
00134   Prefs::setLayout(theBoardLayout.path());
00135   Prefs::setBackground(theBackground.path());
00136   Prefs::self()->writeConfig();
00137 }
00138 
00139 void BoardWidget::setDisplayedWidth() {
00140   //TODO remove method and let the layout handle it
00141   //for now we just force our resizeEvent() to be called
00142   resize(width() , height());
00143 }
00144 
00145 void BoardWidget::populateSpriteMap() {
00146     //Delete previous sprites (full update), synchronize state with GameData
00147     while (!items()->isEmpty())
00148     delete items()->first();
00149 
00150     //Clear our spritemap as well
00151     spriteMap.clear();
00152 
00153     //Recreate our background
00154     QPalette palette;
00155     palette.setBrush( backgroundRole(), theBackground.getBackground() );
00156     setPalette( palette );
00157     setAutoFillBackground (true);
00158 
00159     //create the sprites
00160     for (int z=0; z<Game->m_depth; z++) {
00161         // we draw down the board so the tile below over rights our border
00162         for (int y = 0; y < Game->m_height; y++) {
00163             // drawing right to left to prevent border overwrite
00164             for (int x=Game->m_width-1; x>=0; x--) {
00165 
00166         // skip if no tile to display
00167         if (!Game->tilePresent(z,y,x))
00168             continue;
00169 
00170                 QPixmap s;
00171         QPixmap us;
00172         QPixmap f;
00173         bool selected = false;
00174         s= theTiles.selectedTile(m_angle);
00175         us= theTiles.unselectedTile(m_angle);
00176         f= theTiles.tileface(Game->BoardData(z,y,x)-TILE_OFFSET);
00177         if (Game->HighlightData(z,y,x)) {
00178             selected = true;
00179         }
00180 
00181           TileSprite * thissprite = new TileSprite(this, us, s, f, m_angle, selected);
00182 
00183           spriteMap.insert(TileCoord(x,y,z), thissprite);
00184             }
00185         }
00186     }
00187 
00188     updateSpriteMap();
00189 }
00190 
00191 
00192 void BoardWidget::updateSpriteMap() {
00193     // initial offset on the screen of tile 0,0
00194     // think of it as what is left if you add all tilefaces (qwidth/heigh*2) plus one (wholetile-shadow(3dindent)-tileface), and divide by 2
00195     int xOffset = (width() - (Game->m_width*(theTiles.qWidth())) - (theTiles.width()-(theTiles.qWidth()*2)))/2;;
00196     int yOffset = (height() - (Game->m_height*(theTiles.qHeight())) - (theTiles.height()-(theTiles.qHeight()*2)))/2;;
00197 
00198     // we iterate over the depth stacking order. Each successive level is
00199     // drawn one indent up and to the right. The indent is the width
00200     // of the 3d relief on the tile left (tile shadow width)
00201     switch (m_angle)
00202     {
00203     case NW:
00204     //remove shadow from margin calculation
00205     xOffset += theTiles.levelOffsetX()/2;
00206         yOffset += theTiles.levelOffsetY()/2;
00207 
00208     //Position
00209     for (int z=0; z<Game->m_depth; z++) {
00210         // we draw down the board so the tile below over rights our border
00211         for (int y = 0; y < Game->m_height; y++) {
00212         // drawing right to left to prevent border overwrite
00213         for (int x=Game->m_width-1; x>=0; x--) {
00214             int sx = x*(theTiles.qWidth()  )+xOffset;
00215             int sy = y*(theTiles.qHeight()  )+yOffset;
00216     
00217             // skip if no tile to display
00218             if (!Game->tilePresent(z,y,x))
00219                 continue;
00220     
00221             TileSprite * thissprite =spriteMap.value(TileCoord(x,y,z));
00222     
00223             if (thissprite) thissprite->moveTo(sx, sy);
00224             if (thissprite) thissprite->show();
00225         }
00226         }
00227         xOffset +=theTiles.levelOffsetX();
00228         yOffset -=theTiles.levelOffsetY();
00229     }
00230     //Layer
00231     for (int z=0; z<Game->m_depth; z++) {
00232         // start drawing in diagonal for correct layering. For this we double the board, 
00233         //actually starting outside of it, in the bottom right corner, so our first diagonal ends
00234         // at the actual top right corner of the board
00235         for (int x=Game->m_width*2; x>=0; x--) {
00236         // reset the offset
00237         int offset = 0;
00238         for (int y=Game->m_height-1; y>=0; y--) {
00239             if (Game->tilePresent(z,y,x-offset))
00240             {
00241                 TileSprite * thissprite =spriteMap.value(TileCoord(x-offset,y,z));
00242                 if (thissprite) thissprite->raise();
00243             }
00244             //at each pass, move one place to the left
00245             offset++;
00246         }
00247         }
00248     }
00249     break;
00250 
00251     case NE:
00252     xOffset -= theTiles.levelOffsetX()/2;
00253         yOffset += theTiles.levelOffsetY()/2;
00254     //Position
00255     for (int z=0; z<Game->m_depth; z++) {
00256         // we draw down the board so the tile below over rights our border
00257         for (int y = 0; y < Game->m_height; y++) {
00258         // drawing right to left to prevent border overwrite
00259         for (int x=0; x<=Game->m_width-1; x++) {
00260             int sx = x*(theTiles.qWidth()  )+xOffset;
00261             int sy = y*(theTiles.qHeight()  )+yOffset;
00262     
00263             // skip if no tile to display
00264             if (!Game->tilePresent(z,y,x))
00265                 continue;
00266     
00267             TileSprite * thissprite =spriteMap.value(TileCoord(x,y,z));
00268     
00269             if (thissprite) thissprite->moveTo(sx, sy);
00270             if (thissprite) thissprite->show();
00271         }
00272         }
00273         xOffset -=theTiles.levelOffsetX();
00274         yOffset -=theTiles.levelOffsetY();
00275     }
00276     //Layer
00277     for (int z=0; z<Game->m_depth; z++) {
00278         // start drawing in diagonal for correct layering. For this we double the board, 
00279         //actually starting outside of it, in the bottom right corner, so our first diagonal ends
00280         // at the actual top right corner of the board
00281         for (int x=-(Game->m_width); x<=Game->m_width-1; x++) {
00282         // reset the offset
00283         int offset = 0;
00284         for (int y=Game->m_height-1; y>=0; y--) {
00285             if (Game->tilePresent(z,y,x+offset))
00286             {
00287                 TileSprite * thissprite =spriteMap.value(TileCoord(x+offset,y,z));
00288                 if (thissprite) thissprite->raise();
00289             }
00290             //at each pass, move one place to the right
00291             offset++;
00292         }
00293         }
00294     }
00295     break;
00296 
00297     case SE:
00298     xOffset -= theTiles.levelOffsetX()/2;
00299         yOffset -= theTiles.levelOffsetY()/2;
00300     //Position
00301     for (int z=0; z<Game->m_depth; z++) {
00302         for (int y = Game->m_height-1; y >= 0; y--) {
00303         for (int x=0; x<=Game->m_width-1; x++) {
00304             int sx = x*(theTiles.qWidth()  )+xOffset;
00305             int sy = y*(theTiles.qHeight()  )+yOffset;
00306     
00307             if (!Game->tilePresent(z,y,x))
00308                 continue;
00309     
00310             TileSprite * thissprite =spriteMap.value(TileCoord(x,y,z));
00311     
00312             if (thissprite) thissprite->moveTo(sx, sy);
00313             if (thissprite) thissprite->show();
00314         }
00315         }
00316         xOffset -=theTiles.levelOffsetX();
00317         yOffset +=theTiles.levelOffsetY();
00318     }
00319     //Layer
00320     for (int z=0; z<Game->m_depth; z++) {
00321         for (int x=-(Game->m_width); x<=Game->m_width-1; x++) {
00322         int offset = 0;
00323         for (int y=0; y<Game->m_height; y++) {
00324             if (Game->tilePresent(z,y,x+offset))
00325             {
00326                 TileSprite * thissprite =spriteMap.value(TileCoord(x+offset,y,z));
00327                 if (thissprite) thissprite->raise();
00328             }
00329             offset++;
00330         }
00331         }
00332     }
00333     break;
00334 
00335     case SW:
00336     xOffset += theTiles.levelOffsetX()/2;
00337         yOffset -= theTiles.levelOffsetY()/2;
00338 
00339     //Position
00340     for (int z=0; z<Game->m_depth; z++) {
00341         for (int y = Game->m_height-1; y >= 0; y--) {
00342         for (int x=Game->m_width-1; x>=0; x--) {
00343             int sx = x*(theTiles.qWidth()  )+xOffset;
00344             int sy = y*(theTiles.qHeight()  )+yOffset;
00345 
00346             if (!Game->tilePresent(z,y,x))
00347                 continue;
00348     
00349             TileSprite * thissprite =spriteMap.value(TileCoord(x,y,z));
00350     
00351             if (thissprite) thissprite->moveTo(sx, sy);
00352             if (thissprite) thissprite->show();
00353         }
00354         }
00355         xOffset +=theTiles.levelOffsetX();
00356         yOffset +=theTiles.levelOffsetY();
00357     }
00358     //Layer
00359     for (int z=0; z<Game->m_depth; z++) {
00360         for (int x=Game->m_width*2; x>=0; x--) {
00361         int offset = 0;
00362         for (int y=0; y<Game->m_height; y++) {
00363             if (Game->tilePresent(z,y,x-offset))
00364             {
00365                 TileSprite * thissprite =spriteMap.value(TileCoord(x-offset,y,z));
00366                 if (thissprite) thissprite->raise();
00367             }
00368             offset++;
00369         }
00370         }
00371     }
00372     break;
00373    }
00374 }
00375 
00376 void BoardWidget::pause() {
00377     gamePaused = !gamePaused;
00378     drawBoard(!gamePaused);
00379 }
00380 
00381 void BoardWidget::gameLoaded()
00382 {
00383     int i;
00384     Game->initialiseRemovedTiles();
00385     i = Game->TileNum;
00386     // use the history of moves to put in the removed tiles area the correct tiles
00387     while (i < Game->MaxTileNum )
00388     {
00389         Game->setRemovedTilePair(Game->MoveListData(i), Game->MoveListData(i+1));
00390         i +=2;
00391     }
00392         populateSpriteMap();
00393     drawBoard(true);
00394 }
00395 
00396 // ---------------------------------------------------------
00397 int BoardWidget::undoMove()
00398 {
00399     cancelUserSelectedTiles();
00400 
00401     if( Game->TileNum < Game->MaxTileNum )
00402     {
00403 
00404         Game->clearRemovedTilePair(Game->MoveListData(Game->TileNum), Game->MoveListData(Game->TileNum+1));
00405         putTileInBoard( Game->MoveListData(Game->TileNum), false );
00406         Game->TileNum++;
00407         putTileInBoard( Game->MoveListData(Game->TileNum) );
00408         Game->TileNum++;
00409         drawTileNumber();
00410         setStatusText( i18n("Undo operation done successfully.") );
00411     return 1;
00412     }
00413     else {
00414         setStatusText(i18n("What do you want to undo? You have done nothing!"));
00415     return 0;
00416     }
00417 }
00418 
00419 // ---------------------------------------------------------
00420 void BoardWidget::helpMove()
00421 {
00422     cancelUserSelectedTiles();
00423     if (showHelp) helpMoveStop();
00424 
00425     if( Game->findMove( TimerPos1, TimerPos2 ) )
00426     {
00427         cheatsUsed++;
00428         iTimerStep = 1;
00429         showHelp = true;
00430         helpMoveTimeout();
00431     }
00432     else
00433         setStatusText( i18n("Sorry, you have lost the game.") );
00434 }
00435 // ---------------------------------------------------------
00436 void BoardWidget::helpMoveTimeout()
00437 {
00438     if( iTimerStep & 1 )
00439     {
00440         hilightTile( TimerPos1, true, false );
00441         hilightTile( TimerPos2, true );
00442     }
00443     else
00444     {
00445         hilightTile( TimerPos1, false, false );
00446         hilightTile( TimerPos2, false );
00447     }
00448     // restart timer
00449     if( iTimerStep++ < 8 )
00450     {
00451         timer->setSingleShot(true);
00452         timer->start( ANIMSPEED );
00453     }
00454     else
00455         showHelp = false;
00456 }
00457 // ---------------------------------------------------------
00458 
00459 void BoardWidget::helpMoveStop()
00460 {
00461     timer->stop();
00462     iTimerStep = 8;
00463     hilightTile( TimerPos1, false, false );
00464     hilightTile( TimerPos2, false );
00465     showHelp = false;
00466 }
00467 
00468 // ---------------------------------------------------------
00469 void BoardWidget::startDemoMode()
00470 {
00471     calculateNewGame();
00472 
00473     if( TimerState == Stop )
00474     {
00475         TimerState = Demo;
00476         iTimerStep = 0;
00477         emit demoModeChanged( true );
00478         setStatusText( i18n("Demo mode. Click mousebutton to stop.") );
00479         demoMoveTimeout();
00480     }
00481 }
00482 // ---------------------------------------------------------
00483 void BoardWidget::stopDemoMode()
00484 {
00485     TimerState = Stop;    // stop demo
00486     calculateNewGame();
00487     setStatusText( i18n("Now it is you again.") );
00488     emit demoModeChanged( false );
00489     emit gameCalculated();
00490 }
00491 // ---------------------------------------------------------
00492 void BoardWidget::demoMoveTimeout()
00493 {
00494     if( TimerState == Demo )
00495     {
00496         switch( iTimerStep++ % 6 )
00497         {
00498             // at firts, find new matching tiles
00499             case 0:
00500                 if( ! Game->findMove( TimerPos1, TimerPos2 ) )
00501             {
00502                     // if computer has won
00503                 if( Game->TileNum == 0 )
00504                     {
00505                         animateMoveList();
00506                     }
00507                     // else computer has lost
00508                     else
00509                     {
00510                         setStatusText( i18n("Your computer has lost the game.") );
00511                         while( Game->TileNum < Game->MaxTileNum )
00512                         {
00513                             putTileInBoard( Game->MoveListData(Game->TileNum), false );
00514                             Game->TileNum++;
00515                             putTileInBoard( Game->MoveListData(Game->TileNum) );
00516                             Game->TileNum++;
00517                             drawTileNumber();
00518                         }
00519                     }
00520                     TimerState = Stop;
00521                     //startDemoMode();
00522             //do not loop demo
00523             stopDemoMode();
00524                     return;
00525                 }
00526                 break;
00527         // hilight matching tiles two times
00528             case 1:
00529             case 3:
00530                 hilightTile( TimerPos1, true, false );
00531                 hilightTile( TimerPos2, true );
00532             break;
00533 
00534             case 2:
00535             case 4:
00536                 hilightTile( TimerPos1, false, false );
00537                 hilightTile( TimerPos2, false );
00538                 break;
00539         // remove matching tiles from game board
00540             case 5:
00541                 Game->setRemovedTilePair(TimerPos1, TimerPos2);
00542                 removeTile( TimerPos1, false );
00543                 removeTile( TimerPos2 );
00544                 drawTileNumber();
00545                 break;
00546         }
00547         // restart timer
00548         QTimer::singleShot( ANIMSPEED, this, SLOT( demoMoveTimeout() ) );
00549     }
00550 }
00551 
00552 // ---------------------------------------------------------
00553 void BoardWidget::setShowMatch( bool show )
00554 {
00555     if( showMatch )
00556         stopMatchAnimation();
00557     showMatch = show;
00558 }
00559 // ---------------------------------------------------------
00560 void BoardWidget::matchAnimationTimeout()
00561 {
00562     if (matchCount == 0)
00563         return;
00564 
00565     if( iTimerStep++ & 1 )
00566     {
00567         for(short Pos = 0; Pos < matchCount; Pos++)
00568         {
00569           hilightTile(Game->getFromPosTable(Pos), true);
00570         }
00571     }
00572     else
00573     {
00574         for(short Pos = 0; Pos < matchCount; Pos++)
00575         {
00576           hilightTile(Game->getFromPosTable(Pos), false);
00577         }
00578     }
00579     if( TimerState == Match )
00580         QTimer::singleShot( ANIMSPEED, this, SLOT( matchAnimationTimeout() ) );
00581 }
00582 // ---------------------------------------------------------
00583 void BoardWidget::stopMatchAnimation()
00584 {
00585     for(short Pos = 0; Pos < matchCount; Pos++)
00586     {
00587       hilightTile(Game->getFromPosTable(Pos), false);
00588     }
00589     TimerState = Stop;
00590     matchCount = 0;
00591 }
00592 
00593 void BoardWidget::redoMove()
00594 {
00595 
00596     Game->setRemovedTilePair(Game->MoveListData(Game->TileNum-1),Game->MoveListData(Game->TileNum-2));
00597         removeTile(Game->MoveListData(Game->TileNum-1), false);
00598         removeTile(Game->MoveListData(Game->TileNum-1));
00599         drawTileNumber();
00600 }
00601 
00602 // ---------------------------------------------------------
00603 void BoardWidget::animateMoveList()
00604 {
00605     setStatusText( i18n("Congratulations. You have won!") );
00606     animatingMoveListForward();
00607 }
00608 
00609 void BoardWidget::animatingMoveListForward()
00610 {
00611     if (Game->TileNum < Game->MaxTileNum) {
00612         // put back all tiles
00613         putTileInBoard(Game->MoveListData(Game->TileNum));
00614         Game->TileNum++;
00615         putTileInBoard(Game->MoveListData(Game->TileNum), false);
00616         Game->TileNum++;
00617         drawTileNumber();
00618         animateForwardTimer->start(); //it is a single shot timer
00619     } else {
00620         //start removal
00621       animateBackwardsTimer->start(); //it is a single shot timer
00622     }
00623 }
00624 
00625 void BoardWidget::animatingMoveListBackwards()
00626 {
00627     if (Game->TileNum > 0 ) {
00628         // remove all tiles
00629         removeTile(Game->MoveListData(Game->TileNum-1), false);
00630         removeTile(Game->MoveListData(Game->TileNum-1));
00631         drawTileNumber();
00632         animateBackwardsTimer->start(); //it is a single shot timer
00633     } else {
00634         //end of animation
00635         stopEndAnimation();
00636     }
00637 }
00638 
00639 void BoardWidget::stopEndAnimation()
00640 {
00641   animateForwardTimer->stop();
00642   animateBackwardsTimer->stop();
00643 }
00644 
00645 // ---------------------------------------------------------
00646 void BoardWidget::calculateNewGame( int gNumber)
00647 {
00648     cancelUserSelectedTiles();
00649     stopMatchAnimation();
00650     stopEndAnimation();
00651     Game->initialiseRemovedTiles();
00652     setStatusText( i18n("Calculating new game...") );
00653 
00654 
00655     if( !loadBoard())
00656     {
00657         setStatusText( i18n("Error converting board information!") );
00658         return;
00659     }
00660 
00661     if (gNumber == -1) {
00662         gameGenerationNum = KRandom::random();
00663     } else {
00664     gameGenerationNum = gNumber;
00665     }
00666 
00667     Game->random.setSeed(gameGenerationNum);
00668 
00669     // Translate Game->Map to an array of POSITION data.  We only need to
00670     // do this once for each new game.
00671     Game->generateTilePositions();
00672 
00673     // Now use the tile position data to generate tile dependency data.
00674     // We only need to do this once for each new game.
00675     Game->generatePositionDepends();
00676 
00677     // Now try to position tiles on the board, 64 tries max.
00678     for( short nr=0; nr<64; nr++ )
00679     {
00680         if( Game->generateStartPosition2() )
00681         {
00682             drawBoard(true);
00683             setStatusText( i18n("Ready. Now it is your turn.") );
00684             cheatsUsed=0;
00685             emit gameCalculated();
00686             return;
00687         }
00688     }
00689 
00690     drawBoard(true);
00691     setStatusText( i18n("Error generating new game!") );
00692 }
00693 
00694 // ---------------------------------------------------------
00695 // This function replaces the old method of hilighting by
00696 // modifying color 21 to color 20. This was single tileset
00697 // specific. We now have two tile faces, one selected one not.
00698 
00699 void BoardWidget::hilightTile( POSITION& Pos, bool on, bool doRepaint )
00700 {
00701     TileSprite * atile = 0;
00702 
00703     TileCoord coord = TileCoord(Pos.x,Pos.y,Pos.e);
00704 
00705     if (spriteMap.contains(coord)) {
00706       atile = spriteMap.value(coord);
00707     }
00708 
00709     if (on) {
00710         Game->setHighlightData(Pos.e,Pos.y,Pos.x,1);
00711         if (atile)
00712         atile->setSelected(true);
00713     } else {
00714         Game->setHighlightData(Pos.e,Pos.y,Pos.x,0);
00715         if (atile)
00716         atile->setSelected(false);
00717     }
00718 }
00719 
00720 
00721 
00722 // ---------------------------------------------------------
00723 void BoardWidget::drawBoard(bool showTiles)
00724 {
00725    if (gamePaused) showTiles = false;
00726    if (showTiles) {
00727     populateSpriteMap();
00728     drawTileNumber();
00729    } else {
00730      //Delete previous sprites
00731      while (!items()->isEmpty())
00732        delete items()->first();
00733 
00734     //Clear our spritemap as well
00735      spriteMap.clear();
00736 
00737     //Recreate our background
00738      QPalette palette;
00739      palette.setBrush( backgroundRole(), theBackground.getBackground() );
00740      setPalette( palette );
00741      setAutoFillBackground (true);
00742    }
00743 }
00744 
00745 // ---------------------------------------------------------
00746 void BoardWidget::putTileInBoard( POSITION& Pos, bool doRepaint )
00747 {
00748     short E=Pos.e;
00749     short Y=Pos.y;
00750     short X=Pos.x;
00751 
00752     // we ensure that any tile we put on has highlighting off
00753     Game->putTile( E, Y, X, Pos.f );
00754     Game->setHighlightData(E,Y,X,0);
00755 
00756     QPixmap s;
00757     QPixmap us;
00758     QPixmap f;
00759     s= theTiles.selectedTile(m_angle);
00760     us= theTiles.unselectedTile(m_angle);
00761     f= theTiles.tileface(Game->BoardData(E,Y,X)-TILE_OFFSET);
00762     TileSprite * thissprite = new TileSprite(this, us, s, f, m_angle, false);
00763     thissprite->show();
00764     spriteMap.insert(TileCoord(X,Y,E), thissprite);
00765 
00766     updateSpriteMap();
00767 }
00768 
00769 
00770 // ---------------------------------------------------------
00771 //TODO move this to Game after handling the repaint situation
00772 void BoardWidget::removeTile( POSITION& Pos , bool doRepaint)
00773 {
00774     short E = Pos.e;
00775     short Y = Pos.