| 43 #include <assert.h> |
43 #include <assert.h> |
| 44 |
44 |
| 45 void gamestate_init(GameState *gamestate) { |
45 void gamestate_init(GameState *gamestate) { |
| 46 memset(gamestate, 0, sizeof(GameState)); |
46 memset(gamestate, 0, sizeof(GameState)); |
| 47 |
47 |
| 48 // TODO: implement feature - game can be started from arbitrary position |
|
| 49 Board initboard = { |
48 Board initboard = { |
| 50 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
49 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, |
| 51 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
50 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, |
| 52 {0, 0, 0, 0, 0, 0, 0, 0}, |
51 {0, 0, 0, 0, 0, 0, 0, 0}, |
| 53 {0, 0, 0, 0, 0, 0, 0, 0}, |
52 {0, 0, 0, 0, 0, 0, 0, 0}, |
| 97 simulation.movecount++; |
96 simulation.movecount++; |
| 98 } else { |
97 } else { |
| 99 simulation.fen_start = strdup(gamestate->fen_start); |
98 simulation.fen_start = strdup(gamestate->fen_start); |
| 100 } |
99 } |
| 101 |
100 |
| |
101 // TODO: think about setting move_start to a reasonable value |
| |
102 |
| 102 return simulation; |
103 return simulation; |
| 103 } |
|
| 104 |
|
| 105 Color current_color(const GameState *gamestate) { |
|
| 106 // TODO: better would be an API that returns the correct number |
|
| 107 unsigned mc = gamestate->movecount + gamestate->move_start; |
|
| 108 return (mc % 2 == 0) ? WHITE : BLACK; |
|
| 109 } |
104 } |
| 110 |
105 |
| 111 static void calc_movetime(GameState *gamestate, Move *move) { |
106 static void calc_movetime(GameState *gamestate, Move *move) { |
| 112 /* only if move has no time info, compute it */ |
107 /* only if move has no time info, compute it */ |
| 113 if (move->movetime > 0) return; |
108 if (move->movetime > 0) return; |
| 148 return 0; |
143 return 0; |
| 149 } |
144 } |
| 150 } |
145 } |
| 151 |
146 |
| 152 static bool check_stalemate(const GameState *gamestate) { |
147 static bool check_stalemate(const GameState *gamestate) { |
| 153 Color next_player = gamestate->movecount % 2 == 0 ? WHITE : BLACK; |
148 Color next_player = current_color(gamestate); |
| 154 |
149 |
| 155 /* scan the board for pieces of the next player's color */ |
150 /* scan the board for pieces of the next player's color */ |
| 156 Move moves[QUEEN_MOVES_MAX]; |
151 Move moves[QUEEN_MOVES_MAX]; |
| 157 for (Rank r = 0; r < 8; r++) { |
152 for (Rank r = 0; r < 8; r++) { |
| 158 for (File f = 0; f < 8; f++) { |
153 for (File f = 0; f < 8; f++) { |
| 434 void gamestate_at_move(const GameState *gamestate, |
429 void gamestate_at_move(const GameState *gamestate, |
| 435 unsigned move_number, GameState *replay) { |
430 unsigned move_number, GameState *replay) { |
| 436 gamestate_init(replay); |
431 gamestate_init(replay); |
| 437 memcpy(&replay->info, &gamestate->info, sizeof(GameInfo)); |
432 memcpy(&replay->info, &gamestate->info, sizeof(GameInfo)); |
| 438 replay->review = true; |
433 replay->review = true; |
| |
434 // TODO: respect move_start offset |
| 439 if (move_number > gamestate->movecount) { |
435 if (move_number > gamestate->movecount) { |
| 440 move_number = gamestate->movecount; |
436 move_number = gamestate->movecount; |
| 441 } |
437 } |
| 442 for (unsigned i = 0 ; i < move_number ; i++) { |
438 for (unsigned i = 0 ; i < move_number ; i++) { |
| 443 apply_move(replay, &(gamestate->moves[i])); |
439 apply_move(replay, &(gamestate->moves[i])); |
| 1260 } |
1256 } |
| 1261 return false; |
1257 return false; |
| 1262 } |
1258 } |
| 1263 |
1259 |
| 1264 uint16_t remaining_movetime(const GameState *gamestate, Color color) { |
1260 uint16_t remaining_movetime(const GameState *gamestate, Color color) { |
| |
1261 // TODO: we probably need to add the move_start offset here... |
| 1265 unsigned move_number = gamestate->movecount; |
1262 unsigned move_number = gamestate->movecount; |
| 1266 if (color == BLACK) { |
1263 if (color == BLACK) { |
| 1267 move_number |= 1; |
1264 move_number |= 1; |
| 1268 } else { |
1265 } else { |
| 1269 move_number = (move_number + 1) & ~1; |
1266 move_number = (move_number + 1) & ~1; |
| 1270 } |
1267 } |
| 1271 return remaining_movetime2(gamestate, move_number); |
1268 return remaining_movetime2(gamestate, move_number); |
| 1272 } |
1269 } |
| 1273 |
1270 |
| 1274 uint16_t remaining_movetime2(const GameState *gamestate, unsigned move_number) { |
1271 uint16_t remaining_movetime2(const GameState *gamestate, unsigned move_number) { |
| |
1272 // TODO: ... and remove / consider the move_start offset here |
| 1275 if (!gamestate->info.timecontrol) { |
1273 if (!gamestate->info.timecontrol) { |
| 1276 return 0; |
1274 return 0; |
| 1277 } |
1275 } |
| 1278 |
1276 |
| 1279 unsigned total_time = gamestate->info.time; |
1277 unsigned total_time = gamestate->info.time; |