コード例 #1
0
    def multiple_attackers(attackers):
        cnt = len(allies_targeting)
        ind = index_in_sorted(allies_targeting, tank.id)

        segment = (target_avoid_distance_forward -
                   target_avoid_distance_backward) / (cnt + 1)

        shift = segment * (ind + 1) + target_avoid_distance_backward
        #shift *
        if cnt == 2:
            if ind == 0:
                shift = target_avoid_distance_backward + 45
            else:
                shift = target_avoid_distance_forward - 45

        estimate_pos = target_v + target_direction * shift
        shift_fu = fictive_unit(target, estimate_pos.x, estimate_pos.y)

        shoot = (
            physics.will_hit_precise(tank, shift_fu, factor=0.8) and all([
                lambda a: a.remaining_reloading_time <
                MULTIPLE_MAX_TIME_DIFFERENCE or a.reloading_time - a.
                remaining_reloading_time < MULTIPLE_MAX_TIME_DIFFERENCE,
                attackers
            ])
            #and target_avoid_distance_forward - target_avoid_distance_backward < 200
        )

        comment = 'MULTIPLE(%d), shift=%8.2f' % (ind, shift)
        if obstacle_is_attacked(context, estimate_pos):
            shoot = False
            comment += ' blocked'

        if context.debug_mode:
            if shoot and tank.remaining_reloading_time == 0 and all([
                    context.memory.good_to_shoot.get(t.id) or t.id == tank.id
                    for t in attackers
            ]):
                max_pos = target_v + target_avoid_distance_forward * target_direction
                min_pos = target_v + target_avoid_distance_backward * target_direction
                max_pos_fu = fictive_unit(target, max_pos.x, max_pos.y)
                min_pos_fu = fictive_unit(target, min_pos.x, min_pos.y)
                debug_data = {
                    "units": [min_pos_fu, max_pos_fu, target],
                    "tanks": attackers
                }
                debug_dump(
                    debug_data, "/".join([
                        str(context.memory.battle_id),
                        str(context.world.tick) + "_" + str(tank.id) +
                        "_multiple"
                    ]))

        return ((estimate_pos.x,
                 estimate_pos.y), shoot, target_avoid_distance_forward,
                target_avoid_distance_backward, comment)
コード例 #2
0
    def single_attacker():
        #estimate_pos = target_v + target_direction * ((target_avoid_distance_forward + target_avoid_distance_backward) / 2)
        #vulnerable_width = max(90 * target_turret_n_cos, 60 * (1 - target_turret_n_cos))

        target_avoid_distance_forward_new = target_avoid_distance_forward * context.memory.tank_precision[
            tank.id]
        target_avoid_distance_backward_new = target_avoid_distance_backward * context.memory.tank_precision[
            tank.id]
        max_pos = target_v + target_avoid_distance_forward_new * target_direction
        min_pos = target_v + target_avoid_distance_backward_new * target_direction

        max_pos_fu = fictive_unit(target, max_pos.x, max_pos.y)
        min_pos_fu = fictive_unit(target, min_pos.x, min_pos.y)

        #shoot = physics.will_hit(tank, max_pos_fu, 0.9) and physics.will_hit(tank, min_pos_fu, 0.9)

        shoot_precise = physics.will_hit_precise(tank, max_pos_fu, factor=0.8, side_part=0.8) and \
                        physics.will_hit_precise(tank, min_pos_fu, factor=0.8, side_part=0.8) and \
                        physics.will_hit_precise(tank, target, factor=0.8, side_part=0.8)
        shoot = shoot_precise
        fabs(target_turret_n_cos)

        #all_corners = get_unit_corners(max_pos_fu) + get_unit_corners(min_pos_fu)
        all_corners = get_unit_corners(target)
        #closest_corner = min(all_corners, key=lambda c: c.distance(tank_v))
        # Instead of closest corner try to target middle of colsest side
        sc1, sc2 = sorted(all_corners, key=lambda c: c.distance(tank_v))[:2]
        closest_corner = 0.75 * sc1 + 0.25 * sc2

        middle_position = (max_pos + min_pos) / 2

        w = fabs(target_turret_n_cos)**2
        estimate_pos = w * middle_position + (1 - w) * closest_corner

        comment = 'SINGLE, %s' % w

        if obstacle_is_attacked(context, estimate_pos):
            shoot = False
            comment += ' blocked'

        if context.debug_mode:
            if shoot and tank.remaining_reloading_time == 0:
                debug_data = {
                    "units": [min_pos_fu, max_pos_fu, target],
                    "tanks": [tank]
                }
                debug_dump(
                    debug_data, "/".join([
                        str(context.memory.battle_id),
                        str(context.world.tick) + "_" + str(tank.id) +
                        "_single"
                    ]))

        return ((estimate_pos.x,
                 estimate_pos.y), shoot, target_avoid_distance_forward,
                target_avoid_distance_backward, comment)
コード例 #3
0
def obstacle_is_attacked(context, est_pos):
    world = context.world
    tank = context.tank
    physics = context.physics

    obstacles = chain(
        filter(DEAD_TANK, world.tanks),
        filter(ALLY_TANK(tank.id), world.tanks)
    )
    for obstacle in obstacles:
        next_position = physics.estimate_target_position(obstacle, tank)
        next_unit = fictive_unit(obstacle, next_position[0], next_position[1])

        blocked = ((physics.will_hit(tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                    or physics.will_hit(tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                   and tank.get_distance_to_unit(obstacle) < tank.get_distance_to(est_pos.x, est_pos.y))
        if blocked:
            return obstacle

    for bonus in world.bonuses:
        if (physics.will_hit(tank, bonus, BONUS_FACTOR)):
            dist_tank_to_bonus = tank.get_distance_to_unit(bonus)
            dist_tank_to_pos = tank.get_distance_to(est_pos.x, est_pos.y)
            if dist_tank_to_bonus < dist_tank_to_pos:
                dist_bonus_to_pos = bonus.get_distance_to(est_pos.x, est_pos.y)
                free_to_hit = dist_tank_to_bonus > 300 and dist_tank_to_bonus > 2 * dist_bonus_to_pos
                if not free_to_hit:
                    return bonus

    bunker_obstacle = world.obstacles[0]
    if (physics.will_hit(tank, bunker_obstacle, 1.06) and
        tank.get_distance_to_unit(bunker_obstacle) < tank.get_distance_to(est_pos.x, est_pos.y)):
        return bunker_obstacle
    return False
コード例 #4
0
def obstacle_is_attacked(context, est_pos):
    world = context.world
    tank = context.tank
    physics = context.physics

    obstacles = chain(filter(DEAD_TANK, world.tanks),
                      filter(ALLY_TANK(tank.id), world.tanks))
    for obstacle in obstacles:
        next_position = physics.estimate_target_position(obstacle, tank)
        next_unit = fictive_unit(obstacle, next_position[0], next_position[1])

        blocked = (
            (physics.will_hit(tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
             or physics.will_hit(tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
            and tank.get_distance_to_unit(obstacle) < tank.get_distance_to(
                est_pos.x, est_pos.y))
        if blocked:
            return obstacle

    for bonus in world.bonuses:
        if (physics.will_hit(tank, bonus, BONUS_FACTOR)):
            dist_tank_to_bonus = tank.get_distance_to_unit(bonus)
            dist_tank_to_pos = tank.get_distance_to(est_pos.x, est_pos.y)
            if dist_tank_to_bonus < dist_tank_to_pos:
                dist_bonus_to_pos = bonus.get_distance_to(est_pos.x, est_pos.y)
                free_to_hit = dist_tank_to_bonus > 300 and dist_tank_to_bonus > 2 * dist_bonus_to_pos
                if not free_to_hit:
                    return bonus

    bunker_obstacle = world.obstacles[0]
    if (physics.will_hit(tank, bunker_obstacle, 1.06)
            and tank.get_distance_to_unit(bunker_obstacle) <
            tank.get_distance_to(est_pos.x, est_pos.y)):
        return bunker_obstacle
    return False
コード例 #5
0
    def single_attacker():
        #estimate_pos = target_v + target_direction * ((target_avoid_distance_forward + target_avoid_distance_backward) / 2)
        #vulnerable_width = max(90 * target_turret_n_cos, 60 * (1 - target_turret_n_cos))

        target_avoid_distance_forward_new = target_avoid_distance_forward * context.memory.tank_precision[tank.id]
        target_avoid_distance_backward_new = target_avoid_distance_backward * context.memory.tank_precision[tank.id]
        max_pos = target_v + target_avoid_distance_forward_new * target_direction
        min_pos = target_v + target_avoid_distance_backward_new * target_direction

        max_pos_fu = fictive_unit(target, max_pos.x, max_pos.y)
        min_pos_fu = fictive_unit(target, min_pos.x, min_pos.y)

        #shoot = physics.will_hit(tank, max_pos_fu, 0.9) and physics.will_hit(tank, min_pos_fu, 0.9)

        shoot_precise = physics.will_hit_precise(tank, max_pos_fu, factor=0.8, side_part=0.8) and \
                        physics.will_hit_precise(tank, min_pos_fu, factor=0.8, side_part=0.8) and \
                        physics.will_hit_precise(tank, target, factor=0.8, side_part=0.8)
        shoot = shoot_precise
        fabs(target_turret_n_cos)

        #all_corners = get_unit_corners(max_pos_fu) + get_unit_corners(min_pos_fu)
        all_corners = get_unit_corners(target)
        #closest_corner = min(all_corners, key=lambda c: c.distance(tank_v))
        # Instead of closest corner try to target middle of colsest side
        sc1, sc2 = sorted(all_corners, key=lambda c: c.distance(tank_v))[:2]
        closest_corner = 0.75 * sc1 + 0.25 * sc2

        middle_position = (max_pos + min_pos)/2

        w = fabs(target_turret_n_cos)**2
        estimate_pos = w*middle_position + (1 - w) * closest_corner

        comment = 'SINGLE, %s' % w

        if obstacle_is_attacked(context, estimate_pos):
            shoot = False
            comment += ' blocked'

        if context.debug_mode:
            if shoot and tank.remaining_reloading_time == 0:
                debug_data = {
                    "units": [min_pos_fu, max_pos_fu, target],
                    "tanks": [tank]
                }
                debug_dump(debug_data, "/".join([str(context.memory.battle_id), str(context.world.tick) + "_" + str(tank.id) + "_single"]))

        return ((estimate_pos.x, estimate_pos.y), shoot, target_avoid_distance_forward, target_avoid_distance_backward, comment)
コード例 #6
0
    def process(self, cur_target, move):
        tank = self.context.tank
        world = self.context.world
        self.physics = self.context.physics
        world = self.context.world

        est_pos = self.physics.estimate_target_position(cur_target, tank)

        def bonus_is_attacked():
            for bonus in world.bonuses:
                if (self.physics.will_hit(tank, bonus, BONUS_FACTOR)
                        and tank.get_distance_to_unit(bonus) <
                        tank.get_distance_to(*est_pos)):
                    return bonus
            return False

        def obstacle_is_attacked():
            obstacles = chain(filter(DEAD_TANK, world.tanks),
                              filter(ALLY_TANK(tank.id), world.tanks),
                              world.obstacles)
            for obstacle in obstacles:
                next_position = self.physics.estimate_target_position(
                    obstacle, tank)
                next_unit = fictive_unit(obstacle, next_position[0],
                                         next_position[1])

                blocked = ((self.physics.will_hit(tank, next_unit,
                                                  DEAD_TANK_OBSTACLE_FACTOR)
                            or self.physics.will_hit(
                                tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                           and tank.get_distance_to_unit(obstacle) <
                           tank.get_distance_to(*est_pos))
                if blocked:
                    return obstacle
            return False

        cur_angle = tank.get_turret_angle_to(*est_pos)
        good_to_shoot = self.physics.will_hit(
            tank, fictive_unit(cur_target, est_pos[0], est_pos[1]),
            TARGETING_FACTOR)
        if good_to_shoot:
            if self.context.health_fraction > 0.8 and self.context.hull_fraction > 0.5 and tank.get_distance_to_unit(
                    cur_target) > 400 and tank.premium_shell_count <= 3:
                move.fire_type = FireType.REGULAR
            else:
                move.fire_type = FireType.PREMIUM_PREFERRED
        else:
            move.fire_type = FireType.NONE

        if bonus_is_attacked() or obstacle_is_attacked():
            self.context.debug('!!! Obstacle is attacked, don\'t shoot')
            move.fire_type = FireType.NONE

        if world.tick < 10 + tank.teammate_index * 10:
            move.fire_type = FireType.NONE

        if fabs(cur_angle) > PI / 180 * 0.5:
            move.turret_turn = sign(cur_angle)
コード例 #7
0
    def process(self, cur_target, move):
        tank = self.context.tank
        world = self.context.world
        self.physics = self.context.physics
        world = self.context.world

        est_pos = self.physics.estimate_target_position(cur_target, tank)

        def bonus_is_attacked():
            for bonus in world.bonuses:
                if (self.physics.will_hit(tank, bonus, BONUS_FACTOR) and
                    tank.get_distance_to_unit(bonus) < tank.get_distance_to(*est_pos)):
                    return bonus
            return False

        def obstacle_is_attacked():
            obstacles = chain(
                filter(DEAD_TANK, world.tanks),
                filter(ALLY_TANK(tank.id), world.tanks),
                world.obstacles
            )
            for obstacle in obstacles:
                next_position = self.physics.estimate_target_position(obstacle, tank)
                next_unit = fictive_unit(obstacle, next_position[0], next_position[1])

                blocked = ((self.physics.will_hit(tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                            or self.physics.will_hit(tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                           and tank.get_distance_to_unit(obstacle) < tank.get_distance_to(*est_pos))
                if blocked:
                    return obstacle
            return False

        cur_angle = tank.get_turret_angle_to(*est_pos)
        good_to_shoot = self.physics.will_hit(
            tank,
            fictive_unit(cur_target, est_pos[0], est_pos[1]),
            TARGETING_FACTOR
        )
        if good_to_shoot:
            if self.context.health_fraction > 0.8 and self.context.hull_fraction > 0.5 and tank.get_distance_to_unit(cur_target) > 400 and tank.premium_shell_count <= 3:
                move.fire_type = FireType.REGULAR
            else:
                move.fire_type = FireType.PREMIUM_PREFERRED
        else:
            move.fire_type = FireType.NONE

        if bonus_is_attacked() or obstacle_is_attacked():
            self.context.debug('!!! Obstacle is attacked, don\'t shoot')
            move.fire_type = FireType.NONE

        if world.tick < 10 + tank.teammate_index * 10:
            move.fire_type = FireType.NONE

        if fabs(cur_angle) > PI/180 * 0.5:
            move.turret_turn = sign(cur_angle)
コード例 #8
0
    def multiple_attackers(attackers):
        cnt = len(allies_targeting)
        ind = index_in_sorted(allies_targeting, tank.id)

        segment = (target_avoid_distance_forward - target_avoid_distance_backward)/(cnt + 1)

        shift = segment * (ind + 1) + target_avoid_distance_backward
        #shift *
        if cnt == 2:
            if ind == 0:
                shift = target_avoid_distance_backward + 45
            else:
                shift = target_avoid_distance_forward - 45

        estimate_pos = target_v + target_direction * shift
        shift_fu = fictive_unit(target, estimate_pos.x, estimate_pos.y)

        shoot = (physics.will_hit_precise(tank, shift_fu, factor=0.8) and
                 all([lambda a: a.remaining_reloading_time < MULTIPLE_MAX_TIME_DIFFERENCE or a.reloading_time - a.remaining_reloading_time < MULTIPLE_MAX_TIME_DIFFERENCE, attackers])
                 #and target_avoid_distance_forward - target_avoid_distance_backward < 200
            )

        comment = 'MULTIPLE(%d), shift=%8.2f' % (ind, shift)
        if obstacle_is_attacked(context, estimate_pos):
            shoot = False
            comment += ' blocked'

        if context.debug_mode:
            if shoot and tank.remaining_reloading_time == 0 and all([context.memory.good_to_shoot.get(t.id) or t.id == tank.id for t in attackers]):
                max_pos = target_v + target_avoid_distance_forward * target_direction
                min_pos = target_v + target_avoid_distance_backward * target_direction
                max_pos_fu = fictive_unit(target, max_pos.x, max_pos.y)
                min_pos_fu = fictive_unit(target, min_pos.x, min_pos.y)
                debug_data = {
                    "units": [min_pos_fu, max_pos_fu, target],
                    "tanks": attackers
                }
                debug_dump(debug_data, "/".join([str(context.memory.battle_id), str(context.world.tick) + "_" + str(tank.id) + "_multiple"]))

        return ((estimate_pos.x, estimate_pos.y), shoot, target_avoid_distance_forward, target_avoid_distance_backward, comment)
コード例 #9
0
    def shell_will_hit_tank_going_to(self, shell, tank, x, y, et=None):
        if et is None:
            et = self.estimate_time_to_position(x, y, tank)

        dist = tank.get_distance_to(x, y)

        v0 = hypot(shell.speedX, shell.speedY)
        a = SHELL_ACCELERATION
        d = tank.get_distance_to_unit(shell)
        #d = shell.get_distance_to(x, y)
        t = solve_quadratic(a / 2, v0, -d)

        if self.shell_will_hit(shell, tank, factor=1.05) and (et > t):
            return 1

        #self.max_move_distance(fabs(v0), FICTIVE_ACCELERATION, 3, t) < dist):

        if dist < 150:
            # short distance
            result = self.shell_will_hit(shell,
                                         fictive_unit(tank, x, y),
                                         factor=1.05)
            if result:
                pt_v = Vector(x, y)
                tank_v = Vector(tank.x, tank.y)
                dir = pt_v - tank_v
                shell_speed = Vector(shell.speedX, shell.speedY)
                if dir.is_zero() or shell_speed.is_zero():
                    return float(result)
                if dir.angle(shell_speed) < PI / 8 and shell.get_distance_to(
                        x, y) > d:
                    return 0.6

            return result

        else:
            # long distance, check if our direction is intersecting segment between shell and shell + v_shell*t
            pt_v = Vector(x, y)
            tank_v = Vector(tank.x, tank.y)
            dir = tank_v - pt_v
            shell_v = Vector(shell.x, shell.y)
            shell_speed = Vector(shell.speedX, shell.speedY)
            next_shell = shell_v + shell_speed * (t + 5)
            if sign((shell_v - tank_v).cross_product(dir)) == sign(
                    dir.cross_product(next_shell - tank_v)):
                return True
            else:
                return False
コード例 #10
0
            def obstacle_is_attacked():
                obstacles = chain(
                    filter(DEAD_TANK, world.tanks),
                    filter(ALLY_TANK(tank.id), world.tanks),
                    world.obstacles
                )
                for obstacle in obstacles:
                    next_position = self.physics.estimate_target_position(obstacle, tank)
                    next_unit = fictive_unit(obstacle, next_position[0], next_position[1])

                    blocked = ((self.physics.will_hit(tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                                or self.physics.will_hit(tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                               and tank.get_distance_to_unit(obstacle) < tank.get_distance_to(*est_pos))
                    if blocked:
                        return obstacle
                return False
コード例 #11
0
    def shell_will_hit_tank_going_to(self, shell, tank, x, y, et=None):
        if et is None:
            et = self.estimate_time_to_position(x, y, tank)

        dist = tank.get_distance_to(x, y)

        v0 = hypot(shell.speedX, shell.speedY)
        a = SHELL_ACCELERATION
        d = tank.get_distance_to_unit(shell)
        #d = shell.get_distance_to(x, y)
        t = solve_quadratic(a/2, v0, -d)

        if self.shell_will_hit(shell, tank, factor=1.05) and (et > t):
            return 1

        #self.max_move_distance(fabs(v0), FICTIVE_ACCELERATION, 3, t) < dist):

        if dist < 150:
            # short distance
            result = self.shell_will_hit(shell, fictive_unit(tank, x, y), factor=1.05)
            if result:
                pt_v = Vector(x, y)
                tank_v = Vector(tank.x, tank.y)
                dir = pt_v - tank_v
                shell_speed = Vector(shell.speedX, shell.speedY)
                if dir.is_zero() or shell_speed.is_zero():
                    return float(result)
                if dir.angle(shell_speed) < PI/8 and shell.get_distance_to(x, y) > d:
                    return 0.6

            return result

        else:
            # long distance, check if our direction is intersecting segment between shell and shell + v_shell*t
            pt_v = Vector(x, y)
            tank_v = Vector(tank.x, tank.y)
            dir = tank_v - pt_v
            shell_v = Vector(shell.x, shell.y)
            shell_speed = Vector(shell.speedX, shell.speedY)
            next_shell = shell_v + shell_speed * (t + 5)
            if sign((shell_v - tank_v).cross_product(dir)) == sign(dir.cross_product(next_shell - tank_v)):
                return True
            else:
                return False
コード例 #12
0
            def obstacle_is_attacked():
                obstacles = chain(filter(DEAD_TANK, world.tanks),
                                  filter(ALLY_TANK(tank.id), world.tanks),
                                  world.obstacles)
                for obstacle in obstacles:
                    next_position = self.physics.estimate_target_position(
                        obstacle, tank)
                    next_unit = fictive_unit(obstacle, next_position[0],
                                             next_position[1])

                    blocked = ((self.physics.will_hit(
                        tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                                or self.physics.will_hit(
                                    tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                               and tank.get_distance_to_unit(obstacle) <
                               tank.get_distance_to(*est_pos))
                    if blocked:
                        return obstacle
                return False
コード例 #13
0
        def process_shooting():
            targets = filter(ALIVE_ENEMY_TANK, world.tanks)

            if not targets:
                return

            def get_target_priority(tank, target):
                health_fraction = tank.crew_health / tank.crew_max_health

                # ================
                # DISTANCE
                # ================
                angle_penalty_factor = (
                    1 + (1 - health_fraction) * 1.5 -
                    (1 - max(0, 150 - tank.remaining_reloading_time) / 150) *
                    1)

                angle_degrees = fabs(
                    tank.get_turret_angle_to_unit(target)) / PI * 180

                distance_penalty = tank.get_distance_to_unit(target) / 10
                angle_penalty = angle_penalty_factor * (angle_degrees**1.2) / 2

                # ================
                # FINISH
                # ================
                if ((target.crew_health <= 20 or target.hull_durability <= 20)
                        or (tank.premium_shell_count > 0 and
                            (target.crew_health <= 35
                             or target.hull_durability <= 35))):
                    finish_bonus = 30
                else:
                    finish_bonus = 0

                # ================
                # RESPONSE
                # ================
                if self.physics.attacked_area(
                        tank.x, tank.y, target, cache=self.EA_cache) > 0.5:
                    attacking_me_bonus = 20
                else:
                    attacking_me_bonus = 0

                # ================
                # LAST TARGET
                # ================
                last_target_bonus = 0
                if self.memory.last_turret_target_id:
                    if self.memory.last_turret_target_id == target.id:
                        last_target_bonus = 5

                result = 180 + finish_bonus + attacking_me_bonus + last_target_bonus - distance_penalty - angle_penalty
                self.debug(
                    'TARGET [%20s] (x=%8.2f, y=%8.2f, |v|=%8.2f) finish_B=%8.2f, AM_B=%8.2f, LT_B=%8.2f, D_P=%8.2f, A_P=%8.2f, APF=%8.2f, result=%8.2f'
                    % (target.player_name, target.x, target.y,
                       hypot(target.speedX, target.speedY), finish_bonus,
                       attacking_me_bonus, last_target_bonus, distance_penalty,
                       angle_penalty, angle_penalty_factor, result))
                return result

            if self.debug_mode:
                targets = sorted(targets, key=lambda t: t.player_name)
            targets_f = [(t, get_target_priority(tank, t)) for t in targets]

            cur_target = max(targets_f, key=operator.itemgetter(1))[0]
            self.memory.last_turret_target_id = cur_target.id

            est_pos = self.physics.estimate_target_position(cur_target, tank)

            def bonus_is_attacked():
                for bonus in world.bonuses:
                    if (self.physics.will_hit(tank, bonus, BONUS_FACTOR)
                            and tank.get_distance_to_unit(bonus) <
                            tank.get_distance_to(*est_pos)):
                        return bonus
                return False

            def obstacle_is_attacked():
                obstacles = chain(filter(DEAD_TANK, world.tanks),
                                  filter(ALLY_TANK(tank.id), world.tanks),
                                  world.obstacles)
                for obstacle in obstacles:
                    next_position = self.physics.estimate_target_position(
                        obstacle, tank)
                    next_unit = fictive_unit(obstacle, next_position[0],
                                             next_position[1])

                    blocked = ((self.physics.will_hit(
                        tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                                or self.physics.will_hit(
                                    tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                               and tank.get_distance_to_unit(obstacle) <
                               tank.get_distance_to(*est_pos))
                    if blocked:
                        return obstacle
                return False

            cur_angle = tank.get_turret_angle_to(*est_pos)
            good_to_shoot = self.physics.will_hit(
                tank, fictive_unit(cur_target, est_pos[0], est_pos[1]),
                TARGETING_FACTOR)
            if good_to_shoot:
                if self.health_fraction > 0.8 and self.hull_fraction > 0.5 and tank.get_distance_to_unit(
                        cur_target) > 400 and tank.premium_shell_count <= 3:
                    move.fire_type = FireType.REGULAR
                else:
                    move.fire_type = FireType.PREMIUM_PREFERRED
            else:
                move.fire_type = FireType.NONE

            if bonus_is_attacked() or obstacle_is_attacked():
                self.debug('!!! Obstacle is attacked, don\'t shoot')
                move.fire_type = FireType.NONE

            if world.tick < 10 + tank.teammate_index * 10:
                move.fire_type = FireType.NONE

            if fabs(cur_angle) > PI / 180 * 0.5:
                move.turret_turn = sign(cur_angle)
コード例 #14
0
        def process_shooting():
            targets = filter(ALIVE_ENEMY_TANK, world.tanks)

            if not targets:
                return

            def get_target_priority(tank, target):
                health_fraction = tank.crew_health / tank.crew_max_health

                # ================
                # DISTANCE
                # ================
                angle_penalty_factor = (1 + (1 - health_fraction) * 1.5 -
                                        (1 - max(0, 150 - tank.remaining_reloading_time)/150) * 1)

                angle_degrees = fabs(tank.get_turret_angle_to_unit(target)) / PI * 180

                distance_penalty = tank.get_distance_to_unit(target) / 10
                angle_penalty = angle_penalty_factor * (angle_degrees**1.2)/2

                # ================
                # FINISH
                # ================
                if ((target.crew_health <= 20 or target.hull_durability <= 20) or
                    (tank.premium_shell_count > 0 and (target.crew_health <= 35 or target.hull_durability <= 35))):
                    finish_bonus = 30
                else:
                    finish_bonus = 0

                # ================
                # RESPONSE
                # ================
                if self.physics.attacked_area(tank.x, tank.y, target, cache=self.EA_cache) > 0.5:
                    attacking_me_bonus = 20
                else:
                    attacking_me_bonus = 0

                # ================
                # LAST TARGET
                # ================
                last_target_bonus = 0
                if self.memory.last_turret_target_id:
                    if self.memory.last_turret_target_id == target.id:
                        last_target_bonus = 5

                result = 180 + finish_bonus + attacking_me_bonus + last_target_bonus - distance_penalty - angle_penalty
                self.debug('TARGET [%20s] (x=%8.2f, y=%8.2f, |v|=%8.2f) finish_B=%8.2f, AM_B=%8.2f, LT_B=%8.2f, D_P=%8.2f, A_P=%8.2f, APF=%8.2f, result=%8.2f' %
                           (target.player_name, target.x, target.y, hypot(target.speedX, target.speedY), finish_bonus, attacking_me_bonus, last_target_bonus,
                            distance_penalty, angle_penalty, angle_penalty_factor, result))
                return result

            if self.debug_mode:
                targets = sorted(targets, key=lambda t : t.player_name)
            targets_f = [(t, get_target_priority(tank, t)) for t in targets]

            cur_target = max(targets_f, key=operator.itemgetter(1))[0]
            self.memory.last_turret_target_id = cur_target.id

            est_pos = self.physics.estimate_target_position(cur_target, tank)

            def bonus_is_attacked():
                for bonus in world.bonuses:
                    if (self.physics.will_hit(tank, bonus, BONUS_FACTOR) and
                        tank.get_distance_to_unit(bonus) < tank.get_distance_to(*est_pos)):
                        return bonus
                return False

            def obstacle_is_attacked():
                obstacles = chain(
                    filter(DEAD_TANK, world.tanks),
                    filter(ALLY_TANK(tank.id), world.tanks),
                    world.obstacles
                )
                for obstacle in obstacles:
                    next_position = self.physics.estimate_target_position(obstacle, tank)
                    next_unit = fictive_unit(obstacle, next_position[0], next_position[1])

                    blocked = ((self.physics.will_hit(tank, next_unit, DEAD_TANK_OBSTACLE_FACTOR)
                                or self.physics.will_hit(tank, obstacle, DEAD_TANK_OBSTACLE_FACTOR))
                               and tank.get_distance_to_unit(obstacle) < tank.get_distance_to(*est_pos))
                    if blocked:
                        return obstacle
                return False

            cur_angle = tank.get_turret_angle_to(*est_pos)
            good_to_shoot = self.physics.will_hit(
                tank,
                fictive_unit(cur_target, est_pos[0], est_pos[1]),
                TARGETING_FACTOR
            )
            if good_to_shoot:
                if self.health_fraction > 0.8 and self.hull_fraction > 0.5 and tank.get_distance_to_unit(cur_target) > 400 and tank.premium_shell_count <= 3:
                    move.fire_type = FireType.REGULAR
                else:
                    move.fire_type = FireType.PREMIUM_PREFERRED
            else:
                move.fire_type = FireType.NONE

            if bonus_is_attacked() or obstacle_is_attacked():
                self.debug('!!! Obstacle is attacked, don\'t shoot')
                move.fire_type = FireType.NONE

            if world.tick < 10 + tank.teammate_index * 10:
                move.fire_type = FireType.NONE

            if fabs(cur_angle) > PI/180 * 0.5:
                move.turret_turn = sign(cur_angle)
コード例 #15
0
    def debug_value(self, target):
        tank = self.context.tank
        physics = self.context.physics

        b = tank.angle + tank.turret_relative_angle
        e = Vector(1, 0)
        q = e.rotate(b)

        target_v = Vector(target.x, target.y)
        target_direction = Vector(1, 0).rotate(target.angle)
        target_speed = Vector(target.speedX, target.speedY)

        def get_hit_time():
            v0 = INITIAL_SHELL_VELOCITY
            a = SHELL_ACCELERATION
            d = max(0, tank.get_distance_to_unit(target) - 60)
            return solve_quadratic(a / 2, v0, -d)

        def max_move_distance(v0, a, max_v, t):
            #TODO: this estimation is rough
            v0 = max(-max_v, min(v0, max_v))
            if fabs(v0 + a * t) > max_v:
                if a > 0:
                    t1 = fabs((max_v - v0) / a)
                else:
                    t1 = fabs((-max_v - v0) / a)
                t2 = t - t1
            else:
                t1 = t
                t2 = 0
            if a > 0:
                return a * t1**2 / 2 + v0 * t1 + max_v * t2
            else:
                return a * t1**2 / 2 + v0 * t1 - max_v * t2

        t = get_hit_time()
        center = Vector(target.x - tank.x, target.y - tank.y)

        v0 = target_speed.projection(target_direction)
        target_avoid_distance_forward = max_move_distance(
            v0, FICTIVE_TARGET_ACCELERATION, MAX_TARGET_SPEED, t)
        target_avoid_distance_backward = max_move_distance(
            v0, -FICTIVE_TARGET_ACCELERATION * 0.75, MAX_TARGET_SPEED, t)
        max_pos = target_v + target_avoid_distance_forward * target_direction
        min_pos = target_v + target_avoid_distance_backward * target_direction

        target_turret_n_cos = fabs(cos(fabs(b - target.angle) + PI / 2))

        var = fabs(
            (target_avoid_distance_forward - target_avoid_distance_backward) *
            target_turret_n_cos)

        estimate_pos = target_v + target_direction * (
            (target_avoid_distance_forward + target_avoid_distance_backward) /
            2)
        vulnerable_width = max(90 * target_turret_n_cos,
                               60 * (1 - target_turret_n_cos))

        shoot = physics.will_hit(
            tank, fictive_unit(
                target, max_pos.x, max_pos.y)) and physics.will_hit(
                    tank, fictive_unit(target, min_pos.x, min_pos.y))

        return "fw=%s, bw=%s, t=%s, var=%s, wid=%s, degree=%s, shoot=%s" % (
            int(target_avoid_distance_forward),
            int(target_avoid_distance_backward), int(t), int(var),
            vulnerable_width,
            fabs(tank.get_turret_angle_to(estimate_pos.x, estimate_pos.y)) /
            PI * 180, shoot)