public AttackResult Attack(Character attacker, Character defender, int? attackRoll = null) { if (attackRoll == null) { throw new NotImplementedException("Random dice roll not implemented; specify a roll"); } var result = new AttackResult { AttackRoll = attackRoll.Value }; var isCriticalHit = (attackRoll == 20); var isCriticalMiss = (attackRoll == 1); var attackDoesNotBeatArmor = ((attackRoll + attacker.GetModifier(Attribute.Strength)) < defender.EffectiveArmorClass); if (isCriticalMiss || attackDoesNotBeatArmor) { result.Success = false; return result; } result.Success = true; result.EarnedXP = XP_EARNED_FOR_SUCCESSFUL_ATTACK; var baseDamage = 1; var damageTaken = baseDamage + attacker.GetModifier(Attribute.Strength); if (isCriticalHit) damageTaken = damageTaken * 2; // strength modifier should never result in less than 1 point of damage if (damageTaken < 1) damageTaken = 1; result.Damage = damageTaken; defender.TakeDamage(damageTaken); return result; }