Games-PMM

 view release on metacpan or  search on metacpan

lib/Games/PMM/Arena.pm  view on Meta::CPAN


sub set_position
{
	my ($self, %args) = @_;

	my $coords   = $self->coordinates();
	my $monsters = $self->monsters();

	return unless $self->validate_position( %args );

	$coords->[ $args{x} ][ $args{y} ]   = $args{monster};
	$monsters->{ $args{monster}->id() } = [ $args{x}, $args{y} ];
}

sub validate_position
{
	my ($self, %args) = @_;
	my $coords        = $self->coordinates();

	return unless $self->within_bounds( %args );

	return if defined $coords->[ $args{x} ][ $args{y} ];
	return 1;
}

sub within_bounds
{
	my ($self, %args) = @_;
	my $coords        = $self->coordinates();

	return if $args{x} > $self->x_limit() or $args{y} > $self->y_limit();
	return if $args{x} < 0                or $args{y} < 0;

	return 1;
}

sub delete_position
{
	my ($self, %args) = @_;
	my $coords        = $self->coordinates();
	my $monsters      = $self->monsters();
	my $monster       = $coords->[ $args{ x } ][ $args{ y } ];

	$coords->[ $args{ x } ][ $args{ y } ] = undef;
	return unless $monster;
	delete $monsters->{ $monster->id() };
}

sub get_position
{
	my ($self, $monster) = @_;
	my $id               = $monster->id();
	my $monsters         = $self->monsters();

	return unless exists $monsters->{ $id };

	my ($x, $y)          = @{ $monsters->{ $id } }; 
	return { x => $x, y => $y };
}

sub update_position
{
	my ($self, $monster, %args)   = @_;
	my $old_pos                   = $self->get_position( $monster );

	return unless $self->validate_position( %args );

	$self->delete_position( monster => $monster, %$old_pos );
	$self->set_position(    monster => $monster,  %args );
}

sub get_monster
{
	my ($self, %args) = @_;
	my $coords        = $self->coordinates();

	return unless $self->within_bounds( %args );

	return $coords->[ $args{x} ][ $args{y} ];
}

for my $method
(
	{ name => 'forward', modifier => +1 },
	{ name => 'reverse', modifier => -1 },
)
{
	no strict 'refs';

	*{ $method->{name} } = sub
	{
		my ($self, $monster) = @_;

		my $pos        = $self->get_position( $monster );
		my $direction  = $monster->direction( $method->{modifier} );
		$pos->{x}     += $direction->{x};
		$pos->{y}     += $direction->{y};

		return unless $self->validate_position( %$pos );

		$self->update_position( $monster, %$pos );
	};
}

sub is_wall
{
	my ($self, %args) = @_;

	return 1 if $args{x} < 0 or $args{x} > $self->x_limit();
	return 1 if $args{y} < 0 or $args{y} > $self->y_limit();
	return;
}

sub get_distance
{
	my ($self, $pos, %to) = @_;

	my ($small_x, $big_x) = $self->minmax( $to{x}, $pos->{x} );
	my ($small_y, $big_y) = $self->minmax( $to{y}, $pos->{y} );

	return $big_x - $small_x + $big_y - $small_y;



( run in 0.663 second using v1.01-cache-2.11-cpan-99c4e6809bf )