Chess
view release on metacpan or search on metacpan
lib/Chess/Game.pm view on Meta::CPAN
$obj_data->{message} = "Not your turn";
return 0;
}
return 0 unless ($piece->can_reach($sq2));
my $capture = $board->get_piece_at($sq2);
if (defined($capture)) {
unless ($capture->get_player() ne $player) {
$obj_data->{message} = "You can't capture your own piece";
return 0;
}
if ($piece->isa('Chess::Piece::Pawn')) {
unless (abs(Chess::Board->horz_distance($sq1, $sq2)) == 1) {
$obj_data->{message} = "Pawns may only capture diagonally";
return 0;
}
}
elsif ($piece->isa('Chess::Piece::King')) {
unless (abs(Chess::Board->horz_distance($sq1, $sq2)) < 2) {
$obj_data->{message} = "You can't capture while castling";
return 0;
}
}
}
else {
if ($piece->isa('Chess::Piece::Pawn')) {
my $ml = $obj_data->{movelist};
unless (Chess::Board->horz_distance($sq1, $sq2) == 0 or
_is_valid_en_passant($obj_data, $piece, $sq1, $sq2)) {
$obj_data->{message} = "Pawns must capture on a diagonal move";
return 0;
}
}
}
my $valid_castle = 0;
my $clone = $self->clone();
my $r_clone = _get_game($$clone);
my $king = $r_clone->{_kings}[($player eq $player1 ? 0 : 1)];
if ($piece->isa('Chess::Piece::King')) {
my $hdist = Chess::Board->horz_distance($sq1, $sq2);
if (abs($hdist) == 2) {
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Can't castle out of check";
return 0;
}
if ($hdist > 0) {
return 0 unless (_is_valid_short_castle($obj_data, $piece, $sq1, $sq2));
$valid_castle = MOVE_CASTLE_SHORT;
}
else {
return 0 unless (_is_valid_long_castle($obj_data, $piece, $sq1, $sq2));
$valid_castle = MOVE_CASTLE_LONG;
}
}
}
elsif (!$piece->isa('Chess::Piece::Knight')) {
my $board_c = $board->clone();
$board_c->set_piece_at($sq1, undef);
$board_c->set_piece_at($sq2, undef);
unless ($board_c->line_is_open($sq1, $sq2)) {
$obj_data->{message} = "Line '$sq1' - '$sq2' is blocked";
return 0;
}
}
if (!$valid_castle) {
$clone->make_move($sq1, $sq2, 0);
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Move leaves your king in check";
return 0;
}
}
else {
if ($valid_castle == MOVE_CASTLE_SHORT) {
my $tsq = Chess::Board->square_right_of($sq1);
$clone->make_move($sq1, $tsq, 0);
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Can't castle through check";
return 0;
}
$clone->make_move($tsq, $sq2, 0);
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Move leaves your king in check";
return 0;
}
}
else {
my $tsq = Chess::Board->square_left_of($sq1);
$clone->make_move($sq1, $tsq, 0);
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Can't castle through check";
return 0;
}
$clone->make_move($tsq, $sq2, 0);
_mark_threatened_kings($r_clone);
unless (!$king->threatened()) {
$obj_data->{message} = "Move leaves your king in check";
return 0;
}
}
}
$obj_data->{message} = '';
return 1;
}
sub make_move {
my ($self, $sq1, $sq2, $validate) = @_;
my $move;
$validate = 1 unless (defined($validate));
unless (Chess::Board->square_is_valid($sq1)) {
carp "Invalid square '$sq1'";
return undef;
}
unless (Chess::Board->square_is_valid($sq2)) {
carp "Invalid square '$sq2'";
return undef;
}
if ($validate) {
( run in 2.128 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )