Понимание требований
- Все игроки имеют ограниченное количество соседних противников.
Прежде всего, мы говорим о точках появления игроков, а не о текущей позиции игроков в данный момент в игре. Просто убираю это с дороги.
Смежные хорошо определены, когда мы говорим о графе. Мы можем думать о карте, которая отображает навигацию на карте - отныне «график».
Если узел can может иметь не более одной точки возрождения, то говорить о том, что они «смежны», имеет смысл. Примечание: я не буду ограничивать узлы, чтобы иметь максимум одну единственную точку появления, по причинам, которые будут очевидны позже.
Чтобы построить график, нам нужно будет рассмотреть такие вещи, как стены, мосты, лестницы, точки телепортации или даже рассмотреть пространство для полета, если может существовать игрок, способный летать. Каждый узел представляет собой проходимое местоположение; каждое соединение представляет возможное движение.
Примечание: узнайте размер и форму узлов и работайте с фактически смежными узлами. Не считайте узлы точкой. Не рассматривайте соединения как имеющие длину. Также используйте выпуклые узлы.
График мог быть предварительно скомпилирован (карта была создана дизайнером); в противном случае его можно создать на лету, если карта генерируется случайным образом.
- Все игроки имеют равные шансы встретить соседних врагов.
Я предполагаю, что враги - другие игроки. Опять же, просто убираю это с пути.
Предполагая, что каждый игрок совершает случайную прогулку, вероятность нахождения игрока в данной точке - на ровном пространстве, свободном от препятствий - будет определяться (гауссовой) функцией расстояния до точки появления - с этого момента функция».
Поскольку мы работаем над графиком, мы вместо этого будем аннотировать значения на графике.
- Размер карты не нужно увеличивать пропорционально количеству игроков.
Если бы у нас было ограничение на наличие одной точки появления на узел, то для добавления большего количества игроков нам потребовались бы меньшие узлы. Если мы определим график до того, как узнаем, сколько у нас будет игроков, нам, возможно, придется разделить узлы для конкретной игры.
- Эти ограничения не применяются для произвольных непроходимых мест.
Я не намерен добавлять препятствия для решения проблемы. В противоположность , мне нужно работать вокруг препятствий. Если бы их не было, реализация была бы проще.
Решение
Мы пытаемся разместить N точек появления так, чтобы шанс встретить другого игрока во всех этих точках появления был равным.
Мы можем получить меру ошибки как сумму различий между шансами и средними шансами. Мы пытаемся минимизировать это (фактически мы хотим сделать это 0).
Для этого нам нужно знать шанс встретить игрока на каждом узле графика.
Чтобы рассчитать этот шанс, начните с нуля. Поскольку шанс найти игрока на любом данном узле, когда нет игроков, равен нулю. И затем, для каждой точки появления, проходите график, добавляя к аннотированному шансу значение функции для текущей точки появления.
Примечание 1: Добавление или перемещение точки появления влияет на шанс встретить игрока на всей карте.
Примечание 2: Отслеживание того, насколько каждая точка появления влияет на шанс, упростит ситуацию.
Примечание 3: Поскольку узлы имеют размер, то насколько близко вы можете добраться до error = zero, зависит от размера узлов. Вы можете быть более точным, работая с диапазонами значений (минимальный и максимальный шанс, в зависимости от конкретной позиции точек появления в узле).
Разместите точки возрождения в случайном порядке, затем начните перемещать их таким образом, чтобы ошибка становилась меньше (рассмотрите возможное движение, и если ошибка уменьшится, сохраните ее, в противном случае верните ее). И продолжайте делать это, пока мы не сможем улучшить дальше (слишком много итераций без улучшения или ошибка равна нулю).
Примечание 4: При перемещении точки возрождения вы можете использовать шанс встречи с игроком (исключая точку возрождения, которую вы будете перемещать), чтобы случайным образом выбрать новую позицию для точки возрождения, такую, чтобы иметь возможность встретить игрока ближе к среднее значение более вероятно. Напоминаю, что перемещение точки появления влияет на среднее значение.
Ожидаемое поведение заключается в том, что точки появления, находящиеся слишком близко друг к другу, раздвигаются, а точки появления, находящиеся слишком далеко друг от друга, сближаются. Пока они не достигнут равновесия.
Если на какой-либо данной итерации у вас есть несколько точек появления на узле (что маловероятно, поскольку они должны стремиться разойтись, но возможно, если у вас достаточно большие узлы), разделите узел и продолжите решение. Любое разделение узла является действительным.
Вышеупомянутое решение приблизится к ошибке = ноль, но не гарантированно достигнет нуля. Вы можете запустить его, пока он не достигнет локального минимума ... Теоретически вы можете разделить узлы, чтобы сделать его ровно нулевым ... Тем не менее, это эквивалентно настройке координат точки возрождения!
Попробуйте смоделированный отжиг, чтобы переместить точку появления внутри узла. Хотя, если честно, вероятно, не стоит возиться с таким уровнем детализации.
Я хочу прояснить, что в результате для плоской карты, свободной от препятствий, не будет равномерно распределенных точек. Вместо этого, если у карты есть ребра (то есть, если она не переворачивается), тогда будет больше точек появления ближе к краям, это потому, что точки в центре могут быть достигнуты с большего количества направлений, увеличивая вероятность встречи другие игроки там. Таким образом, точки дальше от центра, чтобы компенсировать.