本帖最后由 这只话唠菜鹰是路人 于 2016-11-22 00:40 编辑
前言:
在製作傭兵的歲月裡的某一天,(帥氣的)哈羅德在QQ上問了一個問題:可否用1.4的AI寫出類似以下的判斷語句,這裡我用一個生活化的例子來說明:
在遙遠的未來,狂熊終於交了一個女友。
但是這個女友相當霸道,不准狂熊繼續打帝國和上翔鷹。
可憐的狂熊只好在女友視線看不到的地方打帝國。
一日,這對情侶來到一個環型的公園,
公園中間樹木茂盛,看不到對面。
狂熊就趁這個機會逃到了對面:
A:狂熊女友,B:狂熊
現在狀況是:因為中間樹木茂密遮住視野的關係,狂熊女友看不到狂熊
但是萬一狂熊或是他女友移動了相對位置,造成狂熊和女友間沒有遮蔽物:
那麼狂熊就會被女友發現,再也不能玩帝國了。
這就是(帥氣的)哈羅德當時所問的問題核心。雖然他當時沒有想到這麼完美的例子。
當時Ru和我提出了不同的想法,而我簡略的動手寫了一下AI來測試。當時的效果並不太理想,加上因為在趕火十一截止的關係,最後不了了之。因此這個想法一直到現在才發表出來。我必須強調的是,這個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θ2可以直接由直角三角形QPS得到,我們有 這裡一個小問題是,1.4的AI只能記憶整數,因此像是除法這類會造成小數的運算都必須避免。因此我們假設 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製成的小演示場景。
|