庙算兵棋推演AI开发初探(5-数据处理)
碎碎念:这最近几个月过得那叫一个难受,研究生开题没过、需求评审会在4月和6月开了2次、7月紧接着软件设计评审会,加班干得都是文档的事情,还有开会前的会务和乱七八糟的琐事,我们干的还被规定弄的束手束脚,领导还在“动态的增加任务”,逼得我和领导发了个火……把人当承载任务的工具和垫脚石,不考虑员工的自身发展、创造性和工作时间,我是怎么还能待到现在的。
——2024.7.28以上
开题终于在12月过了,刚过去的这周又全周无休准备出差的东西,今天终于有时间在开题后搞一搞了——2025.1.6
关于庙算的东西网上实在太少,再深入的话我可能先去找找sc2(星际2)的相关内容了。后来我建了个QQ庙算智能体开发研讨群聊——962415181,欢迎同好加入。
0.实现神经网络驱动的智能体的步骤
以下是模仿学习的步骤(分拣、提取、构建神经网络+行为预测)
1_filter
从源视数据中筛选出符合标准的对局复盘(replay)
2_extract
从筛选过的复盘数据中提取样本(sample)
切碎的细节特征(features)
——这部分是用numpy把各种特征组合成矩阵,方便神经网络来学习
3_neuralnetwork
设计的单算子行为克隆网络
设计的多算子分层监督学习网络
1.复盘格式版本问题
首先,庙算平台在2024年更新过一次,从python3.8改成3.10了,存储的复盘文件从一个json变成了一帧一个json然后打成压缩包的形式了(更方便找数据了,但我也需要重新写解析的代码了……)
写了一个拆分版本、一个json版本相互转化的代码:
def replay_merge(input_dir, output_file):
"""
用于新版1800+个分文件合并回旧文件
"""
merged_data = []
for file_name in sorted(os.listdir(input_dir)):
if file_name.endswith('.json'):
file_path = os.path.join(input_dir, file_name)
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
merged_data.append(data)
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(merged_data, f, ensure_ascii=False, indent=4)
# json.dump(merged_data, f, ensure_ascii=False) # 一行json不缩进
print(f"Created {output_file}")
def replay_split(source_file, output_dir=None):
"""
用于旧版一行json文件转化为新版1800+个分文件
"""
with open(source_file, 'r', encoding='gbk') as f:
content = f.read()
json_data = json.loads(content)
#直接输出到源目录
if output_dir is None:
# 新建一个文件夹路径
new_dir = os.path.join(os.path.dirname(source_file), 'replay_split')
# 创建新文件夹
os.makedirs(new_dir, exist_ok=True)
output_dir = new_dir
# 检查 json_data 是否是列表
if isinstance(json_data, list):
for i, item in enumerate(json_data):
new_file_name = f"{output_dir}/element_{i}.json"
with open(new_file_name, 'w', encoding='utf-8') as new_file:
json.dump(item, new_file, ensure_ascii=False, indent=4)
# json.dump(item, new_file, ensure_ascii=False) # 一行json不缩进
print(f"Created {new_file_name}")
else:
print("json_data is not a list")
2.复盘json查看方法
在每次的离线推演后,都有数据压缩包在log文件夹中被保存(新版把每一帧的数据当作独立的json数据文件了,也还可以)
为了我的RLHF(RLHF (RL with Human Feedback))来模拟人决策风格的想法,我需要处理实时的人类操作和交互数据。
比如我打开了上面的某条数据,是“一行”的json,我用vscode打开,可以右键“格式化文档”,左侧也可以找一个json扩展来方便使用。【格式化文档后,记得点一下插件上的“刷新”来重新匹配所在行】
格式化后的效果
目前我用qt绘制了兵棋的棋盘(已经搁置,用不上了),通过linux虚拟机运行庙算引擎与我的外部qt进行udp通信来进行交互。
3.复盘json代码解析
这部分一般需要通过json.load(file)函数,然后用['xxx']来获取
4.特征提取(特征化为编码区分,以便输入神经网络)
一般使用 one-hot 编码对特征进行编码,再放到神经网络中
神经网络的输入是有形状要求的
……(这部分回头补上)
最后是附录,从官网文档整理得到,加了与demoAI的agnet里行为枚举的中英对照
吐槽:官网文档里竟然还有括号没补全的小错误!!!我给补上了。
附录:行为指令json解释
"""
兵棋以json串来作为执行命令的载体,action的type来解释实际使用的是什么动作
https://wargame.ia.ac.cn/docs/reference/actions/
"""
actions = \
{
"机动,Move": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 1,
"move_path": "机动路径 list(int)"
},
"打击,Shoot": {
"actor": "int 动作发出者席位",
"obj_id": "攻击算子ID int",
"type": 2,
"target_obj_id": "目标算子ID",
"weapon_id": "武器ID int"
},
"上车,GetOn": {
"actor": "int 动作发出者席位",
"obj_id": "乘员算子ID int",
"type": 3,
"target_obj_id": "车辆算子ID"
},
"下车,GetOff": {
"actor": "int 动作发出者席位",
"obj_id": "车辆算子ID int",
"type": 4,
"target_obj_id": "乘员算子ID"
},
"夺控,Occupy": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 5
},
"切换状态,ChangeState": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 6,
"target_state": "目标状态 0-正常机动 1-行军 2-一级冲锋 3-二级冲锋, 4-掩蔽 5-半速"
},
"移除压制,RemoveKeep": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 7
},
"间瞄射击,JMPlan": {
"actor": "int 动作发出者席位",
"obj_id": "攻击算子ID int",
"type": 8,
"jm_pos": "目标位置",
"weapon_id": "武器ID int"
},
"引导射击,GuideShoot": {
"actor": "int 动作发出者席位",
"obj_id": "引导算子ID int",
"type": 9,
"target_obj_id": "目标算子ID",
"weapon_id": "武器ID int",
"guided_obj_id": "射击算子ID"
},
"停止机动,StopMove": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 10
},
"武器锁定,WeaponLock": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 11
},
"武器展开,WeaponUnFold": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 12
},
"取消间瞄计划,CancelJMPlan": {
"actor": "int 动作发出者席位",
"obj_id": "算子ID int",
"type": 13
},
"配置编组信息(营长专属动作)": {
"actor": "int 动作发出者席位",
"type": 100,
"info": {
"int 席位数": {
"operators": [
"int 算子id",
"int 算子id"
]
}
}
},
"进攻任务(营长专属下达)": {
"actor": "int 动作发出者席位",
"type": 207,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
"防御任务(营长专属下达)": {
"actor": "int 动作发出者席位",
"type": 208,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
"侦察任务(营长专属下达)": {
"actor": "int 动作发出者席位",
"type": 209,
"seat": "命令接收人id",
"hex": "任务目标位置",
"radius": "侦察半径",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
"集结任务(营长专属下达)": {
"actor": "int 动作发出者席位",
"type": 210,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
"删除作战任务(营长专属动作)": {
"actor": "int 动作发出者席位",
"type": 202,
"msg_id": "int 要删除的作战指令的id"
},
"部署上车": {
"actor": "int 动作发出者席位",
"obj_id": "乘员算子ID int",
"type": 303,
"target_obj_id": "车辆算子ID"
},
"部署下车": {
"actor": "int 动作发出者席位",
"obj_id": "车辆算子ID int",
"type": 304,
"target_obj_id": "乘员算子ID"
},
"解聚,Fork": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 14
},
"聚合,Union": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"target_obj_id": "算子ID int",
"type": 15
},
"部署解聚(赛前部署动作)": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 314
},
"部署聚合(赛前部署动作)": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"target_obj_id": "算子ID int",
"type": 315
},
"改变高程,ChangeAltitude": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 16,
"target_altitude": "目标高程,20超低空,200低空 500高空"
},
"部署改变高程(赛前部署动作)": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 316,
"target_altitude": "目标高程,20超低空,200低空 500高空"
},
"开启校射雷达,ActivateRadar": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 17
},
"进入工事,EnterFort": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 18,
"target_obj_id": "工事算子ID"
},
"退出工事,ExitFort": {
"actor": "int 动作发出者",
"obj_id": "算子ID int",
"type": 19,
"target_obj_id": "工事算子ID"
},
"布雷,LayMine": {
"actor": "int 动作发出者",
"obj_id": "布雷车算子ID int",
"type": 20,
"target_pos": "布雷坐标 int"
},
"导演击杀算子(导演动作)": {
"actor": "int",
"type": 401,
"target_obj_id": "击杀算子id"
},
"导演布雷(导演动作)": {
"actor": "int",
"type": 402,
"target_pos": "布雷坐标"
},
"导演建造路障(导演动作)": {
"actor": "int",
"type": 403,
"target_pos": "路障坐标"
},
"导演增加算子(导演动作)": {
"actor": "int",
"type": 404,
"sub_type": "算子sub_type",
"color": "0红, 1蓝",
"hex": "空降位置"
},
"结束部署(赛前部署动作)": {
"actor": "int,动作发出者",
"type": 333
},
"发送聊天信息": {
"actor": "int 动作发出者",
"type": 204,
"to_all": "0-发给队友,1-发给全部",
"msg_body": "custoum strings, up to 100 characters in Chinese and 50 words in English"
},
"发送辅助渲染信息":
{
"actor": "int 动作发出者",
"type": 205,
"msg_body": {
"hexs": ["六角格坐标"],
"graphic_type": "渲染模式,见下文",
"word": "渲染字符",
"color": "颜色,hex各式,#ffffff",
"description": "对于此命令的其他描述,字符串"
}
}
}
附录:观测状态json解释
"""
态势信息json格式
整理来源 https://wargame.ia.ac.cn/docs/reference/observations/
"""
observation =\
{
"actions": # 上一步接收到的动作
[
{
"cur_step": "int, 当前步长",
"message": "dict, 动作信息",
"error": {
"code": "int, 错误码 int",
"message": "str, 错误原因"
}
}
],
"cities": # 各个夺控点的信息
[
{
"coord": "int, 坐标",
"value": "int, 分值",
"flag": "int, 阵营 0-红 1-蓝",
"name": "str, 名称 str"
}
],
"communication": # 通信相关信息
[
# 进攻任务信息
{
"actor": "int 动作发出者席位",
"type": 207,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
# 防御任务
{
"actor": "int 动作发出者席位",
"type": 208,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
# 侦察任务
{
"actor": "int 动作发出者席位",
"type": 209,
"seat": "命令接收人id",
"hex": "任务目标位置",
"radius": "侦察半径",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
# 集结任务
{
"actor": "int 动作发出者席位",
"type": 210,
"seat": "命令接收人id",
"hex": "任务目标位置",
"start_time": "起始时间",
"end_time": "结束时间",
"unit_ids": "执行任务的单位ID列表",
"route": "执行此任务的途径点列表"
},
# 聊天信息
{
"actor": "int, 本方营长的席位id",
"type": "int, 204",
"receive_step": "int, 接收时的步数",
"to_all": "int, 0-对队友发出,1-对所有人发出",
"msg_body": "str",
"msg_id": "int, 此消息的id"
},
# 渲染信息
{
"actor": "int 动作放出者",
"type": "int, 205",
"msg_id": "int, 此消息的id",
"receive_step": "int, 接收时的步数",
"to_all": "int, 0-对队友发出,1-对所有人发出",
"msg_body": {
"hexs": "list[int], 要渲染的六角格坐标",
"graphic_type": "str, 渲染类型",
"word": "str, 渲染字符",
"color": "str, 颜色",
"description": "str, 对于此命令的其他描述"
}
}
],
"jm_points": # 间瞄点信息
[
{
"obj_id": "int, 攻击算子ID",
"weapon_id": "int, 攻击武器ID",
"pos": "int, 位置",
"status": "int, 当前状态 0-正在飞行 1-正在爆炸 2-无效",
"fly_time": "int, 已飞行时间",
"boom_time": "int, 已爆炸时间"
}
],
"judge_info": # 裁决信息
[
# 直瞄射击类型
{
"att_level": "int, 攻击等级 ",
"att_obj_blood": "int, 攻击算子血量",
"att_obj_id": "int, 攻击算子ID",
"attack_color": "int, 攻击算子颜色",
"attack_sub_type": "int, 攻击算子类型",
"cur_step": "int, 当前步长",
"damage": "int, 最终战损",
"distance": "int, 距离",
"ele_diff": "int, 高差等级",
"ori_damage": "int, 原始战损",
"random1": "int, 随机数1",
"random2": "int, 随机数2",
"random2_rect": "int, 随机数2修正值",
"rect_damage": "int, 战损修正值",
"target_color": "int, 目标颜色",
"target_obj_id": "int, 目标id",
"target_sub_type": "int, 目标类型",
"type": "str, 直瞄射击",
"wp_id": "int, 武器ID int"
},
# 间瞄射击类型
{
"align_status": "int, 较射类型 0-无较射 1-格内较射 2-目标较射",
"att_obj_blood": "int, 攻击算子血量",
"att_obj_id": "int, 攻击算子ID",
"attack_color": "int, 攻击算子颜色",
"attack_sub_type": "int, 攻击算子类型",
"cur_step": "int, 当前步长",
"damage": "int, 最终战损",
"distance": "int, 距离",
"ori_damage": "int, 原始战损",
"ori_random2": "int, ",
"offset": "bool, 偏移 bool",
"random1": "int, 随机数1",
"random2": "int, 随机数2",
"random2_rect": "int, 随机数2修正值",
"rect_damage": "int, 战损修正值",
"target_color": "int, 目标颜色",
"target_obj_id": "int, 目标id",
"target_sub_type": "int, 目标类型",
"type": "str, 间瞄射击",
"wp_id": "int, 武器ID"
},
# 引导射击类型
{
"att_level": "int, 攻击等级",
"att_obj_blood": "int, 攻击算子血量",
"att_obj_id": "int, 攻击算子ID",
"attack_color": "int, 攻击算子颜色",
"attack_sub_type": "int, 攻击算子类型",
"cur_step": "int, 当前步长",
"damage": "int, 最终战损",
"distance": "int, 距离",
"ele_diff": "int, 高差等级",
"guide_obj_id": "int, 引导算子ID",
"ori_damage": "int, 原始战损",
"random1": "int, 随机数1",
"random2": "int, 随机数2",
"random2_rect": "int, 随机数2修正值",
"rect_damage": "int, 战损修正值",
"target_color": "int, 目标颜色",
"target_obj_id": "int, 目标id",
"target_sub_type": "int, 目标类型",
"type": "str, 引导射击",
"wp_id": "int, 武器ID",
},
# 雷场射击类型
{
"target_obj_id": "int, 目标算子id",
"target_color": "int, 目标颜色",
"target_type": "int, 目标类型",
"target_armor": "int, 目标护甲",
"original_damage_random_number": "int, 原始战损随机数",
"calibration_random_number": "int, 修正随机数",
"calibration_value": "int, 修正值",
"final_damage": "int, 最终战损",
"cur_step": "int, 当前步数",
"minefield_id": "int, 雷场id",
"minefield_hex": "int, 雷场位置",
"minefield_color": "int, 雷场颜色",
"type": "str, 雷场裁决"
}
],
"landmarks": # 地标信息,雷场,路障
{
"roadblocks": "list[int], 六角格坐标",
"minefields": [
{
"id": "int, 雷场id",
"name": "str, 雷场",
"hex": "int, 位置",
"color": "int, 颜色",
"creator": "int/None, 雷场创造者,None-想定自带雷场,int-算子创造雷场",
"roads": [
{
"id": "int, 通路id",
"creator": "int, 通路制造者,int-制造通路的算子id",
"direction": "int, 通路方向,0~5,0是正右侧,按逆时针递进",
"color": "int, 通路颜色",
"hex": "int, 通路位置"
}
]
}
]
},
"operators": # 算子信息
[
# "算子信息":
{
"obj_id": "int, 算子ID",
"color": "int, 算子阵营 0-红 1-蓝",
"type": "int, 算子类型 1-步兵 2-车辆 3-飞机 4-工事 5-战略支援算子",
"name": "str, 名称",
"sub_type": "int, 细分类型 坦克 0/ 战车1 / 人员2 / 炮兵3 / 无人战车4 / 无人机5 / 直升机6 / 巡飞弹7 / 运输直升机8 / 侦察型战车9 / 炮兵校射雷达车10 / 人员战斗工事11 / 车辆工事12 / 布雷车13 / 扫雷车14 / 防空高炮15 / 便携防空导弹排16 / 车载防空导弹车17 / 皮卡车18 / 天基侦察算子19 / 人员隐蔽工事20",
"basic_speed": "int, 基础速度 int km/h",
"armor": "int, 装甲类型 int 0-无装甲 1-轻型装甲 2-中型装甲 3-重型装甲 4-复合装甲",
"A1": "int, 是否有行进间射击能力",
"stack": "int, 是否堆叠",
"carry_weapon_ids": "list[int] 携带武器ID",
"remain_bullet_nums": "dict[int, int] 剩余弹药数 dict{弹药类型 int 0-非导弹, 100-重型导弹, 101-中型导弹, 102-小型导弹: 剩余弹药数 int}",
"remain_bullet_nums_bk": "dict[int, int] 敌对阵营看到的弹药数",
"guide_ability": "int, 是否有引导射击能力",
"value": "int, 分值",
"valid_passenger_types": "list[int], 可承载类型,代表可以装在的乘员sub_type",
"max_passenger_nums": "dict[int, int], 最大承载数",
"loading_capacity": "int, 车辆单位最大承载算子车班数",
"observe_distance": "list[int], 观察距离, 一维列表,代表此算子可以观察到各个sub_type算子的最大观察距离",
"move_state": "int, 机动状态 0-正常机动 1-行军 2-一级冲锋 3-二级冲锋 4-掩蔽 5-半速",
"cur_hex": "int, 四位当前坐标",
"cur_pos": "float, 当前格到下一格的百分比进度",
"speed": "int, 当前机动速度 格/s >0: 移动中, =0: 暂停或停止 int",
"move_to_stop_remain_time": "int, 机动转停止剩余时间 >0表示",
"can_to_move": "int, 是否可机动标志位.只在停止转换过程中用来判断是否可以继续机动.强制停止不能继续机动,正常停止可以继续机动. 0-否 1-是",
"flag_force_stop": "int, 是否被强制停止机动 0-否 1-是",
"stop": "int, 是否静止 0-否, 1-是",
"move_path": "list[int], 计划机动路径, 首个元素代表下一目标格",
"blood": "int, 当前血量",
"max_blood": "int, 最大血量",
"tire": "int, 疲劳等级 0-不疲劳 1-一级疲劳 2-二级疲劳",
"tire_accumulate_time": "int, 疲劳累积时间",
"keep": "int, 是否被压制",
"keep_remain_time": "int, 压制剩余时间",
"on_board": "int, 是否在车上",
"car": "int, 所属车辆ID",
"launcher": "int, 算子下车/发射后,记录所属发射器",
"passenger_ids": "list[int],乘客列表",
"launch_ids": "list[int],记录车辆发射单元列表",
"lose_control": "int, 算子是否失去控制(指无人车失去指挥)",
"alive_remain_time": "int, 巡飞弹剩余存活时间",
"get_on_remain_time": "float, 上车剩余时间",
"get_on_partner_id": "list[int], 车辆算子ID(本算子为上车算子) 或 待上车算子(本算子为车辆算子)",
"get_off_remain_time": "int,下车剩余时间",
"get_off_partner_id": "list[int], 车辆算子ID(本算子为待下车算子) 或 车上算子ID(本算子为车辆算子ID)",
"change_state_remain_time": "int, 切换状态剩余时间",
"target_state": "int, 状态转换过程中记录目标状态 int 0-正常机动 1-行军 2-一级冲锋 3-二级冲锋 4-掩蔽",
"weapon_cool_time": "int, 武器剩余冷却时间",
"weapon_unfold_time": "int, 武器锁定状态表示展开剩余时间, 武器展开状态下表示锁定剩余时间",
"weapon_unfold_state": "int, 武器状态 0-锁定 1-展开",
"see_enemy_bop_ids": "list[int], 观察敌方算子列表",
"owner": "int/str, 当前拥有此算子的玩家席位id",
"close_combat": "int, 当前算子是否在同格交战中",
"stationary_count": "int, 算子距离上次改变坐标的时间步长",
"forking": "int, 是否在解聚",
"forking_remain_time": "int, 解聚剩余时长",
"unioning": "int, 算子是否在聚合",
"unioning_remain_time": "int, 聚合剩余时间",
"unioning_partner": "int, 聚合对象算子id",
"unioining_role": "int, 1-聚合发起者,2-聚合被动者",
"altitude": "int, 算子当前高度",
"changing_altitude": "int, 是否在改变高度",
"changing_altitude_remain_time": "int, 改变高度剩余时间",
"target_altitude": "int, 目标高程",
"activating_radar": "int, 是否在开启炮兵校射雷达",
"activating_radar_remain_time": "int, 开启雷达剩余时间",
"radar_activated": "int, 雷达是否开启",
"in_fort": "int, 是否在工事中",
"fort": "int, 工事id",
"entering_fort": "int, 是否在进入工事",
"entering_fort_remain_time": "int, 进入工事剩余时间",
"entering_fort_partner": "list[int], 进入工事动作对象",
"exiting_fort": "int, 是否在离开工事",
"exiting_fort_remain_time": "int, 离开工事剩余时间",
"exiting_fort_partner": "list[int], 离开工事动作对象",
"fort_passengers": "list[int]工事中的算子",
"laying_mine": "int, 是否在布雷中",
"laying_mine_remain_time": "int, 布雷剩余时间",
"remaining_mine_count": "int, 剩余可布雷场数",
"laying_mine_target_pos": "int, 当前布雷目标点",
"observalbe_distance": "int, 此算子可被观察的基础距离"
},
# "敌方阵营的不可见信息或部分可见的信息":
{
"remain_bullet_nums": "剩余弹药数 dict{弹药类型 int 0-非导弹, 100-重型导弹, 101-中型导弹, 102-小型导弹: 剩余弹药数 int}",
"move_to_stop_remain_time": "机动转停止剩余时间 >0表示",
"can_to_move": "是否可机动标志位.只在停止转换过程中用来判断是否可以继续机动.强制停止不能继续机动,正常停止可以继续机动. 0-否 1-是",
"move_path": "计划机动路径 [int] 首个元素代表下一目标格,只能观察到敌方机动的下一格,不能观察到全部路径",
"tire_accumulate_time": "疲劳状态剩余时间 int",
"keep_remain_time": "压制状态剩余时间 int",
"launcher": "算子下车/发射后,记录所属发射器 int",
"passenger_ids": "乘客列表 [int]",
"launch_ids": "记录车辆发射单元列表 [int]",
"alive_remain_time": "巡飞弹剩余存活时间",
"get_on_remain_time": "上车剩余时间 float",
"get_off_remain_time": "下车剩余时间 float",
"weapon_unfold_time": "武器锁定状态表示展开剩余时间, 武器展开状态下表示锁定剩余时间 float",
"see_enemy_bop_ids": "观察敌方算子列表 list(int)",
"C2": "普通弹药数",
"C3": "剩余导弹数",
"target_state": "状态转换过程中记录目标状态 int 0-正常机动 1-行军 2-一级冲锋 3-二级冲锋 4-掩蔽",
},
# "敌方间瞄点信息":
{
"obj_id": "攻击算子ID int",
"weapon_id": "攻击武器ID int",
"fly_time": "剩余飞行时间 float",
"boom_time": "剩余爆炸时间 float"
}
],
"passengers": [], # 乘员信息
"role_and_grouping_info": # 玩家信息和编组信息
{
#席位0
0: {
"faction": "int 红为0,蓝为1",
"role": "int 分队为0,群队为1",
"operators": "list[int],拥有的算子id",
"user_id": "int",
"user_name": "str"
},
#席位1
1: {
"faction": "int, 红为0,蓝为1",
"role": "int, 分队为0,群队为1",
"operators": "list[int], 拥有的算子id",
"user_id": "int",
"user_name": "str"
},
2: {
"faction": "int, 红为0,蓝为1",
"role": "int, 分队为0,群队为1",
"operators": "list[int], 拥有的算子id",
"user_id": "int",
"user_name": "str"
}
},
"scenario_id": 0, # 想定ID
"scores": # 分数
{
"blue_attack": "int, 蓝方攻击得分",
"blue_occupy": "int, 蓝方夺控分",
"blue_remain": "int, 蓝方剩余得分",
"blue_reamin_max": "int, 蓝方最大剩余得分",
"blue_total": "int, 蓝方总分",
"blue_win": "int, 蓝方净胜分",
"red_attack": "int, 红方战斗得分",
"red_occupy": "int, 红方夺控分",
"red_remain": "int, 红方剩余算子分",
"red_reamin_max": "int, 红方最大剩余得分",
"red_total": "int, 红方总分",
"red_win": "int, 红方净胜分"
},
"terrain_id": 0, # 地图id
"time": # 时间信息
{
"cur_step": "int, 当前步长",
"tick": "int, 每次step会前进多少帧",
"max_time": "int, 最大帧数",
"max_step": "int, 最大步数,等于max_time/tick",
"stage": "int, 当前处于的阶段,0-环境配置阶段,1-部署阶段,2-正常推进阶段"
},
"valid_actions": # 当前态势下的可做动作信息
{
"算子ID": {
"1-机动": "null",
"2-射击": [
{
"target_obj_id": "目标ID int",
"weapon_id": "武器ID int",
"attack_level": "攻击等级 int"
}
],
"3-上车": [
{
"target_obj_id": "车辆ID int"
}
],
"4-下车": [
{
"target_obj_id": "乘客ID int"
}
],
"5-夺控": "null",
"6-切换状态": [
{
"target_state": "目标状态 0-正常机动 1-行军 2-一级冲锋 3-二级冲锋 4-掩蔽"
}
],
"7-移除压制": "null",
"8-间瞄": [
{
"weapon_id": "武器ID"
}
],
"9-引导射击": [
{
"guided_obj_id": "被引导算子ID int",
"target_obj_id": "目标算子ID",
"weapon_id": "武器ID int",
"attack_level": "攻击等级 int"
}
],
"10-停止机动": "null",
"11-武器锁定": "null",
"12-武器展开": "null",
"13-取消间瞄计划": "null",
"14-解聚": "null",
"15-聚合": [
{
"target_obj_id": "聚合对象ID int"
}
],
"16-改变高程": [
{
"target_altitude": "目标高程 int"
}
],
"17-开启炮兵校射雷达": "null",
"18-进入工事": [
{
"target_obj_id": "工事ID int"
}
],
"19-退出工事": [
{
"target_obj_id": "工事ID int"
}
],
"20-布雷": "null",
},
"如果是绿方态势中,会有绿方专属的valid_actions": {
"401-导演击杀算子": "null",
"402-导演布雷": "null",
"403-导演建造路障": "null",
"404-导演增加算子": "null"
}
}
}