示例#1
0
    def gen_input_hero(self, hero, rival_towers):
        if hero.state == 'out' or hero.hp <= 0:
            return list(np.zeros(13+3*19))

        dis_rival = 10000
        if len(rival_towers) > 0:
            dis_list = [StateUtil.cal_distance2(hero.pos, t.pos) for t in rival_towers]
            dis_rival = min(dis_list)

        hero_input = [self.normalize_value(int(hero.hero_name)),
                  self.normalize_value(hero.pos.x),
                  self.normalize_value(hero.pos.z),
                  self.normalize_value(hero.speed),
                  self.normalize_value(hero.att),
                  # todo: 2 是普攻手长,现只适用于1,2号英雄,其他英雄可能手长不同
                  0.2,
                  self.normalize_value(hero.mag),
                  self.normalize_value(hero.hp),
                  hero.hp/float(hero.maxhp),
                  self.normalize_value(hero.mp),
                  self.normalize_value(dis_rival),
                  hero.team]

        is_enemy_visible = hero.is_enemy_visible()
        hero_input.append(int(is_enemy_visible))

        skill_info1 = SkillUtil.get_skill_info(hero.cfg_id, 1)
        skill_info2 = SkillUtil.get_skill_info(hero.cfg_id, 2)
        skill_info3 = SkillUtil.get_skill_info(hero.cfg_id, 3)

        skill_input1 = self.gen_input_skill(skill_info1, hero.skills[1])
        skill_input2 = self.gen_input_skill(skill_info2, hero.skills[2])
        skill_input3 = self.gen_input_skill(skill_info3, hero.skills[3])
        hero_input=hero_input+skill_input1+skill_input2+skill_input3
        return hero_input
示例#2
0
    def gen_input_hero(hero, query_hero, revert=False):
        if hero is None or hero.state == 'out' or hero.hp <= 0:
            return list(np.zeros(20 + 3 * 23))

        # 添加英雄基础信息 11个
        hero_input = [
            TeamBattleInput.normalize_value(hero.pos.x -
                                            query_hero.pos.x if not revert else
                                            -(hero.pos.x - query_hero.pos.x)),
            TeamBattleInput.normalize_value(hero.pos.z -
                                            query_hero.pos.z if not revert else
                                            -(hero.pos.z - query_hero.pos.z)),
            TeamBattleInput.normalize_value(hero.speed),
            # # todo: 2 是普攻手长,现只适用于1,2号英雄,其他英雄可能手长不同
            # 0.2,
            TeamBattleInput.normalize_value(hero.hp),
            hero.hp / float(hero.maxhp),
            TeamBattleInput.normalize_value(hero.hprec),
            TeamBattleInput.normalize_value(hero.mp),
            TeamBattleInput.normalize_value(hero.mag),
            TeamBattleInput.normalize_value(hero.magpen),
            TeamBattleInput.normalize_value(hero.magpenrate),
            hero.team if not revert else 1 - hero.team
        ]

        # 添加物理攻击信息,预留5个攻击对象位,9个
        hero_input.append(TeamBattleInput.normalize_value(hero.att)),
        hero_input.append(TeamBattleInput.normalize_value(hero.attspeed)),
        hero_input.append(TeamBattleInput.normalize_value(hero.attpen)),
        hero_input.append(TeamBattleInput.normalize_value(hero.attpenrate)),
        hero_input.append(0)
        hero_input.append(0)
        hero_input.append(0)
        hero_input.append(0)
        hero_input.append(0)

        # 添加技能信息
        skill_info1 = SkillUtil.get_skill_info(hero.cfg_id, 1)
        skill_info2 = SkillUtil.get_skill_info(hero.cfg_id, 2)
        skill_info3 = SkillUtil.get_skill_info(hero.cfg_id, 3)
        skill_input1 = TeamBattleInput.gen_input_skill(skill_info1,
                                                       hero.skills[1])
        skill_input2 = TeamBattleInput.gen_input_skill(skill_info2,
                                                       hero.skills[2])
        skill_input3 = TeamBattleInput.gen_input_skill(skill_info3,
                                                       hero.skills[3])

        #TODO 添加历史信息,之前3帧,每次的位置,动作(移动,攻击,技能1-3),hitinfo,tgtpos

        hero_input = hero_input + skill_input1 + skill_input2 + skill_input3
        return hero_input
示例#3
0
    def gen_input_hero(self, hero, query_hero, rival_towers, revert=False):
        if hero.state == 'out' or hero.hp <= 0:
            return list(np.zeros(16 + 3 * 17))

        dis_rival = 10000
        if len(rival_towers) > 0:
            dis_list = [
                StateUtil.cal_distance2(hero.pos, t.pos) for t in rival_towers
            ]
            dis_rival = min(dis_list)

        hero_input = [
            self.normalize_value(hero.pos.x -
                                 query_hero.pos.x if not revert else -(
                                     hero.pos.x - query_hero.pos.x)),
            self.normalize_value(hero.pos.z -
                                 query_hero.pos.z if not revert else -(
                                     hero.pos.z - query_hero.pos.z)),
            self.normalize_value(hero.speed),
            self.normalize_value(hero.att),
            self.normalize_value(hero.attspeed),
            self.normalize_value(hero.attpen),
            self.normalize_value(hero.attpenrate),
            # # todo: 2 是普攻手长,现只适用于1,2号英雄,其他英雄可能手长不同
            # 0.2,
            self.normalize_value(hero.hp),
            hero.hp / float(hero.maxhp),
            self.normalize_value(hero.hprec),
            self.normalize_value(hero.mp),
            self.normalize_value(hero.mag),
            self.normalize_value(hero.magpen),
            self.normalize_value(hero.magpenrate),
            self.normalize_value(dis_rival),
            hero.team if not revert else 1 - hero.team
        ]

        # is_enemy_visible = hero.is_enemy_visible()
        # hero_input.append(int(is_enemy_visible))

        skill_info1 = SkillUtil.get_skill_info(hero.cfg_id, 1)
        skill_info2 = SkillUtil.get_skill_info(hero.cfg_id, 2)
        skill_info3 = SkillUtil.get_skill_info(hero.cfg_id, 3)

        skill_input1 = self.gen_input_skill(skill_info1, hero.skills[1])
        skill_input2 = self.gen_input_skill(skill_info2, hero.skills[2])
        skill_input3 = self.gen_input_skill(skill_info3, hero.skills[3])
        hero_input = hero_input + skill_input1 + skill_input2 + skill_input3
        return hero_input
示例#4
0
    def gen_attack_cast_action_indic(hero_info, enemy_info, friends, opponents):
        recommmend_actions = []
        tgt_idx = TeamBattleUtil.get_hero_index(enemy_info.hero_name)

        # 添加物理攻击
        action_idx = TeamBattleUtil.get_action_index(tgt_idx, 0)
        recommmend_actions.append(action_idx)

        # 添加技能攻击
        for skill_id in range(1, 4):
            skill_info = SkillUtil.get_skill_info(hero_info.cfg_id, skill_id)
            if skill_info.cast_target == SkillTargetEnum.rival:
                action_idx = TeamBattleUtil.get_action_index(tgt_idx, skill_id)
                recommmend_actions.append(action_idx)
            elif skill_info.cast_target == SkillTargetEnum.self:
                # 如果技能对象是自己,添加自己作为目标,
                # 注意,这里的合理性会由技能检查条件来覆盖
                action_idx = TeamBattleUtil.get_action_index(0, skill_id)
                recommmend_actions.append(action_idx)
        return recommmend_actions, tgt_idx
示例#5
0
    def get_action_cmd(action_list,
                       unaval_list,
                       recommmend_list,
                       state_info,
                       hero_name,
                       friends,
                       opponents,
                       revert=False):
        hero = state_info.get_hero(hero_name)
        found = False

        # 如果有推荐的行为,只从中挑选
        if len(recommmend_list) > 0:
            for i in range(len(action_list)):
                if i not in recommmend_list:
                    action_list[i] = -1
            print("battle_id", state_info.battleid, "tick", state_info.tick,
                  "hero", hero_name, "根据推荐,只从以下行为中挑选",
                  ",".join(str("%f" % float(act)) for act in action_list),
                  ",".join(str("%f" % float(act)) for act in recommmend_list))

        while not found:
            max_q = max(action_list)
            if max_q <= -1:
                action = CmdAction(hero_name, CmdActionEnum.HOLD, None, None,
                                   hero.pos, None, None, 48, None)
                return action, max_q, -1

            selected = action_list.index(max_q)
            avail_type = unaval_list[selected]
            if avail_type == -1:
                #TODO avail_type == 0: 是否考虑技能不可用时候不接近对方
                # 不可用行为
                action_list[selected] = -1
                continue

            if selected < 8:  # move
                fwd = StateUtil.mov(selected, revert)
                # 根据我们的移动公式计算一个目的地,缺点是这样可能被障碍物阻挡,同时可能真的可以移动距离比我们计算的长
                tgtpos = TeamBattleUtil.set_move_target(hero, fwd)
                # tgtpos = PosStateInfo(hero.pos.x + fwd.x * 15, hero.pos.y + fwd.y * 15, hero.pos.z + fwd.z * 15)
                action = CmdAction(hero.hero_name, CmdActionEnum.MOVE, None,
                                   None, tgtpos, None, None, selected, None)
                return action, max_q, selected
            elif selected < 13:  # 对敌英雄使用普攻
                target_index = selected - 8
                target_hero = TeamBattleUtil.get_target_hero(
                    hero.hero_name, friends, opponents, target_index)
                target_hero_info = state_info.get_hero(target_hero)
                avail_type = unaval_list[selected]
                if avail_type == 0:
                    action = CmdAction(hero.hero_name, CmdActionEnum.MOVE,
                                       None, None, target_hero_info.pos, None,
                                       None, selected, None)
                else:
                    action = CmdAction(hero.hero_name, CmdActionEnum.ATTACK, 0,
                                       target_hero, None, None, None, selected,
                                       None)
                return action, max_q, selected
            elif selected < 28:  # skill
                skillid = int((selected - 13) / 5 + 1)
                tgt_index = selected - 13 - (skillid - 1) * 5
                skill_info = SkillUtil.get_skill_info(hero.cfg_id, skillid)
                is_buff = True if skill_info.cast_target == SkillTargetEnum.buff else False
                is_self = True if skill_info.cast_target == SkillTargetEnum.self else False
                tgt_hero = TeamBattleUtil.get_target_hero(
                    hero.hero_name, friends, opponents, tgt_index, is_buff,
                    is_self)
                tgt_pos = state_info.get_hero(tgt_hero).pos
                fwd = tgt_pos.fwd(hero.pos)
                avail_type = unaval_list[selected]
                if avail_type == 0:
                    action = CmdAction(hero.hero_name, CmdActionEnum.MOVE,
                                       None, None, tgt_pos, None, None,
                                       selected, None)
                else:
                    action = CmdAction(hero.hero_name, CmdActionEnum.CAST,
                                       skillid, tgt_hero, tgt_pos, fwd, None,
                                       selected, None)
                return action, max_q, selected
示例#6
0
    def list_unaval_actions(act_size,
                            state_info,
                            hero_name,
                            team_battle_heros,
                            battle_range,
                            debug=False):
        friends, opponents = TeamBattleUtil.get_friend_opponent_heros(
            team_battle_heros, hero_name)
        avail_list = [-1] * act_size
        for i in range(act_size):
            hero = state_info.get_hero(hero_name)
            selected = i
            if selected < 8:  # move
                # 不再检查movelock,因为攻击硬直也会造成这个值变成false(false表示不能移动)
                # 屏蔽会离开战圈的移动
                fwd = StateUtil.mov(selected)
                move_pos = TeamBattleUtil.play_move(hero, fwd)
                in_range = TeamBattleTrainer.in_battle_range(
                    move_pos, battle_range)
                if in_range != -1:
                    avail_list[selected] = -1
                else:
                    avail_list[selected] = 1
                continue
            elif selected < 13:  # 物理攻击:五个攻击目标
                target_index = selected - 8
                target_hero = TeamBattleUtil.get_target_hero(
                    hero_name, friends, opponents, target_index)
                if target_hero is None:
                    avail_list[selected] = -1
                    if debug: print("找不到对应目标英雄")
                    continue
                rival_info = state_info.get_hero(target_hero)
                dist = StateUtil.cal_distance(hero.pos, rival_info.pos)
                # 英雄不可见
                if not rival_info.is_enemy_visible():
                    avail_list[selected] = -1
                    if debug: print("英雄不可见")
                    continue
                # 英雄太远,放弃普攻
                # if dist > self.att_dist:
                if dist > StateUtil.ATTACK_HERO_RADIUS:
                    avail_list[selected] = 0
                    if debug: print("英雄太远,放弃普攻")
                    continue
                # 对方英雄死亡时候忽略这个目标
                elif rival_info.hp <= 0:
                    avail_list[selected] = -1
                    if debug: print("对方英雄死亡")
                    continue
                avail_list[selected] = 1
            elif selected < 28:  # skill1
                # TODO 处理持续施法,目前似乎暂时还不需要
                skillid = int((selected - 13) / 5 + 1)
                if hero.skills[skillid].canuse != True:
                    # 被沉默,被控制住(击晕击飞冻结等)或者未学会技能
                    avail_list[selected] = -1
                    if debug:
                        print("技能受限,放弃施法" + str(skillid) +
                              " hero.skills[x].canuse=" +
                              str(hero.skills[skillid].canuse) + " tick=" +
                              str(state_info.tick))
                    continue
                if hero.skills[skillid].cost is not None and hero.skills[
                        skillid].cost > hero.mp:
                    # mp不足
                    # 特殊情况,德古拉1,2技能是扣除血量
                    if not (hero.cfg_id == '103' and
                            (skillid == 1 or skillid == 2)):
                        avail_list[selected] = -1
                        if debug: print("mp不足,放弃施法" + str(skillid))
                        continue
                if hero.skills[skillid].cd > 0:
                    # 技能未冷却
                    avail_list[selected] = -1
                    if debug: print("技能cd中,放弃施法" + str(skillid))
                    continue
                tgt_index = selected - 13 - (skillid - 1) * 5
                skill_info = SkillUtil.get_skill_info(hero.cfg_id, skillid)
                # TODO 这个buff逻辑还没有测试对应的英雄
                is_buff = True if skill_info.cast_target == SkillTargetEnum.buff else False
                is_self = True if skill_info.cast_target == SkillTargetEnum.self else False
                tgt_hero = TeamBattleUtil.get_target_hero(
                    hero.hero_name, friends, opponents, tgt_index, is_buff,
                    is_self)

                if tgt_hero is None:
                    avail_list[selected] = -1
                    if debug: print("找不到对应目标英雄")
                    continue
                [tgtid, tgtpos] = TeamBattleTrainer.choose_skill_target(
                    tgt_index, state_info, skill_info, hero_name, hero.pos,
                    tgt_hero, debug)
                if tgtid == -1 or tgtid == 0:
                    avail_list[selected] = tgtid
                    if debug: print("目标不符合施法要求")
                    continue
                else:
                    # 根据规则再去过滤
                    policy_avail = TeamBattlePolicy.check_skill_condition(
                        skill_info, state_info, hero, tgt_hero, friends,
                        opponents)
                    if not policy_avail:
                        avail_list[selected] == -1
                    else:
                        avail_list[selected] = 1
        return avail_list
示例#7
0
    def guess_player_action(prev_state_info, state_info, next_state_info,
                            next_next_state_info, hero_name, rival_hero_name):
        #针对每一帧,结合后一帧信息,判断英雄在该帧的有效操作
        #仅对于一对一线上模型有效
        #技能>攻击>走位
        #技能:检查cd和mp变化,hitstateinfo,attackstateinfo,dmgstateinifo,回推pos,fwd,tgt,selected
        #攻击:检查hit,damage,attack
        #检查pos变化

        prev_hero = prev_state_info.get_hero(hero_name)
        prev_viral_hero = prev_state_info.get_hero(rival_hero_name)
        current_hero = state_info.get_hero(hero_name)

        hero_attack_info = state_info.get_hero_attack_info(hero_name)
        if hero_attack_info is not None:
            skill = hero_attack_info.skill

            # 看十位来决定技能id
            skillid = int(hero_attack_info.skill % 100 / 10)
            tgtid = int(hero_attack_info.defer) if (
                hero_attack_info.defer is not None
                and hero_attack_info.defer != 'None') else 0
            tgtpos = hero_attack_info.tgtpos

            # 回城
            if hero_attack_info.skill == 10000:
                action = CmdAction(hero_name, CmdActionEnum.CAST, 6, None,
                                   None, None, None, 49, None)
                return action
            # 普攻,不会以自己为目标
            output_idx = None
            if skillid == 0:
                # 打塔
                if StateUtil.if_unit_tower(tgtid):
                    output_idx = 8
                # 普通攻击敌方英雄
                elif tgtid == prev_viral_hero.hero_name:  # 普通攻击敌方英雄
                    output_idx = 9
                # 普通攻击敌方小兵
                elif tgtid != 0:
                    creeps = StateUtil.get_nearby_enemy_units(
                        prev_state_info, hero_name)
                    n = len(creeps)
                    for i in range(n):
                        if creeps[i].unit_name == str(tgtid):
                            output_idx = i + 10
                # attacinfo里没有目标,从hit里找目标
                elif tgtid == 0:
                    # hitinfo 和 dmginfo都有延迟,尤其是超远距离的攻击技能
                    hit_infos = state_info.get_hero_hit_with_skill(
                        hero_name, skill)
                    hit_infos.extend(
                        next_state_info.get_hero_hit_with_skill(
                            hero_name, skill))
                    if len(hit_infos) > 0:
                        # 首先检查是否敌方英雄被击中,这种优先级最高
                        if rival_hero_name in [hit.tgt for hit in hit_infos]:
                            output_idx = 9
                        else:
                            # 找到被攻击者中血量最少的,认为是目标对象
                            tgtid_list = [
                                state_info.get_obj(hit.tgt)
                                for hit in hit_infos
                            ]
                            tgt_unit = min(tgtid_list, key=lambda x: x.hp)

                            if StateUtil.if_unit_tower(tgt_unit.unit_name):
                                output_idx = 8
                            else:
                                # 从英雄附近的小兵中,检索它的编号
                                # 注:极端情况下有可能丢失,比如在这0.5秒钟内,英雄接近了小兵并进行了攻击
                                # 扩大搜索的范围
                                creeps = StateUtil.get_nearby_enemy_units(
                                    prev_state_info,
                                    hero_name,
                                    max_distance=StateUtil.ATTACK_HERO_RADIUS +
                                    2)
                                for i in range(len(creeps)):
                                    if creeps[i].unit_name == tgtid:
                                        output_idx = i + 10
                if output_idx is not None:
                    action = CmdAction(hero_name, CmdActionEnum.ATTACK, 0,
                                       tgtid, tgtpos, None, None, output_idx,
                                       None)
                    return action
            # 使用技能,不考虑以敌方塔为目标(若真以敌方塔为目标则暂时先不管吧,现在的两个英雄技能都对建筑无效)
            # TODO 暂时忽略技能为方向/范围型并且放空的情况(部分技能无任何目标,tgt为0)。这种情况下应该会有个pos记录释放点,后续可以考虑如何学习
            else:
                # 对自身施法
                if tgtid == int(
                        hero_name
                ):  # or (tgtid=='0' and Replayer.skill_tag[skillid]==1):
                    tgtpos = prev_hero.pos
                    output_idx = 8 + skillid * 10
                # 对敌方英雄施法
                elif tgtid == int(rival_hero_name):
                    tgtpos = prev_viral_hero.pos
                    output_idx = 9 + skillid * 10
                # 对小兵施法
                elif tgtid != 0 and not StateUtil.if_unit_tower(tgtid):
                    creeps = StateUtil.get_nearby_enemy_units(
                        prev_state_info, hero_name)
                    n = len(creeps)
                    for i in range(n):
                        if creeps[i].unit_name == str(tgtid):
                            output_idx = i + skillid * 10 + 10
                # attacinfo里没有目标,从hit里找目标
                elif tgtid == 0:
                    # 远程技能的伤害延迟可能会比较长
                    hit_infos = state_info.get_hero_hit_with_skill(
                        hero_name, skill)
                    hit_infos.extend(
                        next_state_info.get_hero_hit_with_skill(
                            hero_name, skill))
                    hit_infos.extend(
                        next_next_state_info.get_hero_hit_with_skill(
                            hero_name, skill))

                    if len(hit_infos) > 0:
                        # 首先检查是否敌方英雄被击中,这种优先级最高
                        if rival_hero_name in [hit.tgt for hit in hit_infos]:
                            tgtid = rival_hero_name
                            output_idx = 9 + skillid * 10
                        else:
                            # 找到被攻击者中血量最少的,认为是目标对象
                            tgtid_list = [
                                state_info.get_obj(hit.tgt)
                                for hit in hit_infos
                            ]
                            tgt_unit = min(tgtid_list, key=lambda x: x.hp)

                            # 从英雄附近的小兵中,检索它的编号
                            # 注:极端情况下有可能丢失,比如在这0.5秒钟内,英雄接近了小兵并进行了攻击
                            creeps = StateUtil.get_nearby_enemy_units(
                                prev_state_info, hero_name)
                            for i in range(len(creeps)):
                                if creeps[i].unit_name == tgt_unit.unit_name:
                                    tgtid = creeps[i].unit_name
                                    output_idx = i + 10 + skillid * 10

                # 组装结果
                if output_idx is not None:
                    action = CmdAction(hero_name, CmdActionEnum.CAST, skillid,
                                       tgtid, tgtpos, None, None, output_idx,
                                       None)
                    return action
                # 任然没有hit,技能空放
                if tgtid == 0:
                    # attackinfo里没有攻击目标id,只有坐标,根据位置找最近的目标作为输出
                    if tgtpos != None:
                        search_radius = 1
                        # 首先寻找目标为对方英雄, 目前,如果在范围内有敌人英雄,选第一个作为主目标
                        nearby_rival_heros = StateUtil.get_nearby_enemy_heros(
                            prev_state_info, hero_name, search_radius)
                        if len(nearby_rival_heros) > 0:
                            tgtid = nearby_rival_heros[0].hero_name
                            output_idx = 9 + skillid * 10
                        else:
                            # 其次检查是否可以释放给自己
                            skill_info = SkillUtil.get_skill_info(
                                prev_hero.cfg_id, skillid)
                            if skill_info is not None:
                                if skill_info.cast_target != SkillTargetEnum.rival:
                                    tgtid = hero_name
                                    output_idx = 8 + skillid * 10
                                # 最后检查是否可以释放给小兵
                                else:
                                    nearby_soldiers = StateUtil.get_nearby_enemy_units(
                                        prev_state_info, hero_name,
                                        search_radius)
                                    if len(nearby_soldiers) > 0:
                                        target_unit = min(nearby_soldiers,
                                                          key=lambda u: u.hp)
                                        for i in range(len(nearby_soldiers)):
                                            if nearby_soldiers[
                                                    i].unit_name == target_unit.unit_name:
                                                tgtid = nearby_soldiers[
                                                    i].unit_name
                                                output_idx = i + 10 + skillid * 10
                    # 组装结果
                    if output_idx is not None:
                        action = CmdAction(hero_name, CmdActionEnum.CAST,
                                           skillid, tgtid, tgtpos, None, None,
                                           output_idx, None)
                        return action
                    else:  # 真的技能空放了
                        action = CmdAction(hero_name, CmdActionEnum.HOLD, None,
                                           None, prev_hero.pos, None, None, 48,
                                           None)
                        return action
                action = CmdAction(hero_name, CmdActionEnum.HOLD, None, None,
                                   prev_hero.pos, None, None, 48, None)
                return action
        # 没有角色进行攻击或使用技能,英雄在移动或hold
        if current_hero.pos.x != prev_hero.pos.x or current_hero.pos.z != prev_hero.pos.z or current_hero.pos.y != prev_hero.pos.y:  # 移动
            fwd = current_hero.pos.fwd(prev_hero.pos)
            [fwd, output_index] = Replayer.get_closest_fwd(fwd)
            action = CmdAction(hero_name, CmdActionEnum.MOVE, None, None, None,
                               fwd, None, output_index, None)
            return action
        else:  # hold
            action = CmdAction(hero_name, CmdActionEnum.HOLD, None, None,
                               prev_hero.pos, None, None, 48, None)
            return action
示例#8
0
    def choose_skill_target(selected,
                            stateinformation,
                            skill,
                            hero_name,
                            pos,
                            rival_hero,
                            debug=False):
        hero_info = stateinformation.get_hero(hero_name)
        skill_info = SkillUtil.get_skill_info(hero_info.cfg_id, skill)
        if selected == 0:
            # 施法目标为自己
            # 首先判断施法目标是不是只限于敌方英雄
            if skill_info.cast_target == SkillTargetEnum.rival:
                return [-1, None]
            tgtid = hero_name
            # TODO 这里有点问题,如果是目标是自己的技能,是不是要区分下目的,否则fwd计算会出现问题
            tgtpos = None
        elif selected == 1:
            # 攻击对方英雄
            # 首先判断施法目标是不是只限于自己
            if skill_info.cast_target == SkillTargetEnum.self:
                return [-1, None]
            rival = stateinformation.get_hero(rival_hero)
            if not rival.is_enemy_visible():
                if debug: print("敌方英雄不可见")
                tgtid = -1
                tgtpos = None
            elif StateUtil.cal_distance(rival.pos,
                                        pos) > skill_info.cast_distance:
                if debug:
                    print("技能攻击不到对方 %s %s %s" %
                          (rival_hero, StateUtil.cal_distance(
                              rival.pos, pos), skill_info.cast_distance))
                tgtid = -1
                tgtpos = None
            # 对方英雄死亡时候忽略这个目标
            elif rival.hp <= 0:
                if debug: print("技能攻击不了对方,对方已经死亡")
                tgtid = -1
                tgtpos = None
            else:
                tgtid = rival_hero
                tgtpos = rival.pos
        else:
            # 对敌方小兵施法
            if skill_info.cast_target == SkillTargetEnum.self:
                return [-1, None]

            # 寻找合适的小兵作为目标
            creeps = StateUtil.get_nearby_enemy_units(stateinformation,
                                                      hero_name)
            n = selected - 2
            if n >= len(creeps):
                # 没有这么多小兵
                if debug: print("技能不能攻击,没有指定的小兵")
                return [-1, None]
            elif not creeps[n].is_enemy_visible():
                if debug: print("敌方小兵不可见")
                tgtid = -1
                tgtpos = None
            elif StateUtil.cal_distance(
                    pos, creeps[n].pos) > skill_info.cast_distance:
                if debug: print("技能不能攻击,小兵距离过远")
                tgtid = -1
                tgtpos = None
            elif creeps[n].hp <= 0:
                if debug: print("技能不能攻击,小兵已经死亡")
                tgtid = -1
                tgtpos = None
            else:
                tgtid = creeps[n].unit_name
                tgtpos = creeps[n].pos
        return [tgtid, tgtpos]