##EasyReadMore##

2009年12月22日 星期二

[轉帖][WE JASS] AI腳本初級教程




文章網址:http://bbs.wow8.org/thread-3845-1-34.html

BY 蚊子叮

JASS與C語言很類似,所以在閱讀以下內容之前,首先應該對TRIGGER JASS有著一定的瞭解。
瞭解JASS之後,你將很快的瞭解AI JASS。
AI JASS的概念
最主要的是理解AI線程(Threads)的概念。
線程是什麼?
線程就像TRIGGER的一個循環判斷語句,線程會不停的判斷在線程程序列表內所缺少的元素,並去按照線程的指令排放順序去完成它。
就像碗中的飯,有即吃,有即吃,有即吃,Loop......
為什麼不用TRIGGER去完成電腦的人工智能呢?
由於使用TRIGGER相比之下可能會消耗大量的內存,所以,最好用AI線程來完成電腦的人工智能。
注意: 線程只針對單個玩家運作。

AI的類型(Melee AI 和 Campaign AI )
Melee AI 對戰AI基本上完全可以利用WORLDEDITOR自帶的AI編輯器(AI Edior)完成
Campaign AI 戰役AI(即「非對戰AI」),可以詳細瞭解以下內容即可製作一般常用的戰役AI
註:戰役AI的用途十分廣泛,完全可以利用其製作生存,3C,TD等類型的地圖,並且免除了不停使用TRIGGER創造單位所帶來的內存洩露。


線程(Threads)和觸發器(Trigger)的區別AI腳本只能使用JASS函數庫common.j和common.ai中的函數和量Trigger腳本只能使用common.j和Blizzard.j中的函數和量線程只應用於AI腳本(AI JASS), 不能用於觸發器腳本(Trigger Jass)觸發器只應用用於觸發器腳本(Trigger Jass),不能用於AI腳本(AI JASS)
通常, 當AI腳本開始運行時只創建一個線程, 創建更多的線程可以用comman.j的本地函數:
native StartThread takes code func returns nothing
運行方式的區別在於線程一旦開啟即可自動運轉,觸發器必須調用或者借助事件的發生才可以運行。 調用 call StartThread(function myfunc) 將創建一個從函數myfunc開始執行的線程.
調用 call SleepForever() 使線程永久性的關閉 *每個玩家最多可以擁有6個線程(包括一開始執行的主線程在內,當一個玩家有6個線程數時, 調用StartThread()的語句將被忽略. ) *線程不能回收, 當你為某玩家創建了5個自定義線程, 將無法為該玩家創建更多的線程. *局域性的全局狀態,在同一玩家中的所有線程都共享全局狀態(包括變量). 即是修改某個全局變量, 修改後的值在此玩家的所有線程中都是可見的. *當新線程創建時, 線程立即生效. *當線程讓步執行時, 創建此線程的父線程將繼續執行.

線程在以下的情況讓步執行, 返回父線程
a) 當線程中的操作碼(opcode)超出限制, 線程會自動休眠 1 秒
 當線程中用使用 Sleep(n), 線程將休眠 n 秒, 然後繼續執行.

線程在以下情況會中止, 返回父線程
a) 如果 call StartThread(null)中, 線程中止
 當線程的主函數返回, 線程中止.
(StartThread()中之間調用的函數就是主函數.)
c) 當線程中使用沒有聲明的變量, 線程中止. 在使用之前, 變量必須聲明.
d) 當線程中出現零為被除數時, 線程中止
e) 線程主函數出現語法錯誤.
注意: 雖然AI腳本可以使用大部分common.j的庫函數, 但有些類型的函數在AI不能正常工作, 如:
a) 返回字符串類型(string)的本地函數, 如I2S(), SubString()等
 需要以code, trigger, boolexpr 等類型數據為參數的本地函數, 如觸發器函數, 隊列函數(ForGroup, 等)

注意: AI中不可以使用Blizzard.j的函數, 觸發器中也不可以使用common.ai的函數, AI和觸發器都可以使用common.j的函數(當然, 對於AI, 還受上面所說的限制)

common.ai和common.j是寫AI時可以調用和參考庫文件, 要研究AI, 先去讀這2個文件.******************************************************************

3) 跨腳本通訊(Inter-Script Communication)
在遊戲中, 可能會有多個獨立的Jass腳本文件同時運行. 比如在對戰地圖中的遊戲, 運行觸發器腳本文件的同時, 也可能運行了每個電腦玩家的AI腳本文件. 每個腳本文件之間的全局變量不是共享的. 所以, 一個電腦玩家的AI腳本中設置的全局變量不會影響另一個電腦玩家的AI腳本的執行.

觸發器腳本也不可以和AI腳本共享全局變量. 但可以用傳遞命令的方法進行腳本之間的數據交換. 命令由一對數值型數據(integer)組成: 命令值(command value)和數據值(data value).

從觸發器腳本向AI腳本發出通訊命令, 可以使用common.j中定義的以下本地函數:
native CommandAI takes player num,
integer command, integer data returns nothing

參數:
player num //玩家
integer command //命令
integer data //命令數據


常數:
//--------------------------------------------------------------------
constant integer M1 = 60 實際上是時間!
constant integer M2 = 2*60
constant integer M3 = 3*60
constant integer M4 = 4*60
constant integer M5 = 5*60
constant integer M6 = 6*60
constant integer M7 = 7*60
constant integer M8 = 8*60
constant integer M9 = 9*60
constant integer M10 = 10*60
constant integer M11 = 11*60
constant integer M12 = 12*60
constant integer M13 = 13*60
constant integer M14 = 14*60
constant integer M15 = 15*60

constant integer EASY = 1
constant integer NORMAL = 2
constant integer HARD = 3
constant integer INSANE = 4 // not used

constant integer MELEE_NEWBIE = 1
constant integer MELEE_NORMAL = 2
constant integer MELEE_INSANE = 3

constant integer ATTACK_CAPTAIN = 1
constant integer DEFENSE_CAPTAIN = 2
constant integer BOTH_CAPTAINS = 3

constant integer BUILD_UNIT = 1
constant integer BUILD_UPGRADE = 2
constant integer BUILD_EXPAND = 3

constant integer UPKEEP_TIER1 = 50
constant integer UPKEEP_TIER2 = 80


JASS函數庫common.ai的全局變量(可以更改,也可以自行增加,以下內容會經常在AI腳本中使用):
player ai_player //AI玩家 integer sleep_seconds
//等待時間
integer total_gold = 0 //總計的金錢 integer total_wood = 0
//總計的木材
integer gold_buffer = 0
// usually for potion money
integer difficulty = NORMAL
//難度,默認為中等難度
integer exp_seen = 0
integer racial_farm = 'hhou'
integer hero_id = 'Hamg'
//第一個英雄的ID,默認為聖騎士
integer hero_id2 = 'Hmkg'
//第二個英雄的ID,默認為山丘之王
integer hero_id3 = 'Hpal'
//第三個英雄的ID,默認為大法
integer array skill
integer array skills1
integer array skills2
integer array skills3
integer max_hero_level = 0
integer array harass_qty
integer array harass_max
integer array harass_units
integer harass_length = 0
防守單位的全局變量
例子:防守單位defense_units[defense_length]的數量為defense_qty[defense_length]
integer array defense_qty //設置防守單位的數量
integer array defense_units //設置防守的單位
integer defense_length = 0 //單位Index
建造的全局變量
為了區分建造的種類,BLZ為建造的全局變量設置了4類例子:建造單位build_type[build_length]的數量為build_qty[build_length]
integer array build_qty //建造的數量 設置建造單位的數量
integer array build_type //建造的種類 普通單位類(包括單位和建築)
integer array build_item //購買物品的種類 物品類
integer array build_town //建造基地的種類 基地類
integer build_length = 0
設置採集工人的數量
integer campaign_gold_peons = 5 //主基地採集金子的人數
integer campaign_wood_peons = 3 //住基地採集木材的人數
integer campaign_basics_speed = 5
integer min_creeps = -1 integer max_creeps = -1
遊戲初試設置的全局變量
boolean harvest_town1 = true
boolean harvest_town2 = true
boolean harvest_town3 = true
boolean do_campaign_farms = true
//自動製造戰役AI 提供人口的建築
boolean two_heroes = false
//雙英雄
boolean allow_air_creeps = false
//空中的中立單位(假如有,AI會針對性的發展)
boolean take_exp = false //<


一般戰役AI常用函數


CampaignAI takes integer farms, code heroes returns nothing
是BLZ在COMMON.AI中設置的一個簡便函數,直接初始化戰役AI
farms - 提供AI玩家人口的建築類型
heroes - 指向設置英雄的ID的CODE

SetReplacements takes integer easy, integer med, integer hard returns nothing
尚未研究的函數,一般用法為:
call SetReplacement( 2, 2, 4 )
easy - 遊戲難度為簡單所賦的值
med - 遊戲難度為普通所賦的值
hard - 遊戲難度為困難所賦的值

native SetCaptainHome takes integer which, real x, real y returns nothing
設置攻擊組隊長在家的點?
which - 什麼的聚集點,參數有:
constant integer ATTACK_CAPTAIN = 1 進攻的點
constant integer DEFENSE_CAPTAIN = 2 防禦的點
constant integer BOTH_CAPTAINS = 3 進攻和防禦的點
x - X坐標
Y - Y坐標

SetBuildUnit takes integer qty, integer unitid returns nothing
指令AI玩家製造(所有類型的建造,包括升級)
qty - 數量
unitid - 單位類型

SetBuildUnitEx takes integer easy, integer med, integer hard, integer unitid returns nothing
指令AI玩家製造單位按照遊戲難度
easy - 簡單時候的數量
med - 普通時候的數量
hard - 困難時候的數量
unitid - 單位類型

CampaignDefender takes integer level, integer qty, integer unitid returns nothing
設置防守單位的數量

CampaignDefenderEx takes integer easy, integer med, integer hard, integer unitid returns nothing
設置防守單位的數量,
按難度 call WaitForSignal() 等待TRIGGER發出AI指令,當堆積的指令數量不等於0時,繼續進行AI線程


進攻組的指令
function InitAssaultGroup takes nothing returns nothing
初始化進攻組,設置全局變量harass_length = 0


CampaignAttacker takes integer level, integer qty, integer unitid returns nothing
增加進攻組的進攻單位
qty - 數量
unitid - 單位類型

CampaignAttackerEx takes integer easy, integer med, integer hard, integer unitid returns nothing
增加進攻組的進攻單位,按遊戲難度
easy - 簡單時候的數量
med - 普通時候的數量
hard - 困難時候的數量
unitid - 單位類型

SuicideOnPoint takes integer seconds, player p, integer x, integer y returns nothing
設置進攻的玩家的點seconds 發起進攻等待的時間,
常量參數有
constant integer M1 = 60
constant integer M2 = 260
constant integer M3 = 360
constant integer M4 = 460
constant integer M5 = 560
constant integer M6 = 660
constant integer M7 = 760
constant integer M8 = 860
constant integer M9 = 960
constant integer M10 = 1060
constant integer M11 = 1160
constant integer M12 = 1260
constant integer M13 = 1360
constant integer M14 = 1460
constant integer M15 = 1560
p - 目標玩家

SuicideOnUnits takes integer seconds, player p returns nothing
設置進攻的目標玩家seconds


一般戰役AI的製作方案
參看BLZ在戰役中所製作的AI腳本「n08_green.ai」來瞭解怎麼製作AI
//變量 進攻的目標玩家
globals
player user = Player(1)
endglobals function main takes nothing returns nothing //AI初試設置
call CampaignAI(ZIGGURAT_1,null)
call SetReplacements(2,2,4)
call SetCaptainHome(ATTACK_CAPTAIN,4161,-4668 )
call SetCaptainHome(DEFENSE_CAPTAIN,5218,-6441 )
set campaign_wood_peons = 2 //需要建造的建築以及單位
call SetBuildUnit( 1, NECROPOLIS_1 )
call SetBuildUnit( 1, ACOLYTE )
call SetBuildUnit( 1, UNDEAD_MINE )
call SetBuildUnit( 1, GRAVEYARD )
call SetBuildUnit( 8, ZIGGURAT_1 )
call SetBuildUnit( 2, CRYPT )
call SetBuildUnit( 1, UNDEAD_ALTAR )
call SetBuildUnit( 1, NECROPOLIS_2 )
call SetBuildUnit( 2, SLAUGHTERHOUSE )
call SetBuildUnit( 1, DAMNED_TEMPLE )
call SetBuildUnit( 1, NECROPOLIS_3 )
call SetBuildUnit( 2, BONEYARD )
call SetBuildUnit( 5, ACOLYTE )
call SetBuildUnit( 8, ZIGGURAT_2 ) //防守單位
call CampaignDefenderEx( 1,1,2, ABOMINATION )
call CampaignDefenderEx( 1,1,1, GARGOYLE )
call CampaignDefenderEx( 1,1,1, FROST_WYRM )
call CampaignDefenderEx( 1,1,1, CRYPT_FIEND )
call CampaignDefenderEx( 1,1,1, DREAD_LORD ) //TRIGGER發出指令就開始進行下面的AI進程
call WaitForSignal() //進攻,製造
//WAVE 1
call InitAssaultGroup()
call CampaignAttackerEx( 6,6,8, GARGOYLE )
call SuicideOnPlayerEx(M5,M5,M3,user)
call SetBuildUpgrEx( 1,1,1, UPG_FIEND_WEB )
call SetBuildUpgrEx( 1,1,1, UPG_CANNIBALIZE )
call SetBuildUpgrEx( 1,1,1, UPG_UNHOLY_STR )
call SetBuildUpgrEx( 1,1,1, UPG_CR_ATTACK )
//WAVE 2
call InitAssaultGroup()
call CampaignAttackerEx( 6,6,8, GARGOYLE )
call CampaignAttackerEx( 2,2,4, CRYPT_FIEND )
call CampaignAttackerEx( 1,1,2, FROST_WYRM )
call SuicideOnPlayerEx(M6,M6,M4,user)
//WAVE 3
call InitAssaultGroup()
call CampaignAttackerEx( 6,6,8, GARGOYLE )
call CampaignAttackerEx( 2,2,4, CRYPT_FIEND )
call CampaignAttackerEx( 1,1,2, FROST_WYRM )
call CampaignAttackerEx( 1,1,1, DREAD_LORD )
call SuicideOnPlayerEx(M6,M6,M4,user)
call SetBuildUpgrEx( 2,2,2, UPG_UNHOLY_STR )
call SetBuildUpgrEx( 2,2,2, UPG_CR_ATTACK )
call SetBuildUpgrEx( 1,1,1, UPG_SKEL_LIFE )
call SetBuildUpgrEx( 1,1,1, UPG_WYRM_BREATH )
//WAVE 4
call InitAssaultGroup()
call CampaignAttackerEx( 2,2,3, GARGOYLE )
call CampaignAttackerEx( 5,5,6, CRYPT_FIEND )
call CampaignAttackerEx( 1,1,2,




沒有留言:

張貼留言

※怎麼下載?Xuite硬碟MediaFireBadongoSendSpace
※文章可以轉貼嗎?可以,不過要註明出處、標示本站連結。
※載點可以轉貼嗎?不可以,不能盜連。
※建議瀏覽器:Chrome 或 Firefox 或 Opera 或 IE7以上
!請按+1來支持本站!