@@ -53,34 +53,34 @@ discard block |
||
| 53 | 53 | class ChessGame { |
| 54 | 54 | |
| 55 | 55 | /** |
| 56 | - * Indicates whether object is valid. |
|
| 57 | - * |
|
| 58 | - * If empty string (''), indicates this is a valid object; otherwise contains an error message. |
|
| 56 | + * Indicates whether object is valid. |
|
| 57 | + * |
|
| 58 | + * If empty string (''), indicates this is a valid object; otherwise contains an error message. |
|
| 59 | 59 | * Should be checked after creating an instance of this class. |
| 60 | - * |
|
| 61 | - * @var string $error |
|
| 62 | - */ |
|
| 60 | + * |
|
| 61 | + * @var string $error |
|
| 62 | + */ |
|
| 63 | 63 | var $error; |
| 64 | 64 | |
| 65 | 65 | /** |
| 66 | 66 | * gamestate |
| 67 | 67 | * |
| 68 | - * The game state is represented as an array with the following elements: |
|
| 69 | - * |
|
| 70 | - * - 'fen_piece_placement' |
|
| 71 | - * - 'fen_active_color' |
|
| 72 | - * - 'fen_castling_availability' |
|
| 73 | - * - 'fen_en_passant_target_square' |
|
| 74 | - * - 'fen_halfmove_clock' |
|
| 75 | - * - 'fen_fullmove_number' |
|
| 76 | - * - 'pgn_result' |
|
| 77 | - * - 'pgn_fen' |
|
| 78 | - * - 'pgn_movetext' |
|
| 79 | - * |
|
| 80 | - * The elements prefixed with 'fen_' are standard Forsyth-Edwards Notation (FEN) elements, |
|
| 81 | - * and the elements prefixed with 'pgn_' are standard Portable Game Notation (PGN) elements. |
|
| 82 | - * |
|
| 83 | - * Each element is a string. |
|
| 68 | + * The game state is represented as an array with the following elements: |
|
| 69 | + * |
|
| 70 | + * - 'fen_piece_placement' |
|
| 71 | + * - 'fen_active_color' |
|
| 72 | + * - 'fen_castling_availability' |
|
| 73 | + * - 'fen_en_passant_target_square' |
|
| 74 | + * - 'fen_halfmove_clock' |
|
| 75 | + * - 'fen_fullmove_number' |
|
| 76 | + * - 'pgn_result' |
|
| 77 | + * - 'pgn_fen' |
|
| 78 | + * - 'pgn_movetext' |
|
| 79 | + * |
|
| 80 | + * The elements prefixed with 'fen_' are standard Forsyth-Edwards Notation (FEN) elements, |
|
| 81 | + * and the elements prefixed with 'pgn_' are standard Portable Game Notation (PGN) elements. |
|
| 82 | + * |
|
| 83 | + * Each element is a string. |
|
| 84 | 84 | * |
| 85 | 85 | * @var array $gamestate |
| 86 | 86 | */ |
@@ -89,23 +89,23 @@ discard block |
||
| 89 | 89 | /** |
| 90 | 90 | * board |
| 91 | 91 | * |
| 92 | - * A 64-element array, constructed from fen_piece_placement, is used for handling moves. |
|
| 93 | - * Its indices are related to the standard tile coordinates as follows: |
|
| 94 | - * |
|
| 92 | + * A 64-element array, constructed from fen_piece_placement, is used for handling moves. |
|
| 93 | + * Its indices are related to the standard tile coordinates as follows: |
|
| 94 | + * |
|
| 95 | 95 | * <pre> |
| 96 | - * 8 | 56 57 58 59 60 61 62 63 |
|
| 97 | - * 7 | 48 49 50 51 52 53 54 55 |
|
| 98 | - * 6 | 40 41 42 43 44 45 46 47 |
|
| 99 | - * 5 | 32 33 34 35 36 37 38 39 |
|
| 100 | - * 4 | 24 25 26 27 28 29 30 31 |
|
| 101 | - * 3 | 16 17 18 19 20 21 22 23 |
|
| 102 | - * 2 | 8 9 10 11 12 13 14 15 |
|
| 103 | - * 1 | 0 1 2 3 4 5 6 7 |
|
| 104 | - * ------------------------ |
|
| 105 | - * a b c d e f g h |
|
| 96 | + * 8 | 56 57 58 59 60 61 62 63 |
|
| 97 | + * 7 | 48 49 50 51 52 53 54 55 |
|
| 98 | + * 6 | 40 41 42 43 44 45 46 47 |
|
| 99 | + * 5 | 32 33 34 35 36 37 38 39 |
|
| 100 | + * 4 | 24 25 26 27 28 29 30 31 |
|
| 101 | + * 3 | 16 17 18 19 20 21 22 23 |
|
| 102 | + * 2 | 8 9 10 11 12 13 14 15 |
|
| 103 | + * 1 | 0 1 2 3 4 5 6 7 |
|
| 104 | + * ------------------------ |
|
| 105 | + * a b c d e f g h |
|
| 106 | 106 | * </pre> |
| 107 | - * |
|
| 108 | - * For example, $board[17] is tile b3 and $board[55] is tile h7. |
|
| 107 | + * |
|
| 108 | + * For example, $board[17] is tile b3 and $board[55] is tile h7. |
|
| 109 | 109 | * |
| 110 | 110 | * @var array $board |
| 111 | 111 | */ |
@@ -131,13 +131,13 @@ discard block |
||
| 131 | 131 | |
| 132 | 132 | |
| 133 | 133 | /** |
| 134 | - * updated by handleMove, not used now but might be used in future |
|
| 134 | + * updated by handleMove, not used now but might be used in future |
|
| 135 | 135 | * @var string $last_move |
| 136 | 136 | */ |
| 137 | 137 | var $last_move; |
| 138 | 138 | |
| 139 | 139 | /** |
| 140 | - * updated by handleMove, not used now but might be used in future |
|
| 140 | + * updated by handleMove, not used now but might be used in future |
|
| 141 | 141 | * @var string $captured_piece |
| 142 | 142 | */ |
| 143 | 143 | var $captured_piece; |
@@ -455,65 +455,65 @@ discard block |
||
| 455 | 455 | /* DEBUG: echo "$fx,$fy --> $dx,$dy: "; */ |
| 456 | 456 | switch ( $fig ) |
| 457 | 457 | { |
| 458 | - /* knight */ |
|
| 459 | - case 'N': |
|
| 460 | - if ( abs($fx-$dx)==1 && abs($fy-$dy)==2 ) |
|
| 461 | - $result = 1; |
|
| 462 | - if ( abs($fy-$dy)==1 && abs($fx-$dx)==2 ) |
|
| 463 | - $result = 1; |
|
| 464 | - break; |
|
| 465 | - /* bishop */ |
|
| 466 | - case 'B': |
|
| 467 | - if ( abs($fx-$dx) != abs($fy-$dy) ) |
|
| 468 | - break; |
|
| 469 | - if ( $dy < $fy ) $change = -8; else $change = 8; |
|
| 470 | - if ( $dx < $fx ) $change -= 1; else $change += 1; |
|
| 471 | - if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 472 | - $result = 1; |
|
| 473 | - break; |
|
| 474 | - /* rook */ |
|
| 475 | - case 'R': |
|
| 476 | - if ( $fx!=$dx && $fy!=$dy ) |
|
| 477 | - break; |
|
| 478 | - if ( $fx==$dx ) |
|
| 479 | - { |
|
| 480 | - if ( $dy<$fy ) $change = -8; else $change = 8; |
|
| 481 | - } |
|
| 482 | - else { |
|
| 483 | - if ( $dx<$fx ) $change = -1; else $change = 1; |
|
| 484 | - } |
|
| 485 | - if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 486 | - $result = 1; |
|
| 487 | - break; |
|
| 488 | - /* queen */ |
|
| 489 | - case 'Q': |
|
| 490 | - if ( abs($fx-$dx) != abs($fy-$dy) && $fx!=$dx && $fy!=$dy ) |
|
| 491 | - break; |
|
| 492 | - if ( abs($fx-$dx) == abs($fy-$dy) ) |
|
| 493 | - { |
|
| 494 | - if ( $dy < $fy ) $change = -8; else $change = 8; |
|
| 495 | - if ( $dx < $fx ) $change -= 1; else $change += 1; |
|
| 496 | - } |
|
| 497 | - else if ( $fx==$dx ) { |
|
| 498 | - if ( $dy<$fy ) $change = -8; else $change = 8; |
|
| 499 | - } |
|
| 500 | - else |
|
| 501 | - { |
|
| 502 | - if ( $dx<$fx ) $change = -1; else $change = 1; |
|
| 503 | - } |
|
| 504 | - if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 505 | - $result = 1; |
|
| 506 | - break; |
|
| 507 | - /* king */ |
|
| 508 | - case 'K': |
|
| 509 | - if ( abs($fx-$dx) > 1 || abs($fy-$dy) > 1 ) break; |
|
| 510 | - $kings = 0; |
|
| 511 | - $adj_tiles = $this->getAdjTiles( $dest_pos ); |
|
| 512 | - foreach( $adj_tiles as $tile ) |
|
| 513 | - if ($this->board[$tile]{1} == 'K' ) $kings++; |
|
| 514 | - if ( $kings == 2 ) break; |
|
| 515 | - $result = 1; |
|
| 516 | - break; |
|
| 458 | + /* knight */ |
|
| 459 | + case 'N': |
|
| 460 | + if ( abs($fx-$dx)==1 && abs($fy-$dy)==2 ) |
|
| 461 | + $result = 1; |
|
| 462 | + if ( abs($fy-$dy)==1 && abs($fx-$dx)==2 ) |
|
| 463 | + $result = 1; |
|
| 464 | + break; |
|
| 465 | + /* bishop */ |
|
| 466 | + case 'B': |
|
| 467 | + if ( abs($fx-$dx) != abs($fy-$dy) ) |
|
| 468 | + break; |
|
| 469 | + if ( $dy < $fy ) $change = -8; else $change = 8; |
|
| 470 | + if ( $dx < $fx ) $change -= 1; else $change += 1; |
|
| 471 | + if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 472 | + $result = 1; |
|
| 473 | + break; |
|
| 474 | + /* rook */ |
|
| 475 | + case 'R': |
|
| 476 | + if ( $fx!=$dx && $fy!=$dy ) |
|
| 477 | + break; |
|
| 478 | + if ( $fx==$dx ) |
|
| 479 | + { |
|
| 480 | + if ( $dy<$fy ) $change = -8; else $change = 8; |
|
| 481 | + } |
|
| 482 | + else { |
|
| 483 | + if ( $dx<$fx ) $change = -1; else $change = 1; |
|
| 484 | + } |
|
| 485 | + if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 486 | + $result = 1; |
|
| 487 | + break; |
|
| 488 | + /* queen */ |
|
| 489 | + case 'Q': |
|
| 490 | + if ( abs($fx-$dx) != abs($fy-$dy) && $fx!=$dx && $fy!=$dy ) |
|
| 491 | + break; |
|
| 492 | + if ( abs($fx-$dx) == abs($fy-$dy) ) |
|
| 493 | + { |
|
| 494 | + if ( $dy < $fy ) $change = -8; else $change = 8; |
|
| 495 | + if ( $dx < $fx ) $change -= 1; else $change += 1; |
|
| 496 | + } |
|
| 497 | + else if ( $fx==$dx ) { |
|
| 498 | + if ( $dy<$fy ) $change = -8; else $change = 8; |
|
| 499 | + } |
|
| 500 | + else |
|
| 501 | + { |
|
| 502 | + if ( $dx<$fx ) $change = -1; else $change = 1; |
|
| 503 | + } |
|
| 504 | + if ( $this->pathIsNotBlocked( $fig_pos+$change, $dest_pos, $change ) ) |
|
| 505 | + $result = 1; |
|
| 506 | + break; |
|
| 507 | + /* king */ |
|
| 508 | + case 'K': |
|
| 509 | + if ( abs($fx-$dx) > 1 || abs($fy-$dy) > 1 ) break; |
|
| 510 | + $kings = 0; |
|
| 511 | + $adj_tiles = $this->getAdjTiles( $dest_pos ); |
|
| 512 | + foreach( $adj_tiles as $tile ) |
|
| 513 | + if ($this->board[$tile]{1} == 'K' ) $kings++; |
|
| 514 | + if ( $kings == 2 ) break; |
|
| 515 | + $result = 1; |
|
| 516 | + break; |
|
| 517 | 517 | } |
| 518 | 518 | |
| 519 | 519 | /* DEBUG: echo " $result<BR>"; */ |
@@ -533,17 +533,17 @@ discard block |
||
| 533 | 533 | { |
| 534 | 534 | if ( $this->board[$fig_pos]{0} == 'w' ) |
| 535 | 535 | { |
| 536 | - if ( ($fig_pos % 8) > 0 && $dest_pos == $fig_pos+7 ) |
|
| 537 | - return 1; |
|
| 538 | - if ( ($fig_pos % 8) < 7 && $dest_pos == $fig_pos+9 ) |
|
| 539 | - return 1; |
|
| 536 | + if ( ($fig_pos % 8) > 0 && $dest_pos == $fig_pos+7 ) |
|
| 537 | + return 1; |
|
| 538 | + if ( ($fig_pos % 8) < 7 && $dest_pos == $fig_pos+9 ) |
|
| 539 | + return 1; |
|
| 540 | 540 | } |
| 541 | 541 | else if ( $this->board[$fig_pos]{0} == 'b' ) |
| 542 | 542 | { |
| 543 | - if ( ($fig_pos % 8) < 7 && $dest_pos == $fig_pos-7 ) |
|
| 544 | - return 1; |
|
| 545 | - if ( ($fig_pos % 8) > 0 && $dest_pos == $fig_pos-9 ) |
|
| 546 | - return 1; |
|
| 543 | + if ( ($fig_pos % 8) < 7 && $dest_pos == $fig_pos-7 ) |
|
| 544 | + return 1; |
|
| 545 | + if ( ($fig_pos % 8) > 0 && $dest_pos == $fig_pos-9 ) |
|
| 546 | + return 1; |
|
| 547 | 547 | } |
| 548 | 548 | return 0; |
| 549 | 549 | } |
@@ -568,23 +568,23 @@ discard block |
||
| 568 | 568 | |
| 569 | 569 | if ( $this->board[$fig_pos]{0} == 'w' ) |
| 570 | 570 | { |
| 571 | - if ( $fig_pos >= 8 && $fig_pos <= 15 ) |
|
| 572 | - $first_move = 1; |
|
| 573 | - if ( $dest_pos==$fig_pos+8 ) |
|
| 574 | - return 1; |
|
| 575 | - if ( $first_move && ( $dest_pos==$fig_pos+16 ) ) |
|
| 576 | - if ($this->is_empty_tile($fig_pos + 8)) |
|
| 577 | - return 1; |
|
| 571 | + if ( $fig_pos >= 8 && $fig_pos <= 15 ) |
|
| 572 | + $first_move = 1; |
|
| 573 | + if ( $dest_pos==$fig_pos+8 ) |
|
| 574 | + return 1; |
|
| 575 | + if ( $first_move && ( $dest_pos==$fig_pos+16 ) ) |
|
| 576 | + if ($this->is_empty_tile($fig_pos + 8)) |
|
| 577 | + return 1; |
|
| 578 | 578 | } |
| 579 | 579 | else if ($this->board[$fig_pos]{0} == 'b' ) |
| 580 | 580 | { |
| 581 | - if ( $fig_pos >= 48 && $fig_pos <= 55 ) |
|
| 582 | - $first_move = 1; |
|
| 583 | - if ( $dest_pos==$fig_pos-8 ) |
|
| 584 | - return 1; |
|
| 585 | - if ( $first_move && ( $dest_pos==$fig_pos-16 ) ) |
|
| 586 | - if ($this->is_empty_tile($fig_pos - 8)) |
|
| 587 | - return 1; |
|
| 581 | + if ( $fig_pos >= 48 && $fig_pos <= 55 ) |
|
| 582 | + $first_move = 1; |
|
| 583 | + if ( $dest_pos==$fig_pos-8 ) |
|
| 584 | + return 1; |
|
| 585 | + if ( $first_move && ( $dest_pos==$fig_pos-16 ) ) |
|
| 586 | + if ($this->is_empty_tile($fig_pos - 8)) |
|
| 587 | + return 1; |
|
| 588 | 588 | } |
| 589 | 589 | return 0; |
| 590 | 590 | } |
@@ -602,16 +602,16 @@ discard block |
||
| 602 | 602 | { |
| 603 | 603 | #var_dump('tileIsUnderAttack, opp', $opp, 'dest_pos', $dest_pos, 'board', $board);#*#DEBUG# |
| 604 | 604 | for ( $i = 0; $i < 64; $i++ ) |
| 605 | - if ($this->board[$i]{0} == $opp ) |
|
| 606 | - { |
|
| 607 | - if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$dest_pos)) || |
|
| 608 | - ($this->board[$i]{1}!='P' && |
|
| 609 | - $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos)) ) |
|
| 610 | - { |
|
| 611 | - /*DEBUG: echo "attack test: $i: ",$opp,"P<BR>"; */ |
|
| 612 | - return 1; |
|
| 613 | - } |
|
| 614 | - } |
|
| 605 | + if ($this->board[$i]{0} == $opp ) |
|
| 606 | + { |
|
| 607 | + if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$dest_pos)) || |
|
| 608 | + ($this->board[$i]{1}!='P' && |
|
| 609 | + $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos)) ) |
|
| 610 | + { |
|
| 611 | + /*DEBUG: echo "attack test: $i: ",$opp,"P<BR>"; */ |
|
| 612 | + return 1; |
|
| 613 | + } |
|
| 614 | + } |
|
| 615 | 615 | return 0; |
| 616 | 616 | } |
| 617 | 617 | |
@@ -629,11 +629,11 @@ discard block |
||
| 629 | 629 | |
| 630 | 630 | #var_dump('kingIsUnderAttack, player', $player, 'opp', $opp, 'board', $board);#*#DEBUG# |
| 631 | 631 | for ( $i = 0; $i < 64; $i++ ) |
| 632 | - if ($this->board[$i]{0} == $player && $this->board[$i]{1} == 'K' ) |
|
| 633 | - { |
|
| 634 | - $king_pos = $i; |
|
| 635 | - break; |
|
| 636 | - } |
|
| 632 | + if ($this->board[$i]{0} == $player && $this->board[$i]{1} == 'K' ) |
|
| 633 | + { |
|
| 634 | + $king_pos = $i; |
|
| 635 | + break; |
|
| 636 | + } |
|
| 637 | 637 | /*DEBUG: echo "$player king is at $king_pos<BR>"; */ |
| 638 | 638 | |
| 639 | 639 | return $this->tileIsUnderAttack( $opp, $king_pos ); |
@@ -651,23 +651,23 @@ discard block |
||
| 651 | 651 | function isCheckMate($player, $opp) |
| 652 | 652 | { |
| 653 | 653 | for ( $i = 0; $i < 64; $i++ ) |
| 654 | - if ($this->board[$i]{0} == $player && $this->board[$i]{1} == 'K' ) |
|
| 655 | - { |
|
| 656 | - $king_pos = $i; |
|
| 657 | - $king_x = $i % 8; |
|
| 658 | - $king_y = floor($i/8); |
|
| 659 | - break; |
|
| 660 | - } |
|
| 654 | + if ($this->board[$i]{0} == $player && $this->board[$i]{1} == 'K' ) |
|
| 655 | + { |
|
| 656 | + $king_pos = $i; |
|
| 657 | + $king_x = $i % 8; |
|
| 658 | + $king_y = floor($i/8); |
|
| 659 | + break; |
|
| 660 | + } |
|
| 661 | 661 | |
| 662 | 662 | /* test adjacent tiles while king is temporarly removed */ |
| 663 | 663 | $adj_tiles = $this->getAdjTiles( $king_pos ); |
| 664 | 664 | $contents = $this->board[$king_pos]; $this->clear_tile($king_pos); |
| 665 | 665 | foreach ( $adj_tiles as $dest_pos ) |
| 666 | 666 | { |
| 667 | - if ($this->board[$dest_pos]{0} == $player ) continue; |
|
| 668 | - if ( $this->tileIsUnderAttack($opp,$dest_pos) ) continue; |
|
| 669 | - $this->board[$king_pos] = $contents; |
|
| 670 | - return 0; |
|
| 667 | + if ($this->board[$dest_pos]{0} == $player ) continue; |
|
| 668 | + if ( $this->tileIsUnderAttack($opp,$dest_pos) ) continue; |
|
| 669 | + $this->board[$king_pos] = $contents; |
|
| 670 | + return 0; |
|
| 671 | 671 | } |
| 672 | 672 | $this->board[$king_pos] = $contents; |
| 673 | 673 | |
@@ -676,15 +676,15 @@ discard block |
||
| 676 | 676 | /* get all figures that attack the king */ |
| 677 | 677 | $attackers = array(); $count = 0; |
| 678 | 678 | for ( $i = 0; $i < 64; $i++ ) |
| 679 | - if ( $this->board[$i]{0} == $opp ) |
|
| 680 | - { |
|
| 681 | - if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$king_pos)) || |
|
| 682 | - ($this->board[$i]{1}!='P' && |
|
| 683 | - $this->tileIsReachable($this->board[$i]{1},$i,$king_pos)) ) |
|
| 684 | - { |
|
| 685 | - $attackers[$count++] = $i; |
|
| 686 | - } |
|
| 687 | - } |
|
| 679 | + if ( $this->board[$i]{0} == $opp ) |
|
| 680 | + { |
|
| 681 | + if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$king_pos)) || |
|
| 682 | + ($this->board[$i]{1}!='P' && |
|
| 683 | + $this->tileIsReachable($this->board[$i]{1},$i,$king_pos)) ) |
|
| 684 | + { |
|
| 685 | + $attackers[$count++] = $i; |
|
| 686 | + } |
|
| 687 | + } |
|
| 688 | 688 | /* DEBUG: |
| 689 | 689 | for( $i = 0; $i < $count; $i++ ) |
| 690 | 690 | echo "Attacker: $attackers[$i] "; |
@@ -696,32 +696,32 @@ discard block |
||
| 696 | 696 | /* check whether attacker can be killed by own figure */ |
| 697 | 697 | $dest_pos = $attackers[0]; |
| 698 | 698 | for ( $i = 0; $i < 64; $i++ ) |
| 699 | - if ( $this->board[$i]{0} == $player ) |
|
| 700 | - { |
|
| 701 | - if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$dest_pos)) || |
|
| 702 | - ($this->board[$i]{1}!='P' && $this->board[$i]{1}!='K' && |
|
| 703 | - $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos)) || |
|
| 704 | - ($this->board[$i]{1}=='K' && |
|
| 705 | - $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos) && |
|
| 706 | - !$this->tileIsUnderAttack($opp,$dest_pos)) ) |
|
| 707 | - { |
|
| 708 | - /* DEBUG: echo "candidate: $i "; */ |
|
| 709 | - $can_kill_atk = 0; |
|
| 710 | - $contents_def = $this->board[$i]; |
|
| 711 | - $contents_atk = $this->board[$dest_pos]; |
|
| 712 | - $this->board[$dest_pos] = $this->board[$i]; |
|
| 713 | - $this->clear_tile($i); |
|
| 714 | - if ( !$this->tileIsUnderAttack($opp,$king_pos) ) |
|
| 715 | - $can_kill_atk = 1; |
|
| 716 | - $this->board[$i] = $contents_def; |
|
| 717 | - $this->board[$dest_pos] = $contents_atk; |
|
| 718 | - if ( $can_kill_atk ) |
|
| 719 | - { |
|
| 720 | - /* DEBUG: echo "$i can kill attacker"; */ |
|
| 721 | - return 0; |
|
| 722 | - } |
|
| 723 | - } |
|
| 724 | - } |
|
| 699 | + if ( $this->board[$i]{0} == $player ) |
|
| 700 | + { |
|
| 701 | + if ( ($this->board[$i]{1}=='P' && $this->checkPawnAttack($i,$dest_pos)) || |
|
| 702 | + ($this->board[$i]{1}!='P' && $this->board[$i]{1}!='K' && |
|
| 703 | + $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos)) || |
|
| 704 | + ($this->board[$i]{1}=='K' && |
|
| 705 | + $this->tileIsReachable($this->board[$i]{1},$i,$dest_pos) && |
|
| 706 | + !$this->tileIsUnderAttack($opp,$dest_pos)) ) |
|
| 707 | + { |
|
| 708 | + /* DEBUG: echo "candidate: $i "; */ |
|
| 709 | + $can_kill_atk = 0; |
|
| 710 | + $contents_def = $this->board[$i]; |
|
| 711 | + $contents_atk = $this->board[$dest_pos]; |
|
| 712 | + $this->board[$dest_pos] = $this->board[$i]; |
|
| 713 | + $this->clear_tile($i); |
|
| 714 | + if ( !$this->tileIsUnderAttack($opp,$king_pos) ) |
|
| 715 | + $can_kill_atk = 1; |
|
| 716 | + $this->board[$i] = $contents_def; |
|
| 717 | + $this->board[$dest_pos] = $contents_atk; |
|
| 718 | + if ( $can_kill_atk ) |
|
| 719 | + { |
|
| 720 | + /* DEBUG: echo "$i can kill attacker"; */ |
|
| 721 | + return 0; |
|
| 722 | + } |
|
| 723 | + } |
|
| 724 | + } |
|
| 725 | 725 | |
| 726 | 726 | /* check whether own unit can block the way */ |
| 727 | 727 | |
@@ -734,7 +734,7 @@ discard block |
||
| 734 | 734 | $dest_x = $dest_pos % 8; |
| 735 | 735 | $dest_y = floor($dest_pos/8); |
| 736 | 736 | if ( abs($dest_x-$king_x)<=1 && abs($dest_y-$king_y)<=1 ) |
| 737 | - return 1; |
|
| 737 | + return 1; |
|
| 738 | 738 | |
| 739 | 739 | /* get the list of tiles between king and attacking |
| 740 | 740 | * unit that can be blocked to stop the attack */ |
@@ -744,17 +744,17 @@ discard block |
||
| 744 | 744 | /* DEBUG: foreach( $path as $tile ) echo "tile: $tile "; */ |
| 745 | 745 | foreach( $path as $pos ) |
| 746 | 746 | { |
| 747 | - for ( $i = 0; $i < 64; $i++ ) |
|
| 748 | - if ( $this->board[$i]{0} == $player ) |
|
| 749 | - { |
|
| 750 | - if ( ($this->board[$i]{1}=='P' && $this->checkPawnMove($i,$pos)) || |
|
| 751 | - ($this->board[$i]{1}!='P' && $this->board[$i]{1}!='K' && |
|
| 752 | - $this->tileIsReachable($this->board[$i]{1},$i,$pos)) ) |
|
| 753 | - { |
|
| 754 | - /* DEBUG: echo "$i can block "; */ |
|
| 755 | - return 0; |
|
| 756 | - } |
|
| 757 | - } |
|
| 747 | + for ( $i = 0; $i < 64; $i++ ) |
|
| 748 | + if ( $this->board[$i]{0} == $player ) |
|
| 749 | + { |
|
| 750 | + if ( ($this->board[$i]{1}=='P' && $this->checkPawnMove($i,$pos)) || |
|
| 751 | + ($this->board[$i]{1}!='P' && $this->board[$i]{1}!='K' && |
|
| 752 | + $this->tileIsReachable($this->board[$i]{1},$i,$pos)) ) |
|
| 753 | + { |
|
| 754 | + /* DEBUG: echo "$i can block "; */ |
|
| 755 | + return 0; |
|
| 756 | + } |
|
| 757 | + } |
|
| 758 | 758 | } |
| 759 | 759 | return 1; |
| 760 | 760 | } |
@@ -773,62 +773,62 @@ discard block |
||
| 773 | 773 | function isStaleMate($player, $opp) |
| 774 | 774 | { |
| 775 | 775 | for ( $i = 0; $i < 64; $i++ ) |
| 776 | - if ($this->board[$i]{0} == $player ) |
|
| 777 | - switch ($this->board[$i]{1} ) |
|
| 778 | - { |
|
| 779 | - case 'K': |
|
| 780 | - $adj_tiles = $this->getAdjTiles( $i ); |
|
| 781 | - foreach ( $adj_tiles as $pos ) |
|
| 782 | - { |
|
| 783 | - if ( $this->board[$pos]{0} == $player ) continue; |
|
| 784 | - if ( $this->tileIsUnderAttack($opp,$pos) ) continue; |
|
| 785 | - return 0; |
|
| 786 | - } |
|
| 787 | - /* DEBUG: echo "King cannot escape by itself! "; */ |
|
| 788 | - break; |
|
| 789 | - case 'P': |
|
| 790 | - if ( $player == 'w' ) |
|
| 791 | - { |
|
| 792 | - if ($this->is_empty_tile($i + 8)) return 0; |
|
| 793 | - if ( ($i%8) > 0 && $this->board[$i+7]{0} != $player ) return 0; |
|
| 794 | - if ( ($i%8) < 7 && $this->board[$i+9]{0} != $player ) return 0; |
|
| 795 | - } |
|
| 796 | - else |
|
| 797 | - { |
|
| 798 | - if ($this->is_empty_tile($i - 8)) return 0; |
|
| 799 | - if ( ($i%8) > 0 && $this->board[$i-9]{0} != $player ) return 0; |
|
| 800 | - if ( ($i%8) < 7 && $this->board[$i-7]{0} != $player ) return 0; |
|
| 801 | - } |
|
| 802 | - break; |
|
| 803 | - case 'B': |
|
| 804 | - if ( $i-9 >= 0 && $this->board[$i-9]{0} != $player ) return 0; |
|
| 805 | - if ( $i-7 >= 0 && $this->board[$i-7]{0} != $player ) return 0; |
|
| 806 | - if ( $i+9 <= 63 && $this->board[$i+9]{0} != $player ) return 0; |
|
| 807 | - if ( $i+7 <= 63 && $this->board[$i+7]{0} != $player ) return 0; |
|
| 808 | - break; |
|
| 809 | - case 'R': |
|
| 810 | - if ( $i-8 >= 0 && $this->board[$i-8]{0} != $player ) return 0; |
|
| 811 | - if ( $i-1 >= 0 && $this->board[$i-1]{0} != $player ) return 0; |
|
| 812 | - if ( $i+8 <= 63 && $this->board[$i+8]{0} != $player ) return 0; |
|
| 813 | - if ( $i+1 <= 63 && $this->board[$i+1]{0} != $player ) return 0; |
|
| 814 | - break; |
|
| 815 | - case 'Q': |
|
| 816 | - $adj_tiles = $this->getAdjTiles( $i ); |
|
| 817 | - foreach ( $adj_tiles as $pos ) |
|
| 818 | - if ( $this->board[$pos]{0} != $player ) |
|
| 819 | - return 0; |
|
| 820 | - break; |
|
| 821 | - case 'N': |
|
| 822 | - if ( $i-17 >= 0 && $this->board[$i-17]{0} != $player ) return 0; |
|
| 823 | - if ( $i-15 >= 0 && $this->board[$i-15]{0} != $player ) return 0; |
|
| 824 | - if ( $i-6 >= 0 && $this->board[$i-6]{0} != $player ) return 0; |
|
| 825 | - if ( $i+10 <= 63 && $this->board[$i+10]{0} != $player ) return 0; |
|
| 826 | - if ( $i+17 <= 63 && $this->board[$i+17]{0} != $player ) return 0; |
|
| 827 | - if ( $i+15 <= 63 && $this->board[$i+15]{0} != $player ) return 0; |
|
| 828 | - if ( $i+6 <= 63 && $this->board[$i+6]{0} != $player ) return 0; |
|
| 829 | - if ( $i-10 >= 0 && $this->board[$i-10]{0} != $player ) return 0; |
|
| 830 | - break; |
|
| 831 | - } |
|
| 776 | + if ($this->board[$i]{0} == $player ) |
|
| 777 | + switch ($this->board[$i]{1} ) |
|
| 778 | + { |
|
| 779 | + case 'K': |
|
| 780 | + $adj_tiles = $this->getAdjTiles( $i ); |
|
| 781 | + foreach ( $adj_tiles as $pos ) |
|
| 782 | + { |
|
| 783 | + if ( $this->board[$pos]{0} == $player ) continue; |
|
| 784 | + if ( $this->tileIsUnderAttack($opp,$pos) ) continue; |
|
| 785 | + return 0; |
|
| 786 | + } |
|
| 787 | + /* DEBUG: echo "King cannot escape by itself! "; */ |
|
| 788 | + break; |
|
| 789 | + case 'P': |
|
| 790 | + if ( $player == 'w' ) |
|
| 791 | + { |
|
| 792 | + if ($this->is_empty_tile($i + 8)) return 0; |
|
| 793 | + if ( ($i%8) > 0 && $this->board[$i+7]{0} != $player ) return 0; |
|
| 794 | + if ( ($i%8) < 7 && $this->board[$i+9]{0} != $player ) return 0; |
|
| 795 | + } |
|
| 796 | + else |
|
| 797 | + { |
|
| 798 | + if ($this->is_empty_tile($i - 8)) return 0; |
|
| 799 | + if ( ($i%8) > 0 && $this->board[$i-9]{0} != $player ) return 0; |
|
| 800 | + if ( ($i%8) < 7 && $this->board[$i-7]{0} != $player ) return 0; |
|
| 801 | + } |
|
| 802 | + break; |
|
| 803 | + case 'B': |
|
| 804 | + if ( $i-9 >= 0 && $this->board[$i-9]{0} != $player ) return 0; |
|
| 805 | + if ( $i-7 >= 0 && $this->board[$i-7]{0} != $player ) return 0; |
|
| 806 | + if ( $i+9 <= 63 && $this->board[$i+9]{0} != $player ) return 0; |
|
| 807 | + if ( $i+7 <= 63 && $this->board[$i+7]{0} != $player ) return 0; |
|
| 808 | + break; |
|
| 809 | + case 'R': |
|
| 810 | + if ( $i-8 >= 0 && $this->board[$i-8]{0} != $player ) return 0; |
|
| 811 | + if ( $i-1 >= 0 && $this->board[$i-1]{0} != $player ) return 0; |
|
| 812 | + if ( $i+8 <= 63 && $this->board[$i+8]{0} != $player ) return 0; |
|
| 813 | + if ( $i+1 <= 63 && $this->board[$i+1]{0} != $player ) return 0; |
|
| 814 | + break; |
|
| 815 | + case 'Q': |
|
| 816 | + $adj_tiles = $this->getAdjTiles( $i ); |
|
| 817 | + foreach ( $adj_tiles as $pos ) |
|
| 818 | + if ( $this->board[$pos]{0} != $player ) |
|
| 819 | + return 0; |
|
| 820 | + break; |
|
| 821 | + case 'N': |
|
| 822 | + if ( $i-17 >= 0 && $this->board[$i-17]{0} != $player ) return 0; |
|
| 823 | + if ( $i-15 >= 0 && $this->board[$i-15]{0} != $player ) return 0; |
|
| 824 | + if ( $i-6 >= 0 && $this->board[$i-6]{0} != $player ) return 0; |
|
| 825 | + if ( $i+10 <= 63 && $this->board[$i+10]{0} != $player ) return 0; |
|
| 826 | + if ( $i+17 <= 63 && $this->board[$i+17]{0} != $player ) return 0; |
|
| 827 | + if ( $i+15 <= 63 && $this->board[$i+15]{0} != $player ) return 0; |
|
| 828 | + if ( $i+6 <= 63 && $this->board[$i+6]{0} != $player ) return 0; |
|
| 829 | + if ( $i-10 >= 0 && $this->board[$i-10]{0} != $player ) return 0; |
|
| 830 | + break; |
|
| 831 | + } |
|
| 832 | 832 | |
| 833 | 833 | return 1; |
| 834 | 834 | } |
@@ -890,12 +890,12 @@ discard block |
||
| 890 | 890 | |
| 891 | 891 | if ( strlen($move)>=6 ) |
| 892 | 892 | { |
| 893 | - /* full move: a pawn requires a ? in the end |
|
| 893 | + /* full move: a pawn requires a ? in the end |
|
| 894 | 894 | * to automatically choose a queen on last line */ |
| 895 | - if ( $move[0] == 'P' ) |
|
| 896 | - if ( $move[strlen($move)-1]<'A' || $move[strlen($move)-1]>'Z' ) |
|
| 897 | - $this->ac_move = "$move?"; |
|
| 898 | - return ""; |
|
| 895 | + if ( $move[0] == 'P' ) |
|
| 896 | + if ( $move[strlen($move)-1]<'A' || $move[strlen($move)-1]>'Z' ) |
|
| 897 | + $this->ac_move = "$move?"; |
|
| 898 | + return ""; |
|
| 899 | 899 | } |
| 900 | 900 | |
| 901 | 901 | /* allow last letter to be a capital one indicating |
@@ -905,186 +905,186 @@ discard block |
||
| 905 | 905 | $pawn_upg = "?"; |
| 906 | 906 | if ( $move[strlen($move)-1]>='A' && $move[strlen($move)-1]<='Z' ) |
| 907 | 907 | { |
| 908 | - $pawn_upg = $move[strlen($move)-1]; |
|
| 909 | - $move = substr( $move, 0, strlen($move)-1 ); |
|
| 908 | + $pawn_upg = $move[strlen($move)-1]; |
|
| 909 | + $move = substr( $move, 0, strlen($move)-1 ); |
|
| 910 | 910 | } |
| 911 | 911 | // remove trailing '=', if present |
| 912 | 912 | if ($move{strlen($move)-1} == '=') { |
| 913 | - $move = substr($move, 0, strlen($move)-1); |
|
| 913 | + $move = substr($move, 0, strlen($move)-1); |
|
| 914 | 914 | } |
| 915 | 915 | if ( $pawn_upg == "P" || $pawn_upg == "K" ) |
| 916 | - return _MD_CHESS_MOVE_PAWN_MAY_BECOME; // "A pawn may only become either a knight, a bishop, a rook or a queen!" |
|
| 916 | + return _MD_CHESS_MOVE_PAWN_MAY_BECOME; // "A pawn may only become either a knight, a bishop, a rook or a queen!" |
|
| 917 | 917 | |
| 918 | 918 | if ( $move[0]>='a' && $move[0]<='h' ) |
| 919 | 919 | { |
| 920 | - /* pawn move. either it's 2 or for characters as |
|
| 920 | + /* pawn move. either it's 2 or for characters as |
|
| 921 | 921 | * listed above */ |
| 922 | - if ( strlen($move) == 4 ) |
|
| 923 | - { |
|
| 924 | - if ( $move[1] != 'x' ) |
|
| 925 | - return _MD_CHESS_MOVE_USE_X; // "use x to indicate an attack" |
|
| 926 | - $dest_x = $move[2]; |
|
| 927 | - $dest_y = $move[3]; |
|
| 928 | - $src_x = $move[0]; |
|
| 929 | - if ( $player == 'w' ) |
|
| 930 | - $src_y = $dest_y-1; |
|
| 931 | - else |
|
| 932 | - $src_y = $dest_y+1; |
|
| 933 | - $this->ac_move = sprintf( "P%s%dx%s%d%s", |
|
| 934 | - $src_x,$src_y,$dest_x,$dest_y, |
|
| 935 | - $pawn_upg ); |
|
| 936 | - return ""; |
|
| 937 | - } |
|
| 938 | - else |
|
| 939 | - if (strlen($move) == 2 ) |
|
| 940 | - { |
|
| 941 | - $fig = sprintf( "%sP", $player ); |
|
| 942 | - if ( $move[1] >= '1' && $move[1] <= '8' ) |
|
| 943 | - { |
|
| 944 | - /* pawn move */ |
|
| 945 | - $pos = $this->boardCoordToIndex( $move ); |
|
| 946 | - if ( $pos == 64 ) return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $move); // "coordinate $move is invalid" |
|
| 947 | - if ( $player == 'w' ) |
|
| 948 | - { |
|
| 949 | - while( $pos >= 0 && $this->board[$pos] != $fig ) $pos -= 8; |
|
| 950 | - if ( $pos < 0 ) $not_found = 1; |
|
| 951 | - } |
|
| 952 | - else |
|
| 953 | - { |
|
| 954 | - while( $pos <= 63 && $this->board[$pos] != $fig ) $pos += 8; |
|
| 955 | - if ( $pos > 63 ) $not_found = 1; |
|
| 956 | - } |
|
| 957 | - $pos = $this->boardIndexToCoord( $pos ); |
|
| 958 | - if ( (isset($not_found) && $not_found) || $pos == "" ) { |
|
| 959 | - return $this->move_msg(_MD_CHESS_MOVE_CANNOT_FIND_PAWN, $player, $move[0]); // "cannot find $player pawn in column $move[0]" |
|
| 960 | - } else { |
|
| 961 | - $this->ac_move = sprintf( "P%s-%s%s", $pos, $move, $pawn_upg ); |
|
| 962 | - return ""; |
|
| 963 | - } |
|
| 964 | - } |
|
| 965 | - else |
|
| 966 | - { |
|
| 967 | - /* notation: [a-h][a-h] for pawn attack no longer allowed |
|
| 922 | + if ( strlen($move) == 4 ) |
|
| 923 | + { |
|
| 924 | + if ( $move[1] != 'x' ) |
|
| 925 | + return _MD_CHESS_MOVE_USE_X; // "use x to indicate an attack" |
|
| 926 | + $dest_x = $move[2]; |
|
| 927 | + $dest_y = $move[3]; |
|
| 928 | + $src_x = $move[0]; |
|
| 929 | + if ( $player == 'w' ) |
|
| 930 | + $src_y = $dest_y-1; |
|
| 931 | + else |
|
| 932 | + $src_y = $dest_y+1; |
|
| 933 | + $this->ac_move = sprintf( "P%s%dx%s%d%s", |
|
| 934 | + $src_x,$src_y,$dest_x,$dest_y, |
|
| 935 | + $pawn_upg ); |
|
| 936 | + return ""; |
|
| 937 | + } |
|
| 938 | + else |
|
| 939 | + if (strlen($move) == 2 ) |
|
| 940 | + { |
|
| 941 | + $fig = sprintf( "%sP", $player ); |
|
| 942 | + if ( $move[1] >= '1' && $move[1] <= '8' ) |
|
| 943 | + { |
|
| 944 | + /* pawn move */ |
|
| 945 | + $pos = $this->boardCoordToIndex( $move ); |
|
| 946 | + if ( $pos == 64 ) return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $move); // "coordinate $move is invalid" |
|
| 947 | + if ( $player == 'w' ) |
|
| 948 | + { |
|
| 949 | + while( $pos >= 0 && $this->board[$pos] != $fig ) $pos -= 8; |
|
| 950 | + if ( $pos < 0 ) $not_found = 1; |
|
| 951 | + } |
|
| 952 | + else |
|
| 953 | + { |
|
| 954 | + while( $pos <= 63 && $this->board[$pos] != $fig ) $pos += 8; |
|
| 955 | + if ( $pos > 63 ) $not_found = 1; |
|
| 956 | + } |
|
| 957 | + $pos = $this->boardIndexToCoord( $pos ); |
|
| 958 | + if ( (isset($not_found) && $not_found) || $pos == "" ) { |
|
| 959 | + return $this->move_msg(_MD_CHESS_MOVE_CANNOT_FIND_PAWN, $player, $move[0]); // "cannot find $player pawn in column $move[0]" |
|
| 960 | + } else { |
|
| 961 | + $this->ac_move = sprintf( "P%s-%s%s", $pos, $move, $pawn_upg ); |
|
| 962 | + return ""; |
|
| 963 | + } |
|
| 964 | + } |
|
| 965 | + else |
|
| 966 | + { |
|
| 967 | + /* notation: [a-h][a-h] for pawn attack no longer allowed |
|
| 968 | 968 | * except for history browser */ |
| 969 | - if ( $this->browsing_mode == 0 ) |
|
| 970 | - return _MD_CHESS_MOVE_USE_NOTATION; // "please use denotation [a-h]x[a-h][1-8] for pawn attacks (see help for more information)" |
|
| 971 | - /* pawn attack must be only one pawn in column! */ |
|
| 972 | - $pawns = 0; |
|
| 973 | - $start = $this->boardCoordToIndex( sprintf( "%s1", $move[0] ) ); |
|
| 974 | - if ( $start == 64 ) return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $move[0]); // "coordinate $move[0] is invalid" |
|
| 975 | - for ( $i = 1; $i <= 8; $i++, $start+=8 ) |
|
| 976 | - if ( $this->board[$start] == $fig ) |
|
| 977 | - { |
|
| 978 | - $pawns++; |
|
| 979 | - $pawn_line = $i; |
|
| 980 | - } |
|
| 981 | - if ( $pawns == 0 ) |
|
| 982 | - return $this->move_msg(_MD_CHESS_MOVE_NO_PAWN, $move[0]); // "there is no pawn in column $move[0]" |
|
| 983 | - else if ( $pawns > 1 ) |
|
| 984 | - return $this->move_msg(_MD_CHESS_MOVE_TWO_PAWNS, $move[0]); // "there is more than one pawn in column $move[0]" |
|
| 985 | - else |
|
| 986 | - { |
|
| 987 | - if ( $player == 'w' ) |
|
| 988 | - $dest_line = $pawn_line+1; |
|
| 989 | - else |
|
| 990 | - $dest_line = $pawn_line-1; |
|
| 991 | - $this->ac_move = sprintf( "P%s%dx%s%d", |
|
| 992 | - $move[0],$pawn_line,$move[1],$dest_line ); |
|
| 993 | - return ""; |
|
| 994 | - } |
|
| 995 | - } |
|
| 996 | - } |
|
| 969 | + if ( $this->browsing_mode == 0 ) |
|
| 970 | + return _MD_CHESS_MOVE_USE_NOTATION; // "please use denotation [a-h]x[a-h][1-8] for pawn attacks (see help for more information)" |
|
| 971 | + /* pawn attack must be only one pawn in column! */ |
|
| 972 | + $pawns = 0; |
|
| 973 | + $start = $this->boardCoordToIndex( sprintf( "%s1", $move[0] ) ); |
|
| 974 | + if ( $start == 64 ) return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $move[0]); // "coordinate $move[0] is invalid" |
|
| 975 | + for ( $i = 1; $i <= 8; $i++, $start+=8 ) |
|
| 976 | + if ( $this->board[$start] == $fig ) |
|
| 977 | + { |
|
| 978 | + $pawns++; |
|
| 979 | + $pawn_line = $i; |
|
| 980 | + } |
|
| 981 | + if ( $pawns == 0 ) |
|
| 982 | + return $this->move_msg(_MD_CHESS_MOVE_NO_PAWN, $move[0]); // "there is no pawn in column $move[0]" |
|
| 983 | + else if ( $pawns > 1 ) |
|
| 984 | + return $this->move_msg(_MD_CHESS_MOVE_TWO_PAWNS, $move[0]); // "there is more than one pawn in column $move[0]" |
|
| 985 | + else |
|
| 986 | + { |
|
| 987 | + if ( $player == 'w' ) |
|
| 988 | + $dest_line = $pawn_line+1; |
|
| 989 | + else |
|
| 990 | + $dest_line = $pawn_line-1; |
|
| 991 | + $this->ac_move = sprintf( "P%s%dx%s%d", |
|
| 992 | + $move[0],$pawn_line,$move[1],$dest_line ); |
|
| 993 | + return ""; |
|
| 994 | + } |
|
| 995 | + } |
|
| 996 | + } |
|
| 997 | 997 | } |
| 998 | 998 | else |
| 999 | 999 | { |
| 1000 | - /* figure move */ |
|
| 1001 | - $dest_coord = substr( $move, strlen($move)-2, 2 ); |
|
| 1002 | - $action = $move[strlen($move)-3]; |
|
| 1003 | - if ( $action != 'x' ) $action = '-'; |
|
| 1004 | - if ( $player == 'w' ) |
|
| 1005 | - $figures = $this->w_figures; |
|
| 1006 | - else |
|
| 1007 | - $figures = $this->b_figures; |
|
| 1008 | - $fig_count = 0; |
|
| 1009 | - foreach( $figures as $figure ) |
|
| 1010 | - if ( $figure[0] == $move[0] ) |
|
| 1011 | - { |
|
| 1012 | - $fig_count++; |
|
| 1013 | - if ( $fig_count == 1 ) |
|
| 1014 | - $pos1 = substr( $figure, 1, 2 ); |
|
| 1015 | - else |
|
| 1016 | - $pos2 = substr( $figure, 1, 2 ); |
|
| 1017 | - } |
|
| 1018 | - if ( $fig_count == 0 ) |
|
| 1019 | - return $this->move_msg(_MD_CHESS_MOVE_NO_FIGURE, $move[0], $this->getFullFigureName($move[0])); // sprintf("there is no figure %s = %s", $move[0], $this->getFullFigureName($move[0])) |
|
| 1020 | - else |
|
| 1021 | - if ( $fig_count == 1 ) |
|
| 1022 | - { |
|
| 1023 | - $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1024 | - $move[0], $pos1, $action, $dest_coord ); |
|
| 1025 | - return ""; |
|
| 1026 | - } |
|
| 1027 | - else |
|
| 1028 | - { |
|
| 1029 | - /* two figures which may cause ambiguity */ |
|
| 1030 | - $dest_pos = $this->boardCoordToIndex( $dest_coord ); |
|
| 1031 | - if ( $dest_pos == 64 ) |
|
| 1032 | - return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $dest_coord); // "coordinate $dest_coord is invalid" |
|
| 1033 | - $fig1_can_reach = $this->tileIsReachable( $move[0], |
|
| 1034 | - $this->boardCoordToIndex($pos1), $dest_pos ); |
|
| 1035 | - $fig2_can_reach = $this->tileIsReachable( $move[0], |
|
| 1036 | - $this->boardCoordToIndex($pos2), $dest_pos ); |
|
| 1037 | - if ( !$fig1_can_reach && !$fig2_can_reach ) |
|
| 1038 | - return $this->move_msg(_MD_CHESS_MOVE_NEITHER_CAN_REACH, $move[0], $this->getFullFigureName($move[0]), $dest_coord); // sprintf("neither of the %s = %s can reach %s", $move[0], $this->getFullFigureName($move[0]), $dest_coord) |
|
| 1039 | - else |
|
| 1040 | - if ( $fig1_can_reach && $fig2_can_reach ) |
|
| 1041 | - { |
|
| 1042 | - /* ambiguity - check whether a hint is given */ |
|
| 1043 | - if ( ($action=='-' && strlen($move)==4) || |
|
| 1044 | - ($action=='x' && strlen($move)==5) ) |
|
| 1045 | - $hint = $move[1]; |
|
| 1046 | - if ( empty($hint) ) |
|
| 1047 | - return $this->move_msg(_MD_CHESS_MOVE_BOTH_CAN_REACH, $move[0], $this->getFullFigureName($move[0]), $dest_coord); // sprintf("both of the %s = %s can reach %s", $move[0], $this->getFullFigureName($move[0]), $dest_coord) |
|
| 1048 | - else |
|
| 1049 | - { |
|
| 1050 | - $move_fig1 = 0; |
|
| 1051 | - $move_fig2 = 0; |
|
| 1052 | - if ( $hint>='1' && $hint<='8' ) |
|
| 1053 | - { |
|
| 1054 | - if ( $pos1[1]==$hint && $pos2[1]!=$hint ) |
|
| 1055 | - $move_fig1 = 1; |
|
| 1056 | - if ( $pos2[1]==$hint && $pos1[1]!=$hint ) |
|
| 1057 | - $move_fig2 = 1; |
|
| 1058 | - } |
|
| 1059 | - else |
|
| 1060 | - { |
|
| 1061 | - if ( $pos1[0]==$hint && $pos2[0]!=$hint ) |
|
| 1062 | - $move_fig1 = 1; |
|
| 1063 | - if ( $pos2[0]==$hint && $pos1[0]!=$hint ) |
|
| 1064 | - $move_fig2 = 1; |
|
| 1065 | - } |
|
| 1066 | - if ( !$move_fig1 && !$move_fig2 ) |
|
| 1067 | - return _MD_CHESS_MOVE_AMBIGUOUS; // "ambiguity is not properly resolved" |
|
| 1068 | - if ( $move_fig1 ) |
|
| 1069 | - $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1070 | - $move[0], $pos1, $action, $dest_coord ); |
|
| 1071 | - else |
|
| 1072 | - $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1073 | - $move[0], $pos2, $action, $dest_coord ); |
|
| 1074 | - return; |
|
| 1075 | - } |
|
| 1076 | - } |
|
| 1077 | - else |
|
| 1078 | - { |
|
| 1079 | - if ( $fig1_can_reach ) |
|
| 1080 | - $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1081 | - $move[0], $pos1, $action, $dest_coord ); |
|
| 1082 | - else |
|
| 1083 | - $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1084 | - $move[0], $pos2, $action, $dest_coord ); |
|
| 1085 | - return ""; |
|
| 1086 | - } |
|
| 1087 | - } |
|
| 1000 | + /* figure move */ |
|
| 1001 | + $dest_coord = substr( $move, strlen($move)-2, 2 ); |
|
| 1002 | + $action = $move[strlen($move)-3]; |
|
| 1003 | + if ( $action != 'x' ) $action = '-'; |
|
| 1004 | + if ( $player == 'w' ) |
|
| 1005 | + $figures = $this->w_figures; |
|
| 1006 | + else |
|
| 1007 | + $figures = $this->b_figures; |
|
| 1008 | + $fig_count = 0; |
|
| 1009 | + foreach( $figures as $figure ) |
|
| 1010 | + if ( $figure[0] == $move[0] ) |
|
| 1011 | + { |
|
| 1012 | + $fig_count++; |
|
| 1013 | + if ( $fig_count == 1 ) |
|
| 1014 | + $pos1 = substr( $figure, 1, 2 ); |
|
| 1015 | + else |
|
| 1016 | + $pos2 = substr( $figure, 1, 2 ); |
|
| 1017 | + } |
|
| 1018 | + if ( $fig_count == 0 ) |
|
| 1019 | + return $this->move_msg(_MD_CHESS_MOVE_NO_FIGURE, $move[0], $this->getFullFigureName($move[0])); // sprintf("there is no figure %s = %s", $move[0], $this->getFullFigureName($move[0])) |
|
| 1020 | + else |
|
| 1021 | + if ( $fig_count == 1 ) |
|
| 1022 | + { |
|
| 1023 | + $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1024 | + $move[0], $pos1, $action, $dest_coord ); |
|
| 1025 | + return ""; |
|
| 1026 | + } |
|
| 1027 | + else |
|
| 1028 | + { |
|
| 1029 | + /* two figures which may cause ambiguity */ |
|
| 1030 | + $dest_pos = $this->boardCoordToIndex( $dest_coord ); |
|
| 1031 | + if ( $dest_pos == 64 ) |
|
| 1032 | + return $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $dest_coord); // "coordinate $dest_coord is invalid" |
|
| 1033 | + $fig1_can_reach = $this->tileIsReachable( $move[0], |
|
| 1034 | + $this->boardCoordToIndex($pos1), $dest_pos ); |
|
| 1035 | + $fig2_can_reach = $this->tileIsReachable( $move[0], |
|
| 1036 | + $this->boardCoordToIndex($pos2), $dest_pos ); |
|
| 1037 | + if ( !$fig1_can_reach && !$fig2_can_reach ) |
|
| 1038 | + return $this->move_msg(_MD_CHESS_MOVE_NEITHER_CAN_REACH, $move[0], $this->getFullFigureName($move[0]), $dest_coord); // sprintf("neither of the %s = %s can reach %s", $move[0], $this->getFullFigureName($move[0]), $dest_coord) |
|
| 1039 | + else |
|
| 1040 | + if ( $fig1_can_reach && $fig2_can_reach ) |
|
| 1041 | + { |
|
| 1042 | + /* ambiguity - check whether a hint is given */ |
|
| 1043 | + if ( ($action=='-' && strlen($move)==4) || |
|
| 1044 | + ($action=='x' && strlen($move)==5) ) |
|
| 1045 | + $hint = $move[1]; |
|
| 1046 | + if ( empty($hint) ) |
|
| 1047 | + return $this->move_msg(_MD_CHESS_MOVE_BOTH_CAN_REACH, $move[0], $this->getFullFigureName($move[0]), $dest_coord); // sprintf("both of the %s = %s can reach %s", $move[0], $this->getFullFigureName($move[0]), $dest_coord) |
|
| 1048 | + else |
|
| 1049 | + { |
|
| 1050 | + $move_fig1 = 0; |
|
| 1051 | + $move_fig2 = 0; |
|
| 1052 | + if ( $hint>='1' && $hint<='8' ) |
|
| 1053 | + { |
|
| 1054 | + if ( $pos1[1]==$hint && $pos2[1]!=$hint ) |
|
| 1055 | + $move_fig1 = 1; |
|
| 1056 | + if ( $pos2[1]==$hint && $pos1[1]!=$hint ) |
|
| 1057 | + $move_fig2 = 1; |
|
| 1058 | + } |
|
| 1059 | + else |
|
| 1060 | + { |
|
| 1061 | + if ( $pos1[0]==$hint && $pos2[0]!=$hint ) |
|
| 1062 | + $move_fig1 = 1; |
|
| 1063 | + if ( $pos2[0]==$hint && $pos1[0]!=$hint ) |
|
| 1064 | + $move_fig2 = 1; |
|
| 1065 | + } |
|
| 1066 | + if ( !$move_fig1 && !$move_fig2 ) |
|
| 1067 | + return _MD_CHESS_MOVE_AMBIGUOUS; // "ambiguity is not properly resolved" |
|
| 1068 | + if ( $move_fig1 ) |
|
| 1069 | + $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1070 | + $move[0], $pos1, $action, $dest_coord ); |
|
| 1071 | + else |
|
| 1072 | + $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1073 | + $move[0], $pos2, $action, $dest_coord ); |
|
| 1074 | + return; |
|
| 1075 | + } |
|
| 1076 | + } |
|
| 1077 | + else |
|
| 1078 | + { |
|
| 1079 | + if ( $fig1_can_reach ) |
|
| 1080 | + $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1081 | + $move[0], $pos1, $action, $dest_coord ); |
|
| 1082 | + else |
|
| 1083 | + $this->ac_move = sprintf( "%s%s%s%s", |
|
| 1084 | + $move[0], $pos2, $action, $dest_coord ); |
|
| 1085 | + return ""; |
|
| 1086 | + } |
|
| 1087 | + } |
|
| 1088 | 1088 | } |
| 1089 | 1089 | |
| 1090 | 1090 | return $error; |
@@ -1111,37 +1111,37 @@ discard block |
||
| 1111 | 1111 | /* valid pawn moves are always non-ambigious */ |
| 1112 | 1112 | if ( $move[0] == 'P' ) |
| 1113 | 1113 | { |
| 1114 | - /* skip P anycase. for attacks skip source digit |
|
| 1114 | + /* skip P anycase. for attacks skip source digit |
|
| 1115 | 1115 | and for moves skip source pos and - */ |
| 1116 | - if ( $move[3] == '-' ) |
|
| 1117 | - $new_move = substr( $move, 4 ); |
|
| 1118 | - else |
|
| 1119 | - if ( $move[3] == 'x' ) |
|
| 1120 | - $new_move = sprintf("%s%s", $move[1], substr( $move, 3 ) ); |
|
| 1116 | + if ( $move[3] == '-' ) |
|
| 1117 | + $new_move = substr( $move, 4 ); |
|
| 1118 | + else |
|
| 1119 | + if ( $move[3] == 'x' ) |
|
| 1120 | + $new_move = sprintf("%s%s", $move[1], substr( $move, 3 ) ); |
|
| 1121 | 1121 | } |
| 1122 | 1122 | else |
| 1123 | 1123 | { |
| 1124 | - /* try to remove the source position and check whether it |
|
| 1124 | + /* try to remove the source position and check whether it |
|
| 1125 | 1125 | * is a non-ambigious move. if it is add one of the components |
| 1126 | 1126 | * and check again */ |
| 1127 | - if ( $move[3] == '-' ) |
|
| 1128 | - $dest = substr( $move, 4 ); |
|
| 1129 | - else |
|
| 1130 | - if ( $move[3] == 'x' ) |
|
| 1131 | - $dest = substr( $move, 3 ); |
|
| 1132 | - $new_move = sprintf("%s%s", $move[0], $dest ); |
|
| 1133 | - if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1134 | - { |
|
| 1135 | - /* add a component */ |
|
| 1136 | - $new_move = sprintf("%s%s%s", $move[0], $move[1], $dest ); |
|
| 1137 | - if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1138 | - { |
|
| 1139 | - /* add other component */ |
|
| 1140 | - $new_move = sprintf("%s%s%s", $move[0], $move[2], $dest ); |
|
| 1141 | - if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1142 | - $new_move = $move; /* give up */ |
|
| 1143 | - } |
|
| 1144 | - } |
|
| 1127 | + if ( $move[3] == '-' ) |
|
| 1128 | + $dest = substr( $move, 4 ); |
|
| 1129 | + else |
|
| 1130 | + if ( $move[3] == 'x' ) |
|
| 1131 | + $dest = substr( $move, 3 ); |
|
| 1132 | + $new_move = sprintf("%s%s", $move[0], $dest ); |
|
| 1133 | + if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1134 | + { |
|
| 1135 | + /* add a component */ |
|
| 1136 | + $new_move = sprintf("%s%s%s", $move[0], $move[1], $dest ); |
|
| 1137 | + if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1138 | + { |
|
| 1139 | + /* add other component */ |
|
| 1140 | + $new_move = sprintf("%s%s%s", $move[0], $move[2], $dest ); |
|
| 1141 | + if ( $this->completeMove($player,$new_move) != "" ) |
|
| 1142 | + $new_move = $move; /* give up */ |
|
| 1143 | + } |
|
| 1144 | + } |
|
| 1145 | 1145 | } |
| 1146 | 1146 | |
| 1147 | 1147 | $this->ac_move = $old_ac_move; |
@@ -1175,14 +1175,14 @@ discard block |
||
| 1175 | 1175 | $cur_player = $this->gamestate['fen_active_color']; /* b or w */ |
| 1176 | 1176 | |
| 1177 | 1177 | if ($cur_player != 'w' and $cur_player != 'b') { |
| 1178 | - return(array(false, "handleMove, internal error: player='$cur_player'")); |
|
| 1178 | + return(array(false, "handleMove, internal error: player='$cur_player'")); |
|
| 1179 | 1179 | } |
| 1180 | 1180 | |
| 1181 | 1181 | $cur_opp = ($cur_player == 'w') ? 'b' : 'w'; |
| 1182 | 1182 | |
| 1183 | 1183 | if ($this->gamestate['pgn_result'] != '*') |
| 1184 | 1184 | { |
| 1185 | - return(array(false, _MD_CHESS_MOVE_GAME_OVER)); |
|
| 1185 | + return(array(false, _MD_CHESS_MOVE_GAME_OVER)); |
|
| 1186 | 1186 | } |
| 1187 | 1187 | |
| 1188 | 1188 | // get castling availability flags |
@@ -1327,83 +1327,83 @@ discard block |
||
| 1327 | 1327 | |
| 1328 | 1328 | else |
| 1329 | 1329 | { |
| 1330 | - /* [PRNBQK][a-h][1-8][-:x][a-h][1-8][RNBQK] full move */ |
|
| 1330 | + /* [PRNBQK][a-h][1-8][-:x][a-h][1-8][RNBQK] full move */ |
|
| 1331 | 1331 | |
| 1332 | - /* allow short move description by autocompleting to |
|
| 1332 | + /* allow short move description by autocompleting to |
|
| 1333 | 1333 | * full description */ |
| 1334 | - $ac_error = $this->completeMove( $cur_player, trim($move) ); |
|
| 1335 | - if ( $ac_error != "" ) |
|
| 1336 | - return(array(false, $ac_error)); // "ERROR: autocomplete: $ac_error" |
|
| 1337 | - else |
|
| 1338 | - $move = $this->ac_move; |
|
| 1339 | - $this->last_move = str_replace( "?", "", $move ); |
|
| 1334 | + $ac_error = $this->completeMove( $cur_player, trim($move) ); |
|
| 1335 | + if ( $ac_error != "" ) |
|
| 1336 | + return(array(false, $ac_error)); // "ERROR: autocomplete: $ac_error" |
|
| 1337 | + else |
|
| 1338 | + $move = $this->ac_move; |
|
| 1339 | + $this->last_move = str_replace( "?", "", $move ); |
|
| 1340 | 1340 | |
| 1341 | - /* a final captial letter may only be N,B,R,Q for the |
|
| 1341 | + /* a final captial letter may only be N,B,R,Q for the |
|
| 1342 | 1342 | * appropiate chessman */ |
| 1343 | - $c = $move[strlen($move)-1]; |
|
| 1344 | - if ( $c >= 'A' && $c <= 'Z' ) |
|
| 1345 | - if ( $c != 'N' && $c != 'B' && $c != 'R' && $c != 'Q' ) |
|
| 1346 | - return(array(false, _MD_CHESS_MOVE_INVALID_PIECE)); // "ERROR: only N (knight), B (bishop), R (rook) and Q (queen) are valid chessman identifiers" |
|
| 1343 | + $c = $move[strlen($move)-1]; |
|
| 1344 | + if ( $c >= 'A' && $c <= 'Z' ) |
|
| 1345 | + if ( $c != 'N' && $c != 'B' && $c != 'R' && $c != 'Q' ) |
|
| 1346 | + return(array(false, _MD_CHESS_MOVE_INVALID_PIECE)); // "ERROR: only N (knight), B (bishop), R (rook) and Q (queen) are valid chessman identifiers" |
|
| 1347 | 1347 | |
| 1348 | - /* if it is a full move, try to shorten the history move */ |
|
| 1349 | - if ( strlen( $history_move ) >= 6 ) |
|
| 1350 | - $history_move = |
|
| 1351 | - $this->convertFullToChessNotation($cur_player,$history_move); |
|
| 1352 | - /* DEBUG: echo "Move: $move ($history_move)<BR>"; */ |
|
| 1348 | + /* if it is a full move, try to shorten the history move */ |
|
| 1349 | + if ( strlen( $history_move ) >= 6 ) |
|
| 1350 | + $history_move = |
|
| 1351 | + $this->convertFullToChessNotation($cur_player,$history_move); |
|
| 1352 | + /* DEBUG: echo "Move: $move ($history_move)<BR>"; */ |
|
| 1353 | 1353 | |
| 1354 | - /* validate figure and position */ |
|
| 1355 | - $fig_type = $move[0]; |
|
| 1356 | - $fig_name = $this->getFullFigureName( $fig_type ); |
|
| 1357 | - if ( $fig_name == "empty" ) |
|
| 1358 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_UNKNOWN_FIGURE, $fig_type))); // "ERROR: Figure $fig_type is unknown!" |
|
| 1359 | - $fig_coord = substr($move,1,2); |
|
| 1360 | - $fig_pos = $this->boardCoordToIndex( $fig_coord ); |
|
| 1361 | - if ( $fig_pos == 64 ) return(array(false, $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $fig_coord))); // "ERROR: $fig_coord is invalid!" |
|
| 1362 | - /* DEBUG echo "fig_type: $fig_type, fig_pos: $fig_pos<BR>"; */ |
|
| 1363 | - if ($this->is_empty_tile($fig_pos)) |
|
| 1364 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_TILE_EMPTY, $fig_coord))); // "ERROR: Tile $fig_coord is empty." |
|
| 1365 | - if ( $this->board[$fig_pos]{0} != $cur_player ) |
|
| 1366 | - return(array(false, _MD_CHESS_MOVE_NOT_YOUR_PIECE)); // "ERROR: Figure does not belong to you!" |
|
| 1367 | - if ( $this->board[$fig_pos]{1} != $fig_type ) |
|
| 1368 | - return(array(false, _MD_CHESS_MOVE_NOEXIST_FIGURE)); // "ERROR: Figure does not exist!" |
|
| 1354 | + /* validate figure and position */ |
|
| 1355 | + $fig_type = $move[0]; |
|
| 1356 | + $fig_name = $this->getFullFigureName( $fig_type ); |
|
| 1357 | + if ( $fig_name == "empty" ) |
|
| 1358 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_UNKNOWN_FIGURE, $fig_type))); // "ERROR: Figure $fig_type is unknown!" |
|
| 1359 | + $fig_coord = substr($move,1,2); |
|
| 1360 | + $fig_pos = $this->boardCoordToIndex( $fig_coord ); |
|
| 1361 | + if ( $fig_pos == 64 ) return(array(false, $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $fig_coord))); // "ERROR: $fig_coord is invalid!" |
|
| 1362 | + /* DEBUG echo "fig_type: $fig_type, fig_pos: $fig_pos<BR>"; */ |
|
| 1363 | + if ($this->is_empty_tile($fig_pos)) |
|
| 1364 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_TILE_EMPTY, $fig_coord))); // "ERROR: Tile $fig_coord is empty." |
|
| 1365 | + if ( $this->board[$fig_pos]{0} != $cur_player ) |
|
| 1366 | + return(array(false, _MD_CHESS_MOVE_NOT_YOUR_PIECE)); // "ERROR: Figure does not belong to you!" |
|
| 1367 | + if ( $this->board[$fig_pos]{1} != $fig_type ) |
|
| 1368 | + return(array(false, _MD_CHESS_MOVE_NOEXIST_FIGURE)); // "ERROR: Figure does not exist!" |
|
| 1369 | 1369 | |
| 1370 | - /* get target index */ |
|
| 1371 | - $dest_coord = substr($move,4,2); |
|
| 1372 | - $dest_pos = $this->boardCoordToIndex( $dest_coord ); |
|
| 1373 | - if ( $dest_pos == 64 ) |
|
| 1374 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $dest_coord))); // "ERROR: $dest_coord is invalid!" |
|
| 1375 | - if ( $dest_pos == $fig_pos ) |
|
| 1376 | - return(array(false, _MD_CHESS_MOVE_START_END_SAME)); |
|
| 1377 | - /* DEBUG echo "dest_pos: $dest_pos<BR>"; */ |
|
| 1378 | - |
|
| 1379 | - /* get action */ |
|
| 1380 | - $action = $move[3]; |
|
| 1381 | - if ( $move[3] == "-" ) |
|
| 1382 | - $action = 'M'; /* move */ |
|
| 1383 | - else if ( $move[3] == 'x' ) |
|
| 1384 | - $action = 'A'; /* attack */ |
|
| 1385 | - else |
|
| 1386 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_UNKNOWN_ACTION, $action))); // "ERROR: $action is unknown! Please use \"-\" for a move and \"x\" for an attack." |
|
| 1387 | - |
|
| 1388 | - /* if attack an enemy unit must be present on tile |
|
| 1370 | + /* get target index */ |
|
| 1371 | + $dest_coord = substr($move,4,2); |
|
| 1372 | + $dest_pos = $this->boardCoordToIndex( $dest_coord ); |
|
| 1373 | + if ( $dest_pos == 64 ) |
|
| 1374 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_COORD_INVALID, $dest_coord))); // "ERROR: $dest_coord is invalid!" |
|
| 1375 | + if ( $dest_pos == $fig_pos ) |
|
| 1376 | + return(array(false, _MD_CHESS_MOVE_START_END_SAME)); |
|
| 1377 | + /* DEBUG echo "dest_pos: $dest_pos<BR>"; */ |
|
| 1378 | + |
|
| 1379 | + /* get action */ |
|
| 1380 | + $action = $move[3]; |
|
| 1381 | + if ( $move[3] == "-" ) |
|
| 1382 | + $action = 'M'; /* move */ |
|
| 1383 | + else if ( $move[3] == 'x' ) |
|
| 1384 | + $action = 'A'; /* attack */ |
|
| 1385 | + else |
|
| 1386 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_UNKNOWN_ACTION, $action))); // "ERROR: $action is unknown! Please use \"-\" for a move and \"x\" for an attack." |
|
| 1387 | + |
|
| 1388 | + /* if attack an enemy unit must be present on tile |
|
| 1389 | 1389 | * and if move then tile must be empty. in both cases |
| 1390 | 1390 | * the king must not be checked after moving. */ |
| 1391 | 1391 | |
| 1392 | - /* check whether the move is along a valid path and |
|
| 1392 | + /* check whether the move is along a valid path and |
|
| 1393 | 1393 | * whether all tiles in between are empty thus the path |
| 1394 | 1394 | * is not blocked. the final destination tile is not |
| 1395 | 1395 | * checked here. */ |
| 1396 | - if ( $fig_type != 'P' ) |
|
| 1397 | - { |
|
| 1398 | - if ( !$this->tileIsReachable( $fig_type, $fig_pos, $dest_pos ) ) |
|
| 1399 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of moving range for $fig_name at $fig_coord!" |
|
| 1400 | - } |
|
| 1401 | - else { |
|
| 1402 | - if ( $action == 'M' && !$this->checkPawnMove( $fig_pos, $dest_pos ) ) |
|
| 1403 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of moving range for $fig_name at $fig_coord!" |
|
| 1404 | - if ( $action == 'A' && !$this->checkPawnAttack( $fig_pos, $dest_pos ) ) |
|
| 1405 | - return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of attacking range for $fig_name at $fig_coord!" |
|
| 1406 | - } |
|
| 1396 | + if ( $fig_type != 'P' ) |
|
| 1397 | + { |
|
| 1398 | + if ( !$this->tileIsReachable( $fig_type, $fig_pos, $dest_pos ) ) |
|
| 1399 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of moving range for $fig_name at $fig_coord!" |
|
| 1400 | + } |
|
| 1401 | + else { |
|
| 1402 | + if ( $action == 'M' && !$this->checkPawnMove( $fig_pos, $dest_pos ) ) |
|
| 1403 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of moving range for $fig_name at $fig_coord!" |
|
| 1404 | + if ( $action == 'A' && !$this->checkPawnAttack( $fig_pos, $dest_pos ) ) |
|
| 1405 | + return(array(false, $this->move_msg(_MD_CHESS_MOVE_OUT_OF_RANGE, $dest_coord, $fig_name, $fig_coord))); // "ERROR: Tile $dest_coord is out of attacking range for $fig_name at $fig_coord!" |
|
| 1406 | + } |
|
| 1407 | 1407 | |
| 1408 | 1408 | $en_passant_capture_performed = 0; // 1 if en passant captured occurred, else 0 |
| 1409 | 1409 | /* check action */ |
@@ -1427,43 +1427,43 @@ discard block |
||
| 1427 | 1427 | return(array(false, $this->move_msg(_MD_CHESS_MOVE_ATTACK_SELF, $dest_coord))); // "ERROR: You cannot attack own unit at $dest_coord." |
| 1428 | 1428 | } |
| 1429 | 1429 | |
| 1430 | - /* backup affected tiles */ |
|
| 1431 | - $old_fig_tile = $this->board[$fig_pos]; |
|
| 1432 | - $old_dest_tile = $this->board[$dest_pos]; |
|
| 1433 | - |
|
| 1434 | - /* perform move */ |
|
| 1435 | - $this->clear_tile($fig_pos); |
|
| 1436 | - if (!$this->is_empty_tile($dest_pos)) |
|
| 1437 | - $this->piece_captured = sprintf("%s%s",$this->board[$dest_pos],$dest_pos); |
|
| 1438 | - $this->board[$dest_pos] = "$cur_player$fig_type"; |
|
| 1439 | - if ( $en_passant_capture_performed ) { |
|
| 1440 | - /* kill pawn */ |
|
| 1441 | - if ( $cur_player == 'w' ) |
|
| 1442 | - { |
|
| 1443 | - $this->clear_tile($dest_pos - 8); |
|
| 1444 | - $this->piece_captured = sprintf("bP%s",$dest_pos-8); |
|
| 1445 | - } |
|
| 1446 | - else |
|
| 1447 | - { |
|
| 1448 | - $this->clear_tile($dest_pos + 8); |
|
| 1449 | - $this->piece_captured = sprintf("wP%s",$dest_pos+8); |
|
| 1450 | - } |
|
| 1451 | - } |
|
| 1452 | - |
|
| 1453 | - /* check check :) */ |
|
| 1454 | - if ( $this->kingIsUnderAttack( $cur_player, $cur_opp ) ) |
|
| 1455 | - { |
|
| 1456 | - $this->board[$fig_pos] = $old_fig_tile; |
|
| 1457 | - $this->board[$dest_pos] = $old_dest_tile; |
|
| 1458 | - if ( $en_passant_capture_performed ) { |
|
| 1459 | - // restore pawn that was captured above, since that move is invalid |
|
| 1460 | - if ( $cur_player == 'w' ) |
|
| 1461 | - $this->board[$dest_pos-8] = "bP"; |
|
| 1462 | - else |
|
| 1463 | - $this->board[$dest_pos+8] = "wP"; |
|
| 1464 | - } |
|
| 1465 | - return(array(false, _MD_CHESS_MOVE_IN_CHECK)); // "ERROR: Move is invalid because king would be under attack then." |
|
| 1466 | - } |
|
| 1430 | + /* backup affected tiles */ |
|
| 1431 | + $old_fig_tile = $this->board[$fig_pos]; |
|
| 1432 | + $old_dest_tile = $this->board[$dest_pos]; |
|
| 1433 | + |
|
| 1434 | + /* perform move */ |
|
| 1435 | + $this->clear_tile($fig_pos); |
|
| 1436 | + if (!$this->is_empty_tile($dest_pos)) |
|
| 1437 | + $this->piece_captured = sprintf("%s%s",$this->board[$dest_pos],$dest_pos); |
|
| 1438 | + $this->board[$dest_pos] = "$cur_player$fig_type"; |
|
| 1439 | + if ( $en_passant_capture_performed ) { |
|
| 1440 | + /* kill pawn */ |
|
| 1441 | + if ( $cur_player == 'w' ) |
|
| 1442 | + { |
|
| 1443 | + $this->clear_tile($dest_pos - 8); |
|
| 1444 | + $this->piece_captured = sprintf("bP%s",$dest_pos-8); |
|
| 1445 | + } |
|
| 1446 | + else |
|
| 1447 | + { |
|
| 1448 | + $this->clear_tile($dest_pos + 8); |
|
| 1449 | + $this->piece_captured = sprintf("wP%s",$dest_pos+8); |
|
| 1450 | + } |
|
| 1451 | + } |
|
| 1452 | + |
|
| 1453 | + /* check check :) */ |
|
| 1454 | + if ( $this->kingIsUnderAttack( $cur_player, $cur_opp ) ) |
|
| 1455 | + { |
|
| 1456 | + $this->board[$fig_pos] = $old_fig_tile; |
|
| 1457 | + $this->board[$dest_pos] = $old_dest_tile; |
|
| 1458 | + if ( $en_passant_capture_performed ) { |
|
| 1459 | + // restore pawn that was captured above, since that move is invalid |
|
| 1460 | + if ( $cur_player == 'w' ) |
|
| 1461 | + $this->board[$dest_pos-8] = "bP"; |
|
| 1462 | + else |
|
| 1463 | + $this->board[$dest_pos+8] = "wP"; |
|
| 1464 | + } |
|
| 1465 | + return(array(false, _MD_CHESS_MOVE_IN_CHECK)); // "ERROR: Move is invalid because king would be under attack then." |
|
| 1466 | + } |
|
| 1467 | 1467 | |
| 1468 | 1468 | // check whether this forbids any castling |
| 1469 | 1469 | if ($fig_type == 'K') { |
@@ -1501,29 +1501,29 @@ discard block |
||
| 1501 | 1501 | $this->gamestate['fen_en_passant_target_square'] = '-'; |
| 1502 | 1502 | } |
| 1503 | 1503 | |
| 1504 | - if ($action == 'M' ) |
|
| 1505 | - $result = $this->move_msg(_MD_CHESS_MOVE_MOVED, $fig_name, $fig_coord, $dest_coord); |
|
| 1506 | - else |
|
| 1507 | - $result = $this->move_msg(_MD_CHESS_MOVE_CAPTURED, $fig_name, $dest_coord, $fig_coord); |
|
| 1504 | + if ($action == 'M' ) |
|
| 1505 | + $result = $this->move_msg(_MD_CHESS_MOVE_MOVED, $fig_name, $fig_coord, $dest_coord); |
|
| 1506 | + else |
|
| 1507 | + $result = $this->move_msg(_MD_CHESS_MOVE_CAPTURED, $fig_name, $dest_coord, $fig_coord); |
|
| 1508 | 1508 | |
| 1509 | - /* if pawn reached last line convert into a queen */ |
|
| 1510 | - if ( $fig_type == 'P' ) |
|
| 1511 | - { |
|
| 1512 | - if ( ($cur_player=='w' && $dest_pos>= 56) || |
|
| 1513 | - ($cur_player=='b' && $dest_pos<= 7 ) ) |
|
| 1514 | - { |
|
| 1515 | - $pawn_upg = $move[strlen($move)-1]; |
|
| 1516 | - if ( $pawn_upg == '?' ) |
|
| 1517 | - { |
|
| 1518 | - $pawn_upg = 'Q'; |
|
| 1519 | - $history_move = sprintf( "%sQ", $history_move ); |
|
| 1520 | - } |
|
| 1521 | - $this->board[$dest_pos] = "$cur_player$pawn_upg"; |
|
| 1522 | - $result .= ' ... ' . $this->move_msg(_MD_CHESS_MOVE_PROMOTED, $this->getFullFigureName($pawn_upg)); |
|
| 1523 | - } |
|
| 1524 | - } |
|
| 1509 | + /* if pawn reached last line convert into a queen */ |
|
| 1510 | + if ( $fig_type == 'P' ) |
|
| 1511 | + { |
|
| 1512 | + if ( ($cur_player=='w' && $dest_pos>= 56) || |
|
| 1513 | + ($cur_player=='b' && $dest_pos<= 7 ) ) |
|
| 1514 | + { |
|
| 1515 | + $pawn_upg = $move[strlen($move)-1]; |
|
| 1516 | + if ( $pawn_upg == '?' ) |
|
| 1517 | + { |
|
| 1518 | + $pawn_upg = 'Q'; |
|
| 1519 | + $history_move = sprintf( "%sQ", $history_move ); |
|
| 1520 | + } |
|
| 1521 | + $this->board[$dest_pos] = "$cur_player$pawn_upg"; |
|
| 1522 | + $result .= ' ... ' . $this->move_msg(_MD_CHESS_MOVE_PROMOTED, $this->getFullFigureName($pawn_upg)); |
|
| 1523 | + } |
|
| 1524 | + } |
|
| 1525 | 1525 | |
| 1526 | - $move_handled = 1; |
|
| 1526 | + $move_handled = 1; |
|
| 1527 | 1527 | } |
| 1528 | 1528 | |
| 1529 | 1529 | /* if a legal move was performed test whether you |
@@ -1752,19 +1752,19 @@ discard block |
||
| 1752 | 1752 | //echo $coord," --> "; |
| 1753 | 1753 | switch ( $coord[0] ) |
| 1754 | 1754 | { |
| 1755 | - case 'a': $x = 0; break; |
|
| 1756 | - case 'b': $x = 1; break; |
|
| 1757 | - case 'c': $x = 2; break; |
|
| 1758 | - case 'd': $x = 3; break; |
|
| 1759 | - case 'e': $x = 4; break; |
|
| 1760 | - case 'f': $x = 5; break; |
|
| 1761 | - case 'g': $x = 6; break; |
|
| 1762 | - case 'h': $x = 7; break; |
|
| 1763 | - default: return 64; /* erronous coord */ |
|
| 1755 | + case 'a': $x = 0; break; |
|
| 1756 | + case 'b': $x = 1; break; |
|
| 1757 | + case 'c': $x = 2; break; |
|
| 1758 | + case 'd': $x = 3; break; |
|
| 1759 | + case 'e': $x = 4; break; |
|
| 1760 | + case 'f': $x = 5; break; |
|
| 1761 | + case 'g': $x = 6; break; |
|
| 1762 | + case 'h': $x = 7; break; |
|
| 1763 | + default: return 64; /* erronous coord */ |
|
| 1764 | 1764 | } |
| 1765 | 1765 | $y = $coord[1]-1; |
| 1766 | 1766 | if ( $y < 0 || $y > 7 ) |
| 1767 | - return 64; /* erronous coord */ |
|
| 1767 | + return 64; /* erronous coord */ |
|
| 1768 | 1768 | $index = $y * 8 + $x; |
| 1769 | 1769 | //echo "$index | "; |
| 1770 | 1770 | return $index; |
@@ -1782,7 +1782,7 @@ discard block |
||
| 1782 | 1782 | { |
| 1783 | 1783 | //echo $index," --> "; |
| 1784 | 1784 | if ( $index < 0 || $index > 63 ) |
| 1785 | - return ""; |
|
| 1785 | + return ""; |
|
| 1786 | 1786 | $y = floor($index/8)+1; |
| 1787 | 1787 | $x = chr( ($index%8)+97 ); |
| 1788 | 1788 | $coord = "$x$y"; |