예제 #1
0
    def move(self, me: Player, world: World, game: Game, move: Move):
        if world.tick_index == 0:
            move.action = ActionType.CLEAR_AND_SELECT
            move.right = world.width
            move.bottom = world.height

        if world.tick_index == 1:
            move.action = ActionType.MOVE
            move.x = world.width / 2.0
            move.y = world.height / 2.0
예제 #2
0
파일: MyStrategy.py 프로젝트: EgorBu/raicup
    def move(self, me: Player, world: World, game: Game, move: Move):
        self.map.update(world.new_vehicles, world.vehicle_updates)
        if world.tick_index == 0:
            move.action = ActionType.CLEAR_AND_SELECT
            move.right = world.width
            move.bottom = world.height

        if world.tick_index == 1:
            move.action = ActionType.MOVE
            move.x = world.width / 1.0
            move.y = world.height / 2.0
예제 #3
0
 def do_group(s: MyStrategy, w: World, g: Game, m: Move):
     m.action = action
     m.group = gnum
     if action == ActionType.ASSIGN:
         s.free_groups.discard(gnum)
     elif action == ActionType.DISBAND:
         s.free_groups.add(gnum)
예제 #4
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
예제 #5
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
예제 #6
0
 def select_all(self, move: Move, vehicle_type=None, add_to_selection=False):
     move.action = ActionType.CLEAR_AND_SELECT if not add_to_selection else ActionType.ADD_TO_SELECTION
     move.left = 0.0
     move.top = 0.0
     move.right = self.game.world_width
     move.bottom = self.game.world_height
     if vehicle_type is not None:
         move.vehicle_type = vehicle_type
예제 #7
0
 def do_select(s: MyStrategy, w: World, g: Game, m: Move, a=area):
     m.action = action
     #print("Selecting: " + str(a))
     m.left = a.left - fuzz
     m.right = a.right + fuzz
     m.top = a.top
     m.bottom = a.bottom
     m.group = group
     m.vehicle_type = vtype
예제 #8
0
    def move(self, me: Hockeyist, world: World, game: Game, move: Move):
        factory = self.create_factory(me, world, game, move)
        strategy = self.create_strategy(factory, me, world, game, move)

        move.action = strategy.action
        move.speed_up = strategy.speed_up
        move.turn = strategy.turn

        factory.info[type(strategy)] = strategy.info
예제 #9
0
    def move(self, me: Hockeyist, world: World, game: Game, move: Move):
        factory = self.create_factory(me, world, game, move)
        strategy = self.create_strategy(factory, me, world, game, move)

        move.action = strategy.action
        move.speed_up = strategy.speed_up
        move.turn = strategy.turn

        factory.info[type(strategy)] = strategy.info
예제 #10
0
    def move(self, me: Hockeyist, world: World, game: Game, move: Move):

        # self.me = me
        # self.world = world
        # self.game = game
        # self.me_move = move

        if me.state == HockeyistState.SWINGING:
            move.action = ActionType.STRIKE
            return

        if world.puck.owner_player_id == me.player_id:

            if world.puck.owner_hockeyist_id == me.id:

                opponent = world.get_opponent_player()

                net_x = 0.5 * (opponent.net_back + opponent.net_front)
                net_y = 0.5 * (opponent.net_bottom + opponent.net_top)

                angle_to_net = me.get_angle_to(net_x, net_y)
                move.turn = angle_to_net

                if abs(angle_to_net) < self.STRIKE_ANGLE:
                    move.action = ActionType.STRIKE

            else:

                nearest_opponent = self.get_nearest_opponent(me, world)

                if nearest_opponent is not None:

                    if me.get_distance_to_unit(nearest_opponent) > game.stick_length:
                        move.speed_up = 1
                    else:
                        move.action = ActionType.STRIKE

                    move.turn = me.get_angle_to_unit(nearest_opponent)

        else:
            move.speed_up = 1
            move.turn = me.get_angle_to_unit(world.puck)
            move.action = ActionType.TAKE_PUCK
예제 #11
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        # Every tick, update state first
        state_machine.update_state(me, world, game)

        # Take action for this state
        state_machine.run(me, world, game)

        # Current state
        state = state_machine.get_state()

        # Move
        move.speed = state.forward_speed
        move.strafe_speed = state.strafe_speed
        move.turn = state.turn_angle
        move.action = state.action
예제 #12
0
 def attack(me: Wizard, game: Game, move: Move, skills: Set, unit: LivingUnit, allow_fireball: bool):
     action_type, min_cast_distance = MyStrategy.get_action(me, game, skills, unit, allow_fireball)
     if action_type == ActionType.NONE:
         return False
     # We can cast something.
     is_oriented, cast_angle = MyStrategy.is_oriented_to_unit(me, game, unit)
     if is_oriented:
         # Attack!
         move.cast_angle = cast_angle
         move.action = action_type
         move.min_cast_distance = min_cast_distance
         return True
     # Turn around to the enemy.
     move.turn = me.get_angle_to_unit(unit)
     return True
예제 #13
0
    def read_move(self):
        if not self.read_boolean():
            return None

        move = Move()

        move.speed_up = self.read_double()
        move.turn = self.read_double()
        move.action = self.read_enum(ActionType)
        if move.action == ActionType.PASS:
            move.pass_power = self.read_double()
            move.pass_angle = self.read_double()
        elif move.action == ActionType.SUBSTITUTE:
            move.teammate_index = self.read_int()

        return move
예제 #14
0
    def read_move(self):
        if not self.read_boolean():
            return None

        move = Move()

        move.speed_up = self.read_double()
        move.turn = self.read_double()
        move.action = self.read_enum(ActionType)
        if move.action == ActionType.PASS:
            move.pass_power = self.read_double()
            move.pass_angle = self.read_double()
        elif move.action == ActionType.SUBSTITUTE:
            move.teammate_index = self.read_int()

        return move
예제 #15
0
    def moveToNonMedic(self, me: Trooper, world: object, game: Game, move: Move):
        troopers = world.troopers

        for trooper in troopers:
            if trooper.type != TrooperType.FIELD_MEDIC and trooper.teammate:
                targetX = 0
                targetY = 0
                move.action = ActionType.MOVE

                if me.type == TrooperType.FIELD_MEDIC and trooper.hitpoints < trooper.maximal_hitpoints:
                    targetX = trooper.x
                    targetY = trooper.y
                else:
                    targetX = trooper.x + randint(0, 9) % 3
                    targetY = trooper.y + randint(0, 9) % 3

                self.moveToPoint(targetX, targetY, me, world, game, move)
예제 #16
0
 def shootTrooper(self, trooper : Trooper, move : Move, game : Game, me : Trooper):
     move.action = ActionType.SHOOT
     move.x = trooper.x
     move.y = trooper.y
예제 #17
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        if self.debug:
            self.debug.syncronize(world)

        if not self.initialized:
            self.initialize(me, world, game)

        self.initialize_tick(me, world, game)

        score_threshold = -0.1
        wizard_score = me.life / (me.max_life * 0.5) - 1

        if self.battle_front:
            self.battle_front.init(world, me)
            front_score = self.battle_front.get_front_score(me)
            k = 0.6
            common_score = front_score * (1 - k) + wizard_score * k
        else:
            common_score = wizard_score

        nearest_target = Points2D.get_nearest_target(me, world)
        if nearest_target is not None:
            distance = me.get_distance_to_unit(nearest_target)
            angle = me.get_angle_to_unit(nearest_target)
            if (distance <= game.staff_range) and (abs(angle) <
                                                   game.staff_sector / 2.0):
                move.action = ActionType.STAFF
            elif (distance <= me.cast_range) and (abs(angle) <
                                                  game.staff_sector / 2.0):
                move.action = ActionType.MAGIC_MISSILE
                move.cast_angle = angle
                move.min_cast_distance = distance - nearest_target.radius + game.magic_missile_radius

        if common_score < score_threshold:
            previous_waypoint = Points2D.get_previous_waypoint(
                self.waypoints, me)
            self.map.note_enemy_angle = False
            self.go_to(move, previous_waypoint, note_angle=False)
            self.last_actions[world.tick_index %
                              STOP_CHECK_TICK_COUNT] = Action.BACK
            return
        else:
            nearest_target = Points2D.get_nearest_target(me, world)
            if nearest_target is not None:
                distance = me.get_distance_to_unit(nearest_target)
                angle = me.get_angle_to_unit(nearest_target)
                if distance <= me.cast_range:
                    self.go_to(move, None, note_angle=False)
                    if abs(angle) < game.staff_sector / 2.0:
                        move.action = ActionType.MAGIC_MISSILE
                        move.cast_angle = angle
                        move.min_cast_distance = distance - nearest_target.radius + game.magic_missile_radius
                    self.last_actions[world.tick_index %
                                      STOP_CHECK_TICK_COUNT] = Action.ENEMY
                    return
                else:
                    min_attack_dist = min_atack_distance(me) * self.life_coef
                    new_x = me.x + (nearest_target.x - me.x) / distance * (
                        distance - min_attack_dist)
                    new_y = me.y + (nearest_target.y - me.y) / distance * (
                        distance - min_attack_dist)
                    self.go_to(move, Point2D(new_x, new_y), note_angle=True)
                    self.last_actions[world.tick_index %
                                      STOP_CHECK_TICK_COUNT] = Action.NEXT
                    return
            else:
                next_waypoint = Points2D.get_next_waypoint(self.waypoints, me)
                note_angle = True
                if world.tick_index > STOP_CHECK_TICK_COUNT:
                    last_pos_index = (world.tick_index +
                                      1) % STOP_CHECK_TICK_COUNT
                    dist_last_poses = me.get_distance_to_unit(
                        self.last_poses[last_pos_index])
                    # если далеко не ушел и если последние все действия NEXT
                    if ((dist_last_poses < STOP_CHECK_TICK_COUNT * 0.2 *
                         game.wizard_forward_speed) and
                        (sum([x == Action.NEXT for x in self.last_actions])
                         == STOP_CHECK_TICK_COUNT)):
                        note_angle = False
                        self.map.neutral_coef = 1000 * np.random.normal(1, 0.3)
                        self.map.neutral_dist_coef = 1000
                self.go_to(move, next_waypoint, note_angle=note_angle)
                self.last_actions[world.tick_index %
                                  STOP_CHECK_TICK_COUNT] = Action.NEXT
                if world.tick_index < SLOW_MOVE_TICK_COUNT:
                    move.speed *= 0.5
                    move.strafe_speed *= 0.5
                return
예제 #18
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
예제 #19
0
 def heal(self, trooper : Trooper, move : Move):
     move.action = ActionType.HEAL
     move.x = trooper.x
     move.y = trooper.y
     print('Солдат полечил')
예제 #20
0
 def do_scale(s: MyStrategy, w: World, g: Game, m: Move):
     m.action = ActionType.SCALE
     m.factor = factor
     m.x = center.x
     m.y = center.y
예제 #21
0
 def throwGrenade(self, trooper : Trooper, move : Move):
     move.action = ActionType.THROW_GRENADE
     move.x = trooper.x
     move.y = trooper.y
예제 #22
0
 def move(self, me: Wizard, world: World, game: Game, move: Move):
     move.speed = game.wizard_forward_speed
     move.strafe_speed = game.wizard_strafe_speed
     move.turn = game.wizard_max_turn_angle
     move.action = ActionType.MAGIC_MISSILE
예제 #23
0
 def do_rotate(s: MyStrategy, w: World, g: Game, m: Move):
     m.action = ActionType.ROTATE
     m.angle = angle
     m.max_angular_speed = max_speed
     m.x = center.x
     m.y = center.y
예제 #24
0
    def moveToPoint(self, targetX, targetY, me: Trooper, world: object, game: Game, move: Move):
        cells = world.cells

        offsetX = 0

        if me.x > targetX:
            offsetX = -1
        elif me.x < targetX:
            offsetX = 1
        else:
            offsetX = 0

        offsetY = 0

        if me.y > targetY:
            offsetY = -1
        elif me.y < targetY:
            offsetY = 1
        else:
            offsetY = 0

        x = -1
        y = -1
        canMoveToPoint = False

        if offsetX != 0:
            x = me.x + offsetX
            y = me.y
        elif offsetY != 0:
            x = me.x
            y = me.y + offsetY

        for bonus in world.bonuses:
            if bonus.x == x and bonus.y == y:
                canMoveToPoint = True

        canMoveX = offsetX != 0 and cells[me.x + offsetX][me.y] == CellType.FREE
        canMoveY = offsetY != 0 and cells[me.x][me.y + offsetY] == CellType.FREE

        canMoveX = canMoveX or canMoveToPoint
        canMoveY = canMoveY or canMoveToPoint

        if canMoveX or canMoveY:
            move.action = ActionType.MOVE

            if canMoveX and canMoveY:
                if randint(0, 9) % 2 == 0:
                    move.x = me.x + offsetX
                    move.y = me.y
                else:
                    move.x = me.x
                    move.y = me.y + offsetY
            elif canMoveX:
                move.x = me.x + offsetX
                move.y = me.y
            else:
                move.x = me.x
                move.y = me.y + offsetY
        else:
            print('Recalculate direction')

            quarter = 0

            if me.x > targetX and me.y < targetY:
                quarter = 1
            elif me.x > targetX and me.y > targetY:
                quarter = 2
            elif me.x < targetX and me.y > targetY:
                quarter = 3
            elif me.x < targetX and me.y < targetY:
                quarter = 4

            if quarter == 1:
                offsetX = 1
                offsetY = -1
            elif quarter == 2:
                offsetX = 1
                offsetY = 1
            elif quarter == 3:
                offsetX = -1
                offsetY = 1
            elif quarter == 4:
                offsetX = -1
                offsetY = -1

            if offsetX != 0:
                x = me.x + offsetX
                y = me.y
            elif offsetY != 0:
                x = me.x
                y = me.y + offsetY

            canMoveX = offsetX != 0 and cells[me.x + offsetX][me.y] == CellType.FREE
            canMoveY = offsetY != 0 and cells[me.x][me.y + offsetY] == CellType.FREE

            #if not canMoveX and not canMoveY:
                #self.moveToPoint(targetX + randint(0, 9) % 2, targetY + randint(0, 9) % 2, me, world, game, move)
                #return

            if canMoveX or canMoveY:
                print('Can move new direction')
                move.action = ActionType.MOVE

                if canMoveX and canMoveY:
                    if randint(0, 9) % 2 == 0:
                        move.x = me.x + offsetX
                        move.y = me.y
                    else:
                        move.x = me.x
                        move.y = me.y + offsetY
                elif canMoveX:
                    move.x = me.x + offsetX
                    move.y = me.y
                else:
                    move.x = me.x
                    move.y = me.y + offsetY
예제 #25
0
 def shrink_selected(self, move: Move):
     move.x, move.y = self.my_x, self.my_y
     move.action = ActionType.SCALE
     move.factor = 0.1
예제 #26
0
 def rotate_selected(self, move: Move):
     move.x, move.y = self.my_x, self.my_y
     move.action = ActionType.ROTATE
     move.angle = self.rotate_angle
예제 #27
0
 def move(self, me: Hockeyist, world: World, game: Game, move: Move):
     move.speed_up = -1.0
     move.turn = pi
     move.action = ActionType.STRIKE
예제 #28
0
 def decreaseStance(self, move : Move, game : Game, me : Trooper):
     move.action = ActionType.LOWER_STANCE
     move.direction = Direction.CURRENT_POINT
예제 #29
0
 def do_move(s: MyStrategy, w: World, g: Game, m: Move):
     m.action = ActionType.MOVE
     m.x = destination.x
     m.y = destination.y
     #print("Moving to: " + str(destination.x) + ":" + str(destination.y))
     m.max_speed = max_speed
예제 #30
0
 def expand(self, move: Move, x: float, y: float):
     move.action = ActionType.SCALE
     move.x = x
     move.y = y
     move.factor = 1.5
예제 #31
0
 def move(self, me: Hockeyist, world: World, game: Game, move: Move):
     move.speed_up = -1.0
     move.turn = pi
     move.action = ActionType.STRIKE
예제 #32
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))
예제 #33
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        self.log('TICK %s' % world.tick_index)
        self._init(game, me, world, move)
        self.log('me %s %s %f' %
                 (me.x, me.y, me.get_distance_to(*self.INIT_POINT)))

        # initial cooldown
        if self.PASS_TICK_COUNT:
            self.PASS_TICK_COUNT -= 1
            self.log('initial cooldown pass turn')
            return

        # select lane
        self._select_lane(me)

        # STRATEGY LOGIC
        enemy_targets = self._enemies_in_attack_distance(me)
        enemy_who_can_attack_me = self._enemies_who_can_attack_me(me)
        retreat_move_lock = False
        retreat_by_low_hp = False

        # чистим уже погибшие снаряды из карты
        current_projectiles_id = set(
            [p.id for p in self.W.projectiles if p.owner_unit_id == me.id])
        cached_projectiles_id = set(self.PROJECTILE_MAP.keys())
        for k in cached_projectiles_id - current_projectiles_id:
            del self.PROJECTILE_MAP[k]

        # ищем последний созданный снаряд и его цель для карты снарядов
        if self.PROJECTILE_LAST_ENEMY:
            for p in self.W.projectiles:
                if p.owner_unit_id == me.id and p.id not in self.PROJECTILE_MAP:
                    self.PROJECTILE_MAP[p.id] = self.PROJECTILE_LAST_ENEMY
                    self.PROJECTILE_LAST_ENEMY = None
                    break
        self.log('projectile map %s' % str(self.PROJECTILE_MAP))

        # если ХП мало отступаем
        if me.life < me.max_life * self.LOW_HP_FACTOR:
            retreat_by_low_hp = True
            self.log('retreat by low HP')
            if len(enemy_who_can_attack_me):
                self._goto_backward(me)
                retreat_move_lock = True

        if len(enemy_who_can_attack_me) > self.MAX_ENEMIES_IN_DANGER_ZONE:
            self.log('retreat by enemies in danger zone')
            self._goto_backward(me)
            retreat_move_lock = True

        # если врагов в радиусе обстрела нет - идём к их базе если не находимся в режиме отступления
        if not enemy_targets and not retreat_by_low_hp:
            self.log('move to next waypoint')
            self._goto_forward(me)

        # если на поле есть наши снаряды и расстояние до цели меньше расстояния каста
        # пробуем подойти к цели (если не находимся в отступлении)
        if not retreat_by_low_hp:
            potential_miss_enemies = self._find_potential_miss_enemy(me)
            self.log('found %s potential miss enemies' %
                     potential_miss_enemies)
            if potential_miss_enemies:
                e = self._sort_by_angle(me, potential_miss_enemies)[0]
                self._goto_enemy(me, e)

        if enemy_targets:
            # есть враги в радиусе обстрела
            self.log('found %d enemies for attack' % len(enemy_targets))
            selected_enemy = self._select_enemy_for_attack(me, enemy_targets)
            angle_to_enemy = me.get_angle_to_unit(selected_enemy)

            # если цель не в секторе атаки - поворачиваемся к ней (приоритет за направлением на точку отступления)
            if not self._enemy_in_attack_sector(me, selected_enemy):
                if not retreat_move_lock:
                    self.log('select enemy for turn %s' % selected_enemy.id)
                    self.MOVE_TURN = angle_to_enemy
                else:
                    self.log('ignore select enemy for turn %s by retreat' %
                             selected_enemy.id)
            else:
                # если можем атаковать - атакуем
                self.log('select enemy for attack %s' % selected_enemy.id)
                move.cast_angle = angle_to_enemy
                if self._enemy_in_cast_distance(me, selected_enemy):
                    self.log('cast attack')
                    move.action = ActionType.MAGIC_MISSILE
                    move.min_cast_distance = self._cast_distance(
                        me, selected_enemy)
                    self.PROJECTILE_LAST_ENEMY = selected_enemy.id
                else:
                    self.log('staff attack')
                    move.action = ActionType.STAFF

        if self.MOVE_TURN is not None:
            move.turn = self.MOVE_TURN
            self.MOVE_TURN = None
        if self.MOVE_SPEED is not None:
            move.speed = self.MOVE_SPEED
            self.MOVE_SPEED = None
        if self.MOVE_STRAFE_SPEED is not None:
            move.strafe_speed = self.MOVE_STRAFE_SPEED
            self.MOVE_STRAFE_SPEED = None