Career PickNextCareer(CharacterBuilderOptions options, Character character, Dice dice)
        {
            var careers = new List <Career>();

            //Forced picks (e.g. Draft)
            if (character.NextTermBenefits.MustEnroll != null)
            {
                foreach (var career in m_Careers)
                {
                    if (string.Equals(character.NextTermBenefits.MustEnroll, career.Name, StringComparison.OrdinalIgnoreCase) || string.Equals(character.NextTermBenefits.MustEnroll, career.Assignment, StringComparison.OrdinalIgnoreCase))
                    {
                        careers.Add(career);
                    }
                }
            }

            if (!character.NextTermBenefits.MusterOut && careers.Count == 0 && character.LastCareer != null)
            {
                if (dice.D(10) > 1) //continue career
                {
                    foreach (var career in m_Careers)
                    {
                        if (character.LastCareer.Name == career.Name && character.LastCareer.Assignment == career.Assignment)
                        {
                            careers.Add(career);
                        }
                    }
                }
                else
                {
                    character.NextTermBenefits.MusterOut = true;
                    character.AddHistory("Voluntarily left " + character.LastCareer.ShortName);
                }
            }

            //Random picks
            if (careers.Count == 0)
            {
                foreach (var career in m_Careers)
                {
                    if (character.NextTermBenefits.MusterOut && character.LastCareer.Name == career.Name && character.LastCareer.Assignment == career.Assignment)
                    {
                        continue;
                    }

                    if (career.Qualify(character, dice))
                    {
                        careers.Add(career);
                        character.Trace.Add("Qualified for " + career.Name + " at age " + character.Age);
                    }
                }
            }

            var result = dice.Choose(careers);

            character.Trace.Add("Selected " + result.Name + " at age " + character.Age);
            return(result);
        }
        static bool IsDone(CharacterBuilderOptions options, Character character, Dice dice)
        {
            if ((character.Age + 3) >= options.MaxAge) //+3 because terms are 4 years long
            {
                return(true);
            }

            if (character.Strength <= 0 ||
                character.Dexterity <= 0 ||
                character.Endurance <= 0 ||
                character.Intellect <= 0 ||
                character.Education <= 0 ||
                character.SocialStanding <= 0)
            {
                character.AddHistory($"Died at age {character.Age}");
                character.IsDead = true;
                return(true);
            }

            return(false);
        }
        public Character Build(CharacterBuilderOptions options)
        {
            var seed      = options.Seed ?? (new Random()).Next();
            var dice      = new Dice(seed);
            var character = new Character();

            character.Seed        = seed;
            character.FirstCareer = options.FirstCareer;
            character.Name        = options.Name;

            character.Strength       = dice.D(2, 6);
            character.Dexterity      = dice.D(2, 6);
            character.Endurance      = dice.D(2, 6);
            character.Intellect      = dice.D(2, 6);
            character.Education      = dice.D(2, 6);
            character.SocialStanding = dice.D(2, 6);

            if (character.EducationDM + 3 > 0)
            {
                var backgroundSKills = dice.Choose(m_BackgroundSkills, character.EducationDM + 3, allowDuplicates: false);
                foreach (var skill in backgroundSKills)
                {
                    character.Skills.Add(skill); //all skills added at level 0
                }
            }

            character.CurrentTerm      = 1;
            character.NextTermBenefits = new NextTermBenefits();

            if (!string.IsNullOrEmpty(options.FirstCareer))
            {
                character.NextTermBenefits.MustEnroll = options.FirstCareer;
            }

            while (!IsDone(options, character, dice))
            {
                var nextCareer = PickNextCareer(options, character, dice);
                character.CurrentTermBenefits = character.NextTermBenefits;
                character.NextTermBenefits    = new NextTermBenefits();
                nextCareer.Run(character, dice);

                character.CurrentTerm += 1;

                if (character.CurrentTerm >= 4)
                {
                    AgingRoll(character, dice);
                }
            }

            //Fixups
            if (options.MaxAge.HasValue && !character.IsDead)
            {
                character.Age = options.MaxAge.Value;
            }

            character.Title = character.CareerHistory.Where(c => c.Title != null).OrderByDescending(c => c.Rank + c.CommissionRank).Select(c => c.Title).FirstOrDefault();

            character.Skills.Collapse();

            return(character);
        }