Заблаговременное планирование функций и улучшений

После долгого перерыва у меня появилась возможность вернуться к кодовой базе Осколков Онлайн и начать работать над некоторыми функциями.

Одной из первых вещей, которые я заметил, была зависимость нашего Lua-скрипта от стандартной функции Math.rand(), которая, учитывая ее зависящее от платформы поведение, мне показалась подозрительной для качественной генерации псевдослучайных чисел в будущем.

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

Кубок игральных костей

Идея была проста: взять старый предмет из Ultima Online (Cup and Dice) и реализовать такое же поведение игрового процесса в Shards.

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

Решения, Решения

Имея это в виду, вот как шел мыслительный процесс:

  1. Не было объекта генератора случайных чисел, посвященного игровой составляющей сервера. Я бы создал такой, который можно было бы использовать глобально и который был бы безопасен для потоков (чтобы один серверный процесс не пытался создать его экземпляр одновременно с другим).
  2. Этот новый синглтон «Rand» должен иметь заменяемый генератор псевдослучайных чисел (PRNG). Другими словами, я бы создал набор интерфейсов, которые стояли бы между кодом Lua и кодом Rand, чтобы, если я позже изменил PRNG на Mersenne Twister или реализацию WELL512, больше ничего во всей кодовой базе не пришлось бы менять. Для меня важна уверенность в будущем.
  3. Должен быть статический класс «Dice», чтобы простая команда, такая как Roll(1,6), выводила случайный бросок одной шестигранной кости (1d6).
  4. Кости должны поддерживать два основных использования: Roll(), при котором по умолчанию будет бросок 1d6, или Roll(numDice, numSides), при котором бросается определенное количество кубиков с определенным количеством граней и суммируется результат.
  5. Функция Roll() должна иметь разумные ограничения, чтобы кто-то не мог бросить 1 000 000 игральных костей с 1 000 000 граней и переполнить максимальное значение целого числа (~ 2,6 миллиарда для положительных чисел). Я выбрал кепку из 100 игральных костей, бросающих 1000 сторон.
  6. У меня не было никакого арта для чашки с игральными костями, поэтому мне пришлось использовать временный объект — в итоге это была обеденная тарелка, так как я не мог быстро найти объект чашки.
  7. Кажется, в Lua нет метода заставить неподвижные объекты говорить, поэтому я попросил пользователя, выполняющего действие, говорить за кости.

Тарелка невидимых костей

Некоторые выводы:

  • В тексте должно быть больше пользовательских сообщений, таких как комментарии Snake Eyes для двойных и Craps.
  • Разговор через объект игрока не отличается от случаев в Ultima Online, но UO использовала альтернативные цвета для текста и обычно окружала текст специальными символами, чтобы отличать его от Речи и Эмоций.

В следующий раз мы обсудим реальный код Lua для игры в кости и улучшение изображения.