示例#1
0
        public IEnumerable<string> GetAllPossible(Alignment alignment, CharacterClass characterClass)
        {
            var tableName = string.Format(TableNameConstants.Formattable.Percentile.GOODNESSCLASSBaseRaces, alignment.Goodness, characterClass.Name);
            var baseRaces = percentileResultSelector.SelectAllFrom(tableName);

            return baseRaces.Where(r => RaceIsAllowed(r, characterClass.Level));
        }
示例#2
0
        private string GetStatToIncrease(Dictionary<string, Stat> stats, Race race, CharacterClass characterClass)
        {
            var statPriorities = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.StatPriorities, characterClass.Name);
            var undead = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.MetaraceGroups, GroupConstants.Undead);

            if (undead.Contains(race.Metarace))
                statPriorities = statPriorities.Except(new[] { StatConstants.Constitution });

            if (statPriorities.Any() == false)
            {
                var stat = collectionsSelector.SelectRandomFrom(stats.Keys);

                while (undead.Contains(race.Metarace) && stat == StatConstants.Constitution)
                    stat = collectionsSelector.SelectRandomFrom(stats.Keys);

                return stat;
            }

            var secondPriorityStats = statPriorities.Skip(1);
            if (secondPriorityStats.Any() == false)
                return statPriorities.First();

            var increaseFirst = booleanPercentileSelector.SelectFrom(TableNameConstants.Set.TrueOrFalse.IncreaseFirstPriorityStat);

            if (increaseFirst)
                return statPriorities.First();

            return collectionsSelector.SelectRandomFrom(secondPriorityStats);
        }
示例#3
0
        public Race GenerateWith(Alignment alignment, CharacterClass characterClass, RaceRandomizer baseRaceRandomizer, RaceRandomizer metaraceRandomizer)
        {
            var race = new Race();

            race.BaseRace = baseRaceRandomizer.Randomize(alignment, characterClass);
            race.Metarace = metaraceRandomizer.Randomize(alignment, characterClass);
            race.MetaraceSpecies = DetermineMetaraceSpecies(alignment, race.Metarace);
            race.IsMale = DetermineIfMale(race.BaseRace, characterClass.Name);
            race.Size = DetermineSize(race.BaseRace);
            race.HasWings = DetermineIfRaceHasWings(race);
            race.LandSpeed = DetermineLandSpeed(race);
            race.AerialSpeed = DetermineAerialSpeed(race);

            race.Age = DetermineAge(race, characterClass);

            var tableName = string.Format(TableNameConstants.Formattable.Adjustments.GENDERHeights, race.Gender);
            var baseHeights = adjustmentsSelector.SelectFrom(tableName);
            var heightModifier = GetModifier(race, TableNameConstants.Set.Collection.HeightRolls);
            race.HeightInInches = baseHeights[race.BaseRace] + heightModifier;

            tableName = string.Format(TableNameConstants.Formattable.Adjustments.GENDERWeights, race.Gender);
            var baseWeights = adjustmentsSelector.SelectFrom(tableName);
            var weightModifier = GetModifier(race, TableNameConstants.Set.Collection.WeightRolls);
            race.WeightInPounds = baseWeights[race.BaseRace] + heightModifier * weightModifier;

            return race;
        }
示例#4
0
        public String GenerateAllowingFocusOfAllFrom(String feat, String focusType, Dictionary<String, Skill> skills, IEnumerable<RequiredFeatSelection> requiredFeats, IEnumerable<Feat> otherFeats, CharacterClass characterClass)
        {
            if (focusType == FeatConstants.Foci.All)
                return focusType;

            return GenerateFrom(feat, focusType, skills, requiredFeats, otherFeats, characterClass);
        }
        public IEnumerable<string> GetAllPossible(Alignment alignment, CharacterClass characterClass)
        {
            var alignmentBaseRaces = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.BaseRaceGroups, alignment.Goodness);
            var classBaseRaces = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.BaseRaceGroups, characterClass.Name);

            return alignmentBaseRaces.Intersect(classBaseRaces).Intersect(new[] { SetBaseRace });
        }
示例#6
0
        public Item GenerateMeleeFrom(IEnumerable<Feat> feats, CharacterClass characterClass, Race race)
        {
            var meleeWeapons = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ItemGroups, AttributeConstants.Melee);
            var weapon = GenerateFiltered(feats, characterClass, race, meleeWeapons);

            return weapon;
        }
示例#7
0
        public Dictionary<string, Skill> GenerateWith(CharacterClass characterClass, Race race, Dictionary<string, Stat> stats)
        {
            var classSkills = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ClassSkills, characterClass.Name);
            var crossClassSkills = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.CrossClassSkills, characterClass.Name);

            var specialistSkills = Enumerable.Empty<string>();
            foreach (var specialistField in characterClass.SpecialistFields)
            {
                var newSpecialistSkills = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.SkillGroups, specialistField);
                specialistSkills = specialistSkills.Union(newSpecialistSkills);
            }

            classSkills = classSkills.Union(specialistSkills);

            if (characterClass.Name == CharacterClassConstants.Expert)
                classSkills = GetRandomClassSkills();

            var skills = InitializeSkills(stats, classSkills, crossClassSkills, characterClass);

            skills = AddRanks(characterClass, race, stats, classSkills, crossClassSkills, skills);

            var monsters = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.BaseRaceGroups, GroupConstants.Monsters);
            if (monsters.Contains(race.BaseRace))
                skills = AddMonsterSkillRanks(race, stats, skills);

            skills = ApplySkillSynergies(skills);

            return skills;
        }
        private IEnumerable<Feat> GetAdditionalFeats(CharacterClass characterClass, Race race, Dictionary<string, Stat> stats, Dictionary<String, Skill> skills,
            BaseAttack baseAttack, IEnumerable<Feat> preselectedFeats)
        {
            var additionalFeatSelections = featsSelector.SelectAdditional();
            var availableFeatSelections = additionalFeatSelections.Where(s => s.ImmutableRequirementsMet(baseAttack.RangedBonus, stats, skills, characterClass));

            var numberOfAdditionalFeats = characterClass.Level / 3 + 1;

            if (race.BaseRace == RaceConstants.BaseRaces.Human)
                numberOfAdditionalFeats++;

            if (characterClass.Name == CharacterClassConstants.Rogue && characterClass.Level >= 10)
                numberOfAdditionalFeats += (characterClass.Level - 10) / 3 + 1;

            var monsters = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.BaseRaceGroups, GroupConstants.Monsters);
            if (monsters.Contains(race.BaseRace))
            {
                var monsterHitDice = adjustmentsSelector.SelectFrom(TableNameConstants.Set.Adjustments.MonsterHitDice);
                numberOfAdditionalFeats += monsterHitDice[race.BaseRace] / 3 + 1;
            }

            var feats = PopulateFeatsFrom(characterClass, stats, skills, baseAttack, preselectedFeats, availableFeatSelections, numberOfAdditionalFeats);

            return feats;
        }
        private int GetClassSavingThrowBonus(CharacterClass characterClass, string savingThrow)
        {
            var strong = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ClassNameGroups, savingThrow);
            if (strong.Contains(characterClass.Name))
                return characterClass.Level / 2 + 2;

            return characterClass.Level / 3;
        }
示例#10
0
        public bool VerifyCharacterClassCompatibility(Alignment alignment, CharacterClass characterClass, ILevelRandomizer levelRandomizer, RaceRandomizer baseRaceRandomizer, RaceRandomizer metaraceRandomizer)
        {
            var baseRaces = baseRaceRandomizer.GetAllPossible(alignment, characterClass);
            var metaraces = metaraceRandomizer.GetAllPossible(alignment, characterClass);
            var races = GetAllRacePrototypes(baseRaces, metaraces);

            return races.Any(r => VerifyRaceCompatibility(r, characterClass, levelRandomizer));
        }
        public IEnumerable<Feat> GenerateWith(CharacterClass characterClass, Race race, Dictionary<string, Stat> stats,
            Dictionary<string, Skill> skills, BaseAttack baseAttack, IEnumerable<Feat> preselectedFeats)
        {
            var additionalFeats = GetAdditionalFeats(characterClass, race, stats, skills, baseAttack, preselectedFeats);
            var allButBonusFeats = preselectedFeats.Union(additionalFeats);
            var bonusFeats = GetBonusFeats(characterClass, race, stats, skills, baseAttack, allButBonusFeats);

            return additionalFeats.Union(bonusFeats);
        }
示例#12
0
        public bool VerifyRaceCompatibility(Race race, CharacterClass characterClass, ILevelRandomizer levelRandomizer)
        {
            if (levelRandomizer is ISetLevelRandomizer && (levelRandomizer as ISetLevelRandomizer).AllowAdjustments == false)
                return true;

            var levelAdjustments = adjustmentsSelector.SelectFrom(TableNameConstants.Set.Adjustments.LevelAdjustments);

            return characterClass.Level + levelAdjustments[race.BaseRace] + levelAdjustments[race.Metarace] > 0;
        }
示例#13
0
        private int GetClassHitPoints(CharacterClass characterClass, int constitutionBonus, Race race)
        {
            var undead = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.MetaraceGroups, GroupConstants.Undead);
            if (undead.Contains(race.Metarace))
                return RollHitPoints(characterClass.Level, 12, constitutionBonus);

            var hitDice = adjustmentsSelector.SelectFrom(TableNameConstants.Set.Adjustments.ClassHitDice);
            return RollHitPoints(characterClass.Level, hitDice[characterClass.Name], constitutionBonus);
        }
示例#14
0
        public Item GenerateFrom(IEnumerable<Feat> feats, CharacterClass characterClass, Race race)
        {
            var weapons = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ItemGroups, FeatConstants.Foci.Weapons);
            var ammunition = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ItemGroups, AttributeConstants.Ammunition);
            var nonAmmunitionWeapons = weapons.Except(ammunition);

            var weapon = GenerateFiltered(feats, characterClass, race, nonAmmunitionWeapons);
            return weapon;
        }
        public string Randomize(Alignment alignment, CharacterClass characterClass)
        {
            var baseRaces = GetAllPossible(alignment, characterClass);

            if (baseRaces.Any() == false)
                throw new IncompatibleRandomizersException();

            return baseRaces.Single();
        }
示例#16
0
        private bool ArmorIsValid(Item armor, IEnumerable<string> proficientArmors, CharacterClass characterClass, Race race)
        {
            if (armor == null)
                return true;

            if (armor.Attributes.Contains(AttributeConstants.Shield))
                return false;

            return IsValid(armor, proficientArmors, characterClass, race);
        }
示例#17
0
        public string Randomize(Alignment alignment, CharacterClass characterClass)
        {
            var results = GetAllPossible(alignment, characterClass);
            if (results.Any() == false)
                throw new IncompatibleRandomizersException();

            var tableName = string.Format(TableNameConstants.Formattable.Percentile.GOODNESSCLASSMetaraces, alignment.Goodness, characterClass.Name);

            return generator.Generate(() => percentileResultSelector.SelectFrom(tableName), m => results.Contains(m));
        }
示例#18
0
        public IEnumerable<SpellQuantity> GeneratePerDay(CharacterClass characterClass, Dictionary<string, Stat> stats)
        {
            var spellcasters = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ClassNameGroups, GroupConstants.Spellcasters);

            if (spellcasters.Contains(characterClass.Name) == false)
                return Enumerable.Empty<SpellQuantity>();

            var spellsPerDay = GetSpellsPerDay(characterClass, stats);
            return spellsPerDay.Where(s => s.Quantity > 0 || s.HasDomainSpell);
        }
示例#19
0
        public BaseAttack GenerateBaseAttackWith(CharacterClass characterClass, Race race, Dictionary<string, Stat> stats)
        {
            var baseAttack = new BaseAttack();
            baseAttack.BaseBonus = GetBaseAttackBonus(characterClass);
            baseAttack.SizeModifier = GetSizeAdjustments(race);
            baseAttack.StrengthBonus = stats[StatConstants.Strength].Bonus;
            baseAttack.DexterityBonus = stats[StatConstants.Dexterity].Bonus;
            baseAttack.RacialModifier = GetRacialBaseAttackAdjustments(race);

            return baseAttack;
        }
示例#20
0
        private CharacterClass GetEffectiveCharacterClass(CharacterClass characterClass)
        {
            if (characterClass.Name != CharacterClassConstants.Ranger)
                return characterClass;

            var effectiveCharacterClass = new CharacterClass();
            effectiveCharacterClass.Name = CharacterClassConstants.Druid;
            effectiveCharacterClass.Level = characterClass.Level / 2;

            return effectiveCharacterClass;
        }
示例#21
0
 public Character()
 {
     Alignment = new Alignment();
     Class = new CharacterClass();
     Race = new Race();
     InterestingTrait = string.Empty;
     Combat = new Combat();
     Ability = new Ability();
     Equipment = new Equipment();
     Magic = new Magic();
 }
示例#22
0
        private Age DetermineAge(Race race, CharacterClass characterClass)
        {
            var tableName = string.Format(TableNameConstants.Formattable.Adjustments.RACEAges, race.BaseRace);
            var ages = adjustmentsSelector.SelectFrom(tableName);

            var age = new Age();
            age.Maximum = GetMaximumAge(race, ages);
            age.Years = GetAgeInYears(race, characterClass, ages, age.Maximum);
            age.Stage = GetAgeStage(age.Years, ages);

            return age;
        }
示例#23
0
        public Item GenerateShieldFrom(IEnumerable<Feat> feats, CharacterClass characterClass, Race race)
        {
            var effectiveLevel = GetEffectiveLevel(characterClass);
            var tableName = string.Format(TableNameConstants.Formattable.Percentile.LevelXPower, effectiveLevel);
            var power = percentileSelector.SelectFrom(tableName);
            var proficientShields = GetProficientArmors(feats, AttributeConstants.Shield);

            if (proficientShields.Any() == false)
                return null;

            return generator.Generate(() => GenerateArmor(power),
                s => ShieldIsValid(s, proficientShields, characterClass, race));
        }
示例#24
0
        public void RaceRandomizerTestsSetup()
        {
            mockPercentileResultSelector = new Mock<IPercentileSelector>();
            mockAdjustmentsSelector = new Mock<IAdjustmentsSelector>();
            generator = new ConfigurableIterationGenerator();
            adjustments = new Dictionary<string, int>();
            characterClass = new CharacterClass();
            alignment = new Alignment();

            characterClass.Level = 1;

            mockAdjustmentsSelector.Setup(p => p.SelectFrom(TableNameConstants.Set.Adjustments.LevelAdjustments)).Returns(adjustments);
        }
示例#25
0
        public int GenerateWith(CharacterClass characterClass, int constitutionBonus, Race race, IEnumerable<Feat> feats)
        {
            var hitPoints = GetClassHitPoints(characterClass, constitutionBonus, race);

            var toughness = feats.Where(f => f.Name == FeatConstants.Toughness);
            hitPoints += toughness.Sum(f => f.Power);

            var monsters = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.BaseRaceGroups, GroupConstants.Monsters);
            if (monsters.Contains(race.BaseRace) == false)
                return hitPoints;

            var monsterHitPoints = GetAdditionalMonsterHitDice(race, constitutionBonus);
            return hitPoints + monsterHitPoints;
        }
示例#26
0
        private IEnumerable<string> AnimalsForCharacter(CharacterClass characterClass, Race race, Dictionary<string, int> levelAdjustments)
        {
            var animals = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.Animals, characterClass.Name);
            var animalsForSize = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.Animals, race.Size);
            var animalsWithinLevel = animals.Where(a => characterClass.Level + levelAdjustments[a] > 0);
            var filteredAnimals = animals.Intersect(animalsForSize).Intersect(animalsWithinLevel);

            var mages = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ClassNameGroups, GroupConstants.Mages);

            if (mages.Contains(characterClass.Name) == false)
                return filteredAnimals;

            var animalsForMetarace = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.Animals, race.Metarace);
            return filteredAnimals.Intersect(animalsForMetarace);
        }
        private IEnumerable<string> GenerateProhibitedFields(CharacterClass characterClass)
        {
            if (!characterClass.SpecialistFields.Any())
                return Enumerable.Empty<string>();

            var allProhibitedFields = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ProhibitedFields, characterClass.Name);
            var possibleProhibitedFields = allProhibitedFields.Except(characterClass.SpecialistFields);
            var prohibitedFieldQuantities = adjustmentsSelector.SelectFrom(TableNameConstants.Set.Adjustments.ProhibitedFieldQuantities);

            var prohibitedfieldQuantity = 0;
            foreach (var specialistField in characterClass.SpecialistFields)
                prohibitedfieldQuantity += prohibitedFieldQuantities[specialistField];

            return PopulateFields(prohibitedfieldQuantity, possibleProhibitedFields);
        }
示例#28
0
        public Ability GenerateWith(CharacterClass characterClass, Race race, Dictionary<string, Stat> stats, BaseAttack baseAttack)
        {
            var ability = new Ability();

            ability.Stats = stats;
            ability.Languages = languageGenerator.GenerateWith(race, characterClass.Name, ability.Stats[StatConstants.Intelligence].Bonus);
            ability.Skills = skillsGenerator.GenerateWith(characterClass, race, ability.Stats);
            ability.Feats = featsGenerator.GenerateWith(characterClass, race, ability.Stats, ability.Skills, baseAttack);

            var allFeatGrantingSkillBonuses = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.FeatGroups, FeatConstants.SkillBonus);
            var featNames = ability.Feats.Select(f => f.Name);
            var featNamesGrantingSkillBonuses = allFeatGrantingSkillBonuses.Intersect(featNames);
            var featGrantingSkillBonuses = ability.Feats.Where(f => featNamesGrantingSkillBonuses.Contains(f.Name));
            var allSkills = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.SkillGroups, GroupConstants.Skills);

            foreach (var feat in featGrantingSkillBonuses)
            {
                if (feat.Foci.Any())
                {
                    foreach (var focus in feat.Foci)
                    {
                        if (allSkills.Any(s => focus.StartsWith(s)) == false)
                            continue;

                        var skill = allSkills.First(s => focus.StartsWith(s));

                        if (ability.Skills.ContainsKey(skill) == false)
                            continue;

                        var circumstantial = allSkills.Contains(focus) == false;
                        ability.Skills[skill].CircumstantialBonus |= circumstantial;

                        if (circumstantial == false)
                            ability.Skills[skill].Bonus += feat.Power;
                    }
                }
                else
                {
                    var skillsToReceiveBonus = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.SkillGroups, feat.Name);

                    foreach (var skill in skillsToReceiveBonus)
                        if (ability.Skills.ContainsKey(skill))
                            ability.Skills[skill].Bonus += feat.Power;
                }
            }

            return ability;
        }
示例#29
0
        public IEnumerable<Spell> GeneratePrepared(CharacterClass characterClass, IEnumerable<Spell> knownSpells, IEnumerable<SpellQuantity> spellsPerDay)
        {
            var spellcasters = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ClassNameGroups, GroupConstants.Spellcasters);
            var spells = new List<Spell>();

            if (spellcasters.Contains(characterClass.Name) == false)
                return spells;

            foreach (var spellQuantity in spellsPerDay)
            {
                var levelSpells = GetPreparedSpellsForLevel(spellQuantity, knownSpells, characterClass);
                spells.AddRange(levelSpells);
            }

            return spells;
        }
        public IEnumerable<string> RegenerateSpecialistFields(Alignment alignment, CharacterClass characterClass, Race race)
        {
            if (characterClass.SpecialistFields.Any() == false || race.Metarace == RaceConstants.Metaraces.None)
                return characterClass.SpecialistFields;

            var allClassSpecialistFields = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.SpecialistFields, characterClass.Name);
            var allMetaraceSpecialistFields = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.SpecialistFields, race.Metarace);
            var applicableFields = allClassSpecialistFields.Intersect(allMetaraceSpecialistFields);

            if (applicableFields.Any() == false)
                return characterClass.SpecialistFields;

            var nonAlignmentFields = collectionsSelector.SelectFrom(TableNameConstants.Set.Collection.ProhibitedFields, alignment.ToString());
            var possibleSpecialistFields = applicableFields.Except(nonAlignmentFields);

            return PopulateFields(characterClass.SpecialistFields.Count(), possibleSpecialistFields);
        }