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)); }
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); }
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; }
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 }); }
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; }
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; }
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); }
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; }
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); }
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(); }
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); }
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)); }
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); }
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; }
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; }
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(); }
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; }
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)); }
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); }
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; }
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); }
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; }
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); }