Ejemplo n.º 1
0
 def move_to(me: Wizard, world: World, game: Game, move: Move, x: float, y: float):
     x, y = MyStrategy.avoid_collisions(me, world, x, y)
     direction_x, direction_y = x - me.x, y - me.y
     # Normalize the destination vector.
     distance = math.sqrt(direction_x * direction_x + direction_y * direction_y)
     if abs(distance) < 1.0:
         return
     direction_x /= distance
     direction_y /= distance
     # Wizard's turn vector.
     turn_x, turn_y = math.cos(me.angle), math.sin(me.angle)
     # Project the destination vector onto the speed vector.
     speed = direction_x * turn_x + direction_y * turn_y
     # Project the destination vector onto the strafe speed vector.
     strafe_speed = direction_x * (-turn_y) + direction_y * turn_x
     # Finally, set up the movement.
     max_speed = 10.0
     if speed > 0.0:
         move.speed = speed * max_speed
         move.strafe_speed = strafe_speed * max_speed
     else:
         move.speed = speed * max_speed
         move.strafe_speed = strafe_speed * max_speed
Ejemplo n.º 2
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        # Every tick, update state first
        state_machine.update_state(me, world, game)

        # Take action for this state
        state_machine.run(me, world, game)

        # Current state
        state = state_machine.get_state()

        # Move
        move.speed = state.forward_speed
        move.strafe_speed = state.strafe_speed
        move.turn = state.turn_angle
        move.action = state.action
Ejemplo n.º 3
0
    def move(self, me: Wizard, world: World, game: Game, move: Move):
        if world.tick_index == 0:
            self.init(me, move, world)
            return
        if world.tick_index < 500 and not me.master:
            if me.messages:
                for m in me.messages:
                    self.lane = m.lane
        if world.tick_index == 500 and self.lane is None:
            self.lane_analysis(world)

        self.last_tick = world.tick_index
        move.speed = 0
        move.strafe_speed = 0
        move.turn = 0
        self.x = me.x
        self.y = me.y
        self.tower_analysis(world)

        if world.tick_index - self.last_tick > 500:  # check death
            self.lane_point_index = 0
            self.stuck_start_tick = None
            self.is_fight = False
            self.lane_analysis(world)

        # Stuck
        if self.check_stuck(world.tick_index):
            self.get_out(move, game)
            self.debug_func(world)  # debug
            print("stuck")
            return

        # Escape
        if self.check_danger(me):
            if self.check_if_enemy_near(world, me, game):
                self.map_master(-1, me)
            else:
                # self.map_master(1, me)
                self.wait_status = True
                return
            self.step_point_x, self.step_point_y = self.find_way(world, me)
            self.go(me, move, game)
            self.debug_func(world)  # debug
            print("escape")
            return

        # Fight
        # TODO: уклонение от вражеских снарядов,
        # TODO: хитрая система отхода с максимзацией получаемого опыта
        # TODO: удар посохом
        # TODO: учёт бонусов на врагах
        # TODO: не всегда стрелять!?
        self.is_fight, enemy, distance_to_closest_minion, tower_near, wizards_amount = self.situation_analysis(
            world, me)
        if self.is_fight:
            self.attack(move, game, me, enemy)
            if (me.life < me.max_life*0.5) or \
                    (distance_to_closest_minion < 200) or \
                    ((type(enemy) is Wizard) and (me.life < enemy.life)) or \
                    (wizards_amount > 1):
                self.map_master(-1, me)
                self.step_point_x, self.step_point_y = self.find_way(world, me)
                self.go_back(me, move, game)
            else:
                if distance_to_closest_minion > 500 - 380 * (me.life /
                                                             me.max_life)**2:
                    if not tower_near and (wizards_amount <= 1) and (
                            type(enemy) is not MinionType.FETISH_BLOWDART):
                        self.target_point_x, self.target_point_y = enemy.x, enemy.y
                        self.step_point_x, self.step_point_y = self.find_way(
                            world, me)
                        self.go(me, move, game)
            self.debug_func(world)  # debug
            print("fight")
            return

        # GO
        if world.tick_index < 1500 - int(
                self.lane == LaneType.MIDDLE) * 250:  # wait for minions
            if me.y < 450 + me.x:
                self.map_master(-1, me)
            else:
                self.map_master(1, me)
        else:
            self.map_master(1, me)
        self.step_point_x, self.step_point_y = self.find_way(world, me)
        self.go(me, move, game)
        self.debug_func(world)  # debug
        print("GO")
Ejemplo n.º 4
0
 def move(self, me: Wizard, world: World, game: Game, move: Move):
     move.speed = game.wizard_forward_speed
     move.strafe_speed = game.wizard_strafe_speed
     move.turn = game.wizard_max_turn_angle
     move.action = ActionType.MAGIC_MISSILE
Ejemplo n.º 5
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
Ejemplo n.º 6
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