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   697 use Modern::Perl '2018';
  1         2  
  1         21  
49 1     1   197 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 3 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 2991     2991 1 5901 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 139     139 1 307 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 4321     4321 1 8060 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 3878     3878 1 7164 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 13911     13911 1 17013 my $self = shift;
116             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 3
117 13911         20439 my ($hex, $i) = @_;
118 13911 50       21663 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
119 13911 50       27925 $hex = [$self->xy($hex)] unless ref $hex;
120 13911         41769 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 4990     4990 1 5970 my $self = shift;
145             # $hex is [x,y] or "0x0y" and $i is a number 0 .. 7
146 4990         6960 my ($hex, $i) = @_;
147 4990 50       7716 die join(":", caller) . ": undefined direction for $hex\n" unless defined $i;
148 4990 50       7585 die join(":", caller) . ": direction $i not supported for square $hex\n" if $i > 7;
149 4990 50       10380 $hex = [$self->xy($hex)] unless ref $hex;
150 4990         15044 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 6130     6130 1 10290 my $self = shift;
165 6130         8750 my ($x1, $y1, $x2, $y2) = @_;
166 6130 100       9338 if (@_ == 2) {
167 2438         3381 ($x1, $y1, $x2, $y2) = map { $self->xy($_) } @_;
  4876         7676  
168             }
169 6130         13176 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;