src/chess/rules.c

changeset 182
04c65336777f
parent 181
8bda076d0a16
equal deleted inserted replaced
181:8bda076d0a16 182:04c65336777f
104 104
105 Color current_color(const GameState *gamestate) { 105 Color current_color(const GameState *gamestate) {
106 return (gamestate->movecount % 2 == 0) ? WHITE : BLACK; 106 return (gamestate->movecount % 2 == 0) ? WHITE : BLACK;
107 } 107 }
108 108
109 /* MUST be called BETWEEN validating AND applying a move to work correctly */
110 static void format_move(const GameState *gamestate, Move *move) {
111 char *string = &(move->string[0]);
112
113 /* at least 8 characters should be available, wipe them out */
114 memset(string, 0, 8);
115
116 unsigned int idx;
117 if (piece_type(move->piece) == KING &&
118 abs(move->tofile-move->fromfile) == 2) {
119 /* special formats for castling */
120 if (move->tofile==fileidx('c')) {
121 memcpy(string, "O-O-O", 5);
122 idx = 5;
123 } else {
124 memcpy(string, "O-O", 3);
125 idx = 3;
126 }
127 } else {
128 /* start by notating the piece character */
129 string[0] = getpiecechr(move->piece);
130 idx = string[0] ? 1 : 0;
131
132 /* find out how many source information we do need */
133 if (piece_type(move->piece) == PAWN) {
134 if (move->capture) {
135 string[idx++] = filechr(move->fromfile);
136 }
137 } else if (piece_type(move->piece) != KING) {
138 /* resolve ambiguities, if any */
139 Move candidates[16];
140 size_t ccount;
141 if (get_real_candidates(gamestate, move->torow, move->tofile,
142 piece_color(move->piece), candidates, &ccount)) {
143 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0;
144 for (size_t i = 0 ; i < ccount ; i++) {
145 if (candidates[i].piece == move->piece) {
146 ambpiece++;
147 if (candidates[i].fromrow == move->fromrow) {
148 ambrows++;
149 }
150 if (candidates[i].fromfile == move->fromfile) {
151 ambfiles++;
152 }
153 }
154 }
155 /* neither file, nor row are ambiguous, name file */
156 if (ambpiece > 1 && ambrows == 1 && ambfiles == 1) {
157 /* this is most likely the case with Knights
158 * in diagonal opposition */
159 string[idx++] = filechr(move->fromfile);
160 } else {
161 /* ambiguous row, name file */
162 if (ambrows > 1) {
163 string[idx++] = filechr(move->fromfile);
164 }
165 /* ambiguous file, name row */
166 if (ambfiles > 1) {
167 string[idx++] = rowchr(move->fromrow);
168 }
169 }
170 }
171 }
172
173 /* capturing? */
174 if (move->capture) {
175 string[idx++] = 'x';
176 }
177
178 /* destination */
179 string[idx++] = filechr(move->tofile);
180 string[idx++] = rowchr(move->torow);
181
182 /* promotion? */
183 if (move->promotion) {
184 string[idx++] = '=';
185 string[idx++] = getpiecechr(move->promotion);
186 }
187 }
188
189 /* check? */
190 if (move->checkmate) {
191 string[idx++] = '#';
192 } else if (move->check) {
193 string[idx++] = '+';
194 }
195 }
196
197 static void calc_movetime(GameState *gamestate, Move *move) { 109 static void calc_movetime(GameState *gamestate, Move *move) {
198 /* only if move has no time info, compute it */ 110 /* only if move has no time info, compute it */
199 if (move->movetime > 0) return; 111 if (move->movetime > 0) return;
200 112
201 struct timeval curtimestamp; 113 struct timeval curtimestamp;
618 } 530 }
619 } 531 }
620 } 532 }
621 gamestate_cleanup(&simulation); 533 gamestate_cleanup(&simulation);
622 return canescape ? 1 : 2; 534 return canescape ? 1 : 2;
535 }
536
537
538 static void format_move_impl(const GameState *gamestate, Move *move) {
539 char *string = &(move->string[0]);
540
541 /* at least 8 characters should be available, wipe them out */
542 memset(string, 0, 8);
543
544 unsigned int idx;
545 if (piece_type(move->piece) == KING &&
546 abs(move->tofile-move->fromfile) == 2) {
547 /* special formats for castling */
548 if (move->tofile==fileidx('c')) {
549 memcpy(string, "O-O-O", 5);
550 idx = 5;
551 } else {
552 memcpy(string, "O-O", 3);
553 idx = 3;
554 }
555 } else {
556 /* start by notating the piece character */
557 string[0] = getpiecechr(move->piece);
558 idx = string[0] ? 1 : 0;
559
560 /* find out how many source information we do need */
561 if (piece_type(move->piece) == PAWN) {
562 if (move->capture) {
563 string[idx++] = filechr(move->fromfile);
564 }
565 } else if (piece_type(move->piece) != KING) {
566 /* resolve ambiguities, if any */
567 Move candidates[16];
568 size_t ccount;
569 if (get_real_candidates(gamestate, move->torow, move->tofile,
570 piece_color(move->piece), candidates, &ccount)) {
571 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0;
572 for (size_t i = 0 ; i < ccount ; i++) {
573 if (candidates[i].piece == move->piece) {
574 ambpiece++;
575 if (candidates[i].fromrow == move->fromrow) {
576 ambrows++;
577 }
578 if (candidates[i].fromfile == move->fromfile) {
579 ambfiles++;
580 }
581 }
582 }
583 /* neither file, nor row are ambiguous, name file */
584 if (ambpiece > 1 && ambrows == 1 && ambfiles == 1) {
585 /* this is most likely the case with Knights
586 * in diagonal opposition */
587 string[idx++] = filechr(move->fromfile);
588 } else {
589 /* ambiguous row, name file */
590 if (ambrows > 1) {
591 string[idx++] = filechr(move->fromfile);
592 }
593 /* ambiguous file, name row */
594 if (ambfiles > 1) {
595 string[idx++] = rowchr(move->fromrow);
596 }
597 }
598 }
599 }
600
601 /* capturing? */
602 if (move->capture) {
603 string[idx++] = 'x';
604 }
605
606 /* destination */
607 string[idx++] = filechr(move->tofile);
608 string[idx++] = rowchr(move->torow);
609
610 /* promotion? */
611 if (move->promotion) {
612 string[idx++] = '=';
613 string[idx++] = getpiecechr(move->promotion);
614 }
615 }
616
617 /* check? */
618 if (move->checkmate) {
619 string[idx++] = '#';
620 } else if (move->check) {
621 string[idx++] = '+';
622 }
623 }
624
625 void format_move(const GameState *gamestate, Move *move) {
626 /* correct check/checkmate flags */
627 move->check = move->checkmate = false;
628 switch (determine_check_or_checkmate(gamestate, move)) {
629 case 2: move->checkmate = true;
630 case 1: move->check = true;
631 }
632
633 /* format the move string */
634 format_move_impl(gamestate, move);
623 } 635 }
624 636
625 static int validate_move_rules(const GameState *gamestate, const Move *move) { 637 static int validate_move_rules(const GameState *gamestate, const Move *move) {
626 assert((move->piece & ~(PIECE_MASK|COLOR_MASK)) == 0); 638 assert((move->piece & ~(PIECE_MASK|COLOR_MASK)) == 0);
627 639
1160 case 1: move->check = true; 1172 case 1: move->check = true;
1161 } 1173 }
1162 } 1174 }
1163 1175
1164 /* format the move string */ 1176 /* format the move string */
1165 format_move(gamestate, move); 1177 format_move_impl(gamestate, move);
1166 } 1178 }
1167 } 1179 }
1168 return result; 1180 return result;
1169 } 1181 }
1170 1182
1171 int eval_move_lazy(const GameState *gamestate, 1183 int eval_move(const GameState *gamestate,
1172 const char *mstr, Color color, Move *move) { 1184 const char *mstr, Color color, Move *move) {
1173 return eval_move2(gamestate, mstr, color, move, true); 1185 return eval_move2(gamestate, mstr, color, move, true);
1174 } 1186 }
1175 1187
1176 int eval_move(const GameState *gamestate, 1188 int eval_move_strict(const GameState *gamestate,
1177 const char *mstr, Color color, Move *move) { 1189 const char *mstr, Color color, Move *move) {
1178 return eval_move2(gamestate, mstr, color, move, false); 1190 return eval_move2(gamestate, mstr, color, move, false);
1179 } 1191 }
1180 1192
1181 int check_move(const char *mstr, Color color) { 1193 int check_move(const char *mstr, Color color) {

mercurial