示例#1
0
                def will_meet():
                    if q.collinear(shell_speed):
                        #TODO: may be bug
                        good_direction = sign(shell_speed.x) != sign(
                            q.x) and sign(shell_speed.y) != sign(q.y)
                        if good_direction:
                            return (True, (shell_v - tank_v).length() /
                                    (shell_speed.length() +
                                     INITIAL_SHELL_VELOCITY))
                        else:
                            return (False, -1)
                    else:
                        d_tank, d_shell = intersect_lines(
                            tank_v, q, shell_v, shell_speed.normalize())
                        d_tank = d_tank - 40
                        if d_tank < 0 or d_shell < 0:
                            return (False, -1)

                        t_tank = solve_quadratic(SHELL_ACCELERATION / 2,
                                                 INITIAL_SHELL_VELOCITY,
                                                 -d_tank)
                        t_shell = solve_quadratic(SHELL_ACCELERATION / 2,
                                                  shell_speed.length(),
                                                  -d_shell)
                        if fabs(t_tank - t_shell) < 1.5:
                            return (True, t_tank)
                        else:
                            return (False, -1)
示例#2
0
    def shell_will_hit(self, shell, target, factor=1):
        """
        Returns True if shell will hit rectangular object
        """
        b = shell.angle
        e = Vector(1, 0)
        q = e.rotate(b)

        center = Vector(target.x - shell.x, target.y - shell.y)
        if center.scalar_product(q) < 0:
            return False

        a = target.angle

        c1 = center + Vector(target.width / 2 * factor,
                             target.height / 2 * factor).rotate(a)
        c2 = center + Vector(-target.width / 2 * factor,
                             target.height / 2 * factor).rotate(a)
        c3 = center + Vector(-target.width / 2 * factor,
                             -target.height / 2 * factor).rotate(a)
        c4 = center + Vector(target.width / 2 * factor,
                             -target.height / 2 * factor).rotate(a)
        if sign(c1.cross_product(q)) == sign(q.cross_product(c3)):
            #print("TEST", c1, c2, c3, c4, q)
            return True
        if sign(c2.cross_product(q)) == sign(q.cross_product(c4)):
            #print("TEST", c1, c2, c3, c4, q)
            return True
        return False
示例#3
0
    def shell_will_hit(self, shell, target, factor=1):
        """
        Returns True if shell will hit rectangular object
        """
        b = shell.angle
        e = Vector(1, 0)
        q = e.rotate(b)

        center = Vector(target.x - shell.x, target.y - shell.y)
        if center.scalar_product(q) < 0:
            return False

        a = target.angle

        c1 = center + Vector(target.width/2 * factor, target.height/2 * factor).rotate(a)
        c2 = center + Vector(- target.width/2 * factor, target.height/2 * factor).rotate(a)
        c3 = center + Vector(- target.width/2 * factor, - target.height/2 * factor).rotate(a)
        c4 = center + Vector(target.width/2 * factor, - target.height/2 * factor).rotate(a)
        if sign(c1.cross_product(q)) == sign(q.cross_product(c3)):
            #print("TEST", c1, c2, c3, c4, q)
            return True
        if sign(c2.cross_product(q)) == sign(q.cross_product(c4)):
            #print("TEST", c1, c2, c3, c4, q)
            return True
        return False
示例#4
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
示例#5
0
    def vector_is_intersecting_object(self, p, d, target, factor=1):
        center = Vector(target.x - p.x, target.y - p.y)
        if center.scalar_product(d) < 0:
            return False

        a = target.angle

        w, h = target.width / 2 * factor, target.height / 2 * factor
        c1 = center + Vector(w, h).rotate(a)
        c2 = center + Vector(-w, h).rotate(a)
        c3 = center + Vector(-w, -h).rotate(a)
        c4 = center + Vector(w, -h).rotate(a)
        if sign(c1.cross_product(d)) == sign(d.cross_product(c3)):
            return True
        if sign(c2.cross_product(d)) == sign(d.cross_product(c4)):
            return True
        return False
示例#6
0
    def vector_is_intersecting_object(self, p, d, target, factor=1):
        center = Vector(target.x - p.x, target.y - p.y)
        if center.scalar_product(d) < 0:
            return False

        a = target.angle

        w, h = target.width/2 * factor, target.height/2 * factor
        c1 = center + Vector(w ,h).rotate(a)
        c2 = center + Vector(- w, h).rotate(a)
        c3 = center + Vector(- w, - h).rotate(a)
        c4 = center + Vector(w, - h).rotate(a)
        if sign(c1.cross_product(d)) == sign(d.cross_product(c3)):
            return True
        if sign(c2.cross_product(d)) == sign(d.cross_product(c4)):
            return True
        return False
示例#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 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
    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)
示例#10
0
                def will_meet():
                    if q.collinear(shell_speed):
                        #TODO: may be bug
                        good_direction = sign(shell_speed.x) != sign(q.x) and sign(shell_speed.y) != sign(q.y)
                        if good_direction:
                            return (True, (shell_v - tank_v).length()/(shell_speed.length() + INITIAL_SHELL_VELOCITY))
                        else:
                            return (False, -1)
                    else:
                        d_tank, d_shell = intersect_lines(tank_v, q, shell_v, shell_speed.normalize())
                        d_tank = d_tank - 40
                        if d_tank < 0 or d_shell < 0:
                            return (False, -1)

                        t_tank = solve_quadratic(SHELL_ACCELERATION/2, INITIAL_SHELL_VELOCITY, -d_tank)
                        t_shell = solve_quadratic(SHELL_ACCELERATION/2, shell_speed.length(), -d_shell)
                        if fabs(t_tank - t_shell) < 1.5:
                            return (True, t_tank)
                        else:
                            return (False, -1)
示例#11
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)
        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)