File Coverage

blib/lib/Games/Maze/SVG/Rect.pm
Criterion Covered Total %
statement 94 97 96.9
branch 19 20 95.0
condition 4 5 80.0
subroutine 17 18 94.4
pod 10 10 100.0
total 144 150 96.0


line stmt bran cond sub pod time code
1             # SVG maze output
2             # Performs transformation, cleanup, and printing of output of Games::Maze
3              
4             package Games::Maze::SVG::Rect;
5              
6 28     28   226 use base Games::Maze::SVG;
  28         151  
  28         5340  
7              
8 28     28   174 use Carp;
  28         62  
  28         2572  
9 28     28   160 use Games::Maze;
  28         54  
  28         593  
10 28     28   152 use strict;
  28         54  
  28         1030  
11 28     28   152 use warnings;
  28         67  
  28         14731  
12              
13             =head1 NAME
14              
15             Games::Maze::SVG::Rect - Build rectangular mazes in SVG.
16              
17             =head1 VERSION
18              
19             Version 0.80
20              
21             =cut
22              
23             our $VERSION = 0.80;
24              
25             =head1 SYNOPSIS
26              
27             Games::Maze::SVG::Rect uses the Games::Maze module to create mazes in SVG.
28              
29             use Games::Maze::SVG;
30              
31             my $foo = Games::Maze::SVG->new( 'Rect' );
32             ...
33              
34             =cut
35              
36 28     28   403 use constant DELTA_X => 10;
  28         63  
  28         5072  
37 28     28   165 use constant DELTA_Y => 10;
  28         51  
  28         102248  
38              
39             # ----------------
40             # Shape transformation tables
41             my %Blocks = (
42             ': - |' => 'ul',
43             ':- |' => 'ur',
44             ': -| ' => 'll',
45             ':- | ' => 'lr',
46             ':-- ' => 'h',
47             '-:: ' => 'h',
48             ': ||' => 'v',
49             '| ::' => 'v',
50             ':- ' => 'l',
51             ': - ' => 'r',
52             ': | ' => 't',
53             ': |' => 'd',
54             ': -||' => 'tr',
55             ':- ||' => 'tl',
56             ':--| ' => 'tu',
57             ':-- |' => 'td',
58             ':--||' => 'cross',
59             ':.- |' => 'oul',
60             ':- .|' => 'our',
61             ': -.|' => 'oul',
62             ':-. |' => 'our',
63             ':.-.|' => 'oul',
64             ':-..|' => 'our',
65             ':.-| ' => 'oll',
66             ':-.| ' => 'olr',
67             ': -|.' => 'oll',
68             ':- |.' => 'olr',
69             ':.-|.' => 'oll',
70             ':-.|.' => 'olr',
71             ':--. ' => 'oh',
72             '-::. ' => 'oh',
73             ':-- .' => 'oh',
74             '-:: .' => 'oh',
75             ':. ||' => 'ov',
76             '|. ::' => 'ov',
77             ': .||' => 'ov',
78             '| .::' => 'ov',
79             ':- . ' => 'ol',
80             ': -. ' => 'or',
81             ':-. ' => 'ol',
82             ':.- ' => 'or',
83             ':- .' => 'ol',
84             ': - .' => 'or',
85             ':. | ' => 'ot',
86             ':. |' => 'od',
87             ': .| ' => 'ot',
88             ': . |' => 'od',
89             ': |.' => 'ot',
90             ': .|' => 'od',
91             ':. |.' => 'ot',
92             ':. .|' => 'od',
93             ': .|.' => 'ot',
94             ': ..|' => 'od',
95             ':.-||' => 'otr',
96             ':-.||' => 'otl',
97             ':--|.' => 'otu',
98             ':--.|' => 'otd',
99             );
100              
101             my %Walls = _get_wall_forms();
102              
103             =head1 FUNCTIONS
104              
105             =cut
106              
107             # ----------------------------------------------
108             # Subroutines
109              
110             =over 4
111              
112             =item new
113              
114             Create a new Games::Maze::SVG::Rect object. Supports the following named
115             parameters:
116              
117             =over 4
118              
119             =item wallform
120              
121             String naming the wall format. Legal values are bevel, round, roundcorners,
122             and straight.
123              
124             =item crumb
125              
126             String describing the breadcrumb design. Legal values are dash,
127             dot, line, and none
128              
129             =item dir
130              
131             Directory in which to find the ecmascript for the maze interactivity. Should
132             either be relative, or in URL form.
133              
134             =back
135              
136             =cut
137              
138             sub new
139             {
140 17     17 1 36 my $class = shift;
141              
142 17         80 my $obj = { Games::Maze::SVG::init_object( @_ ), @_, };
143              
144 17 100       145 if( !exists $Walls{ $obj->{wallform} } )
145             {
146 1         7 my $forms = join( ", ", sort keys %Walls );
147 1         168 croak "\n'$obj->{wallform}' is not a valid wall form.\nTry one of: $forms\n\n";
148             }
149              
150 16         154 $obj->{mazeparms}->{cell} = 'Quad';
151 16         47 $obj->{mazeparms}->{form} = 'Rectangle';
152 16         38 $obj->{scriptname} = "rectmaze.es";
153 16         43 $obj->{dx} = DELTA_X;
154 16         57 $obj->{dy} = DELTA_Y;
155              
156 16         96 return bless $obj, $class;
157             }
158              
159             =item is_hex
160              
161             Method always returns false.
162              
163             =cut
164              
165             sub is_hex
166             {
167 2     2 1 9861 return;
168             }
169              
170             =item is_hex_shaped
171              
172             Method always returns false.
173              
174             =cut
175              
176             sub is_hex_shaped
177             {
178 2     2 1 12 return;
179             }
180              
181             =item set_wall_form
182              
183             Set the wall format for the current maze.
184              
185             =over 4
186              
187             =item $form
188              
189             String specifying a wall format.
190              
191             =back
192              
193             Returns a reference to self for chaining.
194              
195             =cut
196              
197             sub set_wall_form
198             {
199 5     5 1 8780 my $self = shift;
200 5         13 my $form = shift;
201              
202 5 100       17 if( exists $Walls{$form} )
203             {
204 4         15 $self->{wallform} = $form;
205             }
206             else
207             {
208 1         11 my $forms = join( ", ", sort keys %Walls );
209 1         200 croak "\n'$form' is not a valid wall form.\nTry one of: $forms\n\n";
210             }
211 4         17 return $self;
212             }
213              
214             =item transform_grid
215              
216             Convert the rectangular grid from ascii format to SVG definition
217             references.
218              
219             =over 4
220              
221             =item $rows
222              
223             Reference to an array of rows
224              
225             =item $walls
226              
227             String specifying wall format.
228              
229             =back
230              
231             =cut
232              
233             sub transform_grid
234             {
235 15     15 1 70036 my $self = shift;
236 15         30 my $rows = shift;
237 15         33 my $walls = shift;
238 15         28 my @out = ();
239              
240 15 100 100     79 my $sp = 'bevel' eq ( $walls || q{} ) ? q{.} : q{ };
241 15         40 remove_horiz_padding( $rows );
242              
243             # transform the printout into block commands
244 15         30 my $height = @{$rows};
  15         25  
245 15         20 my $width = @{ $rows->[0] };
  15         29  
246 15         49 for ( my $r = 0; $r < $height; ++$r )
247             {
248 89         416 for ( my $c = 0; $c < $width; ++$c )
249             {
250 695 100       1392 if( $rows->[$r]->[$c] eq q{ } )
251             {
252 269         649 $out[$r]->[$c] = 0;
253             }
254             else
255             {
256              
257             # convert the cell and its neighbors into a signature
258 426 100 66     4296 my $sig = $rows->[$r]->[$c] # cell
    100          
    100          
259             . ( $c == 0 ? $sp : $rows->[$r]->[ $c - 1 ] ) # left neighbor
260             . ( $rows->[$r]->[ $c + 1 ] || $sp ) # right neighbor
261             . ( $r == 0 ? $sp : $rows->[ $r - 1 ]->[$c] ) # up neighbor
262             . ( $rows->[ $r + 1 ] ? $rows->[ $r + 1 ]->[$c] : $sp ); # down neighbor
263             # convert the signature into the block name
264 426 100       1952 croak "Missing block for '$sig'.\n" unless exists $Blocks{$sig};
265 424         1555 $out[$r]->[$c] = $Blocks{$sig};
266             }
267             }
268             }
269              
270 13         88 return @{$rows} = @out;
  13         183  
271             }
272              
273             =item remove_horiz_padding
274              
275             Remove the extra horizontal space inserted to regularize the look
276             of the rectangular maze
277              
278             =over 4
279              
280             =item $rows
281              
282             Reference to an array of rows
283              
284             =back
285              
286             =cut
287              
288             sub remove_horiz_padding
289             {
290 15     15 1 23 my $rows = shift;
291              
292 15         270 for ( my $i = $#{ $rows->[0] }; $i > 0; $i -= 3 )
  15         224  
293             {
294 39         261 splice( @{$_}, $i - 1, 1 ) foreach ( @{$rows} );
  39         74  
  305         888  
295             }
296              
297             # apparently trailing spaces that I wasn't aware of.
298 15         19 foreach my $r ( @{$rows} )
  15         29  
299             {
300 89 50       189 pop @{$r} if $r->[-1] eq q{ };
  0         0  
301             }
302              
303 15         47 return;
304             }
305              
306             =item wall_definitions
307              
308             Method that returns the definition for the shapes used to build the walls.
309              
310             =cut
311              
312             sub wall_definitions
313             {
314 0     0 1 0 my $self = shift;
315              
316 0         0 return $Walls{ $self->{wallform} };
317             }
318              
319             # _get_wall_forms
320             #
321             #Extract the wall forms from the DATA file handle.
322             #
323             #Returns a hash of wall forms.
324              
325             sub _get_wall_forms
326             {
327 28     28   219 local $/ = "\n===\n";
328 28         1204 chomp( my @list = );
329              
330 28         101 $/ = "\n";
331 28         70 chomp( @list );
332              
333 28         261 return @list;
334             }
335              
336             =item convert_start_position
337              
338             Convert the supplied x and y coordinates into the appropriate real coordinates
339             for a start position on this map.
340              
341             =over 4
342              
343             =item $x x coord from the maze
344              
345             =item $y y coord from the maze
346              
347             =back
348              
349             returns a two element list containing (x, y).
350              
351             =cut
352              
353             sub convert_start_position
354             {
355 2     2 1 1521 my $self = shift;
356 2         6 my ( $x, $y ) = @_;
357              
358 2         5 $x = 2 * ( $x - 1 ) + 1;
359 2         3 $y = 2 * ( $y - 1 );
360              
361 2         6 return ( $x, $y );
362             }
363              
364             =item convert_end_position
365              
366             Convert the supplied x and y coordinates into the appropriate real coordinates
367             for a end position on this map.
368              
369             =over 4
370              
371             =item $x x coord from the maze
372              
373             =item $y y coord from the maze
374              
375             =back
376              
377             returns a two element list containing (x, y).
378              
379             =cut
380              
381             sub convert_end_position
382             {
383 2     2 1 1647 my $self = shift;
384 2         3 my ( $x, $y ) = @_;
385              
386 2         5 $x = 2 * ( $x - 1 ) + 1;
387 2         5 $y = 2 * ( $y - 1 ) + 2;
388              
389 2         37 return ( $x, $y );
390             }
391              
392             =item convert_sign_position
393              
394             Convert the supplied x and y coordinates into the appropriate real coordinates
395             for a the position of the exit sign.
396              
397             =over 4
398              
399             =item $x x coord from the maze
400              
401             =item $y y coord from the maze
402              
403             =back
404              
405             returns a two element list containing (x, y).
406              
407             =cut
408              
409             sub convert_sign_position
410             {
411 4     4 1 2260 my $self = shift;
412 4         7 my ( $x, $y ) = @_;
413              
414 4         22 $x *= $self->dx();
415 4         12 $y *= $self->dy();
416              
417 4         13 $x += 0.5 * $self->dx();
418              
419             # adjust bottom
420 4 100       19 if( $y > $self->{height} / 2 )
421             {
422 2         8 $y += 2 * $self->dy();
423             }
424             else
425             {
426 2         7 $y -= $self->dy();
427             }
428              
429 4         13 return ( $x, $y );
430             }
431              
432             =back
433              
434             =head1 AUTHOR
435              
436             G. Wade Johnson, C<< >>
437              
438             =head1 BUGS
439              
440             Please report any bugs or feature requests to
441             C, or through the web interface at
442             L.
443             I will be notified, and then you'll automatically be notified of progress on
444             your bug as I make changes.
445              
446             =head1 ACKNOWLEDGEMENTS
447              
448             Thanks go to Valen Johnson and Jason Wood for extensive test play of the
449             mazes.
450              
451             =head1 COPYRIGHT & LICENSE
452              
453             Copyright 2004-2006 G. Wade Johnson, all rights reserved.
454              
455             This program is free software; you can redistribute it and/or modify it
456             under the same terms as Perl itself.
457              
458             =cut
459              
460             1;
461              
462             __DATA__