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
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.
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.
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/>.
22 #include "GameController.h"
25 #include <QStringList>
28 // #include <kdebug.h>
33 #include "MoveGenerator.h"
36 GameController::GameController(GameInfo* gameInfo){
37 m_gameInfo = gameInfo;
38 m_humanScore = new Score();
39 m_computerScore = new Score();
40 initializeGameController();
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()));
48 void GameController::initializeGameController(){
50 m_gameDifficulty = GameController::EASY;
51 m_moveGenerator = new MoveGenerator(m_gameDifficulty,m_gameInfo,this);
53 m_cupIndexClicked = -1;
54 m_humanSide = GameController::LOWER;
55 m_humanKalah = Kalah::Right;
58 m_physicalMoveAllowed = false;
59 m_captureInfo = m_gameInfo->captureInfo();
61 //If game is clockwise change human kalah
62 if(m_humanSide == GameController::LOWER && m_gameInfo->rotationType() == GameInfo::CLOCKWISE){
63 m_humanKalah = Kalah::Left;
66 m_humanScore->reset();
67 m_computerScore->reset();
69 emit signalMessage("");
70 emit signalShowTurn(m_humanTurn);
71 emit signalShowScore(m_humanScore->score(),true);
72 emit signalShowScore(m_computerScore->score(),false);
79 void GameController::initializeBoard(){
81 while(m_physicalBoard.count()){
82 m_physicalBoard.pop_back();
83 m_logicalBoard.pop_back();
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());
92 //stoneInfo in kalah's
93 for(int i = 0 ; i < 2 ; i++){
94 m_physicalBoard.append(0);
95 m_logicalBoard.append(0);
100 void GameController::setHumanSideCups(){
102 while(m_humanSideCups.count())
103 m_humanSideCups.pop_back();
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];
115 //It is called from the GraphcisScene to start the game
116 void GameController::setBoardItem(Board *board){
119 //If computer starts we will delay it by 1.5 seconds
121 emit signalShowTurn(false);
122 QTimer::singleShot(1500, this, SLOT(makeComputerMove()));
127 //-------------Is this valid cup(cupIndex) belongs to human ----------------
128 bool GameController::isHumanCup(int cupIndex){
130 if(cupIndex >= m_gameInfo->numCupsPerRow())
135 //----------------Is the kalah(kalahIndex) belongs to human---------------------
136 bool GameController::isHumanKalah(int kalahIndex){
137 kalahIndex -= 2*m_gameInfo->numCupsPerRow();
139 if(kalahIndex == m_humanKalah){
145 //-----------------------------Human Move-----------------------------------
146 void GameController::makeHumanMove(int index){
148 if(isGameOver(m_physicalBoard) || !m_humanTurn) return;
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);
159 //----------------------------------Computer Move----------------------------
160 void GameController::makeComputerMove(){
162 if(isGameOver(m_physicalBoard) || m_humanTurn) return;
164 // kDebug() << "Computer Moving ................";
166 m_physicalMoveAllowed = false;
167 int index = m_moveGenerator->bestMove(m_physicalBoard,false);
168 m_physicalMoveAllowed = true;
169 m_rotationInfo = m_gameInfo->rotationInfo(index);
172 // kDebug() << "Index: " << index << " Stones: " << m_physicalBoard[index];
181 void GameController::sowMaker(int index){
183 if(isGameOver(m_physicalBoard)) return;
184 m_physicalMoveAllowed = true;
187 //For human Turn, we want to response quick, unless it falls between multiple lap
189 if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE && m_multipleLapDelay)
190 QTimer::singleShot(1500,this,SLOT(sowController()));
191 else sowController();
194 else QTimer::singleShot(1500,this,SLOT(sowController()));
198 void GameController::sowController(){
200 if(m_gameOver) return;
203 index = singleSow(index);
205 if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE && !isEndOfLap(index,m_physicalBoard)){
206 if(m_humanTurn) m_multipleLapDelay = true;
207 emit signalSowMaker(index);
210 emit signalAfterSow(index);
216 void GameController::afterSow(int index){
218 if(isGameOver(m_physicalBoard)) return;
219 if(m_gameInfo->isBonusTurn()){
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();
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();
240 if(isGameOver(m_physicalBoard)) return;
241 handleCrossCapture(index,m_physicalBoard);
242 emit signalMessage("");
244 if(isGameOver(m_physicalBoard)) return;
245 int multiplier = handleCountNSeriesCapture(index,m_physicalBoard);
247 if(isGameOver(m_physicalBoard)) return;
250 if(!m_humanTurn && !m_gameOver){
251 // kDebug() << "Next turn computer";
252 if(isComputerSideEmpty(m_physicalBoard)) computerHasNoMove();
255 QTimer::singleShot( multiplier * 1500, this, SLOT(makeComputerMove() ) );
257 QTimer::singleShot(1500, this, SLOT(makeComputerMove()));
261 // kDebug() << "Next turn Human";
262 if(isHumanSideEmpty(m_physicalBoard) ) humanHasNoMove();
267 void GameController::changeTurn(){
269 m_humanTurn == true ? m_humanTurn = false : m_humanTurn = true;
270 emit signalShowTurn(m_humanTurn);
273 //---------------------------- is End Of Lap -----------------------------------
274 bool GameController::isEndOfLap(int index,QList<int>& board){
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()){
280 //if last stone on a kalah
281 if(index >= 2*m_gameInfo->numCupsPerRow()){
288 //Will be true when each cup is empty
289 bool GameController::isGameOver(QList<int>& board){
291 if(m_gameOver) return true;
293 for(int i = 0 ; i < 2*m_gameInfo->numCupsPerRow() ; i++)
294 if( board[i] > m_gameInfo->leftToCup() )
296 if(m_physicalMoveAllowed) emit signalGameOver();
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);
307 // if(m_physicalMoveAllowed) kDebug() << "We are here to sow";
310 if(m_physicalMoveAllowed) board = physicalBoard();
311 else board = logicalBoard();
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;
319 //Initial Check where to put in the first stone
320 if( rotation == GameInfo::ANTICLOCKWISE){
323 if(cupIndex >= m_gameInfo->numCupsPerRow()){
324 kalahNo = Kalah::Right;
327 if( m_gameInfo->stonesToKalah() &&
328 ( (cupIndex == m_gameInfo->numCupsPerRow() && side == GameController::LOWER)
329 || ( cupIndex == 0 && side == GameController::UPPER ) ) )
335 if(cupIndex < m_gameInfo->numCupsPerRow())
336 kalahNo = Kalah::Right;
338 if( m_gameInfo->stonesToKalah() &&
339 ( (cupIndex == (2 * m_gameInfo->numCupsPerRow()-1) && side == GameController::LOWER)
340 || ( cupIndex == (m_gameInfo->numCupsPerRow()-1) && side == GameController::UPPER) ) )
345 //Continuous check and update
346 int loop = board[cupIndex]- m_gameInfo->leftToCup();
348 for(int j = 0 ; j < loop ; j++){
350 if( rotation == GameInfo::CLOCKWISE)
351 i %= 2 * m_gameInfo->numCupsPerRow();
353 if( i < 0) i = 2 * m_gameInfo->numCupsPerRow() - 1;
355 //If it is need to be put in cup
359 if(m_physicalMoveAllowed){
360 m_board->updateChildren(cupIndex,i,true);
361 // // kDebug() << "Putting to cup: " << i;
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 ) ) )
374 if( m_gameInfo->stonesToKalah() &&
375 ( (i == (2 * m_gameInfo->numCupsPerRow()-1) && side == GameController::LOWER)
376 || ( i == (m_gameInfo->numCupsPerRow()-1) && side == GameController::UPPER) ) )
382 //going to put it in kalah
385 if(kalahNo == Kalah::Right){
387 if(m_physicalMoveAllowed){
388 // kDebug() << "Putting to Right Kalah";
389 m_board->updateChildren(cupIndex,Kalah::Right,false);
391 returnValue = 2*m_gameInfo->numCupsPerRow() + Kalah::Right;
392 board[returnValue]++;
396 if(m_physicalMoveAllowed){
397 // kDebug() << "Putting to left kalah";
398 m_board->updateChildren(cupIndex,Kalah::Left,false);
401 returnValue = 2*m_gameInfo->numCupsPerRow() + Kalah::Left;
402 board[returnValue]++;
405 if(m_physicalMoveAllowed){
406 if(m_humanTurn && kalahNo == m_humanKalah)
408 else changeScore(1,false);
417 if(m_physicalMoveAllowed) setPhysicalBoard(board);
418 else setLogicalBoard(board);
424 void GameController::slotGameDifficulty(Difficulty difficulty){
425 // kDebug() << "GameDifficulty is: " << difficulty;
426 m_gameDifficulty = difficulty;
427 m_moveGenerator->changeDifficulty(m_gameDifficulty);
431 //******************************** slots ******************************************
432 void GameController::slotMouseClicked(int index){
438 m_cupIndexClicked = index;
440 if(isHumanSideEmpty(m_physicalBoard)){
441 emit signalMessage( tr("Sorry, you have no move") );
444 else if(m_cupIndexClicked < 0){
445 emit signalMessage( tr("Click on a Cup") );
448 else if(!isHumanCup(index))
449 emit signalMessage( tr("Click on a cup in the lower row") );
451 else if(m_physicalBoard[index] <= m_gameInfo->leftToCup())
452 emit signalMessage( tr("Sorry, not enough stones to move") );
455 makeHumanMove(m_cupIndexClicked);
461 void GameController::slotGameOverForNewGame(int identity){
463 emit signalMessage( tr("Loading game...") );
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)));
471 connect(this,SIGNAL(timeout(int)),this,SLOT(newGameEmitter(int)));
472 timer->setSingleShot(true);
476 void GameController::newGameEmitter(int identity){
477 emit signalNewGame(identity);
480 void GameController::slotGameOverForRestartGame(){
482 // kDebug() << "GameOver is true";
483 emit signalMessage( tr("Loading game...") );
484 QTimer::singleShot(2000,this,SLOT(restartGameEmitter()));
487 void GameController::restartGameEmitter(){
488 emit signalRestartGame();
491 //******************************** slots *****************************
493 bool GameController::isHumanSideEmpty(QList<int>& board){
495 for(int i = 0 ; i < m_gameInfo->numCupsPerRow() ; i++)
496 if(board[m_humanSideCups[i]] > m_gameInfo->leftToCup())
501 bool GameController::isComputerSideEmpty(QList<int>& board){
503 int maxIndex = 2*m_gameInfo->numCupsPerRow() - 1;
505 for(int i = 0 ; i < m_gameInfo->numCupsPerRow() ; i++)
506 if(board[maxIndex - m_humanSideCups[i]] > m_gameInfo->leftToCup())
511 //---------------------------------- capture handling-------------------------------------
513 void GameController::handleCrossCapture(int index,QList<int>& board){
515 if(m_physicalMoveAllowed){ //kDebug() << "handle Cross capture -------";
516 if(isGameOver(m_physicalBoard)) return;
518 if(index >= 2*m_gameInfo->numCupsPerRow())
521 //if CrossCapture allowed then 0th bit should be 1
522 int capture = m_gameInfo->captureType();
523 if(m_physicalMoveAllowed) // kDebug() << "Capture Info: " << capture;
525 if(m_physicalMoveAllowed) //kDebug() << "We will return";
529 int opponentCupIndex;
532 if(index < 2*m_gameInfo->numCupsPerRow()){
534 opponentCupIndex = 2*m_gameInfo->numCupsPerRow() - 1 - index;
535 //if opponet cup is empty
536 if(board[opponentCupIndex] == 0)
538 if(board[index] != 1) //we are now taking that only 1 stone
541 if(isHumanCup(index) && m_humanTurn)
542 kalahIndex = m_humanKalah;
543 else if(!m_humanTurn && !isHumanCup(index))
544 kalahIndex = 1 - m_humanKalah;
546 //Now do the capture;
547 if(kalahIndex != -1){
548 QString strIndex = QString("%1,%2").arg(index).arg(kalahIndex);
551 if(m_physicalMoveAllowed){
552 QTimer* timer = new QTimer(this);
553 signalMapper = new QSignalMapper(this);
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&)));
559 connect(this,SIGNAL(timeout(const QString&)),this,SLOT(crossCapture(const QString&)));
560 timer->setSingleShot(true);
563 else crossCapture(strIndex);
569 //Cross Capture is done here
570 void GameController::crossCapture(const QString& indexString){
572 if(isGameOver(m_physicalBoard)) return;
574 int capture = m_gameInfo->captureType();
575 if(! (capture & 1) ) return;
580 int index,kalahIndex,opponentCupIndex;
582 list = indexString.split(',');
583 index = list[0].toInt();
584 kalahIndex = list[1].toInt();
585 opponentCupIndex = 2*m_gameInfo->numCupsPerRow() - 1 - index;
587 if(m_physicalMoveAllowed) board = physicalBoard();
588 else board = logicalBoard();
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);
595 board[kalahIndex + 2*m_gameInfo->numCupsPerRow()]++;
597 if(m_physicalMoveAllowed){
598 if(kalahIndex == m_humanKalah)
600 else changeScore(1,false);
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()]++;
611 if(m_physicalMoveAllowed){
612 if(kalahIndex == m_humanKalah)
614 else changeScore(1,false);
619 if(m_physicalMoveAllowed) setPhysicalBoard(board);
620 else setLogicalBoard(board);
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;
630 int capture = m_gameInfo->captureType(),i = 0,kalahIndex;
631 int countCaptureIndex = -1,seriesCaptureIndex = -1;
635 if(capture & 1) i++; //cross capture is at capture_info[0]
636 if(capture & 2) countCaptureIndex = i++;
637 if(capture & 4) seriesCaptureIndex = i++;
639 //If no count capture, then no series capture also
640 if(countCaptureIndex == -1){
644 //At this point we know count captue is allowed in this game
645 captureAllowed = false;
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 ) )
653 ( ( ( m_humanTurn && isHumanCup(index) ) || (!m_humanTurn && !isHumanCup(index) ) )
654 && (m_captureInfo[countCaptureIndex].first == GameInfo::OWN ||
655 m_captureInfo[countCaptureIndex].first == GameInfo::BOTH ) ) )
657 captureAllowed = true;
661 while(captureAllowed){
663 //if capture allowed and stone Number matched at the cup, then we will capture
664 if(stoneNumberMatched(index,countCaptureIndex,board)){
667 // if(m_physicalMoveAllowed) kDebug() << "count capture allowed";
668 if(m_humanTurn) kalahIndex = m_humanKalah;
669 else kalahIndex = 1 - m_humanKalah;
671 QString strIndex = QString("%1,%2").arg(index).arg(kalahIndex);
674 if(m_physicalMoveAllowed){
675 // kDebug() << "str: " << strIndex;
677 QTimer* timer = new QTimer(this);
678 signalMapper = new QSignalMapper(this);
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&)));
684 connect(this,SIGNAL(timeout(const QString&)),this,SLOT(countCapture(const QString&)));
685 timer->setSingleShot(true);
686 timer->start(timerCount * 1500);
688 else countCapture(strIndex);
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;
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 )
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;
716 void GameController::countCapture(const QString& indexString){
718 if(isGameOver(m_physicalBoard)) return;
722 int index,kalahIndex;
724 list = indexString.split(',');
725 index = list[0].toInt();
726 kalahIndex = list[1].toInt();
728 if(m_physicalMoveAllowed) board = physicalBoard();
729 else board = logicalBoard();
731 if(m_physicalMoveAllowed) m_board->updateChildren(index,kalahIndex,board[index]);
732 board[kalahIndex + 2*m_gameInfo->numCupsPerRow()] += board[index];
734 if(m_physicalMoveAllowed){
735 if(m_humanTurn) changeScore(board[index],true);
736 else changeScore(board[index],false);
741 if(m_physicalMoveAllowed) setPhysicalBoard(board);
742 else setLogicalBoard(board);
746 bool GameController::stoneNumberMatched(int index,int countCaptureIndex,QList<int>& board){
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];
756 // if(m_physicalMoveAllowed) kDebug() << "Returning false";
761 // if(m_physicalMoveAllowed) kDebug() << "I am in 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];
780 int GameController::nextIndex(int index,int seriesCaptureIndex){
783 if(m_captureInfo[seriesCaptureIndex].second[0] == GameInfo::FOLLOWING){
785 if(m_rotationInfo == GameInfo::CLOCKWISE){
787 index = 2 * m_gameInfo->numCupsPerRow() - 1;
797 index = (index+1) % ( 2 * m_gameInfo->numCupsPerRow() );
804 if(m_rotationInfo == GameInfo::CLOCKWISE){
805 index = (index + 1) % ( 2 * m_gameInfo->numCupsPerRow() );
811 index = 2 * m_gameInfo->numCupsPerRow() - 1;
822 //-------------------------------------capture handling ends---------------------------
824 void GameController::changeScore(int amount,bool human){
826 m_humanScore->changeScore(amount);
827 emit signalShowScore(m_humanScore->score(),true);
830 m_computerScore->changeScore(amount);
831 emit signalShowScore(m_computerScore->score(),false);
835 //Human Has no move, now what
836 void GameController::humanHasNoMove(){
838 if(m_gameOver) return;
839 int check = m_gameInfo->specialFlag();
840 if(m_physicalMoveAllowed) emit signalMessage( tr("No Move human") );
842 if( check & 2){//turn passing
843 if(m_physicalMoveAllowed) changeTurn();
844 else m_humanTurn = !m_humanTurn;
846 if(m_physicalMoveAllowed) makeComputerMove();
849 if(m_physicalMoveAllowed) finalCapture(m_physicalBoard);
850 else finalCapture(m_logicalBoard);
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") );
861 if( check & 2){//turn passing
862 if(m_physicalMoveAllowed) changeTurn();
863 else m_humanTurn = !m_humanTurn;
866 if(m_physicalMoveAllowed) finalCapture(m_physicalBoard);
867 else finalCapture(m_logicalBoard);
871 //when one has no move, this is called on condition
872 void GameController::finalCapture(QList<int>& board){
876 //capture from human side to humanKalah
877 for( int i = 0 ; i < m_humanSideCups.count() ; i++){
878 int index = m_humanSideCups[i];
880 //Going to Human Kalah
883 for(int i = 0 ; i < loop ; i++){
884 if(m_physicalMoveAllowed) m_board->updateChildren(index,m_humanKalah,false);
886 board[m_humanKalah + 2*m_gameInfo->numCupsPerRow()]++;
887 if(m_physicalMoveAllowed) changeScore(1,true);
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);
903 if(m_physicalMoveAllowed){
905 emit signalGameOver();
909 //----------------------------------------------------------------------------------------
912 QPair< bool,QList<int> > GameController::logicalMoveController(QList<int>board,int index,bool turn){
914 bool tempTurn = m_humanTurn; //storing turn of physical board
915 m_physicalMoveAllowed = false; //setting physical move as invalid
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);
922 index = singleSow(index);
924 if(m_gameInfo->lapStyle() == GameInfo::MULTIPLE){
925 while(!isEndOfLap(index,m_logicalBoard)){
926 index = singleSow(index);
931 //If bonus turn do not change turn
932 if(m_gameInfo->isBonusTurn()){
934 if(index >= 2*m_gameInfo->numCupsPerRow()){ //is a kalah
935 //kDebug() << "A Bonus Turn:";
936 if(m_humanTurn && isHumanKalah(index)){
939 else if(!m_humanTurn && !isHumanKalah(index)){
946 handleCrossCapture(index,m_logicalBoard);
947 handleCountNSeriesCapture(index,m_logicalBoard);
949 if(isHumanSideEmpty(m_logicalBoard))
951 else if(isComputerSideEmpty(m_logicalBoard))
954 m_humanTurn = tempTurn; //restoring m_humanTurn
955 m_physicalMoveAllowed = true;
956 return qMakePair(humanTurn,m_logicalBoard);
960 void GameController::setPhysicalBoard(QList<int> board){
961 for(int i = 0 ; i < m_physicalBoard.count() ; i++)
962 m_physicalBoard[i] = board[i];
966 void GameController::setLogicalBoard(QList<int> board){
967 for(int i = 0 ; i < m_logicalBoard.count() ; i++)
968 m_logicalBoard[i] = board[i];
971 QList<int> GameController::logicalBoard(){ return m_logicalBoard;}
972 QList<int> GameController::physicalBoard(){return m_physicalBoard;}
974 //----------------------------------------------------------------------------------------
975 #include "moc_GameController.cpp"