Beispiel #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
Beispiel #2
0
    def find_next_tgt(state_info, unit, soldier_list):
        # 为了节省计算量,我们只从英雄附近的小兵中寻找被攻击者, 或者是英雄
        heros = StateUtil.get_heros_in_team(state_info, 1 - unit.team_id)
        hero = heros[0]
        min_dis = StateUtil.cal_distance2(hero.pos, unit.pos)

        tgt = hero.hero_name
        for soldier in soldier_list:
            dis = StateUtil.cal_distance2(soldier.pos, unit.pos)
            if dis < min_dis:
                tgt = soldier.unit_name
                min_dis = dis

        if min_dis <= StateUtil.TOWER_ATTACK_RADIUS * 1000:
            return tgt
        return None
Beispiel #3
0
 def gen_input_building(self,
                        building,
                        query_hero=None,
                        state_info=None,
                        hero_name=None,
                        revert=False):
     if building is None:
         building_info = np.zeros(8)
         building_info = list(building_info)
     else:
         hero_info = state_info.get_hero(hero_name)
         building_info = [
             self.normalize_value(building.pos.x -
                                  query_hero.pos.x if not revert else -(
                                      building.pos.x - query_hero.pos.x)),
             self.normalize_value(building.pos.z -
                                  query_hero.pos.z if not revert else -(
                                      building.pos.z - query_hero.pos.z)),
             self.normalize_value(building.att),
             self.normalize_value(7000),
             self.normalize_value(building.hp),
             self.normalize_value(
                 StateUtil.cal_distance2(building.pos, hero_info.pos)),
             building.team if not revert else 1 - building.team
         ]
         # 添加是否在攻击当前英雄
         attack_info = state_info.if_unit_attack_hero(
             building.unit_name, hero_name)
         if attack_info is None:
             building_info.append(0)
         else:
             building_info.append(1)
     return building_info
Beispiel #4
0
 def assert_tower_in_input(cur_state, hero_name, rival_hero):
     # 如果敌方塔要攻击英雄的话,检查塔的信息是不是在input中
     att_info = cur_state.if_tower_attack_hero(hero_name)
     if att_info is not None:
         tower = str(att_info.atker)
         tower_info = cur_state.get_obj(tower)
         hero_info = cur_state.get_hero(hero_name)
         model_input = LineModel_PPO1.gen_input(cur_state, hero_name,
                                                rival_hero)
         if model_input[44] == Line_Input_Lite.normalize_value_static(
                 int(tower)):
             print('yes found attack tower in input', tower, 'distance',
                   model_input[50], 'cal_distance',
                   StateUtil.cal_distance2(tower_info.pos, hero_info.pos))
         else:
             print('not found attack tower in input', tower, 'distance',
                   model_input[50], 'cal_distance',
                   StateUtil.cal_distance2(tower_info.pos, hero_info.pos))
Beispiel #5
0
    def play_attack(state_info, attacker, defender, time_second=0.5):
        attacker_info = state_info.get_hero(
            attacker) if StateUtil.if_unit_hero(
                attacker) else state_info.get_unit(attacker)
        defender_info = state_info.get_hero(
            defender) if StateUtil.if_unit_hero(
                defender) else state_info.get_unit(defender)

        #TODO 解决塔和小兵,还有英雄不同的攻击频率问题,有些攻击其实不是每次更新都需要触发的

        # 更新攻击信息,这个信息对下一帧的计算会起来指导作用
        # 如果已经存在一个,需要替换掉
        # 忽略技能id这个参数,因为这种情况下不会被使用到
        att = AttackStateInfo(attacker, defender, defender_info.pos, -1)
        state_info.update_attack_info(att)

        # 如果攻击者是小兵,为了简化,默认都可以攻击到英雄
        if StateUtil.if_unit_soldier(
                attacker_info.cfg_id) and StateUtil.if_unit_long_range_attack(
                    attacker_info.cfg_id):
            # 更新位置信息
            attacker_info.pos = defender.pos
            state_info.update_unit(attacker_info)

        # 英雄攻击,需要考虑距离问题,还有追击的位移情况
        #TODO 这里的英雄位置,可能是移动之前的,也可能是移动之后的,其实需要分别处理。而且判断是否攻击到的条件太简单了
        elif StateUtil.if_unit_hero(attacker):
            dis = StateUtil.cal_distance2(attacker_info.pos, defender_info.pos)
            move_dis = attacker_info.speed * time_second
            if dis > move_dis:
                # 只移动,不攻击
                attacker_info.pos = PlayEngine.move_towards(
                    attacker_info.pos, defender_info.pos, move_dis, dis)
                StateUtil.update_hero(attacker_info)
                return state_info
            else:
                attacker_info.pos = defender_info.pos
                StateUtil.update_hero(attacker_info)

        #TODO 计算最终伤害的公式很不清楚,需要后续核实。减伤比例为 防御/(防御+100)=防御减伤,但是防御值怎么计算得来
        if StateUtil.if_unit_hero(defender):
            hero_cfg_id = defender_info.cfg_id
            defend_value, mag_defend_value = PlayEngine.get_defend_value(
                hero_cfg_id, defender_info.level)
            dmg = attacker_info.attack * defend_value / (defend_value + 100)
            defender_info.hp = max(defender_info.hp - dmg, 0)
            state_info.update_hero(defender_info)
        else:
            dmg = attacker_info.attack
            defender_info.hp = max(defender_info.hp - dmg, 0)
            state_info.update_unit(defender_info)
        return state_info
Beispiel #6
0
    def find_skill_targets(state_info, attacker_info, tgt_pos, skill_length,
                           skill_width, is_circle):
        if not is_circle:
            # 首先满足直线距离应该小于技能长度
            tgt_unit_list = [
                unit for unit in state_info.units
                if StateUtil.cal_distance2(attacker_info.pos, unit.pos) <=
                skill_length and not StateUtil.if_unit_tower(unit.unit_name)
            ]
            tgt_hero_list = [
                hero for hero in state_info.heros
                if StateUtil.cal_distance2(attacker_info.pos, hero.pos) <=
                skill_length and hero.hero_name != attacker_info.hero_name
            ]

            # 需要旋转坐标系 x1 = xcosa + ysina, y1 = ycosa - xsina
            # 或者按比例计算最大最下z值(相当于坐标系上的x)
            tgt_units = []
            for unit in tgt_unit_list:
                mid_x = attacker_info.pos.z + StateUtil.cal_distance2(
                    attacker_info.pos, unit.pos) / StateUtil.cal_distance2(
                        attacker_info.pos, tgt_pos) * (tgt_pos - attacker_info)
                if mid_x - skill_width / 2 <= unit.x <= mid_x + skill_width / 2:
                    tgt_units.append(unit)

            tgt_heros = []
            for hero in tgt_hero_list:
                mid_x = attacker_info.pos.z + StateUtil.cal_distance2(
                    attacker_info.pos, hero.pos) / StateUtil.cal_distance2(
                        attacker_info.pos, tgt_pos) * (tgt_pos - attacker_info)
                if mid_x - skill_width / 2 <= hero.x <= mid_x + skill_width / 2:
                    tgt_heros.append(hero)
            return tgt_units, tgt_heros

        else:
            # 根据tgt_pos画圆,计算范围内的敌人
            # 攻击对象不是塔
            tgt_unit_list = [
                unit for unit in state_info.units
                if StateUtil.cal_distance2(tgt_pos, unit.pos) <= skill_length
                and not StateUtil.if_unit_tower(unit.unit_name)
            ]
            tgt_hero_list = [
                hero for hero in state_info.heros
                if StateUtil.cal_distance2(tgt_pos, hero.pos) <= skill_length
                and hero.hero_name != attacker_info.hero_name
            ]
            return tgt_unit_list, tgt_hero_list
Beispiel #7
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
Beispiel #8
0
 def gen_input_building(self,building, state_info=None, hero_name=None):
     if building is None:
         building_info=np.zeros(9)
         building_info=list(building_info)
     else:
         hero_info = state_info.get_hero(hero_name)
         building_info=[self.normalize_value(int(building.unit_name)),
                        self.normalize_value(building.pos.x),
                        self.normalize_value(building.pos.z),
                        self.normalize_value(building.att),
                        self.normalize_value(7000),
                        self.normalize_value(building.hp),
                        self.normalize_value(StateUtil.cal_distance2(building.pos, hero_info.pos)),
                        building.team]
         # 添加是否在攻击当前英雄
         attack_info = state_info.if_unit_attack_hero(building.unit_name, hero_name)
         if attack_info is None:
             building_info.append(0)
         else:
             building_info.append(1)
     return building_info
Beispiel #9
0
    def gen_input_creep(self,
                        creep,
                        query_hero=None,
                        state_info=None,
                        hero_name=None,
                        towers=None,
                        revert=False):
        if creep is None:
            return list(np.zeros(7))

        dis = 10000
        if len(towers) > 0:
            dis_list = [
                StateUtil.cal_distance2(creep.pos, t.pos) for t in towers
            ]
            dis = min(dis_list)

        creep_info = [
            self.normalize_value(creep.pos.x -
                                 query_hero.pos.x if not revert else -(
                                     creep.pos.x - query_hero.pos.x)),
            self.normalize_value(creep.pos.z -
                                 query_hero.pos.z if not revert else -(
                                     creep.pos.z - query_hero.pos.z)),
            self.normalize_value(creep.att),
            self.normalize_value(creep.hp),
            self.normalize_value(dis),
            creep.team if not revert else 1 - creep.team
        ]

        # 添加是否在攻击当前英雄
        attack_info = state_info.if_unit_attack_hero(creep.unit_name,
                                                     hero_name)
        if attack_info is None:
            creep_info.append(0)
        else:
            creep_info.append(1)
        return creep_info
Beispiel #10
0
    def build_response(self, state_cache, state_index, hero_name):
        action_strs=[]
        restart = False

        # 对于模型,分析当前帧的行为
        if self.real_hero != hero_name:
            state_info = state_cache[state_index]
            prev_hero = state_cache[state_index-1].get_hero(hero_name) if len(state_cache) >= 2 is not None else None
        # 如果有真实玩家,我们需要一些历史数据,所以分析3帧前的行为
        elif len(state_cache) > 3:
            state_info = state_cache[state_index-3]
            next1_state_info = state_cache[state_index-2]
            next2_state_info = state_cache[state_index-1]
            next3_state_info = state_cache[state_index]
        else:
            return action_strs, False

        # 决定是否购买道具
        buy_action = EquipUtil.buy_equip(state_info, hero_name)
        if buy_action is not None:
            buy_str = StateUtil.build_command(buy_action)
            action_strs.append(buy_str)

        # 如果有可以升级的技能,优先升级技能3
        hero = state_info.get_hero(hero_name)
        skills = StateUtil.get_skills_can_upgrade(hero)
        if len(skills) > 0:
            skillid = 3 if 3 in skills else skills[0]
            update_cmd = CmdAction(hero.hero_name, CmdActionEnum.UPDATE, skillid, None, None, None, None, None, None)
            update_str = StateUtil.build_command(update_cmd)
            action_strs.append(update_str)

        # 回城相关逻辑
        # 如果在回城中且没有被打断则继续回城,什么也不用返回
        if prev_hero is not None:
            if hero.hero_name in self.hero_strategy and self.hero_strategy[hero.hero_name] == ActionEnum.town_ing \
                    and prev_hero.hp <= hero.hp \
                    and not StateUtil.if_hero_at_basement(hero):
                if not hero.skills[6].canuse:
                    print(self.battle_id, hero.hero_name, '回城中,继续回城')
                    return action_strs, False
                else:
                    print(self.battle_id, hero.hero_name, '回城失败')
                    town_action = CmdAction(hero.hero_name, CmdActionEnum.CAST, 6, hero.hero_name, None, None, None,
                                            None, None)
                    action_str = StateUtil.build_command(town_action)
                    action_strs.append(action_str)
                    return action_strs, False
                if hero.hp <= 0:
                    self.hero_strategy[hero.hero_name] = None
                    return action_strs, False

        # # 补血逻辑
        # if prev_hero is not None and hero.hero_name in self.hero_strategy and self.hero_strategy[
        #     hero.hero_name] == ActionEnum.hp_restore:
        #     if StateUtil.cal_distance2(prev_hero.pos, hero.pos) < 100:
        #         print(self.battle_id, hero_name, '到达补血点', '血量增长', hero.hp - prev_hero.hp)
        #         del self.hero_strategy[hero_name]
        #         if hero == self.model1_hero:
        #             self.model1_hp_restore = time.time()
        #         else:
        #             self.model2_hp_restore = time.time()

        # 撤退逻辑
        # TODO 甚至可以使用移动技能移动
        if prev_hero is not None and hero.hero_name in self.hero_strategy and self.hero_strategy[hero.hero_name] == ActionEnum.retreat_to_town:
            if StateUtil.cal_distance2(prev_hero.pos, hero.pos) < 100:
                print(self.battle_id, hero_name, '开始回城')
                self.hero_strategy[hero.hero_name] = ActionEnum.town_ing
                town_action = CmdAction(hero.hero_name, CmdActionEnum.CAST, 6, hero.hero_name, None, None, None,
                                        None, None)
                action_str = StateUtil.build_command(town_action)
                action_strs.append(action_str)
            else:
                print(self.battle_id, hero_name, '还在撤退中', StateUtil.cal_distance2(prev_hero.pos, hero.pos))
            return action_strs, False

        # 如果击杀了对方英雄,扫清附近小兵之后则启动撤退回城逻辑
        if prev_hero is not None:
            if hero.hero_name in self.hero_strategy and self.hero_strategy[hero.hero_name] == ActionEnum.town_ing and prev_hero.hp <= hero.hp \
                    and not StateUtil.if_hero_at_basement(hero):
                if not hero.skills[6].canuse:
                    return action_strs, False
                else:
                    town_action = CmdAction(hero.hero_name, CmdActionEnum.CAST, 6, hero.hero_name, None, None, None,
                                            None, None)
                    action_str = StateUtil.build_command(town_action)
                    action_strs.append(action_str)
        if hero.hp <= 0:
            self.hero_strategy[hero.hero_name] = None
            return action_strs, False

        # 检查周围状况
        near_enemy_heroes = StateUtil.get_nearby_enemy_heros(state_info, hero.hero_name, StateUtil.LINE_MODEL_RADIUS)
        near_enemy_units = StateUtil.get_nearby_enemy_units(state_info, hero.hero_name, StateUtil.LINE_MODEL_RADIUS)
        nearest_enemy_tower = StateUtil.get_nearest_enemy_tower(state_info, hero.hero_name,
                                                                StateUtil.LINE_MODEL_RADIUS + 3)
        nearest_friend_units = StateUtil.get_nearby_friend_units(state_info, hero.hero_name, StateUtil.LINE_MODEL_RADIUS)
        line_index = 1
        near_enemy_units_in_line = StateUtil.get_units_in_line(near_enemy_units, line_index)
        nearest_enemy_tower_in_line = StateUtil.get_units_in_line([nearest_enemy_tower], line_index)

        # 如果击杀对面英雄就回城补血。整体逻辑为,周围没有兵的情况下启动撤退逻辑,到达撤退地点之后启动回城。补满血之后再跟兵出来
        # 处在泉水之中的时候设置策略层为吃线
        if len(near_enemy_units_in_line) == 0 and len(near_enemy_heroes) == 0:
            if (hero_name == self.model1_hero and self.model2_just_dead == 1 and not StateUtil.if_hero_at_basement(hero)) \
                    or (hero_name == self.model2_hero and self.model1_just_dead == 1 and not StateUtil.if_hero_at_basement(hero)):
                if hero.hp / float(hero.maxhp) > 0.8:
                    if hero_name == self.model1_hero:
                        self.model2_just_dead = 0
                    else:
                        self.model1_just_dead = 0
                else:
                    print(self.battle_id, hero_name, '选择撤退')
                    self.hero_strategy[hero_name] = ActionEnum.retreat_to_town
                    retreat_pos = StateUtil.get_retreat_pos(state_info, hero, line_index=1)
                    action = CmdAction(hero_name, CmdActionEnum.MOVE, None, None, retreat_pos, None, None, -1, None)
                    action_str = StateUtil.build_command(action)
                    action_strs.append(action_str)
                    if hero_name == self.model1_hero:
                        self.model2_just_dead = 0
                    else:
                        self.model1_just_dead = 0
                    return action_strs, False

            if StateUtil.if_hero_at_basement(hero):
                if hero_name == self.model1_hero:
                    self.model2_just_dead = 0
                else:
                    self.model1_just_dead = 0
                if hero.hp < hero.maxhp:
                    if hero_name in self.hero_strategy:
                        del self.hero_strategy[hero_name]
                    return action_strs, False

            # # 残血并且周围没有敌人的情况下,可以去塔后吃加血
            # if hero.hp / float(hero.maxhp) < 0.9 and hero not in self.hero_strategy:
            #     print('补血条件', self.battle_id, hero_name, time.time(), self.model1_hp_restore, self.model2_hp_restore)
            #     if hero == self.model1_hero and time.time() - self.model1_hp_restore > LineTrainerPPO.HP_RESTORE_GAP:
            #         print(self.battle_id, hero_name, '选择加血')
            #         self.hero_strategy[hero_name] = ActionEnum.hp_restore
            #     elif hero == self.model2_hero and time.time() - self.model2_hp_restore > LineTrainerPPO.HP_RESTORE_GAP:
            #         print(self.battle_id, hero_name, '选择加血')
            #         self.hero_strategy[hero_name] = ActionEnum.hp_restore
            #
            #     if self.hero_strategy[hero_name] == ActionEnum.hp_restore:
            #         restore_pos = StateUtil.get_hp_restore_place(state_info, hero)
            #         action = CmdAction(hero_name, CmdActionEnum.MOVE, None, None, restore_pos, None, None, -1, None)
            #         action_str = StateUtil.build_command(action)
            #         action_strs.append(action_str)
            #         return action_strs, False

        # 开始根据策略决定当前的行动
        # 对线情况下,首先拿到兵线,朝最前方的兵线移动
        # 如果周围有危险(敌方单位)则启动对线模型
        # 如果周围有小兵或者塔,需要他们都是在指定线上的小兵或者塔
        if (len(near_enemy_units_in_line) == 0 and len(nearest_enemy_tower_in_line) == 0 and (
                len(near_enemy_heroes) == 0 or
                StateUtil.if_in_line(hero, line_index, 4000) == -1)
            ) or\
            (len(nearest_friend_units) == 0 and len(near_enemy_units_in_line) == 0 and
            len(near_enemy_heroes) == 0 and len(nearest_enemy_tower_in_line) == 1):

            # 跟兵线或者跟塔,优先跟塔
            self.hero_strategy[hero.hero_name] = ActionEnum.line_1
            # print("策略层:因为附近没有指定兵线的敌人所以开始吃线 " + hero.hero_name)
            front_soldier = StateUtil.get_frontest_soldier_in_line(state_info, line_index, hero.team)
            first_tower = StateUtil.get_first_tower(state_info, hero)

            if front_soldier is None or (hero.team == 0 and first_tower.pos.x > front_soldier.pos.x) or (hero.team == 1 and first_tower.pos.x < front_soldier.pos.x):
                # 跟塔,如果塔在前面的话
                follow_tower_pos = StateUtil.get_tower_behind(first_tower, hero, line_index=1)
                move_action = CmdAction(hero.hero_name, CmdActionEnum.MOVE, None, None, follow_tower_pos, None, None,
                                        None, None)
                action_str = StateUtil.build_command(move_action)
                action_strs.append(action_str)
            else:
                # 得到最前方的兵线位置
                move_action = CmdAction(hero.hero_name, CmdActionEnum.MOVE, None, None, front_soldier.pos, None, None,
                                        None, None)
                action_str = StateUtil.build_command(move_action)
                action_strs.append(action_str)
        else:
            if self.real_hero != hero_name:
                # 使用模型进行决策
                # print("使用对线模型决定英雄%s的行动" % hero.hero_name)
                self.hero_strategy[hero.hero_name] = ActionEnum.line_model

                # 目前对线只涉及到两名英雄
                rival_hero = '28' if hero.hero_name == '27' else '27'
                action, explorer_ratio, action_ratios = self.get_action(state_info, hero_name, rival_hero)

                # 考虑使用固定策略
                # 如果决定使用策略,会连续n条行为全都采用策略(比如确保对方残血时候连续攻击的情况)
                # 如果策略返回为空则表示策略中断
                if self.policy_ratio > 0 and (
                        0 < self.cur_policy_act_idx_map[hero_name] < self.policy_continue_acts
                        or random.uniform(0, 1) <= self.policy_ratio
                ):
                    policy_action = LineTrainerPolicy.choose_action(state_info, action_ratios, hero_name, rival_hero,
                                            near_enemy_units, nearest_friend_units)
                    if policy_action is not None:
                        policy_action.vpred = action.vpred
                        action = policy_action
                        self.cur_policy_act_idx_map[hero_name] += 1
                        print("英雄 " + hero_name + " 使用策略,策略行为计数 idx " + str(self.cur_policy_act_idx_map[hero_name]))
                        if self.cur_policy_act_idx_map[hero_name] >= self.policy_continue_acts:
                            self.cur_policy_act_idx_map[hero_name] = 0
                    else:
                        # 策略中断,清零
                        if self.cur_policy_act_idx_map[hero_name] > 0:
                            print("英雄 " + hero_name + " 策略中断,清零")
                            self.cur_policy_act_idx_map[hero_name] = 0

                action_str = StateUtil.build_command(action)
                action_strs.append(action_str)

                # 如果是要求英雄施法回城,更新英雄状态,这里涉及到后续多帧是否等待回城结束
                if action.action == CmdActionEnum.CAST and int(action.skillid) == 6:
                    print("英雄%s释放了回城" % hero_name)
                    self.hero_strategy[hero.hero_name] = ActionEnum.town_ing

                # 如果是选择了撤退,进行特殊标记,会影响到后续的行为
                if action.action == CmdActionEnum.RETREAT:
                    print("英雄%s释放了撤退,撤退点为%s" % (hero_name, action.tgtpos.to_string()))
                    self.hero_strategy[hero.hero_name] = ActionEnum.retreat
                    self.retreat_pos = action.tgtpos

                # 如果批量训练结束了,这时候需要清空未使用的训练集,然后重启游戏
                if action.action == CmdActionEnum.RESTART:
                    restart = True
                else:
                    # 保存action信息到状态帧中
                    state_info.add_action(action)
            else:
                # 还是需要模型来计算出一个vpred
                rival_hero = '28' if hero.hero_name == '27' else '27'
                action, explorer_ratio, action_ratios = self.get_action(state_info, hero_name, rival_hero)

                # 推测玩家的行为
                guess_action = Replayer.guess_player_action(state_info, next1_state_info, next2_state_info,
                                                            next3_state_info, hero_name, rival_hero)
                guess_action.vpred = action.vpred
                action_str = StateUtil.build_command(guess_action)
                action_str['tick'] = state_info.tick
                print('猜测玩家行为为:' + JSON.dumps(action_str))

                # 保存action信息到状态帧中
                state_info.add_action(guess_action)

        return action_strs, restart
Beispiel #11
0
 def in_battle_range(pos, battle_range):
     dis = StateUtil.cal_distance2(pos, TeamBattleTrainer.BATTLE_CIRCLE)
     if dis < battle_range * 1000 + 500:
         return -1
     return dis