public static IServiceCollection AddWildArmsRandomizerServices(this IServiceCollection serviceCollection)
        {
            serviceCollection.AddSingleton <IRandomizerAgent, RandomizerAgent>();
            serviceCollection.AddTransient <IRandomizerManager, RandomizerManager>();

            serviceCollection.AddTransient <ISparsityMode, SparsityMode>();
            serviceCollection.AddTransient <IThreeOrbMode, ThreeOrbMode>();
            serviceCollection.AddTransient <IAnalysisMode, AnalysisMode>();

            serviceCollection.AddTransient <IAlwaysRunOption, AlwaysRunOption>();
            serviceCollection.AddTransient <IBossRebalancerOption, BossRebalancerOption>();
            serviceCollection.AddTransient <ICeciliaSpellsOption, CeciliaSpellsOption>();
            serviceCollection.AddTransient <IEventReducerOption, EventReducerOption>();
            serviceCollection.AddTransient <IExperienceFlattenerOption, ExperienceFlattenerOption>();
            serviceCollection.AddTransient <IItemPriceCorrectionOption, ItemPriceCorrectionOption>();
            serviceCollection.AddTransient <ISwitchAnywhereOption, SwitchAnywhereOption>();
            serviceCollection.AddTransient <IUberBelselkOption, UberBelselkOption>();
            serviceCollection.AddTransient <IVehiclesAvailableOption, VehiclesAvailableOption>();
            serviceCollection.AddTransient <ISoloFightBufferOption, SoloFightBufferOption>();

            serviceCollection.AddTransient <IAreaRandomizer, AreaRandomizer>();
            serviceCollection.AddTransient <IArmRandomizer, ArmRandomizer>();
            serviceCollection.AddTransient <IAttackRandomizer, AttackRandomizer>();
            serviceCollection.AddTransient <IElementRandomizer, ElementRandomizer>();
            serviceCollection.AddTransient <IEnemyRandomizer, EnemyRandomizer>();
            serviceCollection.AddTransient <IEventRandomizer, EventRandomizer>();
            serviceCollection.AddTransient <IFastDrawRandomizer, FastDrawRandomizer>();
            serviceCollection.AddTransient <IItemRandomizer, ItemRandomizer>();
            serviceCollection.AddTransient <IShoppingListRandomizer, ShoppingListRandomizer>();
            serviceCollection.AddTransient <ISpellRandomizer, SpellRandomizer>();
            serviceCollection.AddTransient <ISummonRandomizer, SummonRandomizer>();

            var attackTierList = new AttackTierList();

            attackTierList.LoadData(Resources.AttackTierList);
            serviceCollection.AddSingleton <IAttackTierList>(attackTierList);

            var bossOrbTierList = new BossOrbTierList();

            bossOrbTierList.LoadData(Resources.BossOrbGroups);
            serviceCollection.AddSingleton <IBossOrbTierList>(bossOrbTierList);

            var enemyTierList = new EnemyTierList();

            enemyTierList.LoadData(Resources.BossTierList);
            serviceCollection.AddSingleton <IEnemyTierList>(enemyTierList);

            var itemTierList = new ItemTierList();

            itemTierList.LoadData(Resources.ItemTierList);
            serviceCollection.AddSingleton <IItemTierList>(itemTierList);

            return(serviceCollection);
        }
        public void ShuffleBossOrder()
        {
            var toSwap  = new List <Tuple <int, int> >();
            var swapped = new HashSet <int>();

            foreach (var bossId in EnemyTierList.BossIds)
            {
                //determine new tier rank
                var  swapBossId   = bossId;
                byte newTier      = 0;
                byte originalTier = 0;
                while (swapBossId == bossId)
                {
                    originalTier = EnemyTierList.GetBossTier(bossId);
                    newTier      = RandomFunctions.GenerateGaussianByte(Agent.Rng, originalTier, Agent.Probabilities.BossShuffleStandardDeviation, (byte)(EnemyTierList.TieredBossIds.Count - 1));
                    if (newTier < 0)
                    {
                        newTier = 0;
                    }
                    //determine what boss to swap with based on new rank
                    var randNum = Agent.Rng.Next(0, EnemyTierList.TieredBossIds[newTier].Count);
                    swapBossId = EnemyTierList.TieredBossIds[newTier][randNum];
                }
                swapped.Add(bossId);
                swapped.Add(swapBossId);
                ScaleEnemies(originalTier, newTier, bossId, swapBossId);
                toSwap.Add(new Tuple <int, int>(bossId, swapBossId));
            }
            EnemyCollection.WriteObjects(Agent.GeneralConfiguration.TempFile);

            foreach (var t in toSwap)
            {
                EnemyCollection.SwapMappedObjects(Agent.GeneralConfiguration.TempFile, EnemyCollection.GetMappedObject(t.Item1), EnemyCollection.GetMappedObject(t.Item2));
            }

            /*
             * foreach (var t in toSwap)
             * {
             *  var bossA = EnemyCollection.GetMappedObject(t.Item1);
             *  var bossB = EnemyCollection.GetMappedObject(t.Item2);
             *  bossA.WriteByte((byte)t.Item2, EnemyOffsets.Id);
             *  bossB.WriteByte((byte)t.Item1, EnemyOffsets.Id);
             * }*/
        }
        private void ScaleEnemies(int oldTier, int newTier, int oldBossId, int newBossId)
        {
            if (newTier == oldTier)
            {
                return;
            }
            var oldBoss = EnemyCollection.GetMappedObject(oldBossId);
            var newBoss = EnemyCollection.GetMappedObject(newBossId);

            if (oldTier > newTier)
            {
                ScaleDownEnemy(oldBoss, newTier, oldTier);
                ScaleUpEnemy(newBoss, newTier, oldTier);
            }
            else
            {
                ScaleUpEnemy(oldBoss, oldTier, newTier);
                ScaleDownEnemy(newBoss, oldTier, newTier);
            }
            EnemyTierList.SwapTiers(oldBossId, newBossId);
        }