Пятница, 03.05.2024, 14:40


Главная
Регистрация
Вход
Dota Allstars ✪ World of WarCraft Приветствую Вас Гость | RSS  
Меню сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Главная » Статьи » Dota Allstars » Полезные статьи

(Melee) AI:Часть пятая. Функции: создание и использование
(Melee) AI:Часть пятая. Функции: создание и использование                             
 

9. Функции: Создание и использование

Функции... чем они хороши, для чего, почему мы используем их? Хорошо... мы хотим, чтобы кто-нибудь еще написал много хороших функций для нас, чтобы вызывать их, так что мы не должны создавать их сами. И мы хотим создать несколько их самим себе, так что мы можем использовать свой код, отличный от других. Разделяй и властвуй . Поделите ваш код в несколько функциий, и затем завоевывайте каждую функцию.
Давайте посмотрим на самую маленькую функцию:
function myFunc takes nothing returns nothing
endfunction
Эта функция совсем ничего не делает и ничего не даёт. Тем не менее, она содержит несколько частей, которые каждая функция должна иметь. Она начинается со слова function и заканчивается словом endfunction. После слова function идёт название функции, myFunc в данном случае. Следующим идёт слово takes и список всех аргументов, которые функция принимает. Эта функция ничего не принимает, {говоря иными словами, ей не нужно что-либо сообщать}. Она также ничего не возвращает. Что все это дает нам? Это дает нам функцию с именем myFunc, которое не берет никакие входные аргументы/параметры и не имеет обратную значение.
Давайте теперь попытаемся сделать функцию, которая делает что-то, принимает какие-либо аргументы и возвращает значение.
function add takes integer a, integer b returns // sum of a и b
 return a + b
endfunction
Сразу видно, что она делает, да? И не очень умно, мы могли бы просто использовать "+" в начале без функции. Давайте сделаем более полезную функцию, ту, которая убеждается, что все крестьяне убирают что-то.
function resourceManager takes goldPeasants returns nothing
 call ClearHarvestAI() // Сначала перезапускаем менеджер сбора, __{то есть останавливаем сбор и начинаем новый}__ и
 call HarvestGold( 0, goldPeasants ) // затем сообщаем имеющимся работникам собирать золото.
 call HarvestWood( 0, GetUnitCountDone('hpea') - goldPeasants ) // и остальным собирать дерево.
Endfunctions
Эта функция берёт, как аргумент, как много крестьян, которым следует собирать золото (остальные собирают дерево). Она может быть вызвана из другой функции, похожей на это:
call resourceManager( 5 )
, которая сделается функцией, поместив туда 5 крестьян, работающих в шахте, а остальных в лесу. Используя эту функцию в предшествующих программах, мы могли бы заменить несколько строк кода из основной функции вызовом функции resourceManager. Программа из части второй - сбор урожая, может теперь быть написана похожей на это:

function resourceManager takes goldPeasants returns nothing
 call ClearHarvestAI() // Сначала перезапускаем менеджер сбора, __{то есть останавливаем сбор и начинаем новый}__ и
 call HarvestGold( 0, goldPeasants ) // затем сообщаем имеющимся работникам собирать золото.
 call HarvestWood( 0, GetUnitCountDone('hpea') - goldPeasants ) // и остальным собирать дерево.
endfunctions

function main takes nothing returns nothing
 call Sleep( 1.0 ) // Ждать одну секунду
 call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, "Script started" )

 loop // начало вечного цикла
 call resourceManager( 4 ) // 4 крестьян в шахте, а остальные в лесу.
 call Sleep( 1.0 ) // Если мы никогда не спим, такой движок может убить нас.
 endloop

 call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, "Script exiting" )
endfunction
Убедитесь, что полезная функция, та, которая быть названа, находится перед той, которая вызывает её. В противном случае WarCraft III думает вроде этого: "Что это за странная функция? Никогда не слышал об этом. Я лучше убью этот сценарий, он выглядит, как повреждённый.”
Другая полезная функция:
function print takes string message returns nothing
 call DisplayTimedTextToPlayer( GetLocalPlayer(), 0.0, 0.0, 3600, message )
endfunction
Хорошо, хорошо, скажете Вы... но эта функция не создаст для нас армию. Хорошо... скоро мы создадим несколько функций, которые помогут нам создать большую армию. Терпение, пожалуйста.
Сценарий для борьбы
Давайте сначала перезапишем код из части пятой - создание барака и подготовка нескольких солдат.
Чтобы увеличивать удобность для чтения и сделать управление кодом легче, сценарий разбит в другие разделы, которые оперируют ресурсами, подготовкой юнитов и строительством зданий.

function resourceManager takes nothing returns nothing 
 local integer goldPeasants = 5
 local integer peasantsDone = GetUnitCountDone('hpea')
 if peasantsDone < 6 then
 set goldPeasants = peasantsDone - 1
 endif

 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "In manager")
 call ClearHarvestAI() // Сначала перезапускаем менеджер сбора, 
__{то есть останавливаем сбор и начинаем новый}__ и
 call HarvestGold( 0, goldPeasants ) // сообщаем
 // рабочим группы goldPeasants собирать золото 
 call HarvestWood( 0, GetUnitCountDone('hpea') - goldPeasants )
 // и остальным собирать дерево. 
endfunction 

function unitManager takes nothing returns nothing 
 if GetUnitCount('hpea') < 12 then
 call SetProduce(1, 'hpea', -1) // Тренировать одного крестьянина, где возможно
 endif
 call SetProduce(1, 'hfoo', -1) // Тренировать одного пехотинца, где возможно
endfunction 

function buildingManager takes nothing returns nothing 
 local integer produced = 12 + 6 * GetUnitCount('hhou') 
 local integer used = 1 * GetUnitCount('hpea') + 2 * GetUnitCount('hfoo')
 local integer foodSpace = produced - used 
 local integer barrack = GetUnitCount('hbar')

 if foodSpace < 6 then 
 call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"Building house") 
 call SetProduce(1,'hhou',-1) 
 endif

 if barrack < 1 then
 call SetProduce(1,'hbar',-1) 
 endif
endfunction 

function main takes nothing returns nothing 
 call Sleep( 1.0 ) // Sleep 1 second 
 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "Script started") 

 loop // начало вечного цикла
 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "in loop") 
 call resourceManager() 
 call unitManager() 
 call buildingManager() 
 call Sleep( 1.0 ) //Если мы никогда не спим, такой движок может убить нас. 
 endloop 

 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "Script exiting") 
endfunction

Этот код произведет отряд пехотинцев, который будет просто стоять и ничего не делать. Но об этом скоро позаботимся... Давайте начнём с создания AI, что произвольно бродит карте со своими пехотинцами. Надо надеяться, он найдет что-то, чтобы убить... Мы должны скоро также рассмотреть как встроенный в AI скрипт решает проблемы обманом...

globals // variables that can be reached from all functions in the AI script.
 unit scoutUnit = null
 real scoutX = 0
 real scoutY = 0
 real scoutHealth
endglobals
//================================================== =======
// resourceManager
//
// Сбор ресурсов путём подачи команд крестьянам
//================================================== =======
function resourceManager takes nothing returns nothing 
 local integer goldPeasants = 5
 local integer peasantsDone = GetUnitCountDone('hpea')
 if peasantsDone < 6 then
 set goldPeasants = peasantsDone - 1
 endif

// call DisplayTextToPlayer(GetLocalPlayer(),
 0.0, 0.0, "In resourceManager")
 call ClearHarvestAI() // Сначала перезапускаем менеджер сбора,
 __{то есть останавливаем сбор и начинаем новый}__ и
 call HarvestGold( 0, goldPeasants ) // сообщаем
 // рабочим группы goldPeasants собирать золото 
 call HarvestWood( 0, GetUnitCountDone('hpea') - goldPeasants )
 // и остальным собирать дерево. 
endfunction 
//================================================== =======
// unitManager
//
// Тренировка юнитов
//================================================== =======
function unitManager takes nothing returns nothing 
 if GetUnitCount('hpea') < 12 then
 call SetProduce(1, 'hpea', -1) // 
Тренировать одного крестьянина, где возможно
 endif
 if GetUnitCount('hfoo') < 15 then
 call SetProduce(1, 'hfoo', -1) // 
Тренировать одного пехотинца, где возможно
 endif
endfunction 
//================================================== =======
// buildingManager
//
// Строительство зданий
//================================================== =======
function buildingManager takes nothing returns nothing 
 local integer produced = 12 + 6 * GetUnitCount('hhou') 
 local integer used = 1 * GetUnitCount('hpea') + 2 * GetUnitCount('hfoo')
 local integer foodSpace = produced - used 
 local integer barrack = GetUnitCount('hbar')

 if foodSpace < 6 then 
// call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"Building house") 
 call SetProduce(1,'hhou',-1) 
 endif

 if barrack < 2 then
 call SetProduce(1,'hbar',-1) 
 endif
endfunction 
//================================================== =======
// allocateScout
//
// Выбор какого-либо юнита разведчиком, чтобы он разведывал тропы
//================================================== =======
function allocateScout takes nothing returns nothing
 local group grp = CreateGroup()
 call GroupEnumUnitsOfType(grp, "footman", null)
 set scoutUnit = FirstOfGroup(grp)
 call RemoveGuardPosition(scoutUnit)
 set scoutX = GetUnitX(scoutUnit)
 set scoutY = GetUnitY(scoutUnit)
 set scoutHealth = GetUnitState(scoutUnit, UNIT_STATE_LIFE)
endfunction
//================================================== =======
// init
//
// Инициализация скрипта
//================================================== =======
function init takes nothing returns nothing
endfunction
//================================================== =======
// walk
//
// Приказывает юниту u двигаться в какое-то место.
//================================================== =======
function walk takes unit u, real distance returns nothing
 local real dir = GetUnitFacing(u) * 3.14 / 180
 local real x = GetUnitX(u) + distance * Cos(dir)
 local real y = GetUnitY(u) + distance * Sin(dir)
 call IssuePointOrder( u, "move", x, y)
endfunction
//================================================== =======
// walk
//
// Приказывает юниту u двигаться в каком-либо направлении.
//================================================== =======
function walkDir takes unit u, real distance, 
real direction returns nothing
 local real dir = direction * 3.14 / 180
 local real x = GetUnitX(u) + distance * Cos(dir)
 local real y = GetUnitY(u) + distance * Sin(dir)
 call IssuePointOrder( u, "move", x, y)
endfunction
//================================================== =======
// helpScout
//
// Посылает юнитов, которые будут следовать по дорогам разведчиков
//================================================== =======
function helpScout takes nothing returns nothing
 local group grp = CreateGroup()
 local unit u
 call GroupEnumUnitsOfType(grp, "footman", null)
 set u = FirstOfGroup(grp)
 loop
 exitwhen u == null
 if u != scoutUnit then
 call IssuePointOrder( u, "attack", scoutX, scoutY) 
 endif
 call GroupRemoveUnit(grp, u)
 set u = FirstOfGroup(grp)
 endloop
 call DestroyGroup(grp)
endfunction
//================================================== =======
// scout
//
// Контролирование скаута, которые бродит по карте.
//================================================== =======
function scout takes nothing returns nothing
 local real R = 1024
 local real x = GetUnitX(scoutUnit)
 local real y = GetUnitY(scoutUnit)

 if scoutX == x и scoutY == y then
// call DisplayTextToPlayer(GetLocalPlayer(),0.0,0.0,"== Bump ==") 
 call walkDir(scoutUnit, R, GetUnitFacing(scoutUnit) + GetRиomReal(90, 270))
 else
 set scoutX = x
 set scoutY = y
 call walk(scoutUnit, R)
 endif
endfunction
//================================================== =======
// combatManager
//
// Контролирование армии, которая будет следовать за скаутом
//================================================== =======
function combatManager takes nothing returns nothing
// call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, 
"In combatManager")
 if scoutUnit == null or not UnitAlive(scoutUnit) then
 call allocateScout()
 endif
 if GetUnitCountDone('hfoo') > 4 и scoutUnit != null then
 call scout()
 call helpScout()
 endif
endfunction
//================================================== =======
// main
//
// Главная функция, запускающая AI
//================================================== =======
function main takes nothing returns nothing 
 call Sleep( 1.0 ) // Sleep 1 second 
 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "Script started") 
 call init()

 loop // начало вечного цикла
// call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "in loop") 
 call resourceManager() 
 call unitManager() 
 call buildingManager() 
 call combatManager()
 call Sleep( 5.0 ) //Если мы никогда не спим, такой движок может убить нас. 
 endloop 

 call DisplayTextToPlayer(GetLocalPlayer(), 0.0, 0.0, "Script exiting") 
endfunction
Попытайтесь создать несколько людей,
борющихся друг с другом при помощи этого сценария… 
Следующий код будет связан со сценарием AI, действующем на игрока 2.
local integer command = 42
local integer data = 6 * 9
call CommиAI(Player(1), commи, data)
Чтобы получать хранимую информацию из сценария AI, используйте следующее:
function ReadAICommи takes nothing returns nothing
 local integer commи
 local integer data
 
 loop
 exitwhen commandsWaiting() > 0
 call Sleep(0.5) // Если мы не спим, игровой движок может быть разрушен...
 endloop
 
 set command = GetLastcommand()
 set data = GetLastData()
 call PopLastcommand()

 // do whatever with command и data. 
Endfunction

Это работает только для целых чисел, конечно...
Другие способы создать связь между Картой и сценарием AI включают в себя установку золота и лесоматериалов для некоторого игрока или установку собственной величины некоторому специфическому юниту. Это возможно также при использовании игрового кеша… не уверен, что это доступно из сценариев AI. Вот, собственно говоря, и всё.


Категория: Полезные статьи | Добавил: TRACTOR (03.05.2012)
Просмотров: 508 | Рейтинг: 1.0/1
Вход на сайт

Поиск

Copyright MyCorp © 2024Сделать бесплатный сайт с uCoz