00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <QDir>
00023 #include <QTimer>
00024 #include <QKeyEvent>
00025 #include <QList>
00026 #include <QMouseEvent>
00027
00028
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
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
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
00059 setPolicy(KGame::PolicyDirty,true);
00060
00061
00062
00063
00064 setMaxPlayers(2);
00065 setMinPlayers(2);
00066
00067
00068 mField.resize(42);
00069
00070
00071
00072
00073
00074
00075
00076
00077
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
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
00104 resetGame(false);
00105
00106 setGameStatus(Intro);
00107
00108
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
00115
00116 dataHandler()->Debug();
00117 }
00118
00119
00120
00121 KWin4Doc::~KWin4Doc()
00122 {
00123 writeConfig(KGlobal::config().data());
00124 if (mHintProcess) delete mHintProcess;
00125 delete mStatus;
00126 mStatus = 0;
00127 }
00128
00129
00130
00131 void KWin4Doc::initPlayers()
00132 {
00133
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
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
00150 void KWin4Doc::setView(KWin4View *view)
00151 {
00152 pView=view;
00153 connect(pView, SIGNAL(signalMoveDone(int)), this, SLOT(moveDone(int)));
00154 }
00155
00156
00157
00158 COLOUR KWin4Doc::getColour(int x,int y)
00159 {
00160 return (COLOUR)mField.at(x+y*FIELD_SIZE_X);
00161 }
00162
00163
00164
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
00177 void KWin4Doc::resetGame(bool initview)
00178 {
00179
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
00190 mHistoryCnt=0;
00191 mCurrentMove=0;
00192 mMaxMove=0;
00193 mLastColumn=-1;
00194 mLastColour=Nobody;
00195 setScore(0);
00196 mLastHint=-1;
00197
00198
00199 if (initview)
00200 {
00201 pView->initGame(mStatus);
00202 }
00203
00204
00205 setCurrentPlayer((COLOUR)mStartPlayer.value());
00206 }
00207
00208
00209
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
00219 void KWin4Doc::endGame(TABLE mode)
00220 {
00221 setGameStatus(End);
00222
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
00240 if (mMaxMove>0)
00241 {
00242 yellow->incBrk();
00243 red->incBrk();
00244 }
00245 break;
00246 }
00247
00248 }
00249
00250
00251
00252 void KWin4Doc::moveDone(int )
00253 {
00254 if (playerCount()>1)
00255 {
00256 playerInputFinished(getPlayer(getCurrentPlayer()));
00257 }
00258
00259
00260 }
00261
00262
00263
00264 KPlayer* KWin4Doc::nextPlayer(KPlayer* last, bool )
00265 {
00266 if (global_debug>1)
00267 kDebug(12010) << k_funcinfo << "nextPlayer last="<<last->id() << " admin=" << isAdmin() <<endl;
00268
00269
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
00284
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
00295
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;
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 ;
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
00333
00334
00335 mCurrentMove=mCurrentMove.value()+1;
00336
00337
00338 if (mode==0) mMaxMove=mCurrentMove.value();
00339 mLastColumn=x;
00340
00341
00342 pView->displayMove(x, y, mLastColour, x, mLastColour, mCurrentMove-1 , mode==1?false:true);
00343
00344 return GNormal;
00345 }
00346
00347
00348
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
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
00366 setColour(x,y,Nobody);
00367
00368
00369 mLastColour=getCurrentPlayer();
00370 if (getCurrentPlayer()==Yellow) setCurrentPlayer(Red);
00371 else setCurrentPlayer(Yellow);
00372 mCurrentMove=mCurrentMove.value()-1;
00373
00374
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
00396 bool KWin4Doc::redoMove()
00397 {
00398 if (getHistoryCnt()>=mMaxMove) return false;
00399
00400 int x=mHistory.at(getHistoryCnt());
00401
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
00413 void KWin4Doc::setName(COLOUR col, const QString& n)
00414 {
00415 getPlayer(col)->setName(n);
00416 }
00417
00418
00419
00420 QString KWin4Doc::getName(COLOUR col)
00421 {
00422 return getPlayer(col)->name();
00423 }
00424
00425
00426
00427
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
00450
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
00463
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
00473
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
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
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
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
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
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
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
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
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
00664 void KWin4Doc::resetStatistic()
00665 {
00666 getPlayer(Yellow)->resetStats();
00667 getPlayer(Red)->resetStats();
00668 }
00669
00670
00671
00672 void KWin4Doc::setScore(long value)
00673 {
00674 mScore.setValue(value);
00675 kDebug() << " ************** SET AI SCORE " << value << " ****************" << endl;
00676 }
00677
00678
00679
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
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;
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
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
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
00751 COLOUR KWin4Doc::getCurrentPlayer()
00752 {
00753 return (COLOUR)mAmzug.value();
00754 }
00755
00756
00757
00758 void KWin4Doc::setCurrentPlayer(COLOUR no)
00759 {
00760 mAmzug.setValue(no);
00761 }
00762
00763
00764
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
00777 int KWin4Doc::getCurrentMove()
00778 {
00779 return mCurrentMove;
00780 }
00781
00782
00783
00784 int KWin4Doc::getMaxMove()
00785 {
00786 return mMaxMove;
00787 }
00788
00789
00790
00791 int KWin4Doc::getHistoryCnt()
00792 {
00793 return mHistoryCnt;
00794 }
00795
00796
00797
00798 QString KWin4Doc::findProcessName()
00799 {
00800
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
00813 QDir dir;
00814
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
00836 void KWin4Doc::networkMessageUpdate(int ,quint32 ,quint32 )
00837 {
00838
00839 }
00840
00841
00842
00843 KPlayer *KWin4Doc::createPlayer(int , 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
00857
00858 bool KWin4Doc::playerInput(QDataStream& msg, KPlayer* )
00859 {
00860 qint32 move, pl;
00861 msg >> pl >> move;
00862 kDebug() << "KWin4Doc::playerInput pl="<<pl<<" and move=" << move <<endl;
00863
00864
00865 if (!doMove(move,pl))
00866 {
00867
00868 QTimer::singleShot(0, this,SLOT(repeatMove()));
00869 }
00870
00871 return false;
00872 }
00873
00874
00875
00876 void KWin4Doc::repeatMove()
00877 {
00878 getPlayer(getCurrentPlayer())->setTurn(true);
00879 }
00880
00881
00882
00883 KGameIO::IOMode KWin4Doc::playedBy(int col)
00884 {
00885 return mPlayedBy[col];
00886 }
00887
00888
00889
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
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);
00904 createIO(player,io);
00905 }
00906 }
00907
00908
00909
00910
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
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
00932 input=new KGameMouseIO(pView->viewport());
00933 if (global_debug>1) kDebug(12010) << "MOUSE IO added " << endl;
00934
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
00946 input=new KGameProcessIO(file);
00947
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
00959 KGameKeyIO *input;
00960 input=new KGameKeyIO(pView->parentWidget());
00961
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
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
00976 *sendit = false;
00977
00978
00979 KPlayer* player=input->player();
00980 if (!player->myTurn()) return ;
00981 if (!b) return ;
00982
00983 qint32 pl;
00984 if (global_debug>1) kDebug(12010) << "slotPrepareComputerTurn for player id= " << player->id() << endl;
00985 pl=player->userId();
00986
00987
00988 prepareGameMessage(stream,pl);
00989
00990
00991 *sendit=true;
00992 }
00993
00994
00995
00996
00997 void KWin4Doc::prepareGameMessage(QDataStream& stream, qint32 pl)
00998 {
00999 if (global_debug>1) kDebug(12010) << " sending col=" << pl << endl;
01000 stream << pl ;
01001
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
01031 void KWin4Doc::processAICommand(QDataStream& in, KGameProcessIO* )
01032 {
01033 qint8 cid;
01034
01035 in >> cid;
01036 switch(cid)
01037 {
01038 case 1:
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
01052
01053
01054
01055
01056 void KWin4Doc::clientConnected(quint32 cid, KGame* )
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
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
01083 if (isAdmin())
01084 {
01085 if (global_debug>1) kDebug(12010) << "WE are ADMIN == COOL ! " << endl;
01086
01087 if (!p1->isVirtual())
01088 {
01089 if (global_debug>1) kDebug(12010) << "p1 id=" << p1->userId() << " is local turn="<<p1->myTurn()<< endl;
01090
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
01098 p2->setTurn(p2->myTurn(),true);
01099 p1->setTurn(!p2->myTurn(),true);
01100 }
01101 }
01102 }
01103
01104
01105
01106
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
01121 void KWin4Doc::calculateHint()
01122 {
01123
01124 if (!mHintProcess)
01125 {
01126 QString file = findProcessName();
01127 if (global_debug>1) kDebug(12010) << "Creating HINT PROCESS " << endl;
01128
01129
01130 mHintProcess=new KGameProcessIO(file);
01131
01132 connect(mHintProcess,SIGNAL(signalProcessQuery(QDataStream&, KGameProcessIO*)),
01133 this,SLOT(processAIHintCommand(QDataStream&, KGameProcessIO*)));
01134 }
01135
01136
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
01147 void KWin4Doc::processAIHintCommand(QDataStream& in,KGameProcessIO* )
01148 {
01149 qint8 cid;
01150
01151 in >> cid;
01152 switch(cid)
01153 {
01154 case 2:
01155 {
01156 qint32 pl;
01157 qint32 move;
01158 qint32 value;
01159
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
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
01178
01179
01180
01181 void KWin4Doc::playerPropertyChanged(KGamePropertyBase* prop,KPlayer* player)
01182 {
01183 if (!pView) return ;
01184
01185
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
01196 void KWin4Doc::gamePropertyChanged(KGamePropertyBase* prop, KGame* )
01197 {
01198 if (!pView) return;
01199
01200
01201 if (prop->id()==mCurrentMove.id())
01202 {
01203
01204 }
01205
01206
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
01213 }
01214
01215
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
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);
01229 }
01230 else if (gameStatus()==Run)
01231 {
01232 if (global_debug>1) kDebug(12010) << "PropertyChanged::status signal game run +++" << endl;
01233 activateCurrentPlayer();
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
01255
01256
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
01264 if (global_debug>1) kDebug(12010)<<"loadgame wants to reset the game"<<endl;
01265 resetGame(true);
01266
01267
01268 bool res=KGame::loadgame(stream,network,reset);
01269 if (global_debug>1) kDebug(12010) << "amzug loaded to ="<<mAmzug.value() << endl;
01270
01271
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
01291 recalcIO();
01292
01293 activateCurrentPlayer();
01294
01295 if (global_debug>1)
01296 kDebug(12010) << "loadgame done +++" << endl;
01297 return res;
01298 }
01299
01300
01301
01302
01303
01304
01305
01306 void KWin4Doc::newPlayersJoin(KGamePlayerList* ,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
01315
01316 if (yellow->networkPriority()>red->networkPriority())
01317 {
01318
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
01322
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
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
01338
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"