Что лучший способ состоит в том, чтобы разрешить комбинаторный взрыв взаимодействий?

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

Давайте назовем это DeathBlaster 4: Deathening. В DB4 у Вас есть много Ship объекты, с которыми периодически и случайным образом встречаются Phenomena как они перемещаются. Данный Phenomenon может иметь нуль, один, или больше Effects на a Ship это встречается с ним. Например, у нас могло бы быть четыре вида Ships и три вида Phenomena.

                              Phenomena
              ==========================================
Ships         GravityWell     BlackHole      NebulaField
------------  ------------------------------------------
RedShip       +20% speed      -50% power     -50% shield
BlueShip no effect       invulnerable   death              Effects of Various
GreenShip     -20% speed      death          +50% shield        Phenomena on Ships
YellowShip    death           +50% power     no effect    

Кроме того, Effects может взаимодействовать друг с другом. Например, a GreenShip это находится в обоих a GravityWell и a NebulaField может получить некоторые совместные действия между сгенерированным SpeedEffect и ShieldEffect. В таких случаях синергетический эффект самостоятельно Effect - например, мог бы быть a PowerLevelSynergyEffect это следует из этого взаимодействия. Никакая информация кроме набора Effects действие на a Ship необходим для разрешения, каков конечный результат должен быть.

Можно начать видеть, что проблема появляется здесь. Как наивный первый подход, любой каждый Ship должен будет знать, как обработать каждый Phenomenon, или каждый Phenomenon должен будет знать о каждом Ship. Это очевидно недопустимо, таким образом, мы хотели бы переместить эти обязанности в другое место. Очевидно существует по крайней мере один внешний класс здесь, возможно, a Mediator или Visitor какой-то.

Но что лучший способ состоит в том, чтобы сделать это? Идеальное решение будет, вероятно, иметь эти свойства:

  • Столь же легкий добавить новое Ship поскольку это должно добавить новое Phenomenon.
  • Взаимодействия, которые не производят эффекта, являются значением по умолчанию и не требуют, чтобы дополнительный код представил. Конвенция по конфигурации.
  • Понимает как Effects взаимодействуйте друг с другом, и способно к управлению этими взаимодействиями для решения, каков конечный результат будет.

Я уже решил, каков мой подход будет, я думаю, но мне интересно слышать, каково согласие лучшего дизайна. Где Вы запустили бы? Какие проспекты Вы исследовали бы?



Последующее обновление: Спасибо за Ваши ответы, всех. Вот то, что я волновал выполнение. Мое основное наблюдение состояло в том что количество различных Effects кажется, является маленьким относительно количества возможных Phenomena × Ships взаимодействия. Таким образом, хотя существует много возможных комбинаций взаимодействий, количество видов результатов тех взаимодействий является меньшим числом.

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

Я представил третий класс, InteractionResolver, определить результат взаимодействий. Это содержит словарь, который отображается Ship-Phenomenon пары к Effects (которые являются в основном делегатом, который выполняет эффект и некоторые метаданные). Каждый Ship вручен EffectStack соответствие Effects это испытывает, когда результат вычислений взаимодействия завершен.

Ships затем используйте EffectStack определить фактический результат Effects на них, путем добавления модификаторов к их существующим атрибутам и свойствам.

Мне нравится это потому что:

  1. Поставки никогда не должны знать о Явлениях.
    • Сложность отношений Явлений Поставки абстрагирована в InteractionResolver.
    • Детали того, как разрешить несколько и возможно сложные эффекты, абстрагированы далеко InteractionResolver. Поставки только должны применить эффекты по мере необходимости.
    • Это включает дополнительные полезные рефакторинги. Например, путь, которым поставка обрабатывает эффекты, мог дифференцироваться путем создания EffectProcessorStrategy. Значение по умолчанию могло бы быть должно обработать все эффекты, но, скажем, a BossShip мог бы проигнорировать незначительные эффекты при наличии другого EffectProcessorStrategy.
10
задан John Feminella 18 November 2019 в 17:24
поделиться