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; |