コード例 #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 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 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)])
コード例 #4
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)
コード例 #5
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
コード例 #6
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
コード例 #7
0
    def _make_turn(self, tank, world, move):
        # Precalc for estimation
        self.enemies = list(filter(ALIVE_ENEMY_TANK, world.tanks))
        self.allies = list(filter(ALLY_TANK(tank.id), world.tanks))
        self.health_fraction = tank.crew_health / tank.crew_max_health
        self.hull_fraction = tank.hull_durability / tank.hull_max_durability
        self.enemies_count = len(self.enemies)
        self.est_time_cache = {}

        positions = []
        for pg in self.position_getters:
            positions += pg.positions(tank, world)
        self.debug('Got %d positions' % len(positions))
        if not positions:
            return

        for e in self.position_estimators:
            e.context = self
        pos_and_values = [(pos, sum([e.value(pos) for e in self.position_estimators]))
                          for pos in positions]

        if self.debug_mode:
            top_pos = [item[0] for item in list(reversed(sorted(pos_and_values, key=operator.itemgetter(1))))[:6]]

            self.debug(' ' * 50, end='')
            for e in self.position_estimators:
                self.debug('%14s' % e.NAME, end='')
            self.debug('%14s' % 'RESULT', end='')
            self.debug('')

            def out_pos(pos):
                self.debug('%-50s' % (str(pos) + ' : '), end='')
                res = 0
                for e in self.position_estimators:
                    v = e.value(pos)
                    self.debug('%14.2f' % v, end='')
                    res += v
                self.debug('%14.2f' % res, end='')
                self.debug('')

            for pos in top_pos:
                out_pos(pos)
            self.debug('=' * 16)
            for pos in positions:
                if pos.name.find('BONUS') != -1:
                    out_pos(pos)
            self.debug('=' * 16)
            for pos in positions:
                if pos.name == 'FORWARD' or pos.name == 'BACKWARD' or pos.name == 'CURRENT':
                    out_pos(pos)

            self.debug('=' * 16)
            for pos in positions:
                if pos.name.find('BORDER') != -1:
                    out_pos(pos)


        next_position = None

        position_iteration = 0
        #average_F = sum([pos[0] for pos in pos_f])/len(pos_f)
        pos_queue = PriorityQueue()
        for p_v in pos_and_values:
            pos_queue.put( (-p_v[1] + random() * 1e-3, p_v[0]) )

        while True:
            cur = pos_queue.get()[1]
            if not self.physics.position_is_blocked(cur.x, cur.y, tank, world) or position_iteration >= MAX_POSITION_ITERATIONS:
                next_position = cur
                break
            position_iteration += 1
            self.debug('!!! Skipping best position, iteration %d' % position_iteration)
            if self.debug_mode:
                self.debug('(blocked by %s)' % str(self.physics.position_is_blocked(cur.x, cur.y, tank, world)))

        self.debug("GOING TO [%10s] (%8.2f, %8.2f); distance=%8.2f, ETA=%8.2f" %
                   (next_position.name, next_position.x, next_position.y,
                    self.tank.get_distance_to(next_position.x, next_position.y), self.physics.estimate_time_to_position(next_position.x, next_position.y, tank))
        )
        self.memory.last_target_position[tank.id] = next_position
        self.physics.move_to_position(next_position.x, next_position.y, tank, move)

        self.debug('=' * 16)
        if self.debug_mode:
            for shell in world.shells:
                v0 = hypot(shell.speedX, shell.speedY)
                a = SHELL_ACCELERATION
                d = tank.get_distance_to_unit(shell)
                tank_v = Vector(tank.x, tank.y)
                shell_v = Vector(shell.x, shell.y)
                shell_speed = Vector(shell.speedX, shell.speedY)
                #d = shell.get_distance_to(x, y)
                t = solve_quadratic(a/2, v0, -d)

                self.debug('SHELL [%12s] (%8.2f, %8.2f) v=%s, will hit=%s, hit time=%8.2f' %
                           (shell.player_name, shell.x, shell.y, shell_speed.length(), str(self.physics.shell_will_hit(shell, tank, factor=1.05)), t) )

            self.debug('=' * 16)
コード例 #8
0
    def _make_turn(self, tank, world, move):
        # Precalc for estimation
        self.enemies = list(filter(ALIVE_ENEMY_TANK, world.tanks))
        self.allies = list(filter(ALLY_TANK(tank.id), world.tanks))
        self.health_fraction = tank.crew_health / tank.crew_max_health
        self.hull_fraction = tank.hull_durability / tank.hull_max_durability
        self.enemies_count = len(self.enemies)
        self.est_time_cache = {}

        positions = []
        for pg in self.position_getters:
            positions += pg.positions(tank, world)
        self.debug('Got %d positions' % len(positions))
        if not positions:
            return

        for e in self.position_estimators:
            e.context = self
        pos_and_values = [
            (pos, sum([e.value(pos) for e in self.position_estimators]))
            for pos in positions
        ]

        if self.debug_mode:
            top_pos = [
                item[0] for item in list(
                    reversed(sorted(pos_and_values, key=operator.itemgetter(
                        1))))[:6]
            ]

            self.debug(' ' * 50, end='')
            for e in self.position_estimators:
                self.debug('%14s' % e.NAME, end='')
            self.debug('%14s' % 'RESULT', end='')
            self.debug('')

            def out_pos(pos):
                self.debug('%-50s' % (str(pos) + ' : '), end='')
                res = 0
                for e in self.position_estimators:
                    v = e.value(pos)
                    self.debug('%14.2f' % v, end='')
                    res += v
                self.debug('%14.2f' % res, end='')
                self.debug('')

            for pos in top_pos:
                out_pos(pos)
            self.debug('=' * 16)
            for pos in positions:
                if pos.name.find('BONUS') != -1:
                    out_pos(pos)
            self.debug('=' * 16)
            for pos in positions:
                if pos.name == 'FORWARD' or pos.name == 'BACKWARD' or pos.name == 'CURRENT':
                    out_pos(pos)

            self.debug('=' * 16)
            for pos in positions:
                if pos.name.find('BORDER') != -1:
                    out_pos(pos)

        next_position = None

        position_iteration = 0
        #average_F = sum([pos[0] for pos in pos_f])/len(pos_f)
        pos_queue = PriorityQueue()
        for p_v in pos_and_values:
            pos_queue.put((-p_v[1] + random() * 1e-3, p_v[0]))

        while True:
            cur = pos_queue.get()[1]
            if not self.physics.position_is_blocked(
                    cur.x, cur.y, tank,
                    world) or position_iteration >= MAX_POSITION_ITERATIONS:
                next_position = cur
                break
            position_iteration += 1
            self.debug('!!! Skipping best position, iteration %d' %
                       position_iteration)
            if self.debug_mode:
                self.debug('(blocked by %s)' % str(
                    self.physics.position_is_blocked(cur.x, cur.y, tank,
                                                     world)))

        self.debug(
            "GOING TO [%10s] (%8.2f, %8.2f); distance=%8.2f, ETA=%8.2f" %
            (next_position.name, next_position.x, next_position.y,
             self.tank.get_distance_to(next_position.x, next_position.y),
             self.physics.estimate_time_to_position(next_position.x,
                                                    next_position.y, tank)))
        self.memory.last_target_position[tank.id] = next_position
        self.physics.move_to_position(next_position.x, next_position.y, tank,
                                      move)

        self.debug('=' * 16)
        if self.debug_mode:
            for shell in world.shells:
                v0 = hypot(shell.speedX, shell.speedY)
                a = SHELL_ACCELERATION
                d = tank.get_distance_to_unit(shell)
                tank_v = Vector(tank.x, tank.y)
                shell_v = Vector(shell.x, shell.y)
                shell_speed = Vector(shell.speedX, shell.speedY)
                #d = shell.get_distance_to(x, y)
                t = solve_quadratic(a / 2, v0, -d)

                self.debug(
                    'SHELL [%12s] (%8.2f, %8.2f) v=%s, will hit=%s, hit time=%8.2f'
                    %
                    (shell.player_name, shell.x, shell.y, shell_speed.length(),
                     str(self.physics.shell_will_hit(shell, tank,
                                                     factor=1.05)), t))

            self.debug('=' * 16)
コード例 #9
0
 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)
コード例 #10
0
 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)