Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

mindbreaker.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include "mindbreaker.h"
00022 
00023 #include <opie2/oresource.h>
00024 
00025 #include <qtopia/config.h>
00026 #include <qtopia/qpeapplication.h>
00027 #include <qtoolbar.h>
00028 
00029 #include <qtoolbutton.h>
00030 #include <qmessagebox.h>
00031 #include <qlayout.h>
00032 #include <qtimer.h>
00033 
00034 #include <stdlib.h>
00035 #include <sys/time.h>
00036 #include <unistd.h>
00037 
00038 static int pegRTTI = 3393393;
00039 
00040 static int adjusted_panel_height;
00041 static int adjusted_panel_width;
00042 
00043 static int adjusted_bin_margin;
00044 static int adjusted_peg_size;
00045 static int adjusted_answerpeg_size;
00046 
00047 static int adjusted_title_height;
00048 static int adjusted_title_width;
00049 
00050 static int adjusted_first_peg_x_diff;
00051 static int adjusted_first_peg_y_diff;
00052 static int adjusted_peg_spacing;
00053 
00054 static int adjusted_answerpegx;
00055 static int adjusted_answerpegy;
00056 static int adjusted_answerpeg_xdiff;
00057 static int adjusted_answerpeg_ydiff;
00058 
00059 static int adjusted_board_height;
00060 static int adjusted_board_width;
00061 
00062 static void setupBoardSize(int w, int h)
00063 {
00064     adjusted_panel_width = w * 3/4;
00065     adjusted_title_width = w * 3/4;
00066 
00067     adjusted_title_height = h/10;
00068     adjusted_panel_height = (h-adjusted_title_height)/9;
00069 
00070     adjusted_bin_margin = w * 10/240;
00071     adjusted_peg_size = adjusted_panel_height*3/4;
00072     adjusted_answerpeg_size = QMIN(adjusted_panel_width*15/180,adjusted_panel_height*15/25);
00073 
00074     // looks a bit dodgy on larger sizes
00075     if ( adjusted_peg_size > 40 )
00076         adjusted_peg_size = 40;
00077 
00078     adjusted_first_peg_x_diff = w * 31/240-adjusted_peg_size/2;
00079     adjusted_first_peg_y_diff = (adjusted_panel_height - adjusted_peg_size)/2;
00080     adjusted_peg_spacing = w * 30/240;
00081 
00082     // looks a bit dodgy on larger sizes (still does though, but not as much...)
00083     if ( adjusted_answerpeg_size > 22 )
00084         adjusted_answerpeg_size = 22;
00085 
00086     adjusted_answerpegx = adjusted_panel_width * 159/180 - adjusted_answerpeg_size/2;
00087     adjusted_answerpegy = adjusted_panel_height/3 - adjusted_answerpeg_size/2;
00088     adjusted_answerpeg_xdiff = adjusted_panel_width * 10/180;
00089     adjusted_answerpeg_ydiff = adjusted_panel_height * 9/25;
00090 
00091     adjusted_board_height = adjusted_title_height + (adjusted_panel_height * 9);
00092     adjusted_board_width = adjusted_panel_width + (adjusted_bin_margin * 2) + adjusted_peg_size;
00093 
00094 //    odebug << "Adjusted width " << adjusted_board_width << " height " << adjusted_board_height << "" << oendl; 
00095 }
00096 
00097 
00098 /* helper class,  */
00099 class Peg : public QCanvasRectangle
00100 {
00101 public:
00102     Peg(QCanvas *canvas, int type, int go = -1, int pos = -1);
00103     int rtti() const {return pegRTTI; }
00104     void advance(int phase);
00105 
00106     bool hit( const QPoint &) const;
00107 
00108 /* a placed peg is one that has been set down on the board correctly and
00109    should not be moved, only copied */
00110     bool placed() const;
00111     void setPlaced(bool);
00112 
00113     int pegGo() const;
00114     int pegPos() const;
00115     void setPegPos(int);
00116 
00117     int type() const;
00118 
00119     static void buildImages();
00120     static QImage imageForType(int t);
00121 
00122     static int eggLevel;
00123 
00124 protected:
00125     void drawShape(QPainter &);
00126 private:
00127     static QVector<QImage> normalPegs;
00128     static QVector<QImage> specialPegs;
00129 
00130     bool isplaced;
00131     int pegtype;
00132     int peg_go;
00133     int peg_pos;
00134 
00135     int aniStep;
00136 };
00137 int Peg::eggLevel = 0;
00138 QVector<QImage> Peg::normalPegs;
00139 QVector<QImage> Peg::specialPegs;
00140 
00141 void Peg::buildImages()
00142 {
00143     QImage pegs = Opie::Core::OResource::loadImage("mindbreaker/pegs");
00144     int x = 0;
00145     int y = 0;
00146     int i;
00147     eggLevel = 0;
00148     normalPegs.resize(10);
00149     for (i = 0; i < 6; i++) {
00150         normalPegs.insert(i, new QImage(pegs.copy(x, y, peg_size, peg_size).
00151                                 smoothScale(adjusted_peg_size, adjusted_peg_size) ));
00152         x += peg_size;
00153     }
00154     specialPegs.resize(5);
00155     for (i = 0; i < 5; i++) {
00156         specialPegs.insert(i, new QImage(pegs.copy(x,y,peg_size, peg_size).
00157                                 smoothScale(adjusted_peg_size, adjusted_peg_size) ));
00158         x += peg_size;
00159     }
00160 
00161     QImage image = Opie::Core::OResource::loadImage("mindbreaker/mindbreaker");
00162     /* copy from master image to functional images */
00163     x = 0;
00164     y = panel_height;
00165     normalPegs.insert(8,
00166             new QImage( image.copy(x, y, panel_width, panel_height).
00167                         smoothScale( adjusted_panel_width, adjusted_panel_height)
00168                       ));
00169     y += panel_height;
00170     y += title_height;
00171     normalPegs.insert(9,
00172             new QImage(image.copy(x, y, title_width, title_height).
00173                         smoothScale( adjusted_title_width, adjusted_title_height)
00174                     ));
00175     y += title_height;
00176 
00177     x = 6 * peg_size;
00178     normalPegs.insert(6,
00179             new QImage(image.copy(x, y, answerpeg_size, answerpeg_size).
00180                         smoothScale( adjusted_answerpeg_size, adjusted_answerpeg_size) ));
00181     x += answerpeg_size;
00182     normalPegs.insert(7,
00183             new QImage(image.copy(x, y, answerpeg_size, answerpeg_size).
00184                         smoothScale( adjusted_answerpeg_size, adjusted_answerpeg_size) ));
00185 }
00186 
00187 QImage Peg::imageForType(int t)
00188 {
00189     if (eggLevel > t ) {
00190         if( t < 5) {
00191             return *specialPegs[t];
00192         } else {
00193             return *normalPegs[rand() % 6];
00194         }
00195     }
00196     return *normalPegs[t];
00197 }
00198 
00199 Peg::Peg(QCanvas *canvas , int t, int g, int p)
00200         : QCanvasRectangle(canvas)
00201 {
00202     setSize(normalPegs[t]->width(), normalPegs[t]->height() );
00203     pegtype = t;
00204     isplaced = FALSE;
00205     peg_pos = p;
00206     peg_go = g;
00207     aniStep = rand() % 6;
00208     setAnimated(TRUE);
00209 }
00210 
00211 void Peg::advance(int phase) {
00212     if (phase == 0)
00213         aniStep = (++aniStep) % 6;
00214     else {
00215         hide();
00216         show();
00217     }
00218 }
00219 
00220 void Peg::drawShape(QPainter &p )
00221 {
00222     if ((pegtype == 5) && eggLevel > 5) {
00223         p.drawImage(int(x()), int(y()), *normalPegs[aniStep]);
00224     } else
00225         p.drawImage(int(x()), int(y()), imageForType(pegtype));
00226 }
00227 
00228 bool Peg::hit( const QPoint &p ) const
00229 {
00230     int ix = p.x() - int(x());
00231     int iy = p.y() - int(y());
00232     if (!normalPegs[pegtype]->valid(ix, iy))
00233         return FALSE;
00234     QRgb pixel = normalPegs[pegtype]->pixel(ix, iy);
00235     return (qAlpha(pixel ) != 0);
00236 }
00237 
00238 inline bool Peg::placed() const
00239 {
00240     return isplaced;
00241 }
00242 
00243 inline int Peg::pegGo() const
00244 {
00245     return peg_go;
00246 }
00247 
00248 inline int Peg::pegPos() const
00249 {
00250     return peg_pos;
00251 }
00252 
00253 inline void Peg::setPegPos(int p)
00254 {
00255     peg_pos = p;
00256 }
00257 
00258 inline void Peg::setPlaced(bool p)
00259 {
00260     isplaced = p;
00261 }
00262 
00263 inline int Peg::type() const
00264 {
00265     return pegtype;
00266 }
00267 
00268 /* Load the main image, copy from it the pegs, the board, and the answer image
00269  * and use these to create the tray, answer and board
00270  */
00271 MindBreaker::MindBreaker( QWidget *parent, const char *name, int wFlags )
00272    : QMainWindow(parent, name, wFlags)
00273 {
00274     setCaption( tr("Mind Breaker"));
00275     QPEApplication::setInputMethodHint( this, QPEApplication::AlwaysOff );
00276     setMinimumSize(160,210);
00277 
00278     QWidget *w = new QWidget( this );
00279     w->setBackgroundColor( black );
00280     QHBoxLayout *hb = new QHBoxLayout( w );
00281     hb->addStretch();
00282     board = new MindBreakerBoard(w);
00283     hb->addWidget( board, 100 );
00284     hb->addStretch();
00285 
00286     setCentralWidget(w);
00287 
00288     setToolBarsMovable( FALSE );
00289 
00290     QToolBar *tb = new QToolBar(this);
00291     tb->setHorizontalStretchable( TRUE );
00292 
00293     QToolButton *btn = new QToolButton( Opie::Core::OResource::loadPixmap("new", Opie::Core::OResource::SmallIcon), tr("New Game"), 0,
00294                      board, SLOT(clear()), tb, "NewGame");
00295     btn->setUsesBigPixmap( qApp->desktop()->size().width() > 330 );
00296 
00297     score = new QToolButton(tb);
00298     score->setText("");
00299     score->setMaximumHeight(20);
00300     score->setUsesTextLabel(TRUE);
00301     tb->setStretchableWidget(score);
00302 
00303     connect(board, SIGNAL(scoreChanged(int,int)), this, SLOT(setScore(int,int)));
00304     connect(score, SIGNAL(clicked()), board, SLOT(resetScore()));
00305 
00306     int a, b;
00307     board->getScore(&a, &b);
00308     setScore(a,b);
00309 
00310     layout()->setResizeMode(QLayout::FreeResize);
00311 }
00312 
00313 void MindBreaker::setScore(int turns, int games)
00314 {
00315     double average;
00316     double total_turns = turns;
00317     double total_games = games;
00318 
00319     if(total_games > 0)
00320         average = total_turns / total_games;
00321     else
00322         average = 0.0;
00323 
00324     score->setText(tr("win avg: %1 turns (%2 games)").arg(average).arg(games));
00325 }
00326 
00327 void MindBreaker::resizeEvent( QResizeEvent *e )
00328 {
00329     board->fixSize();
00330     QMainWindow::resizeEvent( e );
00331 }
00332 
00333 
00334 MindBreakerBoard::MindBreakerBoard( QWidget *parent,
00335                                     const char *name, int wFlags )
00336            : QCanvasView(0, parent, name, wFlags),
00337             moving(0), game_over(FALSE), total_turns(0), total_games(0)
00338 {
00339     setFrameStyle( NoFrame );
00340     setupBoardSize(qApp->desktop()->width(),qApp->desktop()->height());
00341     cnv.resize(100,100);
00342     setCanvas(&cnv);
00343     setBackgroundColor( black );
00344 
00345     struct timeval tv;
00346 
00347     current_go = 0;
00348     gettimeofday(&tv, 0);
00349     srand(tv.tv_usec);
00350 
00351     canvas()->setAdvancePeriod(500);
00352     current_highlight = 0;
00353 
00354     widthTimer = new QTimer( this );
00355     connect(widthTimer, SIGNAL(timeout()), this, SLOT(doFixSize()) );
00356 
00357     setMaximumWidth( QMIN(qApp->desktop()->height(),qApp->desktop()->width()) );
00358     //doFixSize(); // build images... needs to be done before reading config.
00359     //readConfig(); // first read... to ensure initial labels and side look right.
00360 }
00361 
00362 void MindBreakerBoard::readConfig()
00363 {
00364     Config c("MindBreaker", Config::User);
00365     c.setGroup("Board");
00366     game_over = FALSE;
00367     int i;
00368     if (c.readNumEntry("Answer0") < 0) {
00369         for (i = 0; i < 4; i++) {
00370             answer[i] = rand() % 6;
00371             current_guess[i] = 6;
00372         }
00373         total_turns = 0;
00374         total_games = 0;
00375     } else {
00376         int j;
00377         c.setGroup("Score");
00378         total_turns = c.readNumEntry("Turns");
00379         total_games = c.readNumEntry("Games");
00380         if(total_turns < 0)
00381             total_turns = 0;
00382         if(total_games < 0)
00383             total_games = 0;
00384 
00385 
00386         checkScores();
00387         c.setGroup("Board");
00388         for(i = 0; i < 4; i++)
00389             answer[i] = c.readNumEntry(QString("Answer%1").arg(i));
00390         /* read, and parse past guesses */
00391         current_go = 0;
00392         for(j=0; j < 9; j++) {
00393             current_guess[0] = c.readNumEntry(QString("Go%1p0").arg(j));
00394             if (current_guess[0] < 0)
00395                 break;
00396             placeGuessPeg(0, current_guess[0]);
00397             current_guess[1] = c.readNumEntry(QString("Go%1p1").arg(j));
00398             placeGuessPeg(1, current_guess[1]);
00399             current_guess[2] = c.readNumEntry(QString("Go%1p2").arg(j));
00400             placeGuessPeg(2, current_guess[2]);
00401             current_guess[3] = c.readNumEntry(QString("Go%1p3").arg(j));
00402             placeGuessPeg(3, current_guess[3]);
00403             checkGuess();
00404         }
00405         for(i = 0; i < 4; i++) {
00406             current_guess[i] = c.readNumEntry(QString("CurrentGo%1").arg(i));
00407             if (current_guess[i] != 6)
00408                 placeGuessPeg(i, current_guess[i]);
00409         }
00410     }
00411 }
00412 
00413 MindBreakerBoard::~MindBreakerBoard()
00414 {
00415     int i;
00416     if (game_over) {
00417         current_go = 0;
00418         /* clear the answer, clear the guess */
00419         for (i = 0; i < 4; i++) {
00420             answer[i] = rand() % 6;
00421             current_guess[i] = 6;
00422         }
00423     }
00424     writeConfig();
00425 }
00426 
00427 void MindBreakerBoard::writeConfig()
00428 {
00429     Config c("MindBreaker", Config::User);
00430     c.setGroup("Board");
00431     c.clearGroup();
00432     /* write the board */
00433     int i,j;
00434     for (i = 0; i < current_go; i++) {
00435         for(j = 0; j < 4; j++)
00436             c.writeEntry(QString("Go%1p%2").arg(i).arg(j), past_guesses[4*i+j]);
00437     }
00438     for(j = 0; j < 4; j++)
00439         c.writeEntry(QString("CurrentGo%1").arg(j), current_guess[j]);
00440     for(j = 0; j < 4; j++)
00441         c.writeEntry(QString("Answer%1").arg(j), answer[j]);
00442 
00443     c.setGroup("Score");
00444     /* write the score */
00445 
00446     c.writeEntry("Turns", total_turns);
00447     c.writeEntry("Games", total_games);
00448 }
00449 
00450 void MindBreakerBoard::getScore(int *a, int *b)
00451 {
00452     *a = total_turns;
00453     *b = total_games;
00454     return;
00455 }
00456 
00457 void MindBreakerBoard::fixSize()
00458 {
00459     hide();
00460     setMaximumWidth( parentWidget()->height() );
00461     widthTimer->start( 20, TRUE );
00462 }
00463 
00464 void MindBreakerBoard::doFixSize()
00465 {
00466     QSize s = size();
00467     int fw = frameWidth();
00468     s.setWidth(s.width() - fw);
00469     s.setHeight(s.height() - fw);
00470 
00471     /* min size is 200 x 260 */
00472 /*
00473     if (s.width() < adjusted_board_width)
00474         s.setWidth(adjusted_board_width);
00475 
00476     if (s.height() < adjusted_board_height)
00477         s.setHeight(adjusted_board_height);
00478 */
00479 
00480     if ( current_highlight ) // non-first resize
00481         writeConfig();
00482 
00483     setupBoardSize(s.width() - fw, s.height() - fw);
00484     canvas()->resize(s.width() - fw, s.height() - fw);
00485     Peg::buildImages(); // must be done BEFORE any pegs are made
00486 
00487     QImage image = Opie::Core::OResource::loadImage("mindbreaker/mindbreaker");
00488 
00489     /* copy from master image to functional images */
00490     int x = 0;
00491     int y = 0;
00492     panelImage = image.copy(x, y,  panel_width, panel_height).
00493                 smoothScale( adjusted_panel_width, adjusted_panel_height);
00494 
00495     y += panel_height;
00496     y += panel_height;
00497 
00498     titleImage = image.copy(x, y, title_width, title_height).
00499                 smoothScale( adjusted_title_width, adjusted_title_height);
00500     show();
00501 
00502     delete current_highlight;
00503     current_highlight = new Peg(canvas(), 8);
00504     current_highlight->setPlaced(TRUE);
00505     current_highlight->setX(0);
00506     current_highlight->setY(adjusted_board_height - ((current_go + 1) * adjusted_panel_height));
00507     current_highlight->setZ(0);
00508     current_highlight->show();
00509 
00510     /* set up the game */
00511     //readConfig();
00512 
00513     /* draw initial screen */
00514     //drawBackground();
00515     //canvas()->update();
00516     clear();
00517 
00518     readConfig();
00519 }
00520 
00521 void MindBreakerBoard::placeGuessPeg(int pos, int pegId)
00522 {
00523         int x = adjusted_first_peg_x_diff + (pos * adjusted_peg_spacing);
00524         int y = adjusted_board_height - ((current_go + 1) * adjusted_panel_height)
00525                 + adjusted_first_peg_y_diff;
00526 
00527         Peg *peg = new Peg(canvas(), pegId, current_go, pos);
00528         peg->setPegPos(pos);
00529         peg->setPlaced(TRUE);
00530         peg->setX(x);
00531         peg->setY(y);
00532         peg->setZ(2);
00533         peg->show();
00534 }
00535 
00536 void MindBreakerBoard::drawBackground()
00537 {
00538     int i, j, x, y, x_gap, y_gap;
00539     QPixmap background  = QPixmap(canvas()->width(), canvas()->height());
00540 
00541     QPainter painter(&background);
00542 
00543     painter.fillRect(0, 0, canvas()->width(), canvas()->height(), QColor(0,0,0));
00544     /* very first thing is to draw the bins, as everything else needs
00545      * to be drawn over them */
00546 
00547     QPen pen(QColor(85, 45, 27), 4);
00548     painter.setPen(pen);
00549     x_gap = canvas()->width() - (adjusted_panel_width + (2 * adjusted_bin_margin));
00550     //x_gap += peg_size >> 1;
00551     if (x_gap < 1)
00552         x_gap = 1;
00553 
00554     y_gap = adjusted_board_height / 6;
00555     y_gap -= (2 * adjusted_bin_margin);
00556     //y_gap += peg_size >> 1;
00557     if (y_gap < 1)
00558         y_gap = 1;
00559     x = adjusted_panel_width + adjusted_bin_margin - (adjusted_peg_size >> 1);
00560     y = adjusted_bin_margin - (adjusted_peg_size >> 1) + 2;
00561 
00562     for (i = 0; i < 6; i++) {
00563         for (j = 0; j < 10; j++) {
00564             int rx = x + (rand() % x_gap);
00565             int ry = y + (rand() % y_gap);
00566             painter.drawImage(rx,ry, Peg::imageForType(i));
00567         }
00568         y += adjusted_board_height / 6;
00569     }
00570     /* now draw the surrounding boxes */
00571     x_gap = canvas()->width() - adjusted_panel_width;
00572     if (x_gap < 1) x_gap = 1;
00573     y_gap = adjusted_board_height / 6;
00574     x = adjusted_panel_width;
00575     y = 1;
00576 
00577     for (i = 0; i < 6; i++) {
00578         painter.drawRect(x, y, x_gap, y_gap);
00579         y += y_gap;
00580     }
00581 
00582     x = 0;
00583     y = 0;
00584 
00585     painter.drawImage(x,y, titleImage);
00586     y = adjusted_title_height;
00587     /* now nine gues panels */
00588     for (i = 0; i < 9; i ++) {
00589         painter.drawImage(x, y, panelImage);
00590         y += adjusted_panel_height;
00591     }
00592 
00593     painter.flush();
00594     canvas()->setBackgroundPixmap(background);
00595 }
00596 
00597 void MindBreakerBoard::checkGuess()
00598 {
00599     int i,j;
00600     int num_white = 0;
00601     int num_black = 0;
00602     int copy_answer[4];
00603     int copy_guess[4];
00604 
00605     for(i = 0; i < 4; i++) {
00606         copy_answer[i] = answer[i];
00607         copy_guess[i] = current_guess[i];
00608         if (current_guess[i] == 6)
00609             return;
00610         if (answer[i] == current_guess[i]) {
00611             num_black++;
00612             copy_answer[i] = 6;
00613             copy_guess[i] = 7;
00614         }
00615     }
00616 
00617     /* now sure that user has completed a 'guess' */
00618     for (i = 0; i < 4; i++) {
00619         if (copy_guess[i] == 7)
00620             continue; // already marked for a black
00621         for (j = 0; j < 4; j++) {
00622             if(copy_guess[i] == copy_answer[j]) {
00623                 copy_answer[j] = 6;
00624                 num_white++;
00625                 break;
00626             }
00627         }
00628     }
00629 
00630     int x = adjusted_answerpegx;
00631     int y = (adjusted_board_height - ((current_go + 1) * adjusted_panel_height)) + adjusted_answerpegy;
00632 
00633     if (num_black == 4)
00634         game_over = TRUE;
00635 
00636     while(num_black > 0) {
00637         Peg *p = new Peg(canvas(), 7);
00638         p->setPlaced(TRUE);
00639         p->setX(x);
00640         p->setY(y);
00641         p->setZ(1);
00642         p->show();
00643         num_black--;
00644 
00645         if (x == adjusted_answerpegx)
00646             x = adjusted_answerpegx + adjusted_answerpeg_xdiff;
00647         else  {
00648             x = adjusted_answerpegx;
00649             y += adjusted_answerpeg_ydiff;
00650         }
00651     }
00652     while(num_white > 0){
00653         Peg *p = new Peg(canvas(), 6);
00654         p->setPlaced(TRUE);
00655         p->setX(x);
00656         p->setY(y);
00657         p->setZ(1);
00658         p->show();
00659         num_white--;
00660 
00661         if (x == adjusted_answerpegx)
00662             x = adjusted_answerpegx + adjusted_answerpeg_xdiff;
00663         else  {
00664             x = adjusted_answerpegx;
00665             y += adjusted_answerpeg_ydiff;
00666         }
00667     }
00668     /* move to next go */
00669     for(i = 0; i < 4; i++) {
00670         past_guesses[4*current_go+i] = current_guess[i];
00671         current_guess[i] = 6;
00672     }
00673 
00674     current_go++;
00675     if((current_go > 8) || game_over) {
00676         total_games++;
00677         if(!game_over)
00678             total_turns += 10;
00679         else
00680             total_turns += current_go;
00681 
00682         emit scoreChanged(total_turns, total_games);
00683         Peg *p = new Peg(canvas(), 9);
00684         game_over = TRUE;
00685         p->setPlaced(TRUE);
00686         p->setX(0);
00687         p->setY(0);
00688         p->setZ(0);
00689         p->show();
00690 
00691         for (i = 0; i < 4; i++) {
00692             p = new Peg(canvas(), answer[i], -1);
00693             p->setX(adjusted_first_peg_x_diff + (i * adjusted_peg_spacing));
00694             p->setY(adjusted_first_peg_y_diff);
00695             p->setZ(3);
00696             p->show();
00697         }
00698     } else {
00699        current_highlight->setY(adjusted_board_height - ((current_go + 1) * adjusted_panel_height));
00700     }
00701     canvas()->update();
00702 }
00703 
00704 void MindBreakerBoard::clear()
00705 {
00706     if(!game_over) {
00707         total_games++;
00708         total_turns += 10;
00709         emit scoreChanged(total_turns, total_games);
00710     }
00711     int i;
00712     /* reset the game board */
00713     game_over = FALSE;
00714     /* clear the answer, clear the guess */
00715     for (i = 0; i < 4; i++) {
00716         answer[i] = rand() % 6;
00717         current_guess[i] = 6;
00718     }
00719     current_go = 0;
00720 
00721     QCanvasItemList list = canvas()->allItems();
00722     QCanvasItemList::Iterator it = list.begin();
00723     for (; it != list.end(); ++it) {
00724         if (*it == current_highlight)
00725             continue;
00726         if (*it)
00727             delete *it;
00728     }
00729 
00730     current_highlight->setY(adjusted_board_height - ((current_go + 1) * adjusted_panel_height));
00731     checkScores();
00732     drawBackground();
00733     canvas()->update();
00734 }
00735 
00736 void MindBreakerBoard::resetScore()
00737 {
00738     /* are u sure */
00739 
00740     if (QMessageBox::information(this, tr( "Reset Statistics" ),
00741             tr( "Reset the win ratio?" ),
00742             tr( "OK" ), tr( "Cancel" ) ) == 0) {
00743         total_turns = 0;
00744         total_games = 0;
00745         Peg::eggLevel = 0;
00746         drawBackground();
00747         canvas()->update();
00748         emit scoreChanged(total_turns, total_games);
00749     }
00750 }
00751 
00752 /* EVENTS */
00753 
00754 void MindBreakerBoard::contentsMousePressEvent(QMouseEvent *e)
00755 {
00756     if (game_over) {
00757         null_press = TRUE;
00758         null_point = e->pos();
00759         moving = 0;
00760         return;
00761     }
00762 
00763     copy_press = FALSE;
00764     null_press = FALSE;
00765     /* ok, first work out if it is one of the bins that
00766        got clicked */
00767     if (e->x() > adjusted_panel_width) {
00768         /* its a bin, but which bin */
00769         int bin = (e->y() + 2) / (adjusted_board_height / 6);
00770         if (bin > 5)
00771             return; // missed everything
00772 
00773         /* make new peg... set it moving */
00774         moving_pos = e->pos();
00775         moving = new Peg(canvas(), bin, current_go);
00776         moving->setX(e->x() - (adjusted_peg_size >> 1));
00777         moving->setY(e->y() - (adjusted_peg_size >> 1));
00778         moving->setZ(5);
00779         moving->show();
00780         canvas()->update();
00781         return;
00782     }
00783 
00784     QCanvasItemList l = canvas()->collisions(e->pos());
00785     for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
00786         if ( (*it)->rtti() == pegRTTI ) {
00787             Peg *item = (Peg *)(*it);
00788             if (!item->hit(e->pos()))
00789                 continue;
00790             if (item->type() > 5) {
00791                 null_press = TRUE;
00792                 null_point = e->pos();
00793                 continue; /* not a color peg */
00794             }
00795             if (item->placed()) {
00796                 /* copy */
00797                 if(item->pegGo() == -1)
00798                     return;
00799                 if(item->pegGo() == current_go) {
00800                     copy_press = TRUE;
00801                     copy_peg = item;
00802                 }
00803                 moving = new Peg(canvas(),
00804                                  item->type(), current_go);
00805                 moving->setX(e->x() - (adjusted_peg_size >> 1));
00806                 moving->setY(e->y() - (adjusted_peg_size >> 1));
00807                 moving->setZ(5);
00808                 moving->show();
00809                 moving_pos = QPoint(e->x(), e->y());
00810                 canvas()->update();
00811                 return;
00812             }
00813             moving = (Peg *)*it;
00814             moving_pos = e->pos();
00815             canvas()->update();
00816             return;
00817         }
00818     }
00819     null_press = TRUE;
00820     null_point = e->pos();
00821     moving = 0;
00822 }
00823 
00824 void MindBreakerBoard::contentsMouseMoveEvent(QMouseEvent* e)
00825 {
00826     if (moving ) {
00827         moving->moveBy(e->pos().x() - moving_pos.x(),
00828                        e->pos().y() - moving_pos.y());
00829         moving_pos = e->pos();
00830         canvas()->update();
00831         return;
00832     }
00833 }
00834 
00835 void MindBreakerBoard::contentsMouseReleaseEvent(QMouseEvent* e)
00836 {
00837     /* time to put down the peg */
00838     if(moving) {
00839         if(copy_press) {
00840             /* check if collided with original. if so, delete both */
00841             copy_press = FALSE;
00842             QCanvasItemList l = canvas()->collisions(e->pos());
00843             for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
00844                 if (*it == copy_peg)
00845                     copy_press = TRUE;
00846             }
00847             if (copy_press) {
00848                 current_guess[copy_peg->pegPos()] = 6;
00849                 delete copy_peg;
00850                 delete moving;
00851                 copy_press = FALSE;
00852                 moving = 0;
00853                 copy_peg = 0;
00854                 canvas()->update();
00855                 return;
00856             }
00857         }
00858 
00859         /* first work out if in y */
00860         if (e->y() > (adjusted_board_height - (current_go * adjusted_panel_height))) {
00861             delete moving;
00862             moving = 0;
00863             canvas()->update();
00864             return;
00865         }
00866         if (e->y() < (adjusted_board_height - ((current_go + 1) * adjusted_panel_height))) {
00867             delete moving;
00868             moving = 0;
00869             canvas()->update();
00870             return;
00871         }
00872         /* ok, a valid go, but which peg */
00873         int x_bar = adjusted_first_peg_x_diff - (adjusted_peg_size >> 1);
00874         x_bar += adjusted_peg_spacing;
00875         int pos = 0;
00876         if (e->x() > x_bar)
00877             pos = 1;
00878         x_bar += adjusted_peg_spacing;
00879         if (e->x() > x_bar)
00880             pos = 2;
00881         x_bar += adjusted_peg_spacing;
00882         if (e->x() > x_bar)
00883             pos = 3;
00884         x_bar += adjusted_peg_spacing;
00885 
00886         if (e->x() > x_bar) {
00887             /* invalid x */
00888             delete moving;
00889             moving = 0;
00890             canvas()->update();
00891             return;
00892         }
00893 
00894         int x = adjusted_first_peg_x_diff + (pos * adjusted_peg_spacing);
00895         int y = adjusted_board_height - ((current_go + 1) * adjusted_panel_height)
00896                 + adjusted_first_peg_y_diff;
00897         moving->setPegPos(pos);
00898         moving->setX(x);
00899         moving->setY(y);
00900         moving->setZ(2);
00901 
00902         /* remove all other pegs from this position */
00903         QCanvasItemList l = canvas()->collisions(QPoint(x,y));
00904         for (QCanvasItemList::Iterator it=l.begin(); it !=l.end(); ++it) {
00905             if ( (*it)->rtti() == pegRTTI ) {
00906                 Peg *item = (Peg *)(*it);
00907                 if ((item != moving) && (item != current_highlight))
00908                     delete item;
00909             }
00910         }
00911         current_guess[pos] = ((Peg *)moving)->type();
00912 
00913         ((Peg *)moving)->setPlaced(true);
00914         canvas()->update();
00915         return;
00916     }
00917     moving = 0;
00918     null_point -= e->pos();
00919     if(null_point.manhattanLength() < 6) {
00920         if (game_over)
00921             clear();
00922         else
00923             checkGuess();
00924     }
00925 }
00926 
00927 void MindBreakerBoard::resizeEvent(QResizeEvent *e)
00928 {
00929     QCanvasView::resizeEvent(e);
00930     fixSize();
00931 }
00932 
00933 
00934 /* Easter egg function... beat the clock */
00935 void MindBreakerBoard::checkScores()
00936 {
00937     double games = total_games;
00938     double turns = total_turns;
00939     double g = games / 10.0;
00940     Peg::eggLevel = 0;
00941 
00942     double break_even = 5.0;
00943     if (g < 1.0)
00944         return;
00945     double avg = turns / games;
00946     g--;
00947     while (break_even >= 0.0) {
00948         if (avg >= (break_even + g))
00949             return;
00950         // score a peg.
00951         break_even -= 1.0;
00952         Peg::eggLevel = int(5.0 - break_even);
00953     }
00954 }

Generated on Sat Nov 5 16:17:22 2005 for OPIE by  doxygen 1.4.2