| 32 #include "rook.h" |
32 #include "rook.h" |
| 33 #include "knight.h" |
33 #include "knight.h" |
| 34 #include "bishop.h" |
34 #include "bishop.h" |
| 35 #include "queen.h" |
35 #include "queen.h" |
| 36 #include "king.h" |
36 #include "king.h" |
| |
37 #include "fen.h" |
| 37 |
38 |
| 38 #include <string.h> |
39 #include <string.h> |
| 39 #include <stdio.h> |
40 #include <stdio.h> |
| 40 #include <stdlib.h> |
41 #include <stdlib.h> |
| 41 #include <sys/time.h> |
42 #include <sys/time.h> |
| 42 |
43 |
| 43 void gamestate_init(GameState *gamestate) { |
44 void gamestate_init(GameState *gamestate) { |
| 44 memset(gamestate, 0, sizeof(GameState)); |
45 memset(gamestate, 0, sizeof(GameState)); |
| 45 |
46 |
| |
47 // TODO: implement feature - game can be started from arbitrary position |
| 46 Board initboard = { |
48 Board initboard = { |
| 47 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
49 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
| 48 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
50 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
| 49 {0, 0, 0, 0, 0, 0, 0, 0}, |
51 {0, 0, 0, 0, 0, 0, 0, 0}, |
| 50 {0, 0, 0, 0, 0, 0, 0, 0}, |
52 {0, 0, 0, 0, 0, 0, 0, 0}, |
| 52 {0, 0, 0, 0, 0, 0, 0, 0}, |
54 {0, 0, 0, 0, 0, 0, 0, 0}, |
| 53 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, |
55 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, |
| 54 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
56 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} |
| 55 }; |
57 }; |
| 56 memcpy(gamestate->board, initboard, sizeof(Board)); |
58 memcpy(gamestate->board, initboard, sizeof(Board)); |
| |
59 char fen[FEN_MAX_LENGTH]; |
| |
60 fen_compute(fen, gamestate); |
| |
61 gamestate->fen_start = strdup(fen); |
| 57 } |
62 } |
| 58 |
63 |
| 59 void gamestate_cleanup(GameState *gamestate) { |
64 void gamestate_cleanup(GameState *gamestate) { |
| 60 free(gamestate->moves); |
65 free(gamestate->moves); |
| |
66 free(gamestate->fen_start); |
| |
67 for (unsigned i = 0 ; i < gamestate->movecount ; i++) { |
| |
68 free(gamestate->fen[i]); |
| |
69 } |
| |
70 free(gamestate->fen); |
| 61 gamestate->movecount = gamestate->movecapacity = 0; |
71 gamestate->movecount = gamestate->movecapacity = 0; |
| 62 } |
72 } |
| 63 |
73 |
| 64 static GameState gamestate_copy_sim(GameState *gamestate) { |
74 static GameState gamestate_copy_sim(GameState *gamestate) { |
| 65 GameState simulation = *gamestate; |
75 GameState simulation = *gamestate; |
| 66 |
76 |
| 67 // create a new move list for the simulation |
77 /* create new move and position lists for the simulation */ |
| 68 simulation.movecapacity = 4; |
78 simulation.movecapacity = 4; |
| 69 simulation.movecount = 0; |
79 simulation.movecount = 0; |
| 70 simulation.moves = malloc(4 * sizeof(Move)); |
80 simulation.moves = malloc(4 * sizeof(Move)); |
| 71 |
81 simulation.fen = malloc(4 * sizeof(char*)); |
| 72 // copy the most recent move if a move was played |
82 |
| |
83 /* copy the most recent move and position if a move was played */ |
| 73 if (gamestate->movecount > 0) { |
84 if (gamestate->movecount > 0) { |
| |
85 simulation.fen_start = strdup(gamestate->movecount == 1 ? |
| |
86 gamestate->fen_start : gamestate->fen[gamestate->movecount - 2]); |
| 74 simulation.moves[0] = last_move(gamestate); |
87 simulation.moves[0] = last_move(gamestate); |
| |
88 simulation.fen[0] = strdup(gamestate->fen[gamestate->movecount - 1]); |
| 75 simulation.movecount++; |
89 simulation.movecount++; |
| |
90 } else { |
| |
91 simulation.fen_start = strdup(gamestate->fen_start); |
| 76 } |
92 } |
| 77 |
93 |
| 78 return simulation; |
94 return simulation; |
| 79 } |
95 } |
| 80 |
96 |
| 197 move->movetime.tv_usec = (int32_t) micros; |
213 move->movetime.tv_usec = (int32_t) micros; |
| 198 } |
214 } |
| 199 } |
215 } |
| 200 } |
216 } |
| 201 |
217 |
| 202 static void addmove(GameState* gamestate, Move *data) { |
|
| 203 if (gamestate->movecount == gamestate->movecapacity) { |
|
| 204 gamestate->movecapacity += 64; /* 32 more full moves */ |
|
| 205 gamestate->moves = realloc(gamestate->moves, |
|
| 206 gamestate->movecapacity * sizeof(Move)); |
|
| 207 } |
|
| 208 |
|
| 209 Move *move = &gamestate->moves[gamestate->movecount]; |
|
| 210 *move = *data; |
|
| 211 |
|
| 212 /* only if move has no time info, compute it */ |
|
| 213 if (move->movetime.tv_sec == 0 && move->movetime.tv_usec == 0) { |
|
| 214 calc_movetime(gamestate, move); |
|
| 215 } |
|
| 216 |
|
| 217 /* important: only "add" the move after calculating the time! */ |
|
| 218 gamestate->movecount++; |
|
| 219 } |
|
| 220 |
|
| 221 char getpiecechr(uint8_t piece) { |
218 char getpiecechr(uint8_t piece) { |
| 222 switch (piece & PIECE_MASK) { |
219 switch (piece & PIECE_MASK) { |
| 223 case ROOK: return 'R'; |
220 case ROOK: return 'R'; |
| 224 case KNIGHT: return 'N'; |
221 case KNIGHT: return 'N'; |
| 225 case BISHOP: return 'B'; |
222 case BISHOP: return 'B'; |
| 312 gamestate->board[move->torow][fileidx('a')] = 0; |
309 gamestate->board[move->torow][fileidx('a')] = 0; |
| 313 gamestate->board[move->torow][fileidx('d')] = color|ROOK; |
310 gamestate->board[move->torow][fileidx('d')] = color|ROOK; |
| 314 } |
311 } |
| 315 } |
312 } |
| 316 |
313 |
| 317 /* add move, even in simulation (checkmate test needs it) */ |
314 /* add move to the moves array and the new position to the FEN array */ |
| 318 addmove(gamestate, move); |
315 if (gamestate->movecount == gamestate->movecapacity) { |
| |
316 gamestate->movecapacity += 64; /* 32 more full moves */ |
| |
317 gamestate->moves = realloc(gamestate->moves, |
| |
318 gamestate->movecapacity * sizeof(Move)); |
| |
319 gamestate->fen = realloc(gamestate->fen, |
| |
320 gamestate->movecapacity * sizeof(char*)); |
| |
321 } |
| |
322 |
| |
323 /* copy the move data into the game's move array */ |
| |
324 Move *melem = &gamestate->moves[gamestate->movecount]; |
| |
325 *melem = *move; |
| |
326 |
| |
327 /* calculate the FEN and store it in the FEN array */ |
| |
328 char fen[FEN_MAX_LENGTH]; |
| |
329 fen_compute(fen, gamestate); |
| |
330 gamestate->fen[gamestate->movecount] = strdup(fen); |
| |
331 |
| |
332 /* only if move has no time info, compute it */ |
| |
333 if (melem->movetime.tv_sec == 0 && melem->movetime.tv_usec == 0) { |
| |
334 calc_movetime(gamestate, melem); |
| |
335 } |
| |
336 |
| |
337 /* important: only "add" the move after calculating the time! */ |
| |
338 gamestate->movecount++; |
| 319 } |
339 } |
| 320 |
340 |
| 321 void apply_move(GameState *gamestate, Move *move) { |
341 void apply_move(GameState *gamestate, Move *move) { |
| 322 apply_move_impl(gamestate, move, false); |
342 apply_move_impl(gamestate, move, false); |
| 323 } |
343 } |