1.4 AI 練習實例:遮蔽建築效果
本帖最后由 这只话唠菜鹰是路人 于 2016-11-22 00:40 编辑前言:
在製作傭兵的歲月裡的某一天,(帥氣的)哈羅德在QQ上問了一個問題:可否用1.4的AI寫出類似以下的判斷語句,這裡我用一個生活化的例子來說明:
在遙遠的未來,狂熊終於交了一個女友。
但是這個女友相當霸道,不准狂熊繼續打帝國和上翔鷹。
可憐的狂熊只好在女友視線看不到的地方打帝國。
一日,這對情侶來到一個環型的公園,
公園中間樹木茂盛,看不到對面。
狂熊就趁這個機會逃到了對面:
A:狂熊女友,B:狂熊
現在狀況是:因為中間樹木茂密遮住視野的關係,狂熊女友看不到狂熊
但是萬一狂熊或是他女友移動了相對位置,造成狂熊和女友間沒有遮蔽物:
那麼狂熊就會被女友發現,再也不能玩帝國了。
這就是(帥氣的)哈羅德當時所問的問題核心。雖然他當時沒有想到這麼完美的例子。
當時Ru和我提出了不同的想法,而我簡略的動手寫了一下AI來測試。當時的效果並不太理想,加上因為在趕火十一截止的關係,最後不了了之。因此這個想法一直到現在才發表出來。我必須強調的是,這個AI語句可能還有相當大的改進空間,所以也許有更多戰役制作者看完後可以嘗試改良。
(本文基礎建立於條頓武士的[教程] 闪闪发光新时代——翔鹰1.4版 新AI效果示例(第二弹)一文。請初學者先學習該文內容再閱讀本文。此外,本文需要一些基礎數學知識。國小學生可以請教年長的朋友關於其中的知識,以達到寓教於樂的雙重效果。)
想法:
我的想法如下:我們先假設中間的遮蔽物(綠色區域)為圓形,圓心為P,半徑為1單位。並同時假設狂熊位置為Q、狂熊女友位置為R。則我們可以假設三角形PQR的各邊為A、B和C,如下面的簡圖所示:
對於Q點而言,除非R落入下圖所畫的灰色區域,不然必定會被R察覺:
因此Q被R"發現"的充要條件為:1. 角PQR>角PQS 或 2. QR<QS。假設角PQR=θ1、角PQS=θ2,則θ1>θ2在皆為銳角的條件之下,當且僅當
cosθ1< cosθ2;
因此使用餘弦定理加上AI的計算距離語句,我們就可以寫出這個AI。
AI碼:
下面這一段是AI碼,我會逐一解說每段的意義。以下我們假設這堆障礙物的半徑為2格(設為一格會有點問題,這我們之後在予以討論)。原始碼如下
(defconst position-object 12)
(defconst P-1 100)
(defconst P-2 101)
(defconst Q-1 102)
(defconst Q-2 103)
(defconst R-1 104)
(defconst R-2 105)
(defconst Asq 201)
(defconst Bsq 202)
(defconst Csq 203)
(defconst ABsq 204)
(defconst AXsq 205)
(defconst nu-1 206)
(defconst nu-2 207)
(defconst k-1 208)
(defconst k-2 209)
我們一段段來看:首先第一段是定義一些變數:
(defconst position-object 12)
(defconst P-1 100)
(defconst P-2 101)
(defconst Q-1 102)
(defconst Q-2 103)
(defconst R-1 104)
(defconst R-2 105)
(defconst Asq 201)
(defconst Bsq 202)
(defconst Csq 203)
(defconst ABsq 204)
(defconst AXsq 205)
(defconst nu-1 206)
(defconst nu-2 207)
(defconst k-1 208)
(defconst k-2 209)
(P-1,P-2) 為 P 點座標,(Q-1,Q-2)為Q點座標,(R-1,R-2)為R點座標。我們要計算的cosθ1根據餘弦定理為
cosθ1=(A^2+B^2-C^2)/2AB;另一方面,由於cosθ2可以直接由直角三角形QPS得到,我們有(cosθ2)^2=A^2-4/A^2。這裡一個小問題是,1.4的AI只能記憶整數,因此像是除法這類會造成小數的運算都必須避免。因此我們假設Asq=A^2;Bsq=B^2;Csq=C^2;ABsq=(2AB)^2;AXsq=A^2;nu-1=A^2-4;nu-2=(A^+B^2-C^2)^2;k-3=A^2-4=QS距離;則不等式 cosθ1> cosθ2的充要條件為 nu-2/ABsq > nu-1/AXsq。為了避免除法,兩邊通分得到:(nu-2)*(AXsq)>(nu-1)*(ABsq)。我們假設式子兩邊的量為k-1和k-2。這就是這一段代碼的變數定義。
(defrule
(true)
=>
(set-goal 1 0)
(disable-self)
)
(defrule
(true)
=>
(up-set-target-by-id c: 0)
(up-get-point position-object P-1)
(up-set-target-by-id c: 1)
(up-get-point position-object Q-1)
(up-set-target-by-id c: 2)
(up-get-point position-object R-1)
)
(defrule
(true)
=>
(up-get-point-distance P-1 Q-1 Asq)
(up-get-point-distance Q-1 R-1 Bsq)
(up-get-point-distance P-1 R-1 Csq)
)
(defrule
(true)
=>
(up-modify-goal ABsq g:= Asq)
(up-modify-goal ABsq g:* Bsq)
(up-modify-goal ABsq g:* ABsq)
(up-modify-goal ABsq c:* 4)
(up-modify-goal Asq g:* Asq)
(up-modify-goal Bsq g:* Bsq)
(up-modify-goal Csq g:* Csq)
)
這一段是在計算Asq、Bsq、Csq。首先,(set-goal 1 0)這一段是在設置默認狀態,不懂的可以參考條頓武士的那篇文章。第二段是記憶 P、Q、R的座標。然後 "(up-get-point-distance P-1 Q-1 Asq)" 是指把P到Q的距離記錄為Asq。到此為止都是根據參考條頓武士的文章直接應用。
現在,記得我們的Asq是A平方。所以我們記得在最後必須再把這些數值都平方一遍。ABsq則是(2AB)^2,所以就是如下運算:
(up-modify-goal ABsq g:= Asq)
(up-modify-goal ABsq g:* Bsq)
(up-modify-goal ABsq g:* ABsq)
(up-modify-goal ABsq c:* 4)
(defrule
(true)
=>
(up-modify-goal nu-1 g:= Asq)
(up-modify-goal nu-1 g:+ Bsq)
(up-modify-goal nu-1 g:- Csq)
(up-modify-goal nu-1 g:* nu-1)
(up-modify-goal nu-2 g:= Asq)
(up-modify-goal nu-2 c:- 4)
(up-modify-goal AXsq g:= Asq)
)
這段很容易理解,基本上我們以經有所有nu-1、nu-2 所需要的數值了,只要計算即可。然後,把k-1、k-2計算出來並且比較大小,最後記得考慮QS與QR的距離關係,也就是k-3與Bsq的大小關係。(cc-add-resource ... )只是用於外部觸發方便,等到需要製做戰役時可以用這些資源編寫觸發。
結語:這個AI目前還有許多可以探討的層面。有一個方面是"區域可否再縮小"。這個我覺得很難,原因是因為AI記算距離仍舊以格為單位。因此小範圍的情況下在一格範圍裡的資訊對於AI來說是沒有差別的。但是在玩家眼中可能有非常大的差距。
附上狂熊與女友的小劇場,用上述AI製成的小演示場景。
本帖最后由 tryotryotryo 于 2016-3-24 00:23 编辑
感謝一竅不開找到一個距離檢測的問題,已修正。
祝狂熊幸福。以上AI碼可以自由取用,版權沒有,抄襲不究。 為什麼又是我中槍……
除了 set-goal 1 和 di 外, 其他似乎都應該用 up-modify-goal g:=
本帖最后由 一窍不开 于 2016-3-23 05:10 编辑
如果只是比较k-1与k-2的大小的话,完全可以用(up-compare-goal k-1 g:< k-2)替代加减步骤。
还有就是楼上狂叔说的小问题,以及似乎有一点小小的计算错误?
我试着改了改,并且加上了距离检测,弄成了完整的AI,或许可以参考一下?(并未测试,并且默认狂叔不会躲在树林里打帝国)
(defconst position-object 12)
(defconst P-1 100)
(defconst P-2 101)
(defconst Q-1 102)
(defconst Q-2 103)
(defconst R-1 104)
(defconst R-2 105)
(defconst A 201)
(defconst B 202)
(defconst C 203)
(defconst AB 204)
(defconst nu-1 206)
(defconst nu-2 207)
(defconst k-1 208)
(defconst k-2 209)
(defconst tan 300)
(defrule
(true)
=>
(set-goal 1 0)
(disable-self)
)
(defrule
(true)
=>
(up-set-target-by-id c: 0)
(up-get-point position-object P-1)
(up-set-target-by-id c: 1)
(up-get-point position-object Q-1)
(up-set-target-by-id c: 2)
(up-get-point position-object R-1)
)
(defrule
(true)
=>
(up-get-point-distance P-1 Q-1 A)
(up-get-point-distance Q-1 R-1 B)
(up-get-point-distance P-1 R-1 C)
)
(defrule
(true)
=>
(up-modify-goal AB g:= A)
(up-modify-goal AB g:* B)
(up-modify-goal AB g:* AB)
(up-modify-goal A g:* A)
(up-modify-goal B g:* B)
(up-modify-goal C g:* C)
)
(defrule
(true)
=>
(up-modify-goal nu-1 g:= A)
(up-modify-goal nu-1 g:+ B)
(up-modify-goal nu-1 g:- C)
(up-modify-goal nu-1 g:* nu-1)
(up-modify-goal nu-2 g:= A)
(up-modify-goal nu-2 g:+ A)
(up-modify-goal nu-2 c:- 2)
(up-modify-goal nu-2 g:* nu-2)
)
(defrule
(true)
=>
(up-modify-goal k-1 g:= nu-1)
(up-modify-goal k-1 g:* A)
(up-modify-goal k-2 g:= AB)
(up-modify-goal k-2 g:* nu-2)
)
(defrule
(true)
=>
(up-modify-goal tan g:= A)
(up-modify-goal tan c:- 1)
)
(defrule
(goal 1 0)
(or
(up-compare-goal k-1 g:< k-2)
(up-compare-goal B g:< tan )
)
=>
(chat-to-all "Be DETECTED!")
(cc-add-resource gold 1)
(set-goal 1 1)
)
(defrule
(goal 1 1)
(up-compare-goal k-1 g:>= k-2)
(up-compare-goal B g:>= tan )
=>
(chat-to-all "In the shadow...")
(cc-add-resource wood 1)
(set-goal 1 0)
)
当然如果是方形的建筑这个AI就不适用了,还需要另建模型。 这个未来,遥不可及啊,23333 非常不错!理论上实现的算法有很多,比如检测圆心到两人连线的距离小于半径,也是挺复杂的,不过最关键的是“精确度”的问题,ai貌似是四舍五入到个位的……我觉得最好是能找到精确度最高的算法(不知道理论可不可行)…… Howerds 发表于 2016-3-23 13:46
非常不错!理论上实现的算法有很多,比如检测圆心到两人连线的距离小于半径,也是挺复杂的,不过最关键的是 ...
昨晚玩海与山差点玩通宵,惊为天作,给萌萌哒的作者点赞 258791 发表于 2016-3-23 15:32
昨晚玩海与山差点玩通宵,惊为天作,给萌萌哒的作者点赞
哈羅德先生、哈羅德先生,請到七樓櫃台領回你走失的粉絲 @Howerds 实在太屌 是不是寫太難都乏人問津。{:167:} 赞{:155:}
页:
[1]