예제 #1
0
 def new_move(self,
              action=None,
              group=0,
              x_range=(0.0, WORLD_WIDTH),
              y_range=(0.0, WORLD_HEIGHT),
              vector=(0.0, 0.0),
              angle=0.0,
              factor=0.0,
              max_speed=0.0,
              max_angular_speed=0.0,
              vehicle_type=None,
              facility_id=-1,
              vehicle_id=-1):
     m = Move()
     m.action = action
     m.group = group
     m.left, m.right = x_range
     m.top, m.bottom = y_range
     m.x, m.y = vector
     m.angle = angle
     m.factor = factor
     m.max_speed = max_speed
     m.max_angular_speed = max_angular_speed
     m.vehicle_type = vehicle_type
     m.facility_id = facility_id
     m.vehicle_id = vehicle_id
     return m
예제 #2
0
    def move_forward(self, move: Move):
        enemy_vehicle = min(
            (vehicle for vehicle in self.enemy_vehicles.values()),
            key=(lambda vehicle: vehicle.get_distance_to(self.my_x, self.my_y)),
        )
        x, y = enemy_vehicle.x, enemy_vehicle.y

        # Nuclear strike logic.
        if (
            self.me.remaining_nuclear_strike_cooldown_ticks == 0 and
            enemy_vehicle.get_distance_to(self.my_x, self.my_y) > self.r
        ):
            vehicle, distance = min(
                self.get_vehicles_with_distance_to(self.my_vehicles.values(), enemy_vehicle),
                key=itemgetter(1),
            )
            if distance < self.get_vision_range(vehicle):
                print('[{}] TACTICAL NUCLEAR STRIKE!'.format(self.world.tick_index))
                move.action = ActionType.TACTICAL_NUCLEAR_STRIKE
                move.vehicle_id = vehicle.id
                move.x = enemy_vehicle.x
                move.y = enemy_vehicle.y
                return

        move.action = ActionType.MOVE
        move.max_speed = self.get_max_speed()
        if self.me.score > self.world.get_opponent_player().score:
            # We're winning. Why take a risk? Slowly go away.
            move.x = -(x - self.my_x)
            move.y = -(y - self.my_y)
            move.max_speed = 0.01
        elif (
            self.attack_ratio >= 1.0 or
            enemy_vehicle.get_distance_to(self.my_x, self.my_y) > self.r + 20.0 or
            self.world.tick_index > 19000
        ):
            # We have enough vehicles or opponent is too far away, let's attack!
            move.x = x - self.my_x
            move.y = y - self.my_y
        else:
            # We're losing the battle. Let's move left-right until something good happens.
            move.x = y - self.my_y
            move.y = -(x - self.my_x)
            if getrandbits(1):
                move.x = -move.x
                move.y = -move.y
예제 #3
0
    def move(self, me: Player, world: World, game: Game, move: Move):
        self.update(me, world, game)
        self.clear_cache()

        # PREPROCESSING OF MEDIANS
        #  me
        median_me_all = self.get_median(me)
        median_me_ground = self.get_median(me, types=[0, 3, 4])
        median_me_aerial = self.get_median(me, types=[1, 2])
        median_me_of_type = [self.get_median(me, types=[type])
                             for type in range(5)]
        # enemy
        median_en_all = self.get_median(self.enemy)
        # median_en_ground = self.get_median(self.enemy, types=[0, 3, 4])
        # median_en_aerial = self.get_median(self.enemy, types=[1, 2])
        # median_en_of_type = [self.get_median(self.enemy, types=[type])
        #                      for type in range(5)]

        if world.tick_index % 100 == 0:
            print("NOW AT TICK", world.tick_index)
            print(median_me_all)
            print("CENTERS:")
            for type in range(5):
                median = median_me_of_type[type]
                print(" ", self.VEHICLE_TYPE_NAMES[type], median)
                X = np.array(list(self.get_data_of_units(me, types=[type])[0]))
                Y = np.array(list(self.get_data_of_units(me, types=[type])[1]))
                print(" ", " ", "domain:", X.min(), X.max())
                print(" ", " ", "range:", Y.min(), Y.max())
            print()

        # INIT INFO
        if world.tick_index == 0:
            fighter_x, fighter_y = median_me_of_type[1]
            helicopter_x, helicopter_y = median_me_of_type[2]
            if (fighter_x == helicopter_x and fighter_y < helicopter_y) or \
               (fighter_x > fighter_y and not (fighter_x < helicopter_x and
                                               fighter_y == helicopter_y)):
                self.aerial_formation_type = 'right_down'
            else:
                self.aerial_formation_type = 'down_right'

            self.next_formation_stage(stage='aerial')
            self.next_formation_stage(stage='ground')

        # PLANNED TACTICS FOR ROUND II
        # 1) do phase 1 improved using potential flows
        # 2) split into 4, treat these groups as single entities
        # 3) use potential flows to occupy facilities
        # 4) produce enough units for a 5th group
        # 5) if one facility is not occupied, then use the 5th group to occupy it 
        #    else 2 or more groups to invade an facility and let the 5th remain on it

        # PHASE I: FORMATION
        ## AERIAL UNITS
        if self.aerial_formation_stage == 1 and self.lock == 'free':      # select fighter planes
            self.act_new_select(move, vehicle_type=1, stage='aerial')
            self.lock = 'aerial'
            return
        elif self.aerial_formation_stage == 2 and self.lock == 'aerial':  # move fighter planes
            if self.aerial_formation_type == 'right_down':
                self.act_move(move, source=median_me_of_type[1],
                                    dest=(270, median_me_of_type[1][1]), stage='aerial')
            else:
                self.act_move(move, source=median_me_of_type[1],
                                    dest=(median_me_of_type[1][0], 270), stage='aerial')
            self.aerial_wait = self.DEF_AERIAL_WAIT
            self.lock = 'free'
            return
        elif self.aerial_formation_stage == 3:                            # wait for fighter planes to be in position
            fighter_x, fighter_y = median_me_of_type[1]
            if self.aerial_formation_type == 'right_down':
                if abs(fighter_x - 270) < self.EPS:
                    if self.aerial_wait == 0:
                        self.next_formation_stage(stage='aerial')
                    else:
                        self.aerial_wait -= 1
            else:
                if abs(fighter_y - 270) < self.EPS:
                    if self.aerial_wait == 0:
                        self.next_formation_stage(stage='aerial')
                    else:
                        self.aerial_wait -= 1
        elif self.aerial_formation_stage == 4 and self.lock == 'free':      # select fighter planes
            self.act_new_select(move, vehicle_type=1, stage='aerial')
            self.lock = 'aerial'
            return
        elif self.aerial_formation_stage == 5 and self.lock == 'aerial':  # move fighter planes
            if self.aerial_formation_type == 'right_down':
                self.act_move(move, source=median_me_of_type[1],
                                    dest=(median_me_of_type[1][0], 270), stage='aerial')
            else:
                self.act_move(move, source=median_me_of_type[1],
                                    dest=(270, median_me_of_type[1][1]), stage='aerial')
            self.lock = 'free'
            return
        elif self.aerial_formation_stage == 6 and self.lock == 'free':    # select helicopters
            self.act_new_select(move, vehicle_type=2, stage='aerial')
            self.lock = 'aerial'
            return
        elif self.aerial_formation_stage == 7 and self.lock == 'aerial':  # move helicopters
            if self.aerial_formation_type == 'right_down':
                dest = (274 - self.AERIAL_SQUAD_SIZE - 20, 274)
            else:
                dest = (274, 274 - self.AERIAL_SQUAD_SIZE - 20)
            self.act_move(move, source=median_me_of_type[2], dest=dest, stage='aerial')
            self.aerial_wait = self.DEF_AERIAL_WAIT
            self.lock = 'free'
            return
        elif self.aerial_formation_stage == 8:                            # wait for both to be in position
            if not self.check_in_pos(median_me_of_type[1], (270, 270)):
                pass
            elif (self.aerial_formation_type == 'right_down' and
                  self.check_in_pos(median_me_of_type[2], (274 - self.AERIAL_SQUAD_SIZE - 20, 274))) or \
                 (self.aerial_formation_type == 'down_right' and
                  self.check_in_pos(median_me_of_type[2], (274, 274 - self.AERIAL_SQUAD_SIZE - 20))):
                    if self.aerial_wait == 0:
                        self.next_formation_stage(stage='aerial')
                    else:
                        self.aerial_wait -= 1
        elif self.aerial_formation_stage == 9 and self.lock == 'free':    # select fighter planes
            self.act_new_select(move, vehicle_type=1, stage='aerial')
            self.lock = 'aerial'
            return
        elif self.aerial_formation_stage == 10 and self.lock == 'aerial':  # scale fighter planes
            self.act_scale(move, median_me_of_type[1], stage='aerial')
            self.lock = 'free'
            return
        elif self.aerial_formation_stage == 11 and self.lock == 'free':   # select helicopters
            self.act_new_select(move, vehicle_type=2, stage='aerial')
            self.lock = 'aerial'
            return
        elif self.aerial_formation_stage == 12 and self.lock == 'aerial': # scale helicopters
            self.act_scale(move, median_me_of_type[2], stage='aerial')
            self.aerial_wait = self.DEF_AERIAL_WAIT
            return
        elif self.aerial_formation_stage == 13:                           # wait for both to scale
            if self.check_if_scaled(vehicle_type=1, target_size=self.AERIAL_SQUAD_SIZE) and \
               self.check_if_scaled(vehicle_type=2, target_size=self.AERIAL_SQUAD_SIZE):
                if self.aerial_wait == 0:
                    self.next_formation_stage(stage='aerial')
                else:
                    self.aerial_wait -= 1
        elif self.aerial_formation_stage == 14 and self.lock == 'aerial': # finish formation
            self.act_move(move, source=median_me_of_type[2],
                                dest=(274, 274), stage='aerial')
            self.aerial_wait = self.DEF_AERIAL_WAIT
            return
        elif self.aerial_formation_stage == 15:                           # wait for helicopters to be in position
            if self.check_in_pos(median_me_of_type[2], (274, 274)):
                if self.aerial_wait == 0:
                    self.next_formation_stage(stage='aerial')
                else:
                    self.aerial_wait -= 1
        elif self.aerial_formation_stage == 16 and self.lock == 'aerial': # add fighters to selection
            self.act_add_select(move, vehicle_type=1, stage='aerial')
            return
        elif self.aerial_formation_stage == 17 and self.lock == 'aerial': # move to centroid of ground units
            self.act_move(move, source=median_me_of_type[2],
                                dest=self.get_centroid(self.me, types=[0, 3, 4]), stage='aerial')
            self.lock = 'free'
            return
        ## GROUND UNITS
        '''move_to = {45:56.7, 119:178.3, 193:299.9}
        if self.ground_formation_stage in [1, 2, 3, 4, 5, 6]:
            i = (self.ground_formation_stage-1)//2
            vehicle_type = [0, 3, 4][i]
            if self.ground_formation_stage % 2 == 1 and self.lock == 'free':
                self.act_new_select(move, vehicle_type, stage='ground')
                self.lock = 'ground'
            elif self.lock == 'ground':
                med = median_me_of_type[vehicle_type]
                self.act_move(move, source=med,
                                    dest=(move_to[int(med[0])]+4.1*i,
                                          move_to[int(med[1])]+4.1*i), stage='ground')
                self.lock = 'free'
            return
        elif world.tick_index > 400 and self.ground_formation_stage in [7, 8, 9, 10, 11, 12]:
            i = (self.ground_formation_stage-7)//2
            vehicle_type = [0, 3, 4][i]
            if self.ground_formation_stage % 2 == 1 and self.lock == 'free':
                self.act_new_select(move, vehicle_type, stage='ground')
                self.lock = 'ground'
            elif self.lock == 'ground':
                med = median_me_of_type[vehicle_type]
                self.act_scale(move, pivot=med, factor=self.GROUND_SCALE_FACTOR, stage='ground')
                self.lock = 'free'
            return
        elif world.tick_index > 700 and self.ground_formation_stage in [13, 14, 15, 16, 17, 18]:
            i = (self.ground_formation_stage-13)//2
            vehicle_type = [0, 3, 4][i]
            if self.ground_formation_stage % 2 == 1 and self.lock == 'free':
                self.act_new_select(move, vehicle_type, stage='ground')
                self.lock = 'ground'
            elif self.lock == 'ground':
                med = median_me_of_type[vehicle_type]
                self.act_move(move, relative=(median_me_ground[0]-med[0], 0), stage='ground')
                self.lock = 'free'
        '''
        if self.ground_formation_stage == 1 and self.lock == 'free':      # select ARRVs
            self.act_new_select(move, vehicle_type=0, stage='ground')
            self.lock = 'ground'
            return
        elif self.ground_formation_stage == 2 and self.lock == 'ground':  # add IFVs to selection
            self.act_add_select(move, vehicle_type=3, stage='ground')
            return
        elif self.ground_formation_stage == 3 and self.lock == 'ground':  # add Tanks to selection
            self.act_add_select(move, vehicle_type=4, stage='ground')
            return
        elif self.ground_formation_stage == 4 and self.lock == 'ground':  # rotate all ground units
            self.act_rotate(move, types=[0, 3, 4], pivot=(122, 122), stage='ground')
            self.form_rotation_start = world.tick_index
            self.lock = 'free'
            return
        ## MOVE IN
        elif self.ground_formation_stage == 5:                            # wait for 300 ticks
            if world.tick_index - self.form_rotation_start >= 300:
                self.next_formation_stage(stage='ground')
        elif self.ground_formation_stage in [6, 7, 8, 9, 10, 11]:         # move each type of vehicle to the center
            ground_centroid = self.get_centroid(self.me, types=[0, 3, 4])
            type = [0, 3, 4][(self.ground_formation_stage-6)//2]
            type_centroid = self.get_centroid(self.me, types=[type])
            if self.get_squared_distance(*ground_centroid, *type_centroid) < self.EPS:
                pass
            if self.ground_formation_stage % 2 == 0 and self.lock == 'free':
                self.act_new_select(move, vehicle_type=type, stage='ground')
                self.lock = 'ground'
            elif self.lock == 'ground':
                self.act_move(move, source=type_centroid,
                                    dest=(122, 122), stage='ground')
                self.lock = 'free'
            return
        elif self.ground_formation_stage == 12:                           # wait for another 300 ticks
            if world.tick_index - self.form_rotation_start >= 600:
                self.next_formation_stage(stage='ground')
        elif self.ground_formation_stage == 13 and self.lock == 'free':   # select ARRVs
            self.act_new_select(move, vehicle_type=0, stage='ground')
            self.lock = 'ground'
            return
        elif self.ground_formation_stage == 14 and self.lock == 'ground': # add IFVs to selection
            self.act_add_select(move, vehicle_type=3, stage='ground')
            return
        elif self.ground_formation_stage == 15 and self.lock == 'ground': # add Tanks to selection
            self.act_add_select(move, vehicle_type=4, stage='ground')
            return
        elif self.ground_formation_stage == 16 and self.lock == 'ground': # scale down the formation of ground units
            self.act_scale(move, self.get_centroid(self.me, types=[0, 3, 4]),
                                                   factor=0.1, stage='ground')
            self.lock = 'free'
            return

        # DETECT ENEMY NUKES
        # NOTE: only does this after the formation
        if self.enemy_is_nuking == False and self.enemy.next_nuclear_strike_tick_index > 0:
            self.enemy_is_nuking = True
            self.en_nuke_detected = world.tick_index
            self.en_nuke_x = self.enemy.next_nuclear_strike_x
            self.en_nuke_y = self.enemy.next_nuclear_strike_y
            self.en_nuke_tick = self.enemy.next_nuclear_strike_tick_index
        elif self.enemy_is_nuking == True and self.enemy.next_nuclear_strike_tick_index < 0:
            self.enemy_is_nuking = False
            self.en_nuke_detected = -1
        # EVADE ENEMY NUKES
        if self.enemy_is_nuking == True:
            # OPTION: delay scale up when enemy is nuking to prevent the
            #         units from deviating too much from the formation
            if world.tick_index == self.en_nuke_detected:
                self.act_new_select(move)
            elif world.tick_index == self.en_nuke_detected + 1:
                self.act_scale(move, pivot=(self.en_nuke_x,
                                            self.en_nuke_y), factor=10.0)
            # do nothing while enemy is nuking
            return
        # REGROUP
        if self.enemy_is_nuking == False and world.tick_index <= self.en_nuke_tick + 32:
            if world.tick_index == self.en_nuke_tick + 1:
                self.act_new_select(move)
            elif world.tick_index == self.en_nuke_tick + 2:
                self.act_scale(move, pivot=(self.en_nuke_x,
                                            self.en_nuke_y), factor=0.1)
            # do nothing else while regrouping
            return

        # PHASE II: TRAVEL ACROSS GAME WORLD
        # OPTION: use potential fields to calculate movement patterns
        for idx in range(1000, 20001, 250):
            if world.tick_index == idx + 1:
                self.act_new_select(move)
            elif world.tick_index == idx + 2:
                me_x, me_y = median_me_all
                en_x, en_y = self.world.width, self.world.height
                for centroid in self.get_centroids(self.enemy, method='kmeans'):
                    if self.get_squared_distance(me_x, me_y, *centroid) < \
                       self.get_squared_distance(me_x, me_y, en_x, en_y):
                        en_x, en_y = centroid
                self.act_move(move, source=(me_x, me_y), dest=(en_x, en_y),
                              max_speed=game.tank_speed * game.swamp_terrain_speed_factor)
        # REFORM
        # Overrides previous loop
        for idx in range(1500, 20001, 1500):
            if world.tick_index == idx + 1:
                self.act_new_select(move, vehicle_type=1)
            elif world.tick_index == idx + 2:
                self.act_add_select(move, vehicle_type=2)
            elif world.tick_index == idx + 3:
                self.act_move(move, source=median_me_aerial, dest=median_me_ground)
            elif world.tick_index == idx + 4:
                self.act_new_select(move, vehicle_type=0)
            elif world.tick_index == idx + 5:
                self.act_add_select(move, vehicle_type=3)
            elif world.tick_index == idx + 6:
                self.act_add_select(move, vehicle_type=4)
            elif world.tick_index == idx + 7:
                self.act_rotate(move, types=[0, 3, 4], angle=np.pi/2)
            if world.tick_index == 250 + idx + 1:
                self.act_new_select(move)
            elif world.tick_index == 250 + idx + 2:
                self.act_scale(move, pivot=median_me_all, factor=0.1)

        # NUCLEAR OPTION (not really an option; all hail america!)
        # Only done when the strategy is idle
        if world.tick_index % 10 == 0 and self.can_nuke() and move.action is None:
            best_nuke_score = 0
            # TODO: Take the velocity of the target into account
            # TODO: Take your velocity into account for planning when to nuke
            for centroid in self.get_centroids(self.enemy, method='kmeans'):
                unit_nuking = self.get_nuking_unit(*centroid)
                damages = self.calc_nuke_damages(*centroid)
                if unit_nuking == -1 or damages[1] < self.EPS:
                    continue
                if damages[0]/damages[1] <= self.SIG_NUKE_DAMAGE_RATIO \
                    and damages[1] - damages[0] > best_nuke_score:
                        move.action = ActionType.TACTICAL_NUCLEAR_STRIKE
                        move.x, move.y = centroid
                        move.vehicle_id = unit_nuking
                        break
            if move.action == ActionType.TACTICAL_NUCLEAR_STRIKE:
                print("NUKE: ({}, {}) with unit #{}".format(move.x, move.y,
                                                            move.vehicle_id))
예제 #4
0
 def do_nuke(s: MyStrategy, w: World, g: Game, m: Move):
     m.action = ActionType.TACTICAL_NUCLEAR_STRIKE
     m.x = target.x
     m.y = target.y
     m.vehicle_id = navigator