Sargeras
Лидер "Двух Королевств"
offline
Опыт:
21,363Активность: |
Создание простого (Melee) AI
Руководство по AI-скрипту: Создание простого (Melee) AI Автор: Vidstige Ссылка на оригинал {Примечание: мои собственные пометки начинаются с символа “{” и заканчиваются символом “}”. Чтобы статья была похожа на статью, из неё были убраны некоторые авторские слова, не относящиеся к теме статьи, а также те, которые в какой-то мере были проявлением рекламы сайта, где расположен оригинал. Кроме того, в статье не были переведены те моменты, которые касались того, что уже есть на нашем сайте, в частности, теория Jass’a, лучше описанная юзером Сергеем в его соответствующей статье, однако всё то, что непосредственно связано с написанием AI-скриптов, например, рассмотрение понятия «циклы» в Jass’e с примерами из «реальной жизни», осталось. Благодарю Remal’a за предоставленную информацию для перевода и Злую Тысячу (ZlaYa1000) за предложение перевести её.} Это руководство расскажет, как шаг за шагом построить Melee AI-скрипт через файл .ai. Если вы думаете, что это руководство научит вас, как сделать AI лучше, чем AMAI, то вам не следует продолжать его читать. Взамен оно попытается научить вас основам Jass, стандартным встроенным функциям и понятиям, которые вам понадобятся, чтобы попробовать свои силы в качестве AI-скриптера. Это руководство (к несчастью) не будет всё о триггерах. ------------------------------------------ Содержание: 1. Hello World! 2. Сбор ресурсов 3. Подготовка большего количества рабочих 4. Строительство ферм для поддержки большего количества рабочих 5. Создание барака и подготовка нескольких солдат 6. Больше теории Jass’a: управление действиями, условия и циклы 7. Функции: те, которые мы использовали до этого 8. Когда нам следует что-то построить [код для добавления ] 9. Функции: Создание и использование 1. Hello World! Давайте начнём с уверенности, что вы знаете, как получить простой скрипт “Hello World!” и запустим его. Код:
Вставьте вышеуказанный код в файл, который называется human.ai . Запустите Word Editor. Откройте вашу любимую melee - карту и сохраните её под другим именем или (предпочтительней) в другой директории. Нажмите F12 (или откройте меню модулей и выберите менеджер импорта) . Select File --> Import file in the Import manager. Выберите созданный файл human.ai. Щёлкните правой кнопкой мыши на импортированном файле и выберите Modify file properties. Измените путь к файлу на “\Scripts\human.ai”. Сохраните карту (вам, вероятно, также нужно закрыть карту). Запустите WarCraft III, выберите ''Single game -> Custom Game -> Ваша милая карта’’. Убедитесь, что Вы играете против компьютера расы человека. Позже Вы захотите выбрать, чтобы вся карта стала видимой. Начните игру и ищите “Hello World!” на экране (она всё же быстро исчезает). Если Вы считаете, что надпись очень быстро исчезла, или Вы не уверены, что она вообще была там, Вы можете попробовать эту версию вместо той: Код:
Если Вы далеко от экрана более чем один час (3600 сек), Вы можете посмотреть на приветствие, нажав F12. 2. Сбор ресурсов Каждый знает, что сбор ресурсов является важной аспектом во время игры в Warcraft. Так почему бы не посмотреть на то, как должен быть сделан AI-скрипт для сбора: Код:
Опробуйте этот скрипт тем же способом, с каким опробовали вышеуказанный “Hello World!”. Вместо удаления более раннего импортированного файла, и дальнейшего добавления новой версии, Вы можете щёлкнуть правой кнопкой мыши (в менеджере импорта) на добавленный до этого файл и выбрать замену. Не забывайте всегда устанавливать полную видимость в дополнительных настройках игры, иначе вам будет нелегко увидеть, что делает AI-игрок. { Хотя можно воспользоваться чит-кодом “iseedeadpeople”} Почему мы восстанавливаем и переназначаем менеджеру сбора время? Что случится, если рабочий, рубящий дерево, умрёт? Если мы не восстановим то, что было мделано менеджером сбора, работник больше никогда не сможет быть заменён. . 3. Подготовка большего количества рабочих Если у нас есть только 5 работников, то их недостаточно, чтобы создать армию, поэтому давайте создадим гораздо больше рабочих. Код:
GetUnitCountDone('hpea') считает, как много людских крестьян, которых контролирует игрок. Это используется для того, чтобы высчитать, как много крестьян, которые не собирают золото и послать их рубить дерево. Почему бы вам не понаблюдать за компьютером, строящим тысячи рабочих? Другой способ, чтобы начать карту, полезную для наблюдения за игроками AI, которых мы разрабатываем, - это создать игру LAN, {то же, что и игра по локальной сети, только без дополнительных игроков.}. Если Вы установите дополнительные опции, чтобы позволить полное наблюдение и сделать наблюдателем самого себя, тогда Вы сможете изучать, как много ресурсов имеет AI-игрок при выборе тех или иных юнитов или зданий. Вы попытались? Построил ли он тысячи юнитов? Нет? Ему нужно больше пищи? Мы скоро сделаем это, построив несколько ферм… 4. Строительство ферм для поддержки большего количества рабочих Давайте построим несколько ферм, из-за чего мы сможем подготовить большее количество рабочих и получить больше золота. Если мы производим менее чем 3 дополнительных единицы пищи, тогда мы начинаем строить новую ферму. Код:
Благодаря этому получим множество рабочих и множество ресурсов, но не следует ли нам попытаться потратить ресурсы на что-то забавное? Если мы будем создавать больше строений, возможно, эти здания помогут нам тренировать армию. Почему бы нет? 5. Создание барака и подготовка нескольких солдат Настало время, чтобы предпринять наши первые меры к подготовке армии, которая разрушит всё сопротивление. Давайте начнем с создания барака и подготовим какого-нибудь пехотинца. Код:
Возможно, Вы обратили внимание, что AI через некоторое время одновременно остановило конструкцию ферм и строительство юнитов. Можете ли Вы вычислить, почему мы не строим больше ферм, когда мы вот-вот начнём испытывать недостаток пищи? Может быть мы запутались с тем, как много еды мы используем? Может быть, Вы могли бы попытаться уладить эту проблему сами, прежде чем я покажу решение её? (НАМЕК: Есть проблема в одном из условий). Прежде, чем мы сделаем код больше, подобно созданию других типов зданий, готовящих другие типы военных подразделений, может быть мы могли бы даже позволить подразделениям напасть на что-то? Почему бы нет, но это, вероятно, тяжело и выходит из области этого основного руководства. Прежде чем попытаться узнать, если это - трудно, самое время познать немного больше о Jass. Пора узнать полезность от присутствия некоторых функций. Это, может быть, даже время, чтобы узнать, где все те странные функции, которые мы использовали до этого, и как они действительно работают. Не уходите. 6. Больше теории Jass’a: управление действиями, условия и циклы Управление действиями - о том, как сделать возможным ходить разными путями в программе, {например, как устанавливать порядок действий. Можно создать множество действий, а потом сделать их последовательными благодаря условиям и циклам, а можно использовать это и в других целях...} Jass поддерживает это со своим if и циклическими конструкциями. Так давайте бегло ознакомимся с ними. {Примечание: данная часть статьи была переведена лишь потому, что здесь можно найти некоторые интересные примеры использования циклов при создании AI-скриптов.} if Существует несколько вариантов того, как может быть использован if. Но основная идея в том, что если что-то - истина, тогда мы сделаем какие-то действия, в противном случае мы сделаем нечто другое (или может быть вообще ничего не сделаем). Код:
Эй, а если мы захотим сделать что-то другое, если будем иметь всех крестьян? Код:
Это хорошо, если есть только две возможности, но что если нам нужно выбрать между тремя отдельными действиями? Код:
Путём добавления большего количества elseif’ов Вы можете сделать программу выбирающую между несколькими различными действиями. Просто убедитесь, что Вы поместили ваши условия в соответствующее место. Следующий скрипт неудачен: Код:
Если у нас есть один крестьянин, код скажет, что нам больше не нужны крестьяне. Это потому что условия проверяются сверху вниз. Loop Циклы - это повторяющаяся много раз вещь. Если вы использовали циклы в других языках, Вы можете ощутить неудобство с циклами Jass'а. Всё же есть способ реализации циклов while и for в Jass. Давайте сначала посмотрим на цикл, который будет запускаться вечно. Код:
Циклы, которые запускаются навсегда, используются, но они не очень гибкие. Так давайте введем строки, чтобы выйти из цикла. Код:
for Мы не имеем циклы for в Jass, но мы можем сделать цикл, который будет вести себя подобно циклу for. Код:
может быть сделан на Jass как Код:
А теперь давайте посмотрим на более конкретный пример. Код:
На Jass’e станет Код:
while Может быть, вам следует самому попытаться сделать это. Если вы не имеете обыкновение в использовать цикл while, просто проигнорируйте иго, Jass, во всяком случае, ничего не знает о нём. 7. Функции, которые мы использовали до этого Эта часть о тех функциях, которые мы использовали до этого, о том, как они работают, что они делают, и почему мы хотим, чтобы они делали только это. Для каждых функций, которые мы использовали, я укажу, как она объявлена в sourcefiles, объясню аргументы, что она делает и что возвращает. native Sleep takes real seconds returns nothing call Sleep( 3.5 ) // заставляет наш скрипт заснуть на 3,5 секунд Если мы никогда не спим, движок получается анормальным и выводит скрипт из строя после некоторого времени. constant native GetLocalPlayer takes nothing returns player local Player p = GetLocalPlayer() // {создаёт локального игрока p, которого мы используем, чтобы выдать текст именно ему (смотрите ниже)} native DisplayTextToPlayer takes player toPlayer, real x, real y, string message returns nothing call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, "Hello local player!" ) Нам нужно сообщить функции, что писать и кому. Изменяя нули на нечто другое, мы можем также контролировать, где текст появится на экране. Почувствуйте себя свободным для эксперимента, нули обычно работают всё же лучше. Это сообщение уйдет после некоторого времени. Время зависит от длины сообщения. native DisplayTimedTextToPlayer takes player toPlayer, real x, real y, real duration, string message returns nothing call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, 60, "Hello for 60 secs!" ) Также, как и выше, но теперь мы контролируем, как долго будет показываться текст. native ClearHarvestAI takes nothing returns nothing call ClearHarvestAI() // приказывает искусственному интеллекту, отвечающему за сбор, остановить сбор. Это используется с двумя функциями ниже, чтобы контролировать, как много рабочих собирают золото и дерево. native HarvestGold takes integer town, integer peons returns nothing call HarvestGold( 0, 5 ) // Сообщает 5 рабочим начать сбор золота в городе 0, который является главным городом. Если этот вызов сделан дважды, без ClearHarvestAI, 10 рабочих вместо 5 будут собирать золото. native HarvestWood takes integer town, integer peons returns nothing call HarvestWood( 0, 10 ) Работает точно также, как и выше, только вместо золота дерево. native SetProduce takes integer qty, integer id, integer town returns boolean local boolean success = SetProduce( 1, 'hpea', 0 ) // Попытается создать одного крестьянина в городе 0 (главный город). call SetProduce( 1, 'hpea', 0 ) Я не полностью верю обратной величине, но это, может быть, из-за того, что иногда я немного скептичен. native GetUnitCount takes integer unitid returns integer set numberOfPeasants = GetUnitCount( 'hpea' ) // Считает количество, крестьян, которое имеет AI-игрок. Это величина включает и тех крестьян, кто в то время создаётся. native GetUnitCountDone takes integer unitid returns integer set numberOfPeasants = GetUnitCount( 'hpea' ) // Считает количество, крестьян, которое имеет AI-игрок. Это величина не включает тех крестьян, кто в то время создаётся. Вы, вероятно, скажете, что всё это очень хорошо, но как я могу построить или сосчитать другие вещи? Мы скоро рассмотрим, какие секретные величины использованы, чтобы создавать другие вещи. 8. Когда нам следует что-то построить [код для добавления ] Эта часть статьи могла бы быть о конструировании наших собственных функций, но она бы требовала больше теории. Следовательно, мы рассмотрим, как мы можем узнать, когда мы должны строить новые здания и тренировать новых юнитов. Это не очень умно, чтобы пытаться создать стрелка, если у нас есть барак, но отсутствует кузница. Самый простой путь заставить AI создать здания будет только лишь позволить ему попытаться это сделать, игнорируя все зависимости. Если мы поместили бы все приказы строительства в цикле, это в конечном счете построит всё, что мы приказали бы. Но он всё же не будет работать очень хорошо, мы получим несколько зданий, подобно 3 кузнецам. Как затем эта проблема может быть решена? Если мы снова просмотрим часть четвёртую (Строительство ферм для поддержки большего количества рабочих) и пятую (Создание барака и подготовка нескольких солдат), то мы увидим, что есть несколько if'ов, условий, которые решают, что должно быть сделано. Мы должны быть способными создать несколько правил, которым должен следовать AI, чтобы построить хотя бы одно здание. Так, что мы ждём, давайте попробуем сделать это! Правило 1: Если у нас мало крестьян, нам нужно тренировать больше крестьян. Правило 2: Если у нас мало еды, нам нужно строить больше ферм. Правило 3: Если у нас нет казарм, мы должны построить казармы. Правило 4: Если у нас есть казармы, то мы должны тренировать пехотинцев. Правило 5: Если у нас есть казармы, мы должны построить кузницу. Правило 6: Если у нас нет алтаря, то мы должны построить алтарь. Правило 7: Если у нас есть алтарь, но нет героя, мы должны создать героя. Давайте посмотрим на эти правила, которые, надо надеяться, дадут нам армию пехотинцев и стрелков, лидируемых героем. Но почему Вы не подумали, как будете преобразовывать их в Jass, прежде, чем Вы прочитали? (Часть шестая, содержащая if-условия, может помочь.) Эх, ленитесь попытаться сделать что-то своё? Хорошо, я проведу вас через несколько из них. Давайте посмотрим, как мы можем реализовать правило первое на Jass, Оно будет похожим на это в условии if: Код:
Что делает few mean, и как много more? Давайте изменим правила вот так: Rule 1b: Если у нас меньше 10 крестьян, начинаем тренировать одного крестьянина. И попробуем преобразовать новое правило в Jass: Код:
Мило! Так давайте сделаем то же самое с другими правилами. Я укажу преобразованные правила и код. Попробуйте это сами, перед тем, как я. Правило 1b: Если мы имеем менее чем 10 крестьян, тогда начинаем тренировать 1 крестьянина. Правило 2b: Если мы имеем менее чем 6 дополнительных единиц пищи, тогда начинаем строить 1 ферму. Правило 3b: Если мы имеем менее чем 1 казарму, тогда начинаем строить ещё 1 казарму. Правило 4b: Если у нас есть более, чем 0 казарм, тогда начинаем тренировать одного пехотинца. Правило 5b: Если у нас есть более, чем 0 казарм и мы имеем меньше чем 1 кузнецу, тогда начинаем строить одну кузнецу. Правило 6b: Если мы имеем менее чем 1 алтарь, тогда начинаем строить 1 алтарь. Правило 7b: Если у нас есть более, чем 0 алтарей и мы имеем менее 1 героя, тогда начинаем готовить 1 героя. Правило 8b: Если у нас есть более 0 правил, не конвертированных в Jass, тогда начните преобразовывать первое правило на Jass. 9. Функции: Создание и использование Функции... чем они хороши, для чего, почему мы используем их? Хорошо... мы хотим, чтобы кто-нибудь еще написал много хороших функций для нас, чтобы вызывать их, так что мы не должны создавать их сами. И мы хотим создать несколько их самим себе, так что мы можем использовать свой код, отличный от других. Разделяй и властвуй . Поделите ваш код в несколько функциий, и затем завоевывайте каждую функцию. Давайте посмотрим на самую маленькую функцию: Код:
Эта функция совсем ничего не делает и ничего не даёт. Тем не менее, она содержит несколько частей, которые каждая функция должна иметь. Она начинается со слова function и заканчивается словом endfunction. После слова function идёт название функции, myFunc в данном случае. Следующим идёт слово takes и список всех аргументов, которые функция принимает. Эта функция ничего не принимает, {говоря иными словами, ей не нужно что-либо сообщать}. Она также ничего не возвращает. Что все это дает нам? Это дает нам функцию с именем myFunc, которое не берет никакие входные аргументы/параметры и не имеет обратную значение. Давайте теперь попытаемся сделать функцию, которая делает что-то, принимает какие-либо аргументы и возвращает значение. Код:
Сразу видно, что она делает, да? И не очень умно, мы могли бы просто использовать "+" в начале без функции. Давайте сделаем более полезную функцию, ту, которая убеждается, что все крестьяне убирают что-то. Код:
Эта функция берёт, как аргумент, как много крестьян, которым следует собирать золото (остальные собирают дерево). Она может быть вызвана из другой функции, похожей на это: Код:
, которая сделается функцией, поместив туда 5 крестьян, работающих в шахте, а остальных в лесу. Используя эту функцию в предшествующих программах, мы могли бы заменить несколько строк кода из основной функции вызовом функции resourceManager. Программа из части второй - сбор урожая, может теперь быть написана похожей на это: Код:
Убедитесь, что полезная функция, та, которая быть названа, находится перед той, которая вызывает её. В противном случае WarCraft III думает вроде этого: “Что это за странная функция? Никогда не слышал об этом. Я лучше убью этот сценарий, он выглядит, как повреждённый.” Другая полезная функция: Код:
Хорошо, хорошо, скажете Вы... но эта функция не создаст для нас армию. Хорошо... скоро мы создадим несколько функций, которые помогут нам создать большую армию. Терпение, пожалуйста. Сценарий для борьбы Давайте сначала перезапишем код из части пятой - создание барака и подготовка нескольких солдат. Чтобы увеличивать удобность для чтения и сделать управление кодом легче, сценарий разбит в другие разделы, которые оперируют ресурсами, подготовкой юнитов и строительством зданий. Код:
Этот код произведет отряд пехотинцев, который будет просто стоять и ничего не делать. Но об этом скоро позаботимся... Давайте начнём с создания AI, что произвольно бродит карте со своими пехотинцами. Надо надеяться, он найдет что-то, чтобы убить... Мы должны скоро также рассмотреть как встроенный в AI скрипт решает проблемы обманом... Код:
Попытайтесь создать несколько людей, борющихся друг с другом при помощи этого сценария… Следующий код будет связан со сценарием AI, действующем на игрока 2. Код:
Чтобы получать хранимую информацию из сценария AI, используйте следующее: Код:
Это работает только для целых чисел, конечно... Другие способы создать связь между Картой и сценарием AI включают в себя установку золота и лесоматериалов для некоторого игрока или установку собственной величины некоторому специфическому юниту. Это возможно также при использовании игрового кеша… не уверен, что это доступно из сценариев AI. Вот, собственно говоря, и всё. Отредактировано Sargeras, 19.06.2007 в 09:13. |
19.06.2007, 09:07 | #1
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
S
offline
Опыт:
43,833Активность: |
Труъ! Тянет на 2000 опыта :)
Слава Саргерасу, создателю первого внятного АИ! +) Отредактировано Sasha, 19.06.2007 в 11:09. |
19.06.2007, 09:38 | #2
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
Sargeras
Лидер "Двух Королевств"
offline
Опыт:
21,363Активность: |
Цитата:
Спасибо за тёплые слова.) |
|
19.06.2007, 09:44 | #3
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
FausT
offline
Опыт:
1,451Активность: |
Долго строчил? Зачет ето за размер, Мегазачет - статья рулезз (хотя еще и не чытал) сейчас скину на флешку, вдому прочитаю. Еще раз зачет!
Да у меня заказ - АИ для футменов. Если нету времени или лень написать, можешь кинуть мне в приват скороченой вариант. Отредактировано Dead_knight, 20.06.2007 в 04:13. |
19.06.2007, 13:11 | #4
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
Sargeras
Лидер "Двух Королевств"
offline
Опыт:
21,363Активность: |
FausT, на мой взгляд, в статье прекрасно написано и рассказано, как можно реализовать данный вид AI. набросайте условий, добавьте побольше юнитов и т.д. Сам я не смогу Вам помочь, потому что сейчас катастрофически не хватает времени из-за моего проекта. Спасибо за комментарии.
|
20.06.2007, 08:38 | #5
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
tysch_tysch
Работаем
online
Опыт: отключен
|
Sargeras разместишь на сайте?
|
21.06.2007, 23:07 | #6
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
Sargeras
Лидер "Двух Королевств"
offline
Опыт:
21,363Активность: |
ZlaYa1000, да, конечно, считайте, что уже разместил)
|
22.06.2007, 08:30 | #7
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|
PlayerDark
Coraline
offline
Опыт:
10,569Активность: |
Sargeras AI - шник ?
|
22.06.2007, 09:37 | #8
+0/−0
Профиль |
Приват |
Поиск |
IP: Записан
|