/usr/local/CPAN/Games-Checkers/Games/Checkers/MoveLocationConstructor.pm
# Games::Checkers, Copyright (C) 1996-2004 Mikhael Goikhman
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
use strict;
package Games::Checkers::MoveLocationConstructor;
use base 'Games::Checkers::Board';
use Games::Checkers::Constants;
use Games::Checkers::BoardConstants;
use Games::Checkers::MoveConstants;
use constant MAX_MOVE_JUMP_NUM => 9;
sub new ($$$) {
my $class = shift;
my $board = shift;
my $color = shift;
my $self = $class->SUPER::new($board);
my $fields = {
color => $color,
destin => [],
src => NL,
piece => 0,
mustBeat => $board->canColorBeat($color),
origBoard => $board,
};
$self->{$_} = $fields->{$_} foreach keys %$fields;
return $self;
}
sub init ($) {
my $self = shift;
$self->{destin} = [];
$self->{src} = NL;
$self->copy($self->{origBoard});
}
sub source ($$) {
my $self = shift;
my $loc = shift;
$self->init;
return Err if $loc == NL || !$self->occup($loc) || $self->color($loc) != $self->{color};
return Err if $self->{mustBeat} && !$self->canPieceBeat($loc) || !$self->{mustBeat} && !$self->canPieceStep($loc);
$self->{piece} = $self->piece($self->{src} = $loc);
return Ok;
}
sub addDst ($$) {
my $self = shift;
my $dst = shift;
return Err if $self->{src} == NL || @{$self->{destin}} == MAX_MOVE_JUMP_NUM-1;
if ($self->{mustBeat}) {
die "Internal" unless $self->occup($self->dst_1);
return Err unless $self->canPieceBeat($self->dst_1, $dst);
} else {
return Err if @{$self->{destin}} > 0;
return Err unless $self->canPieceStep($self->{src}, $dst);
}
push @{$self->{destin}}, $dst;
$self->transformOne;
return Ok;
}
sub delDst ($) {
my $self = shift;
return NL if $self->{src} == NL || @{$self->{destin}} == 0;
my $dst = pop @{$self->{destin}};
$self->transformAll;
return $dst;
}
sub canCreateMove ($) {
my $self = shift;
return $self->{mustBeat} && @{$self->{destin}} > 0
&& $self->canPieceBeat($self->dst_1) == No
|| !$self->{mustBeat} && @{$self->{destin}} == 1;
}
sub createMove ($) {
my $self = shift;
return NO_MOVE if $self->{src} == NL
|| $self->{mustBeat} && @{$self->{destin}} < 1
|| !$self->{mustBeat} && @{$self->{destin}} != 1;
return new Games::Checkers::Move(
$self->{mustBeat}, $self->{src}, $self->{destin});
}
sub transformOne ($) {
my $self = shift;
my $src = $self->dst_2;
my $dst = $self->dst_1;
$self->clr($src);
$self->set($dst, $self->{color}, $self->{piece});
$self->clr($self->figureBetween($src, $dst)) if $self->{mustBeat};
if (convertType->[$self->{color}][$self->{piece}] & (1 << $dst)) {
$self->{pieceMap} ^= (1 << $dst);
$self->{piece} ^= 1;
}
}
sub transformAll ($) {
my $self = shift;
$self->copy($self->{origBoard});
return if $self->{src} == NL || @{$self->{destin}} == 0;
$self->{piece} = $self->piece($self->{src});
my $destin = $self->{destin};
$self->{destin} = [];
while (@$destin) {
push @{$self->{destin}}, shift @$destin;
$self->transformOne;
}
}
sub dst_1 ($) {
my $self = shift;
return @{$self->{destin}} == 0? $self->{src}: $self->{destin}->[-1];
}
sub dst_2 ($) {
my $self = shift;
return @{$self->{destin}} == 1? $self->{src}: $self->{destin}->[-2];
}
1;