Серия статей по написанию ИИ для многопользовательской онлайн игры жанра рогалик, ограниченного производительностью одноплатного компьютера.
В этой части статьи мы посмотрим на один из самых понятных и послушных ИИ в рогаликах, напишем простые правила, которыми можно будет легко управлять, и поговорим о сборе статистики.
Но перед этим немного о возвышенном: janvarev запустил очень удобный лидерборд, по которому можно отследить свой рейтинг среди игроков, которые играли в течение десяти дней. Присоединяйся и ты! Первые пять пользователей Гиктаймса, которые 30 сентября в лидерборде займут место выше, чемзолото открытку из Москвы! Я бедный студент, живу на стипендию Единственное условие — никнейм бота должен совпадать с никнеймом в Гиктаймсе (или хотя бы очень походить).
> Часть 1
> Часть 2
Для начала необходимо понять, что такое потенциальные поля (ПП), для этого нам нужны эта и эта статьи.
В целом, ПП можно представить как карту распространения сигнала от объекта на все клетки поля, огибая преграды. Вот, к примеру, распространение поля возле игрока R (id=4), чем темнее, тем слабее поле.
Существуют реализации с использованием псевдокода, что позволяет работать над ПП с большинством языков программирования.
Расчет потенциальных полей для всех рудников, игроков и таверн — не очень тяжелая задача, с которой даже одноплатный компьютер справляется при должной пряморукости программиста.
Теперь посмотрим на эту задачу полноценно:
Теперь будем работать по пунктам:
Тут говорить, честно говоря, не о чем. На официальном сайте доступны наборы для быстрого старта на 28 языках программирования. К слову, очень легко обойтись и без них, ведь там всего-лишь POST-запросы и работа с json. Для python существуют модули requests и json, которые сделают всю грязную работу сами. Во второй части был приведен код, который работает с ответами сервера.
Здесь нужно сказать пару слов:
Выше я сказал, что для реализации потенциального поля на своем ЯП нет преград. Лично мне понравилось очень лаконичное и быстрое решение отсюда, стоит только часть функции emit перенести в свой код, чутка доработав напильником. Нужно поделить все объекты на три категории:
— Пустота — сохраняет и распространяет дальше заряд поля. К таким объектам принадлежат спаунпоинты и пустые клетки. К слову, спаунпоинт должен распространять заряд, даже если на нем стоит персонаж.
— Барьер — не сохраняет и не распространяет дальше заряд поля. Такими объектами являются все препятствия, с которыми игрок не может взаимодействовать (отмечены на карте "##").
— Аккумулятор — сохраняет в себе значение заряда, но не распространяет дальше. Это нужно для того, чтобы поле огибало эти объекты. Такими объектами являются рудники, игроки, таверны В случае, если, к примеру, какой-то игрок заблокирует проход шириной в одну клетку, сигнал не сможет распространиться дальше.
Теперь, если есть смысл заморачиваться со скоростью работы, необходимо задачу разбить на N частей (в случае с одноплатным четырехъядерным компьютером N=3, чтобы сохранить одно ядро для основного процесса и для внутренних нужд операционной системы) и скормить карту и координаты процессам, чтобы получить потенциальные карты всех объектов (моя реализация на Python3 в один поток не справляется при размере карты 28х28 с 40+ объектами, приходится параллелить).
Теперь мы можем обратиться к любой точке карты, чтобы узнать расстояние объектов до нее.
Довольно топорно, неоптимизированно, однако для начала пойдет. Это был один из самых первых набросков ИИ для
Рассмотрим способы, с помощью которым можно искать рудники на карте:
Плюсы:
+ Самый простой способ.
Минусы:
— Все остальные составляющие этой затеи
Комментарий:
Если стоим на перепутье с одинаковым расстоянием до двух ближайших рудников, можно выбирать любой.
Три боя, выложенные чуть выше, раскрывают всю нежизнеспособность этого способа. Лишние ходы, нелогичные движения, наворачивание кругов — всё пестрит избыточностью.
Плюсы:
+Теперь ИИ будет выбирать количественно более приятный способ.
+ Легко реализуется.
Минусы:
— Существует способ и получше.
Комментарий:
Этот способ действительно невероятно хорош. Мы будем искать не самый близкий вариант, а самый хороший в краткосрочной перспективе. Для реализации можно использовать сложение всех весов при формуле, к примеру, 600/(n+1), где n- расстояние до объекта. Это поможет точно дойти до лучшего места при равном расстоянии, а также делает более привлекательными точки с большим количеством рудников. При этом стоит сделать сам рудник, к примеру, с весом 1000 единиц, ибо в противном случае клетка рядом с двумя рудниками будет обладать аналогичной привлекательностью, что и сам рудник (600/1 = 600/2 + 600/2). Средний показатель очков Эло за 100 битв увеличился с 1550 до 1833 только с изменением способа поиска рудников, это говорит о многом.
Часть карты, где такой способ будет действенным
Алгоритм таков:
Плюсы:
+Существенно более хороший способ поиска рудников.
+ Ищет оптимальные «цепи» для поиска рудников.
+ Самый эффективный способ, если бы не существование соперников.
Минусы:
— Может быть несколько ресурсозатратным.
— Не учитывает деятельность врагов.
Комментарий:
У этого способа есть достоинства, которые нельзя не принимать во внимание. Если поработать в этом направлении, то можно достичь значительного успеха, даже уложившись в ресурсы одноплатника. В качестве оценивающей функции можно использовать затраченное количество ходов и количество захваченных рудников или, к примеру,
Если есть задумка по поиску рудников, изложите его в комментариях, ибо мне мало что иное в голову приходит.
Но как убедиться, что изменение в движке бота сделало его лучше?
Определимся с собираемым материалом. Для меня выбор был прост:
— viewUrl — ссылка, по которой можно просмотреть бой
— место, которое мы заняли в бою
— соотношение нашего золота и золота победителя как показатель успешности боя
— текущее количество очков Эло
— выбыли ли мы из игры преждевременно (это может случиться, если были проблемы с интернетом или если мы пересекли лимит в 1 секунду на отправку решения)
— размер карты (который нередко коррелирует с выигрышным местом)
Теперь необходимо выбрать способ сохранения данной информации. Если выбирать из простого, есть два варианта: .scv и Google Forms. Стоит сказать, что GF может быть более удобным вариантом, так как он из-под коробки добавляет временную метку и статистика доступна онлайн. Как заносить ответы в форму можно поискать по запросу «submit google form язык_программирования».
А пока пользователям Гиктаймса вопрос номер 2:
На скриншоте представлен кусок карты:
Q — наш игрок
S — вражеский спаунпоинт
Программист Окноз решил добавить такое свойство: если у владельца вражеского спаунпоинта опасно малое количество очков здоровья, то спаунтпоинт начинает излучать отталкивающее потенциальное поле, которое не поощряет близкое нахождение возле этого спаунпоинта. Но игрок оказался в ловушке, став отличной добычей для вражеского игрока, как только он возродится. Окноз думает над тем, что же нужно сделать, чтобы таких ситуаций не случалось.
Есть догадки? Одно из возможных решений я напишу в комментариях под спойлером.
Вот так, шаг за шагом, можно создать смелого и могучего воина, который скрестит свои мечи с адептами альфа-бета отсечения и минимакса на равных!
В следующей части рассмотрим возможные варианты поведения для таверн, спаунпоинтов, соперников, посмотрим, как складываются поля, что такое блокировка приоритетным полем, рассмотрим, стоит ли закрашивать тупики. И, конечно, пара слов о конкурирующих алгоритмах.
> Ссылка на Vindinium
> Ссылка на сабреддит Vindinium — очень полезная вещь, там можно услышать ответы на очень интересные и заковыристые вопросы.
> Ссылка на мой гитхаб с небольшими старыми наработками по Vindinium
В этой части статьи мы посмотрим на один из самых понятных и послушных ИИ в рогаликах, напишем простые правила, которыми можно будет легко управлять, и поговорим о сборе статистики.
Но перед этим немного о возвышенном: janvarev запустил очень удобный лидерборд, по которому можно отследить свой рейтинг среди игроков, которые играли в течение десяти дней. Присоединяйся и ты! Первые пять пользователей Гиктаймса, которые 30 сентября в лидерборде займут место выше, чем
Zonko 0.11
, получат > Часть 1
> Часть 2
Потенциальные поля...
Для начала необходимо понять, что такое потенциальные поля (ПП), для этого нам нужны эта и эта статьи.
В целом, ПП можно представить как карту распространения сигнала от объекта на все клетки поля, огибая преграды. Вот, к примеру, распространение поля возле игрока R (id=4), чем темнее, тем слабее поле.
Существуют реализации с использованием псевдокода, что позволяет работать над ПП с большинством языков программирования.
Расчет потенциальных полей для всех рудников, игроков и таверн — не очень тяжелая задача, с которой даже одноплатный компьютер справляется при должной пряморукости программиста.
Теперь посмотрим на эту задачу полноценно:
- Получаем от сервера информацию о состоянии игры;
- Добываем координаты таверн, игроков, рудников — значимых игровых объектов;
- Считаем потенциальное поле всех игровых объектов, складываем в общий словарь вида:
Координата поля - id объекта - значение поля
; - Используя магию, получаем решение, в какую сторону пойдем в этот раз.
Теперь будем работать по пунктам:
1. Информация о состоянии игры
Тут говорить, честно говоря, не о чем. На официальном сайте доступны наборы для быстрого старта на 28 языках программирования. К слову, очень легко обойтись и без них, ведь там всего-лишь POST-запросы и работа с json. Для python существуют модули requests и json, которые сделают всю грязную работу сами. Во второй части был приведен код, который работает с ответами сервера.
2. Добываем координаты игровых объектов
Здесь нужно сказать пару слов:
- Координаты всех четырех игроков доступны в
game - heroes - hero_id - pos
; - Таверны и спаунпоинты — единственные неизменные объекты на карте. Они не перемещаются, не переходят из одних рук в другие. Их расположение можно запомнить раз и навсегда;
- Координаты рудников придется доставать из карты каждый раз, ибо они имеют свойство менять своего хозяина;
- Затем всё это упаковываем в один словарь «название — координата», при этом рудники и таверны следует пронумеровать.
Как конечный этап выглядит у меня:
При этом первый символ ключа обозначает тип объекта, последний — количество одинаковых объектов. 0, 1, 2, 3, 4 обозначают рудники и их принадлежность какому-либо игроку (0 — нейтральный рудник, 3 — рудник, принадлежащий третьему игроку). Q, W, E, R — четыре игрока соответственно, A, S, D, F — их спаунпоинты. В качестве значения представлены координаты.
{'0_0': [4, 2],
'0_1': [4, 13],
'0_2': [11, 2],
'0_3': [11, 13],
'A_0': [3, 3],
'D_0': [12, 12],
'E_0': [12, 12],
'F_0': [3, 12],
'Q_0': [3, 3],
'R_0': [3, 12],
'S_0': [12, 3],
'W_0': [12, 3],
't_0': [3, 4],
't_1': [3, 11],
't_2': [12, 4],
't_3': [12, 11]}
При этом первый символ ключа обозначает тип объекта, последний — количество одинаковых объектов. 0, 1, 2, 3, 4 обозначают рудники и их принадлежность какому-либо игроку (0 — нейтральный рудник, 3 — рудник, принадлежащий третьему игроку). Q, W, E, R — четыре игрока соответственно, A, S, D, F — их спаунпоинты. В качестве значения представлены координаты.
3. Просчитать потенциальные поля
Выше я сказал, что для реализации потенциального поля на своем ЯП нет преград. Лично мне понравилось очень лаконичное и быстрое решение отсюда, стоит только часть функции emit перенести в свой код, чутка доработав напильником. Нужно поделить все объекты на три категории:
— Пустота — сохраняет и распространяет дальше заряд поля. К таким объектам принадлежат спаунпоинты и пустые клетки. К слову, спаунпоинт должен распространять заряд, даже если на нем стоит персонаж.
— Барьер — не сохраняет и не распространяет дальше заряд поля. Такими объектами являются все препятствия, с которыми игрок не может взаимодействовать (отмечены на карте "##").
— Аккумулятор — сохраняет в себе значение заряда, но не распространяет дальше. Это нужно для того, чтобы поле огибало эти объекты. Такими объектами являются рудники, игроки, таверны В случае, если, к примеру, какой-то игрок заблокирует проход шириной в одну клетку, сигнал не сможет распространиться дальше.
Теперь, если есть смысл заморачиваться со скоростью работы, необходимо задачу разбить на N частей (в случае с одноплатным четырехъядерным компьютером N=3, чтобы сохранить одно ядро для основного процесса и для внутренних нужд операционной системы) и скормить карту и координаты процессам, чтобы получить потенциальные карты всех объектов (моя реализация на Python3 в один поток не справляется при размере карты 28х28 с 40+ объектами, приходится параллелить).
Многопроцессность для питона
Использую модуль concurrent.futures, очень поманила простота работы с процессами и потоками.
Как разбиваю задачу:
Как разбиваю задачу:
g = list(board.objects.keys()) # лист, содержащий ключи от словаря, представленного в спойлере выше
#магическое разбиение одного массива на три
if len(g)%3 == 0:
missions = (g[:len(g)//3], g[len(g)//3:2*len(g)//3], g[2*len(g)//3:])
else:
missions = (g[:len(g)//3+1], g[len(g)//3+1:2*len(g)//3+1] , g[2*len(g)//3+1:])
pot_field = zero_field(data['game']['board']['size']) # создаем пустое поле, в которое будем заносить результаты работы
with concurrent.futures.ProcessPoolExecutor(max_workers=3) as pool:
pp = []
for i in range(3):
#worker_layer решает потенциальные поля переданных ему объектов
pp.append(pool.submit(worker_layer, board, targets=missions[i], coors=targets))
for i in pp:
m = i.result()
# тут надо суммировать три поля в одно
if pot_field =='':
pot_field = m
else:
for key in pot_field.keys():
if key in m:
pot_field[key].update(m[key])
4. Магия
Теперь мы можем обратиться к любой точке карты, чтобы узнать расстояние объектов до нее.
Стартовый набор для сборки не самого умного ИИ
Для того, чтобы проверить, что мы до сих пор делаем всё правильно, предлагаю такую простую, но не лишенную изъянов, схему:
- Возьмем пять точек от нашего объекта: (x,y) — Stay, (x-1, y) — North, (x+1, y) — South, (x, y-1) — West, (x, y+1) — East. Исключим те точки, которые упираются в барьеры ("##").
- Для каждой из оставшихся точек:
- Найдем значение сигнала от ближайшей таверны, ближайшего не нашего рудника(=наименьшее значение сигнала по выбранным категориям);
- Возьмем answer = 0;
- Воспользуемся правилом для ближайшего рудника:
- Если наше_здоровье <21 и расстояние_до_рудника==0, то answer-=100;
- Иначе если расстояние до шахты ==0, то answer+=990;
- Иначе answer+=49+mod(50, расстояние_до_шахты+1);
- Воспользуемся правилом для ближайшей таверны:
- Если наше_здоровье>80 и расстояние_до_таверны==0, то answer-=100;
- Иначе если наше здоровье >50 или количество_золота<2, то игнор;
- Иначе если расстояние_до_таверны==0, то answer+=100;
- Иначе answer+=mod(mod(200, наше_здоровье), расстояние_до_таверны+1);
- Воспользуемся правилом для каждого врага:
- Если наше_здоровье-здоровье_врага>-19 и количество_рудников>0 и расстояние==1, то answer+=80;
- наше_здоровье-здоровье_врага>-19 и количество_рудников>0 и расстояние==1, то answer+=100;
- Иначе если расстояние<4 и наше_здоровье<45, то answer+= -100+8*расстояние;
- Выбираем точку с наибольшим значением answer, отправляем направление.
Довольно топорно, неоптимизированно, однако для начала пойдет. Это был один из самых первых набросков ИИ для
Zaraza 0.1
. Попробуйте запустить ИИ, следуя этим инструкциям, и увидите проблеск разума. За тем, как играет ИИ по таким правилам, можно посмотреть здесь, здесь и здесь. Становится понятно, что на больших картах, где нечасто приходится встречаться с врагами, ИИ может потягаться с драчунами, просто избегая встреч, а на средних и маленьких картах, где столкновения неизбежны, этот зачаток интеллекта не может сражаться с другими ИИ. Нужно провести работу по оптимизации движка.Исследование объектов: рудники
Рассмотрим способы, с помощью которым можно искать рудники на карте:
Способ 1 — идти к самому ближайшему руднику
Плюсы:
+ Самый простой способ.
Минусы:
— Все остальные составляющие этой затеи
Комментарий:
Если стоим на перепутье с одинаковым расстоянием до двух ближайших рудников, можно выбирать любой.
Три боя, выложенные чуть выше, раскрывают всю нежизнеспособность этого способа. Лишние ходы, нелогичные движения, наворачивание кругов — всё пестрит избыточностью.
Способ 2 — добавить веса за хороший выбор
Плюсы:
+Теперь ИИ будет выбирать количественно более приятный способ.
+ Легко реализуется.
Минусы:
— Существует способ и получше.
Комментарий:
Этот способ действительно невероятно хорош. Мы будем искать не самый близкий вариант, а самый хороший в краткосрочной перспективе. Для реализации можно использовать сложение всех весов при формуле, к примеру, 600/(n+1), где n- расстояние до объекта. Это поможет точно дойти до лучшего места при равном расстоянии, а также делает более привлекательными точки с большим количеством рудников. При этом стоит сделать сам рудник, к примеру, с весом 1000 единиц, ибо в противном случае клетка рядом с двумя рудниками будет обладать аналогичной привлекательностью, что и сам рудник (600/1 = 600/2 + 600/2). Средний показатель очков Эло за 100 битв увеличился с 1550 до 1833 только с изменением способа поиска рудников, это говорит о многом.
Способ 3 — какой-то план, которому он следует
Часть карты, где такой способ будет действенным
Алгоритм таков:
- Составляем список всех рудников, которые мы можем завоевать с текущим количеством здоровья (чтобы успешно захватить рудник, нужно обладать минимум 21 единицей здоровья. Очевидно, нас хватит максимум на 4 рудника).
- Мысленно идем до каждого рудника, завоевываем.
- Теперь повторяем пункт 1 и 2, начиная от места завоевания определенного рудника ровно до тех пор, пока у нас не будет список всех возможных сценариев по захвату близлежащих рудников (а у учеток количества здоровья, можно захватить не более четырех рудников), можно построить даже дерево таких комбинаций. Благо, расстояние от каждой точки до рудника у нас есть.
- Можно также посмотреть дальше — оценить расстояние до таверны, ведь она является жизненно необходимой вещью в этом круговороте.
- Выбрать самый вкусный вариант
Плюсы:
+Существенно более хороший способ поиска рудников.
+ Ищет оптимальные «цепи» для поиска рудников.
+ Самый эффективный способ, если бы не существование соперников.
Минусы:
— Может быть несколько ресурсозатратным.
— Не учитывает деятельность врагов.
Комментарий:
У этого способа есть достоинства, которые нельзя не принимать во внимание. Если поработать в этом направлении, то можно достичь значительного успеха, даже уложившись в ресурсы одноплатника. В качестве оценивающей функции можно использовать затраченное количество ходов и количество захваченных рудников или, к примеру,
(полученное количество золота)/(потраченное количество ходов)
. Здесь может быть много интересных идей.Способ Geektimes
Если есть задумка по поиску рудников, изложите его в комментариях, ибо мне мало что иное в голову приходит.
Но как убедиться, что изменение в движке бота сделало его лучше?
Собрать статистику за 50/100/250 игр!
Определимся с собираемым материалом. Для меня выбор был прост:
— viewUrl — ссылка, по которой можно просмотреть бой
— место, которое мы заняли в бою
— соотношение нашего золота и золота победителя как показатель успешности боя
— текущее количество очков Эло
— выбыли ли мы из игры преждевременно (это может случиться, если были проблемы с интернетом или если мы пересекли лимит в 1 секунду на отправку решения)
— размер карты (который нередко коррелирует с выигрышным местом)
Теперь необходимо выбрать способ сохранения данной информации. Если выбирать из простого, есть два варианта: .scv и Google Forms. Стоит сказать, что GF может быть более удобным вариантом, так как он из-под коробки добавляет временную метку и статистика доступна онлайн. Как заносить ответы в форму можно поискать по запросу «submit google form язык_программирования».
Задача на дом
А пока пользователям Гиктаймса вопрос номер 2:
На скриншоте представлен кусок карты:
Q — наш игрок
S — вражеский спаунпоинт
Программист Окноз решил добавить такое свойство: если у владельца вражеского спаунпоинта опасно малое количество очков здоровья, то спаунтпоинт начинает излучать отталкивающее потенциальное поле, которое не поощряет близкое нахождение возле этого спаунпоинта. Но игрок оказался в ловушке, став отличной добычей для вражеского игрока, как только он возродится. Окноз думает над тем, что же нужно сделать, чтобы таких ситуаций не случалось.
Есть догадки? Одно из возможных решений я напишу в комментариях под спойлером.
Заключение
Вот так, шаг за шагом, можно создать смелого и могучего воина, который скрестит свои мечи с адептами альфа-бета отсечения и минимакса на равных!
В следующей части рассмотрим возможные варианты поведения для таверн, спаунпоинтов, соперников, посмотрим, как складываются поля, что такое блокировка приоритетным полем, рассмотрим, стоит ли закрашивать тупики. И, конечно, пара слов о конкурирующих алгоритмах.
> Ссылка на Vindinium
> Ссылка на сабреддит Vindinium — очень полезная вещь, там можно услышать ответы на очень интересные и заковыристые вопросы.
> Ссылка на мой гитхаб с небольшими старыми наработками по Vindinium
rakovskij_stanislav Автор
А теперь усложним задачу. Что, если в конце тупика расположен рудник? Изолировать эту территорию будет неправильно в случаях с маленькими картами, где всего 4 рудника на карте и удерживание двух из них принесет победу. Что же тогда делать? Ответ: перетягивающие поля спаунпоинтов.
Сколько у нас спаунпоинтов? Четыре отметим их точками A, S, D, F. Мы застряли за одним из них — за D, к примеру. Сам игрок стоит на точке X. То есть можно сказать, что расстояние AD, SD, FD будут в любом случае больше или равны соответсвующим им расстояниям AX, SX и DX, что можно считать признаком того, что мы в тупике. Верно? Не совсем.
На фотографиии изображены два случая. Случай 1 — эталонный, случай 2 — исключение. Нужно что-то более сложное.
rakovskij_stanislav Автор
Однако такой способ хоть и хорошо помогает избежать заточения в мертвую зону, но всё равно не является идеальным, поэтому было бы неплохо рассмотреть другие варианты решения задачи (притягивание к тавернам? Таверны нередко находятся в этом самом тупике, которого мы хотим избежать, и пока мы сражаемся с вечно возрождающимся противником, мы теряем золото в таверне, наши рудники захватывают остальные два игрока. Тогда мб к середине карты? Но иногда бывает так, что середина карты заполнена лесом, поэтому определить середину проблематично. Как самая действенная идея — 8 клеток, которые образуют прицел на середину, но подробнее расскажу уже в следующей статье)
zuborg
При захвате рудников стоит отдавать предпочтение тем из них, которые заняты топовыми ботами (имеющими большее кол-во золота) — увеличивает шанс победы.
Просчитывать рекурсивно план захвата будет ресурсоемко, а без учета ходов противников ещё и малодейственно. Проще примитивно выбрать ближайшие N (с учетом текущего здоровья) доступных к захвату шахт (скорректировав их вес (1/dist) на ценность отбивания их у противников) и посчитать, движение в каком направлении имеет максимальное увеличение суммы весов этих N шахт). Это будет работать вполне неплохо, хотя и не всегда оптимально.
Ну и следует учитывать, что удачная стратегия заключается вовсе не в эффективном захвате шахт, а в успешном выживании и успешной охоте на других ботов. Иначе все эти эффективно захваченные шахты достанутся более умному боту ) Так что лучше посчитать в глубину план взаимодействия с другими ботами, а не просто захват шахт.
rakovskij_stanislav Автор
Мне даже и в голову не приходило строить козни против лидирующего соперника… Действительно замечательная идея! Я соберу статистику по играм с безыскусным захватом рудников и с целенаправленноым увеличением важности захватата рудников лидера.
Думаю, это новведение определенно точно принесет большую пользу, увеличив коэффицент успешности боя (рассчтывается как отношение моего золота и золота лидера). Спасибо за отличные идеи)
janvarev
Мой опыт (боты типа Elfar) показывает, что вроде как не очень работает — если отдавать предпочтение шахтам соперников (была у меня такая настройка), то бот вместо ближайших шахт предпочитает пилить до соседских (получается меньше золота) + больше вступает в бои. В результате у меня эффективность падала, но, может, это можно настроить.
Вообще идея строить козни да, есть :))
zavod
не вижу смысла учитывать, что у врага мало хп и он может вернуться на точку возрождения. Т.к.
1. через точку возрождения ближе
2. он может никогда на нее не вернуться
Надо учитывать точку возрождения, только если чужой игрок находится рядом с ней.
rakovskij_stanislav Автор
Тут есть определенные нюансы:
1. Если мы стоим именно на точке возрождения, то в случае смерти врага он нас убивает и захватывает все рудники.
2. В отличие от реальной жизни, противник не может быть внезапно смертным, т.е. можно оценить шанс того, что скоро он умрет.
3. Если мы попадем в эту ловушку, то шанс умереть составляет 100%, если противник имеет адекватные способности к сражениям; мы точно потеряем все рудники, да еще и впустую упустим несколько своих ходов.
Спаунпоинт — очень важная единица в игровом мире. Не следует пренебрегать ей, иначе можно сильно пожалеть.
janvarev
Есть еще такая особенность, что значимость этой ловушки сильно зависит от числа шахт на карте. Я, например, её не раз наблюдал в ситуации — маленькая карта до 10х10 и 4 шахты. Там, на мой взгляд, практически неважно как ты играешь — де-факто ты не можешь захватить больше 1 шахты на продолжительное время, потому что игроки быстро гибнут и быстро захватывают самую близкую шахту.
На таких картах, по моим наблюдениям, лучше всего работает минимаксный расчет ближайших вариантов — он все-таки позволяет Mini-Me (пока самый сильный играющий бот) зарабатывать больше золота к концу игры, хотя и не намного.
zavod
Про нюансы я согласен. Но если у вас нет рудников, то и респаун нет смысла учитывать в потенциальных полях. Т.к. самое худшее вам не повезет и вы окажетесь на своем респавне.
К тому же потенциально респавн может быть и привлекательным. Если вы знаете, что чужой игрок сейчас умрет, а вам нужно на свой респавн, т.к. там можно убить другого игрока и получить + по шахтам.