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 3     3   2235 use Modern::Perl '2018';
  3         8  
  3         31  
49 3     3   1109 use Mojo::Base -role;
  3         8  
  3         29  
50              
51             =head1 METHODS
52              
53             =head2 reverse
54              
55             Reverses a direction.
56              
57             =cut
58              
59             sub reverse {
60 2     2 1 8 my ($self, $i) = @_;
61 2         11 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 5819     5819 1 18137 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 269     269 1 870 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 8734     8734 1 21562 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 7832     7832 1 19248 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 27583     27583 1 45994 my $self = shift;
116             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 3
117 27583         66143 my ($hex, $i) = @_;
118 27583 50       61692 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
119 27583 50       87069 $hex = [$self->xy($hex)] unless ref $hex;
120 27583         116751 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 9984     9984 1 16083 my $self = shift;
145             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 7
146 9984         20229 my ($hex, $i) = @_;
147 9984 50       22200 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
148 9984 50       20260 die join(":", caller) . ": direction $i not supported for square $hex\n" if $i > 7;
149 9984 50       29296 $hex = [$self->xy($hex)] unless ref $hex;
150 9984         45724 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 10747     10747 1 32307 my $self = shift;
165 10747         35446 my ($x1, $y1, $x2, $y2) = @_;
166 10747 100       32249 if (@_ == 2) {
167 4504         8922 ($x1, $y1, $x2, $y2) = map { $self->xy($_) } @_;
  9008         21851  
168             }
169 10747         38552 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;