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

gowidget.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of 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 "gowidget.h"
00022 
00023 /* OPIE */
00024 #include <opie2/odebug.h>
00025 #include <opie2/oresource.h>
00026 #include <qpe/config.h>
00027 using namespace Opie::Core;
00028 
00029 /* QT */
00030 #include <qpainter.h>
00031 #include <qtoolbar.h>
00032 #include <qmenubar.h>
00033 #include <qaction.h>
00034 #include <qapplication.h> //processEvents()
00035 #include <qlabel.h>
00036 
00037 static const enum bVal computer_color = BLACK;
00038 
00039 static int current_handicap = 1;
00040 
00041 static QBrush *goBrush;
00042 static QPixmap *newBlackStone;
00043 static QPixmap *blackStone;
00044 static QPixmap *whiteStone;
00045 
00046 static bool smallStones = FALSE;
00047 
00048 GoMainWidget::GoMainWidget( QWidget *parent, const char* name, WFlags fl) :
00049         QMainWindow( parent, name, fl )
00050 {
00051     setCaption( tr( "Go" ) );
00052      setToolBarsMovable( FALSE );
00053     GoWidget *go = new GoWidget(this);
00054 
00055     setCentralWidget(go);
00056     toolbar = new QToolBar(this);
00057     toolbar->setHorizontalStretchable( TRUE );
00058     addToolBar(toolbar);
00059 
00060     QMenuBar *mb = new QMenuBar( toolbar );
00061     mb->setMargin(0);
00062     QPopupMenu *file = new QPopupMenu( this );
00063 
00064     QAction *a = new QAction( tr( "New Game" ), QString::null, 0, this, 0 );
00065     connect( a, SIGNAL( activated() ), go, SLOT( newGame() ) );
00066     a->addTo( file );
00067 
00068     a = new QAction( tr( "Pass" ), Opie::Core::OResource::loadPixmap( "pass", Opie::Core::OResource::SmallIcon ),
00069                      QString::null, 0, this, 0 );
00070     connect( a, SIGNAL( activated() ), go, SLOT( pass() ) );
00071     a->addTo( file );
00072     a->addTo( toolbar );
00073 
00074 
00075     a = new QAction( tr( "Resign" ), Opie::Core::OResource::loadPixmap( "reset", Opie::Core::OResource::SmallIcon ),
00076                      QString::null, 0, this, 0 );
00077     connect( a, SIGNAL( activated() ), go, SLOT( resign() ) );
00078     a->addTo( file );
00079 
00080     a = new QAction( tr( "Two player option" ),  QString::null, 0, this, 0 );
00081     a->setToggleAction( TRUE );
00082     connect( a, SIGNAL( toggled(bool) ), go, SLOT( setTwoplayer(bool) ) );
00083     a->addTo( file );
00084 
00085     mb->insertItem( tr( "Game" ), file );
00086 
00087     QLabel *turnLabel = new QLabel( toolbar );
00088     turnLabel->setBackgroundMode( PaletteButton );
00089     connect( go, SIGNAL(showTurn(const QPixmap&)),
00090              turnLabel, SLOT(setPixmap(const QPixmap&)) );
00091 
00092 
00093     QLabel * scoreLabel = new QLabel( toolbar );
00094     scoreLabel->setBackgroundMode( PaletteButton );
00095     connect( go, SIGNAL(showScore(const QString&)),
00096              scoreLabel, SLOT(setText(const QString&)) );
00097 
00098     toolbar->setStretchableWidget( scoreLabel );
00099 
00100     go->readConfig();
00101 }
00102 
00103 void GoMainWidget::resizeEvent( QResizeEvent * )
00104 {
00105     //### this won't work because of the text label...
00106     /*
00107     if ( width() > height() )
00108         moveToolBar( toolbar, Left );
00109     else
00110         moveToolBar( toolbar, Top );
00111     */
00112 }
00113 
00114 GoWidget *GoWidget::self = 0;
00115 
00116 GoWidget::GoWidget( QWidget *parent, const char* name) :
00117         QWidget( parent, name )
00118 {
00119     if ( self )
00120         fatal( "Only one Go widget allowed" );
00121     self = this;
00122     twoplayer = FALSE;
00123 
00124 
00125     d = bx = by = 1;
00126 
00127     QPixmap pix = Opie::Core::OResource::loadPixmap( "go/pine" );
00128     goBrush = new QBrush( black, pix );
00129     blackStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-black" ));
00130     whiteStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-white" ));
00131     newBlackStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-black-highlight" ));
00132 
00133     init();
00134 }
00135 
00136 GoWidget::~GoWidget()
00137 {
00138     writeConfig();
00139 }
00140 
00141 void GoWidget::writeConfig()
00142 {
00143     Config cfg("Go");
00144     cfg.setGroup("Game");
00145     cfg.writeEntry("TwoPlayer", twoplayer);
00146     cfg.writeEntry("CurrentPlayer", currentPlayer);
00147     cfg.writeEntry("NPassed", nPassed);
00148     QString b;
00149     for (int i=0; i<19; i++)
00150         for (int j=0; j<19; j++)
00151             b += board[i][j] == BLACK ? 'B' : board[i][j] == WHITE ? 'W' : '.';
00152     cfg.writeEntry("Board", b);
00153     cfg.writeEntry("LastX", lastX);
00154     cfg.writeEntry("LastY", lastY);
00155     extern int blackPrisoners, whitePrisoners;
00156     cfg.writeEntry("BlackPrisoners", blackPrisoners);
00157     cfg.writeEntry("WhitePrisoners", whitePrisoners);
00158 }
00159 
00160 void GoWidget::readConfig()
00161 {
00162     init();
00163     Config cfg("Go");
00164     cfg.setGroup("Game");
00165     twoplayer = cfg.readBoolEntry("TwoPlayer");
00166     currentPlayer = (bVal)cfg.readNumEntry("CurrentPlayer",1);
00167     nPassed = cfg.readNumEntry("NPassed",0);
00168     QString b = cfg.readEntry("Board");
00169     if ( b.length() == 19*19 )
00170         for (int i=0; i<19; i++)
00171             for (int j=0; j<19; j++) {
00172                 QChar ch = b[j+19*i];
00173                 if ( ch != '.' )
00174                     GoPlaceStone( ch == 'B' ? BLACK : WHITE, i, j );
00175             }
00176     lastX = cfg.readNumEntry("LastX");
00177     lastY = cfg.readNumEntry("LastY");
00178     extern int blackPrisoners, whitePrisoners;
00179     blackPrisoners = cfg.readNumEntry("BlackPrisoners",0);
00180     whitePrisoners = cfg.readNumEntry("WhitePrisoners",0);
00181     reportPrisoners(blackPrisoners,whitePrisoners);
00182     emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
00183 }
00184 
00185 void GoWidget::resizeEvent( QResizeEvent * )
00186 {
00187     d = QMIN(width(),height())/19;
00188     //    int r = (d/2-1);
00189     bx = (width() - 18*d)/2 ;
00190     by = (height() - 18*d)/2 ;
00191 
00192     if ( d < 10 && !smallStones ) {
00193         blackStone->convertFromImage( blackStone->convertToImage().smoothScale(8,8) );
00194         whiteStone->convertFromImage( whiteStone->convertToImage().smoothScale(8,8) );
00195         newBlackStone->convertFromImage( newBlackStone->convertToImage().smoothScale(8,8) );
00196 
00197         smallStones = TRUE;
00198     } else if ( d >= 10 && smallStones ) {
00199         blackStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-black" ));
00200         whiteStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-white" ));
00201         newBlackStone = new QPixmap(Opie::Core::OResource::loadPixmap( "Go-black-highlight" ));
00202         smallStones = FALSE;
00203     }
00204 }
00205 
00206 void GoWidget::init()
00207 {
00208     lastX = lastY = newX = newY = -1;
00209     nPassed = 0;
00210     for ( int i = 0; i < 19; i++ )
00211         for ( int j = 0; j < 19; j++ )
00212             board[i][j]=-1;
00213     gameActive = TRUE;
00214     goRestart(current_handicap);
00215 
00216     if ( twoplayer ) {
00217         currentPlayer = BLACK;
00218     } else {
00219         doComputerMove();
00220         currentPlayer = WHITE;
00221     }
00222     emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
00223 }
00224 
00225 void GoWidget::paintEvent( QPaintEvent *e )
00226 {
00227     int i,j;
00228 
00229     int r = whiteStone->width()/2;
00230 
00231     QPainter p(this);
00232     p.fillRect( bx - d/2, by - d/2, 19*d, 19*d, *goBrush );
00233 
00234     int xMin = QMAX( x2board(e->rect().left()), 0 );
00235     int xMax = QMIN( x2board(e->rect().right()), 18 );
00236     int yMin = QMAX( y2board(e->rect().top()), 0 );
00237     int yMax = QMIN( y2board(e->rect().bottom()), 18 );
00238 
00239     QColor pine( 255, 186, 89 );
00240     p.setPen( pine.dark() );
00241 
00242     for ( i = xMin; i < xMax+1 ; i ++ ) {
00243         p.drawLine( bx+i*d, by, bx+i*d, by+18*d );
00244     }
00245     for ( j = yMin; j < yMax+1 ; j ++ ) {
00246         p.drawLine( bx, by+j*d, bx+18*d, by+j*d);
00247     }
00248 
00249     // dots are at (3,3), (3,9), (3,15) and so on
00250     p.setBrush( black );
00251     for ( i = 3; i < xMax+1; i+=6 )
00252         for ( j = 3; j < yMax+1; j+=6 )
00253             p.drawEllipse( bx+i*d-2, by+j*d-2, 5, 5 );
00254 
00255 
00256     for ( i = xMin; i < xMax+1; i++ )
00257         for ( j = yMin; j < yMax+1; j++ ) {
00258             if ( board[i][j] == WHITE ||
00259                  currentPlayer==WHITE && newX == i && newY == j )
00260                 p.drawPixmap( bx+i*d - r, by+j*d - r, *whiteStone );
00261             else if ( i == lastX && j == lastY )
00262                 p.drawPixmap( bx+i*d - r, by+j*d - r, *newBlackStone );
00263             else if ( board[i][j] == BLACK ||
00264                       currentPlayer==BLACK && newX == i && newY == j)
00265                 p.drawPixmap( bx+i*d - r, by+j*d - r, *blackStone );
00266         }
00267 }
00268 
00269 void GoWidget::doMove( int x, int y )
00270 {
00271 
00272     if ( !GoPlaceStone( currentPlayer, x, y ) ) {
00273         //printf( "Illegal move (%d,%d)\n", x, y );
00274         return;
00275     }
00276     //printf( "you do (%d,%d)\n", x, y );
00277     nPassed = 0;
00278     if ( twoplayer )
00279         currentPlayer = (currentPlayer==WHITE) ? BLACK : WHITE;
00280     else
00281         doComputerMove();
00282 
00283     emit showTurn( currentPlayer == WHITE ? *whiteStone : *blackStone );
00284 
00285 }
00286 
00287 void GoWidget::pass()
00288 {
00289     if ( !gameActive )
00290         return;
00291     nPassed++;
00292     if ( nPassed >= 2 )
00293         endGame();
00294     else if ( !twoplayer )
00295         doComputerMove();
00296 }
00297 
00298 void GoWidget::resign()
00299 {
00300     if ( gameActive )
00301         endGame();
00302 }
00303 
00304 
00305 void GoWidget::newGame()
00306 {
00307     init();
00308     update();
00309 }
00310 
00311 
00312 void GoWidget::endGame()
00313 {
00314     gameActive = FALSE;
00315 
00316     int w,b;
00317     CountUp( &w, &b);
00318     QString s = tr("White %1, Black %2. ").arg(w).arg(b);
00319     if ( w > b )
00320         s += tr("White wins.");
00321     else if ( w < b )
00322         s += tr("Black wins.");
00323     else
00324         s += tr("A draw.");
00325     emit showScore( s );
00326 }
00327 
00328 void GoWidget::doComputerMove()
00329 {
00330     int ox = lastX;
00331     int oy = lastY;
00332     lastX = lastY = -1;
00333     emit showTurn( *blackStone );
00334     refresh( ox, oy);
00335     qApp->processEvents();
00336     short int x,y;
00337     if ( genMove( computer_color, &x, &y ) ) {
00338         lastX = x;
00339         lastY = y;
00340         //printf( "I do (%d,%d)\n", x, y );
00341         GoPlaceStone(computer_color,x,y);
00342         nPassed = 0;
00343     } else {
00344         emit showScore( tr("I pass") );
00345         nPassed++;
00346         if ( nPassed >= 2 )
00347             endGame();
00348     }
00349 }
00350 
00351 void GoWidget::mousePressEvent( QMouseEvent *me )
00352 {
00353     if ( !gameActive )
00354         return;
00355     int x = x2board(me->x());
00356     int y = y2board(me->y());
00357     showStone(x,y,currentPlayer);
00358 }
00359 
00360 void GoWidget::mouseMoveEvent( QMouseEvent *me )
00361 {
00362     if ( !gameActive )
00363         return;
00364     int x = x2board(me->x());
00365     int y = y2board(me->y());
00366     if ( x != newX || y != newY )
00367         showStone(x,y,currentPlayer);
00368 }
00369 
00370 void GoWidget::showStone( int x, int y, enum bVal c )
00371 {
00372 
00373     if ( newX > -1 ) {
00374         refresh( newX, newY );
00375         newY = newX = -1;
00376     }
00377     if ( x < 0 || x > 18 || y < 0 || y > 18 ) {
00378         newX = newY = -1;
00379         return;
00380     }
00381     if ( board[x][y] == -1 && !Suicide( c, x, y ) ) {
00382         newX = x;
00383         newY = y;
00384         refresh(x,y);
00385     }
00386 
00387 }
00388 
00389 void GoWidget::mouseReleaseEvent( QMouseEvent * )
00390 {
00391     if ( gameActive && newX > -1 )
00392         doMove( newX, newY );
00393     newX = newY = -1;
00394 }
00395 
00396 void GoWidget::refresh( int x, int y )
00397 {
00398     update( bx+d*x-d/2-1, by+d*y-d/2-1, d+2, d+2 );
00399 }
00400 
00401 void GoWidget::removeStone(short x, short y)
00402 {
00403     board[x][y]=-1;
00404     refresh( x, y );
00405 }
00406 
00407 void GoWidget::placeStone (enum bVal c, short x, short y )
00408 {
00409     board[x][y]=c;
00410     refresh( x, y );
00411 }
00412 
00413 void GoWidget::reportPrisoners( int blackcnt, int whitecnt )
00414 {
00415     QString s = tr( "Prisoners: black %1, white %2" ).arg(blackcnt).arg(whitecnt);
00416     emit showScore( s );
00417 }
00418 
00419 void GoWidget::setTwoplayer( bool b )
00420 {
00421     twoplayer = b;
00422 }
00423 
00424 void GoWidget::setHandicap( int h )
00425 {
00426     current_handicap = h;
00427 }
00428 
00429 
00430 extern "C" {
00431 
00432 void    removestone(short x, short y)
00433 {
00434     GoWidget::self->removeStone(x,y);
00435 }
00436 
00437 void    placestone (enum bVal c, short x, short y )
00438 {
00439     GoWidget::self->placeStone(c,x,y);
00440 }
00441 
00442 void    intrMoveReport(enum bVal c ,char *coord ,char *reason )
00443 {
00444     odebug << "intrMoveReport colour " << c << ", " << coord << " " << reason << "" << oendl; 
00445 }
00446 
00447 void    intrPrisonerReport( short blackcnt, short whitecnt )
00448 {
00449     GoWidget::self->reportPrisoners(blackcnt,whitecnt);
00450 }
00451 
00452 }
00453 

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