| 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
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
144
|
|
|
19
|
2
|
|
|
2
|
|
375
|
use Traveller::Util qw(nearby in); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
92
|
|
|
20
|
2
|
|
|
2
|
|
779
|
use Traveller::System::Classic::MPTS; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
19
|
|
|
21
|
2
|
|
|
2
|
|
66
|
use Traveller::System::Classic; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
10
|
|
|
22
|
2
|
|
|
2
|
|
44
|
use Traveller::System; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
8
|
|
|
23
|
2
|
|
|
2
|
|
51
|
use Mojo::Base -base; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
6
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
has 'systems' => sub { [] }; |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub one { |
|
28
|
2538
|
|
|
2538
|
0
|
3550
|
my $i = int(rand(scalar @_)); |
|
29
|
2538
|
|
|
|
|
4392
|
return $_[$i]; |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub compute_digraphs { |
|
33
|
64
|
|
|
64
|
0
|
645
|
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
|
64
|
|
|
|
|
360
|
my @second = qw(a e i o u a e i o u a e i o u .); |
|
38
|
64
|
|
|
|
|
131
|
my @d; |
|
39
|
64
|
|
|
|
|
237
|
for (1 .. 10+rand(20)) { |
|
40
|
1269
|
|
|
|
|
2152
|
push(@d, one(@first)); |
|
41
|
1269
|
|
|
|
|
1898
|
push(@d, one(@second)); |
|
42
|
|
|
|
|
|
|
} |
|
43
|
64
|
|
|
|
|
408
|
return \@d; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub add { |
|
47
|
1283
|
|
|
1283
|
0
|
2219
|
my ($self, $system) = @_; |
|
48
|
1283
|
|
|
|
|
1607
|
push(@{$self->systems}, $system); |
|
|
1283
|
|
|
|
|
2275
|
|
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub init { |
|
52
|
2
|
|
|
2
|
0
|
2053
|
my ($self, $width, $height, $rules, $density) = @_; |
|
53
|
2
|
|
50
|
|
|
9
|
$density ||= 0.5; |
|
54
|
2
|
|
|
|
|
11
|
my $digraphs = $self->compute_digraphs; |
|
55
|
2
|
|
50
|
|
|
17
|
$width //= 8; |
|
56
|
2
|
|
50
|
|
|
9
|
$height //= 10; |
|
57
|
2
|
|
|
|
|
7
|
for my $x (1..$width) { |
|
58
|
64
|
|
|
|
|
241
|
for my $y (1..$height) { |
|
59
|
2560
|
100
|
|
|
|
9530
|
if (rand() < $density) { |
|
60
|
1283
|
|
|
|
|
1616
|
my $system; |
|
61
|
1283
|
50
|
|
|
|
2705
|
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
|
1283
|
|
|
|
|
3100
|
$system = Traveller::System->new(); |
|
67
|
|
|
|
|
|
|
} |
|
68
|
1283
|
|
|
|
|
7903
|
$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
|
|
|
|
|
10
|
for my $system (shuffle(grep { rand(20) < 1 } @{$self->systems})) { |
|
|
1283
|
|
|
|
|
1973
|
|
|
|
2
|
|
|
|
|
9
|
|
|
75
|
62
|
|
|
|
|
873
|
$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
|
|
|
|
|
44
|
return $self; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub spread { |
|
85
|
62
|
|
|
62
|
0
|
189
|
my ($self, $system, $digraphs, $jump_distance, $jump_number) = @_; |
|
86
|
62
|
|
|
|
|
249
|
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
|
62
|
|
|
|
|
192
|
my $network = [$system]; |
|
89
|
62
|
|
|
|
|
254
|
$self->grow($system, $jump_distance, $jump_number, $network); |
|
90
|
62
|
|
|
|
|
228
|
for my $other (@$network) { |
|
91
|
1437
|
|
|
|
|
9164
|
$other->culture($culture); |
|
92
|
1437
|
|
|
|
|
8413
|
$other->name($other->compute_name($digraphs)); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub grow { |
|
97
|
715
|
|
|
715
|
0
|
1962
|
my ($self, $system, $jump_distance, $jump_number, $network) = @_; |
|
98
|
|
|
|
|
|
|
my @new_neighbours = |
|
99
|
1830
|
100
|
|
|
|
10065
|
grep { not $_->culture or int(rand(2)) } |
|
100
|
715
|
|
|
|
|
2293
|
grep { not Traveller::Util::in($_, @$network) } |
|
|
5485
|
|
|
|
|
12290
|
|
|
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
|
715
|
|
|
|
|
5066
|
push(@$network, @new_neighbours); |
|
106
|
715
|
100
|
|
|
|
2650
|
if ($jump_number > 0) { |
|
107
|
363
|
|
|
|
|
876
|
for my $neighbour (@new_neighbours) { |
|
108
|
653
|
|
|
|
|
2432
|
$self->grow($neighbour, $jump_distance, $jump_number - 1, $network); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub neighbours { |
|
114
|
715
|
|
|
715
|
0
|
1643
|
my ($self, $system, $jump_distance, $jump_number) = @_; |
|
115
|
715
|
|
|
|
|
2501
|
my @neighbours = nearby($system, $jump_distance, $self->systems); |
|
116
|
715
|
|
|
|
|
3071
|
return @neighbours; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub str { |
|
120
|
2
|
|
|
2
|
0
|
10
|
my $self = shift; |
|
121
|
2
|
|
|
|
|
6
|
my $subsector; |
|
122
|
2
|
|
|
|
|
4
|
foreach my $system (@{$self->systems}) { |
|
|
2
|
|
|
|
|
11
|
|
|
123
|
1283
|
|
|
|
|
2625
|
$subsector .= $system->str . "\n"; |
|
124
|
|
|
|
|
|
|
} |
|
125
|
2
|
|
|
|
|
158
|
return $subsector; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
1; |