private static CombatResult CalculateInCombatEffects(MonsterCard attacker, MonsterCard defender)
        {
            CombatResult combatResult = CalculateDamage(attacker, defender);

            defender.Hp -= combatResult.DamageDealt;
            CalculateEffects(attacker, defender, AttributeTriggers.DuringAttack, combatResult);
            CalculateEffects(defender, attacker, AttributeTriggers.DuringAttack, combatResult);
            return(combatResult);
        }
        public static CombatResult Attacks(this MonsterCard attacker, MonsterCard defender, double attackDefenseRatioMultiplier = 22.5)
        {
            AttackDefenseRatioMultiplier = attackDefenseRatioMultiplier; // for test purposes

            CalculateBeforeCombatEffects(attacker, defender);
            CombatResult combatResult = CalculateInCombatEffects(attacker, defender);

            CalculateAfterCombatEffects(attacker, defender, combatResult);
            return(combatResult);
        }
        private static CombatResult CalculateDamage(MonsterCard attacker, MonsterCard defender)
        {
            bool   canHitCritical     = CalculateCanHitCritical(attacker);
            int    criticalMultiplier = 1;
            Random rnd = new Random();

            CalculateCriticalMultiplier(attacker, canHitCritical, rnd, ref criticalMultiplier);
            double randomMultiplier = (rnd.Next(100, 125) / 100d);
            double typeMultiplier   = GetTypeMultiplier(attacker, defender);
            double calculated       = (attacker.Atk / (double)defender.Def * AttackDefenseRatioMultiplier);

            CombatResult dei = new CombatResult
            {
                DamageDealt = (int)(criticalMultiplier * randomMultiplier * typeMultiplier * calculated),
                WasCritical = criticalMultiplier == 2
            };

            return(dei);
        }
        private static void CalculateAfterCombatEffects(MonsterCard attacker, MonsterCard defender, CombatResult combatResult)
        {
            CalculateEffects(attacker, defender, AttributeTriggers.AfterAttack);

            if (defender.Hp <= 0)
            {
                combatResult.DidDefenderDie = true;
            }

            CalculateEffects(defender, attacker, AttributeTriggers.AfterDefense);
            RevertEffects(attacker, defender, AttributeTriggers.BeforeAttack);
            RevertEffects(defender, attacker, AttributeTriggers.BeforeDefense);
        }
 private static void CalculateEffects(MonsterCard attacker, MonsterCard defender, AttributeTriggers trigger, CombatResult dei = null)
 {
     foreach (ICardAttributeAffectVariable attackerAttribute in attacker.Attributes.Where(x => x.TriggerAttributeOn == trigger))
     {
         IVariableParameter parameter = attackerAttribute switch
         {
             ICardAttributeAffectVariable <SelfCardParameter> => new SelfCardParameter(attacker),
             ICardAttributeAffectVariable <DoubleCardParameter> => new DoubleCardParameter(attacker, defender),
             ICardAttributeAffectVariable <DuringCardParameter> => new DuringCardParameter(attacker, dei),
         };
         attackerAttribute.Affect(parameter);
     }
 }