
本教程为2019年新版教程的AI部分。
2019年新版教程包——
https://pan.baidu.com/s/1bP_gnDGGVScAZsfkJKezRA
j1jn
AI的艺♂术 - 2019年5月版AI教程
by Madman_M
前言 关于AI的一些常识
在折腾AI之前,首先要明确一点——Ra2这个游戏的AI非常残障,因此某种意义上来讲AI必须通过一定程度的作弊才能与玩家抗衡…… 写AI的目的,一方面是尽量让AI显得不那么残障,另一方面是限制AI的作弊程度,让AI的作弊变得不那么明显。
目录 (上半部分) 第一章 AI的设计思路 第二章 Rules(MD) 第三章 单位代码 (下半部分) 第四章 AI(MD) 第五章 地图相关
PLUS Ares平台下的AI骚操作
第一章 AI的设计思路
1.什么样的AI才是好的AI? 无脑暴兵摁死玩家的AI是屑,换着花样儿慢慢“折磨”玩家的AI才是AI之鉴。 而折磨玩家的目的也不在于摁死玩家,而是让玩家在反折磨和反推AI之后获得成就感。 当然,一堆AI三下五除二灭掉一个玩家还是合情合理的…… 2.AI应该怎样折磨玩家? (1)战术的多样化:AI可以玩骚扰,而且玩起来还挺6。只要给AI加上抢中立科技、工程师偷家、间谍断电偷钱之类的骚扰战术,玩家在与AI正面对抗的同时,就需要随时留意后方。这样一来处理难度会有很大提升。 (2)攻击形式的多样化:在调整了全局的条件下,AI的最大优势就是不差钱,不差钱带来的优势就是可以随时改变战术。在一波地面攻势之后,AI可以毫无压力地再出动一波空中攻势,而玩家此时很可能并没有做好防空的准备,应付起来就会手忙脚乱。 (3)兵种搭配的多样化:与(2)不同,兵种搭配是在一个部队内进行的,如反装甲单位和反步兵单位搭配、远程单位和近战单位搭配、地面单位和空中单位搭配,都可以起到很好的效果。如果有不同阵营的AI,还有可能出现几支需要玩家使用不同手段分别处理的部队同时杀向玩家的奇景,会给玩家造成很大压力。 (4)适当暴兵:就像玩家一样,暴兵也是AI不可或缺的战术。但是暴兵时需要控制数量。一方面是要让玩家能够处理,另一方面也要考虑AI的寻路能力。 3.怎样才能做出优秀的AI? 首先合理的全局设定是AI执行的前提。其次优秀的AI通常【应该】掌握一些基本操作: (1)工程师占中立或偷家。 (2)Rush和守家。 (3)间谍和反间谍。 (4)运输。 (5)扰矿。 (6)反特定建筑(如防御建筑和超武)。 (7)巷战和反巷战。 (8)海军。 (9)空袭。 总而言之,就是把自己能想到战术赋予AI,给AI制定一个具有多种可能性的剧本,并且通过代码让AI按照剧本发展,从而让AI表现得更像是有策略地进攻而不只是机械地出兵,是AI设计应该考虑的主要内容。
第二章 Rules(MD)
一套完整的AI,从来都不是只靠ai(md).ini一个文件来实现的。而是Rules设定、ai(md).ini以及单位代码共同作用的结果。 Rules对AI表现的影响非常大,会直接影响AI的出兵效率和发展水平。 以下是Rules中部分对AI产生影响的内容解释: (注释: num-数字、X,Y,Z-三个数字、bool-yes/no、list-列表) [General] ; computer and movement controls BaseBias=num ;当敌人靠近AI时,AI对敌人威胁的判定倍数,会影响AI对单位威胁值的敏锐度。可以调高。 BaseDefenseDelay=num ;AI派出防御部队处理基地威胁的延迟时间。(单位:分钟) CloseEnough=num ;AI执行"移动到"指令时,距离目的地多近就视为完成接近。 Stray=num ;一个小队在执行任务时,偏离这个距离之内时不会导致小队重组。可以适当增加以便AI可以使用大部队。 RelaxedStray=num ;执行"集结"指令(应该是指53,54号指令)时,以这个数值替代Stray。可以适当增加以便AI可以使用大部队。 TeamDelays=X,Y,Z ;(困难、中等、简单)的AI创造部队时间间隔。(单位:帧) AIHateDelays=X,Y,Z ;(困难、中等、简单)的AI选择敌人的时间间隔。(单位:帧) AIAlternateProductionCreditCutoff=num ;AI资金低于这个数值就不再花钱。 MultiplayerAICM=X,Y,Z ;(困难、中等、简单)的AI开局时的金钱【百分比】。公式为:AI开局金钱=玩家开局金钱*(X+100)/100。 AIVirtualPurifiers=X,Y,Z ;(困难、中等、简单)的AI获取资金的倍数。 AISlaveMinerNumber=X,Y,Z ;(困难、中等、简单)的AI的奴隶矿车数。 HarvestersPerRefinery=X,Y,Z ;三个阵营每个矿场的矿车数。 AIExtraRefineries=X,Y,Z ;(困难、中等、简单)的AI追加的矿场数。(Ares里的建议不给矿场加AIBuildCounts,如果需要增加矿场数量的话用AIExtraCounts) FillEarliestTeamProbability=X,Y,Z ;(困难、中等、简单)的AI制造第一个部队的时间。(单位:帧) MinimumAIDefensiveTeams=X,Y,Z ;(困难、中等、简单)的AI最少守家部队(IsBaseDefense=yes)数量。 MaximumAIDefensiveTeams=X,Y,Z ;(困难、中等、简单)的AI最多守家部队数量。(Min和Max即使都写0,0,0也会至少造1队守家部队) UseMinDefenseRule=bool ;AI在制造了满足MinimumAIDefensiveTeams数量的守家部队之后才开始制造其他小队。 ;UseMinDefenseRule=无论写啥AI都会至少先造1个守家部队,但是写no的话AI不会因为没有可造的守家部队而傻掉。所以如果UseMinDefenseRule=yes,要保证每个阵营【至少有一个】(不是只有一个!)可用的IsBaseDefense=yes的小队,否则AI不会出兵。 TotalAITeamCap=X,Y,Z ;(困难、中等、简单)的AI可以同时使用的部队总数。 DissolveUnfilledTeamDelay=num ;AI在多久后会解散一个不完整的部队。理论上不应降低,否则AI制造成员较多的部队时会在制造完毕之前就解散该队伍。(单位:帧) ;*** New AI type snippets *** AISafeDistance=num ;AI执行53号指令时的集结点与敌方基地的距离。 (Ares)AIFriendlyDistance=num ;AI执行54号指令时的集结点与己方基地的距离。默认=AISafeDistance AIMinorSuperReadyPercent=num ;AI使用次级超武的几率 AlliedBaseDefenseCounts=X,Y,Z SovietBaseDefenseCounts=X,Y,Z ThirdBaseDefenseCounts=X,Y,Z 三个阵营在(困难、中等、简单)时的防御建筑数量系数。计算公式:((已有建筑的价格-2000)/1500 * GDIBaseDefenseCoefficient) + 3*(该系数-1) AIPickWallDefensePercent=X,Y,Z ;(困难、中等、简单)的AI选择围墙来替代防御建筑的概率。 AIRestrictReplaceTime=num ;AI建筑被摧毁后,用电厂/防御建筑/围墙替代被摧毁建筑的时间。(单位:帧) ThreatPerOccupant=num ;每个驻军对可进驻建筑威胁值的提升。 GuardAreaTargetingDelay=num ;区域警戒(Area Guard)状态下AI搜索目标的延迟。 NormalTargetingDelay=num ;闲置状态下AI搜索目标的延迟。 DisabledDisguiseDetectionPercent=X,Y,Z ;(困难、中等、简单)的AI识破幻影的概率。 AISuperDefenseProbability=X,Y,Z ;(困难、中等、简单)的AI用护盾防御超武的概率。 AISuperDefenseFrames=num ;AI用护盾防御超武的延迟。(单位:帧) AISuperDefenseDistance=num ;基地的多少距离内是AI考虑使用护盾的范围。 ; AI trigger weighting parameters AITriggerSuccessWeightDelta=num ;触发成功权重变化值(可以写负值)。 AITriggerFailureWeightDelta=num ;触发失败权重变化值(通常是负值)。 AITriggerTrackRecordCoefficient=num ;触发权重变化系数(建议写1)。 ;负责[AITriggerTypes]中权重变化的三个数值。计算方法是每当AI的部队执行一次49号指令,就会在该AITrigger中增加AITriggerSuccessWeightDelta的权重。如果被消灭之前没能执行49号指令,则减少AITriggerFailureWeightDelta*AITriggerTrackRecordCoefficient的权重。 威胁值相关: ; default threat evaluation controls MyEffectivenessCoefficientDefault=num ;当AI的单位与威胁等级高于自身的目标交战时,会在计算威胁时乘以这个系数。帮助AI恃强凌弱。 TargetEffectivenessCoefficientDefault=num ;当AI的单位与威胁等级高于自身的目标交战时,会在计算威胁时乘以这个系数。防止AI以卵击石。 TargetSpecialThreatCoefficientDefault=num ;当AI目标具有SpecialThreatValue时,会在计算威胁时考虑这个系数。 TargetStrengthCoefficientDefault=num ;当AI的单位将目标指向生命比自己高的单位时,会根据敌方生命百分比考虑这个系数。 TargetDistanceCoefficientDefault=num ;当AI的单位选择目标时,会根据距离考虑这个系数。 ; defaults for dumb threat evaluation ;与default threat evaluation controls基本相同,但是适用于HasStupidGuardMode=yes的单位。 DumbMyEffectivenessCoefficient=num DumbTargetEffectivenessCoefficient=num DumbTargetSpecialThreatCoefficient=num DumbTargetStrengthCoefficient=num DumbTargetDistanceCoefficient=num EnemyHouseThreatBonus=num 以上数值都不是百分数,而官方给的数值却是按百分数填的。都除以100可能会获得较为明显的效果。 附:威胁值计算公式 float Threat = Attacker's best weapon's Verses against Defender * Target Effectiveness; if(Attacker is currently targeting Defender) { Threat = Threat * (-1);} float tempValue = Special Threat Value * Special Threat Coefficient; Threat = Threat + tempValue; if(Defender is currently considering Attacker's owner house as the Enemy House) {Threat = Threat + [General]→EnemyHouseThreatBonus=;} tempValue = Defender's best weapon's Verses against Attacker * Self Effectiveness; Threat = Threat + tempValue; tempValue = Target Strength * Attacker's current health percentage; Threat = Threat + tempValue; tempValue = Target Distance * Distance between Defender and Attacker; Threat = Threat + tempValue; Threat = Threat + 100000.0; 粗(JI)翻: Threat = 攻击单位武器对目标的Versus * TargetEffectiveness; 如果进攻者已经在攻击目标,Threat=Threat * (-1) tempValue = 单位的SpecialThreatValue * TargetSpecialThreatCoefficient; Threat = Threat + tempValue; 如果AI作为防御方把进攻者视为敌对方,Threat = Threat + EnemyHouseThreatBonus; tempValue = 防御方武器对进攻者的Versus * MyEffectiveness; Threat = Threat + tempValue; tempValue = TargetStrengthCoefficient * 攻击者当前的生命百分比; Threat = Threat + tempValue; tempValue = TargetDistanceCoefficient * 防御者和攻击者之间的距离; Threat = Threat + tempValue; Threat = Threat + 100000.0; [CombatDamage] Crush=num ;距离这么近时AI会尝试用碾压代替开火。写高点的话AI的车辆更容易直接碾压玩家步兵。 [AI] BuildConst=list ;基地列表(可以不是基地)。在Ares里,决定StartInMultiplayer.WithConst=true时开局给的【建筑】。 BuildPower=list ;电力建筑列表,每个阵营只能写一个。开局必然会先造一个,因此如果有给某个阵营使用昂贵电力插件作为电力供给的情况,请把兵营或其他开局就能造的建筑注册到电力列表里。 BuildRefinery=list ;矿场列表。 BuildBarracks=list ;兵营列表。 BuildTech=list ;高科列表。 BuildWeapons=list ;工厂列表。 BuildRadar=list ;雷达列表。 ConcreteWalls=list ;围墙列表。 BuildNavalYard=list ;船坞列表。 ;不弹框的最低要求是有基地(废话)、电厂,并且兵营和工厂没同时被禁(当然,这并不意味着AI真的能造,只要让AI以为自己能造就可以)。 AlliedBaseDefenses=list SovietBaseDefenses=list ThirdBaseDefenses=list AIForcePredictionFudge=X,Y,Z ;(困难、中等、简单)的AI根据敌方拥有单位的造价总和,按照此处数值的百分比选择防空,反装甲或反步兵的防御建筑。(数值越小越敏感) MaximumBaseDefenseValue=num ;AI防御建筑的威胁值总和(不包括防空建筑)。 ComputerBaseDefenseResponse=num ; 影响AI对基地和ToProtect单位的响应程度,具体效果未知。 PatrolScan=num ;AI执行巡逻任务时搜索敌人的时间。(单位:分钟) CreditReserve=num ;低于这个资金量时AI不再进行维修。 PathDelay=num ;堵车时间隔这么长时间再次尝试通过。(单位:分钟) BlockagePathDelay=num ;再次尝试隔这么长时间仍无法通过则绕路。(单位:帧) AutocreateTime=num ;平均间隔多长时间建造一队具有"Autocreate=yes"标签的小队。(单位:分钟) InfantryReserve=num ;AI拥有高于这个数值的金钱时将会一直建造步兵。 InfantryBaseMult=num ;如果AI当前建筑数量乘以此数值比步兵数量多,则一直制造步兵。 PowerSurplus=num ;AI电力超出临界不足这个数值时将会制造电厂。 BaseSizeAdd=num ;AI的基地规模不会大于玩家基地规模的这个倍数。 RefineryRatio=num RefineryLimit=num BarracksRatio=num BarracksLimit=num WarRatio=num WarLimit=num DefenseRatio=num DefenseLimit=num AARatio=num AALimit=num TeslaRatio=num TeslaLimit=num HelipadRatio=num HelipadLimit=num AirstripRatio=num ;由于Ra2里没有Airstrips,这个数值最好写0。 AirstripLimit=num ;同上。 ;各类建筑的建造比重和数量限制,各类Ratio总和不能低于1。 Paranoid=bool ;AI私下进行PY交易共同对抗玩家。 PowerEmergency=num ;砸锅卖铁保电量的电量临界值。(%) AIBaseSpacing=num ;AI建筑间隔距离,写0会无法正常摆建筑,稍微增大可以缓解AI堵车。 [IQ] ;一系列数字,通常结合地图中所属方的IQ设置生效。遭遇战中AI的IQ均为最大值。 MaxIQLevels=num ;IQ最大值。 SuperWeapons=num ;AI自动使用超武。 Production=num ;自动建造建筑物。 GuardArea=num ;新造出来的小队自动进入[Area Guard]状态。 RepairSell=num ;可以选择维修或变卖受损建筑。 AutoCrush=num ;自动碾压。 Scatter=num ;规避有弹道的抛射体。 ContentScan=num ;使[Easy]、[Normal]、[Difficult]项下的ContentScan生效。 Aircraft=num ;自动补充飞机。 Harvester=num ;自动补充矿车。 SellBack=num ;允许变卖建筑。 (ARES)TogglePower=num ;没电时让可断电建筑停止工作。 [Easy]、[Normal]、[Difficult] ;这仨的注册名称写!倒!了!Easy代表的是困难,Difficult代表的是简单。(然而里面的数值是正常的,WWSB!) ContentScan=bool ;AI使用运输单位时,会将运输工具及乘客的Points和ThreatPosed都考虑进去。写no或[IQ]此项不满足的话则只考虑运输工具自身的。 ; ******* Mission Control ******* ;一些状态(Mission)相关参数,决定特定情况下单位的行动模式。箱子单位状态可能与踩箱子的单位一致(待验证)。 [Harvest] ;FreeUnit的默认状态。 [Hunt] ;很重要的一个状态,伞兵和空投单位通常都是这个状态。 [Enter] ;会自动找寻可进驻建筑物,可进驻的伞兵有时会是这个状态。 Recruitable=bool ;是否允许重组,写yes的话,AI的小队在执行一些特殊指令后(主要为11号指令相关)就可以接受重组并加入到其他小队中去。 Rule部分其实比AI更复杂,对AI强度的影响也更明显。赋予AI合理的数值是AI能否正常执行AI(MD)中指令的前提。 Ares新增阵营和新增国家相关: 新增阵营和新增国家,AI最低要求是至少不弹框。而让AI不弹框需要注意以下几项: 1.[AI]中指定了新阵营的基地、电厂。 2.[新国家]中用AI.PowerPlants指明了且该电厂的AIBasePlanningSide正常。
第三章 单位代码
单位代码虽然也包含在Rules里,但由于不同种类单位情况各不相同,因此单独列为一章。
本章内容较少,仅列举一些特殊语句和单位。 通用: TechLevel=num ;AI可以建造TechLevel=-1的建筑,但是不能建造TechLevel=-1或大于最大TechLevel的单位。 的给各个可造单位安排合理的TechLevel可以让玩家的建造界面比较有层次感。(TechLevel=0可以用来调整建造界面单位顺序。) 拓展姿势:AI开局的建筑建造顺序: 经常玩无初始部队虐电1V7的小伙伴们肯定很熟悉AI的奇葩建造顺序——先憋矿场再造兵营,开局很容易被玩家工程师偷掉一两家。 电厂开局必然会先造一个。而决定兵营和矿场(目前测试结果来看也仅限兵营和矿场)建造顺序的,是兵营和矿场哪个TechLevel更小。 只要保证兵营的TechLevel小于矿场,AI就会先出兵营并且开始造守家部队,玩家速偷的战术成功率就会大大下降。 AI建造前提: 建筑: 无视:【TechLevel=-1】,PrerequisiteOverride,RequiresStolenAlliedTech,RequiresStolenSovietTech,RequiresStolenThirdTech,SpyEffect.StolenTechIndex(Ares) 有效:TechLevel,Prerequisite,Owner,AIBasePlanningSide,RequiredHouses,ForbiddenHouses ;如果建筑A的Prerequisite为建筑B且Owner/AIBasePlanningSide均正常,但是建筑B因为RequiredHouses/ForbiddenHouses无法建造,AI会认为建筑A可造,但是实际上无法建造建筑A,且不影响其他符合条件的建筑建造。 单位: 无视:Prerequisite,PrerequisiteOverride,Owner 有效:TechLevel,RequiredHouses,ForbiddenHouses,RequiresStolenAlliedTech,RequiresStolenSovietTech,RequiresStolenThirdTech,SpyEffect.StolenTechIndex(Ares) ;如果[TaskForces]里有无法建造的单位,则会跳过该项继续建造之后的单位。除非通过重组凑齐无法建造的单位,否则无法执行脚本。 ThreatPosed=num SpecialThreatValue=num 详见Rules中的威胁值部分,给单位安排合理的威胁值会影响到AI选择目标的优先顺序,关系到AI能否选择合适的目标进行攻击。 建筑: AIBasePlanningSide=num ;写阵营序号(0=GDI,1=Nod,2=ThirdSide,Ares新阵营依次往后排),标明第几个阵营会建造该建筑(写-1时所有阵营都可造)。 AIBuildThis=bool ;AI是否会建造该建筑。 (Ares)AIBuildCounts=X,Y,Z ;AI至少建造几个该建筑。 (Ares)AIExtraCounts=X,Y,Z ;AI可能额外补充几个该建筑。 AI在补足AIBuildCounts和AIExtraCounts数量时不是一股脑补足的,而是随机穿插建造(虽然也有可能一连造好几个)。 另:AI所有建筑的数量都会根据其拥有的基地数量而翻倍! 单位: ToProtect=bool ;写yes的单位受到攻击时,AI会出动守家部队去保护。原版海军都有这句,但海军加这个意义不大,除非给海军加守家部队…… 专属单位: RequiredHouses/ForbiddenHouses导致某个国家无法使用该阵营通用单位时,涉及该通用单位的[TaskForces]就需要每个国家单独设置。否则被禁用的国家在制造带有该单位时,会产生一支无法执行脚本的半成品小队。 武装直升机相关: 原版AI使用武直执行一切移动指令时,由于指令判定点为地面,而武直不会主动降落,因此会无限卡在移动指令的目标地点上空。想让AI的武直部署基本上只能在攻击指令之后衔接部署指令。 如果想让AI的武直执行移动指令,就需要给武直添加BalloonHover=yes语句。 给武直添加BalloonHover目前未发现任何负面效果,不但不影响部署落地,甚至BalloonHover自带的一定要飞目标头上拉翔的特技,在武直身上都不存在。 当然,做到这一步只能算初步解决了AI武直的移动问题和部署问题(这时的部署仅是个视觉效果)。除此之外还要面临一系列问题: 1.移动到路径点之后AI可能不会部署:经测试,AI可以正常完成移动至路径点的指令,只是无法在移动后部署。只要在移动和部署之间随便增加个容易完成的指令即可,比如5,0(非最优)。 2.部署之后立即起飞(甚至在部署状态就起飞,AI作弊实锤!):部署之后需要让AI执行防守指令,以免AI瞎起飞。(注:不能用11,11) 3.部署之后不开炮或开炮距离过近:再给武直加个与副武器射程等同的GuardRange即可。 综上,在给武直添加BalloonHover和GuardRange之后,再结合合理的指令,即可做到让AI批量部署武直。 还想让AI部署之后重新起飞?其实也是可行的,不过意义不大。AI的武直杵在地上当炮台才是坠吼的!至于方法,在AI(MD)部分里找吧。
PS:本教程可能随时根据测试结果进行更新,请以最后发布日期为准。
Madman_M 2019.05.01