necessary pawns.
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
IHM: ihm.{c,h} (affichage de l'othellier, saisie d'un coup, entrée au clavier, ...)
coups: coups.{c.h} (coups jouables)
regle: regle.{c,h} (implantation des règles du jeu)
- constantes: constantes.h (les constantes)
+ constantes: constantes.{c,h} (les constantes)
->Exploration dans une direction (i, j):
Si hors_othellier ou case vide
#include "constants.h"
-//const unsigned int board_size = 8;
+//const int board_size = 8;
const unsigned int empty = 0;
const unsigned int black = 1;
const unsigned int player_one = 1; /* first player is black */
const unsigned int player_two = 2;
-const unsigned int hint_allowed = 3;
+const unsigned int hint_allowed = 3;
const unsigned int hint_forbidden = 4;
-const unsigned int north = 5;
-const unsigned int north_east = 6;
-const unsigned int east = 7;
-const unsigned int south_east = 8;
-const unsigned int south = 9;
-const unsigned int south_west = 10;
-const unsigned int west = 11;
-const unsigned int north_west = 12;
+const unsigned int north = 10;
+const unsigned int north_east = 11;
+const unsigned int east = 12;
+const unsigned int south_east = 13;
+const unsigned int south = 14;
+const unsigned int south_west = 15;
+const unsigned int west = 16;
+const unsigned int north_west = 17;
#ifndef CONSTANTS_H
#define CONSTANTS_H
-#define board_size 8
-//extern const unsigned int board_size; /* 8 */
+#define board_size 8 /* 8 */
+//extern const int board_size; /* 8 */
extern const unsigned int empty; /* 0 */
extern const unsigned int black; /* 1 */
#include <string.h>
+#include "othello.h"
+#include "constants.h"
#include "debug.h"
-void dbg_mvprintw(int base_y, int base_x, const char* fmt, va_list varglist) {
+void display_array(int base_y, int base_x, unsigned int pawn_array[board_size][board_size]) {
- mvprintw(base_y, base_x - snprintf(NULL, 0, fmt, varglist)/2, fmt, varglist);
+ for (int i = 1; i <= board_size; i++) {
+ mvprintw(base_y + i, base_x, "%d", i);
+ for (int j = 1; j <= board_size; j++) {
+ mvprintw(base_y, base_x + j, "%d", j);
+ mvprintw(base_y + i, base_x + j, "%d", get_box_value(i, j, pawn_array));
+ }
+ }
}
#include <ncurses.h>
-void dbg_mvprintw(int base_y, int base_x, const char* fmt, va_list varglist);
+void display_array(int base_y, int base_x, unsigned int pawn_array[board_size][board_size]);
#include <stdlib.h>
#include <stdbool.h>
+#include <string.h>
#include "othello.h"
+#include "debug.h"
unsigned int current_player(unsigned int round_count) {
}
}
-/* for consitency with ncurses, the board coordinates are in the following order:
+unsigned int current_opponent(unsigned int current_player) {
+
+ if (current_player == player_one) {
+ return player_two;
+ } else {
+ return player_one;
+ }
+}
+
+/* for consistency with ncurses, the board coordinates are in the following order:
* O--x-->
* |
* y
}
}
-/* helper function to set a value != empty at the (y, x) coordinates in the pawns array */
-int** set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]) {
+static bool is_valid_coordinates(int y, int x) {
+
+ if ((y > 0 && y < board_size + 1) && \
+ (x > 0 && x < board_size + 1)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* helper function to set a correct value at the (y, x) coordinates in the pawns array */
+void set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]) {
- if (is_box_type(y, x, pawn_array, empty)) {
+ if (type > 0 && type < 3 && \
+ is_valid_coordinates(y, x)) {
pawn_array[y-1][x-1] = type;
- return (int**)pawn_array;
- } else {
- return NULL;
}
}
-static int** zero_pawns(unsigned int pawn_array[board_size][board_size]) {
+/* reverse the pawn at (y, x) coordinates if it exists */
+static void reverse_pawn(int y, int x, unsigned int pawn_array[board_size][board_size]) {
+
+ if (is_box_type(y, x, pawn_array, black)) {
+ set_pawn(y, x, white, pawn_array);
+ } else if (is_box_type(y, x, pawn_array, white)) {
+ set_pawn(y, x, black, pawn_array);
+ }
+}
+
+void zero_pawns(unsigned int pawn_array[board_size][board_size]) {
- for (unsigned int i = 1; i <= board_size; i++) {
- for (unsigned int j = 1; j <= board_size; j++) {
- pawn_array = set_pawn(i, j, empty, pawn_array);
+ for (int i = 1; i <= board_size; i++) {
+ for (int j = 1; j <= board_size; j++) {
+ set_pawn(i, j, empty, pawn_array);
}
}
- return (int**)pawn_array;
}
/* set the pawns in the start position */
-int** init_pawns(unsigned int pawn_array[board_size][board_size]) {
-
- pawn_array = zero_pawns(pawn_array);
- pawn_array = set_pawn(5, 4, black, pawn_array);
- pawn_array = set_pawn(4, 5, black, pawn_array);
- pawn_array = set_pawn(4, 4, white, pawn_array);
- pawn_array = set_pawn(5, 5, white, pawn_array);
- return (int**)pawn_array;
+void init_pawns(unsigned int pawn_array[board_size][board_size]) {
+
+ /* the 2D array zeroing is not necessary if it is properly initialized to zero */
+ zero_pawns(pawn_array);
+ set_pawn(5, 4, black, pawn_array);
+ set_pawn(4, 5, black, pawn_array);
+ set_pawn(4, 4, white, pawn_array);
+ set_pawn(5, 5, white, pawn_array);
}
-unsigned int count_pawn_type(unsigned int pawn_array[board_size][board_size], unsigned int type) {
+unsigned int count_pawns_type(unsigned int pawn_array[board_size][board_size], unsigned int type) {
unsigned int count = 0;
if (type > 2) {
- return -1;
+ return 0;
}
- for (unsigned int i = 1; i <= board_size; i++) {
- for (unsigned int j = 1; j <= board_size; j++) {
+ for (int i = 1; i <= board_size; i++) {
+ for (int j = 1; j <= board_size; j++) {
if (is_box_type(i, j, pawn_array, type)) {
count++;
}
return count;
}
-bool is_valid_input(int y, int x, unsigned int pawn_array[board_size][board_size]) {
-
- /* FIXME: separate the tests to permit to print explicit error messages */
- if ((y > 0 && y < board_size + 1) && \
- (x > 0 && x < board_size + 1) && \
- is_box_type(y, x, pawn_array, empty)) {
- return true;
- } else {
- return false;
+static void direction_to_coordinates(unsigned int direction, int* start_y, int* start_x) {
+
+ if (direction == north) {
+ *start_y = *start_y - 1;
+ } else if (direction == north_east) {
+ *start_y = *start_y - 1;
+ *start_x = *start_x + 1;
+ } else if (direction == east) {
+ *start_x = *start_x + 1;
+ } else if (direction == south_east) {
+ *start_y = *start_y + 1;
+ *start_x = *start_x + 1;
+ } else if (direction == south) {
+ *start_y = *start_y + 1;
+ } else if (direction == south_west) {
+ *start_y = *start_y + 1;
+ *start_x = *start_x - 1;
+ } else if (direction == west) {
+ *start_x = *start_x - 1;
+ } else if (direction == north_west) {
+ *start_y = *start_y - 1;
+ *start_x = *start_x - 1;
}
}
bool is_board_full(unsigned int pawn_array[board_size][board_size]) {
/* an alternate method is to test the round count vs. 60 */
- for (unsigned int i = 1; i <= board_size; i++) {
- for (unsigned int j = 1; j <= board_size; j++) {
+ for (int i = 1; i <= board_size; i++) {
+ for (int j = 1; j <= board_size; j++) {
if (is_box_type(i, j, pawn_array , empty)) {
return false;
}
}
}
-void direction_to_coordinates(unsigned int direction, int* start_y, int* start_x) {
+static unsigned int reverse_one_direction(int y, int x, int direction, unsigned int current_player, unsigned int pawn_array[board_size][board_size]) {
+ unsigned int nb_pawns_reserved = 0;
+ int moving_y = y, moving_x = x;
- if (direction == north) {
- *start_y = *start_y - 1;
- } else if (direction == north_east) {
- *start_y = *start_y - 1;
- *start_x = *start_x + 1;
- } else if (direction == east) {
- *start_x = *start_x + 1;
- } else if (direction == south_east) {
- *start_y = *start_y + 1;
- *start_x = *start_x + 1;
- } else if (direction == south) {
- *start_y = *start_y + 1;
- } else if (direction == south_west) {
- *start_y = *start_y + 1;
- *start_x = *start_x - 1;
- } else if (direction == west) {
- *start_x = *start_x - 1;
- } else if (direction == north_west) {
- *start_y = *start_y - 1;
- *start_x = *start_x - 1;
+ /* count for pawn to reverse in the chosen direction */
+ direction_to_coordinates(direction, &moving_y, &moving_x);
+ while (true) {
+ if (!is_valid_coordinates(moving_y, moving_x) || is_box_type(moving_y, moving_x, pawn_array, empty)) {
+ return 0;
+ }
+ if (is_box_type(moving_y, moving_x, pawn_array, current_player)) {
+ break;
+ }
+ nb_pawns_reserved++;
+ direction_to_coordinates(direction, &moving_y, &moving_x);
+ }
+
+ /* now reverse the needed panws */
+ if (nb_pawns_reserved > 0) {
+ moving_y = y, moving_x = x;
+ direction_to_coordinates(direction, &moving_y, &moving_x);
+ while (!is_box_type(moving_y, moving_x, pawn_array, current_player)) {
+ reverse_pawn(moving_y, moving_x, pawn_array);
+ direction_to_coordinates(direction, &moving_y, &moving_x);
+ }
}
+ return nb_pawns_reserved;
}
-bool explore(int y, int x, int direction) {
+/* play the shot if legal and flip or reverse the necessary pawns */
+unsigned int valid_shot(int y, int x, unsigned int current_player, unsigned int pawn_array[board_size][board_size]) {
+ unsigned int nb_pawns_reserved = 0;
+
+ if (!is_valid_coordinates(y, x) || !is_box_type(y, x, pawn_array, empty)) {
+ return 0;
+ }
+
+ for (unsigned int direction = north; direction <= north_west; direction++) {
+ nb_pawns_reserved += reverse_one_direction(y, x, direction, current_player, pawn_array);
+ }
+
+ if (nb_pawns_reserved == 0) {
+ return 0;
+ }
+ set_pawn(y, x, current_player, pawn_array);
+ return nb_pawns_reserved;
}
#ifndef OTHELLO_H
#define OTHELLO_H
+#include <stdbool.h>
+
#include "constants.h"
#include "list.h"
-/* TODO: must be used to replace the explicit pawns 2D array */
-struct pawns_s {
- unsigned int pawns[board_size][board_size];
-};
-
-/* linked list of played shots */
-struct shots_history_list_s {
- struct list_head list;
- unsigned int*** pawn_array_member; /* pointer to a cell of the pawns 2D array */
- /* struct* pawns_s pawn */
-};
-
/* linked list of can play shots */
-struct shots_exploration_s {
+struct shots_list_s {
struct list_head list;
int y;
int x;
- unsigned int type;
+ unsigned int type; /* can be white or black or hint allowed or hint_fordidden */
};
unsigned int current_player(unsigned int round_count);
unsigned int eval_winner(unsigned int nb_white, unsigned int nb_black);
-int** init_pawns(unsigned int pawn_array[board_size][board_size]);
+void zero_pawns(unsigned int pawn_array[board_size][board_size]);
+void init_pawns(unsigned int pawn_array[board_size][board_size]);
unsigned int get_box_value(int y, int x, unsigned int pawn_array[board_size][board_size]);
-int** set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]);
+void set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]);
-bool is_valid_input(int y, int x, unsigned int pawn_array[board_size][board_size]);
bool is_box_type(int y, int x, unsigned int pawn_array[board_size][board_size], unsigned int type);
bool is_board_full(unsigned int pawn_array[board_size][board_size]);
-unsigned int count_pawn_type(unsigned int pawn_array[board_size][board_size], unsigned int type);
+unsigned int count_pawns_type(unsigned int pawn_array[board_size][board_size], unsigned int type);
+
+unsigned int valid_shot(int y, int x, unsigned int current_player, unsigned int pawn_array[board_size][board_size]);
#endif /* OTHELLO_H */
void print_pawns(int base_y, int base_x, unsigned int pawn_array[board_size][board_size]) {
- for (unsigned int i = 1; i <= board_size; i++) {
- for (unsigned int j = 1; j <= board_size; j++) {
+ for (int i = 1; i <= board_size; i++) {
+ for (int j = 1; j <= board_size; j++) {
if (!is_box_type(i, j, pawn_array, empty)) {
print_o(base_y + remap_y(i), base_x + remap_x(j), get_box_value(i, j, pawn_array));
}
int prompt_values(WINDOW* windows, int base_y, int base_x, const char* msg, int* y, char* x) {
mvwprintw(windows, base_y, base_x, "%s\n", msg);
- int retVal = mvwscanw(windows, base_y + 1, base_x + strlen(msg)/2, "%d%c", y, x);
- return (retVal == 1) ? 0 : 1;
+ int retval = mvwscanw(windows, base_y + 1, base_x + strlen(msg)/2, "%d%c", y, x);
+ return (retval == 1) ? 0 : 1;
}
char* player_msg = "Joueur %d (%s) joue !";
char* winner_msg = "Joueur %d (%s) gagne !";
char* draw_msg = "Egalite !";
-
- unsigned int pawns[board_size][board_size] = {{}};
- pawns[board_size][board_size] = init_pawns(pawns);
+
+ /* linked list of the history shots */
+ //struct shots_history_list_s shots_history;
+ //INIT_LIST_HEAD(&shots_history.list);
+ /* linked list of black playable shots */
+ struct shots_list_s black_playable_shots;
+ INIT_LIST_HEAD(&black_playable_shots.list);
+ /* linked list of white playable shots */
+ struct shots_list_s white_playable_shots;
+ INIT_LIST_HEAD(&white_playable_shots.list);
+
+ unsigned int pawns[board_size][board_size] = {
+ {0, 0},
+ {0, 0}
+ };
+ init_pawns(pawns);
initscr();
if (has_colors() == false) {
getmaxyx(stdscr, row, col);
if (row < min_y || col < min_x) {
endwin();
- printf("Votre terminal est trop petit pour afficher le jeu.\n");
+ printf("Votre terminal est trop petit pour afficher ce jeu.\n");
printf("Merci d'agrandir la fenetre de votre terminal.\n");
exit(EXIT_FAILURE);
}
- /* FIXME: fail if the screen size is too small */
echo();
curs_set(0);
mvprintw(center_y - 26/2 - 2, center_x - snprintf(NULL, 0, player_msg, player, "blanc")/2, player_msg, player, "blanc");
}
- nb_white = count_pawn_type(pawns, white);
- nb_black = count_pawn_type(pawns, black);
+ nb_white = count_pawns_type(pawns, white);
+ nb_black = count_pawns_type(pawns, black);
mvprintw(center_y, center_x - 42/2 - snprintf(NULL, 0, score_msg, "noirs", nb_black) - 2, score_msg, "noirs", nb_black);
mvprintw(center_y, center_x + 42/2 + 2, score_msg, "blancs", nb_white);
+
+ display_array(1, 1, pawns);
int y;
- char x;
+ char x_char;
bool input_ok = false;
do {
y = 0;
- x = (char)"";
+ x_char = "";
char* prompt_msg = "Prochain pion ? (ligne colonne - chiffre lettre):";
- int prmt_rt = prompt_values(stdscr, center_y + 26/2 + 1, center_x - strlen(prompt_msg)/2, prompt_msg, &y, &x);
- if (is_valid_input(y, map_col_letter_to_index(x), pawns) && prmt_rt == 1) {
+ int prmt_rt = prompt_values(stdscr, center_y + 26/2 + 1, center_x - strlen(prompt_msg)/2, prompt_msg, &y, &x_char);
+ int x = map_col_letter_to_index(x_char);
+ if (valid_shot(y, x, player, pawns) > 0 && prmt_rt == 1) {
input_ok = true;
}
} while (!input_ok);
- pawns[board_size][board_size] = set_pawn(y, map_col_letter_to_index(x), player, pawns);
- struct shots_history_list_s shots_history;
- INIT_LIST_HEAD(&shots_history.list);
- struct shots_history_list_s shots_elmt;
- shots_elmt.pawn_array_member = &pawns[y-1][x-1];
- list_add(&shots_elmt.list, &shots_history.list);
round++; /* increment the round count */
- refresh();
-
/* here are all the end of the game conditions */
- //if (is_board_full(pawns) || (round == 60)) {
if (is_board_full(pawns)) {
- int winner = eval_winner(nb_white, nb_black);
+ unsigned int winner = eval_winner(nb_white, nb_black);
if (winner != 0) {
if (winner == player_one) {
mvprintw(center_y - 26/2 - 2, center_x - snprintf(NULL, 0, winner_msg, winner, "noir"), winner_msg, winner, "noir");
/* print and implement restart possibility */
exit_condition = true;
}
+
+ refresh();
} while (!exit_condition);