浩气长存 发表于 2017-5-12 13:30:17

如何设置触发使得取消建造奇观(已有地基)后失败?

  问题如题。前不久翻旧邮件,找到个15年前上学时闲来无事花了两天时间胡乱做的一张战役地图,当年的即兴之作后来半途而废,上面只有可怜区区12个触发。
  这两天正好也是闲极无聊,就继续编辑这张图,目前触发数到了八九十个,但是还是没有找到解决当年设想的途径——如何像官方战役“征服者的战役”里面的利普顿海战那样,如果玩家已有奇观地基,一旦点击“取消建造”就导致失败。
  用战役管理器提取出利普顿地图查看,发现一个“we can't delete the wonder”触发,条件是AI信号6,结果是敌人宣告胜利。但是直接照搬复制后无效。这可能和战役AI有关?
  目前我就是要寻求如何实现这样,使得玩家的奇观不能被取消建造,所以在这里发帖求助诸位大能,希望不吝赐教。待地图完成后我会在这里发上来。

troytroytroy 发表于 2017-5-12 13:44:23

本帖最后由 tryotryotryo 于 2017-5-12 13:46 编辑

這觸發的意思就是它在AI裡寫了一條計算奇觀地基數量的語句,所以你要先把戰役的AI提出來並且找到那行語句,寫進你的戰役AI裡。
具體提出AI的方法要用aokts,你可以先蒐尋論壇一下。

troytroytroy 发表于 2017-5-12 13:50:41

https://www.hawkaoe.net/bbs/thread-116458-1-1.html

此帖四樓有導出戰役AI的方法。先導出AI找一下它產生信號6的語句位置,如果還是不懂晚點在上來問。

Oracle_Ameth 发表于 2017-5-12 14:02:34

建议楼主下载我在“人工智能”板块里发的建毁类战役专用AI编写教程,里面关于这个效果有做详细解释。

浩气长存 发表于 2017-5-12 14:48:07

tryotryotryo 发表于 2017-5-12 13:50
https://www.hawkaoe.net/bbs/thread-116458-1-1.html

此帖四樓有導出戰役AI的方法。先導出AI找一下它產 ...

首先感谢兄台指教。我刚用触发编辑器导出了官方利普顿战役电脑土耳其方所用AI,其中“AI信号6”代码如下:
;Lepanto scn6 player 2
; Turks

(load "scenario difficulty")

(defrule
        (game-time > 6)
        (cc-players-building-type-count 1 wonder < 1)
=>
        (set-strategic-number sn-special-attack-type1 276)
        (set-signal 6)
        (disable-self)
)
然后这玩意怎么用?摘出来保存成.per和.ai文件吗?再用触发编辑器导入进自编场景?
还有最上面的民族名“; Turks”,用的时候是不是要按自己设的电脑控制民族其中之一设,还是直接空缺?还请进一步指教。

Oracle_Ameth 发表于 2017-5-12 15:52:17

本帖最后由 Oracle_Ameth 于 2017-5-12 17:07 编辑

浩气长存 发表于 2017-5-12 14:48
首先感谢兄台指教。我刚用触发编辑器导出了官方利普顿战役电脑土耳其方所用AI,其中“AI信号6”代码如下 ...简单讲解一下,这段AI语句的大意是,检测玩家1拥有的奇观的数量,包括已建成的和还未建成的地基。当检测到数量为0时,就向场景发送一个特定的信号。然后场景触发检测到这个信号之后执行触发,效果为宣布玩家的敌人胜利。简单的来说,就是以AI检测到的事实作为实现触发效果的条件。关于这段语句的用法,直接保存成per文件是没有用的,因为只有这一个规则的AI基本没有意义。所以如果你已经有了可以用的AI,就把这一段复制进你的AI里,然后编写对应的场景触发就可以了。

troytroytroy 发表于 2017-5-12 17:21:35

補充一點,其實有用到的語句只有這段:
(defrule
      (game-time > 6)
      (cc-players-building-type-count 1 wonder < 1)
=>
      (set-strategic-number sn-special-attack-type1 276)
      (set-signal 6)
      (disable-self)
)
前面是不相干的。

浩气长存 发表于 2017-5-12 17:49:14

Oracle_Ameth 发表于 2017-5-12 15:52
简单讲解一下,这段AI语句的大意是,检测玩家1拥有的奇观的数量,包括已建成的和还未建成的地基。当检测到 ...

谢谢兄台指教。看了两个钟头阁下的教程,有了一些头绪。麻烦再请教一下,利普顿战役里是一开始就设置了奇观地基,然后检测游戏开始6时间之后玩家是否有奇观或者地基;我的地图里是某个触发建立奇观地基,时间不定,那么我设定检测到玩家有奇观地基后设为AI信号6,检测到玩家没有奇观或者地基,则设为AI信号12。根据阁下的教程我编写了个简单的AI,并在AI里这样设置:
(defrule
        (cc-players-building-type-count 1 wonder1)
=>
        (set-signal 6)
        (disable-self)
)

(defrule
        (cc-players-building-type-count 1 wonder < 1)
=>
        (set-strategic-number sn-special-attack-type1 276)
        (set-signal 12)
        (disable-self)
)
前面的语句是否正确?这里面的AI信号值多少是随便设定的吗?set-strategic-number sn-special-attack-type1 276是指AI优先攻击奇观?
然后我用触发编辑器建立AI信号12导致玩家失败的触发,起始状态关闭,然后用AI信号6激活刚才的触发,然后导入AI,为什么还是不能实现设想的功能?问题出在何处呢?

浩气长存 发表于 2017-5-12 17:56:17

tryotryotryo 发表于 2017-5-12 17:21
補充一點,其實有用到的語句只有這段:

前面是不相干的。

麻烦看下我上面发的语句哪里出问题了,为什么按照我的设想还是不能实现?

Oracle_Ameth 发表于 2017-5-12 18:08:10

本帖最后由 Oracle_Ameth 于 2017-5-12 23:24 编辑

浩气长存 发表于 2017-5-12 17:49
谢谢兄台指教。看了两个钟头阁下的教程,有了一些头绪。麻烦再请教一下,利普顿战役里是一开始就设置了奇 ...
首先看你的第一个规则:

(defrule
         (cc-players-building-type-count 1 wonder1)
=>
         (set-signal 6)
         (disable-self)
)

你的第一个规则的写法估计是想让AI检测到玩家1拥有一个奇观(地基)的时候给场景发送编号为6的信号,但是你的检测事实用的语句cc-players-building-type-count用的语法错了。正确的语法应该是:

cc-players-building-type-count + 玩家编号 + 建筑种类 + 运算符号 + 数量


也就是说,你缺少了一个运算符号,此处应该补上一个大于等于号,即:

(defrule
         (cc-players-building-type-count 1 wonder >=1)
=>
         (set-signal 6)
         (disable-self)
)

这样的写法才是正确的。

其次,你的第二个规则如果是这样写的话,那么根据你的描述,在游戏初期玩家肯定是没有奇观的。而AI会时刻检测它里面的规则是否能被执行,也就是说,游戏一开始,AI就会给场景发送12号信号,然后被你的触发检测到。当那个收到信号就宣布玩家失败的触发被激活,不管玩家当时有没有奇观都会被宣布失败。


-----------------------------------------------------------------------------------

所以我们应该这样写这一段AI:


首先定义一个目标常数,让你知道这个目标(goal)是干什么用的。

(defconst YES 1)
(defconst NO 2)
(defconst wonderevent 6)

这样定义过后,在你的AI里,所有的"wonderevent"的字眼都可以被AI看作6理解。同样的,"YES"被看作1,"NO"被看作2。

然后是定义规则,首先我们要将那个在玩家拥有奇观地基之后检测玩家的奇观是否被摧毁的规则保持在非激活状态,等到玩家获得奇观地基的时候再激活,以免在玩家还没有获得奇观地基的时候直接被宣布失败:

(defrule
    (true)
=>
    (set-goal wonderevent NO)
    (disable-self)
)

当玩家获得一个奇观地基的时候,激活那个检测玩家奇观是否被摧毁的规则:

(defrule
    (cc-players-building-type-count 1 wonder >=1)
    (goal wonderevent NO)
=>
    (set-goal wonderevent YES)
    (disable-self)
)

然后我们再写检查玩家奇观是否被摧毁的规则:
假设当检测到玩家奇观被摧毁的时候你想要发送给场景的AI信号的编号是6。这里set-signal的wonderevent等同于6。

(defrule
    (goal wonderevent YES)
    (cc-players-building-type-count 1 wonder <1)
=>
    (set-signal wonderevent)
    (disable-self)
)

把这些定义的常数和规则都复制到你的AI然后做对应的触发就行了。


浩气长存 发表于 2017-5-12 19:17:58

Oracle_Ameth 发表于 2017-5-12 18:08
首先看你的第一个规则:

(defrule


十分感谢!虽然这对于上大学时编程课考不及格的我来说难了点,语句仍然看得似懂非懂,但我的思路问题出在哪儿刚也想明白了,看到阁下的解答颇有拨云见日的感觉。再次感谢你不厌其烦对一个新人问题的回答!

wierek 发表于 2017-5-12 19:26:54

请问是 一开始有个奇观的地基然后如果取消建造就失败 吗?
我刚使了一下 不用那么复杂 自带的就可以

wierek 发表于 2017-5-12 19:31:13

先 触发1 效果1 世界奇观的地基 然后效果2指向触发2(建立触发2) 触发2 条件1 计时器(大概5视情况而定) 条件2对象已有目标(世界奇观)(反向条件)   效果1 宣布胜利

wierek 发表于 2017-5-12 19:32:04

我是萌新说错了,表骂我。

wierek 发表于 2017-5-12 19:56:43

抱歉 刚才又试了下发现不行,但是我还有别的解决办法,那就是在地基上循环建一个东西,取消世界奇观或毁灭,则产生目标,检测然后宣布失败。

浩气长存 发表于 2017-5-12 20:51:51

wierek 发表于 2017-5-12 19:56
抱歉 刚才又试了下发现不行,但是我还有别的解决办法,那就是在地基上循环建一个东西,取消世界奇观或毁灭 ...

谢谢关注这个问题,但是不论一开始就有地基还是触发建立地基,总归是地基,触发编辑器中好像可没有对应地基消失的触发的哦。
如果一开始是建成的建物,那么它消失后不用触发原址产生任何其他物体,建筑被消灭本身就是一个触发条件。但是地基不行。

浩气长存 发表于 2017-5-12 21:25:41

Oracle_Ameth 发表于 2017-5-12 18:08
首先看你的第一个规则:

(defrule


琢磨了半天兄台给写的代码,好像是看明白了,其实里面的核心问题是检测奇观或地基数量,只是为了使得检测奇观数量这一动作在特定时间段发生两次,先虚设了三个参数1,2和6,先把参数6的值赋为1,当6的值为1且检测到1个奇观或地基时将6赋值为2;再当6的值为2且检测到奇观或地基少于1个也就是没有的时候,发出信号6。但是有一个问题:最后发出的信号6的值,究竟是2还是6?

Oracle_Ameth 发表于 2017-5-12 21:32:44

浩气长存 发表于 2017-5-12 21:25
琢磨了半天兄台给写的代码,好像是看明白了,其实里面的核心问题是检测奇观或地基数量,只是为了使得检测 ...

最后发送的信号是wonder,因为wonder的值是6,所以发送的信号就是6。

浩气长存 发表于 2017-5-12 21:40:53

Oracle_Ameth 发表于 2017-5-12 18:08
首先看你的第一个规则:

(defrule


而且我也试过了,把这些代码复制到AI里,设置AI信号6导致玩家失败,或者AI信号2导致玩家失败都不行,测试时取消建造奇观,然后什么也没有发生。
我把最后的代码写成“set-signal 6”照样还是不行。不知问题出在哪里呢?

Oracle_Ameth 发表于 2017-5-12 21:44:02

浩气长存 发表于 2017-5-12 21:40
而且我也试过了,把这些代码复制到AI里,设置AI信号6导致玩家失败,或者AI信号2导致玩家失败都不行,测试 ...

AI语句写成我这样是绝对没有问题的,你检查一下自己的触发是不是写对了
页: [1] 2
查看完整版本: 如何设置触发使得取消建造奇观(已有地基)后失败?