| Games-Battleship documentation | Contained in the Games-Battleship distribution. |
Games::Battleship::Player - A Battleship player class
use Games::Battleship::Player;
$aeryk = Games::Battleship::Player->new(name => 'Aeryk');
$gene = Games::Battleship::Player->new(name => 'Gene');
print 'Player 1: ', $aeryk->name, "\n",
'Player 2: ', $gene->name, "\n";
$aeryk->strike($gene, 0, 0);
# Repeat and get a duplicate strike warning.
$strike = $aeryk->strike($gene, 0, 0);
print $aeryk->grid($gene), "\nThat was a " .
( $strike == 1 ? 'hit!'
: $strike == 0 ? 'miss.'
: 'duplicate?' ), "\n";
$craft_obj = $aeryk->craft($id);
A Games::Battleship::Player object represents a Battleship player
complete with fleet and game surface.
$player => Games::Battleship::Player->new(
name => 'Aeryk',
fleet => \@fleet,
dimensions => [$x, $y],
);
An optional attribute provided to give the player a name.
If not provided, the string "player_1" or "player_2" is used.
Array reference of Games::Battleship::Craft objects.
If not explicitely provided, the standard fleet (with 5 ships) is created by default.
Array reference with the player's grid height and width values.
If the grid dimensions are not explicitly specified, the standard ten by ten grid is used.
$grid = $player->grid(); $grid = $player->grid($enemy);
Return the playing grid as a "flush-left" text matrix like this:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . S S S . . . . . . . . . . C . . . . . . . . A C . . . . D . . . A C . . B . D . . . A . . . B . . . . . A . . . B . . . . . A . . . B
Eventually, this method will respect the game type and return an apppropriate representation, such as a PNG file or XML, etc.
$strike = $player->strike($enemy, $x, $y);
Strike the enemy at the given coordinate and return a numeric value to indicate success or failure.
The player to strike must be given as a Games::Battleship::Player
object and the coordinate must be given as a numeric pair.
On success, an "x" is placed on the striking player's "opponent map
grid" (a Games::Battleship::Grid object attribute named for the
opponent) at the given coordinate, the opponent's "craft grid" is
updated by lowercasing the Games::Battleship::Craft object id
at the given coordinate, the opponent Games::Battleship::Craft
object hits attribute is incremented, the striking player's
score attribute is incremented, and a one (i.e. true) is returned.
If an enemy craft is completely destroyed, a happy warning is emitted.
On failure, an "o" is placed on the striking player's "opponent map grid" at the given coordinate and a zero (i.e. false) is returned.
If a player calls for a strike at a coordinate that was already struck, a warning is emitted and a negative one (-1) is returned.
$craft = $player->craft($id); $craft = $player->craft(id => $id); $craft = $player->craft(name => $name);
Return the player's Games::Battleship::Craft object that matches
the given argument(s).
If the last argument is not provided the first argument is assumed to
be the id attribute.
Return true or false if another player's strike is successful. That is, return a one if there is a craft at the given coordinate and zero otherwise.
Include a weapon argument in the strike method.
Make the grid method honor the game type and return something
appropriate.
Gene Boggs <gene@cpan.org>
See Games::Battleship.
| Games-Battleship documentation | Contained in the Games-Battleship distribution. |
# $Id: Player.pm,v 1.25 2004/08/25 08:36:50 gene Exp $ package Games::Battleship::Player; $VERSION = 0.05; use strict; use warnings; use Carp; use Games::Battleship::Craft; use Games::Battleship::Grid; sub new { my ($proto, %args) = @_; my $class = ref ($proto) || $proto; my $self = { id => $args{id} || undef, name => $args{name} || undef, score => $args{score} || 0, life => $args{life} || 0, fleet => $args{fleet} || [ Games::Battleship::Craft->new( name => 'aircraft carrier', points => 5, ), Games::Battleship::Craft->new( name => 'battleship', points => 4, ), Games::Battleship::Craft->new( name => 'cruiser', points => 3, ), Games::Battleship::Craft->new( name => 'submarine', points => 3, ), Games::Battleship::Craft->new( name => 'destroyer', points => 2, ), ], }; bless $self, $class; $self->_init(\%args); return $self; } sub _init { my ($self, $args) = @_; # Initialize a grid and place the player's fleet, if one is # provided. $self->{grid} = Games::Battleship::Grid->new( fleet => $self->{fleet}, dimensions => $args->{dimensions}, ); # Compute the life points for this player. $self->{life} += $_->{points} for @{ $self->{fleet} }; } sub name { return shift->{name} } # The enemy must be a G::B::Player object. sub grid { my ($self, $enemy) = @_; return $enemy ? join "\n", map { "@$_" } @{ $self->{$enemy->{name}}{matrix} } : join "\n", map { "@$_" } @{ $self->{grid}{matrix} }; } # The enemy must be a G::B::Player object. sub strike { my ($self, $enemy, $x, $y) = @_; croak "No opponent to strike.\n" unless $enemy; croak "No coordinate at which to strike.\n" unless defined $x && defined $y; if ($enemy->{life} > 0) { # Initialize the enemy grid map if we need to. $self->{$enemy->{name}} = Games::Battleship::Grid->new unless exists $self->{$enemy->{name}}; my $enemy_pos = \$enemy->{grid}{matrix}[$x][$y]; my $map_pos = \$self->{$enemy->{name}}{matrix}[$x][$y]; if ($$map_pos ne '.') { warn "Duplicate strike on $enemy->{name} by $self->{name} at $x, $y.\n"; return -1; } elsif ($enemy->_is_a_hit($x, $y)) { # Set the enemy grid map coordinate char to 'hit'. $$map_pos = 'x'; # What craft was hit? my $craft = $self->craft(id => $$enemy_pos); warn "$self->{name} hit $enemy->{name}'s $craft->{name}!\n"; # How much is left on this craft? my $remainder = $craft->hit; # Tally the hit in the craft object, itself and emit a happy # warning if it was totally destroyed. warn "$self->{name} sunk $enemy->{name}'s $craft->{name}!\n" unless $remainder; # Indicate the hit on the enemy grid by lowercasing the craft # id. $$enemy_pos = lc $$enemy_pos; # Increment the player's score. $self->{score}++; # Decrement the opponent's life. warn "$enemy->{name} is out of the game.\n" if --$enemy->{life} <= 0; return 1; } else { # Set the enemy grid map coordinate char to 'miss'. warn "$self->{name} missed $enemy->{name} at $x, $y.\n"; $$map_pos = 'o'; return 0; } } else { warn "$enemy->{name} is already out of the game. Strike another opponent.\n"; return -1; } } sub _is_a_hit { my ($self, $x, $y) = @_; return $self->{grid}{matrix}[$x][$y] ne '.' ? 1 : 0; } sub craft { my ($self, $key, $val) = @_; # If the key is not defined, assume it's supposed to be the id. unless (defined $val) { $val = $key; $key = 'id'; } my $craft; for (@{ $self->{fleet} }) { if ($val eq $_->{$key}) { $craft = $_; last; } } return $craft; } 1; __END__