Beispiel #1
0
 def move_by_tiles_to(me: Wizard, world: World, game: Game, move: Move, x: float, y: float) -> Tuple[float, float]:
     # We're already there?
     if me.get_distance_to(x, y) < 1.0:
         # Reached the destination.
         return x, y
     if me.get_distance_to(x, y) < DIRECT_MOVE_DISTANCE:
         # We can just move there.
         MyStrategy.move_to(me, world, game, move, x, y)
         return x, y
     # Find the nearest tile.
     my_index, (my_tile_x, my_tile_y) = min(enumerate(KEY_TILES), key=(lambda tile: me.get_distance_to(*tile[1])))
     if not MyStrategy.is_in_tile(my_tile_x, my_tile_y, me.x, me.y):
         # We're away. Go to this tile.
         MyStrategy.move_to(me, world, game, move, my_tile_x, my_tile_y)
         return my_tile_x, my_tile_y
     # Find the destination tile.
     destination_index = next(
         i for i, (tile_x, tile_y) in enumerate(KEY_TILES)
         if MyStrategy.is_in_tile(tile_x, tile_y, x, y)
     )
     # Find route between tiles.
     bfs_queue = [destination_index]
     bfs_visited = {destination_index}
     while bfs_queue:
         current_index = bfs_queue.pop(0)
         for previous_index in KEY_ADJACENT[current_index]:
             if previous_index == my_index:
                 move_x, move_y = KEY_TILES[current_index]
                 MyStrategy.move_to(me, world, game, move, move_x, move_y)
                 return move_x, move_y
             if previous_index not in bfs_visited:
                 bfs_queue.append(previous_index)
                 bfs_visited.add(current_index)
     print("Failed to find route from %s, %s to %s, %s" % (me.x, me.y, x, y))
     return x, y
Beispiel #2
0
    def calculateCurrentLane(self, wiz: Wizard):
        distances_to_lanes = [  min( self.ways[LaneType.TOP][1:6], key=lambda x: wiz.get_distance_to_unit(x) ),
                                min( self.ways[LaneType.MIDDLE][1:6], key=lambda x: wiz.get_distance_to_unit(x) ),
                                min( self.ways[LaneType.BOTTOM][1:6], key=lambda x: wiz.get_distance_to_unit(x) ) ]

        lane_index = distances_to_lanes.index(min( distances_to_lanes, key=lambda x: wiz.get_distance_to_unit(x) ))
        return lane_index
Beispiel #3
0
 def is_oriented_to_unit(me: Wizard, game: Game, unit: CircularUnit) -> (bool, float):
     angle_to_unit = me.get_angle_to_unit(unit)
     cast_angle = abs(angle_to_unit) - math.atan(unit.radius / me.get_distance_to_unit(unit))
     if cast_angle < 0.0:
         # We can attack.
         return True, 0.0
     # Attack with some cast angle.
     if cast_angle < game.staff_sector / 2.0:
         # Cast angle has the same sign as turn angle.
         return True, math.copysign(cast_angle, angle_to_unit)
     # :(
     return False, None
Beispiel #4
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        # First, initialize some common things.
        attack_faction = self.get_attack_faction(me.faction)
        skills = set(me.skills)

        # Learn some skill.
        move.skill_to_learn = self.skill_to_learn(skills)
        # Apply some skill.
        move.status_target_id = me.id

        # Bonus pick up.
        bonus_tick_index = world.tick_index % 2500
        if self.pick_up_bonus is None and (me.x > 1600.0 or me.y < 2400.0) and bonus_tick_index >= 2000:
            self.pick_up_bonus = min(BONUSES, key=(lambda bonus: me.get_distance_to(*bonus)))
        if me.x < 400.0 and me.y > 3600.0:
            self.pick_up_bonus = None
        if self.pick_up_bonus is not None:
            x, y = self.pick_up_bonus
            if not MyStrategy.attack_nearest_enemy(me, world, game, move, skills, attack_faction):
                move.turn = me.get_angle_to(x, y)
            if bonus_tick_index >= 2000 and me.get_distance_to(x, y) < me.radius + 2.0 * game.bonus_radius:
                # Bonus hasn't appeared yet. Stay nearby.
                return
            if 0 < bonus_tick_index < 2000 and (
                # Bonus has just been picked up.
                me.get_distance_to(x, y) < me.radius or
                # No bonus there.
                (me.get_distance_to(x, y) < me.vision_range and not world.bonuses)
            ):
                self.pick_up_bonus = None
            else:
                self.move_by_tiles_to(me, world, game, move, x, y)
            return

        # Check if I'm healthy.
        if self.is_in_danger(me, world, game, me.x, me.y, attack_faction):
            # Retreat to the nearest safe tile.
            x, y = min((
                (x, y)
                for x, y in KEY_TILES
                if not self.is_in_danger(me, world, game, x, y, attack_faction)
            ), key=(lambda point: me.get_distance_to(*point)))
            self.move_by_tiles_to(me, world, game, move, x, y)
            MyStrategy.attack_nearest_enemy(me, world, game, move, skills, attack_faction)
            return

        # Else try to attack the best target.
        if MyStrategy.attack_best_target(me, world, game, move, skills, attack_faction):
            return

        # Quick and dirty fix to avoid being stuck near the base.
        if me.x < 400.0 and me.y > 3600.0:
            move.turn = me.get_angle_to(*self.move_by_tiles_to(me, world, game, move, 200.0, 200.0))
            return

        # Nothing to do. Just go to enemy base.
        x, y = self.move_by_tiles_to(me, world, game, move, ATTACK_BASE_X, ATTACK_BASE_Y)
        move.turn = me.get_angle_to(x, y)
def get_nearest_target(me: Wizard, world: World):
    """
    Находим ближайшую цель для атаки, независимо от её типа и других характеристик.
    """
    targets = []
    targets.extend(world.buildings)
    targets.extend(world.wizards)
    targets.extend(world.minions)

    nearest_target = None
    nearest_target_distance = 1.5 * me.vision_range

    for target in targets:
        # Нейтралов атакуем тоже если их хп меньше максимального - они стригеренны
        # if (target.faction == Faction.NEUTRAL and target.life == target.max_life) or \
        #          (target.faction == me.faction):
        if not is_enemy(target, me):
            continue

        distance = me.get_distance_to_unit(target)
        if distance < nearest_target_distance:
            nearest_target = target
            nearest_target_distance = distance

    return nearest_target
Beispiel #6
0
    def attack_best_target(me: Wizard, world: World, game: Game, move: Move, skills: Set, attack_faction):
        targets = [
            unit
            for unit in world.wizards
            if unit.faction == attack_faction and me.get_distance_to_unit(unit) < me.vision_range
        ]
        if targets:
            # Try to attack the weakest wizard.
            target = min(targets, key=(lambda unit: unit.life))
            if MyStrategy.attack(me, game, move, skills, target, True):
                return True
            # Try to attack the nearest wizard.
            target = min(targets, key=(lambda unit: me.get_distance_to_unit(unit)))
            if MyStrategy.attack(me, game, move, skills, target, True):
                return True
            # Chase for it.
            MyStrategy.move_to(me, world, game, move, target.x, target.y)
            return True

        # Else try to attack an enemy building.
        targets = [
            unit
            for unit in world.buildings
            if unit.faction == attack_faction and me.get_distance_to_unit(unit) < me.vision_range
        ]
        if targets:
            target = min(targets, key=(lambda unit: me.get_distance_to_unit(unit)))
            if MyStrategy.attack(me, game, move, skills, target, True):
                return True
            # Move closer to the building.
            MyStrategy.move_to(me, world, game, move, target.x, target.y)
            return True

        # Else try to attack an enemy minion.
        targets = [
            unit
            for unit in world.minions
            if unit.faction == attack_faction and me.get_distance_to_unit(unit) < me.cast_range
        ]
        if targets:
            target = min(targets, key=(lambda unit: unit.life))
            if MyStrategy.attack(me, game, move, skills, target, False):
                return True

        # Couldn't attack anyone.
        return False
def apply_go_to_move(point: Point2D, me: Wizard, game: Game, move: Move):
    """
    Простейший способ перемещения волшебника.
    """
    angle = me.get_angle_to(point.x, point.y)
    move.turn = angle

    if math.fabs(angle) < game.staff_sector / 4.0:
        move.speed = game.wizard_forward_speed
    def _find_problem_units(self, me: Wizard, reverse=False):
        def is_problem_unit(angle, reverse, problem_sector):
            if reverse:
                return fabs(angle) > radians(180) - problem_sector
            else:
                return fabs(angle) < problem_sector

        units = self.W.buildings + self.W.wizards + self.W.minions + self.W.trees
        connected_u = [
            t for t in units
            if me.get_distance_to_unit(t) <= (me.radius + t.radius) *
            1.05 and me.id != t.id
        ]
        problem_u = [
            t for t in connected_u if is_problem_unit(me.get_angle_to_unit(
                t), reverse, self.PROBLEM_ANGLE)
        ]
        return None if not problem_u else problem_u[0]
Beispiel #9
0
 def attack_nearest_enemy(me: Wizard, world: World, game: Game, move: Move, skills: Set, attack_faction):
     targets = sorted((
         unit
         for unit in itertools.chain(world.wizards, world.minions, world.buildings)
         if unit.faction == attack_faction
     ), key=(lambda unit: me.get_distance_to_unit(unit)))
     for target in targets:
         if MyStrategy.attack(me, game, move, skills, target, not isinstance(target, Minion)):
             return True
     return False
Beispiel #10
0
    def read_wizard(self):
        if not self.read_boolean():
            return None

        return Wizard(
            self.read_long(), self.read_double(), self.read_double(), self.read_double(), self.read_double(),
            self.read_double(), self.read_enum(Faction), self.read_double(), self.read_int(), self.read_int(),
            self.read_statuses(), self.read_long(), self.read_boolean(), self.read_int(), self.read_int(),
            self.read_double(), self.read_double(), self.read_int(), self.read_int(), self.read_enums(SkillType),
            self.read_int(), self.read_ints(), self.read_boolean(), self.read_messages()
        )
Beispiel #11
0
    def _goto_forward(self, me: Wizard):
        coords_tuple = self._get_next_waypoint(me)
        problem_unit = self._find_problem_units(me)
        if problem_unit:
            angle_to_connected_unit = me.get_angle_to_unit(problem_unit)
            self.log('found connected unit %s (%.4f angle)' %
                     (problem_unit.id, angle_to_connected_unit))
            if angle_to_connected_unit >= 0:
                self.log('run left')
                self.MOVE_STRAFE_SPEED = -1 * self.G.wizard_strafe_speed
            else:
                self.log('run right')
                self.MOVE_STRAFE_SPEED = self.G.wizard_strafe_speed
        else:
            turn_only = False
            if coords_tuple is None:
                turn_only = True
                coords_tuple = (self.ENEMY_BASE.x, self.ENEMY_BASE.y)
            angle = me.get_angle_to(*coords_tuple)
            self.MOVE_TURN = angle

            if fabs(angle) < self.STAFF_SECTOR / 4.0 and not turn_only:
                self.MOVE_SPEED = self.MAX_SPEED
Beispiel #12
0
 def attack(me: Wizard, game: Game, move: Move, skills: Set, unit: LivingUnit, allow_fireball: bool):
     action_type, min_cast_distance = MyStrategy.get_action(me, game, skills, unit, allow_fireball)
     if action_type == ActionType.NONE:
         return False
     # We can cast something.
     is_oriented, cast_angle = MyStrategy.is_oriented_to_unit(me, game, unit)
     if is_oriented:
         # Attack!
         move.cast_angle = cast_angle
         move.action = action_type
         move.min_cast_distance = min_cast_distance
         return True
     # Turn around to the enemy.
     move.turn = me.get_angle_to_unit(unit)
     return True
Beispiel #13
0
 def _goto_backward(self, me: Wizard):
     coords_tuple = self._get_prev_waypoint(me)
     problem_unit = self._find_problem_units(me, True)
     if problem_unit:
         angle_to_connected_unit = me.get_angle_to_unit(problem_unit)
         self.log('backward angle %.4f' % angle_to_connected_unit)
         self.log('found connected unit %s (%.4f angle)' %
                  (problem_unit.id, angle_to_connected_unit))
         if angle_to_connected_unit > 0:
             self.log('run right')
             self.MOVE_STRAFE_SPEED = -1 * self.G.wizard_strafe_speed
         else:
             self.log('run left')
             self.MOVE_STRAFE_SPEED = self.G.wizard_strafe_speed
     else:
         angle = me.get_angle_to(*coords_tuple)
         angle_reverse = radians(180) - fabs(angle)
         if angle > 0:
             angle_reverse *= -1
         self.log('backward angle %.4f %.4f' % (angle, angle_reverse))
         self.log('backward angle staff %.4f' % self.STAFF_SECTOR)
         self.MOVE_TURN = angle_reverse
         if fabs(angle_reverse) < self.STAFF_SECTOR / 4.0:
             self.MOVE_SPEED = -1 * self.MAX_SPEED
def get_nearest_neutral(me: Wizard, world: World):
    targets = []
    targets.extend(world.trees)
    targets.extend(world.minions)

    nearest_neutral = None
    nearest_neutral_distance = me.cast_range

    for target in targets:
        if is_neutral(target):
            distance = me.get_distance_to_unit(target)
            if distance < nearest_neutral_distance:
                nearest_neutral = target
                nearest_neutral_distance = distance

    return nearest_neutral
Beispiel #15
0
 def get_action(me: Wizard, game: Game, skills: Set[SkillType], unit: LivingUnit, allow_fireball: bool) -> (ActionType, float):
     distance_to_unit = me.get_distance_to_unit(unit)
     min_cast_distance = distance_to_unit - unit.radius
     if distance_to_unit < game.staff_range:
         return ActionType.STAFF, min_cast_distance
     if distance_to_unit > me.cast_range:
         return ActionType.NONE, min_cast_distance
     if (
         # FIXME: StatusType.BURNING not in unit.statuses and
         SkillType.FIREBALL in skills and
         allow_fireball and
         me.mana > game.fireball_manacost and
         distance_to_unit > game.fireball_explosion_max_damage_range + me.radius
     ):
         return ActionType.FIREBALL, min_cast_distance
     if (
         # FIXME: StatusType.FROZEN not in unit.statuses and
         SkillType.FROST_BOLT in skills and
         me.mana > game.frost_bolt_manacost
     ):
         return ActionType.FROST_BOLT, min_cast_distance
     if me.mana > game.magic_missile_manacost:
         return ActionType.MAGIC_MISSILE, min_cast_distance
     return ActionType.NONE, min_cast_distance
Beispiel #16
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        self.log('TICK %s' % world.tick_index)
        self._init(game, me, world, move)
        self.log('me %s %s %f' %
                 (me.x, me.y, me.get_distance_to(*self.INIT_POINT)))

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

        # select lane
        self._select_lane(me)

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

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

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

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

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

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

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

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

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

        if self.MOVE_TURN is not None:
            move.turn = self.MOVE_TURN
            self.MOVE_TURN = None
        if self.MOVE_SPEED is not None:
            move.speed = self.MOVE_SPEED
            self.MOVE_SPEED = None
        if self.MOVE_STRAFE_SPEED is not None:
            move.strafe_speed = self.MOVE_STRAFE_SPEED
            self.MOVE_STRAFE_SPEED = None
Beispiel #17
0
 def _goto_enemy(self, me: Wizard, e: LivingUnit):
     angle = me.get_angle_to_unit(e)
     self.log('enemy angle for projectile care is %.2f' % angle)
     if fabs(angle) < self.STAFF_SECTOR / 4.0:
         self.MOVE_TURN = angle
         self.MOVE_SPEED = self.MAX_SPEED
Beispiel #18
0
 def _sort_by_angle(me: Wizard, el: list):
     return sorted(el, key=lambda u: fabs(me.get_angle_to_unit(u)))
Beispiel #19
0
 def _enemy_in_staff_distance(self, me: Wizard, e):
     return me.get_distance_to_unit(e) <= (self.G.staff_range + e.radius)
Beispiel #20
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        self.initTick( me, world, game, move )
        self.debugFeatures();

        if self.state == PlayerState.CHECK_BONUSES:
            if not self.walk_reached:
                if self.bonus_index != -1 and self.target_waypoint != self.center_point:
                    
                    if self.isVisible(self.target_waypoint, game.bonus_radius) and (world.tick_index > self.check_time + self.bonus_predict_time):
                        print( 'I can see bonus!' )
                        target_bonus = list( filter( lambda x: self.target_waypoint.x == x.x and self.target_waypoint.y == x.y, world.bonuses ) )
                        if not target_bonus:
                            if self.bonus_index == 0:
                                self.bonus_index = 1
                                self.target_waypoint = self.bonus_points[self.bonus_index]
                            else:
                                self.target_waypoint = self.center_point

                if me.get_distance_to_unit(self.target_waypoint) < (self.wp_radius * 2 if self.target_waypoint == self.center_point \
                                                                                        else game.bonus_radius + me.radius):
                    print( 'Reached' )
                    if self.target_waypoint in self.bonus_points:
                        print( 'Go to center' )
                        self.target_waypoint = self.center_point
                    else:
                        self.walk_reached = True
                else:
                    self.goToWaypointWithAttackNear( self.target_waypoint )
            else:
                if self.bonus_index == -1:
                    if self.current_lane == LaneType.MIDDLE or self.current_lane == LaneType.TOP:
                        self.bonus_index = 0
                    else:
                        self.bonus_index = 1
                    self.target_waypoint = self.bonus_points[self.bonus_index]
                    self.walk_reached = False
                    
                elif self.bonus_index == 0:
                    self.bonus_index = 1
                    if self.current_lane == LaneType.MIDDLE:
                        self.target_waypoint = self.bonus_points[self.bonus_index]
                        self.walk_reached = False
                else:
                    self.state = PlayerState.WALK_FORWARD
                    if self.isEnemyInRange(game.wizard_vision_range):
                        self.state = PlayerState.BATTLE
                        print('Found enemy!')
                        return

        if self.state == PlayerState.WALK_TO_BASE:
            if not self.walk_reached:
                if me.get_distance_to_unit(self.target_waypoint) < self.wp_radius:
                    self.walk_reached = True
                    if self.target_waypoint != self.base_point:
                        self.target_waypoint = self.getPreviousWP()
                        self.walk_reached = False
                else:
                    self.goToWaypointWithAttackNear( self.target_waypoint )
                    if self.target_waypoint == self.base_point and self.isEnemyInRange( game.wizard_vision_range * 1.5 ):
                        self.state = PlayerState.BATTLE
                        print('Found enemy!')
                        return
            else:
                if self.change_lane:
                    self.setLane( (self.current_lane + 1) % 3 )
                    self.change_lane = False

                self.state = PlayerState.WALK_FORWARD

            return
        
        if self.state == PlayerState.WALK_FORWARD:

            next_wp = self.getNextWP()

            self.goToWaypointWithAttackNear( next_wp )
            
            self.checkReachedLastWP()
            self.checkBaseUnderAttack()
            self.checkBonuses()

            if self.isEnemyInRange( game.wizard_vision_range * 1.5 ):
                self.state = PlayerState.BATTLE
                print('Found enemy!')
                return

            near_friendly = []
            near_friendly.extend( self.friendly_wizards )
            near_friendly.extend( self.friendly_minions )
            near_friendly = list(filter( lambda x: x.get_distance_to_unit(next_wp) < me.get_distance_to_unit(next_wp), near_friendly))

            if world.tick_index < 1500:
                if next_wp == self.center_point and me.get_distance_to_unit( next_wp ) < 600 and len( near_friendly ) < 2:
                    move.speed = 0
                    move.strafe_speed = 0

            return

        if self.state == PlayerState.BATTLE:

            self.checkReachedLastWP()
            self.checkBaseUnderAttack()
            self.checkBonuses()

            if self.isNearBase():
                lane = self.calculateCurrentLane( me )
                self.setLane( lane )

            if not self.isEnemyInRange( game.wizard_vision_range * 1.5 ):
                self.state = PlayerState.WALK_FORWARD
                return

            target = self.getNearestEnemy()

            near_weak_enemies = list( filter( lambda x: self.isTargetInCastRange(x) and \
                                                        x.life <= game.magic_missile_direct_damage * 2, self.enemy_units ) )
            
            enemy_minions_in_attack_range = \
                list( filter( lambda x: x.faction != me.faction and x.faction != Faction.NEUTRAL and \
                                        x.get_distance_to_unit( me ) <= \
                                        (game.orc_woodcutter_attack_range if x.type == MinionType.ORC_WOODCUTTER \
                                            else game.fetish_blowdart_attack_range) + x.radius + me.radius, world.minions ) )

            enemy_wizards_on_target = \
                list( filter( lambda x: x.get_distance_to_unit( me ) <= game.wizard_vision_range and \
                                        abs(x.get_angle_to_unit( me )) < (game.staff_sector / 2.), self.enemy_wizards ) )

            enemies_in_staff_range = list( filter( lambda x: self.isTargetInStaffRange(x), self.enemy_units ) )
            enemy_wizards_in_cast_range = list( filter( lambda x: self.isTargetInCastRange(x), self.enemy_wizards ) )
            enemies_in_cast_range = list( filter( lambda x: self.isTargetInCastRange(x), self.enemy_units ) )

            # if self.enemy_wizards and not enemy_minions_in_attack_range:
            #     nearest_enemy_wizard = min( self.enemy_wizards, key=lambda x: me.get_distance_to_unit( x ) )
            #     if me.get_distance_to_unit( nearest_enemy_wizard ) <= game.wizard_vision_range:
            #         target = nearest_enemy_wizard

            # if near_weak_enemies and not enemy_minions_in_attack_range:
            #     enemy_wizards_in_attack_range = \
            #         list( filter( lambda x: x.get_distance_to_unit( me ) < game.wizard_cast_range + me.radius and \
            #                                 x != near_weak_enemies[0], self.enemy_wizards ) )
            #     if not enemy_wizards_in_attack_range:
            #         target = near_weak_enemies[0]

            # self.attackTarget( target )

            if self.isHealthLow(0.4):
                self.keepDistanceToUnit( self.getNearestEnemy(), game.wizard_vision_range )
                if enemy_wizards_in_cast_range:
                    nearest_wiz = min( enemy_wizards_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest_wiz )
                elif enemies_in_cast_range:
                    nearest = min( enemies_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest )

            elif len(enemy_wizards_on_target) > 2:
                nearest_wiz = min( enemy_wizards_on_target, key=lambda x: me.get_distance_to_unit(x) )
                self.stepBackFromUnit( nearest_wiz, game.wizard_cast_range + (me.radius + target.radius) )
                if enemy_wizards_in_cast_range:
                    nearest_wiz = min( enemy_wizards_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest_wiz )
                elif enemies_in_cast_range:
                    nearest = min( enemies_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest )

            elif len(enemy_minions_in_attack_range) >= 2:
                nearest = min( enemy_minions_in_attack_range, key=lambda x: me.get_distance_to_unit(x) )
                self.stepBackFromUnit( nearest, (game.orc_woodcutter_attack_range if nearest.type == MinionType.ORC_WOODCUTTER \
                                                else game.fetish_blowdart_attack_range) + nearest.radius + me.radius )
                if enemy_wizards_in_cast_range:
                    nearest_wiz = min( enemy_wizards_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest_wiz )
                elif enemies_in_cast_range:
                    nearest = min( enemies_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                    self.attackTarget( nearest )

            elif not enemies_in_cast_range:
                nearest = self.getNearestEnemy()
                self.goForwardToUnit( nearest, game.wizard_cast_range - (me.radius + target.radius) )
                self.attackTarget( nearest )

            else:
                if self.isMagicMissileReady():
                    if enemy_wizards_in_cast_range:
                        nearest_wiz = min( enemy_wizards_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                        self.goForwardToUnit( nearest_wiz, game.wizard_cast_range - (me.radius + target.radius) )
                        self.attackTarget( nearest_wiz )
                    elif enemies_in_cast_range:
                        nearest = min( enemies_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                        if not self.isHealthLow(0.6):
                            self.goForwardToUnit( nearest, game.staff_range + (me.radius + target.radius) )
                        self.attackTarget( nearest )
                else:
                    if len(enemy_wizards_on_target) > 0:
                        nearest_wiz = min( enemy_wizards_on_target, key=lambda x: me.get_distance_to_unit(x) )
                        self.stepBackFromUnit( nearest_wiz, game.wizard_cast_range + (me.radius + target.radius) )
                    elif enemies_in_staff_range:
                        nearest = min( enemies_in_staff_range, key=lambda x: me.get_distance_to_unit(x) )
                        self.attackTarget( nearest )
                    elif enemies_in_cast_range:
                        nearest = min( enemies_in_cast_range, key=lambda x: me.get_distance_to_unit(x) )
                        if not self.isHealthLow(0.6):
                            self.goForwardToUnit( nearest, game.staff_range + (me.radius) )
                        self.attackTarget( nearest )

            safe_tower_distance = game.guardian_tower_attack_range + me.radius * 2 + game.guardian_tower_radius
            near_enemy_tower = next((x for x in world.buildings if me.get_distance_to_unit( x ) <= safe_tower_distance and x.faction != me.faction), None)
            
            if near_enemy_tower:
                if near_enemy_tower.life > near_enemy_tower.max_life * 0.25:
                    if me.life > near_enemy_tower.damage:
                        friend_minions_near_tower = list( filter( lambda x: near_enemy_tower.get_distance_to_unit( me ) > near_enemy_tower.get_distance_to_unit( x ), self.friendly_minions ) )
                        if len( friend_minions_near_tower ) < 2 and near_enemy_tower.remaining_action_cooldown_ticks < 150:
                            self.stepBackFromUnit( near_enemy_tower, safe_tower_distance )
                    else:
                        if near_enemy_tower.remaining_action_cooldown_ticks < 200:
                            self.stepBackFromUnit( near_enemy_tower, safe_tower_distance )
            return
Beispiel #21
0
 def _cast_distance(self, me: Wizard, e: LivingUnit):
     projectile_radius = self.G.magic_missile_radius
     return me.get_distance_to_unit(e) - e.radius - projectile_radius
Beispiel #22
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        if self.debug:
            self.debug.syncronize(world)

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

        self.initialize_tick(me, world, game)

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

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

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

        if common_score < score_threshold:
            previous_waypoint = Points2D.get_previous_waypoint(
                self.waypoints, me)
            self.map.note_enemy_angle = False
            self.go_to(move, previous_waypoint, note_angle=False)
            self.last_actions[world.tick_index %
                              STOP_CHECK_TICK_COUNT] = Action.BACK
            return
        else:
            nearest_target = Points2D.get_nearest_target(me, world)
            if nearest_target is not None:
                distance = me.get_distance_to_unit(nearest_target)
                angle = me.get_angle_to_unit(nearest_target)
                if distance <= me.cast_range:
                    self.go_to(move, None, note_angle=False)
                    if abs(angle) < game.staff_sector / 2.0:
                        move.action = ActionType.MAGIC_MISSILE
                        move.cast_angle = angle
                        move.min_cast_distance = distance - nearest_target.radius + game.magic_missile_radius
                    self.last_actions[world.tick_index %
                                      STOP_CHECK_TICK_COUNT] = Action.ENEMY
                    return
                else:
                    min_attack_dist = min_atack_distance(me) * self.life_coef
                    new_x = me.x + (nearest_target.x - me.x) / distance * (
                        distance - min_attack_dist)
                    new_y = me.y + (nearest_target.y - me.y) / distance * (
                        distance - min_attack_dist)
                    self.go_to(move, Point2D(new_x, new_y), note_angle=True)
                    self.last_actions[world.tick_index %
                                      STOP_CHECK_TICK_COUNT] = Action.NEXT
                    return
            else:
                next_waypoint = Points2D.get_next_waypoint(self.waypoints, me)
                note_angle = True
                if world.tick_index > STOP_CHECK_TICK_COUNT:
                    last_pos_index = (world.tick_index +
                                      1) % STOP_CHECK_TICK_COUNT
                    dist_last_poses = me.get_distance_to_unit(
                        self.last_poses[last_pos_index])
                    # если далеко не ушел и если последние все действия NEXT
                    if ((dist_last_poses < STOP_CHECK_TICK_COUNT * 0.2 *
                         game.wizard_forward_speed) and
                        (sum([x == Action.NEXT for x in self.last_actions])
                         == STOP_CHECK_TICK_COUNT)):
                        note_angle = False
                        self.map.neutral_coef = 1000 * np.random.normal(1, 0.3)
                        self.map.neutral_dist_coef = 1000
                self.go_to(move, next_waypoint, note_angle=note_angle)
                self.last_actions[world.tick_index %
                                  STOP_CHECK_TICK_COUNT] = Action.NEXT
                if world.tick_index < SLOW_MOVE_TICK_COUNT:
                    move.speed *= 0.5
                    move.strafe_speed *= 0.5
                return
Beispiel #23
0
 def _enemy_in_attack_sector(self, me: Wizard, e):
     return fabs(me.get_angle_to_unit(e)) <= self.STAFF_SECTOR / 2.0
Beispiel #24
0
 def _near_waypoint(me: Wizard, wp_coords):
     return me.get_distance_to(*wp_coords) < me.radius * 2