public void RemoveEntries_PreserveAtZero_LeaveNone_GetExpectedOrderAndWeights()
        {
            var weightedList = new WeightedList<string>();
            
            weightedList.Add("A");
            weightedList.Add("B");
            weightedList.Add("C");

            weightedList.Add("A");
            weightedList.Add("B");
            weightedList.Add("C");

            weightedList.Add("A");
            weightedList.Add("B");

            weightedList.Remove("A", false);
            weightedList.Remove("A", false);
            weightedList.Remove("A", false);

            List<string> list = weightedList.ToSortedList();

            Assert.AreEqual(3, weightedList.Count);
            Assert.AreEqual(3, list.Count);
            Assert.AreEqual("A", list[0]);
            Assert.AreEqual("C", list[1]);
            Assert.AreEqual("B", list[2]);
            Assert.AreEqual("A", weightedList.GetMinWeight());
            Assert.AreEqual("B", weightedList.GetMaxWeight());
        }
Example #2
0
        public Card Draw()
        {
            Card result = cards.GetRandom();

            cards.Remove(result);
            return(result);
        }
        private static void FilterOnMapsWithEncountersWithValidContractRequirements(SimGameState simGameState, WeightedList <MapAndEncounters> activeMaps, List <Contract> currentContracts)
        {
            List <MapAndEncounters> mapsToRemove = new List <MapAndEncounters>();

            StarSystem system                = MissionControl.Instance.System;
            var        validParticipants     = AccessTools.Method(typeof(SimGameState), "GetValidParticipants").Invoke(simGameState, new object[] { system });
            MethodInfo GetValidFactionMethod = AccessTools.Method(typeof(SimGameState), "GetValidFaction");
            MethodInfo DoesContractMeetRequirementsMethod = AccessTools.Method(typeof(SimGameState), "DoesContractMeetRequirements");

            for (int i = 0; i < activeMaps.Count; i++)
            {
                MapAndEncounters level     = activeMaps[i];
                bool             removeMap = true;

                foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters)
                {
                    int contractTypeId = (int)encounterLayerMDD.ContractTypeRow.ContractTypeID;

                    // If the encounter ContractTypeID exists in the potential contracts list, continue
                    if (MissionControl.Instance.PotentialContracts.ContainsKey(contractTypeId))
                    {
                        // If the contract overrides in the potential contracts by ContractTypeID has a `DoesContractMeetRequirements` sucess, mark remove = false
                        List <ContractOverride> contractOverrides = MissionControl.Instance.PotentialContracts[contractTypeId];
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - contractOverrides count is: {contractOverrides.Count}");
                        for (int j = contractOverrides.Count; j > 0; j--)
                        {
                            ContractOverride contractOverride = contractOverrides[j - 1];
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - contractOverride is: {contractOverride.ID}");
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - validParticipants is: {validParticipants}");
                            bool doesContractHaveValidFactions = (bool)GetValidFactionMethod.Invoke(simGameState, new object[] { system, validParticipants, contractOverride.requirementList, null });
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Contract '{contractOverride.ID}' has valid fations?: {doesContractHaveValidFactions}");
                            if (!doesContractHaveValidFactions)
                            {
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Removing Contract '{contractOverride.ID}' from potential list");
                                contractOverrides.RemoveAt(j - 1);
                                continue;
                            }

                            bool doesContractMeetReqs = (bool)DoesContractMeetRequirementsMethod.Invoke(simGameState, new object[] { system, level, contractOverride });
                            if (doesContractMeetReqs)
                            {
                                // At least one contract override meets the requirements to prevent the infinite spinner so ignore this logic now and continue to the next map/encounter combo
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Level '{level.Map.MapName}.{encounterLayerMDD.Name}' has at least one valid contract override");
                                removeMap = false;
                                break;
                            }
                        }
                    }
                }

                if (removeMap)
                {
                    // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Level '{level.Map.MapName}' had no encounters with any valid contract overrides. Removing map.");
                    mapsToRemove.Add(level);
                }
            }

            // Remove maps that have no valid contracts due to failing requirements
            foreach (MapAndEncounters level in mapsToRemove)
            {
                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Attempting to remove Level '{level.Map.MapName}'");
                activeMaps.Remove(level);
            }

            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] There are '{activeMaps.Count}' active maps/encounter combos to use. These are:");

            /*
             * for (int k = 0; k < activeMaps.Count; k++) {
             * MapAndEncounters level = activeMaps[k];
             * Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] - '{level.Map.MapName}' with '{level.Encounters.Length}' encounters");
             * foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters) {
             *  Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements]   - Encounter '{encounterLayerMDD.Name}'");
             * }
             * }
             */
        }
        private static void FilterOnMapsWithEncountersWithValidContractRequirements(SimGameState simGameState, WeightedList <MapAndEncounters> activeMaps, List <Contract> currentContracts)
        {
            List <MapAndEncounters> mapsToRemove = new List <MapAndEncounters>();
            StarSystem system                = MissionControl.Instance.System;
            var        validParticipants     = AccessTools.Method(typeof(SimGameState), "GetValidParticipants").Invoke(simGameState, new object[] { system });
            MethodInfo GetValidFactionMethod = AccessTools.Method(typeof(SimGameState), "GetValidFaction");
            MethodInfo DoesContractMeetRequirementsMethod = AccessTools.Method(typeof(SimGameState), "DoesContractMeetRequirements");

            for (int i = 0; i < activeMaps.Count; i++)
            {
                MapAndEncounters level = activeMaps[i];
                List <int>       checkedContractTypeIds = new List <int>();
                bool             removeMap = true;

                // Main.LogDebug($"");
                // Main.LogDebug($"--- PROCESSING MAP '{level.Map.MapName}' ---");
                // Main.LogDebug($"");

                foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters)
                {
                    int contractTypeId = (int)encounterLayerMDD.ContractTypeRow.ContractTypeID;

                    // Main.LogDebug($"");
                    // Main.LogDebug($"--- PROCESSING CONTRACT TYPE {contractTypeId} ---");
                    // Main.LogDebug($"");

                    // If the encounter ContractTypeID exists in the potential contracts list, continue
                    if (MissionControl.Instance.PotentialContracts.ContainsKey(contractTypeId) && !checkedContractTypeIds.Contains(contractTypeId))
                    {
                        checkedContractTypeIds.Add(contractTypeId);
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' is within potential contracts.");

                        // If the contract overrides in the potential contracts by ContractTypeID has a `DoesContractMeetRequirements` success, mark remove = false
                        List <ContractOverride> contractOverrides = MissionControl.Instance.PotentialContracts[contractTypeId];
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - There are '{contractOverrides.Count}' ContractOverrides (contracts)");
                        for (int j = contractOverrides.Count; j > 0; j--)
                        {
                            ContractOverride contractOverride = contractOverrides[j - 1];
                            // Main.LogDebug("");
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Encounter '{encounterLayerMDD.Name}' Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - ContractOverride is: {contractOverride.ID}");
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - ValidParticipants is: {validParticipants}. Cannot extract factions/participants due to BT intern restrictions.");

                            bool doesContractHaveValidFactions = (bool)GetValidFactionMethod.Invoke(simGameState, new object[] { system, validParticipants, contractOverride.requirementList, null });
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - Contract '{contractOverride.ID}' has valid fations?: {doesContractHaveValidFactions}");
                            if (!doesContractHaveValidFactions)
                            {
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - Removing Contract '{contractOverride.ID}' from potential list due to not having any valid factions/participants on the contract.");
                                contractOverrides.RemoveAt(j - 1);
                                continue;
                            }

                            bool doesContractMeetReqs = (bool)DoesContractMeetRequirementsMethod.Invoke(simGameState, new object[] { system, level, contractOverride });
                            if (!doesContractMeetReqs)
                            {
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - Contract '{contractOverride.ID}' FAILS requirements with level '{level.Map.MapName}.{encounterLayerMDD.Name}'. Removing Contract '{contractOverride.ID}' from potential list due to not having met requirements on the contract.");
                                contractOverrides.RemoveAt(j - 1);
                                continue;
                            }

                            // At least one contract override meets the requirements to prevent the infinite spinner so ignore this logic now and continue to the next map/encounter combo
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - Contract '{contractOverride.ID}' MEETS requirements with level '{level.Map.MapName}.{encounterLayerMDD.Name}' and has at least one valid contract override. Will keep as a possible 'active map' for selection on.");
                            removeMap = false;
                        }
                    }
                    else if (checkedContractTypeIds.Contains(contractTypeId))
                    {
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Skipping checks for Encounter '{encounterLayerMDD.Name}' because already checked Contract Type '{encounterLayerMDD.ContractTypeRow.Name}'");
                    }
                    else
                    {
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Contract Type '{encounterLayerMDD.ContractTypeRow.Name}' - Doesn't exist in the potential contracts.");
                    }
                }

                if (removeMap)
                {
                    // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Level '{level.Map.MapName}' had no encounters with any valid contract overrides. Removing map.");
                    mapsToRemove.Add(level);
                }
            }

            // Remove maps that have no valid contracts due to failing requirements
            foreach (MapAndEncounters level in mapsToRemove)
            {
                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Attempting to remove Level '{level.Map.MapName}'");
                activeMaps.Remove(level);
            }

            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] There are '{activeMaps.Count}' active maps/encounter combos to use. These are:");
            for (int k = 0; k < activeMaps.Count; k++)
            {
                MapAndEncounters level = activeMaps[k];
                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{level.Map.MapName}' with '{level.Encounters.Length}' encounters");
                foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters)
                {
                    // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Encounter '{encounterLayerMDD.Name}'");
                }
            }
        }
        private static void FilterOnMapsWithEncountersWithValidContractRequirements(SimGameState simGameState, WeightedList <MapAndEncounters> activeMaps, List <Contract> currentContracts)
        {
            List <MapAndEncounters> mapsToRemove = new List <MapAndEncounters>();

            StarSystem system                = MissionControl.Instance.System;
            var        validParticipants     = AccessTools.Method(typeof(SimGameState), "GetValidParticipants").Invoke(simGameState, new object[] { system });
            MethodInfo GetValidFactionMethod = AccessTools.Method(typeof(SimGameState), "GetValidFaction");
            MethodInfo DoesContractMeetRequirementsMethod = AccessTools.Method(typeof(SimGameState), "DoesContractMeetRequirements");

            for (int i = 0; i < activeMaps.Count; i++)
            {
                MapAndEncounters level     = activeMaps[i];
                bool             removeMap = true;

                foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters)
                {
                    int contractTypeId = (int)encounterLayerMDD.ContractTypeRow.ContractTypeID;

                    // If the encounter ContractTypeID exists in the potential contracts list, continue
                    if (MissionControl.Instance.PotentialContracts.ContainsKey(contractTypeId))
                    {
                        // If the contract overrides in the potential contracts by ContractTypeID has a `DoesContractMeetRequirements` sucess, mark remove = false
                        List <ContractOverride> contractOverrides = MissionControl.Instance.PotentialContracts[contractTypeId];
                        // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - contractOverrides count is: {contractOverrides.Count}");
                        for (int j = contractOverrides.Count; j > 0; j--)
                        {
                            ContractOverride contractOverride = contractOverrides[j - 1];
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - contractOverride is: {contractOverride.ID}");
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - validParticipants is: {validParticipants}");
                            bool doesContractHaveValidFactions = (bool)GetValidFactionMethod.Invoke(simGameState, new object[] { system, validParticipants, contractOverride.requirementList, null });
                            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Contract '{contractOverride.ID}' has valid fations?: {doesContractHaveValidFactions}");
                            if (!doesContractHaveValidFactions)
                            {
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Removing Contract '{contractOverride.ID}' from potential list");
                                contractOverrides.RemoveAt(j - 1);
                                continue;
                            }

                            bool doesContractMeetReqs = (bool)DoesContractMeetRequirementsMethod.Invoke(simGameState, new object[] { system, level, contractOverride });
                            if (doesContractMeetReqs)
                            {
                                // At least one contract override meets the requirements to prevent the infinite spinner so ignore this logic now and continue to the next map/encounter combo
                                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] '{contractTypeId}' - Level '{level.Map.MapName}.{encounterLayerMDD.Name}' has at least one valid contract override");
                                removeMap = false;
                                break;
                            }
                        }
                    }
                }

                if (removeMap)
                {
                    // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Level '{level.Map.MapName}' had no encounters with any valid contract overrides. Removing map.");
                    mapsToRemove.Add(level);
                }
            }

            // Remove maps that have no valid contracts due to failing requirements
            foreach (MapAndEncounters level in mapsToRemove)
            {
                // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] Attempting to remove Level '{level.Map.MapName}'");
                activeMaps.Remove(level);
            }

            // Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] There are '{activeMaps.Count}' active maps/encounter combos to use. These are:");

            /*
             * for (int k = 0; k < activeMaps.Count; k++) {
             * MapAndEncounters level = activeMaps[k];
             * Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements] - '{level.Map.MapName}' with '{level.Encounters.Length}' encounters");
             * foreach (EncounterLayer_MDD encounterLayerMDD in level.Encounters) {
             *  Main.LogDebug($"[FilterOnMapsWithEncountersWithValidContractRequirements]   - Encounter '{encounterLayerMDD.Name}'");
             * }
             * }
             */

            // If there are no more active maps, reset the biomes/maps list
            if (activeMaps.Count <= 0)
            {
                Main.Logger.LogWarning($"[FilterOnMapsWithEncountersWithValidContractRequirements] No valid map/encounter combinations. Clearing map discard pile. WARNING: MapEncounters unfiltered by MC being used. Potential for infinite loading issue. If you see this from an infinite load freeze - inform CWolf from Mission Control");
                List <string> mapDiscardPile = (List <string>)AccessTools.Field(typeof(SimGameState), "mapDiscardPile").GetValue(simGameState);
                mapDiscardPile.Clear();

                WeightedList <MapAndEncounters> playableMaps = (WeightedList <MapAndEncounters>)AccessTools.Method(typeof(SimGameState), "GetSinglePlayerProceduralPlayableMaps").Invoke(null, new object[] { system });
                IEnumerable <int> source = from map in playableMaps select map.Map.Weight;
                WeightedList <MapAndEncounters> weightedList = new WeightedList <MapAndEncounters>(WeightedListType.WeightedRandom, playableMaps.ToList(), source.ToList <int>(), 0);

                activeMaps.AddRange(weightedList);
            }
        }