File Coverage

blib/lib/Games/Board/Grid.pm
Criterion Covered Total %
statement 42 43 97.6
branch 7 10 70.0
condition 6 6 100.0
subroutine 12 13 92.3
pod 7 7 100.0
total 74 79 93.6


line stmt bran cond sub pod time code
1 2     2   133783 use strict;
  2         22  
  2         59  
2 2     2   10 use warnings;
  2         4  
  2         118  
3              
4             package Games::Board::Grid 1.014;
5 2     2   868 use parent qw(Games::Board);
  2         612  
  2         10  
6             # ABSTRACT: a grid-shaped gameboard
7              
8 2     2   84 use Carp;
  2         5  
  2         779  
9              
10             #pod =head1 SYNOPSIS
11             #pod
12             #pod use Games::Board::Grid;
13             #pod
14             #pod my $chess = Games::Board->new(size => 8);
15             #pod
16             #pod my $rook = Games::Board::Piece->new(id => 'KR')->move(to => '7 7');
17             #pod
18             #pod =head1 DESCRIPTION
19             #pod
20             #pod This module provides a base class for representing a board made up of spaces on
21             #pod a right-angled grid.
22             #pod
23             #pod =cut
24              
25             #pod =method new
26             #pod
27             #pod my $board = Games::Board::Grid->new(size => $size);
28             #pod
29             #pod This method constructs a new game board and returns it. As constructed it has
30             #pod no spaces or pieces on it. The C argument may be an integer, to produce
31             #pod a square board, or an arrayref containing two integers, to produce a
32             #pod rectangular board.
33             #pod
34             #pod =cut
35              
36             sub new {
37 2     2 1 201 my ($class, %args) = @_;
38              
39 2 50       11 croak "no size given to construct grid" unless $args{size};
40              
41 2 50       14 $args{size} = [ ($args{size}) x 2 ] unless ref $args{size};
42              
43 2         7 my $board = { size => $args{size} };
44 2         4 bless $board => $class;
45 2         9 $board->init;
46             }
47              
48             #pod =method init
49             #pod
50             #pod This method sets up the spaces on the board.
51             #pod
52             #pod =cut
53              
54             sub init {
55 2     2 1 5 my $board = shift;
56              
57 2         13 $board->{spaces} = {};
58              
59 2         12 for my $x (0 .. ($board->{size}[0] - 1)) {
60 16         39 for my $y (0 .. ($board->{size}[1] - 1)) {
61 128         260 my $id = $board->index2id([$x,$y]);
62 128         758 $board->{spaces}{$id} = Games::Board::Grid::Space->new(id => $id, board => $board);
63             }
64             }
65              
66 2         7 $board;
67             }
68              
69             #pod =method size
70             #pod
71             #pod =cut
72              
73 68     68 1 229 sub size { (shift)->{size} }
74              
75             #pod =method id2index
76             #pod
77             #pod my $index = $board->id2index($id);
78             #pod
79             #pod This method returns the grid location of an identified space, in the format
80             #pod C<[$x, $y]>. In Games::Board::Grid, the index C<[x,y]> becomes the id C<'x
81             #pod y'>. Yeah, it's ugly, but it works.
82             #pod
83             #pod Reimplementing this method on a subclass can allow the use of idiomatic space
84             #pod identifiers on a grid. (See, for example, the chess-custom.t test in this
85             #pod distribution.)
86             #pod
87             #pod =cut
88              
89 21     21 1 77 sub id2index { [ split(/ /,$_[1]) ] }
90              
91             #pod =method index2id
92             #pod
93             #pod my $id = $board->index2id($index);
94             #pod
95             #pod This method performs the same translation as C, but in reverse.
96             #pod
97             #pod =cut
98              
99 79     79 1 100 sub index2id { join(q{ }, @{$_[1]}) }
  79         243  
100              
101             #pod =method space
102             #pod
103             #pod my $space = $board->space($id);
104             #pod
105             #pod This method returns the space with the given C<$id>. If no space with that id
106             #pod exists, undef is returned.
107             #pod
108             #pod =cut
109              
110             sub space {
111 47     47 1 8067 my $board = shift;
112 47         69 my $id = shift;
113              
114 47         207 return $board->{spaces}{$id};
115             }
116              
117             #pod =method add_space
118             #pod
119             #pod This method, provided by Games::Board, will croak immediately if called.
120             #pod
121             #pod =cut
122              
123 0     0 1 0 sub add_space { croak "spaces can't be added to grid board" }
124              
125             #pod =head2 Games::Board::Grid::Space
126             #pod
127             #pod The spaces on a grid board are blessed into this class. It acts like a
128             #pod L object, but directions are given as arrayrefs with x-
129             #pod and y-offsets. For example, a knight's move might be represented as:
130             #pod
131             #pod $board->space('1 0')->dir([2,1]);
132             #pod
133             #pod =cut
134              
135             package Games::Board::Grid::Space 1.014;
136 2     2   14 use parent qw(Games::Board::Space);
  2         4  
  2         25  
137              
138             sub dir_id {
139 42     42   79 my ($self, $dir) = @_;
140 42 50       119 return unless ref $dir eq 'ARRAY';
141              
142 42         106 my $pos = $self->board->id2index($self->id);
143              
144 42         326 my $newpos = [
145             $pos->[0] + $dir->[0],
146             $pos->[1] + $dir->[1]
147             ];
148              
149 42 100 100     193 return if $newpos->[0] < 0 or $newpos->[1] < 0;
150             return
151 36 100 100     83 if $newpos->[0] >= $self->board->size->[0]
152             or $newpos->[1] >= $self->board->size->[1];
153 30         65 return $self->board->index2id($newpos);
154             }
155              
156             "Family fun night!";
157              
158             __END__