add qmake .pro file
[mancala] / src / GameController.cpp
1 /*
2 Mancala - A Historical Board Game
3 Copyright (C) 2009-2010 A.H.M.Mahfuzur Rahman 65mahfuz90@gmail.com
4 Copyright (c) 2010 Reto Zingg g.d0b3rm4n@gmail.com
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 // #include <KLocale>
21
22 #include "GameController.h"
23
24 #include <QTimer>
25 #include <QStringList>
26 #include <QList>
27
28 // #include <kdebug.h>
29
30 #include "Board.h"
31 #include "Score.h"
32 #include "Kalah.h"
33 #include "MoveGenerator.h"
34
35
36 GameController::GameController(GameInfo* gameInfo){
37     m_gameInfo = gameInfo;
38     m_humanScore = new Score();
39     m_computerScore = new Score();
40     initializeGameController();
41
42     connect(this,SIGNAL(signalSowMaker(int)),this,SLOT(sowMaker(int)));
43     connect(this,SIGNAL(signalAfterSow(int)),this,SLOT(afterSow(int)));
44     connect(this,SIGNAL(signalComputerMove()),this,SLOT(makeComputerMove()));
45
46 }
47
48 void GameController::initializeGameController(){
49
50     m_gameDifficulty = GameController::EASY;
51     m_moveGenerator = new MoveGenerator(m_gameDifficulty,m_gameInfo,this);
52     m_humanTurn = true;
53     m_cupIndexClicked = -1;
54     m_humanSide = GameController::LOWER;
55     m_humanKalah = Kalah::Right;
56     m_gamePaused = false;
57     m_gameOver = false;
58     m_physicalMoveAllowed = false;
59     m_captureInfo = m_gameInfo->captureInfo();
60
61     //If game is clockwise change human kalah
62     if(m_humanSide == GameController::LOWER && m_gameInfo->rotationType() == GameInfo::CLOCKWISE){
63         m_humanKalah = Kalah::Left;
64     }
65
66     m_humanScore->reset();
67     m_computerScore->reset();
68
69     emit signalMessage("");
70     emit signalShowTurn(m_humanTurn);
71     emit signalShowScore(m_humanScore->score(),true);
72     emit signalShowScore(m_computerScore->score(),false);
73
74     initializeBoard();
75     setHumanSideCups();
76
77 }
78
79 void GameController::initializeBoard(){
80
81     while(m_physicalBoard.count()){
82         m_physicalBoard.pop_back();
83         m_logicalBoard.pop_back();
84     }
85
86     //stoneInfo in cups (0 to 2*m_gameInfo->numCupsPerRow()-1)
87     for(int i = 0 ; i< 2*m_gameInfo->numCupsPerRow();i++){
88         m_physicalBoard.append(m_gameInfo->initialStonesPerCup());
89         m_logicalBoard.append(m_gameInfo->initialStonesPerCup());
90     }
91
92     //stoneInfo in kalah's
93     for(int i = 0 ; i < 2 ; i++){
94         m_physicalBoard.append(0);
95         m_logicalBoard.append(0);
96     }
97
98 }
99
100 void GameController::setHumanSideCups(){
101
102     while(m_humanSideCups.count())
103         m_humanSideCups.pop_back();
104
105     for(int i = 0 ; i < m_gameInfo->numCupsPerRow();i++)
106         m_humanSideCups.append(i);
107     if(m_humanSide == GameController::LOWER)
108         for(int i = 0 ; i < m_gameInfo->numCupsPerRow();i++){
109         m_humanSideCups[i] = 2*m_gameInfo->numCupsPerRow() - 1 - m_humanSideCups[i];
110
111     }
112
113 }
114
115 //It is called from the GraphcisScene to start the game
116 void GameController::setBoardItem(Board *board){
117     m_board = board;
118
119     //If computer starts we will delay it by 1.5 seconds
120     if(!m_humanTurn){
121         emit signalShowTurn(false);
122         QTimer::singleShot(1500, this, SLOT(makeComputerMove()));
123     }
124
125 }
126
127 //-------------Is this valid cup(cupIndex) belongs to human ----------------
128 bool GameController::isHumanCup(int cupIndex){
129
130     if(cupIndex >= m_gameInfo->numCupsPerRow())
131         return true;
132     return false;
133 }
134
135 //----------------Is the kalah(kalahIndex) belongs to human---------------------
136 bool GameController::isHumanKalah(int kalahIndex){
137     kalahIndex -= 2*m_gameInfo->numCupsPerRow();
138
139     if(kalahIndex == m_humanKalah){
140         return true;
141     }
142     return false;
143 }
144
145 //-----------------------------Human Move-----------------------------------
146 void GameController::makeHumanMove(int index){
147
148     if(isGameOver(m_physicalBoard) || !m_humanTurn) return;
149
150     m_physicalMoveAllowed = true;
151     // kDebug() << "Human Moving .................";
152     if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE)
153         m_multipleLapDelay = false;
154     m_rotationInfo = m_gameInfo->rotationInfo(index);
155     sowMaker(index);
156
157 }
158
159 //----------------------------------Computer Move----------------------------
160 void GameController::makeComputerMove(){
161
162     if(isGameOver(m_physicalBoard) || m_humanTurn) return;
163
164     // kDebug() << "Computer Moving ................";
165
166     m_physicalMoveAllowed = false;
167     int index = m_moveGenerator->bestMove(m_physicalBoard,false);
168     m_physicalMoveAllowed = true;
169     m_rotationInfo = m_gameInfo->rotationInfo(index);
170
171     if(index != -1){
172         // kDebug() << "Index: " << index << " Stones: " << m_physicalBoard[index];
173         sowMaker(index);
174     }
175
176     else
177         computerHasNoMove();
178 }
179
180 //slot sowMaker
181 void GameController::sowMaker(int index){
182
183     if(isGameOver(m_physicalBoard)) return;
184     m_physicalMoveAllowed = true;
185
186     m_index = index;
187     //For human Turn, we want to response quick, unless it falls between multiple lap
188     if(m_humanTurn){
189         if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE && m_multipleLapDelay)
190             QTimer::singleShot(1500,this,SLOT(sowController()));
191         else sowController();
192     }
193
194     else QTimer::singleShot(1500,this,SLOT(sowController()));
195 }
196
197
198 void GameController::sowController(){
199
200     if(m_gameOver) return;
201
202     int index = m_index;
203     index = singleSow(index);
204
205     if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE && !isEndOfLap(index,m_physicalBoard)){
206         if(m_humanTurn) m_multipleLapDelay = true;
207         emit signalSowMaker(index);
208     }
209     else{
210         emit signalAfterSow(index);
211     }
212
213 }
214
215 //slot After Sow
216 void GameController::afterSow(int index){
217
218     if(isGameOver(m_physicalBoard)) return;
219     if(m_gameInfo->isBonusTurn()){
220
221         if(index >= 2*m_gameInfo->numCupsPerRow()){   //is a kalah
222             // kDebug() << "A Bonus Turn:";
223             if(m_humanTurn && isHumanKalah(index)){
224                 emit signalMessage( tr("You got a bonus turn") );
225                 if(isHumanSideEmpty(m_physicalBoard)) humanHasNoMove();
226                 return;
227
228             }
229             else if(!m_humanTurn && !isHumanKalah(index)){
230                 emit signalMessage( tr("Computer got a bonus turn") );
231                 if(isComputerSideEmpty(m_physicalBoard)) computerHasNoMove();
232                 emit signalComputerMove();
233                 return;
234             }
235
236         }
237     }
238
239
240     if(isGameOver(m_physicalBoard)) return;
241     handleCrossCapture(index,m_physicalBoard);
242     emit signalMessage("");
243
244     if(isGameOver(m_physicalBoard)) return;
245     int multiplier = handleCountNSeriesCapture(index,m_physicalBoard);
246
247     if(isGameOver(m_physicalBoard)) return;
248     changeTurn();
249
250     if(!m_humanTurn && !m_gameOver){
251         // kDebug() << "Next turn computer";
252         if(isComputerSideEmpty(m_physicalBoard)) computerHasNoMove();
253         else{
254             if(multiplier > 0)
255                 QTimer::singleShot( multiplier * 1500, this, SLOT(makeComputerMove() ) );
256             else
257                 QTimer::singleShot(1500, this, SLOT(makeComputerMove()));
258         }
259     }
260     else{
261         // kDebug() << "Next turn Human";
262         if(isHumanSideEmpty(m_physicalBoard) ) humanHasNoMove();
263     }
264
265 }
266
267 void GameController::changeTurn(){
268
269     m_humanTurn == true ? m_humanTurn = false : m_humanTurn = true;
270     emit signalShowTurn(m_humanTurn);
271 }
272
273 //---------------------------- is End Of Lap -----------------------------------
274 bool GameController::isEndOfLap(int index,QList<int>& board){
275
276     //if last stone ends on a cup with desired no of stone
277     if(index < 2*m_gameInfo->numCupsPerRow() && board[index] == m_gameInfo->stonesToEndLap()){
278         return true;
279     }
280     //if last stone on a kalah
281     if(index >= 2*m_gameInfo->numCupsPerRow()){
282         return true;
283     }
284
285     return false;
286 }
287
288 //Will be true when each cup is empty
289 bool GameController::isGameOver(QList<int>& board){
290
291     if(m_gameOver) return true;
292
293     for(int i = 0 ; i < 2*m_gameInfo->numCupsPerRow() ; i++)
294         if( board[i] > m_gameInfo->leftToCup() )
295             return false;
296     if(m_physicalMoveAllowed) emit signalGameOver();
297     m_gameOver = true;
298     return m_gameOver;
299 }
300
301 //--------------------------------single Lap sowing -------------------------------------
302 int GameController::singleSow(int cupIndex){
303     //we first find out from which side the sowing started - easy, who is moving
304     Side side = m_humanSide;
305     if(!m_humanTurn) side = (Side)(1 - m_humanSide);
306
307     // if(m_physicalMoveAllowed) kDebug() << "We are here to sow";
308
309     QList<int> board;
310     if(m_physicalMoveAllowed) board = physicalBoard();
311     else board = logicalBoard();
312
313     //0-CLOCKWISE,1-ANTI_CLOCKWISE
314     int rotation = m_gameInfo->rotationInfo(cupIndex);
315     int i , kalahNo = Kalah::Left;
316     bool putKalahNow = false;
317     int returnValue = cupIndex;
318
319     //Initial Check where to put in the first stone
320     if( rotation == GameInfo::ANTICLOCKWISE){
321
322         i = cupIndex - 1;
323         if(cupIndex >= m_gameInfo->numCupsPerRow()){
324             kalahNo = Kalah::Right;
325         }
326
327         if( m_gameInfo->stonesToKalah() &&
328             ( (cupIndex == m_gameInfo->numCupsPerRow() && side == GameController::LOWER)
329             || ( cupIndex == 0 && side == GameController::UPPER ) ) )
330             putKalahNow = true;
331     }
332     //clockwise
333     else{
334         i = cupIndex + 1;
335         if(cupIndex < m_gameInfo->numCupsPerRow())
336             kalahNo = Kalah::Right;
337
338         if( m_gameInfo->stonesToKalah() &&
339             ( (cupIndex == (2 * m_gameInfo->numCupsPerRow()-1) && side == GameController::LOWER)
340                || ( cupIndex == (m_gameInfo->numCupsPerRow()-1) && side == GameController::UPPER) ) )
341             putKalahNow = true;
342     }
343
344
345     //Continuous check and update
346     int loop = board[cupIndex]- m_gameInfo->leftToCup();
347
348     for(int j = 0 ; j < loop ; j++){
349
350         if( rotation == GameInfo::CLOCKWISE)
351             i %= 2 * m_gameInfo->numCupsPerRow();
352         else
353             if( i < 0) i = 2 * m_gameInfo->numCupsPerRow() - 1;
354
355         //If it is need to be put in cup
356         if( !putKalahNow ){
357             board[i]++;
358
359             if(m_physicalMoveAllowed){
360                 m_board->updateChildren(cupIndex,i,true);
361 //                // kDebug() << "Putting to cup: " << i;
362             }
363             returnValue = i;
364
365             //check whether the next stone will put in kalah or not
366             if( rotation == GameInfo::ANTICLOCKWISE){
367                 if( m_gameInfo->stonesToKalah() &&
368                     ( ( i == m_gameInfo->numCupsPerRow() && side == GameController::LOWER )
369                       ||( i == 0 && side == GameController::UPPER ) ) )
370                     putKalahNow = true;
371                 i--;
372             }
373             else{
374                 if( m_gameInfo->stonesToKalah() &&
375                     ( (i == (2 * m_gameInfo->numCupsPerRow()-1) && side == GameController::LOWER)
376                      || ( i == (m_gameInfo->numCupsPerRow()-1) &&  side == GameController::UPPER) ) )
377                     putKalahNow = true;
378                 i++;
379             }
380
381         }
382         //going to put it in kalah
383         else{
384
385             if(kalahNo == Kalah::Right){
386
387                 if(m_physicalMoveAllowed){
388 //                    kDebug() << "Putting to Right Kalah";
389                     m_board->updateChildren(cupIndex,Kalah::Right,false);
390                 }
391                 returnValue = 2*m_gameInfo->numCupsPerRow() + Kalah::Right;
392                 board[returnValue]++;
393             }
394
395             else{
396                 if(m_physicalMoveAllowed){
397 //                    kDebug() << "Putting to left kalah";
398                     m_board->updateChildren(cupIndex,Kalah::Left,false);
399                 }
400
401                 returnValue = 2*m_gameInfo->numCupsPerRow() + Kalah::Left;
402                 board[returnValue]++;
403             }
404
405             if(m_physicalMoveAllowed){
406                 if(m_humanTurn && kalahNo == m_humanKalah)
407                     changeScore(1,true);
408                 else changeScore(1,false);
409             }
410
411             putKalahNow = false;
412         }
413
414         board[cupIndex]--;
415     }
416
417     if(m_physicalMoveAllowed) setPhysicalBoard(board);
418     else setLogicalBoard(board);
419
420     return returnValue;
421 }
422
423
424 void GameController::slotGameDifficulty(Difficulty difficulty){
425 //    kDebug() << "GameDifficulty is: " << difficulty;
426     m_gameDifficulty = difficulty;
427     m_moveGenerator->changeDifficulty(m_gameDifficulty);
428 }
429
430
431 //******************************** slots ******************************************
432 void GameController::slotMouseClicked(int index){
433
434     if(m_gameOver)
435         return;
436
437     if(m_humanTurn){
438         m_cupIndexClicked = index;
439
440         if(isHumanSideEmpty(m_physicalBoard)){
441             emit signalMessage( tr("Sorry, you have no move") );
442             humanHasNoMove();
443         }
444         else if(m_cupIndexClicked < 0){
445             emit signalMessage( tr("Click on a Cup") );
446         }
447
448         else if(!isHumanCup(index))
449             emit signalMessage( tr("Click on a cup in the lower row") );
450
451         else if(m_physicalBoard[index] <= m_gameInfo->leftToCup())
452             emit signalMessage( tr("Sorry, not enough stones to move") );
453
454         else{
455             makeHumanMove(m_cupIndexClicked);
456         }
457     }
458
459 }
460
461 void GameController::slotGameOverForNewGame(int identity){
462     m_gameOver = true;
463     emit signalMessage( tr("Loading game...") );
464
465     QTimer* timer = new QTimer(this);
466     signalMapper = new QSignalMapper(this);
467     connect(timer,SIGNAL(timeout()),signalMapper,SLOT(map()));
468     signalMapper->setMapping(timer,identity);
469     connect(signalMapper,SIGNAL(mapped(int)),this,SIGNAL(timeout(int)));
470
471     connect(this,SIGNAL(timeout(int)),this,SLOT(newGameEmitter(int)));
472     timer->setSingleShot(true);
473     timer->start(1500);
474 }
475
476 void GameController::newGameEmitter(int identity){
477     emit signalNewGame(identity);
478 }
479
480 void GameController::slotGameOverForRestartGame(){
481     m_gameOver = true;
482 //    kDebug() << "GameOver is true";
483     emit signalMessage( tr("Loading game...") );
484     QTimer::singleShot(2000,this,SLOT(restartGameEmitter()));
485 }
486
487 void GameController::restartGameEmitter(){
488     emit signalRestartGame();
489 }
490
491 //******************************** slots *****************************
492
493 bool GameController::isHumanSideEmpty(QList<int>& board){
494
495     for(int i = 0 ; i < m_gameInfo->numCupsPerRow() ; i++)
496         if(board[m_humanSideCups[i]] > m_gameInfo->leftToCup())
497             return false;
498     return true;
499 }
500
501 bool GameController::isComputerSideEmpty(QList<int>& board){
502
503     int maxIndex = 2*m_gameInfo->numCupsPerRow() - 1;
504
505     for(int i = 0 ; i < m_gameInfo->numCupsPerRow() ; i++)
506         if(board[maxIndex - m_humanSideCups[i]] > m_gameInfo->leftToCup())
507             return false;
508     return true;
509 }
510
511 //---------------------------------- capture handling-------------------------------------
512
513 void GameController::handleCrossCapture(int index,QList<int>& board){
514
515     if(m_physicalMoveAllowed){ //kDebug() << "handle Cross capture -------";
516         if(isGameOver(m_physicalBoard)) return;
517     }
518     if(index >= 2*m_gameInfo->numCupsPerRow())
519         return;
520
521     //if CrossCapture allowed then 0th bit should be 1
522     int capture = m_gameInfo->captureType();
523     if(m_physicalMoveAllowed) // kDebug() << "Capture Info: " << capture;
524     if(!(capture & 1)){
525         if(m_physicalMoveAllowed) //kDebug() << "We will return";
526         return;
527     }
528
529     int opponentCupIndex;
530     int kalahIndex = -1;
531     //If it is a cup
532     if(index < 2*m_gameInfo->numCupsPerRow()){
533
534         opponentCupIndex = 2*m_gameInfo->numCupsPerRow() - 1 - index;
535         //if opponet cup is empty
536         if(board[opponentCupIndex] == 0)
537             return;
538         if(board[index] != 1)    //we are now taking that only 1 stone
539             return;
540
541         if(isHumanCup(index) && m_humanTurn)
542             kalahIndex = m_humanKalah;
543         else if(!m_humanTurn && !isHumanCup(index))
544             kalahIndex = 1 - m_humanKalah;
545
546         //Now do the capture;
547         if(kalahIndex != -1){
548            QString strIndex = QString("%1,%2").arg(index).arg(kalahIndex);
549
550            //Animation part
551            if(m_physicalMoveAllowed){
552                QTimer* timer = new QTimer(this);
553                signalMapper = new QSignalMapper(this);
554
555                connect(timer,SIGNAL(timeout()),signalMapper,SLOT(map()));
556                signalMapper->setMapping(timer,strIndex);
557                connect(signalMapper,SIGNAL(mapped(const QString&)),this,SIGNAL(timeout(const QString&)));
558
559                connect(this,SIGNAL(timeout(const QString&)),this,SLOT(crossCapture(const QString&)));
560                timer->setSingleShot(true);
561                timer->start(1500);
562            }
563            else crossCapture(strIndex);
564         }
565     }
566
567 }
568
569 //Cross Capture is done here
570 void GameController::crossCapture(const QString& indexString){
571
572     if(isGameOver(m_physicalBoard)) return;
573
574     int capture = m_gameInfo->captureType();
575     if(! (capture & 1) ) return;
576
577     int loop,i;
578     QList<int> board;
579     QStringList list;
580     int index,kalahIndex,opponentCupIndex;
581
582     list = indexString.split(',');
583     index = list[0].toInt();
584     kalahIndex = list[1].toInt();
585     opponentCupIndex = 2*m_gameInfo->numCupsPerRow() - 1 - index;
586
587     if(m_physicalMoveAllowed) board = physicalBoard();
588     else board = logicalBoard();
589
590     loop = board[index];
591     for(i = 0 ; i < loop ; ++i){
592         //we want to remove from index and put to kalah(human)
593         if(m_physicalMoveAllowed) m_board->updateChildren(index,kalahIndex,false);
594         board[index]--;
595         board[kalahIndex + 2*m_gameInfo->numCupsPerRow()]++;
596
597         if(m_physicalMoveAllowed){
598             if(kalahIndex == m_humanKalah)
599                 changeScore(1,true);
600             else changeScore(1,false);
601         }
602     }
603
604     loop = board[opponentCupIndex];
605     for(i = 0 ; i < loop ; ++i){
606         //we want to remove from index and put to kalah(human)
607         if(m_physicalMoveAllowed) m_board->updateChildren(opponentCupIndex,kalahIndex,false);
608         board[opponentCupIndex]--;
609         board[kalahIndex + 2*m_gameInfo->numCupsPerRow()]++;
610
611         if(m_physicalMoveAllowed){
612             if(kalahIndex == m_humanKalah)
613                 changeScore(1,true);
614             else changeScore(1,false);
615         }
616
617     }
618
619     if(m_physicalMoveAllowed) setPhysicalBoard(board);
620     else setLogicalBoard(board);
621
622 }
623
624 int GameController::handleCountNSeriesCapture(int index,QList<int>& board){
625     if(m_physicalMoveAllowed){
626         // kDebug() << "count and series capture--------";
627         if(isGameOver(m_physicalBoard)) return 0;
628     }
629     //Do the capture
630     int capture = m_gameInfo->captureType(),i = 0,kalahIndex;
631     int countCaptureIndex = -1,seriesCaptureIndex = -1;
632     bool captureAllowed;
633     int timerCount;
634
635     if(capture & 1) i++;    //cross capture is at capture_info[0]
636     if(capture & 2) countCaptureIndex = i++;
637     if(capture & 4) seriesCaptureIndex = i++;
638
639     //If no count capture, then no series capture also
640     if(countCaptureIndex == -1){
641         return 0;
642     }
643     else{
644         //At this point we know count captue is allowed in this game
645         captureAllowed = false;
646
647         //we will check whether capture is allowed in this position. For example, game supports
648         //capture at the opponent, but current last stone is on own cup, so no capture
649         if( ( !( (m_humanTurn == false && isHumanCup(index) == false) || (m_humanTurn && isHumanCup(index) ) )
650             && ( m_captureInfo[countCaptureIndex].first == GameInfo::OPPONENT ||
651                  m_captureInfo[countCaptureIndex].first == GameInfo::BOTH ) )
652             ||
653                     ( ( ( m_humanTurn && isHumanCup(index) ) || (!m_humanTurn && !isHumanCup(index) ) )
654                       && (m_captureInfo[countCaptureIndex].first == GameInfo::OWN ||
655                           m_captureInfo[countCaptureIndex].first == GameInfo::BOTH ) ) )
656         {
657             captureAllowed = true;
658             timerCount = 0;
659         }
660
661         while(captureAllowed){
662
663             //if capture allowed and stone Number matched at the cup, then we will capture
664             if(stoneNumberMatched(index,countCaptureIndex,board)){
665                 timerCount++;
666
667 //                if(m_physicalMoveAllowed) kDebug() << "count capture allowed";
668                 if(m_humanTurn) kalahIndex = m_humanKalah;
669                 else kalahIndex = 1 - m_humanKalah;
670
671                 QString strIndex = QString("%1,%2").arg(index).arg(kalahIndex);
672
673                 //Animation part
674                 if(m_physicalMoveAllowed){
675 //                    kDebug() << "str: " << strIndex;
676
677                     QTimer* timer = new QTimer(this);
678                     signalMapper = new QSignalMapper(this);
679
680                     connect(timer,SIGNAL(timeout()),signalMapper,SLOT(map()));
681                     signalMapper->setMapping(timer,strIndex);
682                     connect(signalMapper,SIGNAL(mapped(const QString&)),this,SIGNAL(timeout(const QString&)));
683
684                     connect(this,SIGNAL(timeout(const QString&)),this,SLOT(countCapture(const QString&)));
685                     timer->setSingleShot(true);
686                     timer->start(timerCount * 1500);
687                 }
688                 else countCapture(strIndex);
689
690             }
691             else break;
692
693             //Get Index of the next cup
694             if(seriesCaptureIndex != -1){
695                 index = nextIndex(index,seriesCaptureIndex);
696 //                if(m_physicalMoveAllowed) kDebug() << "Next Cup Index: " << index;
697             }
698             else break;
699
700             //if at my own side but capture is only allowed at the opponent
701             if( ( ( ( m_humanTurn && isHumanCup(index)) || (!m_humanTurn && !isHumanCup(index) ) )
702                 && m_captureInfo[countCaptureIndex].first == GameInfo::OPPONENT )
703                     ||
704             //Or at my opponent side, but capture is allowed only at my own side
705                     ( ( ( m_humanTurn && !isHumanCup(index) ) || ( !m_humanTurn && isHumanCup(index) ) )
706                 && m_captureInfo[countCaptureIndex].first == GameInfo::OWN  ) )
707                     captureAllowed = false;
708         }
709
710     }
711     return timerCount;
712
713 }
714
715 //do the capture
716 void GameController::countCapture(const QString& indexString){
717
718     if(isGameOver(m_physicalBoard)) return;
719
720     QList<int> board;
721     QStringList list;
722     int index,kalahIndex;
723
724     list = indexString.split(',');
725     index = list[0].toInt();
726     kalahIndex = list[1].toInt();
727
728     if(m_physicalMoveAllowed) board = physicalBoard();
729     else board = logicalBoard();
730
731     if(m_physicalMoveAllowed) m_board->updateChildren(index,kalahIndex,board[index]);
732     board[kalahIndex + 2*m_gameInfo->numCupsPerRow()] += board[index];
733
734     if(m_physicalMoveAllowed){
735         if(m_humanTurn) changeScore(board[index],true);
736         else changeScore(board[index],false);
737     }
738
739     board[index] = 0;
740
741     if(m_physicalMoveAllowed) setPhysicalBoard(board);
742     else setLogicalBoard(board);
743
744 }
745
746 bool GameController::stoneNumberMatched(int index,int countCaptureIndex,QList<int>& board){
747     //numbered
748     if( m_captureInfo[countCaptureIndex].second[0] == GameInfo::NUMBER){
749         //Check whether the cup has necessary stone to capture
750         for(int i = 1; i<m_captureInfo[countCaptureIndex].second.count();i++){
751             if(m_captureInfo[countCaptureIndex].second[i] == board[index]){
752 //                if(m_physicalMoveAllowed) kDebug() << "Index: " << index << " Stone:" << board[index];
753                 return true;
754             }
755         }
756 //        if(m_physicalMoveAllowed) kDebug() << "Returning false";
757         return false;
758     }
759     //pattern
760     else{
761 //        if(m_physicalMoveAllowed) kDebug() << "I am in pattern";
762         //Even Pattern
763         if(m_captureInfo[countCaptureIndex].second[1] == GameInfo::EVEN){
764             if( board[index] % 2 == 0 && board[index] != 0){
765 //                if(m_physicalMoveAllowed) kDebug() << "Index: " << index << " Stone:" << board[index];
766                 return true;
767             }
768         }
769         //Odd Pattern
770         else{
771             if(board[index] % 2)
772                 return true;
773         }
774
775         return false;
776     }
777 }
778
779
780 int GameController::nextIndex(int index,int seriesCaptureIndex){
781     //We have to go back
782
783     if(m_captureInfo[seriesCaptureIndex].second[0] == GameInfo::FOLLOWING){
784
785         if(m_rotationInfo == GameInfo::CLOCKWISE){
786             if(index == 0){
787                 index = 2 * m_gameInfo->numCupsPerRow() - 1;
788                 return index;
789             }
790
791             else{
792                 index = index-1;
793                 return index;
794             }
795         }
796         else{
797             index = (index+1) % ( 2 * m_gameInfo->numCupsPerRow() );
798             return index;
799         }
800     }
801     //we will go forward
802     else{
803
804         if(m_rotationInfo == GameInfo::CLOCKWISE){
805             index = (index + 1) % ( 2 * m_gameInfo->numCupsPerRow() );
806             return index;
807         }
808
809         else{
810             if(index == 0){
811                 index = 2 * m_gameInfo->numCupsPerRow() - 1;
812                 return index;
813             }
814             else{
815                 index = index - 1;
816                 return index;
817             }
818         }
819     }
820 }
821
822 //-------------------------------------capture handling ends---------------------------
823
824 void GameController::changeScore(int amount,bool human){
825     if(human){
826         m_humanScore->changeScore(amount);
827         emit signalShowScore(m_humanScore->score(),true);
828     }
829     else{
830         m_computerScore->changeScore(amount);
831         emit signalShowScore(m_computerScore->score(),false);
832     }
833 }
834
835 //Human Has no move, now what
836 void GameController::humanHasNoMove(){
837
838     if(m_gameOver) return;
839     int check = m_gameInfo->specialFlag();
840     if(m_physicalMoveAllowed) emit signalMessage( tr("No Move human") );
841
842     if( check & 2){//turn passing
843         if(m_physicalMoveAllowed) changeTurn();
844         else m_humanTurn = !m_humanTurn;
845
846         if(m_physicalMoveAllowed) makeComputerMove();
847     }
848     else{
849         if(m_physicalMoveAllowed) finalCapture(m_physicalBoard);
850         else finalCapture(m_logicalBoard);
851     }
852 }
853
854 //computer has no move, now what
855 void GameController::computerHasNoMove(){
856     // Special Flag - 0(empty Opponent),1(turn Passing),2(Compulsory Moves)
857     if(m_gameOver) return;
858     int check = m_gameInfo->specialFlag();
859     if(m_physicalMoveAllowed) emit signalMessage( tr("No Move Computer") );
860
861     if( check & 2){//turn passing
862         if(m_physicalMoveAllowed) changeTurn();
863         else m_humanTurn = !m_humanTurn;
864     }
865     else{
866         if(m_physicalMoveAllowed) finalCapture(m_physicalBoard);
867         else finalCapture(m_logicalBoard);
868     }
869 }
870
871 //when one has no move, this is called on condition
872 void GameController::finalCapture(QList<int>& board){
873
874     int loop;
875
876     //capture from human side to humanKalah
877     for( int i = 0 ; i < m_humanSideCups.count() ; i++){
878         int index = m_humanSideCups[i];
879
880         //Going to Human Kalah
881         if(board[index]){
882             loop = board[index];
883             for(int i = 0 ; i < loop ; i++){
884                 if(m_physicalMoveAllowed) m_board->updateChildren(index,m_humanKalah,false);
885                 board[index]--;
886                 board[m_humanKalah + 2*m_gameInfo->numCupsPerRow()]++;
887                 if(m_physicalMoveAllowed) changeScore(1,true);
888             }
889         }
890         //Going to Computer kalah
891         if(board[2*m_gameInfo->numCupsPerRow() - 1 - index]){
892             loop = board[2*m_gameInfo->numCupsPerRow() - 1 - index];
893             for(int i = 0 ; i < loop ; i++){
894                 if(m_physicalMoveAllowed)  m_board->updateChildren(2*m_gameInfo->numCupsPerRow() - 1 - index,1-m_humanKalah,false);
895                 board[2*m_gameInfo->numCupsPerRow() - 1 - index]--;
896                 board[1-m_humanKalah + 2*m_gameInfo->numCupsPerRow()]++;
897                 if(m_physicalMoveAllowed) changeScore(1,false);
898             }
899         }
900
901     }
902
903     if(m_physicalMoveAllowed){
904         m_gameOver = true;
905         emit signalGameOver();
906     }
907 }
908
909 //----------------------------------------------------------------------------------------
910
911
912 QPair< bool,QList<int> > GameController::logicalMoveController(QList<int>board,int index,bool turn){
913
914     bool tempTurn = m_humanTurn; //storing turn of physical board
915     m_physicalMoveAllowed = false; //setting physical move as invalid
916
917     bool humanTurn = !turn; //next turn should be other(if not bonus move)
918     m_humanTurn = turn;    //current board status, turn of parent node
919     setLogicalBoard(board);
920
921     //sowing
922     index = singleSow(index);
923
924     if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE){
925         while(!isEndOfLap(index,m_logicalBoard)){
926             index = singleSow(index);
927         }
928     }
929
930
931     //If bonus turn do not change turn
932     if(m_gameInfo->isBonusTurn()){
933
934         if(index >= 2*m_gameInfo->numCupsPerRow()){   //is a kalah
935             //kDebug() << "A Bonus Turn:";
936             if(m_humanTurn && isHumanKalah(index)){
937                 humanTurn = true;
938             }
939             else if(!m_humanTurn && !isHumanKalah(index)){
940                 humanTurn = false;
941             }
942
943         }
944     }
945
946     handleCrossCapture(index,m_logicalBoard);
947     handleCountNSeriesCapture(index,m_logicalBoard);
948
949     if(isHumanSideEmpty(m_logicalBoard))
950         humanHasNoMove();
951     else if(isComputerSideEmpty(m_logicalBoard))
952         computerHasNoMove();
953
954     m_humanTurn = tempTurn; //restoring m_humanTurn
955     m_physicalMoveAllowed = true;
956     return qMakePair(humanTurn,m_logicalBoard);
957
958 }
959
960 void GameController::setPhysicalBoard(QList<int> board){
961     for(int i = 0 ; i < m_physicalBoard.count() ; i++)
962         m_physicalBoard[i] = board[i];
963 }
964
965
966 void GameController::setLogicalBoard(QList<int> board){
967     for(int i = 0 ; i < m_logicalBoard.count() ; i++)
968         m_logicalBoard[i] = board[i];
969 }
970
971 QList<int> GameController::logicalBoard(){ return m_logicalBoard;}
972 QList<int> GameController::physicalBoard(){return m_physicalBoard;}
973
974 //----------------------------------------------------------------------------------------
975 #include "moc_GameController.cpp"