File Coverage

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   12 use List::Util qw(shuffle);
  2         2  
  2         131  
19 2     2   354 use Traveller::Util qw(nearby in);
  2         4  
  2         92  
20 2     2   1113 use Traveller::System::Classic::MPTS;
  2         5  
  2         12  
21 2     2   85 use Traveller::System::Classic;
  2         4  
  2         9  
22 2     2   41 use Traveller::System;
  2         3  
  2         7  
23 2     2   42 use Mojo::Base -base;
  2         3  
  2         5  
24              
25             has 'systems' => sub { [] };
26              
27             sub one {
28 1400     1400 0 1985 my $i = int(rand(scalar @_));
29 1400         2772 return $_[$i];
30             }
31              
32             sub compute_digraphs {
33 37     37 0 513 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 37         179 my @second = qw(a e i o u a e i o u a e i o u .);
38 37         57 my @d;
39 37         163 for (1 .. 10+rand(20)) {
40 700         1286 push(@d, one(@first));
41 700         1140 push(@d, one(@second));
42             }
43 37         302 return \@d;
44             }
45              
46             sub add {
47 679     679 0 1388 my ($self, $system) = @_;
48 679         1080 push(@{$self->systems}, $system);
  679         1695  
49             }
50              
51             sub init {
52 2     2 0 3024 my ($self, $width, $height, $rules, $density) = @_;
53 2   50     8 $density ||= 0.5;
54 2         8 my $digraphs = $self->compute_digraphs;
55 2   50     8 $width //= 8;
56 2   50     7 $height //= 10;
57 2         6 for my $x (1..$width) {
58 40         208 for my $y (1..$height) {
59 1360 100       6309 if (rand() < $density) {
60 679         904 my $system;
61 679 50       1744 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 679         1922 $system = Traveller::System->new();
67             }
68 679         5303 $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         38 for my $system (shuffle(grep { rand(20) < 1 } @{$self->systems})) {
  679         1312  
  2         7  
75 35         552 $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         58 return $self;
82             }
83              
84             sub spread {
85 35     35 0 131 my ($self, $system, $digraphs, $jump_distance, $jump_number) = @_;
86 35         124 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 35         88 my $network = [$system];
89 35         166 $self->grow($system, $jump_distance, $jump_number, $network);
90 35         126 for my $other (@$network) {
91 770         5101 $other->culture($culture);
92 770         5463 $other->name($other->compute_name($digraphs));
93             }
94             }
95              
96             sub grow {
97 413     413 0 1345 my ($self, $system, $jump_distance, $jump_number, $network) = @_;
98             my @new_neighbours =
99 963 100       5921 grep { not $_->culture or int(rand(2)) }
100 413         1617 grep { not Traveller::Util::in($_, @$network) }
  3077         8802  
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 413         3392 push(@$network, @new_neighbours);
106 413 100       2004 if ($jump_number > 0) {
107 216         690 for my $neighbour (@new_neighbours) {
108 378         2331 $self->grow($neighbour, $jump_distance, $jump_number - 1, $network);
109             }
110             }
111             }
112              
113             sub neighbours {
114 413     413 0 1072 my ($self, $system, $jump_distance, $jump_number) = @_;
115 413         2262 my @neighbours = nearby($system, $jump_distance, $self->systems);
116 413         2886 return @neighbours;
117             }
118              
119             sub str {
120 2     2 0 10 my $self = shift;
121 2         5 my $subsector;
122 2         5 foreach my $system (@{$self->systems}) {
  2         10  
123 679         1615 $subsector .= $system->str . "\n";
124             }
125 2         107 return $subsector;
126             }
127              
128             1;