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