diff options
Diffstat (limited to 'src/game_loop.c')
-rw-r--r-- | src/game_loop.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/game_loop.c b/src/game_loop.c new file mode 100644 index 0000000..9cbd5e2 --- /dev/null +++ b/src/game_loop.c @@ -0,0 +1,175 @@ +#define _GNU_SOURCE + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "othello.h" + +#define STREQ(a, b) (strcmp(a, b) == 0) + +static player_color other_player(player_color current_player) { + switch (current_player) { + case WHITE: + return BLACK; + case BLACK: + return WHITE; + default: + return EMPTY; + } +} + +static int player_number_from_color(player_color player) { + switch (player) { + case WHITE: + return 1; + case BLACK: + return 2; + default: + return -1; + } +} + +static void prompt_player(player_color current_player) { + printf("Player %d [h for help] > ", player_number_from_color(current_player)); +} + +static void print_help() { + puts("To enter a move, enter the two row and column seperated by spaces.\n" + "For example `0 0` will select the top left corner.\n\n" + "To print the board again, enter `p`\n\n" + "To drop into a guile repl enter `g`.\n\n" + "In the guile repl you can define an AI to use for the current player.\n\n" + "After you define an AI for that player, it will be used for the rest " + "of the game instead of prompting for input for that user."); +} + +static struct move get_move(player_color board[8][8], + player_color current_player) { + // Initialize move to an invalid move. + struct move move = {-1, -1}; + + do { + prompt_player(current_player); + char *input = NULL; + size_t input_length = 0; + + errno = 0; + while (getline(&input, &input_length, stdin) <= 0) { + if (errno != 0) { + perror("Error getting input"); + exit(EXIT_FAILURE); + } + } + + if (STREQ(input, "h\n")) { + print_help(); + } else if (STREQ(input, "p\n")) { + print_board(board); + } else if (STREQ(input, "g\n")) { + puts("NOT IMPLEMENTED YET!"); + } else { + sscanf(input, "%d %d", &move.row, &move.col); + } + + free(input); + } while (!is_valid_move(board, current_player, move)); + + return move; +} + +static void apply_move(player_color board[8][8], player_color current_player, + struct move move) { + if (!is_valid_move(board, current_player, move)) { + + // We should have checked for the validity of the move before we got here. + fprintf(stderr, "The move %d %d was not valid for player %d\n", move.row, + move.col, player_number_from_color(current_player) + 1); + exit(EXIT_FAILURE); + } + + // Flip in up direction + int up_end = move.row; + for (int i = move.row - 1; i > 0; i--) { + if (board[i][move.col] == EMPTY) { + break; + } else if (board[i][move.col] == current_player) { + /*up_end = i + 1;*/ + up_end = i; + break; + } + } + + // Flip in down direction + int down_end = move.row; + for (int i = move.row + 1; i < 8; i++) { + if (board[i][move.col] == EMPTY) { + break; + } else if (board[i][move.col] == current_player) { + /*down_end = i - 1;*/ + down_end = i; + break; + } + } + + // Flip in left direction + int left_end = move.col; + for (int i = move.col - 1; i > 0; i--) { + if (board[move.row][i] == EMPTY) { + break; + } else if (board[move.row][i] == current_player) { + /*left_end = i + 1;*/ + left_end = i; + break; + } + } + + // Flip in right direction + int right_end = move.col; + for (int i = move.col + 1; i < 8; i++) { + if (board[move.row][i] == EMPTY) { + break; + } else if (board[move.row][i] == current_player) { + /*right_end = i - 1;*/ + right_end = i; + break; + } + } + + for (int i = move.row; i > up_end; i--) { + board[i][move.col] = current_player; + } + for (int i = move.row; i < down_end; i++) { + board[i][move.col] = current_player; + } + for (int i = move.col; i > left_end; i--) { + board[move.row][i] = current_player; + } + for (int i = move.col; i < right_end; i++) { + board[move.row][i] = current_player; + } +} + +char game_loop(player_color board[8][8]) { + player_color current_player = WHITE; + + while (has_valid_moves(board, current_player)) { + struct move move = get_move(board, current_player); + apply_move(board, current_player, move); + /*board[move.row][move.col] = current_player;*/ + current_player = other_player(current_player); + } + + int white_score = 0, black_score = 0; + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + white_score += board[row][col] == WHITE; + black_score += board[row][col] == BLACK; + } + } + + return white_score > black_score ? WHITE + : black_score > white_score ? BLACK + : EMPTY; +} |