src/chess/rules.c

changeset 66
f5cc75565f7c
parent 64
4eda5df55f86
child 67
c76e46970a59
equal deleted inserted replaced
65:dcc5bd2c56c0 66:f5cc75565f7c
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? */
142 } 152 }
143 } 153 }
144 154
145 /* check? */ 155 /* check? */
146 if (move->check) { 156 if (move->check) {
147 /* works only, if this function is called when applying the move */ 157 // TODO: does not work, because checkmate is not set when format_move is called
148 string[idx++] = gamestate->checkmate?'#':'+'; 158 string[idx++] = gamestate->checkmate?'#':'+';
149 } 159 }
150 } 160 }
151 161
152 static void addmove(GameState* gamestate, Move *move) { 162 static void addmove(GameState* gamestate, Move *move) {
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) {

mercurial