C++ AI SDK 文档
1. 选手提交说明
选手必须的填写函数
play
当选手回合开始后,会执行一次 play 函数。选手需要在该函数中操控 client 完成一回合的决策、行动。
NOTE:完成所有的决策和操作后调用finish结束回合。
参数:
client:AI_Client&,参与游戏的 AI 类,在其中处理了数据的发送与接收。
选手可以填写的函数
选手可以填写以下函数,用于处理回合外,自己的陷阱被触发时的处理部分。这两个函数会在回合外,接收到陷阱触发/摧毁消息时被自动调用。
NOTE: 由于陷阱被触发后立刻摧毁,所以可以只填写一个。
参数:
trap:被触发的陷阱类型pos:被触发的位置
提交说明
使用如下指令,将ai_client.cpp, ai_client.h, main.cpp, Makefile, mapconf2.map, 文件夹jsoncpp,和所需的其他文件一同打包交至saiblo。你可以修改Makefile中对应的部分,以使用以下指令更方便的完成打包操作(我们在Makefile中给出了样例ai的打包命令示例):
2. AI_Client
代表游戏中的一个 AI,提供各种行动和信息查询接口。
2.1 构造函数
- 由地图文件构造:
map_config_path:char*,地图文件的路径,默认网站评测时是sdk文件夹下的mapconf2.map,本地评测时默认是逻辑源码文件夹下的mapconf2.map。 - 拷贝构造。
2.2 pos和node的转换
pos2node
参数:
p:const Pos&,待查点的坐标。
返回值:Node&,坐标 p 对应的地图节点。当坐标p不合法时,抛出runtime_error。
node2pos
参数:
n:const Node&,待查的地图节点。
返回值:Pos,节点 n 对应的坐标。
2.3 查询函数
get_state
返回值: 当前的回合数
get_escape_pos
返回值:Pos,最终逃生点的坐标。
get_spawn_pos
参数:
num:int,待查玩家的 ID(0/1/2/3).
返回值:Pos,ID 为 num 的玩家的出生点坐标。
get_player_pos
返回值:Pos,玩家当前的坐标。
get_others_pos
参数:
id:int,待查玩家的 ID.
返回值:Pos,ID 为 id 的玩家的当前坐标。
注:当前玩家的坐标请使用 get_player_pos 获取。
get_player_hp
返回值:int,玩家当前的血量。
get_others_hp
参数:
id:int,待查玩家的 ID.
返回值:int,ID 为 id 的玩家的当前血量。
注:当前玩家的血量请使用 get_player_hp 获取。
get_neighbors
参数:
p:const Pos&,待查点的坐标。consider_elevator:bool,电梯连通性,true表示考虑上下层相连,默认为false.
返回值:std::vector<Pos>,与坐标 p 相邻节点的坐标列表。
注:仅返回可达点的坐标,即相邻且未被缩圈的点。
find_shortest_path
参数:
s:const Pos&,路径起点坐标。t:const Pos&,路径终点坐标。
返回值:std::vector<Pos>,起点 s 到终点 t 的一条最短路径,列表中的坐标按从 s 到 t 顺序排列。
复杂度:线性。
注:若 s 与 t 不连通,则返回空 std::vector.
get_check_cd
返回值:int,探查行动的技能冷却剩余回合数。
get_tools
get_keys
返回值:std::vector<int>,玩家持有的钥匙列表。
get_others_keys
参数:
id:int,待查玩家的 ID.
返回值:std::vector<int>,ID 为 id 的玩家持有的钥匙列表。
注:当前玩家持有的钥匙请使用 get_keys 获取。
get_id
返回值:int,当前玩家的 ID.
judge_if_can_pick
参数:
n:const Node&,待查的地图节点。
返回值:std::pair<bool, std::vector<std::string>>>,若该节点上有物品可拾取,则 .first 为 true;.second 表示物品信息,包含:
"Materials":物资点。"Box":玩家死亡后的掉落物。- 两个都无则vector为空
2.4 进行操作
move
参数:
tar:const Pos&,目标位置的坐标,玩家移动一步,到达tar.
返回值:bool,若操作合法,则返回 true.
attack
参数:
pos:const Pos&,攻击的目标位置。playerid:int,对pos处 ID 为playerid的玩家发动攻击。
返回值:bool,若操作合法,则返回 true.
inspect_materials
拾取物资点中的物资。
参数:
type:const std::string&,要拾取物品的种类,合法取值为ToolType中的字符串:
返回值:若拾取成功,则返回 true.
inspect_box
拾取掉落物。
返回值:操作是否合法。
place_trap
参数:
type:const std::string&,在当前位置放置一个type类型的陷阱,type取值范围为:"LandMine":地雷"Sticky":粘弹(ToolType.Slime)
返回值:bool,若操作合法,则返回 true.
use_kit
使用一个医疗包。
返回值:bool,若操作合法,则返回 true.
detect
参数:
tar:const Pos&,要探查的坐标(合法的坐标与自己所在的坐标相邻,且不可跨层)。
返回值:bool,若发现陷阱,则将其摧毁,并返回 true。但如果该点处的陷阱是自己的,则不将其摧毁,但返回true。若未发现陷阱,则返回false。
注:若操作非法,则无任何效果,并抛出runtime_error异常。
get_key
与当前位置的钥匙机互动,下一回合将获得对应钥匙。
返回值:bool,若操作合法,则返回 true.
escape
进行逃离。
参数:
to_escape:为true表示进入逃生等待状态,为false表示中断逃生等待。
返回值:bool,若操作合法,则返回 true.
blink
参数:
target:Pos&,目标位置的坐标,玩家闪现一步距离(不可跨层闪现),到达target.
返回值:bool,若操作合法,则返回 true.
finish
结束本回合。
2.5 得到拷贝
get_player_copy
参数:
- id: 要得到的player的id,可以为自己
返回值:该player的拷贝值。
get_copy
得到一份完整的AI_Client的拷贝,并返回该拷贝对应的私有变量。
返回值:返回一个AI_Client的拷贝,和该拷贝中所有Player的指针列表。指针列表中按照id顺序,依次存放了该拷贝中,包括自己在内的所有玩家的Player实例。
Tips:修改pos2node的返回值中的信息可以修改当前AI_Client的节点信息。
2.6 主进程函数
run
用于回合制循环。
类型别名
Pos
坐标三元组 \((x, y, z)\).
Trapbag
key_type:陷阱类型:"LandMine":地雷"Sticky":粘弹mapped_type:二维数组,该类型陷阱道具的使用信息[0][]:大小为 \(1\) 的列表,剩余陷阱道具的数量。[1][]:大小为 \(1\) 的列表,已放置的陷阱道具的数量。[i][]:\(i > 1\),大小为 \(3\) 的列表,已放置陷阱道具的坐标 \([x, y, z]\).
Nodeset
三维数组,用于存储地图,三个维度依次对应 \(x, y, z\).
常量
LAYER
地图的层数。
INF
相较于游戏中所有可能出现的合法数值,等效于 \(+\infty\).
ToolType
// 道具类型
struct {
std::string LandMine = "LandMine"; // 地雷
std::string Slime = "Sticky"; // 粘弹,策划案中的官方名称为Slime,游戏逻辑中对应为Sticky
std::string MedKit = "Kit"; // 医疗包,官方名称为MedKit,逻辑中为Kit
std::string Blink ="Transport"; // 闪现,官方名称为Blink,逻辑中为Transport
} const ToolType;
InterpropsType
// 交互道具类型
struct {
std::string KeyMachine = "KeyMachine";
std::string Materials = "Materials";
std::string EscapeCapsule = "EscapeCapsule";
std::string Elevator = "Elevator";
std::string Box = "Box";
} const InterpropsType;
枚举量
STATUS
玩家的游戏状态。
ALIVE:存活DEAD:死亡ESCAPED:逃离成功SKIP:回合跳过(踩中粘弹,或者与钥匙机交互后)WAIT_FOR_ESCAPE:逃生等待状态AI_ERROR:ai错误
MapReaderStatus
读取地图时,表示当前数据段的类型。
NODE:节点EDGE:边MATERIAL:陷阱道具HMATERIAL:医疗包ELEVATOR:电梯BLOCK:功能区
结构体
Edge
struct Edge {
Pos stpos, edpos;
bool elevator_only;
Edge() = default;
Edge(const Pos& s, const Pos& t);
};
地图中的边。
stpos,edpos:Pos,起点、终点。elevator_only:bool,是否为用于电梯的虚边,默认为false.-
构造函数:
-
默认构造。
-
由端点构造:
s:const Pos&,起点坐标。t:const Pos&,终点坐标。
Node
struct Node {
Pos pos;
std::vector<int> playerid;
std::vector<std::string> interprops;
std::vector<Edge*> edges;
bool box = false;
bool has_materials = false;
int block_turn = INF;
bool able = true;
Node() = default;
Node(const Pos& p) : pos(p) {}
Node(const Node& another_node);
};
地图中的节点。
pos:Pos,节点的坐标。playerid:std::vector<int>,位于该节点的玩家 ID 列表。interprops:std::vector<std::string>,交互道具类型:"Materials":物资点"KeyMachine":钥匙机"EscapeCapsule": 逃生舱edges:std::vector<Edge*>,由该点出发的边的列表。box:bool,若该节点上有玩家死亡后的凋落物,则为true,默认为false.has_materials:bool,若该节点上有物资点,则为true,默认为false.block_turn:int,第block_turn回合时该节点将被缩圈,默认为INF.able:bool,若该节点已经被缩圈,则为false,默认为true.- 构造函数:
- 默认构造。
- 由坐标构造:
p:const Pos&,节点坐标。
- 拷贝构造。
Tool
一个玩家的所有道具。
kits_num:int,医疗包数量。 -blinks_num:int,闪现道具数量。trapbag:Trapbag,陷阱的物品栏。
Player
struct Player {
int hp = 200;
STATUS status = ALIVE;
int id = -1;
bool has_entered_escape_layer = false;
std::vector<int> keys;
Pos pos;
Tool toolbag;
Player() = default;
Player(const Player& another_player) = default;
};
玩家类。
hp:int,血量。status:STATUS,玩家的游戏状态。id:int,玩家的 ID.has_entered_escape_layer: 仅对于别的玩家有意义,对于自己是无意义的,表示是否曾经到达逃生舱那层。keys:std::vector<int>,持有钥匙的列表。pos:Pos,当前坐标。toolbag:Tool,持有的道具。- 构造函数:
- 默认构造。
- 拷贝构造。
Map
地图类。
nodeset:Nodeset,地图中节点的数组。edgeset:std::vector<Edge>,地图中边的数组,默认容量为 \(1000\).