Qual é a melhor maneira de resolver uma explosão combinatória de interações?

Uma das coisas em que estou trabalhando agora tem algumas semelhanças com um jogo. Para fins de ilustração, vou explicar meu problema usando um exemplo retirado de um jogo hipotético e fictíci

Vamos chamá-loDeathBlaster 4: O Morte. No DB4, você tem um número deShipbjetos que periodicamente e aleatoriamente encontrPhenomena enquanto viajam. Um dadoPhenomenon pode ter zero, um ou maisEffects com umShip que encontra. Por exemplo, podemos ter quatro tipos deShips e três tipos dePhenomena.

                              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    

Além disso,Effects podem interagir um com o outro. Por exemplo, umGreenShip que está em umGravityWell eNebulaField pode derivar algum tipo de sinergia entre o @ geraSpeedEffect eShieldEffect. Nesses casos, o efeito sinérgico é em si umEffect - por exemplo, pode haver umPowerLevelSynergyEffect que resulta dessa interação. Nenhuma informação além do conjunto deEffects atuando em umShip é necessário para resolver qual deve ser o resultado fina

Você pode começar a ver um problema surgindo aqui. Como uma primeira abordagem ingênua, caShip precisará saber como lidar com cadaPhenomenon ou todos osPhenomenon terá que saber sobre cadaShip. Isso é obviamente inaceitável, então gostaríamos de mudar essas responsabilidades para outro lugar. Claramente, há pelo menos uma classe externa aqui, talvez umMediator ouVisitor de algum tipo

Mas qual é a melhor maneira de fazer isso? A solução ideal provavelmente terá essas propriedades:

Tão fácil quanto adicionar um novoShip como é adicionar um novoPhenomenon. Interações que não produzem efeito são o padrão e não exigem código adicional para representar. Convenção sobre configuração. Compreende comoEffects interagem entre si e é capaz de gerenciar essas interações para decidir qual será o resultado fina

cho que já decidi qual será minha abordagem, mas estou interessado em saber qual é o consenso de melhor design. Por onde você começaria? Que avenidas você exploraria?

Atualização de acompanhamento: Obrigado por suas respostas, pessoal. Aqui está o que eu acabei fazendo. Minha principal observação foi que o número de diferentesEffects parece pequeno em relação ao número possível dePhenomena × Ships interações. Ou seja, embora existam muitos possíveis combinações de interações, o número de tipos de resultados dessas interações é um número menor.

Você pode ver que, por exemplo, embora existam 12 combinações de interação na tabela, existem apenas cinco types de efeitos: modificações na velocidade, modificações no poder, modificações no escudo, invulnerabilidade, mort

Eu introduzi uma terceira classe, oInteractionResolver, para determinar o resultado das interações. Ele contém um dicionário que mapeiaShip-Phenomenon pares paraEffects (que são basicamente um delegado que executa o efeito e alguns metadados). CadaShip recebe umEffectStack correspondente aEffectsstá ocorrendo quando o resultado do cálculo da interação é concluíd

Ships, use oEffectStack para determinar o resultado real doEffects adicionando modificadores aos seus atributos e propriedades existente

Eu gosto disso porque:

s naves nunca precisam saber sobre os fenômeno complexidade do relacionamento Ship-Phenomena é abstraída no InteractionResolve Os detalhes de como resolver efeitos múltiplos e possivelmente complexos são abstraídos peloInteractionResolver. Os navios apenas precisam aplicar os efeitos conforme necessáriIsto permite refatorações úteis adicionais. Por exemplo, omaneir na qual um navio processa efeitos pode ser diferenciado criando umEffectProcessorStrategy. O padrão pode ser processar todos os efeitos, mas, digamos, umBossShip pode ignorar efeitos secundários ao ter umEffectProcessorStrategy.

questionAnswers(7)

yourAnswerToTheQuestion