TP_13: fixlet to a function declaration in a comment
[TD_C.git] / TP_13 / exo2 / lib / coordinates.c
CommitLineData
5df3071e
JB
1/*
2 * =====================================================================================
3 *
4 * Filename: coordinates.c
5 *
6 * Description: Data definition and functions to manipulate elements in the grid
7 *
8 * Version: 1.0
9 * Created: 16/03/2017 19:05:02
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: Jerome Benoit (fraggle), jerome.benoit@piment-noir.org
14 * Organization: Piment Noir
15 *
16 * =====================================================================================
17 */
18
19#include "coordinates.h"
20
21void init_coordinates(coordinates_t* coordinates_array) {
811d4abe 22
5df3071e
JB
23 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
24 coordinates_array[i] = set_coordinates(0, 0, 0);
25 }
26}
27
a177f80c
JB
28void reinit_coordinates(coordinates_t* coordinates_array) {
29
30 init_coordinates(coordinates_array);
31}
32
5df3071e
JB
33coordinates_t set_coordinates(int y, int x, unsigned type) {
34 coordinates_t new_coordinates;
35
36 new_coordinates.y = y;
37 new_coordinates.x = x;
38 new_coordinates.type = type;
39 return new_coordinates;
40}
41
811d4abe 42/* FIXME: Does it worth doing a coordinates_t get_coordinates(int y, int x, unsigned type); helper function? */
168b411f 43/* Or a int get_coordinates_x(coordinates_t coordinates); helper function? */
811d4abe 44
04b0afb5 45/* the function do a lot of sanity checks before adding new board elements,
168b411f
JB
46 * hence the loop. moving the checks in the main loop is also possible.
47 * for now, just branch in the main loop given this function error value returned. */
04b0afb5 48unsigned add_coordinates(coordinates_t new_coordinates, coordinates_t* coordinates_array, unsigned round) {
811d4abe 49
5df3071e
JB
50 /* valid coordinates are in the [1-3] range */
51 if (new_coordinates.y < 1 || new_coordinates.y > 3 || new_coordinates.x < 1 || new_coordinates.x > 3) {
52 return 3; /* error value for invalid coordinates */
a177f80c
JB
53 } else if (round == MAX_COORDINATES - 1) {
54 /* round is off-by-one vs. MAX_COORDINATES */
811d4abe 55 coordinates_array[MAX_COORDINATES - 1] = new_coordinates;
04b0afb5 56 return 1; /* error value for full array */
5df3071e
JB
57 }
58 for (unsigned i = 0; i < MAX_COORDINATES; i++) {
59 /* check if already entered */
60 if (new_coordinates.y == (coordinates_array + i)->y && new_coordinates.x == (coordinates_array + i)->x) {
61 return 2; /* error value for duplicates */
62 } else if ((coordinates_array + i)->y == 0 && (coordinates_array + i)->x == 0) {
63 coordinates_array[i] = new_coordinates;
64 return 0; /* error value when everything if fine */
65 }
66 }
04b0afb5
JB
67 return 4; /* error value for unknown error case - should never happen - */
68}
69
811d4abe
JB
70static bool chk_line(coordinates_t* coordinates_array, int line_number, unsigned round) {
71 unsigned nb_o_align = 0;
72 unsigned nb_x_align = 0;
73
a177f80c 74 for (unsigned i = 0; i <= round; i++) {
811d4abe
JB
75 /* check if they are all the same */
76 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 0) {
77 nb_o_align++;
78 }
79 if ((coordinates_array + i)->y == line_number && (coordinates_array + i)->type == 1) {
80 nb_x_align++;
81 }
82 }
83 if (nb_o_align == 3 || nb_x_align == 3) {
84 return true;
85 }
86 return false;
87}
88
89static bool chk_column(coordinates_t* coordinates_array, int column_number, unsigned round) {
90 unsigned nb_o_align = 0;
91 unsigned nb_x_align = 0;
04b0afb5 92
a177f80c 93 for (unsigned i = 0; i <= round; i++) {
811d4abe
JB
94 /* check if they are all the same */
95 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 0) {
96 nb_o_align++;
97 }
98 if ((coordinates_array + i)->x == column_number && (coordinates_array + i)->type == 1) {
99 nb_x_align++;
100 }
101 }
102 /* one column must be full of the same type */
103 if (nb_o_align == 3 || nb_x_align == 3) {
104 return true;
105 }
106 return false;
107}
108
109static bool chk_diagonals(coordinates_t* coordinates_array, unsigned round) {
110 unsigned nb_o_diag_one = 0, nb_o_diag_two = 0;
111 unsigned nb_x_diag_one = 0, nb_x_diag_two = 0;
112
a177f80c 113 for (unsigned i = 0; i <= round; i++) {
811d4abe
JB
114 /* dumb count of each elements type in the two diagonals */
115 for (int y_x_diag = 1; y_x_diag < 4; y_x_diag++) {
116 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 0) {
117 nb_o_diag_one++;
118 }
119 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 0) {
120 nb_o_diag_two++;
121 }
122 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == y_x_diag && (coordinates_array + i)->type == 1) {
123 nb_x_diag_one++;
124 }
125 if ((coordinates_array + i)->y == y_x_diag && (coordinates_array + i)->x == (4 - y_x_diag) && (coordinates_array + i)->type == 1) {
126 nb_x_diag_two++;
127 }
128 }
129 if (nb_o_diag_one == 3 || nb_o_diag_two == 3 || nb_x_diag_one == 3 || nb_x_diag_two == 3) {
130 return true;
131 }
132 }
133 return false;
134}
135
136bool chk_win_conditions(coordinates_t* coordinates_array, unsigned round) {
137
a177f80c
JB
138 /* winning conditions begin at round = 4 */
139 if (round > 3) {
811d4abe
JB
140 if (chk_diagonals(coordinates_array, round)) {
141 return true;
142 }
143 for (unsigned i = 1; i < 4; i++) {
144 if (chk_line(coordinates_array, i, round) || \
145 chk_column(coordinates_array, i, round)) {
146 return true;
147 }
148 }
04b0afb5
JB
149 }
150 return false;
5df3071e 151}