2009-07-31
honor style(9)
| t3champion.c | file | annotate | diff | revisions |
1.1 --- a/t3champion.c Wed Jul 15 18:09:29 2009 +0200 1.2 +++ b/t3champion.c Fri Jul 31 02:08:51 2009 +0200 1.3 @@ -50,25 +50,25 @@ 1.4 1.5 1.6 #ifdef QUIET 1.7 -# define printf(...) ((void)0) 1.8 -# define fprintf(...) ((void)0) 1.9 +# define printf(...) ((void)0) 1.10 +# define fprintf(...) ((void)0) 1.11 #endif 1.12 1.13 /* # of lines / columns */ 1.14 #ifndef SIZE 1.15 -# define SIZE 3 1.16 +# define SIZE 3 1.17 #endif 1.18 1.19 #if (SIZE < 3 || SIZE % 2 == 0) 1.20 -# error "bad SIZE" 1.21 +# error "bad SIZE" 1.22 #endif 1.23 1.24 /* 1.25 * a position (index) in a board. 1.26 */ 1.27 typedef int position_t; 1.28 -#define INVALID_POSITION (-1) 1.29 -#define POSITION_MAX (SIZE * SIZE) 1.30 +#define INVALID_POSITION (-1) 1.31 +#define POSITION_MAX (SIZE * SIZE) 1.32 1.33 1.34 /* 1.35 @@ -76,28 +76,28 @@ 1.36 * [...] 1.37 */ 1.38 enum status_e { 1.39 - EMPTY = 0, 1.40 - X, /* always begin */ 1.41 - O, 1.42 - DRAW, 1.43 + EMPTY = 0, 1.44 + X, /* always begin */ 1.45 + O, 1.46 + DRAW, 1.47 }; 1.48 /* 1.49 * [...] 1.50 - * 1. to represent the state of a position, EMPTY or 0 when free, X or 1.51 - * O when already played: 1.52 - */ typedef enum status_e state_t; 1.53 + * 1. to represent the state of a position, EMPTY or 0 when free, X or 1.54 + * O when already played: 1.55 + */ typedef enum status_e state_t; 1.56 /* 1.57 - * 2. to represent a player, X or O: 1.58 - */ typedef enum status_e player_t; 1.59 + * 2. to represent a player, X or O: 1.60 + */ typedef enum status_e player_t; 1.61 /* 1.62 - * 3. to represent the status of the game, EMPTY or 0 when running, X or 1.63 - * O when a played won the game, DRAW when the game ended without 1.64 - * winner: 1.65 - */ typedef enum status_e gstatus_t; 1.66 + * 3. to represent the status of the game, EMPTY or 0 when running, X or 1.67 + * O when a played won the game, DRAW when the game ended without 1.68 + * winner: 1.69 + */ typedef enum status_e gstatus_t; 1.70 1.71 1.72 /* Yes, we use some global variables (and maybe some goto), be warned. */ 1.73 -static bool Grandom = false; /* see strategy_t */ 1.74 +static bool Grandom = false; /* see strategy_t */ 1.75 1.76 1.77 /***[STRATEGY]****************************************************************/ 1.78 @@ -122,93 +122,94 @@ 1.79 * been promoted by another strategy that the called one, because of the 1.80 * recursive selection of the strategy applied. 1.81 * 1.82 - */ typedef position_t strategy_t(player_t me, state_t *board); 1.83 + */ typedef position_t strategy_t(player_t me, state_t *board); 1.84 1.85 /* 1.86 * A player can play perfect tic-tac-toe if they choose the move with the 1.87 * highest priority in the following table: 1.88 * 1.89 - * 0. Win: If you have two in a row, play the third to get three in a row. 1.90 - */ strategy_t iWin; 1.91 + * 0. Win: If you have two in a row, play the third to get three in a row. 1.92 + */ strategy_t iWin; 1.93 /* 1.94 - * 1. Block: If the opponent has two in a row, play the third to block them. 1.95 - */ strategy_t iBlock; 1.96 + * 1. Block: If the opponent has two in a row, play the third to block them. 1.97 + */ strategy_t iBlock; 1.98 /* 1.99 - * 2. Fork: Create an opportunity where you can win in two ways. 1.100 - */ strategy_t iFork; 1.101 + * 2. Fork: Create an opportunity where you can win in two ways. 1.102 + */ strategy_t iFork; 1.103 /* 1.104 - * 3. Block Opponent's Fork: 1.105 - * Option 1: Create two in a row to force the opponent into defending, as 1.106 - * long as it doesn't result in them creating a fork or winning. For 1.107 - * example, if "X" has a corner, "O" has the center, and "X" has the 1.108 - * opposite corner as well, "O" must not play a corner in order to 1.109 - * win. (Playing a corner in this scenario creates a fork for "X" to 1.110 - * win.) 1.111 - */ strategy_t iBlockOpponent1; 1.112 -/* Option 2: If there is a configuration where the opponent can fork, 1.113 - * block that fork. 1.114 - */ strategy_t iBlockOpponent2; 1.115 + * 3. Block Opponent's Fork: 1.116 + * Option 1: Create two in a row to force the opponent into 1.117 + * defending, as long as it doesn't result in them creating a fork 1.118 + * or winning. For example, if "X" has a corner, "O" has the 1.119 + * center, and "X" has the opposite corner as well, "O" must not 1.120 + * play a corner in order to win. (Playing a corner in this 1.121 + * scenario creates a fork for "X" to win.) 1.122 + */ strategy_t iBlockOpponent1; 1.123 + 1.124 +/* Option 2: If there is a configuration where the opponent can 1.125 + * fork, block that fork. 1.126 + */ strategy_t iBlockOpponent2; 1.127 /* 1.128 - * 4. Center: Play the center. 1.129 - */ strategy_t iPlayCenter; 1.130 + * 4. Center: Play the center. 1.131 + */ strategy_t iPlayCenter; 1.132 /* 1.133 - * 5. Opposite Corner: If the opponent is in the corner, play the opposite 1.134 - * corner. 1.135 - */ strategy_t iPlayOppositeCorner; 1.136 + * 5. Opposite Corner: If the opponent is in the corner, play the opposite 1.137 + * corner. 1.138 + */ strategy_t iPlayOppositeCorner; 1.139 /* 1.140 - * 6. Empty Corner: Play an empty corner. 1.141 - */ strategy_t iPlayCorner; 1.142 + * 6. Empty Corner: Play an empty corner. 1.143 + */ strategy_t iPlayCorner; 1.144 /* 1.145 - * 7. Empty Side: Play an empty side. 1.146 - */ strategy_t iPlayEmpty; 1.147 + * 7. Empty Side: Play an empty side. 1.148 + */ strategy_t iPlayEmpty; 1.149 1.150 1.151 /* all the used strategy, in order: */ 1.152 strategy_t *strategies[] = { 1.153 - iWin, 1.154 - iBlock, 1.155 - iFork, 1.156 - iBlockOpponent1, 1.157 - iPlayCenter, 1.158 - iPlayOppositeCorner, 1.159 - iPlayCorner, 1.160 - iPlayEmpty, 1.161 - NULL 1.162 + iWin, 1.163 + iBlock, 1.164 + iFork, 1.165 + iBlockOpponent1, 1.166 + iPlayCenter, 1.167 + iPlayOppositeCorner, 1.168 + iPlayCorner, 1.169 + iPlayEmpty, 1.170 + NULL 1.171 }; 1.172 const char *strategies_names[] = { 1.173 - "iWin", 1.174 - "iBlock", 1.175 - "iFork", 1.176 - "iBlockOpponent1", 1.177 - "iPlayCenter", 1.178 - "iPlayOppositeCorner", 1.179 - "iPlayCorner", 1.180 - "iPlayEmpty", 1.181 - NULL 1.182 + "iWin", 1.183 + "iBlock", 1.184 + "iFork", 1.185 + "iBlockOpponent1", 1.186 + "iPlayCenter", 1.187 + "iPlayOppositeCorner", 1.188 + "iPlayCorner", 1.189 + "iPlayEmpty", 1.190 + NULL 1.191 }; 1.192 1.193 /***[PROTOTYPES]**************************************************************/ 1.194 1.195 /* helpers to check parameters */ 1.196 -#define check_ptr(p) assert(("valid pointer", (p) != NULL)) 1.197 -#define check_state_t(s) assert(("valid state_t", (s) >= EMPTY && (s) <= O)) 1.198 -#define check_player_t(s) assert(("valid player_t", (s) == X || (s) == O)) 1.199 +#define check_ptr(p) assert(("valid pointer", (p) != NULL)) 1.200 +#define check_state_t(s) assert(("valid state_t", (s) >= EMPTY && (s) <= O)) 1.201 +#define check_player_t(s) assert(("valid player_t", (s) == X || (s) == O)) 1.202 1.203 /* # of element in a fixed size array */ 1.204 -#define countof(x) (sizeof(x) / sizeof(*(x))) 1.205 +#define countof(x) (sizeof(x) / sizeof(*(x))) 1.206 1.207 /* 1.208 * translate (x,y) Cartesian coordinate into a position_t 1.209 - * position_t at(unsigned int x, unsigned int y); 1.210 + * position_t at(unsigned int x, unsigned int y); 1.211 */ 1.212 -#define at(x, y) ((y) * SIZE + (x)) 1.213 +#define at(x, y) ((y) * SIZE + (x)) 1.214 1.215 /* 1.216 * Pretty Position 1.217 * translate position_t into Cartesian coordinate, only used for display. 1.218 - * unsigned int, unsigned int PP(position_t p); 1.219 + * unsigned int, unsigned int PP(position_t p); 1.220 */ 1.221 -#define PP(p) (((p) % SIZE) + 1), (((p) / SIZE) + 1) 1.222 +#define PP(p) (((p) % SIZE) + 1), (((p) / SIZE) + 1) 1.223 1.224 1.225 /* 1.226 @@ -216,23 +217,23 @@ 1.227 * iPlayCorner. 1.228 */ 1.229 static const position_t corners[4] = { 1.230 - at(SIZE - 1, 0), at(SIZE - 1, SIZE - 1), 1.231 - at(0, 0), at(0, SIZE - 1), 1.232 + at(SIZE - 1, 0), at(SIZE - 1, SIZE - 1), 1.233 + at(0, 0), at(0, SIZE - 1), 1.234 }; 1.235 1.236 /* state_t and player_t to char table */ 1.237 static const char display[] = { 1.238 - [EMPTY] = '_', 1.239 - [X] = 'X', 1.240 - [O] = 'O', 1.241 - [DRAW] = '!', 1.242 + [EMPTY] = '_', 1.243 + [X] = 'X', 1.244 + [O] = 'O', 1.245 + [DRAW] = '!', 1.246 }; 1.247 1.248 1.249 /* 1.250 * return the opponent of given someone. 1.251 */ 1.252 -inline player_t opponent(player_t someone); 1.253 +inline player_t opponent(player_t someone); 1.254 1.255 1.256 /* 1.257 @@ -245,18 +246,18 @@ 1.258 * 1.259 * the positions are stored in matches, and the number of positions in nmatch. 1.260 */ 1.261 -void wins(player_t player, const state_t *board, 1.262 - unsigned int *nmatch, position_t *matches); 1.263 +void wins(player_t player, const state_t *board, 1.264 + unsigned int *nmatch, position_t *matches); 1.265 /* 1.266 * used by wins() to remove duplicates positions in matches. 1.267 * see comments in the wins() function. 1.268 */ 1.269 -void uniq(unsigned int *nmatch, position_t *matches); 1.270 +void uniq(unsigned int *nmatch, position_t *matches); 1.271 /* 1.272 * used by uniq() to call qsort(3). 1.273 * see comments in the uniq() function. 1.274 */ 1.275 -int position_cmp(const void *aptr, const void *bptr); 1.276 +int position_cmp(const void *aptr, const void *bptr); 1.277 1.278 1.279 /* 1.280 @@ -264,8 +265,8 @@ 1.281 * 1.282 * the positions are stored in matches, and the number of positions in nmatch. 1.283 */ 1.284 -void forks(player_t player, const state_t *board, 1.285 - unsigned int *nmatch, position_t *matches); 1.286 +void forks(player_t player, const state_t *board, 1.287 + unsigned int *nmatch, position_t *matches); 1.288 1.289 1.290 /* 1.291 @@ -274,8 +275,8 @@ 1.292 * It return the chosen position_t or INVALID_POSITION if the chosen is not in 1.293 * a EMPTY state. the number of match must be > 0. 1.294 */ 1.295 -position_t apply(player_t me, state_t *board, 1.296 - unsigned int nmatch, const position_t *matches); 1.297 +position_t apply(player_t me, state_t *board, 1.298 + unsigned int nmatch, const position_t *matches); 1.299 1.300 1.301 /* 1.302 @@ -286,49 +287,49 @@ 1.303 /* 1.304 * print the given board in out. 1.305 */ 1.306 -void dump_board(FILE *out, const state_t *board); 1.307 +void dump_board(FILE *out, const state_t *board); 1.308 1.309 1.310 /* 1.311 * check board constistancy, and abort() if an error is detected. 1.312 */ 1.313 -void check_board(const state_t *board); 1.314 +void check_board(const state_t *board); 1.315 1.316 1.317 /* 1.318 * returned values: 1.319 - * EMPTY: the game is running 1.320 - * X: the X player has won 1.321 - * O: the O player has won 1.322 - * DRAW: draw, no one wins 1.323 + * EMPTY: the game is running 1.324 + * X: the X player has won 1.325 + * O: the O player has won 1.326 + * DRAW: draw, no one wins 1.327 */ 1.328 -gstatus_t outcome(const state_t *board); 1.329 +gstatus_t outcome(const state_t *board); 1.330 1.331 1.332 /* 1.333 * choose between iBlockOpponent1 and iBlockOpponent2. 1.334 * if i is not 1 or 2, it has no effect. 1.335 */ 1.336 -void setstrategy3(int i); 1.337 +void setstrategy3(int i); 1.338 1.339 1.340 /* 1.341 * display usage and exit. 1.342 */ 1.343 -void usage(const char *pname, bool full); 1.344 +void usage(const char *pname, bool full); 1.345 1.346 /* 1.347 * ask the user and play. 1.348 */ 1.349 -position_t user_play(player_t player, state_t *board); 1.350 +position_t user_play(player_t player, state_t *board); 1.351 1.352 /* 1.353 * we provide some helper for gstatus_t 1.354 - * bool running(gstatus_t s); 1.355 - * bool draw(gstatus_t s); 1.356 + * bool running(gstatus_t s); 1.357 + * bool draw(gstatus_t s); 1.358 */ 1.359 -#define running(s) ((s) == EMPTY) 1.360 -#define draw(s) ((s) == DRAW) 1.361 +#define running(s) ((s) == EMPTY) 1.362 +#define draw(s) ((s) == DRAW) 1.363 1.364 1.365 /***[FUNCTIONS]***************************************************************/ 1.366 @@ -337,213 +338,204 @@ 1.367 opponent(player_t someone) 1.368 { 1.369 1.370 - check_player_t(someone); 1.371 - return (someone == X ? O : X); 1.372 + check_player_t(someone); 1.373 + return (someone == X ? O : X); 1.374 } 1.375 1.376 1.377 void 1.378 wins(player_t player, const state_t *board, 1.379 - unsigned int *nmatchptr, position_t *matches) 1.380 + unsigned int *nmatchptr, position_t *matches) 1.381 { 1.382 - unsigned int nmatch = 0; 1.383 - unsigned int nplayer, x, y; 1.384 - position_t emptyp; 1.385 + unsigned int nmatch = 0; 1.386 + unsigned int nplayer, x, y; 1.387 + position_t emptyp; 1.388 1.389 - check_player_t(player); 1.390 - check_ptr(board); 1.391 - check_ptr(nmatchptr); 1.392 - check_ptr(matches); 1.393 + check_player_t(player); 1.394 + check_ptr(board); 1.395 + check_ptr(nmatchptr); 1.396 + check_ptr(matches); 1.397 1.398 - /* check each lines */ 1.399 - for (y = 0; y < SIZE; y++) { 1.400 - nplayer = 0; 1.401 - emptyp = INVALID_POSITION; 1.402 - for (x = 0; x < SIZE; x++) { 1.403 - state_t s = board[at(x, y)]; 1.404 - if (s == player) 1.405 - nplayer++; 1.406 - else if (s == EMPTY) 1.407 - emptyp = at(x, y); 1.408 - } 1.409 - if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.410 - matches[nmatch++] = emptyp; 1.411 - } 1.412 + /* check each lines */ 1.413 + for (y = 0; y < SIZE; y++) { 1.414 + nplayer = 0; 1.415 + emptyp = INVALID_POSITION; 1.416 + for (x = 0; x < SIZE; x++) { 1.417 + state_t s = board[at(x, y)]; 1.418 + if (s == player) 1.419 + nplayer++; 1.420 + else if (s == EMPTY) 1.421 + emptyp = at(x, y); 1.422 + } 1.423 + if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.424 + matches[nmatch++] = emptyp; 1.425 + } 1.426 1.427 - /* check each columns */ 1.428 - for (x = 0; x < SIZE; x++) { 1.429 - nplayer = 0; 1.430 - emptyp = INVALID_POSITION; 1.431 - for (y = 0; y < SIZE; y++) { 1.432 - state_t s = board[at(x, y)]; 1.433 - if (s == player) 1.434 - nplayer++; 1.435 - else if (s == EMPTY) 1.436 - emptyp = at(x, y); 1.437 - } 1.438 - if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.439 - matches[nmatch++] = emptyp; 1.440 - } 1.441 + /* check each columns */ 1.442 + for (x = 0; x < SIZE; x++) { 1.443 + nplayer = 0; 1.444 + emptyp = INVALID_POSITION; 1.445 + for (y = 0; y < SIZE; y++) { 1.446 + state_t s = board[at(x, y)]; 1.447 + if (s == player) 1.448 + nplayer++; 1.449 + else if (s == EMPTY) 1.450 + emptyp = at(x, y); 1.451 + } 1.452 + if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.453 + matches[nmatch++] = emptyp; 1.454 + } 1.455 1.456 - /* check the first diagonal / */ 1.457 - nplayer = 0; 1.458 - emptyp = INVALID_POSITION; 1.459 - for (x = 0, y = 0; x < SIZE; x++, y++) { 1.460 - state_t s = board[at(x, y)]; 1.461 - if (s == player) 1.462 - nplayer++; 1.463 - else if (s == EMPTY) 1.464 - emptyp = at(x, y); 1.465 - } 1.466 - if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.467 - matches[nmatch++] = emptyp; 1.468 + /* check the first diagonal / */ 1.469 + nplayer = 0; 1.470 + emptyp = INVALID_POSITION; 1.471 + for (x = 0, y = 0; x < SIZE; x++, y++) { 1.472 + state_t s = board[at(x, y)]; 1.473 + if (s == player) 1.474 + nplayer++; 1.475 + else if (s == EMPTY) 1.476 + emptyp = at(x, y); 1.477 + } 1.478 + if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.479 + matches[nmatch++] = emptyp; 1.480 1.481 - /* check the second diagonal \ */ 1.482 - nplayer = 0; 1.483 - emptyp = INVALID_POSITION; 1.484 - for (x = SIZE - 1, y = 0; x < SIZE; x--, y++) { 1.485 - state_t s = board[at(x, y)]; 1.486 - if (s == player) 1.487 - nplayer++; 1.488 - else if (s == EMPTY) 1.489 - emptyp = at(x, y); 1.490 - } 1.491 - if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.492 - matches[nmatch++] = emptyp; 1.493 + /* check the second diagonal \ */ 1.494 + nplayer = 0; 1.495 + emptyp = INVALID_POSITION; 1.496 + for (x = SIZE - 1, y = 0; x < SIZE; x--, y++) { 1.497 + state_t s = board[at(x, y)]; 1.498 + if (s == player) 1.499 + nplayer++; 1.500 + else if (s == EMPTY) 1.501 + emptyp = at(x, y); 1.502 + } 1.503 + if (nplayer == (SIZE - 1) && emptyp != INVALID_POSITION) 1.504 + matches[nmatch++] = emptyp; 1.505 1.506 - *nmatchptr = nmatch; 1.507 - /* 1.508 - * we have to make sure that we don't have duplicate. A position could make 1.509 - * a winning line *and* a column (for example). So we need to finalize the 1.510 - * result by calling uniq(). 1.511 - */ 1.512 - if (nmatch > 1) 1.513 - uniq(nmatchptr, matches); 1.514 + *nmatchptr = nmatch; 1.515 + /* 1.516 + * we have to make sure that we don't have duplicate. A position could make 1.517 + * a winning line *and* a column (for example). So we need to finalize the 1.518 + * result by calling uniq(). 1.519 + */ 1.520 + if (nmatch > 1) 1.521 + uniq(nmatchptr, matches); 1.522 } 1.523 1.524 1.525 void 1.526 uniq(unsigned int *nmatchptr, position_t *matches) 1.527 { 1.528 - unsigned int i; 1.529 - unsigned int nmatch, unmatch; 1.530 - position_t umatches[POSITION_MAX]; 1.531 + unsigned int i; 1.532 + unsigned int nmatch; 1.533 + unsigned int unmatch; 1.534 + position_t umatches[POSITION_MAX]; 1.535 1.536 - check_ptr(nmatchptr); 1.537 - check_ptr(matches); 1.538 + check_ptr(nmatchptr); 1.539 + check_ptr(matches); 1.540 1.541 - nmatch = *nmatchptr; 1.542 - if (nmatch < 2) 1.543 - return; 1.544 - 1.545 - /* 1.546 - * we don't care about the matches order, so we first sort matches, and 1.547 - * then we can perform a uniq() filter in one pass. 1.548 - * 1.549 - * (sort + filter = uniq): 1.550 - * O(n * log(n)) + O(n) = O(n * log(n)) 1.551 - */ 1.552 - qsort(matches, nmatch, sizeof(position_t), position_cmp); 1.553 - 1.554 - umatches[0] = matches[0]; 1.555 - unmatch = 1; 1.556 - for (i = 0; i < nmatch; i++) { 1.557 - if (matches[i] != umatches[unmatch - 1]) 1.558 - umatches[unmatch++] = matches[i]; 1.559 - } 1.560 - 1.561 - (void)memcpy(matches, umatches, unmatch * sizeof(position_t)); 1.562 - *nmatchptr = unmatch; 1.563 + nmatch = *nmatchptr; 1.564 + if (nmatch < 2) 1.565 + return; 1.566 + /* 1.567 + * we don't care about the matches order, so we first sort matches, and 1.568 + * then we can perform a uniq() filter in one pass. 1.569 + * 1.570 + * (sort + filter = uniq): 1.571 + * O(n * log(n)) + O(n) = O(n * log(n)) 1.572 + */ 1.573 + qsort(matches, nmatch, sizeof(position_t), position_cmp); 1.574 + umatches[0] = matches[0]; 1.575 + unmatch = 1; 1.576 + for (i = 0; i < nmatch; i++) { 1.577 + if (matches[i] != umatches[unmatch - 1]) 1.578 + umatches[unmatch++] = matches[i]; 1.579 + } 1.580 + (void)memcpy(matches, umatches, unmatch * sizeof(position_t)); 1.581 + *nmatchptr = unmatch; 1.582 } 1.583 1.584 1.585 int 1.586 position_cmp(const void *aptr, const void *bptr) 1.587 { 1.588 - const position_t *a, *b; 1.589 + const position_t *a; 1.590 + const position_t *b; 1.591 1.592 - check_ptr(aptr); 1.593 - check_ptr(bptr); 1.594 + check_ptr(aptr); 1.595 + check_ptr(bptr); 1.596 1.597 - a = aptr; 1.598 - b = bptr; 1.599 - 1.600 - return (*a - *b); 1.601 + a = aptr; 1.602 + b = bptr; 1.603 + return (*a - *b); 1.604 } 1.605 1.606 1.607 void 1.608 forks(player_t player, const state_t *board, 1.609 - unsigned int *nmatchptr, position_t *matches) 1.610 + unsigned int *nmatchptr, position_t *matches) 1.611 { 1.612 - unsigned int nmatch = 0; 1.613 - state_t boardcpy[POSITION_MAX]; 1.614 - position_t p; 1.615 + unsigned int nmatch = 0; 1.616 + state_t boardcpy[POSITION_MAX]; 1.617 + position_t p; 1.618 1.619 - check_player_t(player); 1.620 - check_ptr(board); 1.621 - check_ptr(nmatchptr); 1.622 - check_ptr(matches); 1.623 + check_player_t(player); 1.624 + check_ptr(board); 1.625 + check_ptr(nmatchptr); 1.626 + check_ptr(matches); 1.627 1.628 - /* we copy the const board 'cause we need to modify it */ 1.629 - (void)memcpy(boardcpy, board, sizeof(boardcpy)); 1.630 - 1.631 - /* 1.632 - * for each possible position, if we play it and then the Win (1) strategy 1.633 - * return more than one winning position, we've created a fork. 1.634 - */ 1.635 - for (p = 0; p < POSITION_MAX; p++) { 1.636 - if (boardcpy[p] == EMPTY) { 1.637 - position_t wmatches[POSITION_MAX]; 1.638 - unsigned int wnmatch; 1.639 - 1.640 - /* play */ 1.641 - boardcpy[p] = player; 1.642 - /* We call wins() instead of iWin() to avoid board modification */ 1.643 - wins(player, boardcpy, &wnmatch, wmatches); 1.644 - /* undo the move */ 1.645 - boardcpy[p] = EMPTY; 1.646 - 1.647 - if (wnmatch > 1) 1.648 - matches[nmatch++] = p; 1.649 - } 1.650 - } 1.651 - 1.652 - *nmatchptr = nmatch; 1.653 + /* we copy the const board 'cause we need to modify it */ 1.654 + (void)memcpy(boardcpy, board, sizeof(boardcpy)); 1.655 + /* 1.656 + * for each possible position, if we play it and then the Win (1) strategy 1.657 + * return more than one winning position, we've created a fork. 1.658 + */ 1.659 + for (p = 0; p < POSITION_MAX; p++) { 1.660 + if (boardcpy[p] == EMPTY) { 1.661 + position_t wmatches[POSITION_MAX]; 1.662 + unsigned int wnmatch; 1.663 + /* play */ 1.664 + boardcpy[p] = player; 1.665 + /* We call wins() instead of iWin() to avoid board modification */ 1.666 + wins(player, boardcpy, &wnmatch, wmatches); 1.667 + /* undo the move */ 1.668 + boardcpy[p] = EMPTY; 1.669 + if (wnmatch > 1) 1.670 + matches[nmatch++] = p; 1.671 + } 1.672 + } 1.673 + *nmatchptr = nmatch; 1.674 } 1.675 1.676 1.677 position_t 1.678 apply(player_t me, state_t *board, 1.679 - unsigned int nmatch, const position_t *matches) 1.680 + unsigned int nmatch, const position_t *matches) 1.681 { 1.682 - unsigned int i; 1.683 - position_t match; 1.684 + unsigned int i; 1.685 + position_t match; 1.686 1.687 - check_player_t(me); 1.688 - check_ptr(board); 1.689 - check_ptr(matches); 1.690 - assert(("something to apply", nmatch > 0)); 1.691 + check_player_t(me); 1.692 + check_ptr(board); 1.693 + check_ptr(matches); 1.694 + assert(("something to apply", nmatch > 0)); 1.695 1.696 #ifdef VERBOSE 1.697 - (void)printf("-> candidates are: "); 1.698 - for (i = 0; i < nmatch; i++) 1.699 - (void)printf("(%d,%d) ", PP(matches[i])); 1.700 - (void)printf("\n"); 1.701 + (void)printf("-> candidates are: "); 1.702 + for (i = 0; i < nmatch; i++) 1.703 + (void)printf("(%d,%d) ", PP(matches[i])); 1.704 + (void)printf("\n"); 1.705 #endif 1.706 - 1.707 - if (Grandom && nmatch > 1) 1.708 - match = matches[rand() % nmatch]; 1.709 - else 1.710 - match = matches[0]; 1.711 - 1.712 - assert(("apply a valid position", match > INVALID_POSITION && match < POSITION_MAX)); 1.713 - if (board[match] != EMPTY) 1.714 - return (INVALID_POSITION); 1.715 - else 1.716 - board[match] = me; 1.717 - 1.718 - return (match); 1.719 + if (Grandom && nmatch > 1) 1.720 + match = matches[rand() % nmatch]; 1.721 + else 1.722 + match = matches[0]; 1.723 + assert(("apply a valid position", match > INVALID_POSITION && match < POSITION_MAX)); 1.724 + if (board[match] != EMPTY) 1.725 + return (INVALID_POSITION); 1.726 + else 1.727 + board[match] = me; 1.728 + return (match); 1.729 } 1.730 1.731 1.732 @@ -553,64 +545,63 @@ 1.733 position_t 1.734 iWin(player_t me, state_t *board) 1.735 { 1.736 - unsigned int nmatch; 1.737 - position_t matches[POSITION_MAX]; 1.738 + unsigned int nmatch; 1.739 + position_t matches[POSITION_MAX]; 1.740 1.741 - check_player_t(me); 1.742 - check_ptr(board); 1.743 + check_player_t(me); 1.744 + check_ptr(board); 1.745 1.746 - wins(me, board, &nmatch, matches); 1.747 - 1.748 - if (nmatch > 0) 1.749 - return (apply(me, board, nmatch, matches)); 1.750 - else 1.751 - return (INVALID_POSITION); 1.752 + wins(me, board, &nmatch, matches); 1.753 + if (nmatch > 0) 1.754 + return (apply(me, board, nmatch, matches)); 1.755 + else 1.756 + return (INVALID_POSITION); 1.757 } 1.758 1.759 1.760 position_t 1.761 iBlock(player_t me, state_t *board) 1.762 { 1.763 - unsigned int nmatch; 1.764 - position_t matches[POSITION_MAX]; 1.765 + unsigned int nmatch; 1.766 + position_t matches[POSITION_MAX]; 1.767 1.768 - check_player_t(me); 1.769 - check_ptr(board); 1.770 + check_player_t(me); 1.771 + check_ptr(board); 1.772 1.773 - wins(opponent(me), board, &nmatch, matches); 1.774 - 1.775 - if (nmatch > 0) 1.776 - return (apply(me, board, nmatch, matches)); 1.777 - else 1.778 - return (INVALID_POSITION); 1.779 + wins(opponent(me), board, &nmatch, matches); 1.780 + if (nmatch > 0) 1.781 + return (apply(me, board, nmatch, matches)); 1.782 + else 1.783 + return (INVALID_POSITION); 1.784 } 1.785 1.786 1.787 position_t 1.788 iFork(player_t me, state_t *board) 1.789 { 1.790 - unsigned int nmatch; 1.791 - position_t matches[POSITION_MAX]; 1.792 + unsigned int nmatch; 1.793 + position_t matches[POSITION_MAX]; 1.794 1.795 - check_player_t(me); 1.796 - check_ptr(board); 1.797 + check_player_t(me); 1.798 + check_ptr(board); 1.799 1.800 - forks(me, board, &nmatch, matches); 1.801 - 1.802 - if (nmatch > 0) 1.803 - return (apply(me, board, nmatch, matches)); 1.804 - else 1.805 - return (INVALID_POSITION); 1.806 + forks(me, board, &nmatch, matches); 1.807 + if (nmatch > 0) 1.808 + return (apply(me, board, nmatch, matches)); 1.809 + else 1.810 + return (INVALID_POSITION); 1.811 } 1.812 1.813 1.814 position_t 1.815 iBlockOpponent1(player_t me, state_t *board) 1.816 { 1.817 - unsigned int nmatch = 0; 1.818 - position_t matches[POSITION_MAX]; 1.819 - unsigned int nme, nemptyp, x, y; 1.820 - position_t emptyp[2]; 1.821 + unsigned int nmatch = 0; 1.822 + unsigned int nme; 1.823 + unsigned int nemptyp; 1.824 + unsigned int x, y; 1.825 + position_t matches[POSITION_MAX]; 1.826 + position_t emptyp[2]; 1.827 1.828 check_player_t(me); 1.829 check_ptr(board); 1.830 @@ -622,207 +613,204 @@ 1.831 * row (or a row and a diagonal etc), it should have been catched by 1.832 * iFork(). 1.833 */ 1.834 - 1.835 /* check each lines */ 1.836 for (y = 0; y < SIZE; y++) { 1.837 - nme = nemptyp = 0; 1.838 - for (x = 0; x < SIZE; x++) { 1.839 - state_t s = board[at(x, y)]; 1.840 - if (s == me) 1.841 - nme++; 1.842 - else if (s == EMPTY) 1.843 - emptyp[nemptyp++] = at(x, y); 1.844 - } 1.845 - if (nme == SIZE - 2 && nemptyp == 2) { 1.846 - matches[nmatch++] = emptyp[0]; 1.847 - matches[nmatch++] = emptyp[1]; 1.848 - } 1.849 + nme = nemptyp = 0; 1.850 + for (x = 0; x < SIZE; x++) { 1.851 + state_t s = board[at(x, y)]; 1.852 + if (s == me) 1.853 + nme++; 1.854 + else if (s == EMPTY) 1.855 + emptyp[nemptyp++] = at(x, y); 1.856 + } 1.857 + if (nme == SIZE - 2 && nemptyp == 2) { 1.858 + matches[nmatch++] = emptyp[0]; 1.859 + matches[nmatch++] = emptyp[1]; 1.860 + } 1.861 } 1.862 1.863 /* check each columns */ 1.864 for (x = 0; x < SIZE; x++) { 1.865 - nme = nemptyp = 0; 1.866 - for (y = 0; y < SIZE; y++) { 1.867 - state_t s = board[at(x, y)]; 1.868 - if (s == me) 1.869 - nme++; 1.870 - else if (s == EMPTY) 1.871 - emptyp[nemptyp++] = at(x, y); 1.872 - } 1.873 - if (nme == SIZE - 2 && nemptyp == 2) { 1.874 - matches[nmatch++] = emptyp[0]; 1.875 - matches[nmatch++] = emptyp[1]; 1.876 - } 1.877 + nme = nemptyp = 0; 1.878 + for (y = 0; y < SIZE; y++) { 1.879 + state_t s = board[at(x, y)]; 1.880 + if (s == me) 1.881 + nme++; 1.882 + else if (s == EMPTY) 1.883 + emptyp[nemptyp++] = at(x, y); 1.884 + } 1.885 + if (nme == SIZE - 2 && nemptyp == 2) { 1.886 + matches[nmatch++] = emptyp[0]; 1.887 + matches[nmatch++] = emptyp[1]; 1.888 + } 1.889 } 1.890 1.891 /* check the first diagonal / */ 1.892 nme = nemptyp = 0; 1.893 for (x = 0, y = 0; x < SIZE; x++, y++) { 1.894 - state_t s = board[at(x, y)]; 1.895 - if (s == me) 1.896 - nme++; 1.897 - else if (s == EMPTY) 1.898 - emptyp[nemptyp++] = at(x, y); 1.899 + state_t s = board[at(x, y)]; 1.900 + if (s == me) 1.901 + nme++; 1.902 + else if (s == EMPTY) 1.903 + emptyp[nemptyp++] = at(x, y); 1.904 } 1.905 if (nme == SIZE - 2 && nemptyp == 2) { 1.906 - matches[nmatch++] = emptyp[0]; 1.907 - matches[nmatch++] = emptyp[1]; 1.908 + matches[nmatch++] = emptyp[0]; 1.909 + matches[nmatch++] = emptyp[1]; 1.910 } 1.911 1.912 /* check the second diagonal \ */ 1.913 nme = nemptyp = 0; 1.914 for (x = SIZE - 1, y = 0; x < SIZE; x--, y++) { 1.915 - state_t s = board[at(x, y)]; 1.916 - if (s == me) 1.917 - nme++; 1.918 - else if (s == EMPTY) 1.919 - emptyp[nemptyp++] = at(x, y); 1.920 + state_t s = board[at(x, y)]; 1.921 + if (s == me) 1.922 + nme++; 1.923 + else if (s == EMPTY) 1.924 + emptyp[nemptyp++] = at(x, y); 1.925 } 1.926 if (nme == SIZE - 2 && nemptyp == 2) { 1.927 - matches[nmatch++] = emptyp[0]; 1.928 - matches[nmatch++] = emptyp[1]; 1.929 + matches[nmatch++] = emptyp[0]; 1.930 + matches[nmatch++] = emptyp[1]; 1.931 } 1.932 1.933 - unsigned int i; 1.934 - player_t enemy = opponent(me); 1.935 - unsigned int enemynmatch; 1.936 - position_t enemymatches[POSITION_MAX]; 1.937 - unsigned int nfiltered = 0; 1.938 - position_t filteredmatches[POSITION_MAX]; 1.939 + unsigned int i; 1.940 + player_t enemy = opponent(me); 1.941 + unsigned int enemynmatch; 1.942 + position_t enemymatches[POSITION_MAX]; 1.943 + unsigned int nfiltered = 0; 1.944 + position_t filteredmatches[POSITION_MAX]; 1.945 1.946 /* 1.947 * foreach of them we need to ensure that the opponent can't iWin() 1.948 */ 1.949 for (i = 0; i < nmatch; i++) { 1.950 - position_t p = matches[i]; 1.951 - position_t op = matches[(i & 1) ? (i - 1) : (i + 1)]; 1.952 - assert(("I try to play an empty position", board[p] == EMPTY)); 1.953 - board[p] = me; 1.954 - wins(enemy, board, &enemynmatch, enemymatches); 1.955 - if (enemynmatch == 0) { 1.956 - /* 1.957 - * ok, he can't iWin() by defending. We need to check if it'll not 1.958 - * create a fork. 1.959 - */ 1.960 - assert(("I try to play an empty position", board[op] == EMPTY)); 1.961 - board[op] = enemy; 1.962 - wins(enemy, board, &enemynmatch, enemymatches); 1.963 - board[op] = EMPTY; 1.964 - if (enemynmatch < 2) 1.965 - filteredmatches[nfiltered++] = p; 1.966 - } 1.967 - board[p] = EMPTY; 1.968 + position_t p = matches[i]; 1.969 + position_t op = matches[(i & 1) ? (i - 1) : (i + 1)]; 1.970 + assert(("I try to play an empty position", board[p] == EMPTY)); 1.971 + board[p] = me; 1.972 + wins(enemy, board, &enemynmatch, enemymatches); 1.973 + if (enemynmatch == 0) { 1.974 + /* 1.975 + * ok, he can't iWin() by defending. We need to check if it'll not 1.976 + * create a fork. 1.977 + */ 1.978 + assert(("I try to play an empty position", board[op] == EMPTY)); 1.979 + board[op] = enemy; 1.980 + wins(enemy, board, &enemynmatch, enemymatches); 1.981 + board[op] = EMPTY; 1.982 + if (enemynmatch < 2) 1.983 + filteredmatches[nfiltered++] = p; 1.984 + } 1.985 + board[p] = EMPTY; 1.986 } 1.987 1.988 if (nfiltered > 0) 1.989 - return (apply(me, board, nfiltered, filteredmatches)); 1.990 + return (apply(me, board, nfiltered, filteredmatches)); 1.991 else 1.992 - return (INVALID_POSITION); 1.993 + return (INVALID_POSITION); 1.994 } 1.995 1.996 1.997 position_t 1.998 iBlockOpponent2(player_t me, state_t *board) 1.999 { 1.1000 - unsigned int nmatch; 1.1001 - position_t matches[POSITION_MAX]; 1.1002 + unsigned int nmatch; 1.1003 + position_t matches[POSITION_MAX]; 1.1004 1.1005 check_player_t(me); 1.1006 check_ptr(board); 1.1007 1.1008 forks(opponent(me), board, &nmatch, matches); 1.1009 - 1.1010 if (nmatch > 0) 1.1011 - return (apply(me, board, nmatch, matches)); 1.1012 + return (apply(me, board, nmatch, matches)); 1.1013 else 1.1014 - return (INVALID_POSITION); 1.1015 + return (INVALID_POSITION); 1.1016 } 1.1017 1.1018 1.1019 position_t 1.1020 iPlayCenter(player_t me, state_t *board) 1.1021 { 1.1022 - position_t center; 1.1023 + position_t center; 1.1024 1.1025 - check_player_t(me); 1.1026 - check_ptr(board); 1.1027 + check_player_t(me); 1.1028 + check_ptr(board); 1.1029 1.1030 - center = at(SIZE / 2, SIZE / 2); 1.1031 - if (board[center] == EMPTY) 1.1032 - return (apply(me, board, 1, ¢er)); 1.1033 - else 1.1034 - return (INVALID_POSITION); 1.1035 + center = at(SIZE / 2, SIZE / 2); 1.1036 + if (board[center] == EMPTY) 1.1037 + return (apply(me, board, 1, ¢er)); 1.1038 + else 1.1039 + return (INVALID_POSITION); 1.1040 } 1.1041 1.1042 1.1043 position_t 1.1044 iPlayOppositeCorner(player_t me, state_t *board) 1.1045 { 1.1046 - unsigned int i, nmatch = 0; 1.1047 - position_t matches[countof(corners) / 2]; 1.1048 - position_t c, oc; 1.1049 - player_t enemy; 1.1050 + unsigned int i; 1.1051 + unsigned int nmatch = 0; 1.1052 + position_t matches[countof(corners) / 2]; 1.1053 + position_t c, oc; 1.1054 + player_t enemy; 1.1055 1.1056 - check_player_t(me); 1.1057 - check_ptr(board); 1.1058 + check_player_t(me); 1.1059 + check_ptr(board); 1.1060 1.1061 - enemy = opponent(me); 1.1062 - for (i = 0; i < countof(corners); i++) { 1.1063 - c = corners[i]; 1.1064 - oc = corners[countof(corners) - 1 - i]; 1.1065 - if (board[c] == EMPTY && board[oc] == enemy) 1.1066 - matches[nmatch++] = c; 1.1067 - } 1.1068 - 1.1069 - if (nmatch > 0) 1.1070 - return (apply(me, board, nmatch, matches)); 1.1071 - else 1.1072 - return (INVALID_POSITION); 1.1073 + enemy = opponent(me); 1.1074 + for (i = 0; i < countof(corners); i++) { 1.1075 + c = corners[i]; 1.1076 + oc = corners[countof(corners) - 1 - i]; 1.1077 + if (board[c] == EMPTY && board[oc] == enemy) 1.1078 + matches[nmatch++] = c; 1.1079 + } 1.1080 + if (nmatch > 0) 1.1081 + return (apply(me, board, nmatch, matches)); 1.1082 + else 1.1083 + return (INVALID_POSITION); 1.1084 } 1.1085 1.1086 1.1087 position_t 1.1088 iPlayCorner(player_t me, state_t *board) 1.1089 { 1.1090 - unsigned int i, nmatch = 0; 1.1091 - position_t matches[countof(corners)]; 1.1092 - position_t c; 1.1093 + unsigned int i; 1.1094 + unsigned int nmatch = 0; 1.1095 + position_t matches[countof(corners)]; 1.1096 + position_t c; 1.1097 1.1098 check_player_t(me); 1.1099 check_ptr(board); 1.1100 1.1101 for (i = 0; i < countof(corners); i++) { 1.1102 - c = corners[i]; 1.1103 - if (board[c] == EMPTY) 1.1104 - matches[nmatch++] = c; 1.1105 + c = corners[i]; 1.1106 + if (board[c] == EMPTY) 1.1107 + matches[nmatch++] = c; 1.1108 } 1.1109 - 1.1110 if (nmatch > 0) 1.1111 - return (apply(me, board, nmatch, matches)); 1.1112 + return (apply(me, board, nmatch, matches)); 1.1113 else 1.1114 - return (INVALID_POSITION); 1.1115 + return (INVALID_POSITION); 1.1116 } 1.1117 1.1118 1.1119 position_t 1.1120 iPlayEmpty(player_t me, state_t *board) 1.1121 { 1.1122 - unsigned int nmatch = 0; 1.1123 - position_t matches[POSITION_MAX]; 1.1124 - position_t p; 1.1125 + unsigned int nmatch = 0; 1.1126 + position_t matches[POSITION_MAX]; 1.1127 + position_t p; 1.1128 1.1129 check_player_t(me); 1.1130 check_ptr(board); 1.1131 1.1132 for (p = 0; p < POSITION_MAX; p++) { 1.1133 - if (board[p] == EMPTY) 1.1134 - matches[nmatch++] = p; 1.1135 + if (board[p] == EMPTY) 1.1136 + matches[nmatch++] = p; 1.1137 } 1.1138 - 1.1139 if (nmatch > 0) 1.1140 - return (apply(me, board, nmatch, matches)); 1.1141 + return (apply(me, board, nmatch, matches)); 1.1142 else 1.1143 - return (INVALID_POSITION); 1.1144 + return (INVALID_POSITION); 1.1145 } 1.1146 1.1147 1.1148 @@ -834,142 +822,136 @@ 1.1149 void 1.1150 dump_board(FILE *out, const state_t *board) 1.1151 { 1.1152 - unsigned int x, y; 1.1153 + unsigned int x, y; 1.1154 1.1155 - check_ptr(out); 1.1156 - check_ptr(board); 1.1157 + check_ptr(out); 1.1158 + check_ptr(board); 1.1159 1.1160 - (void)fprintf(out, " "); 1.1161 - for (x = 0; x < SIZE; x++) 1.1162 - (void)fprintf(out, " %d", x + 1); 1.1163 - (void)fprintf(out, "\n"); 1.1164 + (void)fprintf(out, " "); 1.1165 + for (x = 0; x < SIZE; x++) 1.1166 + (void)fprintf(out, " %d", x + 1); 1.1167 + (void)fprintf(out, "\n"); 1.1168 1.1169 - (void)fprintf(out, " "); 1.1170 - for (x = 0; x < (SIZE * 2) - 1; x++) 1.1171 - (void)fprintf(out, "_"); 1.1172 - (void)fprintf(out, "\n"); 1.1173 + (void)fprintf(out, " "); 1.1174 + for (x = 0; x < (SIZE * 2) - 1; x++) 1.1175 + (void)fprintf(out, "_"); 1.1176 + (void)fprintf(out, "\n"); 1.1177 1.1178 - for (y = 0; y < SIZE; y++) { 1.1179 - (void)fprintf(out, "%d |", y + 1); 1.1180 - for (x = 0; x < SIZE; x++) 1.1181 - (void)fprintf(out, "%c ", display[board[at(x, y)]]); 1.1182 - (void)fprintf(out, "\n"); 1.1183 - } 1.1184 + for (y = 0; y < SIZE; y++) { 1.1185 + (void)fprintf(out, "%d |", y + 1); 1.1186 + for (x = 0; x < SIZE; x++) 1.1187 + (void)fprintf(out, "%c ", display[board[at(x, y)]]); 1.1188 + (void)fprintf(out, "\n"); 1.1189 + } 1.1190 1.1191 - (void)fprintf(out, "\n"); 1.1192 - (void)fflush(out); 1.1193 + (void)fprintf(out, "\n"); 1.1194 + (void)fflush(out); 1.1195 } 1.1196 1.1197 1.1198 void 1.1199 check_board(const state_t *board) 1.1200 { 1.1201 - position_t p; 1.1202 + position_t p; 1.1203 + unsigned int n[] = { 1.1204 + [EMPTY] = 0, 1.1205 + [X] = 0, 1.1206 + [O] = 0, 1.1207 + [DRAW] = 0, 1.1208 + }; 1.1209 1.1210 - unsigned int n[] = { 1.1211 - [EMPTY] = 0, 1.1212 - [X] = 0, 1.1213 - [O] = 0, 1.1214 - [DRAW] = 0, 1.1215 - }; 1.1216 + check_ptr(board); 1.1217 1.1218 - check_ptr(board); 1.1219 - 1.1220 - for (p = 0; p < POSITION_MAX; p++) { 1.1221 - check_state_t(board[p]); 1.1222 - n[board[p]]++; 1.1223 - } 1.1224 - 1.1225 - assert(("at least one empty position", n[EMPTY] > 0)); 1.1226 - assert(("fair number of turns", abs(n[X] - n[O]) < 2)); 1.1227 - assert(("no invalid state in the board", n[DRAW] == 0)); 1.1228 + for (p = 0; p < POSITION_MAX; p++) { 1.1229 + check_state_t(board[p]); 1.1230 + n[board[p]]++; 1.1231 + } 1.1232 + assert(("at least one empty position", n[EMPTY] > 0)); 1.1233 + assert(("fair number of turns", abs(n[X] - n[O]) < 2)); 1.1234 + assert(("no invalid state in the board", n[DRAW] == 0)); 1.1235 } 1.1236 1.1237 1.1238 gstatus_t 1.1239 outcome(const state_t *board) 1.1240 { 1.1241 - player_t winner; 1.1242 - bool full = true; 1.1243 - unsigned int i, x, y, nwin = 0; 1.1244 - unsigned int lnc[SIZE + SIZE]; /* line and columns */ 1.1245 - unsigned int dia[2]; /* diagonals */ 1.1246 + player_t winner; 1.1247 + bool full = true; 1.1248 + unsigned int i, x, y, nwin = 0; 1.1249 + unsigned int lnc[SIZE + SIZE]; /* line and columns */ 1.1250 + unsigned int dia[2]; /* diagonals */ 1.1251 1.1252 - check_ptr(board); 1.1253 + check_ptr(board); 1.1254 1.1255 - (void)memset(dia, X | O, sizeof(dia)); 1.1256 - (void)memset(lnc, X | O, sizeof(lnc)); 1.1257 + (void)memset(dia, X | O, sizeof(dia)); 1.1258 + (void)memset(lnc, X | O, sizeof(lnc)); 1.1259 + /* check lines and columns */ 1.1260 + for (y = 0; y < SIZE; y++) { 1.1261 + for (x = 0; x < SIZE; x++) { 1.1262 + /* each point contribute to exactly one line and one column. */ 1.1263 + state_t s = board[at(x, y)]; 1.1264 + if (s == EMPTY) 1.1265 + full = false; 1.1266 + lnc[y] &= s; 1.1267 + lnc[SIZE + x] &= s; 1.1268 + } 1.1269 + } 1.1270 + for (i = 0; i < countof(lnc); i++) { 1.1271 + if (lnc[i]) { 1.1272 + if (nwin++ > 0) 1.1273 + assert(("uniq winner", winner == lnc[i])); 1.1274 + else 1.1275 + winner = lnc[i]; 1.1276 + } 1.1277 + } 1.1278 + assert(("fair turns", nwin <= 2)); 1.1279 1.1280 - /* check lines and columns */ 1.1281 - for (y = 0; y < SIZE; y++) { 1.1282 - for (x = 0; x < SIZE; x++) { 1.1283 - /* each point contribute to exactly one line and one column. */ 1.1284 - state_t s = board[at(x, y)]; 1.1285 - if (s == EMPTY) 1.1286 - full = false; 1.1287 - lnc[y] &= s; 1.1288 - lnc[SIZE + x] &= s; 1.1289 - } 1.1290 - } 1.1291 - for (i = 0; i < countof(lnc); i++) { 1.1292 - if (lnc[i]) { 1.1293 - if (nwin++ > 0) 1.1294 - assert(("uniq winner", winner == lnc[i])); 1.1295 - else 1.1296 - winner = lnc[i]; 1.1297 - } 1.1298 - } 1.1299 - assert(("fair turns", nwin <= 2)); 1.1300 - 1.1301 - /* check diagonals */ 1.1302 - for (i = 0; i < SIZE; i++) { 1.1303 - dia[0] &= board[at(i, i)]; 1.1304 - dia[1] &= board[at(i, (SIZE - 1) - i)]; 1.1305 - } 1.1306 - for (i = 0; i < countof(dia); i++) { 1.1307 - if (dia[i]) { 1.1308 - if (nwin++ > 0) 1.1309 - assert(("uniq winner", winner == dia[i])); 1.1310 - else 1.1311 - winner = dia[i]; 1.1312 - } 1.1313 - } 1.1314 + /* check diagonals */ 1.1315 + for (i = 0; i < SIZE; i++) { 1.1316 + dia[0] &= board[at(i, i)]; 1.1317 + dia[1] &= board[at(i, (SIZE - 1) - i)]; 1.1318 + } 1.1319 + for (i = 0; i < countof(dia); i++) { 1.1320 + if (dia[i]) { 1.1321 + if (nwin++ > 0) 1.1322 + assert(("uniq winner", winner == dia[i])); 1.1323 + else 1.1324 + winner = dia[i]; 1.1325 + } 1.1326 + } 1.1327 #if (SIZE == 3) 1.1328 - assert(("fair turns", nwin <= 2)); 1.1329 + assert(("fair turns", nwin <= 2)); 1.1330 #elif (SIZE == 5) 1.1331 - assert(("fair turns", nwin <= 3)); 1.1332 + assert(("fair turns", nwin <= 3)); 1.1333 #else 1.1334 - assert(("fair turns", nwin <= 4)); 1.1335 + assert(("fair turns", nwin <= 4)); 1.1336 #endif 1.1337 1.1338 - if (nwin == 0) 1.1339 - return (full ? DRAW : EMPTY); 1.1340 - else { 1.1341 - check_player_t(winner); 1.1342 - return (winner); 1.1343 - } 1.1344 + if (nwin == 0) 1.1345 + return (full ? DRAW : EMPTY); 1.1346 + else { 1.1347 + check_player_t(winner); 1.1348 + return (winner); 1.1349 +} 1.1350 } 1.1351 1.1352 1.1353 void 1.1354 setstrategy3(int i) 1.1355 { 1.1356 - strategy_t *s; 1.1357 - char *desc; 1.1358 + strategy_t *s; 1.1359 + char *desc; 1.1360 1.1361 - if (i == 1) { 1.1362 - desc = "iBlockOpponent1"; 1.1363 - s = iBlockOpponent1; 1.1364 - } 1.1365 - else if (i == 2) { 1.1366 - desc = "iBlockOpponent2"; 1.1367 - s = iBlockOpponent2; 1.1368 - } 1.1369 - else 1.1370 - return; 1.1371 - 1.1372 - strategies_names[3] = desc; 1.1373 - strategies[3] = s; 1.1374 + if (i == 1) { 1.1375 + desc = "iBlockOpponent1"; 1.1376 + s = iBlockOpponent1; 1.1377 + } else if (i == 2) { 1.1378 + desc = "iBlockOpponent2"; 1.1379 + s = iBlockOpponent2; 1.1380 + } else 1.1381 + return; 1.1382 + strategies_names[3] = desc; 1.1383 + strategies[3] = s; 1.1384 } 1.1385 1.1386 1.1387 @@ -977,200 +959,189 @@ 1.1388 usage(const char *pname, bool full) 1.1389 { 1.1390 1.1391 - (void)fprintf(stderr, "usage: %s [-12hr | -n # | -p [OX]]\n", pname); 1.1392 - if (full) { 1.1393 - (void)fprintf(stderr, "\noptions:\n" 1.1394 - "\t-1 : select the strategy iBlockOpponent1\n" 1.1395 - "\t-2 : select the strategy iBlockOpponents2\n" 1.1396 - "\t-h : show this help\n" 1.1397 - "\t-r : t3champion use rand()\n" 1.1398 - "\t-n # : number of games you wanna play\n" 1.1399 - "\t-p P : the player you wanna play, X always begin\n" 1.1400 - ); 1.1401 - } 1.1402 - 1.1403 - exit(EXIT_FAILURE); 1.1404 + (void)fprintf(stderr, "usage: %s [-12hr | -n # | -p [OX]]\n", pname); 1.1405 + if (full) { 1.1406 + (void)fprintf(stderr, "\noptions:\n" 1.1407 + "\t-1 : select the strategy iBlockOpponent1\n" 1.1408 + "\t-2 : select the strategy iBlockOpponents2\n" 1.1409 + "\t-h : show this help\n" 1.1410 + "\t-r : t3champion use rand()\n" 1.1411 + "\t-n # : number of games you wanna play\n" 1.1412 + "\t-p P : the player you wanna play, X always begin\n"); 1.1413 + } 1.1414 + exit(EXIT_FAILURE); 1.1415 } 1.1416 1.1417 1.1418 position_t 1.1419 user_play(player_t player, state_t *board) 1.1420 { 1.1421 - unsigned int x, y; 1.1422 - unsigned int nmatch = 0; 1.1423 - position_t p; 1.1424 - char buf[BUFSIZ], *xp, *yp; 1.1425 + unsigned int x, y; 1.1426 + unsigned int nmatch = 0; 1.1427 + position_t p; 1.1428 + char buf[BUFSIZ]; 1.1429 + char *xp, *yp; 1.1430 1.1431 - while (nmatch == 0) { 1.1432 - (void)printf("---> (`q' to exit) position (x,y): "); 1.1433 - (void)fflush(stdout); /* just in case :) */ 1.1434 + while (nmatch == 0) { 1.1435 + (void)printf("---> (`q' to exit) position (x,y): "); 1.1436 + (void)fflush(stdout); /* just in case :) */ 1.1437 1.1438 - if (fgets(buf, sizeof(buf), stdin) == NULL) 1.1439 - exit(EXIT_FAILURE); 1.1440 + if (fgets(buf, sizeof(buf), stdin) == NULL) 1.1441 + exit(EXIT_FAILURE); 1.1442 1.1443 - if (strchr(buf, '\n') == NULL) { 1.1444 - /* buf didn't receive EOL, must still be on stdin */ 1.1445 - while (getc(stdin) != '\n' && !feof(stdin)) 1.1446 - continue; 1.1447 - } 1.1448 + if (strchr(buf, '\n') == NULL) { 1.1449 + /* buf didn't receive EOL, must still be on stdin */ 1.1450 + while (getc(stdin) != '\n' && !feof(stdin)) 1.1451 + continue; 1.1452 + } 1.1453 + if (strcmp(buf, "q\n") == 0) { 1.1454 + (void)printf("===> Bye!\n"); 1.1455 + exit(EXIT_SUCCESS); 1.1456 + } 1.1457 + xp = buf; 1.1458 + while (*xp != '\0' && !isdigit(*xp)) 1.1459 + xp++; 1.1460 + if (*xp == '\0') { 1.1461 + (void)printf("---> can't find any number @#$%%!\n"); 1.1462 + continue; 1.1463 + } 1.1464 + x = (int)strtoul(xp, &yp, 10); 1.1465 + assert(("strtoul", yp > xp)); 1.1466 + if (x < 1 || x > SIZE) { 1.1467 + (void)printf("---> bad X coordinate: %d\n", x); 1.1468 + continue; 1.1469 + } 1.1470 + while (*yp != '\0' && !isdigit(*yp)) 1.1471 + yp++; 1.1472 + if (*yp == '\0') { 1.1473 + (void)printf("---> can't find y\n"); 1.1474 + continue; 1.1475 + } 1.1476 + y = (int)strtoul(yp, NULL, 10); 1.1477 + if (y < 1 || y > SIZE) { 1.1478 + (void)printf("---> bad Y coordinate: %d\n", y); 1.1479 + continue; 1.1480 + } 1.1481 + p = at(x - 1, y - 1); 1.1482 + if (board[p] != EMPTY) { 1.1483 + (void)printf("---> position (%d,%d) is not empty\n", x, y); 1.1484 + continue; 1.1485 + } 1.1486 1.1487 - if (strcmp(buf, "q\n") == 0) { 1.1488 - (void)printf("===> Bye!\n"); 1.1489 - exit(EXIT_SUCCESS); 1.1490 - } 1.1491 - 1.1492 - xp = buf; 1.1493 - while (*xp != '\0' && !isdigit(*xp)) 1.1494 - xp++; 1.1495 - if (*xp == '\0') { 1.1496 - (void)printf("---> can't find any number @#$%%!\n"); 1.1497 - continue; 1.1498 - } 1.1499 - 1.1500 - x = (int)strtoul(xp, &yp, 10); 1.1501 - assert(("strtoul", yp > xp)); 1.1502 - if (x < 1 || x > SIZE) { 1.1503 - (void)printf("---> bad X coordinate: %d\n", x); 1.1504 - continue; 1.1505 - } 1.1506 - 1.1507 - while (*yp != '\0' && !isdigit(*yp)) 1.1508 - yp++; 1.1509 - if (*yp == '\0') { 1.1510 - (void)printf("---> can't find y\n"); 1.1511 - continue; 1.1512 - } 1.1513 - 1.1514 - y = (int)strtoul(yp, NULL, 10); 1.1515 - if (y < 1 || y > SIZE) { 1.1516 - (void)printf("---> bad Y coordinate: %d\n", y); 1.1517 - continue; 1.1518 - } 1.1519 - 1.1520 - p = at(x - 1, y - 1); 1.1521 - if (board[p] != EMPTY) { 1.1522 - (void)printf("---> position (%d,%d) is not empty\n", x, y); 1.1523 - continue; 1.1524 - } 1.1525 - 1.1526 - nmatch = 1; 1.1527 - } 1.1528 - 1.1529 - assert(("apply() do what you want", p == apply(player, board, 1, &p))); 1.1530 - return (p); 1.1531 + nmatch = 1; 1.1532 + } 1.1533 + assert(("apply() do what you want", p == apply(player, board, 1, &p))); 1.1534 + return (p); 1.1535 } 1.1536 1.1537 1.1538 int 1.1539 main(int argc, char *argv[]) 1.1540 { 1.1541 - int run, nrun; 1.1542 - gstatus_t winner; 1.1543 - player_t current; 1.1544 - state_t board[POSITION_MAX]; 1.1545 - position_t played; 1.1546 - strategy_t **strategy; 1.1547 - const char **strategy_name; 1.1548 - char ch; 1.1549 + int run, nrun; 1.1550 + gstatus_t winner; 1.1551 + player_t current; 1.1552 + state_t board[POSITION_MAX]; 1.1553 + position_t played; 1.1554 + strategy_t **strategy; 1.1555 + const char **strategy_name; 1.1556 + char ch; 1.1557 1.1558 - /* default game settings */ 1.1559 - bool t3champion[] = { 1.1560 - [X] = true, 1.1561 - [O] = true, 1.1562 - }; 1.1563 - nrun = 1; 1.1564 - Grandom = false; 1.1565 - while ((ch = getopt(argc, argv, "12hrn:p:")) != -1) { 1.1566 - switch ((char)ch) { 1.1567 - case '1': 1.1568 - setstrategy3(1); 1.1569 - break; 1.1570 - case '2': 1.1571 - setstrategy3(2); 1.1572 - break; 1.1573 - case 'r': 1.1574 - Grandom = true; 1.1575 - srand(time(NULL)); 1.1576 - break; 1.1577 - case 'n': 1.1578 - nrun = atoi(optarg); 1.1579 - if (nrun == 0) { 1.1580 - fprintf(stderr, "-n need a number > 0\n"); 1.1581 - return (EXIT_FAILURE); 1.1582 - } 1.1583 - break; 1.1584 - case 'p': 1.1585 - if (strcmp(optarg, "X") == 0) 1.1586 - t3champion[X] = false; 1.1587 - else if (strcmp(optarg, "O") == 0) 1.1588 - t3champion[O] = false; 1.1589 - else { 1.1590 - fprintf(stderr, "-p need X or O\n"); 1.1591 - return (EXIT_FAILURE); 1.1592 - } 1.1593 - break; 1.1594 - case 'h': 1.1595 - usage(argv[0], true); 1.1596 - /* NOTREACHED */ 1.1597 - default: 1.1598 - usage(argv[0], false); 1.1599 - /* NOTREACHED */ 1.1600 - } 1.1601 - } 1.1602 + /* default game settings */ 1.1603 + bool t3champion[] = { 1.1604 + [X] = true, 1.1605 + [O] = true, 1.1606 + }; 1.1607 1.1608 - for (run = 1; run <= nrun; run++) { 1.1609 - (void)printf("------------------------------------------\n"); 1.1610 - (void)printf("===> t3champion ready for run #%d!\n", run); 1.1611 + nrun = 1; 1.1612 + Grandom = false; 1.1613 + while ((ch = getopt(argc, argv, "12hrn:p:")) != -1) { 1.1614 + switch ((char)ch) { 1.1615 + case '1': 1.1616 + setstrategy3(1); 1.1617 + break; 1.1618 + case '2': 1.1619 + setstrategy3(2); 1.1620 + break; 1.1621 + case 'r': 1.1622 + Grandom = true; 1.1623 + srand(time(NULL)); 1.1624 + break; 1.1625 + case 'n': 1.1626 + nrun = atoi(optarg); 1.1627 + if (nrun == 0) { 1.1628 + fprintf(stderr, "-n need a number > 0\n"); 1.1629 + return (EXIT_FAILURE); 1.1630 + } 1.1631 + break; 1.1632 + case 'p': 1.1633 + if (strcmp(optarg, "X") == 0) 1.1634 + t3champion[X] = false; 1.1635 + else if (strcmp(optarg, "O") == 0) 1.1636 + t3champion[O] = false; 1.1637 + else { 1.1638 + fprintf(stderr, "-p need X or O\n"); 1.1639 + return (EXIT_FAILURE); 1.1640 + } 1.1641 + break; 1.1642 + case 'h': 1.1643 + usage(argv[0], true); 1.1644 + /* NOTREACHED */ 1.1645 + default: 1.1646 + usage(argv[0], false); 1.1647 + /* NOTREACHED */ 1.1648 + } 1.1649 + } 1.1650 1.1651 - /* game initialization */ 1.1652 - bzero(board, sizeof(board)); 1.1653 - current = X; 1.1654 + for (run = 1; run <= nrun; run++) { 1.1655 + (void)printf("------------------------------------------\n"); 1.1656 + (void)printf("===> t3champion ready for run #%d!\n", run); 1.1657 1.1658 - do { 1.1659 - (void)printf("===> board\n\n"); 1.1660 - dump_board(stdout, board); 1.1661 - check_board(board); 1.1662 - (void)printf("===> %c to play ", display[current]); 1.1663 - (void)printf("[%s]\n", t3champion[current] ? "t3champion" : "human"); 1.1664 + /* game initialization */ 1.1665 + bzero(board, sizeof(board)); 1.1666 + current = X; 1.1667 + do { 1.1668 + (void)printf("===> board\n\n"); 1.1669 + dump_board(stdout, board); 1.1670 + check_board(board); 1.1671 + (void)printf("===> %c to play ", display[current]); 1.1672 + (void)printf("[%s]\n", t3champion[current] ? "t3champion" : "human"); 1.1673 1.1674 - played = INVALID_POSITION; 1.1675 - if (t3champion[current]) { 1.1676 - strategy = strategies; 1.1677 - strategy_name = strategies_names; 1.1678 - while (played == INVALID_POSITION && strategy != NULL) { 1.1679 + played = INVALID_POSITION; 1.1680 + if (t3champion[current]) { 1.1681 + strategy = strategies; 1.1682 + strategy_name = strategies_names; 1.1683 + while (played == INVALID_POSITION && strategy != NULL) { 1.1684 #ifdef VERBOSE 1.1685 - (void)printf("---> trying strategy(%s)\n", *(strategy_name++)); 1.1686 + (void)printf("---> trying strategy(%s)\n", *(strategy_name++)); 1.1687 #endif 1.1688 - played = (*strategy)(current, board); 1.1689 - strategy++; 1.1690 - } 1.1691 - if (played == INVALID_POSITION) 1.1692 - assert(("I won't loose, even if I have bug.", false)); 1.1693 - } 1.1694 - else { 1.1695 - while (played == INVALID_POSITION) 1.1696 - played = user_play(current, board); 1.1697 - } 1.1698 + played = (*strategy)(current, board); 1.1699 + strategy++; 1.1700 + } 1.1701 + if (played == INVALID_POSITION) 1.1702 + assert(("I won't loose, even if I have bug.", false)); 1.1703 + } else { 1.1704 + while (played == INVALID_POSITION) 1.1705 + played = user_play(current, board); 1.1706 + } 1.1707 1.1708 - (void)printf("===> played (%d,%d)\n", PP(played)); 1.1709 - current = opponent(current); 1.1710 - } while (running(winner = outcome(board))); 1.1711 + (void)printf("===> played (%d,%d)\n", PP(played)); 1.1712 + current = opponent(current); 1.1713 + } while (running(winner = outcome(board))); 1.1714 1.1715 - (void)printf("===> Game Over!\n\n"); 1.1716 - dump_board(stdout, board); 1.1717 -/* override QUIET */ 1.1718 + (void)printf("===> Game Over!\n\n"); 1.1719 + dump_board(stdout, board); 1.1720 + /* override QUIET */ 1.1721 #ifdef printf 1.1722 -# undef printf 1.1723 +# undef printf 1.1724 #endif 1.1725 - (void)printf("===> "); 1.1726 - if (draw(winner)) 1.1727 - (void)printf("draw.\n"); 1.1728 - else { 1.1729 - (void)printf("%c Wins ", display[winner]); 1.1730 - (void)printf("%s\n", t3champion[winner] ? "\\o/" : ""); 1.1731 - } 1.1732 - } 1.1733 - 1.1734 - return (EXIT_SUCCESS); 1.1735 + (void)printf("===> "); 1.1736 + if (draw(winner)) 1.1737 + (void)printf("draw.\n"); 1.1738 + else { 1.1739 + (void)printf("%c Wins ", display[winner]); 1.1740 + (void)printf("%s\n", t3champion[winner] ? "\\o/" : ""); 1.1741 + } 1.1742 + } 1.1743 + return (EXIT_SUCCESS); 1.1744 } 1.1745 -