File Coverage

blib/lib/Traveller/Subsector.pm
Criterion Covered Total %
statement 71 73 97.2
branch 8 10 80.0
condition 3 6 50.0
subroutine 14 14 100.0
pod 0 8 0.0
total 96 111 86.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             # Copyright (C) 2009-2021 Alex Schroeder
3             # Copyright (C) 2020 Christian Carey
4             #
5             # This program is free software: you can redistribute it and/or modify it under
6             # the terms of the GNU General Public License as published by the Free Software
7             # Foundation, either version 3 of the License, or (at your option) any later
8             # version.
9             #
10             # This program is distributed in the hope that it will be useful, but WITHOUT
11             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12             # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13             #
14             # You should have received a copy of the GNU General Public License along with
15             # this program. If not, see .
16              
17             package Traveller::Subsector;
18 2     2   17 use List::Util qw(shuffle);
  2         4  
  2         212  
19 2     2   444 use Traveller::Util qw(nearby in);
  2         4  
  2         114  
20 2     2   927 use Traveller::System::Classic::MPTS;
  2         7  
  2         30  
21 2     2   94 use Traveller::System::Classic;
  2         5  
  2         11  
22 2     2   56 use Traveller::System;
  2         4  
  2         12  
23 2     2   68 use Mojo::Base -base;
  2         4  
  2         11  
24              
25             has 'systems' => sub { [] };
26              
27             sub one {
28 1162     1162 0 1662 my $i = int(rand(scalar @_));
29 1162         2178 return $_[$i];
30             }
31              
32             sub compute_digraphs {
33 30     30 0 318 my @first = qw(b c d f g h j k l m n p q r s t v w x y z .
34             sc ng ch gh ph rh sh th wh zh wr qu
35             st sp tr tw fl dr pr dr);
36             # make missing vowel rare
37 30         176 my @second = qw(a e i o u a e i o u a e i o u .);
38 30         81 my @d;
39 30         132 for (1 .. 10+rand(20)) {
40 581         991 push(@d, one(@first));
41 581         936 push(@d, one(@second));
42             }
43 30         262 return \@d;
44             }
45              
46             sub add {
47 693     693 0 1453 my ($self, $system) = @_;
48 693         975 push(@{$self->systems}, $system);
  693         1407  
49             }
50              
51             sub init {
52 2     2 0 2774 my ($self, $width, $height, $rules, $density) = @_;
53 2   50     12 $density ||= 0.5;
54 2         10 my $digraphs = $self->compute_digraphs;
55 2   50     11 $width //= 8;
56 2   50     8 $height //= 10;
57 2         8 for my $x (1..$width) {
58 40         248 for my $y (1..$height) {
59 1360 100       5739 if (rand() < $density) {
60 693         942 my $system;
61 693 50       1551 if ($rules eq 'mpts') {
    50          
62 0         0 $system = Traveller::System::Classic::MPTS->new();
63             } elsif ($rules eq 'ct') {
64 0         0 $system = Traveller::System::Classic->new();
65             } else {
66 693         1854 $system = Traveller::System->new();
67             }
68 693         4722 $self->add($system->init($x, $y, $digraphs));
69             }
70             }
71             }
72             # Rename some systems: assume a jump-2 and a jump-1 culture per every
73             # subsector of 8×10×½ systems. Go through the list in random order.
74 2         11 for my $system (shuffle(grep { rand(20) < 1 } @{$self->systems})) {
  693         1201  
  2         10  
75 28         438 $self->spread(
76             $system,
77             $self->compute_digraphs,
78             1 + int(rand(2)), # jump distance
79             1 + int(rand(3))); # jump number
80             }
81 2         34 return $self;
82             }
83              
84             sub spread {
85 28     28 0 99 my ($self, $system, $digraphs, $jump_distance, $jump_number) = @_;
86 28         125 my $culture = $system->compute_name($digraphs);
87             # warn sprintf("%02d%02d %s %d %d\n", $system->x, $system->y, $culture, $jump_distance, $jump_number);
88 28         86 my $network = [$system];
89 28         132 $self->grow($system, $jump_distance, $jump_number, $network);
90 28         99 for my $other (@$network) {
91 607         3932 $other->culture($culture);
92 607         3569 $other->name($other->compute_name($digraphs));
93             }
94             }
95              
96             sub grow {
97 293     293 0 865 my ($self, $system, $jump_distance, $jump_number, $network) = @_;
98             my @new_neighbours =
99 731 100       4261 grep { not $_->culture or int(rand(2)) }
100 293         991 grep { not Traveller::Util::in($_, @$network) }
  2100         5072  
101             $self->neighbours($system, $jump_distance, $jump_number);
102             # for my $neighbour (@new_neighbours) {
103             # warn sprintf(" added %02d%02d %d %d\n", $neighbour->x, $neighbour->y, $jump_distance, $jump_number);
104             # }
105 293         2100 push(@$network, @new_neighbours);
106 293 100       1149 if ($jump_number > 0) {
107 143         428 for my $neighbour (@new_neighbours) {
108 265         1174 $self->grow($neighbour, $jump_distance, $jump_number - 1, $network);
109             }
110             }
111             }
112              
113             sub neighbours {
114 293     293 0 654 my ($self, $system, $jump_distance, $jump_number) = @_;
115 293         1282 my @neighbours = nearby($system, $jump_distance, $self->systems);
116 293         1551 return @neighbours;
117             }
118              
119             sub str {
120 2     2 0 9 my $self = shift;
121 2         5 my $subsector;
122 2         4 foreach my $system (@{$self->systems}) {
  2         10  
123 693         1444 $subsector .= $system->str . "\n";
124             }
125 2         73 return $subsector;
126             }
127              
128             1;