Пример #1
0
        /// <summary>process a rule and add/remove the resources from the simulator</simulator>
        private void Process_rule_inner_body(double k, Part p, Rule r, EnvironmentAnalyzer env, VesselAnalyzer va)
        {
            // deduce rate per-second
            double rate = va.crew_count * (r.interval > 0.0 ? r.rate / r.interval : r.rate);

            // prepare recipe
            if (r.output.Length == 0)
            {
                Resource(r.input).Consume(rate * k, r.name);
            }
            else if (rate > double.Epsilon)
            {
                // simulate recipe if output_only is false
                if (!r.monitor)
                {
                    // - rules always dump excess overboard (because it is waste)
                    SimulatedRecipe recipe = new SimulatedRecipe(p, r.name);
                    recipe.Input(r.input, rate * k);
                    recipe.Output(r.output, rate * k * r.ratio, true);
                    recipes.Add(recipe);
                }
                // only simulate output
                else
                {
                    Resource(r.output).Produce(rate * k, r.name);
                }
            }
        }
Пример #2
0
		/// <summary>process the process and add/remove the resources from the simulator</summary>
		private void Process_process_inner_body(double k, Part p, Process pr, EnvironmentAnalyzer env, VesselAnalyzer va)
		{
			// prepare recipe
			SimulatedRecipe recipe = new SimulatedRecipe(p, pr.name);
			foreach (KeyValuePair<string, double> input in pr.inputs)
			{
				recipe.Input(input.Key, input.Value * k);
			}
			foreach (KeyValuePair<string, double> output in pr.outputs)
			{
				recipe.Output(output.Key, output.Value * k, pr.dump.Check(output.Key));
			}
			recipes.Add(recipe);
		}
Пример #3
0
 void Process_harvester(Harvester harvester, VesselAnalyzer va)
 {
     if (harvester.running && harvester.simulated_abundance > harvester.min_abundance)
     {
         SimulatedRecipe recipe = new SimulatedRecipe(harvester.part, "harvester");
         if (harvester.ec_rate > double.Epsilon)
         {
             recipe.Input("ElectricCharge", harvester.ec_rate);
         }
         recipe.Output(
             harvester.resource,
             Harvester.AdjustedRate(harvester, new CrewSpecs("Engineer@0"), va.crew, harvester.simulated_abundance),
             dump: false);
         recipes.Add(recipe);
     }
 }
Пример #4
0
		void Process_generator(ModuleGenerator generator, Part p)
		{
			// skip launch clamps, that include a generator
			if (Lib.PartName(p) == "launchClamp1")
				return;

			SimulatedRecipe recipe = new SimulatedRecipe(p, "generator");
			foreach (ModuleResource res in generator.resHandler.inputResources)
			{
				recipe.Input(res.name, res.rate);
			}
			foreach (ModuleResource res in generator.resHandler.outputResources)
			{
				recipe.Output(res.name, res.rate, true);
			}
			recipes.Add(recipe);
		}
Пример #5
0
		void Process_harvester(ModuleResourceHarvester harvester, VesselAnalyzer va)
		{
			// calculate experience bonus
			float exp_bonus = harvester.UseSpecialistBonus
			  ? harvester.EfficiencyBonus * (harvester.SpecialistBonusBase + (harvester.SpecialistEfficiencyFactor * (va.crew_engineer_maxlevel + 1)))
			  : 1.0f;

			// use part name as recipe name
			// - include crew bonus in the recipe name
			string recipe_name = Lib.BuildString(harvester.part.partInfo.title, " (efficiency: ", Lib.HumanReadablePerc(exp_bonus), ")");

			// generate recipe
			SimulatedRecipe recipe = new SimulatedRecipe(harvester.part, recipe_name);
			foreach (ResourceRatio res in harvester.inputList)
			{
				recipe.Input(res.ResourceName, res.Ratio);
			}
			recipe.Output(harvester.ResourceName, harvester.Efficiency * exp_bonus, true);
			recipes.Add(recipe);
		}
Пример #6
0
		/// <summary>run a single timestamp of the simulator</summary>
		private void RunSimulator(List<Part> parts, EnvironmentAnalyzer env, VesselAnalyzer va)
		{
			// clear previous resource state
			resources.Clear();

			// get amount and capacity from parts
			foreach (Part p in parts)
			{
				for (int i = 0; i < p.Resources.Count; ++i)
				{
					Process_part(p, p.Resources[i].resourceName);
#if DEBUG_RESOURCES
					p.Resources[i].isVisible = true;
					p.Resources[i].isTweakable = true;
#endif
				}
			}

			// process all rules
			foreach (Rule r in Profile.rules)
			{
				if (r.input.Length > 0 && r.rate > 0.0)
				{
					Process_rule(parts, r, env, va);
				}
			}

			// process all processes
			foreach (Process p in Profile.processes)
			{
				Process_process(parts, p, env, va);
			}

			// process all modules
			foreach (Part p in parts)
			{
				// get planner controller in the part
				PlannerController ctrl = p.FindModuleImplementing<PlannerController>();

				// ignore all modules in the part if specified in controller
				if (ctrl != null && !ctrl.considered)
					continue;

				// for each module
				foreach (PartModule m in p.Modules)
				{
					// skip disabled modules
					// rationale: the Selector disable non-selected modules in this way
					if (!m.isEnabled)
						continue;

					if (IsApiModule(m))
					{
						Process_apiModule(m, env, va);
					}
					else
					{
						switch (m.moduleName)
						{
							case "Greenhouse":
								Process_greenhouse(m as Greenhouse, env, va);
								break;
							case "GravityRing":
								Process_ring(m as GravityRing);
								break;
							case "Emitter":
								Process_emitter(m as Emitter);
								break;
							case "Laboratory":
								Process_laboratory(m as Laboratory);
								break;
							case "Experiment":
								Process_experiment(m as Experiment);
								break;
							case "ModuleCommand":
								Process_command(m as ModuleCommand);
								break;
							case "ModuleGenerator":
								Process_generator(m as ModuleGenerator, p);
								break;
							case "ModuleResourceConverter":
								Process_converter(m as ModuleResourceConverter, va);
								break;
							case "ModuleKPBSConverter":
								Process_converter(m as ModuleResourceConverter, va);
								break;
							case "ModuleResourceHarvester":
								Process_harvester(m as ModuleResourceHarvester, va);
								break;
							case "ModuleScienceConverter":
								Process_stocklab(m as ModuleScienceConverter);
								break;
							case "ModuleActiveRadiator":
								Process_radiator(m as ModuleActiveRadiator);
								break;
							case "ModuleWheelMotor":
								Process_wheel_motor(m as ModuleWheelMotor);
								break;
							case "ModuleWheelMotorSteering":
								Process_wheel_steering(m as ModuleWheelMotorSteering);
								break;
							case "ModuleLight":
							case "ModuleColoredLensLight":
							case "ModuleMultiPointSurfaceLight":
								Process_light(m as ModuleLight);
								Process_light(m as ModuleLight);
								Process_light(m as ModuleLight);
								break;
							case "KerbalismScansat":
								Process_scanner(m as KerbalismScansat);
								break;
							case "FissionGenerator":
								Process_fission_generator(p, m);
								break;
							case "ModuleRadioisotopeGenerator":
								Process_radioisotope_generator(p, m);
								break;
							case "ModuleCryoTank":
								Process_cryotank(p, m);
								break;
							case "ModuleRTAntennaPassive":
							case "ModuleRTAntenna":
								Process_rtantenna(m);
								break;
							case "ModuleDataTransmitter":
								Process_datatransmitter(m as ModuleDataTransmitter);
								break;
							case "ModuleEngines":
								Process_engines(m as ModuleEngines);
								break;
							case "ModuleEnginesFX":
								Process_enginesfx(m as ModuleEnginesFX);
								break;
							case "ModuleRCS":
								Process_rcs(m as ModuleRCS);
								break;
							case "ModuleRCSFX":
								Process_rcsfx(m as ModuleRCSFX);
								break;
							case "SolarPanelFixer":
								Process_solarPanel(m as SolarPanelFixer, env);
								break;
						}
					}
				}
			}

			// execute all possible recipes
			bool executing = true;
			while (executing)
			{
				executing = false;
				for (int i = 0; i < recipes.Count; ++i)
				{
					SimulatedRecipe recipe = recipes[i];
					if (recipe.left > double.Epsilon)
					{
						executing |= recipe.Execute(this);
					}
				}
			}
			recipes.Clear();

			// clamp all resources
			foreach (KeyValuePair<string, SimulatedResource> pair in resources)
				pair.Value.Clamp();
		}
Пример #7
0
		void Process_greenhouse(Greenhouse g, EnvironmentAnalyzer env, VesselAnalyzer va)
		{
			// skip disabled greenhouses
			if (!g.active)
				return;

			// shortcut to resources
			SimulatedResource ec = Resource("ElectricCharge");
			SimulatedResource res = Resource(g.crop_resource);

			// calculate natural and artificial lighting
			double natural = env.solar_flux;
			double artificial = Math.Max(g.light_tolerance - natural, 0.0);

			// if lamps are on and artificial lighting is required
			if (artificial > 0.0)
			{
				// consume ec for the lamps
				ec.Consume(g.ec_rate * (artificial / g.light_tolerance), "greenhouse");
			}

			// execute recipe
			SimulatedRecipe recipe = new SimulatedRecipe(g.part, "greenhouse");
			foreach (ModuleResource input in g.resHandler.inputResources)
			{
				// WasteAtmosphere is primary combined input
				if (g.WACO2 && input.name == "WasteAtmosphere")
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "CarbonDioxide");
				// CarbonDioxide is secondary combined input
				else if (g.WACO2 && input.name == "CarbonDioxide")
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "");
				// if atmosphere is breathable disable WasteAtmosphere / CO2
				else if (!g.WACO2 && (input.name == "CarbonDioxide" || input.name == "WasteAtmosphere"))
					recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "");
				else
					recipe.Input(input.name, input.rate);
			}
			foreach (ModuleResource output in g.resHandler.outputResources)
			{
				// if atmosphere is breathable disable Oxygen
				if (output.name == "Oxygen")
					recipe.Output(output.name, env.breathable ? 0.0 : output.rate, true);
				else
					recipe.Output(output.name, output.rate, true);
			}
			recipes.Add(recipe);

			// determine environment conditions
			bool lighting = natural + artificial >= g.light_tolerance;
			bool pressure = va.pressurized || g.pressure_tolerance <= double.Epsilon;
			bool radiation = (env.landed ? env.surface_rad : env.magnetopause_rad) * (1.0 - va.shielding) < g.radiation_tolerance;

			// if all conditions apply
			// note: we are assuming the inputs are satisfied, we can't really do otherwise here
			if (lighting && pressure && radiation)
			{
				// produce food
				res.Produce(g.crop_size * g.crop_rate, "greenhouse");

				// add harvest info
				res.harvests.Add(Lib.BuildString(g.crop_size.ToString("F0"), " in ", Lib.HumanReadableDuration(1.0 / g.crop_rate)));
			}
		}