def perform_current_step(self, action_queue: ActionQueue, updated_vehicle_x_y): # Двигаем юниты на 1 линию if self.current_step == self.STEP_MOVE_TO_INITIAL_POSITIONS: if not self.__check_step_started(): command_builder = InitializerStep0_MoveToInitialPositions( self.__me, self.__weather_map, self.__terrain_map, self.__all_vehicles) commands = command_builder.get_command_list() if len(commands) == 0: if self.__check_interrupt_condition(): self.__set_step(self.STEP_INTERRUPT_CONSOLIDATE) else: self.__set_step() return for command in commands: action_queue.push(command) self.__mark_step_started() if self.__check_move_finished(updated_vehicle_x_y): self.__mark_move_started(False) self.__mark_step_started(False) # Расширяем каждый столбец юнитов в 3 раза elif self.current_step == self.STEP_UNCONSOLIDATE: self.__perform_casual_step(InitializerStep1_Unconsolidate, action_queue, updated_vehicle_x_y) # Делаем вертикальный сдвиг на разное смещение разных типов юнитов elif self.current_step == self.STEP_SHIFT_VERTICAL: self.__perform_casual_step(InitializerStep2_ShiftVertical, action_queue, updated_vehicle_x_y) # Сдвигаем юнитов в одну колонку elif self.current_step == self.STEP_SHIFT_TOGETHER: self.__perform_casual_step(InitializerStep3_ShiftTogether, action_queue, updated_vehicle_x_y) # Сдвигаем группы по 3 через 3 elif self.current_step == self.STEP_SHIFT_HORIZONTAL: self.__perform_casual_step(InitializerStep4_ShiftHorizontal, action_queue, updated_vehicle_x_y) # Формируем длинные ряды elif self.current_step == self.STEP_MAKE_LONG_ROWS: self.__perform_casual_step(InitializerStep5_MakeLongRows, action_queue, updated_vehicle_x_y) # Поворачиваемся elif self.current_step == self.STEP_ROTATE: self.__perform_casual_step(InitializerStep6_Rotate, action_queue, updated_vehicle_x_y) elif self.current_step == self.STEP_INTERRUPT_CONSOLIDATE: self.__perform_casual_step(InitializerStep8_InterruptConsolidate, action_queue, updated_vehicle_x_y) elif self.current_step == self.STEP_INTERRUPT_SHIFT_AIR_UNITS: self.__perform_casual_step(InitializerStep9_InterruptShiftAirUnits, action_queue, updated_vehicle_x_y)
def __perform_casual_step(self, command_builder_class, action_queue: ActionQueue, updated_vehicle_x_y): if not self.__check_step_started(): command_builder = command_builder_class(self.__me, self.__weather_map, self.__terrain_map, self.__all_vehicles) commands = command_builder.get_command_list() if len(commands) == 0: self.__set_step() return for command in commands: action_queue.push(command) self.__mark_step_started() elif self.__check_move_finished(updated_vehicle_x_y): self.__set_step()
class MyStrategy: game = None world = None me = None __weather_map = None __terrain_map = None vehicleById = {} updateTickByVehicleId = {} updatedVehicleXY = {} allVehicles = [] initializer = None actionQueue = None strategy = None _sos_mode = False def initialize_strategy(self): self.initializer = Initializer(self.world) self.actionQueue = ActionQueue(self.world) self.__weather_map = WeatherMap(self.world.weather_by_cell_x_y, Constant.WEATHER_MAP_CELL_SIZE) self.__terrain_map = TerrainMap(self.world.terrain_by_cell_x_y, Constant.TERRAIN_MAP_CELL_SIZE) def initialize_tick(self): self.updatedVehicleXY = {} for vehicle in self.world.new_vehicles: self.vehicleById[vehicle.id] = vehicle self.updateTickByVehicleId[vehicle.id] = self.world.tick_index for vehicleUpdate in self.world.vehicle_updates: vehicleId = vehicleUpdate.id if vehicleUpdate.durability == 0: self.vehicleById.pop(vehicleId) self.updateTickByVehicleId.pop(vehicleId) else: x_old, y_old = self.vehicleById[vehicleId].x, self.vehicleById[ vehicleId].y self.vehicleById[vehicleId].update(vehicleUpdate) x_new, y_new = self.vehicleById[vehicleId].x, self.vehicleById[ vehicleId].y if self.vehicleById[vehicleId].player_id == self.me.id and ( x_old != x_new or y_old != y_new): self.updatedVehicleXY[vehicleId] = (x_new - x_old, y_new - y_old) self.updateTickByVehicleId[vehicleId] = self.world.tick_index self.allVehicles = list(self.vehicleById.values()) def execute_action(self, move: Move, action: dict): for field, value in action.items(): setattr(move, field, value) return True def execute_delayed_action(self, move: Move, world: World): action = self.actionQueue.pop(world) if action is None: return False return self.execute_action(move, action) def move(self, me: Player, world: World, game: Game, move: Move): self.game = game self.world = world self.me = me if world.tick_index == 0: self.initialize_strategy() self.initialize_tick() if self.strategy is None: if self.initializer.current_step not in [ Initializer.STEP_STOP, Initializer.STEP_INTERRUPT_STOP ]: self.initializer.prepare_step(self.me, self.world, self.allVehicles) self.initializer.perform_current_step(self.actionQueue, self.updatedVehicleXY) elif self.initializer.current_step == Initializer.STEP_INTERRUPT_STOP: self.strategy = NaiveStrategy(self.actionQueue, self.world, self.__weather_map, self.__terrain_map) else: self.strategy = NaiveStrategy(self.actionQueue, self.world, self.__weather_map, self.__terrain_map) if self.strategy: #if False: if not self._sos_mode: if self.__save_our_souls(world): return else: if self.__comeback_after_strike(world): return if me.remaining_action_cooldown_ticks > 0: return if self.execute_delayed_action(move, world): return self.determine_following_actions() self.execute_delayed_action(move, world) def determine_following_actions(self): if self.strategy is None: return self.strategy.initialize_tick(self.game, self.world, self.me, self.allVehicles, self.updateTickByVehicleId) self.strategy.determine_following_actions(self.updatedVehicleXY) def __save_our_souls(self, world: World): opponent = world.get_opponent_player() next_nuclear_strike_tick = opponent.next_nuclear_strike_tick_index if next_nuclear_strike_tick == -1: return False f = Formation(self.allVehicles, self.me, ownership=Ownership.ALLY) x = opponent.next_nuclear_strike_x y = opponent.next_nuclear_strike_y next_nuclear_strike_vehicle_id = opponent.next_nuclear_strike_vehicle_id if next_nuclear_strike_vehicle_id == -1: return False if next_nuclear_strike_vehicle_id not in self.vehicleById: return False is_aerial = self.vehicleById[next_nuclear_strike_vehicle_id].aerial kill_factor = f.calc_nuclear_kill_factor(x, y) if kill_factor['total_damage'] < 700 and kill_factor[ 'survived'] > kill_factor['killed'] * 5 and not is_aerial: return False from_x, from_y = self.vehicleById[ next_nuclear_strike_vehicle_id].x, self.vehicleById[ next_nuclear_strike_vehicle_id].y sos_vector = (y - from_y, x - from_x) sos_vector_norm = 120 / math.hypot(sos_vector[0], sos_vector[1]) sos_vector = (sos_vector[0] * sos_vector_norm, sos_vector[1] * sos_vector_norm) topleft = f.find_topleft() bottomright = f.find_bottomright() if topleft[0] + sos_vector[0] < 0 or topleft[1] + sos_vector[1] < 0: sos_vector = (-sos_vector[0], -sos_vector[1]) elif bottomright[0] + sos_vector[0] >= self.world.height or bottomright[ 1] + sos_vector[1] >= self.world.width: sos_vector = (-sos_vector[0], -sos_vector[1]) self.actionQueue.clear() self.actionQueue.push(Action.move(sos_vector[1], sos_vector[0], 0.3)) self._sos_mode = True return True def __comeback_after_strike(self, world: World): opponent = world.get_opponent_player() next_nuclear_strike_tick = opponent.next_nuclear_strike_tick_index if next_nuclear_strike_tick != -1: return False if not self.actionQueue.is_action_in_queue(ActionType.MOVE): self.actionQueue.push(Action.move(0, 0)) else: self.actionQueue.clear() self._sos_mode = False return True