| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Games::Lacuna::Task::Action::Mining; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
2297
|
use 5.010; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
57
|
|
|
4
|
|
|
|
|
|
|
our $VERSION = $Games::Lacuna::Task::VERSION; |
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
411
|
use Moose; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
extends qw(Games::Lacuna::Task::Action); |
|
8
|
|
|
|
|
|
|
with qw(Games::Lacuna::Task::Role::Stars |
|
9
|
|
|
|
|
|
|
Games::Lacuna::Task::Role::Ships |
|
10
|
|
|
|
|
|
|
Games::Lacuna::Task::Role::PlanetRun); |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use List::Util qw(sum); |
|
13
|
|
|
|
|
|
|
use Games::Lacuna::Client::Types qw(ore_types); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub description { |
|
16
|
|
|
|
|
|
|
return q[Deploy mining platforms to best available asteroids]; |
|
17
|
|
|
|
|
|
|
} |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub process_planet { |
|
20
|
|
|
|
|
|
|
my ($self,$planet_stats) = @_; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Get observatory |
|
23
|
|
|
|
|
|
|
my $mining = $self->find_building($planet_stats->{id},'MiningMinistry'); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# Get space port |
|
26
|
|
|
|
|
|
|
my $spaceport = $self->find_building($planet_stats->{id},'SpacePort'); |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
return |
|
29
|
|
|
|
|
|
|
unless $mining && $spaceport; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Get observatory probed stars |
|
32
|
|
|
|
|
|
|
my $mining_object = $self->build_object($mining); |
|
33
|
|
|
|
|
|
|
my $mining_data = $self->request( |
|
34
|
|
|
|
|
|
|
object => $mining_object, |
|
35
|
|
|
|
|
|
|
method => 'view_platforms', |
|
36
|
|
|
|
|
|
|
); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# Check if we can have more platforms |
|
39
|
|
|
|
|
|
|
my $available_platforms = ($mining_data->{max_platforms} - scalar @{$mining_data->{platforms}}); |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
return |
|
42
|
|
|
|
|
|
|
if $available_platforms == 0; |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $spaceport_object = $self->build_object($spaceport); |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Get available mining ships |
|
47
|
|
|
|
|
|
|
my @avaliable_miningships = $self->get_ships( |
|
48
|
|
|
|
|
|
|
planet => $planet_stats, |
|
49
|
|
|
|
|
|
|
quantity => $available_platforms, |
|
50
|
|
|
|
|
|
|
type => 'mining_platform_ship', |
|
51
|
|
|
|
|
|
|
travelling => 1, |
|
52
|
|
|
|
|
|
|
); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
return |
|
55
|
|
|
|
|
|
|
unless scalar @avaliable_miningships; |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
my %ores_production; |
|
58
|
|
|
|
|
|
|
my %ores_coeficient; |
|
59
|
|
|
|
|
|
|
my %asteroids; |
|
60
|
|
|
|
|
|
|
my $ores_planet_total = sum(values %{$planet_stats->{ore}}); |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Get planet ore production |
|
63
|
|
|
|
|
|
|
while (my ($ore,$quantity) = each %{$planet_stats->{ore}}) { |
|
64
|
|
|
|
|
|
|
$ores_production{$ore} ||= 0; |
|
65
|
|
|
|
|
|
|
$ores_production{$ore} += int(($quantity / $ores_planet_total) * $planet_stats->{ore_hour}); |
|
66
|
|
|
|
|
|
|
} |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Get platforms ore production |
|
69
|
|
|
|
|
|
|
foreach my $platform (@{$mining_data->{platforms}}) { |
|
70
|
|
|
|
|
|
|
my $asteroid_id = $platform->{asteroid}{id}; |
|
71
|
|
|
|
|
|
|
$asteroids{$asteroid_id} ||= 0; |
|
72
|
|
|
|
|
|
|
$asteroids{$asteroid_id} ++; |
|
73
|
|
|
|
|
|
|
foreach my $ore (ore_types()) { |
|
74
|
|
|
|
|
|
|
my $quantity = $platform->{$ore.'_hour'}; |
|
75
|
|
|
|
|
|
|
$ores_production{$ore} += $quantity; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
# Total ore production |
|
79
|
|
|
|
|
|
|
my $ores_production_total = sum(values %ores_production); |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Calc which ores are underrepresented |
|
82
|
|
|
|
|
|
|
my $ore_type_count = scalar ore_types(); |
|
83
|
|
|
|
|
|
|
foreach my $ore (ore_types()) { |
|
84
|
|
|
|
|
|
|
$ores_coeficient{$ore} = -1*( ($ores_production{$ore} / $ores_production_total) - (1/$ore_type_count)); |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Get closest asteroids |
|
88
|
|
|
|
|
|
|
my @asteroids = $self->closest_asteroids($planet_stats->{x},$planet_stats->{y},25); |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
foreach my $asteroid (@asteroids) { |
|
91
|
|
|
|
|
|
|
my $asteroid_quality = 1; |
|
92
|
|
|
|
|
|
|
my $asteroid_id = $asteroid->{id}; |
|
93
|
|
|
|
|
|
|
while (my ($ore,$quantity) = each %{$asteroid->{ore}}) { |
|
94
|
|
|
|
|
|
|
next |
|
95
|
|
|
|
|
|
|
if $quantity <= 1; |
|
96
|
|
|
|
|
|
|
$asteroid_quality += $ores_coeficient{$ore} * ($quantity*2) |
|
97
|
|
|
|
|
|
|
if $ores_coeficient{$ore} > 0; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# Calc asteroid quality based on ore quantity, number of different ores and exclusive ores (TODO make this better) |
|
101
|
|
|
|
|
|
|
my $ore_count = $asteroid->{ore_total}; |
|
102
|
|
|
|
|
|
|
$ore_count /= 2; |
|
103
|
|
|
|
|
|
|
$ore_count = 1 |
|
104
|
|
|
|
|
|
|
if $ore_count < 1; |
|
105
|
|
|
|
|
|
|
$asteroid->{quality} = int($asteroid_quality * $asteroid->{ore_total} * $asteroid->{ore_count}); |
|
106
|
|
|
|
|
|
|
$asteroid->{quality} *= (1 - (0.1 * $asteroids{$asteroid_id})) |
|
107
|
|
|
|
|
|
|
if defined $asteroids{$asteroid_id}; |
|
108
|
|
|
|
|
|
|
$self->log('debug','Calculated asteroid quality for %s is %i',$asteroid->{name},$asteroid->{quality}) |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
my @asteroids_sorted = sort { $b->{quality} <=> $a->{quality} } @asteroids; |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# Get all minings ships |
|
114
|
|
|
|
|
|
|
MINING_SHIP: |
|
115
|
|
|
|
|
|
|
foreach my $mining_ship (@avaliable_miningships) { |
|
116
|
|
|
|
|
|
|
# Find best asteroid |
|
117
|
|
|
|
|
|
|
ASTEROID_CANDIDATE: |
|
118
|
|
|
|
|
|
|
while (scalar @asteroids_sorted) { |
|
119
|
|
|
|
|
|
|
my $asteroid = shift(@asteroids_sorted); |
|
120
|
|
|
|
|
|
|
my $asteroid_data = $self->request( |
|
121
|
|
|
|
|
|
|
object => $spaceport_object, |
|
122
|
|
|
|
|
|
|
method => 'get_ships_for', |
|
123
|
|
|
|
|
|
|
params => [ $planet_stats->{id}, { "body_id" => $asteroid->{id} } ], |
|
124
|
|
|
|
|
|
|
); |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
next ASTEROID_CANDIDATE |
|
127
|
|
|
|
|
|
|
if scalar(@{$asteroid_data->{incoming}}) > 0; |
|
128
|
|
|
|
|
|
|
next ASTEROID_CANDIDATE |
|
129
|
|
|
|
|
|
|
if scalar(@{$asteroid_data->{available}}) == 0; |
|
130
|
|
|
|
|
|
|
next ASTEROID_CANDIDATE |
|
131
|
|
|
|
|
|
|
if defined $asteroid_data->{mining_platforms} |
|
132
|
|
|
|
|
|
|
&& scalar(@{$asteroid_data->{mining_platforms}}) == $asteroid->{size}; |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$self->log('notice',"Sending mining platform to %s",$asteroid->{name}); |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# Send mining platform to best asteroid |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my $send_data = $self->request( |
|
139
|
|
|
|
|
|
|
object => $spaceport_object, |
|
140
|
|
|
|
|
|
|
method => 'send_ship', |
|
141
|
|
|
|
|
|
|
params => [ $mining_ship,{ "body_id" => $asteroid->{id} } ], |
|
142
|
|
|
|
|
|
|
); |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
next MINING_SHIP; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# TODO check transport ships |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
return; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub closest_asteroids { |
|
154
|
|
|
|
|
|
|
my ($self,$x,$y,$limit) = @_; |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
$limit //= 1; |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
my @asteroids; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
$self->search_stars_callback( |
|
161
|
|
|
|
|
|
|
sub { |
|
162
|
|
|
|
|
|
|
my ($star_data) = @_; |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
foreach my $body (@{$star_data->{bodies}}) { |
|
165
|
|
|
|
|
|
|
next |
|
166
|
|
|
|
|
|
|
unless $body->{type} eq 'asteroid'; |
|
167
|
|
|
|
|
|
|
$body->{ore_total} = sum(values %{$body->{ore}}); |
|
168
|
|
|
|
|
|
|
$body->{ore_count} = scalar(grep { $_ > 1 } values %{$body->{ore}}); |
|
169
|
|
|
|
|
|
|
push(@asteroids,$body); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
return 0 |
|
173
|
|
|
|
|
|
|
if scalar(@asteroids) >= $limit; |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
return 1; |
|
176
|
|
|
|
|
|
|
}, |
|
177
|
|
|
|
|
|
|
x => $x, |
|
178
|
|
|
|
|
|
|
y => $y, |
|
179
|
|
|
|
|
|
|
is_known => 1, |
|
180
|
|
|
|
|
|
|
distance => 1, |
|
181
|
|
|
|
|
|
|
); |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
return @asteroids; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
187
|
|
|
|
|
|
|
no Moose; |
|
188
|
|
|
|
|
|
|
1; |