作者ddavid (謊言接線生)
看板StarCraft
標題Re: [SC2] AI 腳本開發最簡入門
時間Thu Mar 11 12:39:35 2010
上篇我們已經把最簡單的東西看過一遍了!現在來看看怎樣寫個神族假一波流AI
!(之所以是假一波流,第一是因為不知道怎樣用技能,不會超時空加速、哨兵也不
會開盾,當然連變傳送門變空間之門也不會。第二是我也還沒研究完整的一波流流程
,所以沒最佳化,兵種也只是看來那麼樣子而已XD)
如果你只是想看Stupid AI有多Stupid,直接看文章最末的載點跟使用說明吧!
首先,你要找到的是解開後的Protoss0.galaxy,把它用任何文字編輯器打開,
找到這個function:
void ProtossOpenGnd0 (int player) {
大括號裡面就是可以寫AI的部分了。事實上,下面還有:
static void ProtossMidGndA (int player) {
之類的,它是為了分出前中後期不同任務之類的,用一些function去切換。但是
反正我們是要寫假前期一波流,所以管它的都塞ProtossOpenGnd0裡面就好了!
接下來一段一段看下去:
int nProbe = AITechCount(player, c_PU_Probe,
c_techCountInProgressOrBetter);
int nZealot = AITechCount(player, c_PU_Zealot,
c_techCountInProgressOrBetter);
int nStalker = AITechCount(player, c_PU_Stalker,
c_techCountInProgressOrBetter);
int nDisruptor = AITechCount(player, c_PU_Disruptor,
c_techCountInProgressOrBetter);
int nPylon = AITechCount(player, c_PB_Pylon,
c_techCountInProgressOrBetter);
int nGateway = AITechCount(player, c_PB_Gateway,
c_techCountInProgressOrBetter);
int nCyberneticsCore = AITechCount(player, c_PB_CyberneticsCore,
c_techCountInProgressOrBetter);
很簡單就是把會用到的各種兵種/建築數量存起來,以供後面參考及印出Debug
訊息之用。注意這裡是用c_techCountInProgressOrBetter,也就是正做到一半還沒
做完的那一個也算在內。
TriggerDebugOutput(1,
StringToText(IntToString(nProbe) + " Probe " +
IntToString(nZealot) + " Zealot " +
IntToString(nStalker) + " Stalker " +
IntToString(nDisruptor) + " Disruptor " +
IntToString(nPylon) + " Pylon " +
IntToString(nGateway) + " Gateway " +
IntToString(nCyberneticsCore) +
" CyberneticsCore "), true);
上一篇介紹過了,就是洗螢幕用的資訊表。
AIClearStock(player);
AISetStock(player, 1, c_PB_Nexus);
AISetStock(player, 8, c_PU_Probe);
AISetStock(player, 1, c_PB_Pylon);
然後先用AIClearStock跟AI說我要重設工作了,洗乾淨雙耳給我聽清楚吧。接著
是最基本一定會做的東西:1個bn、8隻Probe、1個be。這裡講到AISetStock的特性一
,就是已有的也算在內,所以你這邊說要1個bn,那因為你原本就有了,所以它不會
去多做一個。之所以還要寫只是很無聊的,萬一你把它bn全爆了而它還有400元,它
就會重蓋(應該吧,沒測過XD)。
同樣的,這裡我們讓它做到8隻Probe就停,存錢直接be!
if(nPylon >= 1) {
AISetStock(player, 11, c_PU_Probe);
AISetStock(player, 1, c_PB_Gateway);
AISetStock(player, 1, c_PU_Zealot);
接著,第一行說如果第一個be至少已經蓋下去了,那我們才給它以下大括號內的
工作。這是為了要表現出8隻Probe後停生存錢be這個動作。我去翻一些別人寫的AI發
現他們直接這樣把流程寫下去:
AISetStock( player, 1, c_PB_Nexus );
AISetStock( player, 9, c_PU_Probe );
AISetStock( player, 1, c_PB_Pylon );
AISetStock( player, 11, c_PU_Probe );
AISetStock( player, 1, c_PB_Gateway );
AISetStock( player, 14, c_PU_Probe );
AISetStock( player, 3, c_PB_Pylon );
我也懷疑過是不是這樣照順序寫就好了。後來我實測發現這是錯的!AISetStock
似乎沒有嚴謹的順序關係!我的測試是這個:
AISetStock( player, 1, c_PB_Nexus );
AISetStock( player, 8, c_PU_Probe );
AISetStock( player, 1, c_PB_Pylon );
AISetStock( player, 1, c_PB_Gateway );
AISetStock( player, 2, c_PB_Pylon );
如果按照美好的順序,它應該做到第8隻Probe後存錢蓋下第1個be,然後存150蓋
bg,再補到第2個be。結果我實測的結果是,它居然第2個be比bg還早一點點蓋下去!
因為bg比較貴,很明顯如果照寫AI順序的話,第2個be應該要被bg卡住晚蓋的。所以
我想直接列下來的順序是沒有意義的,而且同樣針對be的寫兩行也只會取大的,有錢
就會一起蓋下去。所以回到我們的AI:
if(nPylon >= 1) {
AISetStock(player, 11, c_PU_Probe);
AISetStock(player, 1, c_PB_Gateway);
AISetStock(player, 1, c_PU_Zealot);
這裡就需要用if來做流程的控制,要在確定了第一個be蓋下去的情況才開始補到
11隻Probe,並造bg然後先做一隻Zealot。
if(nGateway >= 1) {
AISetGasPeonCountOverride(player, c_townMain, 3);
if(AIGetBuildingCountInTown(player, c_townMain,
c_PB_Assimilator,
c_techCountCompleteOnly) > 1) {
AISetGasPeonCountOverride(player, c_townMain, 6);
}
AISetStock(player, 2, c_PB_Pylon);
AISetStock(player, 19, c_PU_Probe);
AISetStock(player, 1, c_PB_Assimilator);
AISetStock(player, 2, c_PB_Gateway);
AISetStock(player, 3, c_PU_Zealot);
AISetStock(player, 1, c_PB_CyberneticsCore);
同樣的技倆,我們在11隻Probe時又讓它停生,逼它bg要蓋下去了我們才開始堆
後面的工作給它。首先我們要準備採瓦斯了,所以先設定一下3隻去採。但是接著加
個但書,如果後來我們蓋了第二個ba,那就要變6隻去採。
然後我們就堆一堆工作給它:補第2個be、Probe以19隻(礦16隻加上單ba的3隻
)為目標、蓋個ba、補到2bg、Zealot補到3隻、還要蓋個by。
if(nCyberneticsCore >= 1) {
AISetStock(player, 22, c_PU_Probe);
AISetStock(player, 2, c_PB_Assimilator);
AISetStock(player, 4, c_PB_Pylon);
AISetStock(player, 4, c_PU_Zealot);
AISetStock(player, 2, c_PU_Stalker);
AISetStock(player, 1, c_PU_Disruptor);
同樣的,by要蓋下去了我們才又增改新工作。Probe補滿到22隻因為我們要2ba了
。Zealot做到第4隻,而且可以開始做2隻追獵跟1個哨兵了。
if(nDisruptor >= 1) {
AISetStock(player, 6, c_PB_Pylon);
AISetStock(player, 6, c_PU_Stalker);
AISetStock(player, 6, c_PU_Zealot);
AISetStock(player, 3, c_PB_Gateway);
AISetStock(player, 2, c_PU_Disruptor);
}
}
}
}
AIEnableStock(player);
再進一步,哨兵第1隻完成的話,我們就做最後一堆工作。be補到6個,然後以狂
戰、追獵各6而哨兵2的目標去補,同時補下3bg。到最後,用AIEnableStock告訴它你
這AI的生產工作就很笨的到此為止了!
if(AITechCount(player, c_PU_Stalker, c_techCountCompleteOnly) >= 4) {
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
}
}
但如果只堆生產工作給它,它就真的會很笨的只生東西然後就發呆了!要讓它看
起來笨得可愛,你至少要叫它送兵過來死吧!所以在這最後,我們叫它算一下追獵有
沒有4隻做完的了(注意這裡我們用c_techCountCompleteOnly,不然在bg裡正在做的
它也算了),有的話就叫它把目前的兵力主隊改編進攻擊隊去,然後給它放手送死的
指令!這樣整個假一波流就完成了!
我把這樣編出來的Base.SC2Data.my檔(自己照之前改AI的要領,把這檔改名成
Base.SC2Data去替換原檔就好)以及有AI改寫內容的Protoss0.galaxy都放到下面這
裡了,可以自行下載!千萬不要期待強度!
http://www.badongo.com/file/21145938
Have fun!
對了補充一下我忘了講,這當然只有電腦是用到P才有效喔。如果你沒看到洗螢
幕,那電腦就不是P,F10 r r重來吧XD
如果被洗到眼都花了,可以自己嘗試照前幾篇有人提過的做法,把我這篇提到顯
示訊息的那段拔掉再包回去!
我還是補個不洗螢幕版好了:
http://www.badongo.com/file/21146635
另外裡面附了一個星際大腳(我目前是1.012)用的選單表,你可以把兩個檔完
全不改名直接copy到 星際大腳目錄\bfmods\Liberty.SC2Mod下面,就可以在星際大
腳的單機AI選單看到Stupid AI了!
--
「珍貴的回憶?還不是跟夢一樣虛幻不實的東西?你想要什麼樣的回憶,我幫你
做出來啦!」
--艾蜜思,謊言事務所實現使者
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.36.175.240
推 mantohu:推推 03/11 12:42
推 gmoz:感謝教學XD! 03/11 12:43
※ 編輯: ddavid 來自: 114.36.175.240 (03/11 12:46)
→ ddavid:靠,我剛剛想用差不多的流程跟Stupid AI硬剛,結果我先開個 03/11 12:58
→ ddavid:二礦就被幹掉,我比我AI還笨了orz 03/11 12:59
※ 編輯: ddavid 來自: 114.36.175.240 (03/11 13:14)
推 H45:推 03/11 13:19
※ 編輯: ddavid 來自: 114.36.175.240 (03/11 13:22)
→ THD:看來以後要變成AI大戰了 03/11 13:59
→ ddavid:結果不開二礦就沒事了,這個AI因為我只寫到這裡,所以它就 03/11 14:19
→ ddavid:算錢超多也只能做出設定的上限兵力XD 03/11 14:20
推 a7891:跟象棋圍棋一樣 以後寫幾個AI出來比賽看看誰是AI中的霸主 03/11 14:30
推 Kendai:那上次的隱飛甩尾應該是相當的犀利! 03/11 14:35
推 mantohu:SC2的StarCraft AI Competition應該會更精彩 03/11 14:55
→ ileadu:挖瓦斯四隻比較剛好囉.. 03/11 16:01
推 animad:三隻就飽和...四農民採氣到底是誰發表的啊... 03/11 16:05
→ ddavid:連Blizzard原本的AI都直接寫三隻六隻的XD 03/11 16:07
推 animad:SC1四農民採氣才有意義,SC2實測過根本沒差 03/11 16:08
推 rexrainbow:有下有推, 期待後續報導~ 03/12 19:31