AI 编写技巧指南

0 点赞
GLADIABOTS - AI Combat Arena
转载

本指南旨在帮助玩家应对编写AI代码时遇到的简单和复杂挑战。 编辑器 连接节点

连接两个节点时,最好将连接线绘制到目标节点的中心,而非开放的连接孔(见绿色箭头)。 按文件夹进行版本控制

保留机器人的旧版本非常有用,这样当你发现新机器人的表现似乎不如之前的机器人时就派上用场了。有时候好点子在实际应用中可能效果不佳。新机器人可能在带来一些新的好想法的同时也存在一些问题,因此将新机器人与旧机器人进行比较,有助于实现持续改进。 我发现保存机器人版本最简单的方法是,将与单个队伍相关的所有人工智能文件放入一个文件夹,然后只需复制该文件夹即可开始新版本。一旦旧版本完成,我就不再对其进行修改。如果发现错误,我会复制有问题的版本,然后在新的副本上进行修复。 如果你的代码从不引用文件夹外的人工智能文件,这将是一种非常简洁的版本保存方式。这种方法的主要缺点是会创建大量文件夹和文件,从而增加滚动和加载时间。 按文件进行版本控制 我发现自己通常每个版本只做一两个小改动,所以我基本不再按文件夹进行版本控制了。按文件进行版本控制是可行的,但必须对改动非常细致,否则很容易把新改动应用到旧版本中。 差异与优化

这两个条件并不相同。左侧示例的含义是【近距离范围内没有敌人】。右侧示例的含义是【至少有一个敌人不在近距离范围内】。细微差别

有些节点非常相似,但存在细微差别。《机器人大战:AI竞技场》玩家HenryChess最近提出了这样一个例子。正如Pege所指出的,它们极为相似,但并不完全相同。询问【自己】时,始终是“你一直在做什么”;而询问敌方机器人时,始终是“现在正在发生什么”。因此,如果你在最后一个时间步和当前时间步之间摧毁了一个你正在射击的机器人,左侧节点会判定为假,右侧节点会判定为真。玩家可以协同使用这两个节点来追踪机器人的击杀数(由于助攻和子弹飞行时间的影响,此指标存在一定误差)。 消除不必要的条件

通过消除逻辑中不必要的条件,可以节省节点。在此示例中,上方的代码包含多余条件。例如,只有携带资源的机器人才能丢弃资源或得分。请注意,移动条件永远无法达成,因为所有机器人类型都能进行中距离射击。 常见AI模式 使用主AI

即使你的机器人各不相同,为所有机器人设置一个主AI,让它向不同类型的机器人进行简单指令分配可能仍然有用。这样在队伍设置中分配AI会非常简单,因为只需分配这一个主AI,并且可以将其分配给所有机器人。 第一帧规划

在游戏开始时精确执行一次代码可能非常有用。我们可以通过检查是否还未经过任何时间来实现这一点。由于时间以秒为单位,此代码可能会运行4个滴答,因此我们希望只在第一个滴答运行。要做到这一点,我们可以检查机器人在上一个滴答是否处于空闲状态。这通常能确保代码精确执行一次。初始化代码应该是机器人运行的第一段代码,以确保其能正确执行。如果我们希望代码仅由第一个机器人执行一次,而不会被队伍中的其他机器人重复执行,我们可以检查所有友方单位是否都处于空闲状态,这通常只在第一个机器人的第一回合才会成立。 变量乘法

无法直接进行乘法运算,但有玩家(如computer-whispe2等)发现可以通过连续执行多次加法来实现,这类似于【 peasant multiplication】。要注意的是,节点只能执行一次,因此每次进行乘法运算时都需要复制这个子AI。这会导致额外节点数量大幅增加,所以请谨慎使用乘法功能。 此示例中,B的值可以取0到7之间的数字,C的值则基本可以是任意数字。如果想让B使用更大的值,只需按照1、2、4这样的2的幂次规律继续扩展(例如8、16、32等),直到能够满足所需的乘法规模。 固定乘法

如果你想将某个值乘以一个常数,可以使用更少的节点和计数器来实现。在这个示例中,我通过将计数器复制到计数器3,然后将其与自身相加(使其加倍),再加上计数器3,从而有效地实现了乘法运算。换种说法就是:3x = x + x + x 或者 3x = 2x + x。 Gladiabots玩家GameAg在官方Discord上提供了一份相当全面的文本文件,其中包含了从1到10000每个数字的乘法示例。 固定以2的幂次进行除法(右移)

与乘法类似,这里也没有除法运算。除法可以通过长除法来实现。对于2的幂次方,我们可以编写一个相当简单的固定除法程序。实现此过程的方法是查看最高位,将其减去,然后用相应的位替换。如果我们要除以2,就用4替换8,用2替换4,依此类推。如果要除以4,就用2替换8,用1替换4,依此类推。 变量除法

如果我们知道商的上限,可以使用二进制长除法来编写更通用的除法版本。此版本参考了《机器人大战:AI竞技场》玩家Computer-Whispe2的成果,通过扩展8、16、32等值的模式,能够处理更大的商。该解决方案的一个缺点是使用了较多变量(4个!),这可能最终会限制你的整体AI。 循环,随时间变化

在《机器人大擂台》中无法实现变量循环,但你可以随时间执行循环,并且机器人可以协作共同执行循环。通过这种方式,像变量除法这样的运算只需少量节点就能完成。在这个示例中,B是被除数,C是除数,A是商。停止条件是B小于A,此时B也代表余数。不应将创造力局限于除法这类数学运算。如果执行时长相对较短,许多算法的循环都可以通过这种方式来执行。 LatchEarly玩家发现,有时改变节点的执行顺序有助于减少所需条件的数量和节点的重复。随着游戏中计数器功能的加入,Bockwurst的视频大多已经过时,但这种技巧偶尔仍有用武之地。 条件分支选项

在我们的人工智能中,经常需要设置条件。许多编程语言都有If-Else结构。在《机器人大擂台》中,有几种不同的方式可以实现这一点。如果我们知道其中一个分支的条件所导致的结果,不会因后续分支的执行而产生错误行为,那么我们可以将该分支放在前面,而不必再设置“else”条件。在“隐式Else”示例中,如果狙击手在远距离没有目标,那么它在中距离也不可能有目标,因此无需额外条件。如果我们对此有所担心,可以像“显式Else”示例那样,为替代的“else”分支创建一个条件。在某些存在持续执行行为的场景中(例如标记或计数),我们需要一种方法来确保第一个分支的执行不会意外触发第二个分支。我们可以使用前面提到的锁存器来解决此问题。在满足第一个条件后,立即测试后续条件。这会导致后续条件失败,从而防止该路径在之后被执行。 标记计数方法 (本节内容正在完善中) 目前无法为敌方机器人等对象分配计数器,但我们可以通过标记组合来实现相同效果。通过组合使用团队标记或个体标记,我们基本上可以为任何实体创建计数器。 二进制计数器与格雷码 有两种常用的标签值编码方式:格雷码和二进制。格雷码最适合计数非常小的数字,或者不需要转换为数字的场景(例如,你需要计数,但只在数值为0时执行操作)。格雷码计数器。 使用标签制作单个计数器

如果只需要标记一个对象,可以使用更简单的方法。这会用到前面描述的锁存器。由于力场在某些模式下始终存在且很少被标记,因此在需要任意目标时,标记力场会很方便。 使用二进制一递增多个计数器时,可能需要标记多个实体并同时递增它们。 递增格雷码

格雷码非常容易递增。其设计特点是,每表示一个数值,只需改变其中一个标记。 从格雷码转换为计数器 格雷码直接计算起来有点困难,因此在使用前将其转换为计数器会很有用。这可以通过执行一系列异或操作来实现。 代码风格 保持一致的代码风格是提高代码可读性和可维护性的好方法。以下是关于保持代码清晰易懂的建议: 所有代码按行排列。 开始新行时,最中间的节点直接位于其父节点的正下方。 每行之间间隔一个网格方块。 所有节点都对齐到网格。 子节点始终位于其父节点下方的行中(通常低一行)。