33 #include <stdlib.h> |
33 #include <stdlib.h> |
34 #include <sys/time.h> |
34 #include <sys/time.h> |
35 |
35 |
36 static GameState gamestate_copy_sim(GameState *gamestate) { |
36 static GameState gamestate_copy_sim(GameState *gamestate) { |
37 GameState simulation = *gamestate; |
37 GameState simulation = *gamestate; |
|
38 simulation.movecount = 0; /* simulations do not count moves */ |
38 if (simulation.lastmove) { |
39 if (simulation.lastmove) { |
39 MoveList *lastmovecopy = malloc(sizeof(MoveList)); |
40 MoveList *lastmovecopy = malloc(sizeof(MoveList)); |
40 *lastmovecopy = *(simulation.lastmove); |
41 *lastmovecopy = *(simulation.lastmove); |
41 simulation.movelist = simulation.lastmove = lastmovecopy; |
42 simulation.movelist = simulation.lastmove = lastmovecopy; |
42 } |
43 } |
68 elem = elem->next; |
69 elem = elem->next; |
69 free(cur); |
70 free(cur); |
70 }; |
71 }; |
71 } |
72 } |
72 |
73 |
73 /* MUST be called IMMEDIATLY after applying a move to work correctly */ |
74 /* MUST be called BEFORE applying a move to work correctly */ |
74 static void format_move(GameState *gamestate, Move *move) { |
75 static void format_move(GameState *gamestate, Move *move) { |
75 char *string = move->string; |
76 char *string = &(move->string[0]); |
76 |
77 |
77 /* at least 8 characters should be available, wipe them out */ |
78 /* at least 8 characters should be available, wipe them out */ |
78 memset(string, 0, 8); |
79 memset(string, 0, 8); |
79 |
80 |
80 unsigned int idx; |
81 unsigned int idx; |
101 } |
102 } |
102 } else if (piece != KING) { |
103 } else if (piece != KING) { |
103 /* resolve ambiguities, if any */ |
104 /* resolve ambiguities, if any */ |
104 Move threats[16]; |
105 Move threats[16]; |
105 uint8_t threatcount; |
106 uint8_t threatcount; |
106 get_real_threats(gamestate, move->torow, move->tofile, |
107 if (get_threats(gamestate, move->torow, move->tofile, |
107 move->piece&COLOR_MASK, threats, &threatcount); |
108 move->piece&COLOR_MASK, threats, &threatcount)) { |
108 if (threatcount > 1) { |
109 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0; |
109 int ambrows = 0, ambfiles = 0; |
|
110 for (uint8_t i = 0 ; i < threatcount ; i++) { |
110 for (uint8_t i = 0 ; i < threatcount ; i++) { |
111 if (threats[i].fromrow == move->fromrow) { |
111 if (threats[i].piece == move->piece) { |
112 ambrows++; |
112 ambpiece++; |
113 } |
113 if (threats[i].fromrow == move->fromrow) { |
114 if (threats[i].fromfile == move->fromfile) { |
114 ambrows++; |
115 ambfiles++; |
115 } |
|
116 if (threats[i].fromfile == move->fromfile) { |
|
117 ambfiles++; |
|
118 } |
116 } |
119 } |
117 } |
120 } |
118 /* ambiguous row, name file */ |
121 /* neither file, nor row are ambiguous, name file */ |
119 if (ambrows > 1) { |
122 if (ambpiece > 1 && ambrows == 1 && ambfiles == 1) { |
|
123 /* this is most likely the case with Knights |
|
124 * in diagonal opposition */ |
120 string[idx++] = filechr(move->fromfile); |
125 string[idx++] = filechr(move->fromfile); |
121 } |
126 } else { |
122 /* ambiguous file, name row */ |
127 /* ambiguous row, name file */ |
123 if (ambfiles > 1) { |
128 if (ambrows > 1) { |
124 string[idx++] = filechr(move->fromrow); |
129 string[idx++] = filechr(move->fromfile); |
|
130 } |
|
131 /* ambiguous file, name row */ |
|
132 if (ambfiles > 1) { |
|
133 string[idx++] = filechr(move->fromrow); |
|
134 } |
125 } |
135 } |
126 } |
136 } |
127 } |
137 } |
128 |
138 |
129 /* capturing? */ |
139 /* capturing? */ |
205 default: return 0; |
215 default: return 0; |
206 } |
216 } |
207 } |
217 } |
208 |
218 |
209 static void apply_move_impl(GameState *gamestate, Move *move, _Bool simulate) { |
219 static void apply_move_impl(GameState *gamestate, Move *move, _Bool simulate) { |
|
220 /* format move before moving (s.t. ambiguities can be resolved) */ |
|
221 if (!simulate) { |
|
222 if (!move->string[0]) { |
|
223 format_move(gamestate, move); |
|
224 } |
|
225 } |
|
226 |
210 uint8_t piece = move->piece & PIECE_MASK; |
227 uint8_t piece = move->piece & PIECE_MASK; |
211 uint8_t color = move->piece & COLOR_MASK; |
228 uint8_t color = move->piece & COLOR_MASK; |
212 |
229 |
213 /* en passant capture */ |
230 /* en passant capture */ |
214 if (move->capture && piece == PAWN && |
231 if (move->capture && piece == PAWN && |
237 mdst(gamestate->board, move) = move->piece; |
254 mdst(gamestate->board, move) = move->piece; |
238 } |
255 } |
239 |
256 |
240 /* castling */ |
257 /* castling */ |
241 if (piece == KING && move->fromfile == fileidx('e')) { |
258 if (piece == KING && move->fromfile == fileidx('e')) { |
242 |
|
243 if (move->tofile == fileidx('g')) { |
259 if (move->tofile == fileidx('g')) { |
244 gamestate->board[move->torow][fileidx('h')] = 0; |
260 gamestate->board[move->torow][fileidx('h')] = 0; |
245 gamestate->board[move->torow][fileidx('f')] = color|ROOK; |
261 gamestate->board[move->torow][fileidx('f')] = color|ROOK; |
246 } else if (move->tofile == fileidx('c')) { |
262 } else if (move->tofile == fileidx('c')) { |
247 gamestate->board[move->torow][fileidx('a')] = 0; |
263 gamestate->board[move->torow][fileidx('a')] = 0; |
248 gamestate->board[move->torow][fileidx('d')] = color|ROOK; |
264 gamestate->board[move->torow][fileidx('d')] = color|ROOK; |
249 } |
265 } |
250 } |
266 } |
251 |
267 |
252 if (!simulate) { |
|
253 if (!move->string[0]) { |
|
254 format_move(gamestate, move); |
|
255 } |
|
256 } |
|
257 /* add move, even in simulation (checkmate test needs it) */ |
268 /* add move, even in simulation (checkmate test needs it) */ |
258 addmove(gamestate, move); |
269 addmove(gamestate, move); |
259 } |
270 } |
260 |
271 |
261 void apply_move(GameState *gamestate, Move *move) { |
272 void apply_move(GameState *gamestate, Move *move) { |