kwin4doc.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE games kwin4 program
00003    Copyright (c) 2006 Martin Heni <kde@heni-online.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library 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 GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 // include files for Qt
00022 #include <QDir>
00023 #include <QTimer>
00024 #include <QKeyEvent>
00025 #include <QList>
00026 #include <QMouseEvent>
00027 
00028 // include files for KDE
00029 #include <klocale.h>
00030 #include <kstandarddirs.h>
00031 #include <kdebug.h>
00032 #include <krandomsequence.h>
00033 #include <kapplication.h>
00034 #include <kglobal.h>
00035 
00036 // application specific includes
00037 #include "kwin4doc.h"
00038 #include "kwin4view.h"
00039 #include "scoresprite.h"
00040 #include "prefs.h"
00041 #include "score.h"
00042 #include "ui_statuswidget.h"
00043 #include "config-src.h"
00044 
00045 
00046 #define FIELD_SIZE_X 7
00047 #define FIELD_SIZE_Y 6
00048 
00049 // Constructor
00050 KWin4Doc::KWin4Doc(QWidget *parent) : KGame(1234,parent), pView(0), mHintProcess(0)
00051 {
00052   mStatus = new Score(parent);
00053 
00054   connect(this,SIGNAL(signalPropertyChanged(KGamePropertyBase *,KGame *)),
00055           this,SLOT(gamePropertyChanged(KGamePropertyBase *,KGame *)));
00056 
00057   dataHandler()->Debug();
00058   //kDebug(12010) << "Property 7 policy=" << dataHandler()->find(7)->policy() << endl; 
00059   setPolicy(KGame::PolicyDirty,true);
00060 
00061   //kDebug(12010) << "Property 7 policy=" << dataHandler()->find(7)->policy() << endl; 
00062 
00063   // Game design
00064   setMaxPlayers(2);
00065   setMinPlayers(2);
00066 
00067   // Game initialization
00068   mField.resize(42);
00069 
00070   // ****************************************
00071   // NOTE: Do not i18n the strings here. They
00072   //       are for debugging only
00073   // ****************************************
00074   
00075   // The field array needs not be updated as any move will change it
00076   // Careful only in new resetGame! Maybe unlocal it there!
00077   //  mField.setPolicy(KGamePropertyBase::PolicyLocal);  
00078   mField.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mField"));
00079 
00080   mFieldFilled.resize(7);
00081   mHistory.resize(43);
00082   mHistory.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mHistory"));
00083 
00084   mAmzug.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mAmzug"));
00085   mCurrentMove.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mCurrentMove"));
00086   mMaxMove.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mMaxMove"));
00087   mFieldFilled.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mFieldFilled"));
00088   mHistoryCnt.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mHistoryCnt"));
00089   mLastColumn.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mLastColumn"));
00090   mLastHint.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mLastHint"));
00091   mLastColour.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mLastColour"));
00092   mScore.registerData(dataHandler(),KGamePropertyBase::PolicyLocal,QString("mScore"));
00093 
00094   // game startup parameter
00095   mStartPlayer=Yellow;
00096   mStartPlayer.registerData(dataHandler(),KGamePropertyBase::PolicyDirty,QString("mStartPlayer"));
00097   setCurrentPlayer((COLOUR)mStartPlayer.value()); 
00098   if (global_debug>1) kDebug(12010) << "amZug policy=" << mAmzug.policy() << endl;
00099 
00100   mPlayedBy[Yellow] = KGameIO::MouseIO;
00101   mPlayedBy[Red]  = KGameIO::MouseIO;
00102 
00103   // last in init
00104   resetGame(false);
00105   
00106   setGameStatus(Intro);
00107 
00108   // Listen to network
00109   connect(this,SIGNAL(signalMessageUpdate(int, quint32, quint32)),
00110          this,SLOT(networkMessageUpdate(int, quint32, quint32)));
00111   connect(this,SIGNAL(signalClientJoinedGame(quint32, KGame*)),
00112          this,SLOT(clientConnected(quint32, KGame*)));
00113 
00114   // Change global KGame policy
00115   //dataHandler()->setPolicy(KGamePropertyBase::PolicyDirty,false);
00116   dataHandler()->Debug();
00117 }
00118 
00119 
00120 // Destructor
00121 KWin4Doc::~KWin4Doc()
00122 {
00123   writeConfig(KGlobal::config().data());
00124   if (mHintProcess) delete mHintProcess;
00125   delete mStatus;
00126   mStatus = 0;
00127 }
00128 
00129 
00130 // Player initialization
00131 void KWin4Doc::initPlayers()
00132 {
00133   // Create yellow 
00134   KWin4Player* yellow = (KWin4Player*)createPlayer(1, mPlayedBy[Yellow], false);
00135   yellow->setUserId(Yellow);
00136   yellow->setName(Prefs::name1());
00137   addPlayer(yellow);
00138   setPlayedBy(Yellow,mPlayedBy[Yellow]);
00139 
00140   // Create Red
00141   KWin4Player* red = (KWin4Player*)createPlayer(1, mPlayedBy[Red], false);
00142   red->setUserId(Red);
00143   red->setName(Prefs::name1());
00144   addPlayer(red);
00145   setPlayedBy(Red,mPlayedBy[Red]);
00146 }
00147 
00148 
00149 // Set the view to the doc
00150 void KWin4Doc::setView(KWin4View *view)
00151 {
00152   pView=view;
00153   connect(pView, SIGNAL(signalMoveDone(int)), this, SLOT(moveDone(int)));
00154 }
00155 
00156 
00157 // Returns colour on the game board
00158 COLOUR KWin4Doc::getColour(int x,int y)
00159 {
00160   return (COLOUR)mField.at(x+y*FIELD_SIZE_X);
00161 }
00162 
00163 
00164 // Set the colour on the game board
00165 void KWin4Doc::setColour(int x,int y,COLOUR c)
00166 {
00167   if (x<0 || x>=FIELD_SIZE_X || y<0 || y>=FIELD_SIZE_Y)
00168   {
00169     kFatal(12010) << "ERROR: setColour on wrong position " << x << " " << y << endl;
00170     return ;
00171   }
00172   mField.setAt(x+y*FIELD_SIZE_X,c);
00173 }
00174 
00175 
00176 // Reset the whole game (and the view)
00177 void KWin4Doc::resetGame(bool initview)
00178 {
00179   // Reset field
00180   for (int x=0;x<FIELD_SIZE_X;x++)
00181   {
00182     for (int y=FIELD_SIZE_Y-1;y>=0;y--)
00183     {
00184       setColour(x,y,Nobody);
00185     }
00186   }
00187   mFieldFilled.fill(0);
00188 
00189   // Reset game vars
00190   mHistoryCnt=0;
00191   mCurrentMove=0;
00192   mMaxMove=0;
00193   mLastColumn=-1;
00194   mLastColour=Nobody;
00195   setScore(0);
00196   mLastHint=-1;
00197 
00198   // Reset the view
00199   if (initview)
00200   {
00201     pView->initGame(mStatus);
00202   }
00203   
00204   // Who starts this game
00205   setCurrentPlayer((COLOUR)mStartPlayer.value()); 
00206 }
00207 
00208 
00209 // Set current player to setTurn true
00210 void KWin4Doc::activateCurrentPlayer()
00211 {
00212   if (global_debug>1)
00213     kDebug(12010) << "Setting the current player to turn"<<endl;
00214   getPlayer(getCurrentPlayer())->setTurn(true,true);
00215 }
00216 
00217 
00218 // End a game. Update statistic and forward end game to view.
00219 void KWin4Doc::endGame(TABLE mode)
00220 {
00221   setGameStatus(End);
00222   // TODO pView->clearError();
00223   pView->endGame();
00224   KWin4Player *yellow=getPlayer(Yellow);
00225   KWin4Player *red=getPlayer(Red);
00226 
00227   switch(mode)
00228   {
00229     case TWin:  yellow->incWin();
00230                 red->incLost();
00231     break;
00232     case TLost: yellow->incLost();
00233                 red->incWin();
00234     break;
00235     case TRemis: yellow->incRemis();
00236                  red->incRemis();
00237     break;
00238     default:
00239        // Only break if moves have been made
00240        if (mMaxMove>0)
00241        {
00242           yellow->incBrk();
00243           red->incBrk();
00244        }
00245     break;
00246   }
00247   // switch start player
00248 }
00249 
00250 
00251 // Indication that a move has been visually done
00252 void KWin4Doc::moveDone(int /*mode*/ )
00253 {
00254   if (playerCount()>1)
00255   {
00256     playerInputFinished(getPlayer(getCurrentPlayer()));
00257   }
00258 
00259   // TODO pView->clearError();
00260 }
00261 
00262 
00263 // Calculate the next players to turn. Here the players just swap.
00264 KPlayer* KWin4Doc::nextPlayer(KPlayer* last, bool /*exclusive*/)
00265 {
00266   if (global_debug>1)
00267      kDebug(12010) << k_funcinfo << "nextPlayer last="<<last->id() << " admin=" << isAdmin() <<endl;
00268 
00269   // Should be enough if the admin sets the turn
00270   if (last->userId()==Yellow)
00271     setCurrentPlayer(Red);
00272   else
00273     setCurrentPlayer(Yellow);
00274   if (global_debug>1)
00275     kDebug(12010) <<" Current set to "<<getCurrentPlayer()<<endl;
00276   if (isAdmin())
00277     getPlayer(getCurrentPlayer())->setTurn(true,true);
00278   emit signalNextPlayer(int(getCurrentPlayer()));
00279   return getPlayer(getCurrentPlayer());
00280 }
00281 
00282 
00283 // Performs a game move on the given x position. Just calls makeMove()
00284 // and transforms the return value so that true indicates a valid move.
00285 bool KWin4Doc::doMove(int x,int id)
00286 {
00287   if (global_debug>1)
00288     kDebug(12010) <<" KWin4Doc::Move pos="<<x<<" id="<<id<<" "<<endl;
00289 
00290   return (makeMove(x,0) == GNormal);
00291 }
00292 
00293 
00294 // Make a game move on the given position. Display it in the view.
00295 // mode=0 normal move, =1: redo move
00296 MOVESTATUS KWin4Doc::makeMove(int x, int mode)
00297 {
00298   if (x<0 || x>=FIELD_SIZE_X)
00299   {
00300     kDebug(12010) << "ERROR: makeMove auf falsche Position " << x << endl;
00301     return GNotAllowed;
00302   }
00303 
00304   int y=mFieldFilled.at(x);
00305 
00306   if (y>=FIELD_SIZE_Y)
00307   {
00308     return GIllMove;  // no space left in column
00309   }
00310 
00311   if (mLastHint>=0)
00312   {
00313     int hy;
00314     hy=mFieldFilled.at(mLastHint);
00315     setColour(mLastHint,hy,Nobody);
00316     mLastHint=-1;
00317   }
00318   if (mode==Tip)
00319   {
00320     mLastHint=x;
00321     setColour(x,y,Tip);
00322     return GTip ;  // no real move
00323   }
00324 
00325   mFieldFilled.setAt(x,mFieldFilled.at(x)+1);
00326   setColour(x,y,getCurrentPlayer());
00327   
00328   mHistory.setAt(getHistoryCnt(),x);
00329   mHistoryCnt=mHistoryCnt.value()+1;
00330 
00331   mLastColour=getCurrentPlayer();
00332   //if (getCurrentPlayer()==Yellow) setCurrentPlayer(Red);
00333   //else setCurrentPlayer(Yellow);
00334 
00335   mCurrentMove=mCurrentMove.value()+1;
00336 
00337   // only if a real move isdone the maxmove is raised
00338   if (mode==0) mMaxMove=mCurrentMove.value();
00339   mLastColumn=x;
00340 
00341   // Show graphics
00342   pView->displayMove(x, y, mLastColour, x, mLastColour, mCurrentMove-1 , mode==1?false:true);
00343  
00344   return GNormal;
00345 }
00346 
00347 
00348 // Undo a move.
00349 bool KWin4Doc::undoMove()
00350 {
00351   if (getHistoryCnt()<1) return false;
00352   
00353   if (mLastHint>=0)
00354   {
00355     int hy;
00356     hy=mFieldFilled.at(mLastHint);
00357     setColour(mLastHint,hy,Nobody);
00358     mLastHint=-1;
00359   }
00360   // kDebug(12010) << "Undo no="<<mHistoryCnt.value() << endl;
00361   mHistoryCnt=mHistoryCnt.value()-1;
00362   int x=mHistory.at(getHistoryCnt());
00363   mFieldFilled.setAt(x,mFieldFilled.at(x)-1);
00364   int y=mFieldFilled.at(x);
00365   // kDebug(12010) << "Undo x="<<x << " y=" <<y << endl;
00366   setColour(x,y,Nobody);
00367   // We have to remove the piece as well...
00368 
00369   mLastColour=getCurrentPlayer();
00370   if (getCurrentPlayer()==Yellow) setCurrentPlayer(Red);
00371   else setCurrentPlayer(Yellow);
00372   mCurrentMove=mCurrentMove.value()-1;
00373 
00374   // Display move and arrow history
00375   if (getHistoryCnt()>0)
00376   {
00377     pView->displayMove(x, y, Nobody, mHistory.at(getHistoryCnt()-1), mLastColour.value(), mCurrentMove, false);
00378   }
00379   else
00380   {
00381     pView->displayMove(x, y, Nobody, -1, Nobody, mCurrentMove, false);
00382   }
00383 
00384   if (getHistoryCnt()>0)
00385     mLastColumn=mHistory.at(getHistoryCnt()-1);
00386   else
00387     mLastColumn=-1;
00388 
00389   setScore(0);
00390 
00391   return true;
00392 }
00393 
00394 
00395 // Redo a move
00396 bool KWin4Doc::redoMove()
00397 {
00398   if (getHistoryCnt()>=mMaxMove) return false;
00399   
00400   int x=mHistory.at(getHistoryCnt());
00401   //kDebug(12010) << "Redo x=" << x << endl;
00402   makeMove(x,1);
00403   if (getCurrentPlayer()==Yellow)
00404     setCurrentPlayer(Red);
00405   else
00406     setCurrentPlayer(Yellow);
00407   setScore(0);
00408   return true;
00409 }
00410 
00411 
00412 // Set the name of the player of the given color
00413 void KWin4Doc::setName(COLOUR col, const QString& n)
00414 {
00415   getPlayer(col)->setName(n);
00416 }
00417 
00418 
00419 // Retrieve the name of the player of the given color
00420 QString KWin4Doc::getName(COLOUR col)
00421 {
00422   return getPlayer(col)->name();
00423 }
00424 
00425 
00426 // Returns the all time statistics for player of given color
00427 // The mode determins what statistics to access.
00428 int KWin4Doc::getStatistic(COLOUR col, TABLE mode)
00429 {
00430   KWin4Player *player=getPlayer(col);
00431   switch(mode)
00432   {
00433     case TWin: return player->win();
00434     break;
00435     case TRemis: return player->remis();
00436     break;
00437     case TLost: return player->lost();
00438     break;
00439     case TBrk: return player->brk();
00440     break;
00441     case TSum:  return (player->win()+player->remis()+player->lost());
00442     default:
00443       break;
00444   }
00445   return 0;
00446 }
00447 
00448 
00449 // Retrieve the color of the i-th player. Player 0 is the start
00450 // player and player 1 the follow up player.
00451 COLOUR KWin4Doc::getPlayerColour(int player){
00452   if (player==0)
00453     return (COLOUR)mStartPlayer.value();
00454   
00455   if (mStartPlayer.value()==Yellow)
00456     return Red;
00457   else
00458     return Yellow;
00459 }
00460 
00461 
00462 // Check whether the current game has a game over situation
00463 // return -1: remis, 1:won, 0: continue
00464 int KWin4Doc::checkGameOver(KPlayer* p)
00465 {
00466   if (global_debug>1)
00467     kDebug(12010) <<"KWin4Doc::checkGameOver::"<<p->userId()<<endl;
00468   return checkGameOver(mLastColumn ,(COLOUR)(mLastColour.value()));
00469 }
00470 
00471 
00472 // Check whether the current game has a game over situation
00473 // return -1: remis, 1:won, 0: continue
00474 int KWin4Doc::checkGameOver(int x, COLOUR col)
00475 {
00476   int y,i;
00477   COLOUR c;
00478   int star=1;
00479   COLOUR winc=Nobody;
00480 
00481   // Check vertical up
00482   int flag=0;
00483   for (i=0;i<4;i++)
00484   {
00485     y=mFieldFilled.at(x)-1-i;
00486     if (y>=0)
00487     {
00488        c=getColour(x,y);
00489        if (c==col) flag++;
00490     }
00491   }
00492   if (flag>=4 )
00493   {
00494     // Store win fields
00495     for (i=0;i<4;i++)
00496     {
00497       y=mFieldFilled.at(x)-1-i;
00498       pView->displayStar(x,y,star++);
00499       winc=getColour(x,y);
00500     }
00501     return 1;
00502   }
00503   else if (flag>=4) return 1;
00504 
00505   int xx;
00506   // Check horizontal to the right
00507   y=mFieldFilled.at(x)-1;
00508   flag=0;
00509   for (i=-3;i<=3 && flag<4;i++)
00510   {
00511      xx=x+i;
00512      if (xx>=0 && xx<FIELD_SIZE_X)
00513      {
00514        c=getColour(xx,y);
00515        if (c==col) flag++;
00516        else flag=0;
00517      }
00518   }
00519   if (flag>=4 )
00520   {
00521     // Store win fields
00522     y=mFieldFilled.at(x)-1;
00523     winc=getColour(x,y);
00524     int cnt=0;
00525     for (i=0;i<4;i++)
00526     {
00527       xx=x+i;
00528       if (xx>=0 && xx<FIELD_SIZE_X)
00529       {
00530         if (getColour(xx,y)!=winc) break;
00531         pView->displayStar(xx,y,star++);
00532         cnt++;
00533       }
00534       else break;
00535     }
00536     for (i=-1;i>-4 && cnt<4;i--)
00537     {
00538       xx=x+i;
00539       if (xx>=0 && xx<FIELD_SIZE_X)
00540       {
00541         if (getColour(xx,y)!=winc) break;
00542         pView->displayStar(xx,y,star++);
00543         cnt++;
00544       }
00545       else break;
00546     }
00547     return 1;
00548   }
00549   else if (flag>=4) return 1;
00550 
00551 
00552   // Check dy+
00553   flag=0;
00554   for (i=-3;i<=3 && flag<4;i++)
00555   {
00556     xx=x+i;
00557     if (xx>=0 && xx<FIELD_SIZE_X)
00558     {
00559       y=mFieldFilled.at(x)-1-i;
00560       if (y>=0 && y<FIELD_SIZE_Y)
00561       {
00562         c=getColour(xx,y);
00563         if (c==col) flag++;
00564         else flag=0;
00565       }
00566     }
00567   }
00568   if (flag>=4 ) 
00569   {
00570     // Store win fields
00571     y=mFieldFilled.at(x)-1;
00572     winc=getColour(x,y);
00573     int cnt=0;
00574     for (i=0;i<4;i++)
00575     {
00576       xx=x+i;
00577       if (xx>=0 && xx<FIELD_SIZE_X)
00578       {
00579         y=mFieldFilled.at(x)-1-i;
00580         if (y<0) break;
00581         if (getColour(xx,y)!=winc) break;
00582         pView->displayStar(xx,y,star++);
00583         cnt++;
00584       }
00585       else break;
00586     }
00587     for (i=-1;i>-4 && cnt<4;i--)
00588     {
00589       xx=x+i;
00590       if (xx>=0 && xx<FIELD_SIZE_X)
00591       {
00592         y=mFieldFilled.at(x)-1-i;
00593         if (y>=FIELD_SIZE_Y) break;
00594         if (getColour(xx,y)!=winc) break;
00595         pView->displayStar(xx,y,star++);
00596         cnt++;
00597       }
00598       else break;
00599     }
00600     return 1;
00601   }
00602   else if (flag>=4) return 1;
00603 
00604 
00605   // Check dy-
00606   flag=0;
00607   for (i=-3;i<=3 && flag<4;i++)
00608   {
00609     xx=x+i;
00610     if (xx>=0 && xx<FIELD_SIZE_X)
00611     {
00612       y=mFieldFilled.at(x)-1+i;
00613       if (y>=0 && y<FIELD_SIZE_Y)
00614       {
00615         c=getColour(xx,y);
00616         if (c==col) flag++;
00617         else flag=0;
00618       }
00619     }
00620   }
00621   if (flag>=4 ) 
00622   {
00623     // Store win fields
00624     y=mFieldFilled.at(x)-1;
00625     winc=getColour(x,y);
00626     int cnt=0;
00627     for (i=0;i<4;i++)
00628     {
00629       xx=x+i;
00630       if (xx>=0 && xx<FIELD_SIZE_X)
00631       {
00632         y=mFieldFilled.at(x)-1+i;
00633         if (y>=FIELD_SIZE_Y) break;
00634         if (getColour(xx,y)!=winc) break;
00635         pView->displayStar(xx,y,star++);
00636         cnt++;
00637       }
00638       else break;
00639     }
00640     for (i=-1;i>-4 && cnt<4;i--)
00641     {
00642       xx=x+i;
00643       if (xx>=0 && xx<FIELD_SIZE_X)
00644       {
00645         y=mFieldFilled.at(x)-1+i;
00646         if (y<0) break;
00647         if (getColour(xx,y)!=winc) break;
00648         pView->displayStar(xx,y,star++);
00649         cnt++;
00650       }
00651       else break;
00652     }
00653     return 1;
00654   }
00655   else if (flag>=4) return 1;
00656 
00657   if (mCurrentMove>=42) return -1;
00658 
00659   return 0;
00660 }
00661 
00662 
00663 // Reset all the player stats
00664 void KWin4Doc::resetStatistic()
00665 {
00666   getPlayer(Yellow)->resetStats();
00667   getPlayer(Red)->resetStats();
00668 }
00669 
00670 
00671 // Set computer AI score value
00672 void KWin4Doc::setScore(long value)
00673 {
00674   mScore.setValue(value);
00675   kDebug() << " ************** SET AI SCORE " << value << " ****************" << endl;
00676 }
00677 
00678 
00679 // Load settings from Prefs
00680 void KWin4Doc::loadSettings()
00681 {
00682   kDebug() << "++++ KWin4Doc::loadSettings() " << endl;
00683   kDebug() << "Level: " << Prefs::level() << endl;
00684   kDebug() << "Name: " << Prefs::name1() << endl;
00685   kDebug() << "Name2: " << Prefs::name2() << endl;
00686   kDebug() << "input1: " << Prefs::input1() << endl;
00687   kDebug() << "input2: " << Prefs::input2() << endl;
00688   kDebug() << "colour1: " << Prefs::colour1() << endl;
00689 
00690 
00691   // Store level for score sprite display
00692   mStatus->setLevel(Prefs::level(), 0);
00693   mStatus->setLevel(Prefs::level(), 1);
00694 
00695   setName(Yellow, Prefs::name1());
00696   setName(Red, Prefs::name2());
00697 
00698   KGameIO::IOMode mode = KGameIO::MouseIO;
00699   
00700   int m = Prefs::input1();
00701   m = 1; // TODO: HARDCODED
00702   
00703   if(m == 0) mode = KGameIO::MouseIO;
00704   if(m == 1) mode = KGameIO::ProcessIO;
00705   if(m == 2) mode = KGameIO::KeyIO;
00706   setPlayedBy(Yellow, mode);
00707   kDebug() << "Played by Yellow="<<m<<","<<mode<<endl;  
00708   
00709   m = Prefs::input2();
00710   if(m == 0) mode = KGameIO::MouseIO;
00711   if(m == 1) mode = KGameIO::ProcessIO;
00712   if(m == 2) mode = KGameIO::KeyIO;
00713   setPlayedBy(Red, mode);
00714   kDebug() << "Played by Red="<<m<<","<<mode<<endl;  
00715 
00716   COLOUR col = (COLOUR)Prefs::colour1();
00717   if (getPlayerColour(0)!=col)
00718     switchStartPlayer();
00719 
00720 }
00721 
00722 
00723 // Read config file
00724 void KWin4Doc::readConfig(KConfig *config)
00725 {
00726   kDebug() << "++++++++++++++++++++++++++++++++++++ KWin4Doc::ReadConfig" << endl;
00727   loadSettings();
00728   
00729   KConfigGroup ygrp = config->group("YellowPlayer");
00730   getPlayer(Yellow)->readConfig(ygrp);
00731 
00732   KConfigGroup rgrp = config->group("RedPlayer");
00733   getPlayer(Red)->readConfig(rgrp);
00734 }
00735 
00736 
00737 // Write config file
00738 void KWin4Doc::writeConfig(KConfig *config)
00739 {
00740   KConfigGroup ygrp = config->group("YellowPlayer");
00741   getPlayer(Yellow)->writeConfig(ygrp);
00742 
00743   KConfigGroup rgrp = config->group("RedPlayer");
00744   getPlayer(Red)->writeConfig(rgrp);
00745 
00746   config->sync();
00747 }
00748 
00749 
00750 // Returns the current player, resp amzug.
00751 COLOUR KWin4Doc::getCurrentPlayer()
00752 {
00753   return (COLOUR)mAmzug.value();
00754 }
00755 
00756 
00757 // Set the current player
00758 void KWin4Doc::setCurrentPlayer(COLOUR no)
00759 {
00760   mAmzug.setValue(no);
00761 }
00762 
00763 
00764 // Switch the starting player and return the new started
00765 COLOUR KWin4Doc::switchStartPlayer()
00766 {
00767   if (mStartPlayer.value()==Yellow)
00768     mStartPlayer.setValue(Red);
00769   else
00770     mStartPlayer.setValue(Yellow);
00771   
00772   return (COLOUR)mStartPlayer.value();
00773 }
00774 
00775 
00776 // Retrieve the current move number.
00777 int KWin4Doc::getCurrentMove()
00778 {
00779   return mCurrentMove;
00780 }
00781 
00782 
00783 // Retrieve the maximum move number before undo
00784 int KWin4Doc::getMaxMove()
00785 {
00786   return mMaxMove;
00787 }
00788 
00789 
00790 // Retrieve the amount of history moves stored
00791 int KWin4Doc::getHistoryCnt()
00792 {
00793   return mHistoryCnt;
00794 }
00795 
00796 
00797 // Return the filename of the computer player AI process.
00798 QString KWin4Doc::findProcessName()
00799 {
00800   // Try whether we run from a development source dir
00801   #ifdef SRC_DIR
00802     QString srcname = QString(SRC_DIR)+QString("/src/kwin4proc");
00803     QFile fsrc(srcname);
00804     if (fsrc.exists())
00805     {
00806       if (global_debug>1) kDebug() << " Found SRC_DIR process " << srcname << endl;
00807       return srcname;
00808     }
00809   #endif
00810   
00811 
00812   // First try a local dir override
00813   QDir dir;
00814   // TODO: This local filename is not found!!
00815   QString filename=dir.path()+QString("/kwin4/kwin4proc");
00816   kDebug() << "FILENAME="<<filename<<endl;
00817   QFile flocal(filename);
00818   if (flocal.exists())
00819   {
00820     if (global_debug>1) kDebug() << " Found local process " << filename << endl;
00821     return filename;
00822   }
00823   QString path=KGlobal::mainComponent().dirs()->findExe("kwin4proc");
00824   if (!path.isNull())
00825   {
00826     if (global_debug>1) kDebug() << " Found system process " << path << endl;
00827     return path;
00828   }
00829   QString empty;
00830   kError() <<  "Could not locate the computer player" << endl;
00831   return empty;
00832 }
00833 
00834 
00835 // Debug: Listen to messages
00836 void KWin4Doc::networkMessageUpdate(int /*id*/,quint32 /*sender*/,quint32 /*recv*/)
00837 {
00838 //  kDebug(12010) << "MSG: id=" << id << " sender=" << sender << " receiver="<<recv<< endl;
00839 }
00840 
00841 
00842 // Create a KPlayer
00843 KPlayer *KWin4Doc::createPlayer(int /*rtti*/, int io, bool isvirtual)
00844 {
00845   KWin4Player *player = new KWin4Player;
00846   if (!isvirtual)
00847     createIO(player,(KGameIO::IOMode)io);
00848   
00849   connect(player,SIGNAL(signalPropertyChanged(KGamePropertyBase *, KPlayer *)),
00850           this,SLOT(playerPropertyChanged(KGamePropertyBase *, KPlayer *)));
00851   player->setStatus(mStatus);
00852   return player;
00853 }
00854 
00855 
00856 // Called when a player input is received from the KGame object 
00857 // this is e.g. a mouse event, the AI or the network
00858 bool KWin4Doc::playerInput(QDataStream& msg, KPlayer* /*player*/)
00859 {
00860   qint32 move, pl;
00861   msg >> pl >> move;
00862   kDebug() << "KWin4Doc::playerInput pl="<<pl<<" and move=" << move <<endl;
00863 
00864   // Perform move and check for success
00865   if (!doMove(move,pl))
00866   {
00867     // Repeat the same input
00868     QTimer::singleShot(0, this,SLOT(repeatMove()));
00869   }
00870 
00871   return false;
00872 }
00873 
00874 
00875 // Reactivate player in case of a move which could not pe performed.
00876 void KWin4Doc::repeatMove()
00877 {
00878   getPlayer(getCurrentPlayer())->setTurn(true);
00879 }
00880 
00881 
00882 // Query the IO mode of player og the given color.
00883 KGameIO::IOMode KWin4Doc::playedBy(int col)
00884 {
00885   return mPlayedBy[col];
00886 }
00887 
00888 
00889 // Sets the input device mode for the given player color.
00890 void KWin4Doc::setPlayedBy(int col, KGameIO::IOMode io)
00891 {
00892   if (global_debug>1)
00893     kDebug(12010) << "  KWin4Doc::setPlayedBy(int "<<col<<",KGameIO::IOMode "<<io<<")" << endl;
00894 
00895   KWin4Player *player=getPlayer((COLOUR)col);
00896 
00897   // Modes for the score sprite
00898   player->status()->setPlayedBy((int)io,player->userId());
00899 
00900   if (mPlayedBy[col]!=io && !player->isVirtual())
00901   {
00902     mPlayedBy[col]=io;
00903     player->removeGameIO(0); // remove all IO's
00904     createIO(player,io);
00905   }
00906 }
00907 
00908 
00909 // Get the io values right after a load game as the io the playedby
00910 // is not set there.
00911 void KWin4Doc::recalcIO()
00912 {
00913   mPlayedBy[Yellow]=(KGameIO::IOMode)getPlayer(Yellow)->calcIOValue();
00914   mPlayedBy[Red]=(KGameIO::IOMode)getPlayer(Red)->calcIOValue();
00915 }
00916 
00917 
00918 // Create player input devicea (KGame)
00919 void KWin4Doc::createIO(KPlayer* player, KGameIO::IOMode io)
00920 {
00921   if (!player)
00922     return;
00923   
00924   if (global_debug>1)
00925     kDebug() << " KWin4Doc::createIO(KPlayer *player("<<player->userId()<<"),KGameIO::IOMode "<<io<<") " << endl;
00926 
00927   if (io&KGameIO::MouseIO)
00928   {
00929     KGameMouseIO *input;
00930     if (global_debug>1) kDebug() << "Creating MOUSE IO to "<<pView<< endl;
00931     // We want the player to work over mouse
00932     input=new KGameMouseIO(pView->viewport());
00933     if (global_debug>1) kDebug(12010) << "MOUSE IO added " << endl;
00934     // Connect mouse input to a function to process the actual input
00935     connect(input,SIGNAL(signalMouseEvent(KGameIO *,QDataStream &,QMouseEvent *,bool *)),
00936             pView,SLOT(mouseInput(KGameIO *,QDataStream &,QMouseEvent *,bool *)));
00937     player->addGameIO(input);
00938   }
00939   else if (io&KGameIO::ProcessIO)
00940   {
00941     QString file=findProcessName();
00942     if (global_debug>1) kDebug() << "Creating PROCESS IO " << file  << endl;
00943 
00944     KGameProcessIO *input;
00945     // We want a computer player
00946     input=new KGameProcessIO(file);
00947     // Connect computer player to the setTurn
00948     connect(input,SIGNAL(signalPrepareTurn(QDataStream &,bool,KGameIO *,bool *)),
00949             this,SLOT(prepareAITurn(QDataStream &,bool,KGameIO *,bool *)));
00950 
00951     connect(input,SIGNAL(signalProcessQuery(QDataStream&, KGameProcessIO*)),
00952             this,SLOT(processAICommand(QDataStream&, KGameProcessIO*)));
00953     player->addGameIO(input);
00954   }
00955   else if (io&KGameIO::KeyIO)
00956   {
00957     if (global_debug>1) kDebug() << "Creating KEYBOARD IO " << endl;
00958     // We want the player to work over keyboard
00959     KGameKeyIO  *input;
00960     input=new KGameKeyIO(pView->parentWidget());
00961     // Connect keys input to a function to process the actual input
00962     connect((KGameKeyIO *)input,SIGNAL(signalKeyEvent(KGameIO *,QDataStream &,QKeyEvent *,bool *)),
00963             pView,SLOT(keyInput(KGameIO *,QDataStream &,QKeyEvent *,bool *)));
00964     player->addGameIO(input);
00965   }
00966 }
00967 
00968 
00969 // This slot is called when a computer move should be generated
00970 void KWin4Doc::prepareAITurn(QDataStream& stream, bool b, KGameIO* input, bool* sendit)
00971 {
00972   if (global_debug>1)
00973     kDebug(12010) << " KWin4Doc::prepareAITurn b="<<b << endl;
00974  
00975   // Set defaults
00976   *sendit = false;
00977 
00978   // Our player
00979   KPlayer* player=input->player();
00980   if (!player->myTurn()) return ;
00981   if (!b) return ; // only create move on setTurn(true)
00982 
00983   qint32 pl;
00984   if (global_debug>1) kDebug(12010) << "slotPrepareComputerTurn for player id= " << player->id() << endl;
00985   pl=player->userId();
00986 
00987   // Pack the game into the message
00988   prepareGameMessage(stream,pl);
00989 
00990   // Do send
00991   *sendit=true;
00992 }
00993 
00994 // Sends the current game status to the computer player
00995 // Careful: The data needs to be exatcly the same as the computer
00996 // player reading on the other side
00997 void KWin4Doc::prepareGameMessage(QDataStream& stream, qint32 pl)
00998 {
00999   if (global_debug>1) kDebug(12010) << "          sending col=" << pl << endl;
01000   stream << pl ;
01001   // This needs to be the same than the computer player reads!
01002   stream << (qint32)getCurrentMove();
01003   stream << (qint32)getCurrentPlayer();
01004   stream << (qint32)getPlayerColour(0);
01005   stream << (qint32)getPlayerColour(1);
01006   stream << (qint32)Prefs::level();
01007 
01008   int i,j;
01009   for (i=0;i<FIELD_SIZE_Y;i++)
01010   {
01011     for (j=0;j<FIELD_SIZE_X;j++)
01012     {
01013        qint8 col;
01014        col=getColour(j,i);
01015        stream << col;
01016     }
01017     if (global_debug>1) kDebug(12010)
01018       << getColour(0,i)  << " "
01019       << getColour(1,i)  << " "
01020       << getColour(2,i)  << " "
01021       << getColour(3,i)  << " "
01022       << getColour(4,i)  << " "
01023       << getColour(5,i)  << " "
01024       << getColour(6,i)  << endl;
01025   }
01026   stream << (qint32)421256;
01027 }
01028 
01029 
01030 // The AI send a command, e.g. the game value to us
01031 void KWin4Doc::processAICommand(QDataStream& in, KGameProcessIO* /*io*/)
01032 {
01033   qint8 cid;
01034   // Receive command
01035   in >> cid;
01036   switch(cid)
01037   {
01038     case 1:  // game value
01039       qint32 value;
01040       in >> value;
01041       if (global_debug>1) kDebug(12010) << "#### Computer thinks value is " << value << endl;
01042       setScore(value);
01043     break;
01044     default:
01045       kError() << "KWin4Doc::processAICommand: Unknown id " << cid << endl;
01046     break;
01047   }
01048 }
01049 
01050 
01051 // This slot is called by the signal of KGame to indicated
01052 // that the network connection is done and a new client is
01053 // connected
01054 // cid is the id of the client connected. if this is equal
01055 // gameId() WE are the client
01056 void KWin4Doc::clientConnected(quint32 cid, KGame* /* me */)
01057 {
01058   if (global_debug>1) kDebug(12010) << " void KWin4Doc::clientConnected id="<<cid << " we=" <<
01059   gameId() << " we admin=" << isAdmin() << "master)" << isMaster() << endl;
01060 
01061   if (playerList()->count()!=2)
01062   {
01063     kError() << "SERIOUS ERROR: We do not have two players...Trying to disconnect!"<<endl;
01064     disconnect();
01065     return ;
01066   }
01067 
01068   // Get the two players - more are not possible
01069   KWin4Player* p1=(KWin4Player *)playerList()->at(0);
01070   KWin4Player* p2=(KWin4Player *)playerList()->at(1);
01071   if (!p1->isVirtual())
01072   {
01073     emit signalChatChanged(p1);  
01074     if (global_debug>1) kDebug(12010) << "CHAT to player 0 " << endl;
01075   }
01076   else
01077   {
01078     emit signalChatChanged(p2);  
01079     if (global_debug>1) kDebug(12010) << "CHAT to player 1 " << endl;
01080   }
01081 
01082   // Now check whose turn it is. The Admin will rule this
01083   if (isAdmin())
01084   {
01085     if (global_debug>1) kDebug(12010) << "WE are ADMIN == COOL ! " << endl;
01086     // p1 is local
01087     if (!p1->isVirtual())
01088     {
01089       if (global_debug>1) kDebug(12010) << "p1 id=" << p1->userId() << " is local turn="<<p1->myTurn()<< endl;
01090       // Exclusive setting of the turn
01091       p1->setTurn(p1->myTurn(),true);
01092       p2->setTurn(!p1->myTurn(),true);
01093     }
01094     else if (!p2->isVirtual())
01095     {
01096       if (global_debug>1) kDebug(12010) << "p2 id=" << p2->userId() << " is local turn="<<p2->myTurn()<<  endl;
01097       // Exclusive setting of the turn
01098       p2->setTurn(p2->myTurn(),true);
01099       p1->setTurn(!p2->myTurn(),true);
01100     }
01101   }
01102 }
01103 
01104 
01105 // Get the KPlayer from the color by searching all players
01106 // users id's
01107 KWin4Player* KWin4Doc::getPlayer(COLOUR col)
01108 {
01109  KWin4Player* p;
01110  for ( p=(KWin4Player *)playerList()->first(); p!= 0; p=(KWin4Player *)playerList()->next() )
01111  {
01112    if (p->userId()==col)
01113      return p;
01114  }
01115  kError() << "SERIOUS ERROR: Cannot find player with colour " << col << ".  CRASH imminent" << endl;
01116  return 0;
01117 }
01118 
01119 
01120 // We create a process which calulcates a computer move which is shown as hint to the player.
01121 void KWin4Doc::calculateHint()
01122 {
01123   // We allocate the hint process only if it is needed
01124   if (!mHintProcess)
01125   {
01126     QString file = findProcessName();
01127     if (global_debug>1) kDebug(12010) << "Creating HINT PROCESS " << endl;
01128 
01129     // We want a computer player
01130     mHintProcess=new KGameProcessIO(file);
01131 
01132     connect(mHintProcess,SIGNAL(signalProcessQuery(QDataStream&, KGameProcessIO*)),
01133             this,SLOT(processAIHintCommand(QDataStream&, KGameProcessIO*)));
01134   }
01135 
01136   // Send game to process
01137   qint32 pl;
01138   QByteArray buffer;
01139   QDataStream stream(&buffer, QIODevice::WriteOnly);
01140   pl=getCurrentPlayer();
01141   prepareGameMessage(stream, pl);
01142   mHintProcess->sendMessage(stream, 2, 0, gameId());
01143 }
01144 
01145 
01146 // The compute process sent a hint which we show in the game board.
01147 void KWin4Doc::processAIHintCommand(QDataStream& in,KGameProcessIO* /*io*/)
01148 {
01149   qint8 cid;
01150   // Read command
01151   in >> cid;
01152   switch(cid)
01153   {
01154     case 2:  // Hint
01155     {
01156       qint32 pl;
01157       qint32 move;
01158       qint32 value;
01159       // Read parameters of command
01160       in >>  pl >> move  >> value;
01161       if (global_debug>1) kDebug(12010) << "#### Computer thinks pl=" << pl << " move =" << move << endl;
01162       if (global_debug>1) kDebug(12010) << "#### Computer thinks hint is " << move << " and value is " << value << endl;
01163 
01164       // Display hint
01165       int x = move;
01166       int y = mFieldFilled.at(x);
01167       pView->displayHint(x,y);
01168     }
01169     break;
01170     default:
01171       kError() << "KWin4Doc::processAIHintCommand: Unknown id " << cid << endl;
01172     break;
01173   }
01174 }
01175    
01176 
01177 // Called when a player property has changed. We check whether the name
01178 // changed and then update the score widget
01179 // We should maybe do this for the other properties too to update
01180 // the status widget...I am not sure here...we'll see
01181 void KWin4Doc::playerPropertyChanged(KGamePropertyBase* prop,KPlayer* player)
01182 {
01183   if (!pView) return ;
01184 
01185   // Check for name changes
01186   if (prop->id()==KGamePropertyBase::IdName)
01187   {
01188     if (global_debug>1) kDebug(12010) << "Player name id=" << player->userId() << " changed to " << player->name()<<endl;
01189     mStatus->setPlayerName(player->name(),player->userId());
01190   }
01191 
01192 }
01193 
01194 
01195 // Called by KGame when a game property has changed. 
01196 void KWin4Doc::gamePropertyChanged(KGamePropertyBase* prop, KGame* /* me */)
01197 {
01198    if (!pView) return;
01199   
01200    // Move number
01201    if (prop->id()==mCurrentMove.id())
01202    {
01203      // TODO pView->scoreWidget()->setMove(mCurrentMove);
01204    }
01205 
01206    // Computer AI value
01207    else if (prop->id()==mScore.id())
01208    {
01209      int sc=mScore/10000;
01210      if (sc==0 && mScore.value()>0) sc=1;
01211      else if (sc==0 && mScore.value()<0) sc=-1;
01212      // TODO pView->scoreWidget()->setChance(sc);
01213    }
01214 
01215    // Whose turn is it
01216    else if (prop->id()==mAmzug.id())
01217    {
01218      if (global_debug>1) kDebug(12010) << "Amzug changed to " << mAmzug.value()<<endl;
01219      mStatus->setTurn(mAmzug);
01220    }
01221 
01222    // The game status
01223    else if (prop->id()==KGamePropertyBase::IdGameStatus)
01224    {
01225      if (gameStatus()==Abort)
01226      {
01227        if (global_debug>1) kDebug(12010) << "PropertyChanged::status signal game abort +++" << endl;
01228        emit signalGameOver(2,getPlayer(getCurrentPlayer()),this); // 2 indicates Abort
01229      }
01230      else if (gameStatus()==Run)
01231      {
01232        if (global_debug>1) kDebug(12010) << "PropertyChanged::status signal game run +++" << endl;
01233        activateCurrentPlayer(); // Set the current player to play
01234        emit signalGameRun();
01235      }
01236      else if (gameStatus()==Init)
01237      {
01238        if (global_debug>1) kDebug(12010) << "PropertyChanged::status signal game INIT +++" << endl;
01239        resetGame(true);
01240      }
01241      else if (gameStatus()==End)
01242      {
01243        if (global_debug>1) kDebug(12010) << "PropertyChanged::status signal game END +++" << endl;
01244      }
01245      else
01246      {
01247        if (global_debug>1) kDebug(12010) << "PropertyChanged::other status signal +++" << endl;
01248      }
01249      
01250    }
01251 }
01252 
01253 
01254 // This is an overwritten function of KGame which is called
01255 // when a game is loaded. This can either be via a networ
01256 // connect or via a real load from file
01257 bool KWin4Doc::loadgame(QDataStream &stream,bool network,bool reset)
01258 {
01259   if (global_debug>1)
01260     kDebug () << "loadgame() network=" << network << " reset="<< reset << endl;
01261   if (!network) setGameStatus(End);
01262 
01263   // Clear out the old game 
01264   if (global_debug>1) kDebug(12010)<<"loadgame wants to reset the game"<<endl;
01265   resetGame(true);
01266 
01267   // load the new game
01268   bool res=KGame::loadgame(stream,network,reset);
01269   if (global_debug>1) kDebug(12010) << "amzug loaded to ="<<mAmzug.value() << endl;
01270 
01271   // Replay the game be undoing and redoing
01272   if (global_debug>1) kDebug(12010) << "REDRAW GAME using undo/redo" << endl;
01273   if (global_debug>1) kDebug(12010) << "history cnt="<<mHistoryCnt.value() << endl;
01274   if (global_debug>1) kDebug(12010) << "amzug ="<<mAmzug.value() << endl;
01275   int cnt=0;
01276   while(undoMove())
01277   {
01278     cnt++;
01279     if (global_debug>1) kDebug(12010) << "Undoing move "<<cnt<<endl;
01280   }
01281   if (global_debug>1) kDebug(12010) << "amzug ="<<mAmzug.value() << endl;
01282   while(cnt>0)
01283   {
01284     redoMove();
01285     cnt--;
01286     if (global_debug>1) kDebug(12010) << "Redoing move "<<cnt<<endl;
01287   }
01288   if (global_debug>1) kDebug(12010) << "amzug ="<<mAmzug.value() << endl;
01289 
01290   // Set the input devices
01291   recalcIO();
01292   // And set the right player to turn
01293   activateCurrentPlayer();
01294 
01295   if (global_debug>1)
01296     kDebug(12010)  << "loadgame done +++" << endl;
01297   return res;
01298 }
01299 
01300 
01301 // This is also an overwritten function of KGame. It is
01302 // Called in the game negotiation upon connect. Here
01303 // the games have to determine what player is remote and
01304 // what is local
01305 // This function is only called in the Admin.
01306 void KWin4Doc::newPlayersJoin(KGamePlayerList* /*oldList*/,KGamePlayerList* newList,QList<int> &inactivate)
01307 {
01308   if (global_debug>1)
01309     kDebug(12010) << "newPlayersJoin: START"<<endl;
01310   
01311   KWin4Player *yellow=getPlayer(Yellow);
01312   KWin4Player *red=getPlayer(Red);
01313   KPlayer *player;
01314   // Take the master player with the higher priority. Prioirty is set
01315   // be the network dialog
01316   if (yellow->networkPriority()>red->networkPriority())
01317   {
01318     // Deactivate the lower one 
01319     inactivate.append(red->id());
01320     if (global_debug>1) kDebug(12010) << "ADMIN keeps yellow and kicks red= " << red->id()<<" userId/col="<<red->userId()<<endl;
01321     // loop all client players and deactivate the one which have the color
01322     // yellow
01323     for ( player=newList->first(); player != 0; player=newList->next() ) 
01324     {
01325       if (player->userId()==yellow->userId()) 
01326       {
01327         inactivate.append(player->id());
01328         if (global_debug>1) kDebug(12010) << "Deactivate C1 " << player->id()<<" col="<<player->userId()<<endl;
01329       }
01330     }
01331   }
01332   else
01333   {
01334     // Deactivate the lower one 
01335     inactivate.append(yellow->id());
01336     if (global_debug>1) kDebug(12010) << "ADMIN keeps red and kicks yellow= " << yellow->id()<<" userId/col="<<yellow->userId()<<endl;
01337     // loop all client players and deactivate the one which have the color
01338     // red
01339     for ( player=newList->first(); player != 0; player=newList->next() ) 
01340     {
01341       if (player->userId()==red->userId()) 
01342       {
01343         inactivate.append(player->id());
01344         if (global_debug>1) kDebug(12010) << "Deactivate C2 " << player->id()<<" col="<<player->userId()<<endl;
01345       }
01346     }
01347   }
01348   if (global_debug>1)
01349     kDebug(12010) << "newPlayersJoin: DONE"<<endl;
01350 }
01351 
01352 #include "kwin4doc.moc"

Generated on Sun Mar 4 10:56:43 2007 for KWin4 by  doxygen 1.4.6