条顿武士 发表于 2015-1-23 02:23:08

闪闪发光新时代——翔鹰1.4版 新AI效果示例(第二弹)




闪闪发光新时代 新AI效果示例(第二弹)



前言

本教程是介绍翔鹰帝王版所含的UserPatch 1.4环境下新增AI语句在自制战役中可以实现的种种新效果。为了能顺利阅读并理解本教程,您需要在阅读前参考几个相关帖子并学习一些关于AI和战役制作的基础知识:1、UserPatch1.3脚本编写参考2、战役制作新时代——翔鹰Z系列 新AI效果示例(第一弹)3、xyz新时代的开启,论帝国中的“变量至少各位需要了解AI的基础语句结构(While Do结构),即:(defrule
      (事实语句)
=>         
      (动作语句)
)
如果一上来就对AI失去了兴趣,不妨先玩一下这个存档,也是本教程所有效果的示例,相信在玩过之后,您会更加有兴趣来看这部教程:(gaz文件,放在1.4版本的存档文件夹内读取存档游戏)
接下来,让我们进入正题,看看AI中还有哪些比较实用的语句和跨时代意义的突破吧!


坐标点的读取和操作

UserPatch新增的AI语句中,有许多是针对坐标点的读取和操作而创建的,而相关的事实和动作也可以将坐标点与其他数据属性联系起来。由于新AI中引入了目标(goal)作为变量,所以在goal中储存的坐标点可以像变量一样被赋值和计算,在地图编辑器中只能指定为常量的坐标区域,在AI中也可以作为变量来使用。
与坐标有关的新增事实和动作大致如下:
up-add-point语法up-add-point (io)(goal)点1 (in)(goal)点2 类型操作符 (in)(op)值功能加或减两组表示点的目标对。给操作数赋负值表示减。通过把目标点2设为0来使用up-set-target-point存储的点。示例1. 把焦点玩家和目标玩家所在位置相加。(defconst gl-point-x 100)(defconst gl-point-y 101)(defconst gl-other-x 200)(defconst gl-other-y 201)(defrule      (true)=>      (up-get-point position-focus gl-point-x)      (up-get-point position-target gl-other-x)      (up-add-point gl-point-x gl-other-x c: 1))

up-copy-point语法up-copy-point (out)(goal)点1 (in)(goal)点2功能把一组表示点的目标对复制给另一组目标对。示例1. 复制地图中心点位置。(defconst gl-point-x 100)(defconst gl-point-y 101)(defconst gl-other-x 200)(defconst gl-other-y 201)(defrule      (true)=>      (up-get-point position-center gl-point-x)      (up-copy-point gl-other-x gl-point-x))
up-cross-tiles语法up-cross-tiles (io)(goal)点1 (in)(goal)点2 类型操作符 (in)(op)网格数功能获取一个垂直于给定的两组表示点的目标对相连而成的直线的点。网格数为负值表示相减。把点2设置为0,以使用存储在up-set-target-point中的点。示例1. 获取相对于地图中心而言,主城镇中心右侧10格的点。(defconst gl-point-x 100)(defconst gl-point-y 101)(defconst gl-center-x 200)(defconst gl-center-y 201)(defrule      (true)=>      (up-get-point position-self gl-point-x)      (up-get-point position-center gl-center-x)      (up-cross-tiles gl-point-x gl-center-x c: 10))
up-find-flare语法up-find-flare (out)(goal)点功能获取同盟发送的闪光信号坐标,写入表示点的目标对中。命令会写入两个连续编号的命令对中,合法目标编号范围为41至510。如果获取失败,会返回(-1,-1)。命令等效于up-find-player-flare any-ally。示例1. 获取最新的同盟闪光信号位置。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (unit-type-count flare > 0) ; flare = 274=>      (up-find-flare gl-point-x))

up-find-player-flare语法up-find-player-flare (in)(player)玩家 (out)(goal)点功能获取任意可见的闪光信号,读取其位置到表示点的目标对中。命令会写入两个连续编号的命令对中,合法目标编号范围为41至510。如果获取失败,会返回(-1,-1)。示例1. 获取任意敌对玩家闪光信号位置。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (unit-type-count flare > 0) ; flare = 274=>      (up-find-player-flare any-enemy gl-point-x))
up-get-point语法up-get-point (in)(const)位置类型 (out)(goal)点功能读取特定的点坐标信息,存储到表示点的目标对中。命令会写入两个连续编号的命令对中,合法目标编号范围为41至510。如果获取失败,会返回(-1,-1)。示例1. 获取地图中心的位置。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (true)=>      (up-get-point position-center gl-point-x))2. 获取目标玩家的位置。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (true)=>      (up-get-point position-target gl-point-x))
up-get-point-distance语法up-get-point-distance (in)(goal)点1 (in)(goal)点2 (out)(goal)距离功能计算两点距离。把点2设为0,以使用up-set-target-point存储的点位置。示例1. 计算主城镇中心到地图中心的距离。(defconst gl-self-x 100)(defconst gl-self-y 101)(defconst gl-center-x 200)(defconst gl-center-y 201)(defconst gl-distance 300)(defrule      (true)=>      (up-get-point position-self gl-self-x)      (up-get-point position-center gl-center-x)      (up-get-point-distance gl-self-x gl-center-x gl-distance))
up-get-point-terrain语法up-get-point-terrain (in)(goal)点 (out)(goal)地形功能获取给定点的地形编号。把点设为0,以使用up-set-target-point存储的点位置。示例1. 获取地图中心的地形编号。(defconst gl-center-x 100)(defconst gl-center-y 101)(defconst gl-terrain 200)(defrule      (true)=>      (up-get-point position-center gl-center-x)      (up-get-point-terrain gl-center-x gl-terrain))
up-lerp-percent语法up-lerp-percent (io)(goal)点1 (in)(goal)点2 类型操作符 (in)(op)百分数功能计算两点之间的某个百分位点。设置百分数为负数会导致反向。设置点2为0以使用up-set-target-point存储的点。示例1. 计算主城镇中心到地图中心的25%分位点。(defconst gl-point-x 100)(defconst gl-point-y 101)(defconst gl-center-x 200)(defconst gl-center-y 201)(defrule      (true)=>      (up-get-point position-self gl-point-x)      (up-get-point position-center gl-center-x)      (up-lerp-percent gl-point-x gl-center-x c: 25))
up-lerp-tiles语法up-lerp-tiles (io)(goal)点1 (in)(goal)点2 类型操作符 (in)(op)网格数功能获取以点1为基准,沿点2方向偏移给定网格数位置的点。设置网格数为负数会导致反向。设置点2为0以使用up-set-target-point存储的点。示例1. 获取主城镇中心向地图中心方向偏移10格后所在的点。(defconst gl-point-x 100)(defconst gl-point-y 101)(defconst gl-center-x 200)(defconst gl-center-y 201)(defrule      (true)=>      (up-get-point position-self gl-point-x)      (up-get-point position-center gl-center-x)      (up-lerp-tiles gl-point-x gl-center-x c: 10))
up-send-flare语法up-send-flare (in)(goal)点功能在给定点处发送一个闪光信号。示例1. 在目标位置发送一个闪光信号。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (true)=>      (up-get-point position-target gl-point-x)      (up-send-flare gl-point-x))
up-set-target-point语法up-set-target-point (in)(goal)点功能设置目标点,供其他命令使用。示例1. 设置目标点为地图中心。(defconst gl-point-x 100)(defconst gl-point-y 101)(defrule      (true)=>      (up-get-point position-center gl-point-x)      (up-set-target-point gl-point-x))
up-point-contains语法up-point-contains (in)(goal)点 类型操作符 (in)(op)物件编号功能检查给定点处是否有给定物件存在。把点设为0,以使用up-set-target-point存储的点。示例1. 检查地图中心是否有树。(defconst gl-center-x 100)(defconst gl-center-y 101)(defrule      (true)=>      (up-get-point position-center gl-center-x))(defrule      (up-point-contains gl-center-x c: tree-class) ; tree-class = 915=>      (do-nothing))
up-point-distance语法up-point-distance (in)(goal)点1 (in)(goal)点2 比较运算符 (in)(op)值功能为两点之间的距离执行比较操作。把点2设为0,以使用up-set-target-point存储的点。示例1. 检查主城镇中心与地图中心的距离是否大于5。(defconst gl-self-x 100)(defconst gl-self-y 101)(defconst gl-center-x 200)(defconst gl-center-y 201)(defrule      (true)=>      (up-get-point position-self gl-self-x)      (up-get-point position-center gl-center-x))(defrule      (up-point-distance gl-self-x gl-center-x > 5)=>      (do-nothing))
up-point-terrain语法up-point-terrain (in)(goal)点 比较运算符 (in)(op)地形功能检查给定点所处的地形。把点设为0,以使用up-set-target-point存储的点。示例1. 检查地图中心点是否为草地地形。(defconst gl-center-x 100)(defconst gl-center-y 101)(defrule      (true)=>      (up-get-point position-center gl-center-x))(defrule      (up-point-terrain gl-center-x == terrain-grass)=>      (do-nothing))
up-send-scout语法up-send-scout (in)(const)编组类型 (in)(const)位置类型功能命令陆地或海上侦察单位到给定的位置去。示例1. 命令陆地侦察单位到地图对面去。(defrule      (true)=>      (up-send-scout group-type-land-explore scout-opposite)      (disable-self))



实际的AI编写中,我们经常用到另外一个动作来读取指定单位所处的坐标点,即第一弹中所介绍的:
(defconst position-object 12) ;定义常数,position-object对应的内部值为12。(defrule      (true)=>      (up-set-target-by-id c: 0) ;设置地图上ID为0的单位为要检测数据的单位。      (up-get-point position-object 100) ;将该单位的横纵坐标储存在编号为100和下一个(101)的目标对(goal)中。)
由于这里没有加入取消循环的动作语句(disable-self),所以在游戏开始后,AI会一直动态监测地图上ID为0的单位之坐标,并及时更新目标对中的储存数据。在得到坐标数据后,我们可以利用其他AI语句对目标对进行运算,从而获得更多的信息,例如两个单位坐标点之间的距离、一个坐标点周围的坐标点、两点组成的直线方程、过三点的圆的方程(平面解析几何弱项者请补课)等等…
示例:

狂熊(Kuang)和妮娔(Nick)是翔鹰众所周知的一对CP,他们曾经形影不离互相仰慕,在游戏中,狂熊和妮娔的距离为一格时,他们将发挥出爱的力量,个人能力增强;而一旦他们之间的距离稍稍远离,他们就会失去能力的加成,在帝国中要如何实现呢?
参见如下AI代码:
(defconst position-object 12) ;定义常数,position-object对应的内部值为12。(defconst gl-kuang-x 100) ;定义常数,gl-kuang-x和gl-kuang-y分别代表编号为100和101的目标。(defconst gl-kuang-y 101) (defconst gl-nick-x 200) ;定义常数,gl-nick-x和gl-nick-y分别代表编号为200和201的目标。(defconst gl-nick-y 201)(defconst gl-distance 300) ;定义常数,gl-distance用于储存距离。(defrule      (true)=>      (set-goal 1 0);给目标1赋值为0,代表狂熊和妮娔远离的状态(默认状态)。      (disable-self))(defrule      (true)=>      (up-set-target-by-id c: 0) ;设置地图上ID为0的狂熊为要检测数据的单位。      (up-get-point position-object gl-kuang-x) ;将横纵坐标储存在gl-kuang-x和gl-kuang-y中。      (up-set-target-by-id c: 1) ;设置地图上ID为1的妮娔为要检测数据的单位。      (up-get-point position-object gl-nick-x) ;将横纵坐标储存在gl-nick-x和gl-nick-y中。      (up-get-point-distance gl-kuang-x gl-nick-x gl-distance) ;计算狂熊和妮娔的距离,储存在gl-distance中。);上述规则一直在循环执行。(defrule      (goal 1 0) ;如果狂熊和妮娔是在远离的状态(默认状态)。      (up-compare-goal gl-distance < 2) ;如果狂熊和妮娔的距离小于2。=>      (chat-to-all "狂熊妮娔接近,能力上升!")       (cc-add-resource gold 1) ;作弊增加一单位黄金,在编辑器内检测黄金后用触发增加两人能力。      (set-goal 1 1) ;设定狂熊和妮娔是在接近的状态,防止此条循环一直进贡黄金。)(defrule      (goal 1 1);如果狂熊和妮娔是在接近的状态。      (up-compare-goal gl-distance >= 2) ;如果狂熊和妮娔的距离大于等于2。=>      (chat-to-all "狂熊妮娔远离,能力下降!")      (cc-add-resource wood 1) ;作弊增加一单位黄金,在编辑器内检测木材后用触发降低两人能力。      (set-goal 1 0) ;设定狂熊和妮娔是在远离的状态,防止此条循环一直进贡木材。)

实例效果:
这里的效果比较简单,在实际应用中可以考虑设计多个距离区间,实现“距离越近,能力越强”的效果。另外,这里给大家布置一个难度很高的思考题,有兴趣的同学可以尝试,成功实现后共享方法可以获得丰厚的耕战奖励:狂熊、智酱、日狮是翔鹰知名的三巨头,目前地图上玩家一控制着三只阿拉伯奴隶兵,分别代表狂熊、智酱、日狮。他们将协力对抗邪恶的Boss条顿武士。条顿武士的力量十分强大,三巨头必须要利用他们的三角力量才能战胜Boss。所谓三角力量,就是当Boss位于三人位置所围成的三角形之中时,三巨头的能力会大大增强;而在三角形之外时,三巨头的能力复原。请问在帝国中如何实现呢?
——————————————

闪光妙用

在去年九月份的某一次UserPatch版本更新中,制作团队专门为了一条新增的AI语句的优化而进行了版本变动,这条语句就是非常实用的up-retreat-to。
up-retreat-to
语法
up-retreat-to (in)(const)物件编号 类型操作符 (in)(op)单位编号
功能
命令给定类型的所有单位撤退到一个随机单位。
示例
1. 如果可能的话,命令所有骑士撤退到一个随机城堡。
(defrule
      (true)
=>
      (up-retreat-to castle c: knight-line)
      (disable-self)
)

单位撤退实际上就是变相的“指派目标”,但是其目的地不是一个给定的地点,而是一个类别中的随机单位。换个角度考虑,如果作为撤退目标的单位只有唯一的一种且只有一个,那么AI所做出的指派动作就是确定的。同时,这个单位如果是可以在AI中被建立的,并且我们知道其建立地点。那么结合上一部分的内容,我们便可以在AI中实现“指派单位到未知位置”的效果了。
那么,最优秀的目标单位是什么呢?对了,就是游戏中小地图左上角的闪光信号,地图编辑中的FLARE2,闪耀,单位ID是274。为什么说它是最优秀的目标单位呢?因为在AI中,我们有一条语句可以建立FLARE,这也是AI中唯一可以建立的单位:
up-send-flare
语法
up-send-flare (in)(goal)点
功能
在给定点处发送一个闪光信号。
示例
1. 在目标位置发送一个闪光信号。
(defconst gl-point-x 100)
(defconst gl-point-y 101)
(defrule
      (true)
=>
      (up-get-point position-target gl-point-x)
      (up-send-flare gl-point-x)
)
也就是说,当我们计算出一个点的横纵坐标,利用AI语句在此建立一个FLARE2,然后利用AI的retreat语句将单位撤离到FLARE2,就可以完成对未知点的指派目标了。所以,如果你想指派FFF团切入到狂熊和妮娔的中点位置阻隔他们的相见,用这个语句准没错。
不过,即使不通过AI玩家的FLARE,让玩家自己在地图上发送FLARE,由于这个单位的特殊性,也可以产生很神奇的效果。因为玩家在地图上发送信号其实是即时在任意位置建立单位,并且可以通过右上角的小喇叭控制接受信号的玩家,利用这些特点可以让对应玩家的AI乖乖听从指挥去往某个位置。
不过要提示一点,在地图编辑器里建立的闪耀是没有效果的,另外由于闪耀无法通过触发检测,所以在地图编辑器里的应用还是十分有限的。
示例:

玩家一可以在地图上通过发送闪光信号控制同盟的部队进攻敌人,并且可以通过输入数字指令来停止同盟动作。
这个代码十分简单:(defrule(unit-type-count 274 > 0) ;如果地图上ID为274的闪光信号大于0个=>(up-retreat-to 274 c: -1) ;所有单位撤退到闪光处(-1代表所有单位的编号)(enable-timer 1 3) ;激活定时器1,时间为3秒(disable-self))(defrule(timer-triggered 1) ;如果定时器1经过指定时间=>(up-retreat-to 274 c: -1) ;循环撤退(disable-timer 1) ;关闭定时器1(enable-timer 1 3) ;重新激活定时器1,时间为3秒)
(defrule(taunt-detected 1 1) ;检测到玩家输入数字1=>(acknowledge-taunt 1 1) ;注销玩家输入的数字1,以便循环输入(up-reset-unit c: -1) ; 停止玩家3所有单位)



效果显而易见,只不过由于撤退是循环的,而信号虽然会自动消除,但是会有五秒左右的持续时间,所以两次发信号的时间和距离最好有一定间隔。同时停止单位的指令也最好在信号彻底消除后输入。

——————————————

循环遍历

实际上AI一条规则就相当于编辑器内的一条触发,大家都知道如果是两个触发顺序排列,第一个触发执行完毕后激活第二个触发,两者之间是会有一秒钟的执行延迟的。AI也是一样,如果是一个规则中的动作执行完毕后,通过设定其他条件激活第二个规则,这时两者之间也会有同样的一秒延迟。甚至是一条规则的自循环也类似于循环触发,是一秒钟执行一次的。

例如:
(defrule      (true)=>      (chat-to-all "Hey!"))
实际上在运行游戏后,左下角的聊天框会一秒钟一次的弹出Hey! Hey! Hey! ……的聊天信息。但很多情况下,我们需要在瞬间内无延迟的完成某些动作,例如同时检测玩家多个资源的信息,同时检测许多点的地形信息,甚至是《帝国中的变量》里介绍到的二进制转化法,在以往,我们需要写出许多条规则同时执行,或者是在一条规则内把一个动作重复多次才能完成。然而在新AI语句中其实不必那么麻烦,通过一个动作,我们可以在AI内实现一条规则的瞬时循环:
up-jump-rule
语法
up-jump-rule (in)(const)规则差值
功能
在当前规则集合中前后跳转。使用本行动,你可以借助智能的跳过从而减少每次遍历的规则量,也可以借助循环增加规则量。
示例
1. 循环执行一条规则3次。
(defconst gl-value 100)
(defrule
      (true)
      =>
      (chat-local-to-self "Start")
      (set-goal gl-value 0)
      (disable-self)
)
(defrule
      (up-compare-goal gl-value < 3)
      =>
      (up-modify-goal gl-value c:+ 1)
      (up-jump-rule -1)
)其实一个规则就相当于编程语言中一个While Do但是AI语句中有个很致命的弱点,即规则不支持嵌套,也就是说在动作部分不支持出现第二个While Do结构,甚至是诸如if/else的选择结构。这导致我们无法实现多层循环和一些编程语言中可以实现的循环效果。
不过,AI语句中的事实部分可以使用(not (事实语句) )来判定相反情况,这如同1.4版触发中的条件,可以选择反向条件,大家可以查看一下新语句中的所有事实语句,其实有许多语句可以在循环中发挥更好的作用,例如up-point-contains
语法
up-point-contains (in)(goal)点 类型操作符 (in)(op)物件编号
功能
检查给定点处是否有给定物件存在。把点设为0,以使用up-set-target-point存储的点。
虽然有着种种障碍,但我们可以巧妙地利用mod(取余数)和z/(向下取整的整除)两个运算符来实现二重或者多重循环。代码如下(i、j、k代表循环变量,需要在使用前通过defconst定义,以下省略):(defrule
      (true)
=>
(set-goal i 1)
(set-goal j 0)
(set-goal k 0)
(disable-self)
)
(defrule
      (up-compare-goal i < 5)
      =>
      (up-modify-goal j c:mod 4)
      (up-modify-goal j c:+ 1)
      (up-modify-goal k g:= j)
      (up-modify-goal k c:z/ 4)
      (up-chat-data-to-all "i= %d." g: i)
      (up-chat-data-to-all "j= %d." g: j)
      (up-modify-goal i g:+ k)
      (up-jump-rule -1)
)执行后,可以在AI瞬时遍历到4X4区域内的16个坐标点:(1,1)(1,2)(1,3)(1,4)(2,1)……(4.3)(4,4)相关的运算比较复杂,其中c:后接符号,代表执行常数运算,例如(up-modify-goal j c:+ 1)便是把目标j内的数值加上常数1。而g:则代表目标之间的运算,例如(up-modify-goal i g:+ k)表示将i目标内的值与k目标内的值相加,详细请参考Up1.3编程指南内的数学运算符的讲解。这个双层循环可以在AI中实现冒泡排序的算法…另外,这里再给大家布置两个难度很高的思考题,有兴趣的同学可以尝试,成功实现后共享方法可以获得丰厚的耕战奖励:在草原中作战的英雄大肚在面对众多敌人时需要一个鼓舞士气的寄托,幸好小舞是和他一起在草原中冒险的,小舞的外形是一个农民,他只能建造一种建筑物“哨站”,而当大肚周围3X3的区域内存在小舞建造的哨站时,大肚的士气便会被鼓舞,可以继续和草原中的敌人作战并且能力大增,如果大肚周围3X3的区域内没有哨站,则大肚的士气和能力都会复原。小舞可能会根据战况,在草原的任意位置建立多个哨站来鼓舞士气,请问在帝国中如何实现这一效果?
皮卡、日师、狂熊、atila、条顿武士被称为鹰知五虎将。但他们在地图上冒险时经常会有不同程度的受伤,请设计一个数字触发,玩家输入指定数字时根据五位英雄剩余生命值由高到低排序并通过聊天功能显示出来(利用语句up-chat-data-to-all),并可以多次使用。例如输出:系统:五虎将生命值最高为120系统:五虎将生命值次高为100系统:五虎将生命值中值为70系统:五虎将生命偏下值为40系统:五虎将生命值最低为12

——————————————

玩家1辅助AI

在一般情况下,只有电脑玩家可以使用AI,在地图编辑器中即便给玩家1设置了AI,实际上玩家1也必须是人类玩家。不过喜欢AI的玩家可能知道,在我们测试对战AI时,可以在标准游戏中,可以通过把玩家1设置为AI的方法来以第一视角观看AI的行动。这时玩家1和AI相当于联机对战中的双控,AI可以控制玩家1的单位,并且可以对玩家1的单位进行检测和搜索,使得一些通过其他玩家AI无法检测的数值也可以被AI读取,AI的动作直接作用于玩家1的单位也让一些效果成为了可能。然而在实际应用中,我们不可能要求玩家在标准游戏中设置AI来运行我们制作的单人战役,这里就出现了一个更加方便的媒介:存档。存档可以保存各个玩家的AI,并且可以保存一部分通过AGE修改的单位数据,在存档中可以实现许多非常有新意的效果。再加上存档这个媒介相对来说使用比较方便,对于战役传播来说并不构成太大影响,论坛也有诸如《罗宾汉的正义之弓》、《万岁法兰西》等精品存档战役,这个领域或许是代表创新型战役未来发展方向的新地标。本篇教程最后也会以存档战役的形式放上一个示例,集合了本篇教程中所有的示例效果,大家在看完教程后务必下载体验一下。
下面请看这两条语句:
(up-reset-building 0 c: lumber-camp)停止一类建筑的一些行动,包括训练和研究,这里指伐木场。(up-get-object-data object-data-order zhuangtai)获取目标物件的执行编号参数,并储存在名为zhuangtai的目标中。
这两个动作如果在玩家1是AI的情况下,可以对玩家1的建筑或者单位生效,将产生许多神奇的效果,例如在不改变所有权的情况下取消玩家1指定建筑的训练和研究、或是读取玩家1指定单位的执行状态,如巡逻、跟随、防御、修理、建造、打猎、进攻、招降……
示例:

创造三个技能:1、玩家在伐木场中研究双刃斧后,立刻取消研究并返还资源,同时发动名为“回复”的技能,使玩家1的所有单位回复指定生命。2、玩家1的英雄单位在使用Z键执行巡逻操作后,发动名为“暴走”的技能,增加玩家1英雄的移动速度。(军事单位的左下面板中的巡逻、跟随、保护三个指令可以被检测并用作技能发动按钮)。3、玩家1的英雄附近2X2区域内内有任意浅水地形时,发动技能“背水一战”,能力增强,在周围没有浅水地形时能力复原。
这里的实现方法比较复杂:
(defconst position-object 12)(defconst i 2)(defconst j 3)(defconst k 4)(defconst research-pending 2)(defconst gl-kuang-x 100)(defconst gl-kuang-y 101)(defconst gl-kuang1-x 200)(defconst gl-kuang1-y 201)(defconst dixing 202)(defconst zhuangtai 203)(defrule      (up-research-status c: 202 >= research-pending) ;双刃斧科技的编号是202,这里检测科技是否正在研发(用触发也可以实现)=>      (up-reset-building 0 c: lumber-camp) ;停止伐木场的研究      (cc-add-resource food 9999) ;作弊增加玩家1的食物9999,用于和触发联动,进贡回后增加生命)(defrule      (true)=>      (up-set-target-by-id c: 0)      (up-get-point position-object gl-kuang-x)      (up-modify-goal gl-kuang1-x g:= gl-kuang-x)      (up-modify-goal gl-kuang1-y g:= gl-kuang-y)      (up-get-object-data 6 zhuangtai) ;检测狂熊的执行动作编号(6),主要用于检测狂熊是否在巡逻)(defrule      (up-compare-goal zhuangtai == 711) ;巡逻的执行编号为711,如果狂熊在巡逻=>      (cc-add-resource wood 9999) ;作弊增加木材,用于触发联动增加速度)(defrule      (true)=>      (set-goal 1 0)      (disable-self))(defrule      (goal 1 0) ;默认状态重置一次参数的值=>      (set-goal i 1)      (set-goal j 0)      (set-goal k 0)      (set-goal 1 1))
(defrule      (up-compare-goal dixing != 1) ;如果储存地形参数的目标里的值不等于1(1即为浅水地形的代码)      (up-compare-goal i < 6) ;如果循环参数i小于6,用于横坐标遍历1到5,两个条件必须都满足才会执行循环      =>      (up-modify-goal gl-kuang1-x g:= gl-kuang-x) ;把狂熊的坐标复制一份给一个临时的变量      (up-modify-goal gl-kuang1-y g:= gl-kuang-y)      (up-modify-goal j c:mod 5)       (up-modify-goal j c:+ 1)       (up-modify-goal k g:= j)       (up-modify-goal k c:z/ 5)       (up-modify-goal gl-kuang1-x c:- 3) ;原始坐标-3+i,i从1变化到5,即可遍历“原始坐标-2到原始坐标+2”的范围      (up-modify-goal gl-kuang1-x g:+ i)      (up-modify-goal gl-kuang1-y c:- 3)      (up-modify-goal gl-kuang1-y g:+ j)            (up-get-point-terrain gl-kuang1-x dixing) ;检测该点的地形      (up-modify-goal i g:+ k)      (up-jump-rule -1) ;单条规则循环)(defrule      (goal 1 1)      (up-compare-goal i < 6) ;如果i没有循环到6,上面的循环就结束了,那么说明中途遇到了地形有水的部分=>      (cc-add-resource gold 1)      (up-modify-goal dixing g:= 0)            (set-goal 1 0) ;重新重置参数值)(defrule      (goal 1 1)      (up-compare-goal i >= 6) ;如果i循环到6上面的循环才结束,那么说明中没有途遇到地形有水的部分=>      (cc-add-resource stone 1)      (up-modify-goal dixing g:= 0)            (set-goal 1 0))



——————————————
本教程仅仅是新AI语句中的一小部分精华的采撷,致力于先把AI工具能够做到的效果挖掘到极限,至于实际在战役设计中如何运用,或者是否有最合适的运用,根据使用工具人的不同也会有不同的看法。不过在目前帝国战役设计的圈子内,甚至是国际上的设计者,也没有人如此深入的研究AI脚本的作用,这些新效果能不能为战役制作带来一个闪闪发光的新时代,就看大家的想象力和创造力了!
本教程中包含的语句PER文件下载:

本教程中使用的scx文件(直接运行会使部分功能失效,只用于查看触发设计):

【必玩】本教程的可玩示例(gaz文件,在1.4版本中读取存档即可):


见帖子顶部~~



条顿武士 发表于 2015-1-23 02:53:52

另外补充一道思考题:

在AI里用x点目标值兑换成x点黄金。语句如下:

(defrule
    (up-compare-goal x >= 64) ;如果x的值大于等于64,相当于拥有64最大生命值。
=>
    (cc-add-resource gold 64) ;电脑玩家作弊增加64黄金。
    (up-modify-goal x c:- 64) ;x的值减少64,下面的语句都是一样的,一直做到1。
)
(defrule
    (up-compare-goal x >= 32)
=>
    (cc-add-resource gold 32)
    (up-modify-goal x c:- 32)
)


(defrule
    (up-compare-goal x >= 16)
=>
    (cc-add-resource gold 16)
    (up-modify-goal x c:- 16)
)


(defrule
    (up-compare-goal x >= 8)
=>
    (cc-add-resource gold 8)
    (up-modify-goal x c:- 8)
)


(defrule
    (up-compare-goal x >= 4)
=>
    (cc-add-resource gold 4)
    (up-modify-goal x c:- 4)
)


(defrule
    (up-compare-goal x >= 2)
=>
    (cc-add-resource gold 2)
    (up-modify-goal x c:- 2)
)


(defrule
    (up-compare-goal x >= 1)
=>
    (cc-add-resource gold 1)
    (up-modify-goal x c:- 1)
)

现在利用循环语句up-jump-rule -1 ,把这个功能简化成一个规则来实现。

四个圈 发表于 2015-1-23 07:51:16

    看不懂。。。。      

春田一九零三 发表于 2015-1-23 11:43:26

{:155:}绝对是帝国战役的新纪元,期待作者们能用up做出更多奇妙的效果

Redapple 发表于 2015-1-23 12:28:29

2015纪元来了{:162:}!

小寒春风 发表于 2015-1-23 13:45:35

狂拽酷炫叼炸天,我只能这么说。{:149:}

莫奇D龍 发表于 2015-1-25 14:53:49

理解是...众多坐标能被导出为“资源变量”

这样一来,的确可以实现很多有趣的效果,例如雇佣兵、牧师技能系统(各种BUFF)

感觉弊端还是“ID角色”不能挂掉吧,不知能不能将 AI中的 X 设为变量从而根据游戏变化调出呢

AI不是太懂,理解有错误的请见谅,附加一句,AI是好东西!

JimannLee 发表于 2015-1-25 15:48:41

TT,这AI只能用于1.4版的吗?能不适用1.0c?

在1.4版做的战役,在1.0c能运行吗?

ilikemm 发表于 2015-1-27 01:07:35

{:384:}期待新奇好玩的战役出现啊

一窍不开 发表于 2015-3-26 09:07:27

沙发的思考题最简单,就由我来吧{:146:}
(defrule
        (up-compare-goal x >= 1)
=>
        (cc-add-resource gold 1)
        (up-modify-goal x c:- 1)
        (up-jump-rule -1)
)

一窍不开 发表于 2015-3-26 14:08:17

本帖最后由 一窍不通 于 2015-3-26 14:38 编辑

三巨头的思考题。(不知为何反应很迟钝,尤其是在三角形偏向细长的时候,难道是计算误差?)
--------------------------------------------
对了,要不要发个附件。。
--------------------------------------------
是我的问题-=只能在锐角三角形里用。。我去重写一个。。
--------------------------------------------
应该同时也有计算误差。。
--------------------------------------------
过两天再写吧。。用平面直角坐标系的话有些头疼-=
--------------------------------------------
不对,在锐角三角形里也用不了。。只不过精确些。。
(defconst position-object 12)
(defconst gl-kuangxiong-x 100)
(defconst gl-kuangxiong-y 101)
(defconst gl-zhijiang-x 200)
(defconst gl-zhijiang-y 201)
(defconst gl-rishi-x 300)
(defconst gl-rishi-y 301)
(defconst gl-tiaodun-x 400)
(defconst gl-tiaodun-y 401)
(defconst gl-distance-1 500)
(defconst gl-distance-2 501)
(defconst gl-distance-3 502)
(defconst gl-distance-4 503)
(defconst gl-distance-5 504)
(defconst gl-distance-6 505)
(defconst gl-distance-out1 506)
(defconst gl-distance-out2 507)
(defconst gl-distance-out3 508)
(defrule
      (true)
=>
      (set-goal 1 0)
      (disable-self)
)
(defrule
      (true)
=>
      (set-goal gl-distance-out1 0)
      (set-goal gl-distance-out2 0)
      (set-goal gl-distance-out3 0)
      (up-set-target-by-id c: 1)
      (up-get-point position-object gl-kuangxiong-x)
      (up-set-target-by-id c: 2)
      (up-get-point position-object gl-zhijiang-x)
      (up-set-target-by-id c: 3)
      (up-get-point position-object gl-rishi-x)
      (up-set-target-by-id c: 4)
      (up-get-point position-object gl-tiaodun-x)
      (up-get-point-distance gl-kuangxiong-x gl-zhijiang-x gl-distance-1)
      (up-get-point-distance gl-kuangxiong-x gl-rishi-x gl-distance-2)
      (up-get-point-distance gl-zhijiang-x gl-rishi-x gl-distance-3)
      (up-get-point-distance gl-tiaodun-x gl-kuangxiong-x gl-distance-4)
)
(defrule
      (true)
=>
      (up-get-point-distance gl-tiaodun-x gl-zhijiang-x gl-distance-5)
      (up-get-point-distance gl-tiaodun-x gl-rishi-x gl-distance-6)
      (up-modify-goal gl-distance-out1 g:+ gl-distance-1)
      (up-modify-goal gl-distance-out1 g:+ gl-distance-2)
      (up-modify-goal gl-distance-out2 g:+ gl-distance-2)
      (up-modify-goal gl-distance-out2 g:+ gl-distance-3)
      (up-modify-goal gl-distance-out3 g:+ gl-distance-1)
      (up-modify-goal gl-distance-out3 g:+ gl-distance-3)
      (up-modify-goal gl-distance-4 g:+ gl-distance-5)
      (up-modify-goal gl-distance-4 g:+ gl-distance-6)
)
(defrule
      (goal 1 0)
      (up-compare-goal gl-distance-4 g:< gl-distance-out1)
      (up-compare-goal gl-distance-4 g:< gl-distance-out2)
      (up-compare-goal gl-distance-4 g:< gl-distance-out3)
=>
      (chat-to-all "条顿武士进入三角阵,三巨头能力上升!")
      (cc-add-resource gold 1)
      (set-goal 1 1)
)
(defrule
      (goal 1 1)
      (up-compare-goal gl-distance-4 g:>= gl-distance-out1)
      (up-compare-goal gl-distance-4 g:>= gl-distance-out2)
      (up-compare-goal gl-distance-4 g:>= gl-distance-out3)
=>
      (chat-to-all "条顿武士脱离三角阵,三巨头能力还原!")
      (cc-add-resource wood 1)
      (set-goal 1 0)
)

条顿武士 发表于 2015-3-26 14:32:57

一窍不通 发表于 2015-3-26 14:08
三巨头的思考题。(不知为何反应很迟钝,尤其是在三角形偏向细长的时候,难道是计算误差?)
------ ...

刮目相看…

不过这个方法存在一些误判的可能。

这里使用的判别方法是任意一点到三角形三个顶点的距离之和大于三角形任意两边之和。

但是这种判别方法有例外,比如钝角三角形。

做一钝角等腰三角形ABC(顶点为A),以C为圆心AC长为半径作圆与BC交于D,在扇形ACD与三角形非重和部分(三角形内)取一点O,则OC大于AC,OA加OB大于AB,所以OA+OB+OC>AB+AC…

另外因为AI中只会保留整数,所以的确存在很大的误差。

本题目其实我也没有很好的解决方法,一窍不通童鞋能够提出一种思路并且能够测试成功已经十分不容易了,还是把耕战奖励给你吧,非常感谢。

条顿武士 发表于 2015-3-26 14:34:48

一窍不通 发表于 2015-3-26 14:08
三巨头的思考题。(不知为何反应很迟钝,尤其是在三角形偏向细长的时候,难道是计算误差?)
------ ...
啊,在我回复的时候你也发现锐角的问题了…

用坐标系写的话可能会用到直线方程,可能会涉及到比较复杂的运算。

不过一旦能够写出,你一定可以在其它问题上对于这些新AI语句运用自如了!

一窍不开 发表于 2015-3-27 04:38:41

英雄大肚思考题。有个小问题就是周围有地基也会提高士气。。不知可不可以。。(代码有点乱。。{:146:} )
(defconst position-object 12)
(defconst gl-dadu-x 100)
(defconst gl-dadu-y 101)
(defconst c 110)
(defconst d 111)
(defconst e 112)
(defconst f 113)
(defrule
      (true)
=>
      (set-goal 1 0)
      (disable-self)
)
(defrule
      (true)
=>
      (set-goal c 1)
      (set-goal d 0)
      (set-goal e 0)
      (set-goal f 0)
      (up-set-target-by-id c: 2)
      (up-get-point position-object gl-dadu-x)
      (up-modify-goal gl-dadu-x c:- 1)
      (up-modify-goal gl-dadu-y c:- 1)
)
(defrule
      (up-compare-goal c < 10)
      (not(up-point-contains gl-dadu-x c: 598))
=>
      (up-modify-goal gl-dadu-x c:+ 1)
      (up-modify-goal d g:= e)
      (up-modify-goal d c:z/ 2)
      (up-modify-goal gl-dadu-y g:+ d)
      (up-modify-goal d c:* 3)
      (up-modify-goal gl-dadu-x g:- d)
      (up-modify-goal c c:+ 1)
      (up-modify-goal e g:= c)
      (up-modify-goal e c:+ 2)
      (up-modify-goal e c:mod 3)
      (up-jump-rule -1)
)
(defrule
      (goal 1 0)
      (up-compare-goal c < 10)
=>
      (chat-to-all "士气被鼓舞,能力大增!")
      (cc-add-resource gold 1)
      (set-goal 1 1)
)
(defrule
      (goal 1 1)
      (up-compare-goal c >= 10)
=>
      (chat-to-all "士气和能力复原!")
      (cc-add-resource wood 1)
      (set-goal 1 0)
)

一窍不开 发表于 2015-3-27 05:17:27

本帖最后由 一窍不通 于 2015-3-27 05:18 编辑

五虎将思考题。除了代码长了点以外,应该没啥问题吧。。{:146:}亲自测试通过~
(defconst object-data-hitpoints 10)
(defconst hp1 100)
(defconst hp2 101)
(defconst hp3 110)
(defconst hp4 111)
(defconst hp5 112)
(defconst c 113)
(defrule
      (true)
=>
      (up-set-target-by-id c: 2)
      (up-get-object-data object-data-hitpoints hp1)
      (up-set-target-by-id c: 3)
      (up-get-object-data object-data-hitpoints hp2)
      (up-set-target-by-id c: 4)
      (up-get-object-data object-data-hitpoints hp3)
      (up-set-target-by-id c: 5)
      (up-get-object-data object-data-hitpoints hp4)
      (up-set-target-by-id c: 6)
      (up-get-object-data object-data-hitpoints hp5)
)
(defrule
      (up-compare-goal hp2 g:> hp1)
=>
      (up-modify-goal c g:= hp2)
      (up-modify-goal hp2 g:= hp1)
      (up-modify-goal hp1 g:= c)
)
(defrule
      (up-compare-goal hp3 g:> hp1)
=>
      (up-modify-goal c g:= hp3)
      (up-modify-goal hp3 g:= hp1)
      (up-modify-goal hp1 g:= c)
)
(defrule
      (up-compare-goal hp4 g:> hp1)
=>
      (up-modify-goal c g:= hp4)
      (up-modify-goal hp4 g:= hp1)
      (up-modify-goal hp1 g:= c)
)
(defrule
      (up-compare-goal hp5 g:> hp1)
=>
      (up-modify-goal c g:= hp5)
      (up-modify-goal hp5 g:= hp1)
      (up-modify-goal hp1 g:= c)
)
(defrule
      (up-compare-goal hp3 g:> hp2)
=>
      (up-modify-goal c g:= hp3)
      (up-modify-goal hp3 g:= hp2)
      (up-modify-goal hp2 g:= c)
)
(defrule
      (up-compare-goal hp4 g:> hp2)
=>
      (up-modify-goal c g:= hp4)
      (up-modify-goal hp4 g:= hp2)
      (up-modify-goal hp2 g:= c)
)
(defrule
      (up-compare-goal hp5 g:> hp2)
=>
      (up-modify-goal c g:= hp5)
      (up-modify-goal hp5 g:= hp2)
      (up-modify-goal hp2 g:= c)
)
(defrule
      (up-compare-goal hp4 g:> hp3)
=>
      (up-modify-goal c g:= hp4)
      (up-modify-goal hp4 g:= hp3)
      (up-modify-goal hp3 g:= c)
)
(defrule
      (up-compare-goal hp5 g:> hp3)
=>
      (up-modify-goal c g:= hp5)
      (up-modify-goal hp5 g:= hp3)
      (up-modify-goal hp3 g:= c)
)
(defrule
      (up-compare-goal hp5 g:> hp4)
=>
      (up-modify-goal c g:= hp5)
      (up-modify-goal hp5 g:= hp4)
      (up-modify-goal hp4 g:= c)
)
(defrule
      (taunt-detected 1 1)
=>
      (up-chat-data-to-all "五虎将生命值最高为%d" g: hp1)
      (up-chat-data-to-all "五虎将生命值次高为%d" g: hp2)
      (up-chat-data-to-all "五虎将生命值中值为%d" g: hp3)
      (up-chat-data-to-all "五虎将生命偏下值为%d" g: hp4)
      (up-chat-data-to-all "五虎将生命值最低为%d" g: hp5)
      (acknowledge-taunt 1 1)
)

一窍不开 发表于 2015-3-27 17:07:40

一窍不通 发表于 2015-3-27 05:17
五虎将思考题。除了代码长了点以外,应该没啥问题吧。。亲自测试通过~

似乎没法用循环语句啊。。。能否教我下。。

末底改 发表于 2015-3-27 20:40:36

本帖最后由 末底改 于 2015-3-27 20:51 编辑

(defconst x 12)
(defconst x1 101)
(defconst y1 102)
(defconst x2 103)
(defconst y2 104)
(defconst x3 105)
(defconst y3 106)
(defconst x0 110)
(defconst y0 111)
(defconst t1 200)
(defconst t2 201)
(defconst t3 210)
(defconst mid1 300)
(defconst mid2 301)
(defconst mid3 302)
(defconst mid4 303)
(defconst mid5 304)
(defconst mid6 305)
(defconst ex 400)

(defrule
(true)
=>
(up-set-target-by-id c: 0)
(up-get-point x x1)
(up-set-target-by-id c: 1)
(up-get-point x x2)
(up-set-target-by-id c: 2)
(up-get-point x x3)
(up-set-target-by-id c: 3)
(up-get-point x x0)
) ;三巨头的id为0,1,2,条顿武士的id为3

(defrule
(up-compare-goal x1 g:> x2)
=>
(up-modify-goal ex g:= x2)
(up-modify-goal x2 g:= x1)
(up-modify-goal x1 g:= ex)
(up-modify-goal ex g:= y2)
(up-modify-goal y2 g:= y1)
(up-modify-goal y1 g:= ex)
)

(defrule
(up-compare-goal x1 g:> x3)
=>
(up-modify-goal ex g:= x3)
(up-modify-goal x3 g:= x1)
(up-modify-goal x1 g:= ex)
(up-modify-goal ex g:= y3)
(up-modify-goal y3 g:= y1)
(up-modify-goal y1 g:= ex)
)

(defrule
(up-compare-goal x2 g:> x3)
=>
(up-modify-goal ex g:= x3)
(up-modify-goal x3 g:= x2)
(up-modify-goal x2 g:= ex)
(up-modify-goal ex g:= y3)
(up-modify-goal y3 g:= y2)
(up-modify-goal y2 g:= ex)
) ;一般的排序,使x1在最左,x3在最右,才能进行下一步

(defrule
(true)
=>
(set-goal t1 0)
(set-goal t2 0)
)

(defrule
(true)
=>
(set-goal t3 0)
(disable-self)
)

(defrule
(true)
=>
(up-modify-goal mid1 g:= y0)
(up-modify-goal mid1 g:- y1)
(up-modify-goal mid2 g:= x0)
(up-modify-goal mid2 g:- x1)
(up-modify-goal mid1 g:/ mid2)
(up-modify-goal mid3 g:= y3)
(up-modify-goal mid3 g:- y1)
(up-modify-goal mid4 g:= x3)
(up-modify-goal mid4 g:- x1)
(up-modify-goal mid3 g:/ mid4)
(up-modify-goal mid5 g:= y2)
(up-modify-goal mid5 g:- y1)
(up-modify-goal mid6 g:= x2)
(up-modify-goal mid6 g:- x1)
(up-modify-goal mid5 g:/ mid6)
)

(defrule
(up-compare-goal mid1 g:>= mid3)
(up-compare-goal mid1 g:<= mid5)
=>
(set-goal t1 1)
)

(defrule
(up-compare-goal mid1 g:<= mid3)
(up-compare-goal mid1 g:>= mid5)
=>
(set-goal t1 1)
) ;运算:求(x0,y0)与(x1,y1)连线的斜率,并与过(x1,y1)的三角形两边斜率比较,如果是介于其中间,则满足条件1

(defrule
(true)
=>
(up-modify-goal mid1 g:= y0)
(up-modify-goal mid1 g:- y3)
(up-modify-goal mid2 g:= x0)
(up-modify-goal mid2 g:- x3)
(up-modify-goal mid1 g:/ mid2)
(up-modify-goal mid3 g:= y1)
(up-modify-goal mid3 g:- y3)
(up-modify-goal mid4 g:= x1)
(up-modify-goal mid4 g:- x3)
(up-modify-goal mid3 g:/ mid4)
(up-modify-goal mid5 g:= y2)
(up-modify-goal mid5 g:- y3)
(up-modify-goal mid6 g:= x2)
(up-modify-goal mid6 g:- x3)
(up-modify-goal mid5 g:/ mid6)
)

(defrule
(up-compare-goal mid1 g:>= mid3)
(up-compare-goal mid1 g:<= mid5)
=>
(set-goal t2 1)
)

(defrule
(up-compare-goal mid1 g:<= mid3)
(up-compare-goal mid1 g:>= mid5)
=>
(set-goal t2 1)
) ;运算:求(x0,y0)与(x3,y3)连线的斜率,并与过(x3,y3)的三角形两边斜率比较,如果是介于其中间,则满足条件2


尝试着写了一下三巨头的代码,比较冗杂,见笑了。


末底改 发表于 2015-3-27 20:52:57

本帖最后由 末底改 于 2015-3-27 21:25 编辑



(defrule
(goal t3 0)
(goal t1 1)
(goal t2 1)
=>
(set-goal t3 1)
(cc-add-resource gold 1)
(chat-to-all "三巨头力量提升")
) ;条件1,2同时满足,且三巨头能力尚未提升,则提升能力

(defrule
(goal t1 0)
(goal t3 1)
=>
(cc-add-resource wood 1)
(chat-to-all "三巨头力量恢复")
(set-goal t3 0)
)

(defrule
(goal t2 0)
(goal t3 1)
=>
(cc-add-resource wood 1)
(chat-to-all "三巨头力量恢复")
(set-goal t3 0)
) ;条件1,2有一个不满足,且三巨头能力已经提升,则恢复能力

似乎一个回帖内包含不了所有代码,所以再回复一个

效果附件:
页: [1]
查看完整版本: 闪闪发光新时代——翔鹰1.4版 新AI效果示例(第二弹)