Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AI概述 #25

Open
Babygogogo opened this issue Apr 13, 2017 · 0 comments
Open

AI概述 #25

Babygogogo opened this issue Apr 13, 2017 · 0 comments

Comments

@Babygogogo
Copy link
Owner

Babygogogo commented Apr 13, 2017

FreeWars AI设计概述

前言

设计AI不是一件简单的事情。由于个人能力有限,另外为了降低算法及运算复杂度,我决定让AI只对自己的各个部队单独进行分析,而不考虑互相之间的联防/卡位等问题。

AI的主要功能,实际上就是对部队可用的所有指令都进行评分,并选出最高分的那个指令加以实施。

部队可用的指令多种多样,但我们可以人为地把一个指令分成两个部分,分别是“站位”以及“行动”。举例而言:

  • 步兵移动到一个城市上进行占领,则“站位”就是该城市所在的位置,“行动”就是占领
  • 坦克移动到某个位置并攻击某敌军,则“站位”就是该位置,“行动”就是攻击
  • 自走火炮原地待机,则“站位”就是原地,“行动”就是待机

这样,对“站位”以及“行动”分别进行评分,并将评分直接相加,就是该指令的总分。对于一个部队,AI计算其所有可用指令的得分,并选出最高分的指令,这就是AI所认为的最好的指令。

除了部队指令,AI还需要考虑生产部队、释放技能等问题。这些同样是由评分所决定的,其公式将在后文详述。

另外,AI还需要考虑部队移动顺序,这同样在后文详述。

辅助参数、函数、运算符

辅助参数是在评分中会用到的一些参数,它们可以根据场上形势简单计算得到。

辅助函数、运算符是一些常用的小函数和符号,具体意义见下文。

参数:AI部队价值与玩家部队价值的比值(下称UnitValueRatio)

顾名思义, UnitValueRatio = AI所有部队的总价值(含队友的) / 玩家所有部队的总价值。计算总价时,部队的剩余HP考虑在内。

函数:min() max()

min()用于求出参数中最小的一项;max用于求出参数中最大的一项。

运算符

+-*/:加减乘除

^:幂运算,x^2就是x的平方

部队指令评分

概述

部队指令评分 = 站位评分 + 行动评分

通常情况下,部队会有多个可选的站位,每个站位上可能会有一个或多个的行动可选。比如,对于一个移动力为2的Mech,在地形无阻挡的情况下其可用的站位共有13个,在这些站位上根据地图实际情况又可能会有攻击、占领、待机、合流等行动可用。

为找出某个部队评分最高的指令,AI需要枚举每个站位计算站位评分,对于每个站位又需要枚举每个可用的行动计算行动评分,由此可以得出所有可用指令的评分,然后AI才能选出分数最高的指令并加以执行。

站位评分

站位评分 = 受威胁评分 + 维修补给评分 + 占用有生产力的据点的评分 + 与最近的非我方据点的距离的评分 + 与敌人部队的距离的评分

各项子评分见下文详述。

受威胁评分

此评分用于避免AI把部队无脑送给玩家。

受威胁的评判标准是:是否有玩家部队能够对AI部队造成50点或以上、或者是不足50但足以致死的伤害(考虑运气、HP、弹药、地形、技能、晋升、指挥塔、战局设定等各项加成,下同),不考虑玩家拆盾,不考虑玩家可能进行的维修、补给操作。这个标准会导致一些明显的问题:

  • AI的火箭车等高价的脆弱部队可能会直接暴露在玩家的INF、Bike攻击范围中
  • AI会把任意的盟友部队当成是无敌的盾,即使玩家可以轻易拆掉这个盾并对后面的部队造成威胁
  • 即使玩家只有一个AA,AI的两个或以上的BC也都会同时认为受到威胁
  • 如果玩家有个弹药耗尽的AA停在玩家城市上,AI会认为此AA不能造成威胁,而不考虑它在回合初会得到补给并造成威胁

简单起见,以上所有问题都被AI无视。

具体公式为:

  • 如果部队不受任何威胁,则受威胁评分 = 0;
  • 如果部队受到威胁,则受威胁评分 = -min(50, AI部队实际HP) * (2 + 部队原价 / 1000) / (max(1, UnitValueRatio) ^ 2)

此公式意味着,部队越贵,则受威胁时的评分越低(注意是负数);如果AI的部队总价值比玩家的要高,则评分会上升,意味着AI的部队优势越大,则AI的部队站位越不怕死。

维修补给评分

此评分用于引导AI对受伤及缺少弹药的部队进行回复。

AI只考虑使用据点对部队进行维修补给,不考虑使用Rig。

具体公式为:

  • 如果据点不能维修和补给部队,则评分 = 0
  • 如果能维修,则评分由三个子评分合计得到:
    • 回复HP评分 = (10 - 部队显示的HP) * 15
    • 回复弹药评分 = (部队最大弹药量 - 部队当前弹药量) / 部队最大弹药量 * 55 (若部队无主武器,则此项为0)
    • 回复燃料评分 = (部队最大燃料量 - 部队当前燃料量) / 部队最大燃料量 * 50 * 坠毁加成 (若部队耗尽燃料会坠毁,则加成值取2,否则取1)

此公式意味着,部队当前HP、弹药、燃料越少,则维修补给评分越高。

占用有生产力的据点的评分

此评分用于避免AI无故占用盟友或自己的工厂/机场/海港。

具体公式为:

  • 如果据点不属于盟友和AI自己,则评分 = 0
  • 如果属于,则:
    • 据点是工厂,则评分 = -500
    • 据点是机场,则评分 = -200
    • 据点是海港,则评分 = -150

此公式意味着,AI“很不乐意”占用盟友或自己的工厂,机场和海港次之。

与最近的非我方据点的距离的评分

此评分用于引导AI把部队向中立及玩家据点靠近。

为避免AI被特殊地形挡住而无法到达目的地,所以计算距离需要把地形考虑在内(不考虑玩家或AI部队的阻挡),这意味着计算量较大。为避免计算时间过长,我们人为地限定最大路径长度为max(10, 部队移动力),并枚举这个最大长度之内所有非AI方的据点计算其距离评分,取评分最高的一个作为本项最终评分。

距离评分公式为:

距离评分 = 与据点的距离 * -20 * 据点类型加成 * 据点所属势力加成 * 据点剩余占领点加成

其中:

  • 据点类型加成:当据点是工厂/机场/海港其中一种则取0.5,否则取1。这个设定是为了让AI更愿意靠近这几种据点。
  • 据点所属势力加成:当据点是中立时取0.5,否则取1。这个设定是为了让AI更愿意靠近中立据点,从而使得开局走法更合理。
  • 据点剩余占领点加成:当剩余占领点数为20(即无部队正在占领该据点)时取1,否则取2。这是为了让AI更愿意靠近“空闲”的据点。

由于搜索的路径长度有限,所以存在一种可能性,即搜索范围内一个非AI方的据点都没有。在这种情况下,本项最终评分 = (max(10, 部队移动力) + 1) * (-20 * 2)

与敌人部队的距离的评分

此评分用于引导AI把部队向玩家部队靠近。

由于计算量的限制,本项中的距离直接采用曼哈顿距离,无视地形减速和阻挡。考虑到玩家的部队一般不会站桩,而是也会向AI的部队靠近(而且玩家很自然地会选择正确的路线),所以无视地形计算距离造成的负面影响虽然存在,但勉强可以接受。

为避免玩家用一个部队就把AI的大部队勾引出去,这里的距离采用的是与玩家所有部队的平均距离。

具体公式为:

距离评分 = 与玩家所有部队的平均距离 * -10 (如果玩家一个部队都没有,则评分为0)

行动评分

部队可用的行动种类有很多,比如攻击、占领、待机、合流等等。AI并没有完成对所有行动的评分,没有评分的行动就相当于被禁用了。

以下详述目前已完成的行动评分。

攻击评分

此评分用于引导AI攻击最合适的目标。

AI会预估这次攻击会造成的攻击伤害(考虑了各种加成,包括运气伤害):

攻击伤害 = min(预估能造成的伤害, 目标的实际HP)

AI还会预估这次攻击会被造成的反击伤害(同样考虑各种加成以及运气伤害):

反击伤害 = min(预估会被造成的反击伤害, 自身的实际HP)

攻击评分建立在这两个预估的数值之上。由于存在运气因素,而且预估的运气伤害和实际的运气伤害不一定相同,所以存在AI预计能击破玩家部队但实际上剩余1HP的情况,或者是预计不会被反击致死,实际上却挂了的情况;这也是AI随机性的来源之一。

评分公式:

当目标是陨石时,攻击评分 = min(攻击伤害, 陨石剩余生命值)。

当目标是部队时:攻击评分 = 10 + 攻击伤害评分 + 目标占领加成 + 反击伤害评分

其中:

  • 攻击伤害评分 = 攻击伤害 * (2 + 目标原价 / 1000 + max(0, UnitValueRatio - 1)) + 击破加成(如果能击破则取值30,否则取值为0)
  • 目标占领加成取值方法:
    • 目标并非正在占领据点,则取值为0
    • 目标正在占领据点,且下一回合不能完成占领,则取值为20
    • 目标正在占领据点,且下回合能够完成,则取值为200
    • 若目标正在占领的是HQ/工厂/机场/海港,则取值额外增加99999
  • 反击伤害评分 = 反击伤害 * (2 + 自身原价 / 1000) + 被击破加成(如果会被反击击破则取值-20,否则取值为0)

这公式意味着,攻击伤害、目标价值、AI部队优势越大,评分越高;反击伤害、自身价值越大(反击伤害不为0时),评分越低。

(未完待续……欢迎留言评论,不必担心断楼)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant