-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcareful_attacker.py
211 lines (194 loc) · 7.9 KB
/
careful_attacker.py
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
# Let's start by importing the Halite Starter Kit so we can interface with the Halite engine
import hlt
# Then let's import the logging module so we can print out information
import logging
from operator import attrgetter
# GAME START
# Here we define the bot's name as Settler and initialize the game, including communication with the Halite engine.
game = hlt.Game("CarefulAttackerV2")
# Then we print our start message to the logs
logging.info("Starting my Settler bot!")
def get_ship_command(ship, ships_len, planets_to_be_attacked, my_ship_ids, my_planets, turn):
if ship.docking_status != ship.DockingStatus.UNDOCKED:
# Skip this ship
return None, None
entities_by_distance = game_map.nearby_entities_by_distance(ship)
sorted_list = sorted(
entities_by_distance.items(), key=lambda value: value[0])
_planets = []
for element in sorted_list:
for el in element[1]:
if isinstance(el, hlt.entity.Planet):
_planets.append(el)
enemy_planet = None
biggest_closes_planet = None
my_planet = None
if _planets:
closest_planet = _planets[0]
if closest_planet in my_planets and not closest_planet.is_full() and turn > 70:
my_planet = closest_planet
else:
non_taken_planets = [planet for planet in _planets if not planet.is_owned()]
three_closest_planets = non_taken_planets[:4]
if three_closest_planets:
biggest_closes_planet = max(three_closest_planets, key=attrgetter('radius'))
else:
enemy_planets = [planet for planet in _planets if planet not in my_planets][:3]
if enemy_planets:
enemy_planet = min(enemy_planets, key=lambda x: len(x.all_docked_ships()))
else:
return None, None
if biggest_closes_planet:
if ship.can_dock(biggest_closes_planet):
return ship.dock(biggest_closes_planet), None
else:
return ship.navigate(
ship.closest_point_to(biggest_closes_planet),
# non_taken_planet,
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=False), biggest_closes_planet
elif enemy_planet:
docked_ships = enemy_planet.all_docked_ships()
if docked_ships:
docked_ship = docked_ships[0]
else:
docked_ship = enemy_planet
return ship.navigate(
ship.closest_point_to(docked_ship),
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=True), None
elif my_planet:
if ship.can_dock(my_planet):
return ship.dock(my_planet), None
return ship.navigate(
ship.closest_point_to(my_planet),
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=False), None
else:
return None, None
def get_ship_coordinated_command(ship, enemy_planet):
if not enemy_planet:
return None, None
docked_ships = enemy_planet.all_docked_ships()
if docked_ships:
docked_ship = docked_ships[0]
else:
docked_ship = enemy_planet
if ship.can_dock(enemy_planet):
return ship.dock(enemy_planet), enemy_planet
return ship.navigate(
ship.closest_point_to(docked_ship),
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=True), None
class ProtectMission(object):
def __init__(self, planet_to_protect, ship_id):
self.planet_to_protect = planet_to_protect
self.ship_id = ship_id
def get_command(self, game_map, enemy_ships, ship):
enemy_ship = min(
enemy_ships,
key=lambda x: self.planet_to_protect.calculate_distance_between(x))
return ship.navigate(
enemy_ship,
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=True), None
class AttackMission(object):
def __init__(self, planet_to_attack, ship_id):
self.planet_to_attack = planet_to_attack
self.ship_id = ship_id
def get_command(self, game_map, enemy_ships, ship):
docked_ships = self.planet_to_attack.all_docked_ships()
if docked_ships:
docked_ship = docked_ships[0]
else:
docked_ship = self.planet_to_attack
if ship.can_dock(self.planet_to_attack):
return ship.dock(self.planet_to_attack), self.planet_to_attack
return ship.navigate(
ship.closest_point_to(docked_ship),
game_map,
speed=int(hlt.constants.MAX_SPEED),
ignore_ships=True), None
turn = 0
enemy_planets = []
missions = {}
while True:
turn += 1
# TURN START
# Update the map for the new turn and get the latest version
game_map = game.update_map()
my_id = game_map.my_id
i = 0
# Here we define the set of commands to be sent to the Halite engine at the end of the turn
command_queue = []
# For every ship that I control
all_me = game_map.get_me()
total_ships = all_me.all_ships()
planets_to_be_attacked = []
my_ship_ids = [ship.id for ship in total_ships]
planets = game_map.all_planets()
my_planets = [p for p in planets if p.owner and p.owner.id == my_id]
if turn % 3 == 0:
enemy_planets = [p for p in planets if p not in my_planets]
enemy_ships = []
for player in game_map.all_players():
if player.id == my_id:
continue
enemy_ships.extend(player.all_ships())
enemy_planet = None
try:
enemy_planet = min(enemy_planets, key=lambda x: my_planets[0].calculate_distance_between(x))
except:
pass
for ship in total_ships:
logging.info('{} ship ID'.format(ship.id))
# If the ship is docked
if ship.docking_status != ship.DockingStatus.UNDOCKED:
# Skip this ship
continue
if ship.id in missions.keys():
ship_command = missions[ship.id].get_command(
game_map, enemy_ships, ship)
elif ship.id % 5 == 0 and ship.id not in missions.keys() and my_planets and turn > 70:
missions[ship.id] = ProtectMission(my_planets[0], ship.id)
ship_command = missions[ship.id].get_command(
game_map, enemy_ships, ship)
elif ship.id % 2 == 0 and ship.id not in missions.keys():
entities_by_distance = game_map.nearby_entities_by_distance(ship)
sorted_list = sorted(entities_by_distance.items(), key=lambda value: value[0])
_planets = []
for element in sorted_list:
for el in element[1]:
if isinstance(el, hlt.entity.Planet):
_planets.append(el)
non_taken_planets = [planet for planet in _planets if not planet.is_owned()]
if non_taken_planets:
missions[ship.id] = AttackMission(non_taken_planets[0], ship.id)
else:
missions[ship.id] = AttackMission(enemy_planets[0], ship.id)
logging.info('brljaaaa')
ship_command = missions[ship.id].get_command(
game_map, enemy_ships, ship)
elif turn < 150:
if ship.id % 4 == 0 and enemy_planet:
ship_command = get_ship_coordinated_command(ship, enemy_planet)
else:
ship_command = get_ship_command(
ship, len(my_ship_ids), planets_to_be_attacked, my_ship_ids, my_planets, turn)
else:
ship_command = get_ship_coordinated_command(ship, enemy_planet)
if ship_command:
if ship_command[1] and turn >= 5:
planets_to_be_attacked.append(ship_command[1])
if ship_command[0]:
command_queue.append(ship_command[0])
# Send our set of commands to the Halite engine for this turn
logging.info(command_queue)
game.send_command_queue(command_queue)
# TURN END
# GAME END