Как стать автором
Обновить

Баланс стоимости предметов в RPG с помощью линейной алгебры

Уровень сложностиСредний
Время на прочтение4 мин
Количество просмотров12K

Я обожаю RPG, меня привлекают их богатый сюжет, стратегическая глубина и захватывающие миры. Также меня восхищают data-driven подходы к разработке. Они не только улучшают логическую структуру игровых механик, но и гарантируют, что каждый элемент игры сбалансирован и вносит значимый вклад в опыт игрока. Баланс - один из самых сложных аспектов разработки игр, поскольку он требует тщательного внимания к взаимодействию игровых механик. Сегодня я расскажу о том, как использовать линейную алгебру для баланса стоимости предметов в игре.

В чём проблема?

Допустим, мы добавили в нашу игры базовые предметы, которые добавляют скорость атаки, урон, ману и т.д. На основе таких предметов довольно легко создать новые: например, в игре существует меч, дающий + 3 урона, стоит он 30 монет. Не составит труда оценить меч, дающий +9 урона: единица урона стоит 10 монет, следовательно, второй меч будет стоить примерно 90 монет. О том, почему примерно, мы поговорим дальше.

Но что если вы набросали несколько предметов, дающих разное количество характеристик, протестировали их, но их стоимость нельзя явно выразить через эти характеристики? Рассмотрим упрощенный пример:

  • Топор берсерка: дает 9 единиц урона и 2 единицы скорости атаки, стоит 40 монет,

  • Кинжал трикстера: 4 урона и 8 скорости атаки, стоит 35 монет,

  • Меч тамплиера: 5 урона и 5 скорости атаки, стоит 38 монет.

Это оружие можно представить в виде линейного уравнения:

\begin{cases} 9x+2y = 40 \\ 4x +8y = 35 \\ 5x+5y = 38 \end{cases}

Эта система не имеет решения, значит ли это что мы что-то сделали не так и теперь мы не можем балансить игру? Не совсем.

Система не имеет решения
Система не имеет решения

Применим линейную алгебру

Давайте попробуем решить эту систему уравнений иначе. Для этого запишем её в матричной форме:

A \cdot \vec{x}  = \vec{b},

где 𝐴- матрица коэффициентов, 𝑥 - вектор переменных, и 𝑏 - постоянный вектор.

A = \begin{bmatrix} 9 & 2 \\ 4 & 8\\ 5 & 5 \end{bmatrix}, \vec{x} = \begin{bmatrix} x\\ y\end{bmatrix}, \vec{b} = \begin{bmatrix} 40\\ 35\\38\end{bmatrix}

Обычно такие системы решаются с помощью обратных матриц:

\vec{x} = A^{-1} \cdot \vec{b},

Дело в том, что все нижеописанные операции можно автоматизировать в каком-нибудь wolfram или математических библиотеках для python, поэтому, если вам неинтересно как именно мы пытаемся найти решение системы уравнений, прочитайте спойлер и листайте до следующего заголовка).

Hidden text

В результате всех этих упражнений, система уравнений всё ещё не имеет решения

Чтобы определить, имеет ли данная система решение, мы исследуем ранг матрицы A и ранг расширенной матрицы Если ранг A меньше ранга расширенной матрицы, то система противоречива и не имеет решения. Запишем расширенную матрицу:

\begin{bmatrix}\begin{array}{c|c}         A & \vec{b}  \end{array} \end{bmatrix} =\begin{bmatrix}\begin{array}{cc|c}         9 & 2 & 40 \\  4 & 8 & 35\\  5 & 5 & 38 \\     \end{array} \end{bmatrix}

Чтобы найти ранг, мы можем выполнить операции над строками матрицы 𝐴, чтобы свести ее к ступенчатому виду:

Вычтем 4/9 раз первый столбец из второго, получим:

\begin{bmatrix} 9 & 2 \\ 0 & \frac{68}{9}\\ 5 & 5 \end{bmatrix}

Вычтем 5/9 раз первый столбец из третьего, получим:

\begin{bmatrix} 9 & 2 \\ 0 & \frac{68}{9}\\ 0 & \frac{40}{9} \end{bmatrix}

Эта ступенчатая форма строк показывает, что матрица 𝐴 имеет полный ранг (ранг 2), что означает, что исходные уравнения линейно независимы.

Теперь рассчитаем ранг расширенной матрицы \begin{bmatrix}\begin{array}{c|c}         A & \vec{b}  \end{array} \end{bmatrix}. Для этого также вычтем \frac{4}{9} раз первый столбец из второго и \frac{5}{9} раз из третьего:

\begin{bmatrix}\begin{array}{cc|c}         9 & 2 & 40 \\  0 & \frac{68}{9} & \frac{-55}{9}\\  0 & \frac{40}{9} & \frac{-82}{9} \\     \end{array} \end{bmatrix}

Упростим матрицу ещё сильнее: вычтем из третьего ряда второй, умноженный на \frac{40}{68} :

\begin{bmatrix}\begin{array}{cc|c}         9 & 2 & 40 \\  0 & \frac{68}{9} & \frac{-55}{9}\\  0 & 0 & \frac{-26}{17} \\     \end{array} \end{bmatrix}

Ранг дополненной матрицы \begin{bmatrix}\begin{array}{c|c}         A & \vec{b}  \end{array} \end{bmatrix}равен 3, что больше, чем ранг 𝐴, который равен 2.

Собственно, мы ещё раз доказали, что система уравнений противоречива и не имеет решения.

Так что же делать или Мура-Пенроуза

Мы исследовали эту систему уравнений со всех сторон, убедились в том, что она не имеет решений, неужели мы не сможем теперь высчитывать стоимость новых предметов в игре исходя только из их характеристик? Конечно, сможем. Именно на тот случай, когда не существует явного решения, человечество придумало псевдо-решения.

Давайте сначала разберёмся, что именно значит "система не имеет решения". Матричная запись \vec{x} = A^{-1} \cdot \vec{b} предполагает поиск обратной матрицы A^{-1}, но когда система не имеет решения, этой матрицы просто не существует. Однако, в начале-середине прошлого века два математика Элиаким Мур и Роджер Пенроуз сформулировали концепцию псевдообратной матрицы.  

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

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

То есть теперь мы имеем следующую формулу:

\vec{x} = A^{+} \cdot \vec{b},

Дальше мы найдём псевдообратную матрицу. Если вам неинтересен и этот процесс, то снова прочитайте спойлер и листайте к результату.

Hidden text
A^{+} = \begin{bmatrix} 0.1201 & −0.0399 & 0.0157 \\ −0.0753 & 0.1182 & 0.0411 \end{bmatrix}

Начнём с формулы расчёта псевдообратной матрицы

A^{+} = (A^{T}A)^{-1}A^{T}

Посчитаем A^{T}A:

A^{T}A = \begin{bmatrix} 9 & 4 & 5 \\ 2 & 8 & 5\end{bmatrix} \begin{bmatrix} 9 & 2\\ 4 & 8 \\ 5 & 5 \end{bmatrix} = \begin{bmatrix} 122 & 86\\ 86 & 93 \end{bmatrix}

Теперь перейдём к (A^{T}A)^{-1}:

(A^{T}A)^{-1} = \frac{1}{det(A^{T}A)} adj(A^{T}A),

где det(A^{T}A) - определитель A^{T}A, а adj(A^{T}A) - сопряжённая матрица

det(A^{T}A) = 122\cdot93−86\cdot86=4042−7396=−3354 \\ adj(A^{T}A) = \begin{bmatrix} 93 & -86\\ -86 & 122 \end{bmatrix}

Ну и отсюда следует, что:

(A^{T}A)^{-1} = \frac{1}{−3354} \begin{bmatrix} 93 & -86\\ -86 & 122 \end{bmatrix}

Теперь вычислим саму псевдообратную матрицу:

A^{+} =\frac{1}{−3354} \begin{bmatrix} 93 & -86\\ -86 & 122 \end{bmatrix}  \begin{bmatrix} 9 & 4 & 5 \\ 2 & 8 & 5\end{bmatrix} \\ A^{+} = \begin{bmatrix} 0.1201 & −0.0399 & 0.0157 \\ −0.0753 & 0.1182 & 0.0411 \end{bmatrix}

Результат

значения, которые мы получаем из \vec{x} представляют собой оптимальную стоимость каждой единицы урона и скорости атаки, рассчитанную по методу наименьших квадратов. Эти значения могут не полностью совпадать с первоначальной стоимостью предметов, но они предлагают последовательную стратегию ценообразования, которая наилучшим образом уравновешивает различные атрибуты всех предметов.

Приближенное решение с использованием псевдоинверсии Мура-Пенроуза дает нам следующую стоимость характеристик:

  • Стоимость единицы урона (x): примерно 4.01 монеты

  • Стоимость единицы скорости атаки (y): примерно 2.68 монеты

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

Вывод

Используя псевдоинверсию Мура-Пенроуза, мы можем устранить несоответствие в исходной стоимости предметов и найти приближенное решение, которое уравновешивает стоимость каждого атрибута для всех предметов.

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

Если вам интересны такого рода посты, можете подписаться на моq telegram, там я пишу посты поменьше

Теги:
Хабы:
Всего голосов 23: ↑21 и ↓2+25
Комментарии27

Публикации

Работа

Ближайшие события