File Coverage

blib/lib/Game/TextMapper/Schroeder/Square.pm
Criterion Covered Total %
statement 29 33 87.8
branch 7 12 58.3
condition n/a
subroutine 10 11 90.9
pod 9 9 100.0
total 55 65 84.6


line stmt bran cond sub pod time code
1             # Copyright (C) 2009-2021 Alex Schroeder
2             #
3             # This program is free software: you can redistribute it and/or modify it under
4             # the terms of the GNU Affero General Public License as published by the Free
5             # Software Foundation, either version 3 of the License, or (at your option) any
6             # later version.
7             #
8             # This program is distributed in the hope that it will be useful, but WITHOUT
9             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10             # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11             # details.
12             #
13             # You should have received a copy of the GNU Affero General Public License along
14             # with this program. If not, see .
15              
16             =encoding utf8
17              
18             =head1 NAME
19              
20             Game::TextMapper::Schroeder::Square - a role for square map generators
21              
22             =head1 SYNOPSIS
23              
24             # create a map
25             package World;
26             use Modern::Perl;
27             use Mojo::Base -base;
28             use Role::Tiny::With;
29             with 'Game::TextMapper::Schroeder::Base';
30             with 'Game::TextMapper::Schroeder::Square';
31             # use it
32             package main;
33             my $map = World->new(height => 10, width => 10);
34              
35             =head1 DESCRIPTION
36              
37             This role provides basic functionality for map generation with square maps: the
38             number of neighbours within one or two regions distance, how to pick a random
39             neighbour direction, how to compute the coordinates of these neighbours, how to
40             draw arrows towards these neighbours.
41              
42             This inherits attributes and methods from L,
43             such as C and C.
44              
45             =cut
46              
47             package Game::TextMapper::Schroeder::Square;
48 1     1   664 use Modern::Perl '2018';
  1         3  
  1         9  
49 1     1   194 use Mojo::Base -role;
  1         3  
  1         8  
50              
51             =head1 METHODS
52              
53             =head2 reverse
54              
55             Reverses a direction.
56              
57             =cut
58              
59             sub reverse {
60 1     1 1 4 my ($self, $i) = @_;
61 1         5 return ($i + 2) % 4;
62             }
63              
64             =head2 neighbors
65              
66             The list of directions for neighbours one step away (0 to 3).
67              
68             =cut
69              
70 2742     2742 1 5503 sub neighbors { 0 .. 3 }
71              
72             =head2 neighbors2
73              
74             The list of directions for neighbours two steps away (0 to 7).
75              
76             =cut
77              
78 117     117 1 255 sub neighbors2 { 0 .. 7 }
79              
80             =head2 random_neighbor
81              
82             A random direction for a neighbour one step away (a random integer from 0 to 3).
83              
84             =cut
85              
86 4346     4346 1 7845 sub random_neighbor { int(rand(4)) }
87              
88             =head2 random_neighbor2
89              
90             A random direction for a neighbour two steps away (a random integer from 0 to
91             7).
92              
93             =cut
94              
95 3938     3938 1 6928 sub random_neighbor2 { int(rand(8)) }
96              
97             my $delta_square = [[-1, 0], [ 0, -1], [+1, 0], [ 0, +1]];
98              
99             =head2 neighbor($square, $i)
100              
101             say join(",", $map->neighbor("0203", 1));
102             # 2,2
103              
104             Returns the coordinates of a neighbor in a particular direction (0 to 3), one
105             step away.
106              
107             C<$square> is an array reference of coordinates or a string that can be turned
108             into one using the C method from L.
109              
110             C<$i> is a direction (0 to 3).
111              
112             =cut
113              
114             sub neighbor {
115 13761     13761 1 16278 my $self = shift;
116             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 3
117 13761         19446 my ($hex, $i) = @_;
118 13761 50       20583 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
119 13761 50       28834 $hex = [$self->xy($hex)] unless ref $hex;
120 13761         40867 return ($hex->[0] + $delta_square->[$i]->[0],
121             $hex->[1] + $delta_square->[$i]->[1]);
122             }
123              
124             my $delta_square2 = [
125             [-2, 0], [-1, -1], [ 0, -2], [+1, -1],
126             [+2, 0], [+1, +1], [ 0, +2], [-1, +1]];
127              
128             =head2 neighbor2($square, $i)
129              
130             say join(",", $map->neighbor2("0203", 1));
131             # 1, 2
132              
133             Returns the coordinates of a neighbor in a particular direction (0 to 7), two
134             steps away.
135              
136             C<$square> is an array reference of coordinates or a string that can be turned
137             into one using the C method from L.
138              
139             C<$i> is a direction (0 to 3).
140              
141             =cut
142              
143             sub neighbor2 {
144 4874     4874 1 5935 my $self = shift;
145             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 7
146 4874         6860 my ($hex, $i) = @_;
147 4874 50       7381 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
148 4874 50       7358 die join(":", caller) . ": direction $i not supported for square $hex\n" if $i > 7;
149 4874 50       10540 $hex = [$self->xy($hex)] unless ref $hex;
150 4874         14342 return ($hex->[0] + $delta_square2->[$i]->[0],
151             $hex->[1] + $delta_square2->[$i]->[1]);
152             }
153              
154             =head2 distance($x1, $y1, $x2, $y2) or distance($coords1, $coords2)
155              
156             say $map->distance("0203", "0003");
157             # 2
158              
159             Returns the distance between two coordinates.
160              
161             =cut
162              
163             sub distance {
164 6269     6269 1 9553 my $self = shift;
165 6269         8748 my ($x1, $y1, $x2, $y2) = @_;
166 6269 100       9294 if (@_ == 2) {
167 2521         3252 ($x1, $y1, $x2, $y2) = map { $self->xy($_) } @_;
  5042         7750  
168             }
169 6269         12818 return abs($x2 - $x1) + abs($y2 - $y1);
170             }
171              
172             =head2 arrows
173              
174             A helper that returns the SVG fragments for arrows in four directions, to be
175             used in a C element.
176              
177             =cut
178              
179             sub arrows {
180 0     0 1   my $self = shift;
181             return
182             qq{},
183             qq{},
184             map {
185 0           my $angle = 90 * $_;
  0            
186 0           qq{},
187             qq{},
188             } ($self->neighbors());
189             }
190              
191             =head1 SEE ALSO
192              
193             L
194             L
195              
196             =cut
197              
198             1;