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   849 use Modern::Perl '2018';
  1         3  
  1         10  
49 1     1   305 use Mojo::Base -role;
  1         4  
  1         10  
50              
51             =head1 METHODS
52              
53             =head2 reverse
54              
55             Reverses a direction.
56              
57             =cut
58              
59             sub reverse {
60 1     1 1 3 my ($self, $i) = @_;
61 1         8 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 3227     3227 1 6807 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 124     124 1 272 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 4295     4295 1 8098 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 3900     3900 1 7300 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 14154     14154 1 17544 my $self = shift;
116             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 3
117 14154         20709 my ($hex, $i) = @_;
118 14154 50       21943 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
119 14154 50       29491 $hex = [$self->xy($hex)] unless ref $hex;
120 14154         44057 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 4892     4892 1 6338 my $self = shift;
145             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 7
146 4892         7447 my ($hex, $i) = @_;
147 4892 50       7647 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
148 4892 50       7340 die join(":", caller) . ": direction $i not supported for square $hex\n" if $i > 7;
149 4892 50       10635 $hex = [$self->xy($hex)] unless ref $hex;
150 4892         15165 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 6210     6210 1 11140 my $self = shift;
165 6210         9150 my ($x1, $y1, $x2, $y2) = @_;
166 6210 100       9483 if (@_ == 2) {
167 2345         3224 ($x1, $y1, $x2, $y2) = map { $self->xy($_) } @_;
  4690         7553  
168             }
169 6210         13179 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;