/* This file is a part of othello-ai-guile-c * * Copyright (C) 2021 Robby Zambito * * othello-ai-guile-c is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * othello-ai-guile-c is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define _GNU_SOURCE #include #include #include "othello.h" #include "othello_board.h" #include "othello_move.h" static enum player_color **board; enum player_color **get_board() { return board; } SCM scm_get_board() { return scm_board_from_c_board(board); } void initialize_board() { board = calloc(8, sizeof(enum player_color *)); for (int i = 0; i < 8; i++) { board[i] = calloc(8, sizeof(enum player_color)); } // Set all the positions to empty for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { board[i][j] = EMPTY; } } // Fill the starting positions board[3][3] = WHITE; board[3][4] = BLACK; board[4][3] = BLACK; board[4][4] = WHITE; } enum player_color get_winner(enum player_color **board, enum player_color current_player, int *white_score, int *black_score) { int ws = 0, bs = 0; for (int row = 0; row < 8; row++) { for (int col = 0; col < 8; col++) { // This takes advantage of the fact that the 1 is the same thing as a // true, and 0 is the same thing as a false. This will count the number of // white and black spaces. ws += (int)(board[row][col] == WHITE); bs += (int)(board[row][col] == BLACK); } } if (white_score != NULL) { *white_score = ws; } if (black_score != NULL) { *black_score = bs; } return ws > bs ? WHITE : bs > ws ? BLACK : EMPTY; } SCM scm_get_winner(SCM scm_board, SCM scm_current_player) { enum player_color **board = scm_board_to_c_board(scm_board); enum player_color current_player = scm_player_to_c_player(scm_current_player); enum player_color res = get_winner(board, current_player, NULL, NULL); free_board(board); return scm_player_from_c_player(res); } // Should be freed be the caller enum player_color **copy_board(enum player_color **other) { enum player_color **board = calloc(8, sizeof(enum player_color *)); for (int i = 0; i < 8; i++) { board[i] = calloc(8, sizeof(enum player_color)); for (int j = 0; j < 8; j++) { board[i][j] = other[i][j]; } } return board; } void free_board(enum player_color **board) { for (int i = 0; i < 8; i++) { free(board[i]); } free(board); } SCM scm_board_from_c_board(enum player_color **board) { // 2D list of empty rows SCM scm_board = scm_make_list(scm_from_int(8), SCM_EOL); for (int i = 0; i < 8; i++) { // cons up each row. for (int j = 7; j >= 0; j--) { if (board[i][j] == WHITE) { scm_list_set_x(scm_board, scm_from_int(i), scm_cons(scm_from_utf8_symbol("white"), scm_list_ref(scm_board, scm_from_int(i)))); } else if (board[i][j] == BLACK) { scm_list_set_x(scm_board, scm_from_int(i), scm_cons(scm_from_utf8_symbol("black"), scm_list_ref(scm_board, scm_from_int(i)))); } else { scm_list_set_x(scm_board, scm_from_int(i), scm_cons(scm_from_utf8_symbol("empty"), scm_list_ref(scm_board, scm_from_int(i)))); } } } return scm_board; } enum player_color **scm_board_to_c_board(SCM scm_board) { enum player_color **board = calloc(8, sizeof(enum player_color *)); for (int i = 0; i < 8; i++) { board[i] = calloc(8, sizeof(enum player_color)); for (int j = 0; j < 8; j++) { if (scm_is_true( scm_eq_p(scm_list_ref(scm_list_ref(scm_board, scm_from_int(i)), scm_from_int(j)), scm_from_utf8_symbol("white")))) { board[i][j] = WHITE; } else if (scm_is_true(scm_eq_p( scm_list_ref(scm_list_ref(scm_board, scm_from_int(i)), scm_from_int(j)), scm_from_utf8_symbol("black")))) { board[i][j] = BLACK; } else { board[i][j] = EMPTY; } } } return board; } void print_board(enum player_color **board) { puts(" 0 1 2 3 4 5 6 7"); for (int row = 0; row < 8; row++) { printf("%d ", row); for (int col = 0; col < 8; col++) { printf("%c ", board[row][col]); } printf("\n"); } } void scm_print_board(SCM scm_board) { enum player_color **board = SCM_UNBNDP(scm_board) ? get_board() : scm_board_to_c_board(scm_board); print_board(board); }