src/chess/rules.c

changeset 136
1a84ee6b4bf0
parent 135
114e764fbae5
child 137
43d1b3c33369
equal deleted inserted replaced
135:114e764fbae5 136:1a84ee6b4bf0
410 Move simmove = *move; 410 Move simmove = *move;
411 apply_move_impl(&simulation, &simmove, true); 411 apply_move_impl(&simulation, &simmove, true);
412 412
413 /* find kings for check validation */ 413 /* find kings for check validation */
414 uint8_t piececolor = (move->piece & COLOR_MASK); 414 uint8_t piececolor = (move->piece & COLOR_MASK);
415 uint8_t oppcolor = opponent_color(piececolor);
415 416
416 uint8_t mykingfile = 0, mykingrow = 0, opkingfile = 0, opkingrow = 0; 417 uint8_t mykingfile = 0, mykingrow = 0, opkingfile = 0, opkingrow = 0;
417 for (uint8_t row = 0 ; row < 8 ; row++) { 418 for (uint8_t row = 0 ; row < 8 ; row++) {
418 for (uint8_t file = 0 ; file < 8 ; file++) { 419 for (uint8_t file = 0 ; file < 8 ; file++) {
419 if (simulation.board[row][file] == 420 if (simulation.board[row][file] ==
427 } 428 }
428 } 429 }
429 } 430 }
430 431
431 /* don't move into or stay in check position */ 432 /* don't move into or stay in check position */
432 if (is_covered(&simulation, mykingrow, mykingfile, 433 if (is_covered(&simulation, mykingrow, mykingfile, oppcolor)) {
433 opponent_color(piececolor))) {
434
435 gamestate_cleanup(&simulation); 434 gamestate_cleanup(&simulation);
436 if ((move->piece & PIECE_MASK) == KING) { 435 if ((move->piece & PIECE_MASK) == KING) {
437 return KING_MOVES_INTO_CHECK; 436 return KING_MOVES_INTO_CHECK;
438 } else { 437 } else {
439 /* last move is always not null in this case */ 438 /* last move is always not null in this case */
453 bool canescape = false; 452 bool canescape = false;
454 for (int dr = -1 ; dr <= 1 && !canescape ; dr++) { 453 for (int dr = -1 ; dr <= 1 && !canescape ; dr++) {
455 for (int df = -1 ; df <= 1 && !canescape ; df++) { 454 for (int df = -1 ; df <= 1 && !canescape ; df++) {
456 if (!(dr == 0 && df == 0) && 455 if (!(dr == 0 && df == 0) &&
457 isidx(opkingrow + dr) && isidx(opkingfile + df)) { 456 isidx(opkingrow + dr) && isidx(opkingfile + df)) {
458 457 /* escape field neither occupied nor covered */
459 /* escape field neither blocked nor covered */ 458 canescape =
460 if ((simulation.board[opkingrow + dr][opkingfile + df] 459 !simulation.board[opkingrow + dr][opkingfile + df] &&
461 & COLOR_MASK) != opponent_color(piececolor)) { 460 !is_covered(&simulation,
462 canescape |= !is_covered(&simulation,
463 opkingrow + dr, opkingfile + df, piececolor); 461 opkingrow + dr, opkingfile + df, piececolor);
464 }
465 } 462 }
466 } 463 }
467 } 464 }
468 /* can't escape, can he capture? */ 465 /* can't escape, can he capture? */
469 if (!canescape && threatcount == 1) { 466 if (!canescape && threatcount == 1) {
470 canescape = is_attacked(&simulation, threats[0].fromrow, 467 /* TODO: this is bugged - we actually need distinguish two cases
471 threats[0].fromfile, opponent_color(piececolor)); 468 * 1. another piece can rescue the king
469 * (this is what is implemented now)
470 * 2. the king can kill the attacker
471 * - in this case, the threatcount is irrelevant, because
472 * the king moves out of the current threat
473 * - we must verify that the king can actually kill the
474 * attacker without running into a new check
475 */
476 canescape = is_attacked(&simulation,
477 threats[0].fromrow, threats[0].fromfile, oppcolor);
472 } 478 }
473 479
474 /* can't capture, can he block? */ 480 /* can't capture, can he block? */
475 if (!canescape && threatcount == 1) { 481 if (!canescape && threatcount == 1) {
476 Move *threat = &(threats[0]); 482 Move *threat = &(threats[0]);
484 int d = threat->tofile > threat->fromfile ? 1 : -1; 490 int d = threat->tofile > threat->fromfile ? 1 : -1;
485 uint8_t file = threat->fromfile; 491 uint8_t file = threat->fromfile;
486 while (!canescape && file != threat->tofile - d) { 492 while (!canescape && file != threat->tofile - d) {
487 file += d; 493 file += d;
488 canescape |= is_protected(&simulation, 494 canescape |= is_protected(&simulation,
489 threat->torow, file, opponent_color(piececolor)); 495 threat->torow, file, oppcolor);
490 } 496 }
491 } else if (threat->fromfile == threat->tofile) { 497 } else if (threat->fromfile == threat->tofile) {
492 /* rook aspect (on file) */ 498 /* rook aspect (on file) */
493 int d = threat->torow > threat->fromrow ? 1 : -1; 499 int d = threat->torow > threat->fromrow ? 1 : -1;
494 uint8_t row = threat->fromrow; 500 uint8_t row = threat->fromrow;
495 while (!canescape && row != threat->torow - d) { 501 while (!canescape && row != threat->torow - d) {
496 row += d; 502 row += d;
497 canescape |= is_protected(&simulation, 503 canescape |= is_protected(&simulation,
498 row, threat->tofile, opponent_color(piececolor)); 504 row, threat->tofile, oppcolor);
499 } 505 }
500 } else { 506 } else {
501 /* bishop aspect */ 507 /* bishop aspect */
502 int dr = threat->torow > threat->fromrow ? 1 : -1; 508 int dr = threat->torow > threat->fromrow ? 1 : -1;
503 int df = threat->tofile > threat->fromfile ? 1 : -1; 509 int df = threat->tofile > threat->fromfile ? 1 : -1;
507 while (!canescape && file != threat->tofile - df 513 while (!canescape && file != threat->tofile - df
508 && row != threat->torow - dr) { 514 && row != threat->torow - dr) {
509 row += dr; 515 row += dr;
510 file += df; 516 file += df;
511 canescape |= is_protected(&simulation, row, file, 517 canescape |= is_protected(&simulation, row, file,
512 opponent_color(piececolor)); 518 oppcolor);
513 } 519 }
514 } 520 }
515 } 521 }
516 } 522 }
517 523
518 if (!canescape) { 524 if (!canescape) {
519 gamestate->checkmate = 1; 525 gamestate->checkmate = true;
520 } 526 }
521 } 527 }
522 528
523 gamestate_cleanup(&simulation); 529 gamestate_cleanup(&simulation);
524 530

mercurial