| 
					
				 | 
			
			
				@@ -1,12 +1,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "CheckerBoard.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <iostream> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CheckerBoard::CheckerBoard() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+CheckerBoard::CheckerBoard() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lastMove = "NONE"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CheckerBoard CheckerBoard::loadFromFile(string filename) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+CheckerBoard CheckerBoard::loadFromFile(string filename) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerBoard board = CheckerBoard(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ifstream file(filename); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -14,68 +15,100 @@ CheckerBoard CheckerBoard::loadFromFile(string filename) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int color = WHITE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while (getline(file, line)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (line.find("White:") != string::npos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while (getline(file, line)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Toggle color mode if color flag is found 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (line.find("White:") != string::npos) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             color = WHITE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if (line.find("Black:") != string::npos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (line.find("Black:") != string::npos) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             color = BLACK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if (!line.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (line[0] == 'M') board.placeChecker(CheckerPosition(line.substr(1, 2)), color == WHITE ? CheckerPiece::WHITE_KING : CheckerPiece::BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else board.placeChecker(CheckerPosition(line), color == WHITE ? CheckerPiece::WHITE : CheckerPiece::BLACK); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (!line.empty()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // If the checker position starts with M (which marks a king), skip the first character of the position and create a king 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (line[0] == 'M') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                board.placeChecker(CheckerPosition(line.substr(1, 2)), color == WHITE ? CheckerPiece::WHITE_KING : CheckerPiece::BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // otherwise, use full position string and create a regular checker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                board.placeChecker(CheckerPosition(line), color == WHITE ? CheckerPiece::WHITE : CheckerPiece::BLACK); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     file.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Iterate over whole board and assign CheckerPiece::EMPTY where no checker is present 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (int i = 0; i < BOARD_SIZE; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for (int j = 0; j < BOARD_SIZE; j++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPosition pos(i, j); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece piece = board.getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (piece != WHITE && piece != WHITE_KING && piece != BLACK && piece != BLACK_KING) board.setCheckerAt(pos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (piece != WHITE && piece != WHITE_KING && piece != BLACK && piece != BLACK_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                board.setCheckerAt(pos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return board; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-CheckerPiece CheckerBoard::getCheckerAt(CheckerPosition pos) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!pos.isValid()) return CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+CheckerPiece CheckerBoard::getCheckerAt(CheckerPosition pos) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Always return empty space when the position is not valid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!pos.isValid()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return board[pos.x][pos.y]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void CheckerBoard::setCheckerAt(CheckerPosition pos, CheckerPiece checker) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Skip if position is invalid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!pos.isValid()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     board[pos.x][pos.y] = checker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CheckerBoard::moveChecker(CheckerPosition from, CheckerPosition to) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::moveChecker(CheckerPosition from, CheckerPosition to) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece checker = getCheckerAt(from); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Remove the checker from its original position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     setCheckerAt(from, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Calculate movement direction 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int cx = to.x - from.x > 0 ? 1 : -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int cy = to.y - from.y > 0 ? 1 : -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Current position for iterating 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int sx = from.x + cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int sy = from.y + cy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Remove all pieces between the starting and ending point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while (sx != to.x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         setCheckerAt(CheckerPosition(sx, sy), CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         sx += cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         sy += cy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Insert the checker into new position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     setCheckerAt(to, checker); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (checker == CheckerPiece::WHITE && to.y == BOARD_SIZE - 1) setCheckerAt(to, CheckerPiece::WHITE_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    else  if (checker == CheckerPiece::BLACK && to.y == 0) setCheckerAt(to, CheckerPiece::BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // If reached opposite edge of the board, promote checker to king 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (checker == CheckerPiece::WHITE && to.y == BOARD_SIZE - 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        setCheckerAt(to, CheckerPiece::WHITE_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else if (checker == CheckerPiece::BLACK && to.y == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        setCheckerAt(to, CheckerPiece::BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void CheckerBoard::print() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Legend at the top 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     wcout << "--A---B---C---D---E---F---G---H---" << endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (int y = BOARD_SIZE - 1; y >= 0; y--) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -102,17 +135,27 @@ void CheckerBoard::print() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        wcout << "| " << y+1 << endl << "-------------------------------- " << endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Print out the last border, the Y-axis legend and the separator row 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        wcout << "| " << y + 1 << endl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              << "-------------------------------- " << endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-std::vector<CheckerBoard> CheckerBoard::generateLegalMoves(bool isWhite) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+std::vector<CheckerBoard> CheckerBoard::generateLegalMoves(bool isWhite) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::vector<CheckerBoard> moves; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Iterate over all board cells 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece checker = getCheckerAt(CheckerPosition(i, j)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // If the checker is of corresponding color, generate all possible moves for it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if ((isWhite && (checker == WHITE || checker == WHITE_KING)) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                (!isWhite && (checker == BLACK || checker == BLACK_KING))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (!isWhite && (checker == BLACK || checker == BLACK_KING))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 generateMovesForPiece(CheckerPosition(i, j), moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -121,62 +164,101 @@ std::vector<CheckerBoard> CheckerBoard::generateLegalMoves(bool isWhite) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return moves; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CheckerBoard::applyMove(const CheckerBoard& move) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::applyMove(const CheckerBoard &move) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Iterate over all board cells and copy values from the alternative board 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             setCheckerAt(CheckerPosition(i, j), move.getCheckerAt(CheckerPosition(i, j))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int CheckerBoard::evaluate() const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int CheckerBoard::evaluate() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int score = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Iterate over all board cells and calculate the score of the board 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece checker = getCheckerAt(CheckerPosition(i, j)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (checker == WHITE) score += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else if (checker == WHITE_KING) score += 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else if (checker == BLACK) score -= 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else if (checker == BLACK_KING) score -= 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Kings are more valuable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (checker == WHITE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                score += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (checker == WHITE_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                score += 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (checker == BLACK) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                score -= 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (checker == BLACK_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                score -= 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return score; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-bool CheckerBoard::isGameOver() const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isGameOver() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     bool whiteExists = false, blackExists = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (board[i][j] == WHITE || board[i][j] == WHITE_KING) whiteExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (board[i][j] == BLACK || board[i][j] == BLACK_KING) blackExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Iterate over all board cells and find if any checkers of each side still exist 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (board[i][j] == WHITE || board[i][j] == WHITE_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                whiteExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (board[i][j] == BLACK || board[i][j] == BLACK_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                blackExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // The game is over when one of the sides is cleansed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return !whiteExists || !blackExists; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<CheckerBoard>& moves) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<CheckerBoard> &moves) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece piece = getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    int directions[4][2] = { {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (auto& dir : directions) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Possible directions are: bottom-left, top-left, top-right, bottom-right 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int directions[4][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (auto &dir : directions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Position after the move 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         CheckerPosition newpos(pos.x + dir[0], pos.y + dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Position after the move if an enemy's checker is captured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         CheckerPosition cpos(pos.x + 2 * dir[0], pos.y + 2 * dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (isValidMove(pos, newpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isValidMove(pos, newpos, piece)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Copy the board and apply the move 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerBoard newBoard = *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.moveChecker(pos, newpos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Save data about the move 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.lastMove = pos.to_num_string() + " -> " + newpos.to_num_string(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.moveOldPos = pos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.moveNewPos = newpos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && newpos.y == 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Promote to king if the opposite edge is reached 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && newpos.y == 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(newpos, (piece == WHITE) ? WHITE_KING : BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Save the move 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            CheckerPosition cpos(pos.x + 2 * dir[0], pos.y + 2 * dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (isValidCapture(pos, newpos, cpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // If a capture is possible, count it as a different move 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isValidCapture(pos, newpos, cpos, piece)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 CheckerBoard newBoard = *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 CheckerPiece checker = newBoard.getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -184,19 +266,24 @@ void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<Checke 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.moveOldPos = pos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.moveNewPos = newpos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Move the checker and remove one that was captured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(newpos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(pos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(cpos, checker); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && cpos.y == 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // If the opposite edge of the board is reached, promote to king 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && cpos.y == 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     newBoard.setCheckerAt(cpos, (piece == WHITE) ? WHITE_KING : BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                //generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if (isValidCapture(pos, newpos, cpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // If the move is not valid, the capture still might be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (isValidCapture(pos, newpos, cpos, piece)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerBoard newBoard = *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece checker = newBoard.getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -208,15 +295,18 @@ void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<Checke 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.setCheckerAt(pos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.setCheckerAt(cpos, checker); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && cpos.y == 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Promote to king if the opposite edge is reached 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((piece == WHITE && newpos.y == BOARD_SIZE - 1) || (piece == BLACK && cpos.y == 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(cpos, (piece == WHITE) ? WHITE_KING : BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Print out moves for debug purposes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /*for (auto& move : moves) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         wcout << "Move: \n"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -224,70 +314,120 @@ void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<Checke 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-bool CheckerBoard::isValidMove(CheckerPosition oldPos, CheckerPosition newPos, CheckerPiece piece) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (newPos.x < 0 || newPos.x >= BOARD_SIZE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (newPos.y < 0 || newPos.y >= BOARD_SIZE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isValidMove(CheckerPosition oldPos, CheckerPosition newPos, CheckerPiece piece) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // If the new position is not valid, the move is not valid either 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!newPos.isValid()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Checker piece at the current position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece at = getCheckerAt(oldPos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Checker piece at the new position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece atnew = getCheckerAt(newPos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (at == CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (atnew != CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // There should be a checker in the current position (the one we're moving) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (at == CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // You can't move to a cell if it's occupied 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (atnew != CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Calculate position delta 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int dx = newPos.x - oldPos.x, dy = newPos.y - oldPos.y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Calcule movement direction 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int cx = dx > 0 ? 1 : -1, cy = dy > 0 ? 1 : -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     bool isWhite = at == CheckerPiece::WHITE || at == CheckerPiece::WHITE_KING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (abs(dx) != abs(dy) || dx == 0) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Checkers may only move diagonally 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (abs(dx) != abs(dy) || dx == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // King-specific conditions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (piece == CheckerPiece::WHITE_KING || piece == CheckerPiece::BLACK_KING) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int sx = oldPos.x + cx, sy = oldPos.y + cy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // There shouldn't be an ally checker in the way 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         while (sx != newPos.x || sy != newPos.y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece between = getCheckerAt(CheckerPosition(sx, sy)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (isWhite && !(between == CheckerPiece::BLACK || between == CheckerPiece::BLACK_KING || between == CheckerPiece::NONE)) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (!isWhite && !(between == CheckerPiece::WHITE || between == CheckerPiece::WHITE_KING || between == CheckerPiece::NONE)) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isWhite && !(between == CheckerPiece::BLACK || between == CheckerPiece::BLACK_KING || between == CheckerPiece::NONE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isWhite && !(between == CheckerPiece::WHITE || between == CheckerPiece::WHITE_KING || between == CheckerPiece::NONE)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             sx += cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             sy += cy; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Conditions for regular checkers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (isWhite && dy == -1) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if (!isWhite && dy == 1) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Regular checkers may not go backwards 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isWhite && dy == -1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (!isWhite && dy == 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // If moved 2 cells (capture scenario) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         else if (abs(dx) == 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Checker in-between the current and the new position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerPiece between = getCheckerAt(CheckerPosition(oldPos.x + cx, oldPos.y + cy)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (between == CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (getCheckerAt(newPos) != CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (isWhite && !(between == CheckerPiece::BLACK || between == CheckerPiece::BLACK_KING)) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (!isWhite && !(between == CheckerPiece::WHITE || between == CheckerPiece::WHITE_KING)) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // There should be a checker to capture 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (between == CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // There shouldn't be any checker in the new position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (getCheckerAt(newPos) != CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // The captured checker shall not be ally 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isWhite && !(between == CheckerPiece::BLACK || between == CheckerPiece::BLACK_KING)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!isWhite && !(between == CheckerPiece::WHITE || between == CheckerPiece::WHITE_KING)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else if (abs(dx) > 2) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Regular checkers may not move more than 2 cells in any situation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (abs(dx) > 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void CheckerBoard::generateAdditionalCaptures(CheckerPosition pos, CheckerBoard& currentBoard, std::vector<CheckerBoard>& moves) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::generateAdditionalCaptures(CheckerPosition pos, CheckerBoard ¤tBoard, std::vector<CheckerBoard> &moves) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece piece = currentBoard.getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    int directions[4][2] = { {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    for (auto& dir : directions) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Top-left, top-right, bottom-right, bottom-left of the checker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int directions[4][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Analyze all directions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (auto &dir : directions) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // The position of the captured checker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         CheckerPosition npos(pos.x + dir[0], pos.y + dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Final position after capture 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         CheckerPosition cpos(pos.x + 2 * dir[0], pos.y + 2 * dir[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (isValidCapture(pos, npos, cpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // If the capture is valid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isValidCapture(pos, npos, cpos, piece)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             CheckerBoard newBoard = currentBoard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Move the checker and remove captured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.setCheckerAt(cpos, newBoard.getCheckerAt(pos)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.setCheckerAt(pos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             newBoard.setCheckerAt(npos, CheckerPiece::NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if ((piece == WHITE && cpos.x == BOARD_SIZE-1) || (piece == BLACK && cpos.x == 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Promote to king if the opposite edge is reached 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((piece == WHITE && cpos.x == BOARD_SIZE - 1) || (piece == BLACK && cpos.x == 0)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 newBoard.setCheckerAt(cpos, (piece == WHITE) ? WHITE_KING : BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -297,17 +437,36 @@ void CheckerBoard::generateAdditionalCaptures(CheckerPosition pos, CheckerBoard& 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-bool CheckerBoard::isValidCapture(CheckerPosition pos, CheckerPosition newPos, CheckerPosition cpos, CheckerPiece piece) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isValidCapture(CheckerPosition pos, CheckerPosition newPos, CheckerPosition cpos, CheckerPiece piece) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Current checker piece 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece oldC = getCheckerAt(pos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Checker piece at the end position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece newC = getCheckerAt(newPos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Checker piece at the capture position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     CheckerPiece cC = getCheckerAt(cpos); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!cpos.isValid()) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (cC != CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (newC == CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (piece == WHITE && (newC == BLACK || newC == BLACK_KING)) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (piece == BLACK && (newC == WHITE || newC == WHITE_KING)) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ((piece == WHITE_KING || piece == BLACK_KING) && abs(cpos.y - pos.y) == 2 && abs(cpos.x - pos.x) == 2) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Capture position should be valid 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!cpos.isValid()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // There should be a checker to capture 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (cC != CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // There should be a checker at the current position 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (newC == CheckerPiece::NONE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Valid if we're capturing the enemy checker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == WHITE && (newC == BLACK || newC == BLACK_KING)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == BLACK && (newC == WHITE || newC == WHITE_KING)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Not sure about this part 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ((piece == WHITE_KING || piece == BLACK_KING) && abs(cpos.y - pos.y) == 2 && abs(cpos.x - pos.x) == 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |