blazefires 发表于 2020-6-20 13:26:15

[UP1.5]变量存取的最佳方式 指标、指针、阵列的使用

本帖最后由 newtonerdai 于 2020-7-25 17:08 编辑

前言:
由於UP1.5已将goal变量由40提高到512,因此我们可以用来创造最多512长度的阵列,不过我想240长度的阵列就已足够用来纪录240个单位的状态。(注意此范本并不是完整的,只是提供如何操作阵列的概念而已)


核心命令:
(up-set-indirect-goal)、(up-get-indirect-goal)
这2个命令即可用来对阵列进行存和取值的行为




(图片来自8楼,UserPatch 1.5 脚本编写参考)


应用:
今假设我有240兵需要DUC控制个别兵攻击敌人城墙,对每个兵进行道路是否被阻挡判断成功後,对该兵放一个30秒计时器也就是该兵需要自行攻击城墙30秒,且不能影响其他的兵。(所谓我的道路被挡住我就打墙,他的道路没被挡就不打墙,打墙的都需要至少打30秒钟的意思)

UP1.5未到来前,你需要240个计时器(1单位1个)观察是否已经打墙30秒,这根本就是不可能达成的事情。
现在,UP1.5降临了,它带来了阵列,此情况我们只需要1个计时器,就能观察个别兵是否至少打了城墙30秒


代码:
(defonst gl-pointer 1) ;定义一个指针,用以指向阵列中的每个元素
(defonst gl-timer 1) ;定义一个计时器,需要每秒执行一次

;先假设我要用array用来纪录第一个兵打墙的秒数,array就是第二个兵,一直到array为第240个兵
(defrule
      (true)
=>
      (set-goal gl-pointer 100) ;先将指针指向阵列首位置100编号,也就是array
      (enable-timer gl-timer 1) ;开启每秒计时器
      (disable-self)
)

;这边是DUC判断某编号兵是否应该攻击城墙,如果需要则设置其值为30,即array=30
(defrule
    (true) ;假设第一只兵需要打墙,须设置array=30时,即设定打墙30秒
=>
    (up-set-indirect-goal g: gl-pointer c: 30) ;设置指针指向array的值为30,等效於(set-goal 100 30)
    (up-modify-goal gl-pointer c:+ 1) ;将指针指向位置101,用来观察第二只兵
)
(defrule
    (true) ;再假设第二只兵又需要打墙,须设置array=30时,即设定打墙30秒
=>
    (up-set-indirect-goal g: gl-pointer c: 30) ;设置指针指向array的值为30,等效於(set-goal 101 30)
    (up-modify-goal gl-pointer c:+ 1) ;将指针指向位置102,用来观察第三只兵
)
(defrule
    (true) ;假设第三只兵不需要打墙,须设置array=0时,即设定打墙0秒
=>
    (up-set-indirect-goal g: gl-pointer c: 0) ;设置指针指向array的值为0,等效於(set-goal 102 0)
    (up-modify-goal gl-pointer c:+ 1) ;将指针指向位置103,用来观察第四只兵
)
;以上此3规则循环遍历全部240兵後,我们一定有某些值是30(需要打墙) 和 某些值是0(不需要打墙的)


结语:
从这里开始,我们用每秒计时器触发时,就对阵列值扣1,直到扣至0即代表打墙30秒了,即可对该兵取消打墙,而且每个兵都互不干扰,就好像分别对每个兵各放了一个独立计时器一样。
(补充:我也是受了某位资深AI编写者的启发,才发现原来帝国是能操作阵列的){:155:}

zbhcn 发表于 2020-6-20 15:27:58

受教了,但是阵列在哪?用在哪种情况?

blazefires 发表于 2020-6-20 16:52:21

本帖最后由 blazefires 于 2020-6-20 16:56 编辑

zbhcn 发表于 2020-6-20 15:27
受教了,但是阵列在哪?用在哪种情况?
up-set-indirect-goal 就是赋值
up-get-indirect-goal 就是取值

阵列应用非常广阿,用以纪录各个物件状态
比如4只羊移动,就开8长度阵列,分别纪录各自位置,再开启5秒计时器,之後就可查看各绵羊各自走了多少格子距离。

zbhcn 发表于 2020-6-20 22:22:47

blazefires 发表于 2020-6-20 16:52
up-set-indirect-goal 就是赋值
up-get-indirect-goal 就是取值



目前暂未接触到阵列,求教程

凌果 发表于 2020-6-21 02:08:57

本帖最后由 凌果 于 2020-6-21 04:29 编辑

似乎会占用不少goal变量,会造成冲突吗?
例如我前面已经有:
(defonst abc-goal 100)
(defrule
    (true)
=>
    (set-goal abc-goal 1)
    (disable-self)
)

(defrule
    (goal abc-goal 1)
=>
    (chat-to-all "ok")
)

然后又像1楼所说地写上:
(defonst gl-pointer 1)
(defonst gl-timer 1)

(defrule
    (true)
=>
    (set-goal gl-pointer 100)
    (enable-timer gl-timer 1)
    (disable-self)
)

(defrule
    (true)
=>
    (up-set-indirect-goal g: gl-pointer c: 30)
    (up-modify-goal gl-pointer c:+ 1)
)

这样一来是不是就无法得到(chat-to-all "ok")的结果了?因为100号goal的内容被改写成30?
做一个阵列需要占用大量的goal吧,应该是必须把阵列占用的与其它内容占用的区分开吧,那其它内容能用的goal好像就少了很多……

blazefires 发表于 2020-6-21 03:27:01

凌果 发表于 2020-6-21 02:08
似乎会占用不少goal变量,会造成冲突吗?
例如我前面已经有:
(defonst abc-goal 100)


是的,就是把goal100改成30了,但是goal也有很多替代方案,像是利用无用处的策略值sn或是flag取代掉一些开关型的goal变量

newtonerdai 发表于 2020-6-23 02:47:51

(补充@凌果 )从老外那里榨取(x)的知识点,关于如何拓展AI变量数目。

①用80多个过时(obsolete)的策略值(征服者里目标只有40个时,主要是用策略值的)
②用up-modify-flag和up-compare-flag来压缩大量的0/1型的目标。
③用超过10的无实质意义的group和group-flag来承载信息(?暂未确定是否可行)

反正如果冲突的话,就需要对目标变量做规划和压缩了。

newtonerdai 发表于 2020-6-23 03:03:15

非常不错的教程!
(建议好好排版,提高可读性。实在不行,如果你同意,我可以帮忙排)


补充这两个关键语句的脚本指南(出自UserPatch 1.5 脚本编写参考 - 2020.06.15)






其实一般对战时不会遇到需要240个单位同时去打墙的情况,40~80个就已经很多了。读者们不要被吓到(比如“竟然要花费我近一半的goal?!”)。

对于AI脚本来讲,0/1型(只有开和关两种状态)的变量会占用大量goal,这可以用6楼和7楼的方法,把这类0/1型的变量压缩到一两个flag里。AI脚本真正需要的是大量储存十进制数据的变量,这样我们可以用来做很多事情,比如做冒泡排序、缓存大量单位地图ID、缓存周围高低地形,或者像楼主这样的动作计时器……

blazefires 发表于 2020-6-23 14:00:05

newtonerdai 发表于 2020-6-23 03:03
非常不错的教程!
(建议好好排版,提高可读性。实在不行,如果你同意,我可以帮忙排)



谢谢你,排版麻烦了

wangzhen 发表于 2022-6-12 13:16:30

本帖最后由 wangzhen 于 2022-6-12 13:23 编辑

谢谢分享
是这样理解吗?
gl-value 数组名字
int 长度
size 100 留多少位计时数
index临时获取单位ID 100
index2临时获取计时数 200
index3 临时获取计时数 50
XX 30 设定计时数
(set-goal int 100)
(disable-self)
dis
(up-set-target-object search-local c:0)
(up-get-object-data object-data-id index)
保存数值
条件 数值在-2147483648到2147483647范围内
nor(up-compare-goal gl-value <= -2147483647)
   (up-compare-goal gl-value >= 2147483646)
(up-set-indirect-goal g: int g: index)
(up-modify-goal gl-value g:= int)
(up-modify-goal gl-value c:* size)留多少位计时数
(up-modify-goal index2 c:+ XX)设定计时数
(up-modify-goal gl-value g:+ index2) 加在一起
计时器到期
读取
条件 数值在-2147483648到2147483647范围内
nor(up-compare-goal gl-value <= -2147483647)
   (up-compare-goal gl-value >= 2147483646)
(up-modify-goal index2 g:= gl-value)
(up-modify-goal index2 g:z/ 100); 假设数值gl-value是11030除以100得到110
(up-modify-goal index3 g:= index2)
(up-modify-goal index3 c:* 100)
(up-modify-goal gl-value g:- index3)减去差值得到计时
页: [1]
查看完整版本: [UP1.5]变量存取的最佳方式 指标、指针、阵列的使用