File Coverage

blib/lib/Karel/Grid.pm
Criterion Covered Total %
statement 59 59 100.0
branch 10 10 100.0
condition 2 2 100.0
subroutine 18 18 100.0
pod 6 7 85.7
total 95 96 98.9


line stmt bran cond sub pod time code
1             package Karel::Grid;
2              
3             =head1 NAME
4              
5             Karel::Grid
6              
7             =head1 DESCRIPTION
8              
9             Represents the map in which the robot moves.
10              
11             =head1 METHODS
12              
13             =over 4
14              
15             =item 'Karel::Grid'->new
16              
17             my $grid = 'Karel::Grid'->new( x => 10, y => 12 );
18              
19             The constructor creates an empty grid of the given size.
20              
21             =cut
22              
23 8     8   79108 use warnings;
  8         11  
  8         197  
24 8     8   27 use strict;
  8         8  
  8         111  
25              
26 8     8   22 use Carp;
  8         6  
  8         432  
27 8     8   2261 use Karel::Util qw{ positive_int m_to_n };
  8         11  
  8         385  
28 8     8   34 use List::Util qw{ any none };
  8         11  
  8         500  
29 8     8   2961 use Moo;
  8         62412  
  8         32  
30 8     8   9939 use namespace::clean;
  8         54241  
  8         33  
31              
32             =item $grid->x, $grid->y
33              
34             my ($x, $y) = map $grid->$_, qw( x y );
35              
36             Returns the size of the grid.
37              
38             =cut
39              
40             has [qw[ x y ]] => (is => 'ro',
41             isa => \&positive_int,
42             required => 1,
43             );
44              
45              
46             has _grid => ( is => 'rw',
47             isa => sub {
48             croak "Grid should be an AoA!"
49             if 'ARRAY' ne ref $_[0]
50             || any { 'ARRAY' ne ref } @{ $_[0] };
51             },
52             );
53              
54             # Create an empty grid
55             sub BUILD {
56 61     61 0 561 my ($self) = @_;
57 61         299 my ($x, $y) = map $self->$_, qw( x y );
58 61         1199 $self->_grid([ map [ (' ') x ($y + 2) ], 0 .. $x + 1 ]);
59 61         653 $self->_set($_, 0, 'W'), $self->_set($_, $y + 1, 'W') for 0 .. $x + 1;
60 61         390 $self->_set(0, $_, 'W'), $self->_set($x + 1, $_, 'W') for 0 .. $y + 1;
61 61         951 return $self
62             }
63              
64             =item $grid->at($x, $y)
65              
66             Returns a space if there's nothing at the given position. For marks,
67             it returns 1 - 9. For walls, it returns "W" (outer walls) or "w"
68             (inner walls).
69              
70             =cut
71              
72             sub at {
73 243     243 1 2869 my ($self, $x, $y) = @_;
74 243         500 m_to_n($x, 0, $self->x + 1);
75 242         460 m_to_n($y, 0, $self->y + 1);
76 242         3635 return $self->_grid->[$x][$y]
77             }
78              
79              
80             sub _set {
81 1423     1423   4746 my ($self, $x, $y, $what) = @_;
82 1423         2541 m_to_n($x, 0, $self->x + 1);
83 1423         2510 m_to_n($y, 0, $self->y + 1);
84             croak "Unknown object '$what'."
85 1423 100   16091   5142 if none { $_ eq $what } ' ', '0' .. '9', 'w', 'W';
  16091         9980  
86 1422         20825 $self->_grid->[$x][$y] = $what;
87             }
88              
89             =item $grid->build_wall($x, $y)
90              
91             Builds a wall ("w") at the given coordinates.
92              
93             =cut
94              
95             sub build_wall {
96 10     10 1 135 my ($self, $x, $y) = @_;
97 10         28 m_to_n($x, 1, $self->x);
98 10         22 m_to_n($y, 1, $self->y);
99 10         15 $self->_set($x, $y, 'w');
100             }
101              
102             =item $gird->remove_wall($x, $y)
103              
104             Removes a wall ("w") from the given coordinates. Dies if there's no
105             wall.
106              
107             =cut
108              
109             sub remove_wall {
110 2     2 1 246 my ($self, $x, $y) = @_;
111 2 100       4 croak "Not a removable wall at $x, $y." unless 'w' eq $self->at($x, $y);
112 1         8 $self->_set($x, $y, ' ');
113             }
114              
115             =item $grid->drop_mark($x, $y)
116              
117             Drop a mark at the given position. There must be an empty place or
118             less than 9 marks, otherwise the method dies.
119              
120             =cut
121              
122             sub drop_mark {
123 138     138 1 1059 my ($self, $x, $y) = @_;
124 138         171 my $previous = $self->at($x, $y);
125             croak "Can't drop mark to '$previous'."
126 138 100   598   844 if none { $_ eq $previous } ' ', '1' .. '8';
  598         553  
127 137 100       315 $previous = 0 if ' ' eq $previous;
128 137         207 $self->_set($x, $y, $previous + 1);
129             }
130              
131             =item $grid->pick_mark($x, $y)
132              
133             Pick up a mark from the given position. Dies if there's no mark.
134              
135             =cut
136              
137             sub pick_mark {
138 30     30 1 503 my ($self, $x, $y) = @_;
139 30         43 my $previous = $self->at($x, $y);
140             croak "Can't pick mark from '$previous'."
141 30 100   153   230 if none { $_ eq $previous } '1' .. '9';
  153         172  
142 29   100     115 $self->_set($x, $y, ($previous - 1) || ' ');
143             }
144              
145             =item $grid->clear($x, $y)
146              
147             Set the given position to empty (" ").
148              
149             =cut
150              
151             sub clear {
152 106     106 1 234 my ($self, $x, $y) = @_;
153 106         222 m_to_n($x, 1, $self->x);
154 105         173 m_to_n($y, 1, $self->y);
155 105         137 $self->_set($x, $y, ' ');
156             }
157              
158             =back
159              
160             =cut
161              
162             __PACKAGE__