void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){ Move* res = NULL; Move* res_head = res; Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } }; Pos curr; int found_ahead; for (int p = 0; p < 4; p++){ curr = pos[p]; while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){ add_move(piece, &curr, 1); curr = get_next_diag(piece, curr); // BUG - once dests_num == 1 and |dest-start| != 1 add_moves thinks its 1 capture and not a simple move.. } if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){ char tmp = board[curr.row][curr.col]; board[curr.row][curr.col] = EMPTY; Pos new_piece = get_next_diag(piece, curr); if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){ found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece); if (found_ahead == 0) add_move(piece, &new_piece, 1); } board[curr.row][curr.col] = tmp; } } }
int get_capture_moves(Pos start, Pos piece, char board[BOARD_SIZE][BOARD_SIZE], COLOR player, int count, Pos* dests){ Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } }; int found_now = 0, found_ahead; for (int p = 0; p < 4; p++) if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){ Pos new_piece = get_next_diag(piece, pos[p]); if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){ found_now++; char tmp = board[pos[p].col][pos[p].row]; board[pos[p].col][pos[p].row] = EMPTY; Pos* new_dests = malloc(sizeof(Pos) * (count + 1)); for (int i = 0; i < count; i++){ new_dests[i].row = dests[i].row; new_dests[i].col = dests[i].col; } new_dests[count].row = new_piece.row; new_dests[count].col = new_piece.col; found_ahead = get_capture_moves(start, new_piece, board, player, count + 1, new_dests); if (found_ahead == 0){ add_move(start, new_dests, count + 1); free(new_dests); } board[pos[p].row][pos[p].col] = tmp; } } return found_now; }
// finds all moves of a single king piece void get_king_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){ Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } }; Pos curr, new_piece; int found_ahead = -1; for (int p = 0; p < 4; p++){ curr = pos[p]; while (is_valid_pos(curr) && board[curr.col][curr.row] == EMPTY){ add_move(piece, &curr, 0); curr = get_next_diag(piece, curr); } if (is_valid_pos(curr) && is_opposite(player, board[curr.col][curr.row])){ char tmp = board[curr.col][curr.row]; board[curr.col][curr.row] = EMPTY; board[piece.col][piece.row] = EMPTY; new_piece = get_next_diag(piece, curr); if (is_valid_pos(new_piece) && board[new_piece.col][new_piece.row] == EMPTY){ found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece); if (found_ahead == 0) add_move(piece, &new_piece, 1); } board[curr.col][curr.row] = tmp; board[piece.col][piece.row] = curr_piece; } } }
// calculates the score of the board from a player's prospective int calc_score(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ int score = 0, opposites = 0; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++){ if (is_opposite(player, board[i][j])) opposites++; score += get_piece_score(board[i][j], player); } if (opposites == 0) return 100; return score; }
Move * get_all_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ moves_head = NULL; moves = NULL; Pos p; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) if (!is_opposite(player, board[i][j]) && board[i][j] != EMPTY){ p.row = j; p.col = i; get_moves_by_piece(board, player, p); } clear_illegal_moves(board, player); return moves_head; }
Move * get_all_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ clear_old_moves(moves_head); Pos p; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) if (!is_opposite(player, board[i][j]) && board[i][j] != EMPTY){ p.row = j; p.col = i; if (is_king(board[i][j])) get_king_moves(board, player, p); else get_man_moves(board, player, p); } return moves_head; // need to handle man becoming kings }
void get_pawn_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){ int direction = board[piece.col][piece.row] == BLACK_P ? -1 : 1; int pawn_row = board[piece.col][piece.row] == BLACK_P ? 6 : 1; Pos dest; dest.col = piece.col; dest.row = piece.row + direction; if (is_valid_pos(dest)){ if (board[dest.col][dest.row] == EMPTY){ add_move(piece, dest, 0); if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player)); } } if (piece.row == pawn_row){ dest.row = piece.row + (2 * direction); if (is_valid_pos(dest)){ if (board[dest.col][dest.row] == EMPTY && board[piece.col][piece.row + direction] == EMPTY) add_move(piece, dest, 0); } } dest.col = piece.col + 1; dest.row = piece.row + direction; if (is_valid_pos(dest)){ if (is_opposite(player, board[dest.col][dest.row])){ add_move(piece, dest, 0); if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player)); } } dest.col = piece.col - 1; if (is_valid_pos(dest)){ if (is_opposite(player, board[dest.col][dest.row])){ add_move(piece, dest, 0); if (is_EOB(dest, player)) for (int i = 1; i < 5; i++) add_move(piece, dest, get_piece_by_type(i, player)); } } }
Move * get_all_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ moves_head = NULL; moves = NULL; Pos p; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) if (!is_opposite(player, board[i][j]) && board[i][j] != EMPTY){ p.row = j; p.col = i; curr_piece = board[i][j]; if (is_king(curr_piece)) get_king_moves(board, player, p); else get_man_moves(board, player, p); } return moves_head; }
void get_man_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){ Move* res = NULL; Move* res_head = res; Pos pos[4] = { { piece.col - 1, piece.row - 1 }, { piece.col + 1, piece.row - 1 }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row + 1 } }; int direction = 1, found_ahead; if (player == BLACK) direction = -1; for (int p = 0; p < 4; p++){ if (is_valid_pos(pos[p]) && pos[p].row == piece.row + direction && board[pos[p].col][pos[p].row] == EMPTY) add_move(piece, &pos[p], 1); else if (is_valid_pos(pos[p]) && is_opposite(player, board[pos[p].col][pos[p].row])){ char tmp = board[pos[p].row][pos[p].col]; board[pos[p].row][pos[p].col] = EMPTY; Pos new_piece = get_next_diag(piece, pos[p]); if (is_valid_pos(new_piece) && board[new_piece.row][new_piece.col] == EMPTY){ found_ahead = get_capture_moves(piece, new_piece, board, player, 1, &new_piece); if (found_ahead == 0) add_move(piece, &new_piece, 1); } board[pos[p].row][pos[p].col] = tmp; } } }
void get_moves_by_piece(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos piece){ Pos* tmp_dests; switch (board[piece.col][piece.row]){ case WHITE_B: case BLACK_B: get_bishop_moves(board, player, piece); return; case WHITE_R: case BLACK_R: get_rook_moves(board, player, piece); return; case WHITE_Q: case BLACK_Q: get_bishop_moves(board, player, piece); get_rook_moves(board, player, piece); return; case BLACK_P: case WHITE_P: get_pawn_moves(board, player, piece); return; case WHITE_K: case BLACK_K: tmp_dests = (Pos[8]) { { piece.col - 1, piece.row - 1 }, { piece.col - 1, piece.row }, { piece.col - 1, piece.row + 1 }, { piece.col + 1, piece.row - 1 }, { piece.col + 1, piece.row }, { piece.col + 1, piece.row + 1 }, { piece.col, piece.row - 1 }, { piece.col, piece.row + 1 } }; break; case WHITE_N: case BLACK_N: tmp_dests = (Pos[8]) { { piece.col - 2, piece.row - 1 }, { piece.col - 2, piece.row + 1 }, { piece.col + 2, piece.row - 1 }, { piece.col + 2, piece.row + 1 }, { piece.col - 1, piece.row - 2 }, { piece.col + 1, piece.row - 2 }, { piece.col - 1, piece.row + 2 }, { piece.col + 1, piece.row + 2 }}; break; default: return; } for (int i = 0; i < 8; i++){ if (is_valid_pos(tmp_dests[i])){ if (board[tmp_dests[i].col][tmp_dests[i].row] == EMPTY || is_opposite(player, board[tmp_dests[i].col][tmp_dests[i].row])){ add_move(piece, tmp_dests[i], 0); } } } return; }
int is_valid_dest(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, Pos dest){ if (board[dest.col][dest.row] == EMPTY) return 1; if (is_opposite(player, board[dest.col][dest.row])) return 2; return 0; }
// Helper func - checks if a piece belongs to the player int is_valid_piece(char board[BOARD_SIZE][BOARD_SIZE], Move * move, COLOR color){ if (is_valid_pos(move->piece) && board[move->piece.col][move->piece.row] != EMPTY) return !is_opposite(color, board[move->piece.col][move->piece.row]); return 0; }