-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexample.py
More file actions
393 lines (281 loc) · 13.7 KB
/
Copy pathexample.py
File metadata and controls
393 lines (281 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
import math
import operator
import random
import requests
from test import get_next_spiral_checkpoint
base_url = "http://localhost:5001"
def info():
response = requests.get(base_url + "/info")
return response.json()
def scan():
response = requests.get(base_url + "/scan")
return response.json()
def travel(position):
response = requests.post(base_url + "/travel", json={"x": position[0], "y": position[1]})
return response.json()
def mine(planet_id, resource1=None, resource2=None):
response = requests.post(base_url + "/mine",
json={"planet_id": planet_id, "resource1": resource1, "resource2": resource2})
return response.json()
def statistics():
response = requests.get(base_url + "/statistics")
return response.json()
def upgrade(part_name):
response = requests.post(base_url + "/upgrade", json={"part_name": part_name})
return response.json()
def resources_to_list(resources):
order = ['Dark Matter', 'Scrap', 'Energy Crystals', 'Rare Earth Elements', 'Plasma']
resources_list = [resources.get(resource, 0) for resource in order]
return resources_list
def get_available_upgrades(info_response):
if not info_response:
return {}
available_upgrades = {}
current_resources = resources_to_list(info_response['resources'])
for part, details in info_response['parts'].items():
# checking if the resources are sufficient for the upgrade
if all(current >= upgrade for current, upgrade in zip(current_resources, details['cost'])):
available_upgrades[part] = details
return list(available_upgrades.keys())
def get_nearest_mineable_system(scanned_systems, fuel):
if not scanned_systems:
return None
# Filter out systems that can't be mined or have no celestial bodies
mineable_systems = [
system for system in scanned_systems
if system.get('can_be_mined', True) and 'celestial_bodies' in system and fuel >= system['fuel_cost']
]
if not mineable_systems:
return None
# Get the number of celestial bodies for each system
for system in mineable_systems:
system['num_celestial_bodies'] = len(system.get('celestial_bodies'))
# Sort by fuel cost and then by number of celestial bodies in descending order
mineable_systems.sort(key=operator.itemgetter('fuel_cost', 'num_celestial_bodies'))
# Return the nearest system with the most celestial bodies
return mineable_systems[0]
def get_best_planet(system, priority_resources, ignore_planets_ids=None):
if not system or not priority_resources:
return None
celestial_bodies = [body for body in system.get('celestial_bodies', []) if
ignore_planets_ids is None or body['id'] not in ignore_planets_ids]
celestial_bodies = [body for body in celestial_bodies if body.get('can_be_mined', False)]
# Get the resources on each celestial body.
for body in celestial_bodies:
body_resources = body.get('resources', {})
body['priority_resources'] = [resource for resource in body_resources if body_resources[resource] > 0]
# Score the celestial bodies based on the priority of their resources.
for body in celestial_bodies:
body['score'] = sum(
5 - priority_resources.index(resource) if resource in priority_resources else 1 for resource in
body['priority_resources'])
# Sort celestial bodies by their score, in descending order.
celestial_bodies.sort(key=operator.itemgetter('score'), reverse=True)
if len(celestial_bodies) == 0:
return
return {
'id': celestial_bodies[0]['id'],
'resources': celestial_bodies[0]['priority_resources'][:2]
}
def get_best_planets_for_mining(system, priority_resources):
if not system or not priority_resources:
return None
first_planet = get_best_planet(system, priority_resources)
# print(first_planet)
if not first_planet:
return None
priority_resources = [resource for resource in priority_resources if resource not in first_planet['resources']]
second_planet = get_best_planet(system, priority_resources, ignore_planets_ids=[first_planet['id']])
return [first_planet, second_planet]
def mine_best_planets(best_planets):
if not best_planets:
return None
mine_results = []
for planet in best_planets:
resource_1 = None
resource_2 = None
if planet:
if 'resources' in planet:
resource_1 = planet['resources'][0] if len(planet['resources']) > 0 else None
resource_2 = planet['resources'][1] if len(planet['resources']) > 1 else None
# print("Mining planet: " + str(planet['id']) + " with resources: " + str(resource_1) + " and " + str(
# resource_2))
mine_results.append(mine(planet['id'], resource_1, resource_2))
return mine_results
def scan_current_system(scan_result, position):
if not scan_result:
return None
current_system = None
for system in scan_result:
if system['position'] == position:
current_system = system
return current_system
def travel_and_scan_current_system(destination):
travel_result = travel(destination)
if travel_result['success']:
for system in scan():
if system['position'] == destination:
return system
def find_lacking_resources(ship_info):
resources = ship_info['resources']
parts = ship_info['parts']
cargo_hold_value = parts['Cargo Hold']['value']
fuel_tank_value = parts['Fuel Tank']['value']
# Convert the resources dict to a list of tuples, with the amount as a percentage of max capacity
resources_list = []
for resource, amount in resources.items():
max_capacity = fuel_tank_value if resource == 'Dark Matter' else cargo_hold_value
percentage = (amount / max_capacity) * 100
resources_list.append((resource, percentage))
# Sort the list based on the percentage of each resource
resources_list.sort(key=lambda x: x[1])
# Now create a list of resource names, sorted by the percentage of each resource
lacking_resources = [resource for resource, percentage in resources_list]
return lacking_resources
scan_result = scan()
info_result = info()
ship_parts = info_result["parts"]
ship_position = info_result["position"]
ship_resources = info_result["resources"]
ship_fuel = ship_resources["Dark Matter"]
ship_max_travel_distance = ship_parts["Warp Drive"]["value"]
ship_max_scan_distance = ship_parts["Scanner"]["value"]
ship_max_travel_distance = ship_parts["Warp Drive"]["value"]
ship_max_scan_distance = ship_parts["Scanner"]["value"]
def get_ship_destination_in_direction(direction, ship_info):
ship_max_travel_distance = ship_info['parts']['Warp Drive']['value'] - 1
diagonal_distance = ship_max_travel_distance / math.sqrt(2)
# Define the possible moves for each direction
directions = {
"N": (0, ship_max_travel_distance),
"NE": (diagonal_distance, diagonal_distance),
"E": (ship_max_travel_distance, 0),
"SE": (diagonal_distance, -diagonal_distance),
"S": (0, -ship_max_travel_distance),
"SW": (-diagonal_distance, -diagonal_distance),
"W": (-ship_max_travel_distance, 0),
"NW": (-diagonal_distance, diagonal_distance)
}
# Get the current position of the ship
current_position = ship_info['position']
# Get the move for the specified direction
move = directions.get(direction)
if move is None:
print("Invalid direction!")
return
# Calculate the new position
new_position = (current_position[0] + move[0], current_position[1] + move[1])
return new_position
def get_random_direction():
# Define the possible directions
directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]
# Choose and return a random direction
return random.choice(directions)
def get_distance_between_points(p1, p2):
# Calculate the vector towards the target destination
dx, dy = p1[0] - p2[0], p1[1] - p2[1]
# Calculate the distance to the target destination
distance = math.sqrt(dx ** 2 + dy ** 2)
return distance
def get_ship_destination(target_destination, ship_info):
# Get the current position and maximum travel distance of the ship
current_position = ship_info['position']
ship_max_travel_distance = ship_info['parts']['Warp Drive']['value'] - 1
# Calculate the vector towards the target destination
dx, dy = target_destination[0] - current_position[0], target_destination[1] - current_position[1]
# Calculate the distance to the target destination
distance_to_target = math.sqrt(dx ** 2 + dy ** 2)
if distance_to_target <= ship_max_travel_distance:
# The target destination is within reach
return target_destination
else:
# The target destination is too far. Calculate a new destination within reach.
# Maintain the direction towards the target by normalizing the vector
dx, dy = dx / distance_to_target, dy / distance_to_target
# Multiply by the maximum travel distance to get the new destination
new_position = (
math.floor(current_position[0] + dx * ship_max_travel_distance),
math.floor(current_position[1] + dy * ship_max_travel_distance))
return new_position
"""
get_available_upgrades(info_response):
This function returns a list of upgrades that the player can currently afford given the current resources.
get_nearest_mineable_system(scanned_systems, fuel):
This function selects the nearest mineable system from a list of scanned systems, considering the system's fuel cost and the number of celestial bodies it contains.
get_best_planets_for_mining(system, priority_resources):
This function returns the top two planets for mining within a given system, considering the priority of different resources.
mine_best_planets(best_planets):
This function executes the mining operation for the best-selected planets and returns the results.
scan_current_system(scan_result, position):
This function scans the current system and returns its details.
travel_and_scan_current_system(destination):
This function executes travel to a destination, scans the system at that location, and returns its details.
find_lacking_resources(ship_info):
This function determines which resources the player is lacking, considering their current quantities as percentages of maximum capacity. It then returns these resources in ascending order of their percentage amounts.
get_ship_destination_in_direction(direction, ship_max_travel_distance):
This function calculates the new position of the ship in a given direction based on the maximum travel distance.
get_random_direction():
This function randomly selects one direction from eight possible ones: North, North-East, East, South-East, South, South-West, West, and North-West.
"""
def find_next_upgrade(ship_data, strategy):
for part in strategy:
part_name = list(part.keys())[0] # Get the part name
target_level = part[part_name] # Get the target level
# Check if the part's current level is less than the target level
if ship_data['parts'][part_name]['level'] < target_level:
return part_name # Return the part to be upgraded next
return None # If all parts are at target levels, return None
def game_step():
scan_result = scan()
info_result = info()
# statistics_result = statistics()
# print(statistics_result)
ship_parts = info_result["parts"]
ship_position = info_result["position"]
ship_resources = info_result["resources"]
ship_fuel = ship_resources["Dark Matter"]
ship_max_travel_distance = ship_parts["Warp Drive"]["value"]
ship_max_scan_distance = ship_parts["Scanner"]["value"]
strategy = [
{'Cargo Hold': 2},
{'Fuel Tank': 2},
{'Scanner': 2},
]
# print(scan_current_system(scan_result, ship_position))
available_upgrades = get_available_upgrades(info_result) # ["Cargo Hold"]
if available_upgrades and len(available_upgrades) > 0 and ship_fuel < 60:
next_upgrade = find_next_upgrade(info_result, strategy)
if next_upgrade:
print(upgrade(next_upgrade))
else:
print(upgrade(available_upgrades[0]))
info_result = info()
lacking_resources = find_lacking_resources(info_result)
system_for_mining = get_nearest_mineable_system(scan_result, ship_fuel)
if system_for_mining and system_for_mining['position'] != ship_position:
# print("Travelling to system: " + str(system_for_mining['position']))
system_for_mining = travel_and_scan_current_system(system_for_mining['position'])
planets_for_mining = get_best_planets_for_mining(system_for_mining, lacking_resources)
result = mine_best_planets(planets_for_mining)
if not result:
follow_path()
def game_loop():
while True:
game_step()
next_direction = get_next_spiral_checkpoint()
def follow_path():
global next_direction
allowed_distance = 5
disntace_achieved = 0 # just a big number to start
while disntace_achieved < allowed_distance:
next_direction = get_next_spiral_checkpoint()
disntace_achieved = get_distance_between_points(next_direction, info_result["position"])
next_dest = get_ship_destination(next_direction, ship_info=info_result)
travel_result = travel(next_dest)
print(travel_result, next_dest)
if travel_result["success"]:
disntace_achieved = get_distance_between_points(next_dest, travel_result["position"])
if disntace_achieved < allowed_distance:
next_direction = get_next_spiral_checkpoint()
if __name__ == '__main__':
game_loop()