Пример #1
0
    def estimate_time_to_position(self, x, y, tank):
        dist = tank.get_distance_to(x, y)
        vt = Vector(tank.speedX, tank.speedY)

        tank_v = Vector(tank.x, tank.y)
        pt_v = Vector(x, y)
        d = pt_v - tank_v

        if d.is_zero():
            return 0

        tank_d_v = Vector(1, 0).rotate(tank.angle)

        if vt.is_zero() or d.is_zero():
            vd_angle = 0
        else:
            vd_angle = vt.angle(d)

        if tank_d_v.is_zero() or d.is_zero():
            d_angle = 0
        else:
            d_angle = tank_d_v.angle(d)

        # Short distances fix
        if dist < 100:
            if fabs(d_angle) < LOW_ANGLE:
                v0 = vt.projection(d)
                return solve_quadratic(FICTIVE_ACCELERATION/2, v0, -dist)
                #return dist/6
            elif PI - fabs(d_angle) < LOW_ANGLE:
                v0 = vt.projection(d)
                return solve_quadratic(FICTIVE_ACCELERATION/2 * 0.75, v0, -dist)
                #return dist/6 /0.75

        if d.is_zero():
            values = (0, 0, 0, 0, 0, 0, 0, 1)
        else:

            values = (
                d_angle,
                dist,
                vd_angle,
                vt.length(),
                tank.angular_speed,
                tank.crew_health/tank.crew_max_health,
                d_angle ** 2,
                1
                )

        return sum([x * y for (x, y) in zip(values, TIME_ESTIMATION_COEF)])
Пример #2
0
    def estimate_time_to_position(self, x, y, tank):
        dist = tank.get_distance_to(x, y)
        vt = Vector(tank.speedX, tank.speedY)

        tank_v = Vector(tank.x, tank.y)
        pt_v = Vector(x, y)
        d = pt_v - tank_v

        if d.is_zero():
            return 0

        tank_d_v = Vector(1, 0).rotate(tank.angle)

        if vt.is_zero() or d.is_zero():
            vd_angle = 0
        else:
            vd_angle = vt.angle(d)

        if tank_d_v.is_zero() or d.is_zero():
            d_angle = 0
        else:
            d_angle = tank_d_v.angle(d)

        # Short distances fix
        if dist < 100:
            if fabs(d_angle) < LOW_ANGLE:
                v0 = vt.projection(d)
                return solve_quadratic(FICTIVE_ACCELERATION / 2, v0, -dist)
                #return dist/6
            elif PI - fabs(d_angle) < LOW_ANGLE:
                v0 = vt.projection(d)
                return solve_quadratic(FICTIVE_ACCELERATION / 2 * 0.75, v0,
                                       -dist)
                #return dist/6 /0.75

        if d.is_zero():
            values = (0, 0, 0, 0, 0, 0, 0, 1)
        else:

            values = (d_angle, dist, vd_angle, vt.length(), tank.angular_speed,
                      tank.crew_health / tank.crew_max_health, d_angle**2, 1)

        return sum([x * y for (x, y) in zip(values, TIME_ESTIMATION_COEF)])
Пример #3
0
    def value(self, target):
        tank = self.context.tank

        tank_v = Vector(tank.x, tank.y)
        target_v = Vector(target.x, target.y)

        #b = tank.angle + tank.turret_relative_angle
        b = (target_v - tank_v).angle(Vector(1, 0))

        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):
            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()

        v0 = target_speed.projection(target_direction)
        target_health_fraction = target.crew_health / target.crew_max_health
        efficency = (1 + target_health_fraction) / 2

        target_avoid_distance_forward = max_move_distance(
            v0, FICTIVE_TARGET_ACCELERATION * efficency,
            MAX_TARGET_SPEED * efficency, t)
        target_avoid_distance_backward = max_move_distance(
            v0, -FICTIVE_TARGET_ACCELERATION * 0.75 * efficency,
            MAX_TARGET_SPEED * efficency, t)

        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)

        return (1 - var / 200) * self.max_value
Пример #4
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)
Пример #5
0
def get_target_data(context):
    # New Decision Maker
    tank = context.tank
    target = context.cur_target
    physics = context.physics

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

    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)

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

    v0 = target_speed.projection(target_direction)
    target_health_fraction = target.crew_health/target.crew_max_health
    efficency = (1 + target_health_fraction)/2

    target_avoid_distance_forward = physics.max_move_distance(v0, FICTIVE_TARGET_ACCELERATION * efficency, MAX_TARGET_SPEED * efficency, t)
    target_avoid_distance_backward = physics.max_move_distance(v0, -FICTIVE_TARGET_ACCELERATION * BACKWARDS_FICTIVE_MULTIPLIER * efficency, MAX_TARGET_SPEED * efficency, 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)

    allies_targeting = inverse_dict(context.memory.target_id, target.id)

    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)

    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)

    context.memory.good_to_shoot[tank.id] = False

    try_single = single_attacker()
    if len(allies_targeting) == 2 and try_single[1] == False:

        if tank.id in allies_targeting:
            attackers = []
            for t in context.world.tanks:
                if t.id in allies_targeting:
                    attackers.append(t)
            if all([lambda a: a.remaining_reloading_time < 70 or a.reloading_time - a.remaining_reloading_time < MULTIPLE_MAX_TIME_DIFFERENCE, attackers]):
                try_multiple = multiple_attackers(attackers)
                if try_multiple[1]:
                    if tank.remaining_reloading_time < 3:
                        context.memory.good_to_shoot[tank.id] = True
                    ok = all([context.memory.good_to_shoot.get(t.id) for t in attackers])
                    if not ok:
                        try_multiple = (try_multiple[0], False)

                return try_multiple
    return try_single
Пример #6
0
def get_target_data(context):
    # New Decision Maker
    tank = context.tank
    target = context.cur_target
    physics = context.physics

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

    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)

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

    v0 = target_speed.projection(target_direction)
    target_health_fraction = target.crew_health / target.crew_max_health
    efficency = (1 + target_health_fraction) / 2

    target_avoid_distance_forward = physics.max_move_distance(
        v0, FICTIVE_TARGET_ACCELERATION * efficency,
        MAX_TARGET_SPEED * efficency, t)
    target_avoid_distance_backward = physics.max_move_distance(
        v0, -FICTIVE_TARGET_ACCELERATION * BACKWARDS_FICTIVE_MULTIPLIER *
        efficency, MAX_TARGET_SPEED * efficency, 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)

    allies_targeting = inverse_dict(context.memory.target_id, target.id)

    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)

    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)

    context.memory.good_to_shoot[tank.id] = False

    try_single = single_attacker()
    if len(allies_targeting) == 2 and try_single[1] == False:

        if tank.id in allies_targeting:
            attackers = []
            for t in context.world.tanks:
                if t.id in allies_targeting:
                    attackers.append(t)
            if all([
                    lambda a: a.remaining_reloading_time < 70 or a.
                    reloading_time - a.remaining_reloading_time <
                    MULTIPLE_MAX_TIME_DIFFERENCE, attackers
            ]):
                try_multiple = multiple_attackers(attackers)
                if try_multiple[1]:
                    if tank.remaining_reloading_time < 3:
                        context.memory.good_to_shoot[tank.id] = True
                    ok = all([
                        context.memory.good_to_shoot.get(t.id)
                        for t in attackers
                    ])
                    if not ok:
                        try_multiple = (try_multiple[0], False)

                return try_multiple
    return try_single