「演算法」是一個程式用語,意思是「使用特定語言達成特定目的的一種思維方式」。不可否認,WE的觸發的確和程式語言的概念很相似,所以我們必須學習這種思維方式,才能更加容易了解如何把一個想法化成具體的程式語言(觸發)。以下會採用問題&解答的方式來介紹,大家在看到題目時,可以先在腦中構思作法,然後再看參考解答以及其思維方式。當然這裡所提供的解法並非惟一,讀者可以去思考是否有別的更好的方法。
當一個問題有多種可能的寫法時,什麼樣的寫法是好的?基本上我們寫觸發的優化目標有二:一是讓電腦執行有效率,二是讓人容易讀得懂。有時為了效率會犧牲易讀性;有時為了易讀性會犠牲效率(例如全部用JASS寫最有效率,但是為了易讀,連B社的地圖也並非全用JASS)。一個有技巧的人必須能在兩者之中取得平衡點。
下面提供幾個最簡單的範例,一些比較進階的常見問題可以在FAQ找到。
面對一個要用觸發解決的問題,首先應該先思考:前提是什麼?效果是如何? 前提可以看成是要達成效果的前置因素。大致上可以分成幾個層次:
可用一個事件解決。如「部隊被攻擊」、「遊戲時間30秒時」、「每5秒一次」、……。
可用事件與條件解決。如「一個英雄被攻擊」、「玩家失去了所有建築」、「部隊施展了黑死爪」、……。
必須用多個觸發組合去取出實際或接近的前提。如「一個部隊被投射性技能擊中」、「一個部隊受到傷害」、「一個有重生技能的部隊重生」、……。
如果以上幾個做出來的效果不好或者沒辦法做,最後可以考慮用「每X秒執行一次」的觸發去取接近的效果。
每5秒在地圖中央產生二名玩者一的步兵
顯然這個問題中,事件是「每5秒執行一次」,動作是「在地圖中央產生二名玩者一的步兵」,而條件則不需要,所以我們可以這樣寫:
(地圖上的)阿薩斯死亡時,殺人者得100黃金,而被殺者則損失100黃金
這個問題的事件很簡單,就是「阿薩斯死亡」,而動作是增加100黃金與減少100黃金,可是要加給誰呢?玩者一殺就給玩者一,玩者二殺就給玩者二;玩者一死就扣玩者一、玩者二死就扣玩者二……這樣寫多累啊?
要解決這個問題,就得用到事件回應的觀念,當事件是「部隊死亡」時,可以用函數「死亡的部隊(Dying Unit)」、「殺人的部隊(Killing Unit)」、「觸發事件的部隊(即死亡的部隊)(Triggering Unit)」來取得相關的資料。慢著,可是我要加錢給玩者,而不是部隊耶!所以我們可以再用一個函數「Ower of <Unit>」來取出殺人者/被殺者的所屬玩家。 等等!動作的指令中,只有「增加玩者金錢」和「設定玩者金錢」而已,找不到「減少玩者金錢」呀!拜託,要動腦,改成負數不就是減少了嗎?
如果問題簡化成「(地圖上的)阿薩斯死亡時,被殺者則損失100黃金」,可能就會有人這樣寫:
(地圖上的)阿薩斯死亡時,殺人者得100黃金,而被殺者則損失100黃金。但被殺者的金錢不到100時,則把所有被殺者的金錢給殺人者
這個問題是前一個問題的加強版,顯然我們在面對像前面那個問題時,應該要考慮到此種情況的處理方式。
喂!別急著看解答,不妨先想想看怎麼做再看範例:
上面兩個寫法看起來有點高級,是不是,何者比較正確呢?我們可以試著套數字去算:
adv1:
若阿薩斯的擁有者有105黃金(>100),則(Min(((Owner of (Triggering unit)) Current gold), 100))是100,所以殺死阿薩斯的玩者得到100黃金。
接著,(Min(((Owner of (Triggering unit)) Current gold), 100))是100,然後阿薩斯的擁有者損失100黃金。 若阿薩斯的擁有者有90黃金(<100),則(Min(((Owner of (Triggering unit)) Current gold), 100))是90,所以殺死阿薩斯的玩者得到90黃金,
接著,(Min(((Owner of (Triggering unit)) Current gold), 100))是90,然後阿薩斯的擁有者損失90黃金。
adv2:
若阿薩斯的擁有者有105黃金(>100),則(Min(((Owner of (Triggering unit)) Current gold), 100))是100,所以阿薩斯的擁有者損失100黃金。
接著,(Min(((Owner of (Triggering unit)) Current gold), 100))是5,然後殺死阿薩斯的玩者得到5黃金。
若阿薩斯的擁有者有105黃金(>100),則(Min(((Owner of (Triggering unit)) Current gold), 100))是90,所以阿薩斯的擁有者損失90黃金。
接著,(Min(((Owner of (Triggering unit)) Current gold), 100))是0,然後殺死阿薩斯的玩者得到0黃金。
誰對誰錯很明顯了吧?所以,即使只是一個小小的順序差異都可能導致嚴重問題,要多加小心。
此外還有幾種寫法,邏輯上都沒有錯,大家可以選一個比較習慣的使用(不過筆者個人比較推薦第3種):
遊戲進行到40秒時,在玩者一的所有兵營旁產生4名步兵與2名火槍兵
顯然這個問題中,事件是「遊戲40秒時執行」,動作是「在玩者一的所有兵營旁產生4名步兵與2名火槍兵」,而條件則不需要。
事件方面很簡單,可是動作就有一點複雜了,因為即使你翻遍手冊,也一定找不到「在某玩者的所有兵營旁生部隊」這種指令,所以腦筋就要拐點彎了。首先我們先選取玩者一的所有兵營,然後再對所有選到的部隊(兵營)執行「產生部隊」的指令,至於產生在哪裡呢?「兵營旁」可以Position of <兵營>來取得,因此我們可以這樣寫:
這樣OK了嗎?嗯,大致上是可以了,不過……Pick Unit會把死亡的部隊也選出來喔,換句話說,如果玩者一有爆掉的兵營,電腦可能會笨笨地在爆掉的兵營旁邊產生部隊,所以完整的寫法可以這樣寫:
不過也有別的判斷方式,如:
此外要注意一點,前者的If在Pick下面,所以要用Picked Unit做判斷;後者是在matching下做判斷,所以用Matching Unit。
此外也有像這樣的寫法:
遊戲進行到40秒時,在所有玩者的所有兵營旁產生4名步兵與2名火槍兵
乍看之下這個問題和上面的很類似,只不過我們可以換成Unit Group - Pick every unit in (Units of type Barracks) and do (Actions),可是當你寫到動作時,問題就來了:要為哪個玩者創造部隊?
這個前面學過,用「選到的玩家的擁有者」就好囉。以下為二種寫法:
討論區