Программирование ботов для Unreal Tournament 3

Опубликовано 16 декабря 08 12:32:00 | Coding4Fun

Если вам приходилось играть один на один с компьютером, вы, вероятней всего, сражались с управляемыми им «игроками», называемыми «ботами». Это компьютерные программы, созданные с применением принципов искусственного интеллекта (ИИ).До недавнего времени для создания собственных ботов для таких игр, как Unreal Tournament 3 требовалось глубокое изучение C++ и сложных процедур ИИ. Вполне понятно, что вам бы хотелось программировать своих ботов на C# или VB в Visual Studio Express. Именно этот способ здесь и описан.

Ваш первый бот

Создание нового бота начинается с очень простого класса, содержащего лишь конструктор и переопределенный метод ProcessActions().

C#

    1: using System;
    2: using System.Collections.Generic;
    3: using System.Linq;
    4: using System.Text;
    5:  
    6: using UT3Bots;
    7: using UT3Bots.UTItems;
    8: using System.Threading;
    9: using UT3Bots.Communications;
   10:  
   11:  
   12: namespace UT3UserBot
   13: {
   14:     public class MyBot : UTBot
   15:     {
   16:  
   17:         // Конструктор вашего бота
   18:         public MyBot() : base ("174.133.254.34", "Sitting Duck", BotMesh.Harbinger, BotColor.Red)
   19:         {
   20:         }
   21:  
   22:  
   23:         // Метод для управления ботом после его соединения с сервером
   24:         protected override void ProcessActions()
   25:         {
   26:             // Сюда добавьте код для выполнения некоторых действий с определенными интервалами
   27:         }
   28:     }
   29: }

VB

    1: Imports System
    2: Imports System.Collections.Generic
    3: Imports System.Linq
    4: Imports System.Text
    5:  
    6: Imports UT3Bots
    7: Imports UT3Bots.UTItems
    8: Imports System.Threading
    9: Imports UT3Bots.Communications
   10:  
   11:  
   12: Namespace UT3UserBot
   13:     Public Class MyBot
   14:         Inherits UTBot
   15:  
   16:         ' Конструктор вашего бота
   17:         Public Sub New()
   18:             MyBase.New("174.133.254.34", "Sitting Duck", BotMesh.Harbinger, BotColor.Red)
   19:         End Sub
   20:  
   21:  
   22:         ' Метод для управления ботом после его соединения с сервером
   23:         Protected Overloads Overrides Sub ProcessActions()
   24:             ' Сюда добавьте код для выполнения некоторых действий с определенными интервалами
   25:         End Sub
   26:     End Class
   27: End Namespace

Настройка вашего бота

Прежде всего вам надо настроить внешний вид бота, а уже затем действительно подключить его к серверу и ввести в игру. Это несложно, вам надо лишь изменить параметры, передаваемые базовому классу бота в конструкторе.

  • IP-адрес сервера (Server IPAddress) – первый параметр является IP-адресом сервера, к которому подключается бот. По умолчанию это адрес сервера UT3Bots, с которым мы играем в Интернете (ut.utbots.com); вы должны указать здесь адрес нужного вам сервера.
  • Имя (Name) – имя бота, которое будет отображаться в визуализаторе (Visualizer) и в игре.
  • Код бота (Bot Mesh) – разновидность бота на сервере.
  • Цвет бота (Bot Color) – цвет вашего бота.

Вот вы и готовы сыграть в UT3.

Нажмите F5, и ваш бот будет построен и запущен. Проект бота загрузит небольшое консольное приложение, предоставляющее сведения о том, что делает ваш бот.

Первый взгляд бота

Пора научить нашего бота что-нибудь делать. Прежде всего научим его двигаться в направлении точки навигации UTNavPoint. Это такое место в игре, где есть кое-что интересное. Последовательность UTNavPoints представляет путь в текущем уровне к интересным вещам. Бот может перемещаться в пределах уровня, двигаясь от одной точки UTNavPoint к другой.

Для описания положения чего-либо в инфраструктуре данной игры (UT3RemoteBot.dll) можно применять экземпляры класса UTVector. Положение точки UTNavPoint определяется ее свойством Location, которая задается как значение UTVector.

Наш бот должен иметь способ отслеживания своего перемещения, для чего в классе UT3UserBot создан закрытый UTVector с именем destinationLocation:

C#

    1: private UTVector destinationLocation;

VB

    1: Private destinationLocation As UTVector

Мы хотим, чтобы наш бот направлялся к первой точке, которую он «видит». Для этого мы добавляем в метод ProcessActions() следующий код:

C#

    1: this.destinationLocation = this.GameState.NavPointsVisible[0].Location;

VB

    1: Me.destinationLocation = Me.GameState.NavPointsVisible(0).Location

Свойство GameState нашего бота содержит сведения о текущем состоянии игры. NavPointsVisible — это список ссылок на экземпляры UTNavPoint, который определяет все точки UTNavPoint, которые бот может видеть в данный момент. В приведенном выше коде свойству destinationLocation присваивается UTVector в позиции 0 (первая точка, которую видит бот).

Таким образом, теперь бот знает, куда ему двигаться, и нам надо реализовать это движение.

Первые шаги бота

Научим бота двигаться к выбранной им точке. Добавьте в метод ProcessActions() сразу за кодом, написанным в предыдущем примере, следующий фрагмент:

C#

    1: this.Commands.RunTo(this.destinationLocation);

VB

    1: Me.Commands.RunTo(Me.destinationLocation)

Свойство Commands определяет совокупность методов, являющихся командами, которые ваша программа может давать боту. Этих команд довольно много, некоторые из них перечислены ниже. Полную информацию можно получить из описания API.

  • Jump() – подпрыгнуть на месте;
  • RotateBy() – повернуться на указанное число градусов;
  • RunTo() – перейти в указанное место;
  • StartFiring() – открыть огонь по некой цели или месту;
  • StopFiring() – прекратить огонь;
  • StrafeTo() – атаковать определенную позицию, глядя на другую.

В команде RunTo() указывается позиция места назначения. Выполнение этого метода приводит к перемещению вашего бота к указанному месту.

Запустив нашу программу, вы увидите, что бот пошел в направлении места назначения.

Первые выстрелы бота

В демонстрационных целях наш бот будет стрелять в точку, по направлению к которой он движется. Рекомендуется изменить эту цель в своей реализации, поскольку стрельба по пустому месту вряд ли имеет смысл.

Добавьте в метод ProcessActions() сразу за кодом, написанным в предыдущем примере, следующий фрагмент:

C#

    1: this.Commands.StartFiring(this.destinationLocation, false);

VB

    1: Me.Commands.StartFiring(Me.destinationLocation, false)

Запустив программу, вы увидите, что бот стреляет в точку, в которую движется. Он будет продолжать двигаться и стрелять, пока вы не вызовете метод, приказывающий остановиться, иначе он истратит все боеприпасы!

Добавьте в метод ProcessActions() сразу за кодом, написанным в предыдущем примере, следующий фрагмент:

C#

    1: this.Commands.StopFiring();

VB

    1: Me.Commands.StopFiring()

Теперь ваш бот прекратит стрельбу.

Теперь вы знаете, как заставить бота выполнять те или иные действия. Чтобы передвигаться и стрелять, надо всего лишь обращаться к свойству GameState для определения видимых ботом точек и к свойству Commands для вызова методов, реализующих действия.

Первая реакция бота

Научим бота реагировать на происходящие в игре события. Для этого надо реагировать на события, генерируемые ботом, посредством его свойства Events. Логично будет подписаться на события игры сразу при запуске бота, чтобы обладать всей возможной информацией и сделать бота разумным. Для этого надо подключить обработчик события к соответствующему событию в конструкторе бота.

В нашем примере мы подпишемся на событие OnSpawned, происходящее при каждом рождении бота в течении игры, будь то в самом начале или после смерти.

Поместите в конструктор класса MyBot следующий код:

C#

    1: void Events_OnSpawned(object sender, BotSpawnedEventArgs e)
    2: {
    3:     this.Commands.PerformEmote(Emote.PelvicThrust);
    4: } 

VB

    1: AddHandler Me.Events.OnSpawned, AddressOf Events_OnSpawned

Вам также надо добавить в этот класс новый метод, который будет вызываться при рождении бота.

Добавьте в класс MyBot следующий код:

C#

    2: {
    3:     this.Commands.PerformEmote(Emote.PelvicThrust);

VB

    1: Private Sub Events_OnSpawned(ByVal sender As Object, ByVal e As BotSpawnedEventArgs)
    2:     Me.Commands.PerformEmote(Emote.PelvicThrust)
    3: End Sub

Теперь при каждом своем рождении бот будет выполнять выпады. Это не добавит вам дополнительных очков, но может разжечь воображение!

Есть много событий, к которым вы можете привязать обработчики. Это позволит вам менять поведение бота в самых разных обстоятельствах. Подробности вы можете узнать в описании АPI (EN), а также при использовании IntelliSense в Visual Studio.

Наблюдение своего бота в действии

Оценить возможности своего бота вы можете с помощью сделанного нами специального визуализатора на Silverlight 2. Открыв веб-страницу визуализатора, вы увидите статус сервера и общую картину игры. Вы увидите пункты навигации, обозначенные зелеными точками, и активных игроков, имена которых указаны рядом с движущимися кружками и линиями, указывающими, в какую сторону они стоят лицом.

clip_image002

Что делать дальше

Ваш бот уже в игре и настало время сделать его полноценным ее участником. Обратите внимание на члены класса GameMap, с их помощью вы сможете искать оружие и дополнять здоровье. Обратите также внимание на члены класса GameState, предоставляющие данные об обстановке вокруг бота.

Одна вещь, которую вам надо добавить, — определение состояния бота в каждый момент времени. Такими состояниями могут быть «движется», «охотится», «простаивает», «восстанавливается» и пр. В зависимости от текущего состояния бота он будет выполнять разные действия при вызове ProcessActions.

Например, если он движется, он будет искать точку навигации. Если он в состоянии охоты, он будет преследовать других ботов. Если он в состоянии восстановления, он должен избегать других ботов и искать пакеты здоровья и т. д. Вы можете отслеживать состояние бота с помощью собственного перечисления с различными значениями. Ваш метод ProcessActions может содержать оператор switch, с тем чтобы выполнять различные ветви в зависимости от состояния.

Конечный автомат — это лишь один из вариантов применения ИИ в вашей программе. Вы можете пойти дальше и сделать бота настолько разумным, чтобы он определял результаты своих действий и выполнял дальнейшие действия в зависимости от этих результатов. Будьте осторожны с ProcessActions — эта процедура не должна долго выполняться, чтобы не образовывалась очередь необработанных событий, ожидающих ее окончания.

Завершение

Это руководство для начинающих наверняка поможет вам создать своего бойца для UT3.

Если вы почувствовали себя уверенно, присоединяйтесь к нашему проекту на CodePlex: https://www.codeplex.com/UT3Bots и помогайте усовершенствовать бот-клиент, визуализатор и даже серверный мутатор.

Успешной игры!