常数和GOAL配合——AI编写的利器
相信学过编程语言的都清楚,在编程时,往往要用到许多变量,要给他们赋值。而帝国时代的AI语言中,同样也有变量(受到AI官方教程的影响,我喜欢把它叫常数,虽然他是可变的。以下还是叫做常数吧!)。那么,常数到底有什么作用呢?简单地说,常数的用处有以下几点:1.把常数作为条件的一部分,看成不成立。这一个用处的例子有很多,例如:
(defconst G_YES 1)
(defconst G_NO 0)
(defconst gold-on-map 13)
(defconst stone-on-map 14)
(defconst stone-mine 102)
(defconst gold-mine 66)
………………
(定义的前两个常量只是为了表示“是”和“不是”。而13、14等式表示GOAL的编号
然后,就是设置初始值:
(defrule
(true)
=>
(set-goal gold-on-map G_YES)
(set-goal stone-on-map G_YES)
(disable-self)
)
上面的语句等价于
(defrule
(true)
=>
(set-goal 13 1)
(set-goal 14 1)
(disable-self)
)
然后下面是判断语句:
(defrule
(cc-players-unit-type-count 0 gold-mine < 2)
=>
(set-goal gold-on-map G_NO)
(disable-self)
)
(defrule
(cc-players-unit-type-count 0 stone-mine < 2)
=>
(set-goal stone-on-map G_NO)
(disable-self)
)
上面的语句等价于
(defrule
(cc-players-unit-type-count 0 gold-mine < 2)
=>
(set-goal 13 0)
(disable-self)
)
(defrule
(cc-players-unit-type-count 0 stone-mine < 2)
=>
(set-goal 14 0)
(disable-self)
)
(以上的意思是,当盖亚的金矿数小于等于2的时候,就把GOAL编号为gold-on-map(也就是13)的值设为G_NO(也就是0)。当盖亚的石矿数小于等于二的时候,就把GOAL编号为stone-on-map(也就是14)的值设为G_NO(也就是0)
(如果有不了解GOAL的 请稍等,在本文最后将会提到)
如何利用这个常数呢?请看:
(defrule
(current-age == imperial-age)
(goal gold-on-map G_YES)
(goal stone-on-map G_YES)
=>
(set-strategic-number sn-food-gatherer-percentage 40)
(set-strategic-number sn-wood-gatherer-percentage 25)
(set-strategic-number sn-gold-gatherer-percentage 30)
(set-strategic-number sn-stone-gatherer-percentage 5)
(set-strategic-number sn-maximum-food-drop-distance 25)
(set-strategic-number sn-maximum-wood-drop-distance 25)
(set-strategic-number sn-maximum-gold-drop-distance 15)
(set-strategic-number sn-maximum-stone-drop-distance 15)
(disable-self)
)
(defrule
(current-age == imperial-age)
(goal gold-on-map G_NO)
(goal stone-on-map G_NO)
=>
(set-strategic-number sn-food-gatherer-percentage 50)
(set-strategic-number sn-wood-gatherer-percentage 50)
(set-strategic-number sn-gold-gatherer-percentage 0)
(set-strategic-number sn-stone-gatherer-percentage 0)
(disable-self)
)
看!常数就可以用来当条件了!当那个GOAL的值为XX时,就执行XX语句!
如果还有金子,村民们就40%采集食物,25%砍树,30%采金,5%采集石头。
如果没有金子,村民们就一半采集食物,一半砍树。
为什么我们不把
(goal gold-on-map G_NO)
换成
(cc-players-unit-type-count 0 gold-mine < 2)
呢?
因为这样一来,假设后来测试AI的时候,你发现小于2好像不好,要改成3。如果你是用后者的写法,你要把每一个这样的语句中的2换成3。而用前者的写法,只要把
(defrule
(cc-players-unit-type-count 0 gold-mine < 2)
=>
(set-goal gold-on-map G_NO)
(disable-self)
)
里面的2换成3就可以,只用改一个值!这就是常数的便利之处!
2.常数与随机数相结合(实际上也是用GOAL)。
这一点的意思可能很难讲清楚(我表达力不行),直接看代码!
; 定义常数
(defconst feudal-age-rush 1)
(defconst castle-age-rush 2)
; 首次演算:设置一个介于 1 到 100 之间的随机数。
(defrule
(true)
=>
(generate-random-number 100)
(disable-self)
)
; 由其结果决定战略
; 20% 机会进行封建时代快攻
; 80% 机会进行城堡时代快攻
(defrule
(random-number > 80)
=>
(set-goal 1 feudal-age-rush)
(disable-self)
)
(defrule
(random-number < 81)
=>
(set-goal 1 castle-age-rush)
(disable-self)
)
看了代码,你应该就明白了。这是用随机数来确定进行城堡RUSH还是封建RUSH,然后把GOAL 1 的值设为XX。
其实还有一点不知道大家想过没有,第一个例子中的:
(defconst stone-mine 102)
(defconst gold-mine 66)
102,就是石矿的数字代码,66就是金矿的数字代码!
也许你已经想到了!没错!我们可以定义某个没法用英文表示的单位!(说的糊里糊涂的)
例如:
(defconst man-hunter 122)
(defconst woman-hunter 216)
然后呢?我们可以这么写:
(defrule
(building-type-count-total mill == 1)
(or (unit-type-count man-hunter > 0)
(or (unit-type-count woman-hunter > 0) )
(can-build mill)
=>
(set-strategic-number sn-mill-max-distance 35)
(build mill)
(disable-self)
)
看吧!只要一开始先定义某个常数(为了方便名称应该要有点意义)的值为那个单位的ID,然后就可以用那个常数的名字代替那个单位的ID,这样你下次再看的时候,就不会因为忘记了那个数字ID的含义而到处找了!(各种建筑和单位的数字ID看这里:https://www.hawkaoe.net/bbs/thread-23845-1-1.html)
好吧,,下面我来详细讲解一下GOAL的用法。
大家有没有发现,我用常数很多都和GOAL结合了。的确,常数可以说是GOAL的亲密伙伴啊!!
那么,什么是GOAL呢?
通俗地说,GOAL就是一个个箱子,每个箱子都有一个编号。编号可以是1到40中的一个。每个箱子只能够放一个数。
GOAL语句有下面两个:
(set-goal GOAL的编号 要设的数)
(goal GOAL的编号 要检查的数)
上面两个语句第一个是一个动作,用处是把相应的GOAL的值设置为XX
第二个是一个条件 是检查一下那个GOAL的值是否为XX
打个比方 (set-goal a b)就相当于在编号是a的箱子里放一个b数。
(goal a b)就相当于去看一下编号是a的箱子里的数是不是b
其中a的要求是1到40 b的值大概没有要求(如果只是用于表示“是”或者“否”,一般为了方便都用0或1)
有的人可能要问了:那直接用数字不就行了么?为什么还要定义常数呢?那么麻烦!
举个例子吧,当你修改自己的AI,看到(set-goal 25 1)这一句话,你能记起来编号是25的GOAL用处是什么吗?记不得吧!
可是如果你看到(set-goal goal-resign yes) 这一句话,你就马上能够知道,这句话的意思是准备要投降啦!
可是你光这么写,AI可不认识他啊!怎么办呢?这就要用到常数啦!
(defconst goal-resign 25)
上面这句话用处可大了!有了它,AI就会把遇见的goal-resign都看做25来处理!同样地有了(defconst yes 1)这句话,AI就会把yes当做1处理了!
这么一来 你就可以用(set-goal goal-resign yes) 这句话了!
下面来讲一下实际的高级应用:
应用之一:看对方出什么兵,就把GOAL值改成一个数。例如:
(defconst enemy-soilder 1)
(defconst g-knight 1)
(defconst g-archer 2)
(defconst g-spear 3)
....
(defrule
(players-unit-type-count knight-line >= 8)
=>
(set-goal enemy-soilder g-knight)
)
(defrule
(players-unit-type-count archer-line >= 15)
=>
(set-goal enemy-soilder g-archer)
)
(defrule
(players-unit-type-count spearman-line >= 6)
=>
(set-goal enemy-soilder g-spear)
)
然后再根据GOAL的不同值来应对
(defrule
(goal enemy-soilder g-knight)
=>
(.......)
)
(defrule
(goal enemy-soilder g-archer)
=>
(.......)
)
(defrule
(goal enemy-soilder g-spear)
=>
(.......)
)
还可以把升级年代的时候把某个GOAL设为1,然后升完设置回去。然后写当常数为1就出兵或研究科技(怕不够食物或者黄金所以等到升级年代时候才出兵或研究科技。这里不再说了。
先写这么多 不懂就提问吧
[ 本帖最后由 老胡V1 于 2010-1-9 12:40 编辑 ] 寫的的太深奧了,看的不大懂 真是太强大了!:10: 看不懂…:35: :35: :35: :35: 建议你先看看AI教程,在下载中心有。看完后应该会对AI有不小的了解。只要看基础格式和简单命令就可以了,一些复杂的条件或命令可以慢慢理解,也不一定要背,需要时候看就行了。当然一些兵种 建筑 的英文最好记几个,尤其是常用的。另外TRAIN BUILD 这些也最好记住(记不住就怪了)。其实最好是自己编一个,这样理解更快,不必写得很好,能让自己理解那些语句的意思就行。也可以参考别人的AI,利用教程来弄懂别人的语句的意思,理解他人思路,会对自己有不小帮助。 24……上次发现有错就重新写了,谁知道一恢复就没掉了55555
只好重新写 可是思路已经回不来了
暂且写了这些 不懂就提问吧…… 上次用goal定义计时器,居然没有反应…… GOAL和定时器作用不太吧…只是条件。主要是用defconst,来用常数表示定时器,例如(enable-timer a 30) 嗯,知道是条件。但定义后拿那个名字来用发现游戏时没作用。所以我还是老老实实直接用数字了& - -
能把你的代码给我看下吗……
用计时器应该是这样的吧……
(仅供参考)
(defconst TIMER-ATTACK 2)
(defrule
(XXXX)
=>
(enable-timer TIMER-ATTACK 30)
(disable-self)
)
(defrule
(timer-triggered TIMER-ATTACK)
(XXXX)
=>
(attack-now)
(enable-timer TIMER-ATTACK 30)
) 我的就是这样。原代码已经改了,也不用发。可能是我后面什么地方用冲突了 注意一下吧 看看是不是重复使用了计时器……代码太长很容易出现这种情况 最好把用了的列个表 常量吧- -常数只限于数字............ 本帖最后由 粹纳帝国 于 2011-8-25 22:42 编辑
.
看看吧,大家都会支持你
static/image/common/sigline.gif
论坛群发软件 还好有点编程基础,慢慢琢磨吧 看不懂啊高人啊 还好,学过编程语言,看懂了。找时间练练
页:
[1]