use core::cmp::Reverse;
use arrayvec::ArrayVec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
Atmosim,
gases::{Gas, GasProperties, MoleProperties, gases},
maxcap::GasContainerPrototype,
reactions::{GasReaction, GasReactionPrototype, ReactionBuffer},
};
pub(crate) const R: f32 = 8.314_463; pub(crate) const ONE_ATMOSPHERE: f32 = 101.325;
pub(crate) const TCMB: f32 = 2.7;
pub(crate) const T0C: f32 = 273.15;
pub(crate) const MIN_MOLES: f32 = 0.000_000_05;
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct GameConfig {
pub atmospherics: Atmospherics,
pub heat_scale: f32,
pub hydrogen_substitute: Gas,
pub gas_properties: GasProperties,
pub container: GasContainerPrototype,
#[cfg_attr(feature = "serde", serde(flatten))]
pub reactions: ReactionBuffer,
}
impl Default for GameConfig {
fn default() -> Self {
Self {
atmospherics: Atmospherics::default(),
heat_scale: 8.,
hydrogen_substitute: Gas::Hydrogen,
gas_properties: GasProperties::default(),
reactions: ReactionBuffer::default(),
container: GasContainerPrototype::default(),
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Atmospherics {
pub tmax: f32,
pub minimum_heat_capacity: f32,
pub ammonia_oxygen_reaction_rate: f32,
pub n2o_decomposition_rate: f32,
pub frezon_cool_lower_temperature: f32,
pub frezon_cool_mid_temperature: f32,
pub frezon_cool_maximum_energy_modifier: f32,
pub frezon_cool_rate_modifier: f32,
pub frezon_nitrogen_cool_ratio: f32,
pub frezon_cool_energy_released: f32,
pub frezon_production_max_efficiency_temperature: f32,
pub frezon_production_nitrogen_ratio: f32,
pub frezon_production_trit_ratio: f32,
pub frezon_production_conversion_rate: f32,
pub fire_minimum_temperature_to_exist: f32,
pub oxygen_burn_rate_base: f32,
pub plasma_upper_temperature: f32,
pub plasma_minimum_burn_temperature: f32,
pub plasma_super_saturation_ends: f32,
pub plasma_super_saturation_threshold: f32,
pub plasma_oxygen_fullburn: f32,
pub plasma_burn_rate_delta: f32,
pub plasma_fire_energy_released: f32,
pub tritium_minimum_oxyburn_energy: f32,
pub tritium_burn_oxy_factor: f32,
pub tritium_burn_fuel_ratio: f32,
pub tritium_burn_trit_factor: f32,
pub hydrogen_fire_energy_released: f32,
pub n2o_formation_energy: f32,
pub bz_production_energy: f32,
pub healium_production_energy: f32,
pub nitrium_production_energy: f32,
pub nitrium_decomposition_energy: f32,
pub pluoxium_production_energy: f32,
pub minimum_hydrogen_oxyburn_energy: f32,
pub hydrogen_burn_oxy_factor: f32,
pub hyper_noblium_production_energy: f32,
pub halon_combustion_energy: f32,
pub zauker_production_energy: f32,
pub zauker_temperature_scale: f32,
pub zauker_decomposition_energy: f32,
pub zauker_decomposition_max_rate: f32,
pub proto_nitrate_production_energy: f32,
pub proto_nitrate_conversion_energy: f32,
pub proto_nitrate_bz_conversion_energy: f32,
pub zipion_production_conversion_rate: f32,
}
impl Default for Atmospherics {
fn default() -> Self {
let sup_sat_thr = 96.;
Self {
tmax: 262_144.,
minimum_heat_capacity: 0.0003,
ammonia_oxygen_reaction_rate: 2.,
n2o_decomposition_rate: 2.,
frezon_cool_lower_temperature: 23.15,
frezon_cool_mid_temperature: 373.15,
frezon_cool_maximum_energy_modifier: 10.,
frezon_cool_rate_modifier: 20.,
frezon_nitrogen_cool_ratio: 5.,
frezon_cool_energy_released: -600e3,
frezon_production_max_efficiency_temperature: 73.15,
frezon_production_nitrogen_ratio: 10.,
frezon_production_trit_ratio: 50.,
frezon_production_conversion_rate: 50.,
fire_minimum_temperature_to_exist: T0C + 100.,
oxygen_burn_rate_base: 1.4,
plasma_upper_temperature: 1370. + T0C,
plasma_minimum_burn_temperature: 100. + T0C,
plasma_super_saturation_ends: sup_sat_thr / 3.,
plasma_super_saturation_threshold: sup_sat_thr,
plasma_oxygen_fullburn: 10.,
plasma_burn_rate_delta: 9.,
plasma_fire_energy_released: 160e3,
tritium_minimum_oxyburn_energy: 143_000.,
tritium_burn_oxy_factor: 100.,
tritium_burn_fuel_ratio: 2.,
tritium_burn_trit_factor: 10.,
hydrogen_fire_energy_released: 284e3,
n2o_formation_energy: 10e3,
bz_production_energy: 80e3,
healium_production_energy: 9e3,
nitrium_production_energy: -100e3,
nitrium_decomposition_energy: 30e3,
pluoxium_production_energy: 250.,
minimum_hydrogen_oxyburn_energy: 143_000.,
hydrogen_burn_oxy_factor: 100.,
hyper_noblium_production_energy: 2e7,
halon_combustion_energy: -2500.,
zauker_production_energy: 5000.,
zauker_temperature_scale: 5e-6,
zauker_decomposition_energy: 460.,
zauker_decomposition_max_rate: 20.,
proto_nitrate_production_energy: 650.,
proto_nitrate_conversion_energy: 2000.,
proto_nitrate_bz_conversion_energy: -10_000.,
zipion_production_conversion_rate: 40.,
}
}
}
impl Atmosim {
#[must_use]
pub fn new(mut game: GameConfig) -> Self {
if let ReactionBuffer::Protos(protos) = game.reactions {
let mut reactions = protos
.iter()
.map(|&proto| GasReaction::cache(proto))
.collect::<ArrayVec<_, _>>();
reactions.sort_unstable_by_key(|reaction| Reverse(reaction.priority)); game.reactions = ReactionBuffer::Inited(reactions);
}
let inverses = Inverses {
heat_scale: 1. / game.heat_scale,
frez_cool_mid_minus_lower_temp: 1.
/ (game.atmospherics.frezon_cool_mid_temperature
- game.atmospherics.frezon_cool_lower_temperature),
plasma_upper_minus_min_burn_temp: 1.
/ (game.atmospherics.plasma_upper_temperature
- game.atmospherics.plasma_minimum_burn_temperature),
plasma_supsat_thres_minus_ends: 1.
/ (game.atmospherics.plasma_super_saturation_threshold
- game.atmospherics.plasma_super_saturation_ends),
plasma_burn_rate_delta: 1. / game.atmospherics.plasma_burn_rate_delta,
plasma_o2_full_burn: 1. / game.atmospherics.plasma_oxygen_fullburn,
tritium_burn_fuel_ratio: 1. / game.atmospherics.tritium_burn_fuel_ratio,
tritium_burn_trit_factor: 1. / game.atmospherics.tritium_burn_trit_factor,
tritium_burn_oxy_factor: 1. / game.atmospherics.tritium_burn_oxy_factor,
};
for (_, property) in &mut game.gas_properties.0 {
property.specific_heat *= inverses.heat_scale;
}
Self { inverses, game }
}
}
impl GameConfig {
#[must_use]
pub fn wizden_canister() -> Self {
Self {
atmospherics: Atmospherics {
hydrogen_fire_energy_released: 284e4,
..Default::default()
},
container: GasContainerPrototype::default_canister(),
..Default::default()
}
}
#[must_use]
pub fn wizden_pmr() -> Self {
Self {
atmospherics: Atmospherics {
hydrogen_fire_energy_released: 284e4,
..Default::default()
},
container: GasContainerPrototype::old_default_tank(),
..Default::default()
}
}
#[must_use]
pub fn goob() -> Self {
Self {
atmospherics: Atmospherics {
tmax: 262_144_000_000.,
..Default::default()
},
hydrogen_substitute: Gas::WaterVapor,
reactions: ReactionBuffer::Protos(
[
GasReactionPrototype::plasma_fire(),
GasReactionPrototype::old_tritium_fire(),
GasReactionPrototype::frezon_coolant(),
GasReactionPrototype::frezon_production(),
GasReactionPrototype::ammonia_oxygen(),
GasReactionPrototype::n2o_decomposition(),
GasReactionPrototype::funky_bz_formation(),
GasReactionPrototype::goob_n2o_formation(),
GasReactionPrototype::funky_nitrium_production(),
GasReactionPrototype::funky_nitrium_decomposition(),
GasReactionPrototype::funky_pluoxium_production(),
]
.into_iter()
.collect(),
),
container: GasContainerPrototype::old_default_tank(),
..Default::default()
}
}
#[must_use]
pub fn frontier() -> Self {
let sup_sat_thr = 30.;
Self {
atmospherics: Atmospherics {
plasma_super_saturation_threshold: sup_sat_thr,
plasma_super_saturation_ends: sup_sat_thr / 3.,
plasma_upper_temperature: 700.,
..Default::default()
},
reactions: ReactionBuffer::Protos(
[
GasReactionPrototype::plasma_fire(),
GasReactionPrototype::frontier_tritium_fire(),
GasReactionPrototype::frezon_coolant(),
GasReactionPrototype::frezon_production(),
GasReactionPrototype::ammonia_oxygen(),
GasReactionPrototype::n2o_decomposition(),
]
.into_iter()
.collect(),
),
container: GasContainerPrototype::old_default_tank(),
..Default::default()
}
}
#[must_use]
pub fn monolith() -> Self {
Self {
hydrogen_substitute: Gas::WaterVapor,
reactions: ReactionBuffer::Protos(
[
GasReactionPrototype::plasma_fire(),
GasReactionPrototype::frontier_tritium_fire(),
GasReactionPrototype::frezon_coolant(),
GasReactionPrototype::frezon_production(),
GasReactionPrototype::ammonia_oxygen(),
GasReactionPrototype::n2o_decomposition(),
GasReactionPrototype::funky_bz_formation(),
GasReactionPrototype::mono_nitrium_production(),
GasReactionPrototype::funky_nitrium_decomposition(),
GasReactionPrototype::funky_pluoxium_production(),
]
.into_iter()
.collect(),
),
gas_properties: GasProperties(gases! {
Gas::Healium => MoleProperties { specific_heat: 20., mass: 15. },
other => GasProperties::default().0[other] }),
container: GasContainerPrototype {
volume: 10.,
..GasContainerPrototype::old_default_tank()
},
..Self::frontier() }
}
#[must_use]
pub fn funky() -> Self {
Self {
atmospherics: Atmospherics {
tmax: 262_144_000.,
..Default::default()
},
reactions: ReactionBuffer::Protos(
[
GasReactionPrototype::plasma_fire(),
GasReactionPrototype::tritium_fire(),
GasReactionPrototype::frezon_coolant(),
GasReactionPrototype::frezon_production(),
GasReactionPrototype::ammonia_oxygen(),
GasReactionPrototype::n2o_decomposition(),
GasReactionPrototype::funky_bz_formation(),
GasReactionPrototype::funky_nitrium_production(),
GasReactionPrototype::funky_nitrium_decomposition(),
GasReactionPrototype::funky_pluoxium_production(),
GasReactionPrototype::funky_hydrogen_fire(),
GasReactionPrototype::funky_hyper_noblium_production(),
GasReactionPrototype::funky_halon_oxygen_absorbtion(),
GasReactionPrototype::funky_zauker_production(),
GasReactionPrototype::funky_zauker_decomposition(),
GasReactionPrototype::funky_proto_nitrate_production(),
GasReactionPrototype::funky_proto_nitrate_conversion(),
GasReactionPrototype::funky_proto_nitrate_bz_conversion(),
]
.into_iter()
.collect(),
),
container: GasContainerPrototype::old_default_tank(),
..Default::default()
}
}
#[must_use]
pub fn starlight() -> Self {
Self {
atmospherics: Atmospherics {
hydrogen_fire_energy_released: 284e4,
..Self::funky().atmospherics
},
..Self::funky()
}
}
#[must_use]
pub fn klovn() -> Self {
Self {
reactions: ReactionBuffer::Protos(
[
GasReactionPrototype::plasma_fire(),
GasReactionPrototype::tritium_fire(),
GasReactionPrototype::frezon_coolant(),
GasReactionPrototype::frezon_production(),
GasReactionPrototype::ammonia_oxygen(),
GasReactionPrototype::n2o_decomposition(),
GasReactionPrototype::klovn_zipion_formation(),
GasReactionPrototype::klovn_argon_formation(),
GasReactionPrototype::klovn_argon_absorbtion(),
]
.into_iter()
.collect(),
),
..Self::wizden_pmr()
}
}
}
#[derive(Debug)]
pub(crate) struct Inverses {
pub heat_scale: f32,
pub frez_cool_mid_minus_lower_temp: f32,
pub plasma_upper_minus_min_burn_temp: f32,
pub plasma_supsat_thres_minus_ends: f32,
pub plasma_burn_rate_delta: f32,
pub plasma_o2_full_burn: f32,
pub tritium_burn_fuel_ratio: f32,
pub tritium_burn_trit_factor: f32,
pub tritium_burn_oxy_factor: f32,
}