示例#1
0
/*
* Add an available move for the player to the list of moves, the move is specifically created for peons,
* as it may contain promotions.
* - Move is expected to be valid in terms of piece type constraints (e.g: a peon can only move to 3 possible squares).
* - Additional validation will be done in this function (moves that result in a check status for the current player are
*	 illegal).
* --> If the move is legal, it is added to the list of possibleMoves. Otherwise nothing happens.
* Input:
*		board ~ The chess game board.
*		possibleMoves ~ A list of possible moves by the current player, we aggregate it as we check
*						possible eat / position change moves.
*		isMovesForBlackPlayer ~ True if current player is black. False if white.
*		startPos ~ Where the piece is currently located.
*		targetX, targetY ~ Coordinates of where the piece will move to.
*		kingPos ~ Current position of the current player's king (following the execution of the move).
*/
void addPeonMove(char board[BOARD_SIZE][BOARD_SIZE], LinkedList* possibleMoves, bool isMovesForBlackPlayer,
					  Position* startPos, int targetX, int targetY, Position* kingPos)
{
	bool isMoveAdded = addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, targetX, targetY, kingPos);
	if (g_memError)
		return;
	if (!isMoveAdded)
		return;

	// If the pawn reaches the edge, the moves become promotion moves.
	if (isSquareOnOppositeEdge(isMovesForBlackPlayer, targetX))
	{
		char bishop = isMovesForBlackPlayer ? BLACK_B : WHITE_B;
		char rook = isMovesForBlackPlayer ? BLACK_R : BLACK_R;
		char knight = isMovesForBlackPlayer ? BLACK_N : WHITE_N;
		char queen = isMovesForBlackPlayer ? BLACK_Q : WHITE_Q;

		((Move*)(possibleMoves->tail->data))->promotion = queen; // Update the most recent move to a promotion move.

		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, targetX, targetY, kingPos);
		if (g_memError)
			return;
		((Move*)(possibleMoves->tail->data))->promotion = rook; // Update the most recent move to a promotion move.

		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, targetX, targetY, kingPos);
		if (g_memError)
			return;
		((Move*)(possibleMoves->tail->data))->promotion = bishop; // Update the most recent move to a promotion move.

		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, targetX, targetY, kingPos);
		if (g_memError)
			return;
		((Move*)(possibleMoves->tail->data))->promotion = knight; // Update the most recent move to a promotion move.
	}
}
示例#2
0
/*
* Checks if a piece can move / eat in the given direction.
* Input:
*		board ~ The game board.
*		possibleMoves ~ A list of possible moves by the current player, we aggregate it as we check
*						possible eat / position change moves.
*		isMovesForBlackPlayer ~ True if current player is black. False if white.
*		startPos ~ Where the piece is currently located.
*		deltaX, deltaY ~ The direction the piece advances in.
*		kingPos ~ Current position of the current player's king.
*/
void queryDirection(char board[BOARD_SIZE][BOARD_SIZE], LinkedList* possibleMoves,
					bool isMovesForBlackPlayer, Position* startPos, int deltaX, int deltaY, Position* kingPos)
{
	// First square on the diagonal / row / column
	Position currentSquare = { startPos->x + deltaX, startPos->y + deltaY };

	// We advance along the direction, advancing by deltaX, Y each iteration.
	// We will stop once we no longer hit an empty square.
	while (isSquareVacant(board, currentSquare.x, currentSquare.y))
	{
		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer,startPos, currentSquare.x, currentSquare.y, kingPos);
		if (g_memError)
			return;

		currentSquare.x += deltaX;
		currentSquare.y += deltaY;
	}

	// If the reason we stopped iterating was we encountered an enemy piece, we get an additional move: an eat move.
	if (isSquareOccupiedByEnemy(board, isMovesForBlackPlayer, currentSquare.x, currentSquare.y))
	{
		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, currentSquare.x, currentSquare.y, kingPos);
	}
}
示例#3
0
/*
* Add possible move for a single spot, if that spot is available for moving to or eating an enemy piece.
* Input:
*		board ~ The game board.
*		possibleMoves ~ A list of possible moves by the current player, we aggregate it as we check
*						possible eat / position change moves.
*		isMovesForBlackPlayer ~ True if current player is black. False if white.
*		startPos ~ Where the piece is currently located.
*		deltaX, deltaY ~ How many squares away to move the piece to.
*		kingPos ~ Current position of the current player's king.
*/
void querySinglePos(char board[BOARD_SIZE][BOARD_SIZE], LinkedList* possibleMoves,
					bool isMovesForBlackPlayer, Position* startPos, int deltaX, int deltaY, Position* kingPos)
{
	Position nextSquare = { startPos->x + deltaX, startPos->y + deltaY  };

	if (isSquareVacant(board, nextSquare.x, nextSquare.y) ||
		isSquareOccupiedByEnemy(board, isMovesForBlackPlayer, nextSquare.x, nextSquare.y))
	{
		Position* kingPosArg;

		// When the king moves, we should update the kingPos parameter accordingly
		if ((startPos->x == kingPos->x) && (startPos->y == kingPos->y))
			kingPosArg = &nextSquare; // The king's updated position is where the king moves to
		else
			kingPosArg = kingPos; // The current move is not made by a king, the kingPos stays the same

		addPossibleMove(board, possibleMoves, isMovesForBlackPlayer, startPos, nextSquare.x, nextSquare.y, kingPosArg);
	}
}
示例#4
0
void generateMoveList() {
	// First, we'll figure out the horizontal moves that are possible

	int x, y, i, j;
	int start, end;
	move *temp;

	for (y = 0; y < boardHeight; y++) {
		end = -1;
		
		while (end < boardWidth) {
			start = -1;		

			// First, find the first place where we can start a line
			for (x = end + 1; x < boardWidth; x++) {
				if ((gameBoard[xyToIndex(x, y)] & TOP_LINE) == 0) {
					start = x;
					break;
				}
			}

			if (start == -1)
				break;	// No free lines on this line

			// Now that we know where to start, we'll find where to end

			end = boardWidth;	// So if we don't find lines, we have a good endpoint

			for (x = start; x < boardWidth; x++) {
				if (gameBoard[xyToIndex(x, y)] & TOP_LINE) {
					// We found a place with a line! Stop just before it
					end = x;
					break;
				}
			}

			// Now that we've got that, we create the list of possible lines

			for (i = start; i < end; i++) {
				for (j = i + 1; j <= end; j++) {
					addPossibleMove(i, y, j, y);
				}
			}
		}
	}
	
	// We have to handle the last line specially, because we have to check for BOTTOM_LINE, not TOP

	end = -1;

	y = boardHeight - 1;

	while (end < boardWidth) {
		start = -1;

		// First, find the first place where we can start a line
		for (x = end + 1; x < boardWidth; x++) {
			if ((gameBoard[xyToIndex(x, y)] & BOTTOM_LINE) == 0) {
				start = x;
				break;
			}
		}
		
		if (start == -1)
			break;	// No free lines on this line

		// Now that we know where to start, we'll find where to end

		end = boardWidth;	// So if we don't find lines, we have a good endpoint

		for (x = start; x < boardWidth; x++) {
			if (gameBoard[xyToIndex(x, y)] & BOTTOM_LINE) {
				// We found a place with a line! Stop just before it
				end = x;
				break;
			}
		}

		// Now that we've got that, we create the list of possible lines

		for (i = start; i < end; i++) {
			for (j = i + 1; j <= end; j++) {
				addPossibleMove(i, boardHeight, j, boardHeight);
			}
		}
	}

	// Now, the same thing, only for virticle lines

	for (x = 0; x < boardWidth; x++) {
		end = -1;
		
		while (end < boardHeight) {
			start = -1;

			// First, find the first place where we can start a line
			for (y = end + 1; y < boardHeight; y++) {
				if ((gameBoard[xyToIndex(x, y)] & LEFT_LINE) == 0) {
					start = y;
					break;
				}
			}
			
			if (start == -1)
				break;	// No free lines on this line

			// Now that we know where to start, we'll find where to end

			end = boardHeight;	// So if we don't find lines, we have a good endpoint

			for (y = start; y < boardHeight; y++) {
				if (gameBoard[xyToIndex(x, y)] & LEFT_LINE) {
					// We found a place with a line! Stop just before it
					end = y;
					break;
				}
			}

			// Now that we've got that, we create the list of possible lines

			for (i = start; i < end; i++) {
				for (j = i + 1; j <= end; j++) {
					addPossibleMove(x, i, x, j);
				}
			}
		}
	}
	
	// We have to handle the last line specially, because we have to check for BOTTOM_LINE, not TOP

	end = -1;

	x = boardWidth - 1;

	while (end < boardHeight) {
		start = -1;

		// First, find the first place where we can start a line
		for (y = end + 1; y < boardHeight; y++) {
			if ((gameBoard[xyToIndex(x, y)] & RIGHT_LINE) == 0) {
				start = y;
				break;
			}
		}
		
		if (start == -1)
			break;	// No free lines on this line

		// Now that we know where to start, we'll find where to end

		end = boardHeight;	// So if we don't find lines, we have a good endpoint

		for (y = start; y < boardHeight; y++) {
			if (gameBoard[xyToIndex(x, y)] & RIGHT_LINE) {
				// We found a place with a line! Stop just before it
				end = y;
				break;
			}
		}

		// Now that we've got that, we create the list of possible lines

		for (i = start; i < end; i++) {
			for (j = i + 1; j <= end; j++) {
				addPossibleMove(boardWidth, i, boardWidth, j);
			}
		}
	}

	// That's it, the possible move list is full!
}