1use core::cmp::Reverse;
9
10use arrayvec::ArrayVec;
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use crate::{
15 Atmosim,
16 gases::{Gas, GasProperties, MoleProperties, gases},
17 maxcap::GasContainerPrototype,
18 reactions::{GasReaction, GasReactionPrototype, ReactionBuffer},
19};
20
21pub(crate) const R: f32 = 8.314_463; pub(crate) const ONE_ATMOSPHERE: f32 = 101.325;
24pub(crate) const TCMB: f32 = 2.7;
25pub(crate) const T0C: f32 = 273.15;
26pub(crate) const MIN_MOLES: f32 = 0.000_000_05;
27
28#[derive(Debug)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30#[cfg_attr(feature = "serde", serde(default))]
31pub struct GameConfig {
32 pub atmospherics: Atmospherics,
33
34 pub heat_scale: f32,
36
37 pub hydrogen_substitute: Gas,
41
42 pub gas_properties: GasProperties,
43 pub container: GasContainerPrototype,
44 #[cfg_attr(feature = "serde", serde(flatten))]
45 pub reactions: ReactionBuffer,
46}
47
48impl Default for GameConfig {
50 fn default() -> Self {
51 Self {
52 atmospherics: Atmospherics::default(),
53 heat_scale: 8.,
55
56 hydrogen_substitute: Gas::Hydrogen,
57
58 gas_properties: GasProperties::default(),
59 reactions: ReactionBuffer::default(),
60 container: GasContainerPrototype::default(),
61 }
62 }
63}
64
65#[derive(Debug)]
66#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
67#[cfg_attr(feature = "serde", serde(default))]
68pub struct Atmospherics {
69 pub tmax: f32,
70 pub minimum_heat_capacity: f32,
71
72 pub ammonia_oxygen_reaction_rate: f32,
73
74 pub n2o_decomposition_rate: f32,
75
76 pub frezon_cool_lower_temperature: f32,
77 pub frezon_cool_mid_temperature: f32,
78 pub frezon_cool_maximum_energy_modifier: f32,
79 pub frezon_cool_rate_modifier: f32,
80 pub frezon_nitrogen_cool_ratio: f32,
81 pub frezon_cool_energy_released: f32,
82
83 pub frezon_production_max_efficiency_temperature: f32,
84 pub frezon_production_nitrogen_ratio: f32,
85 pub frezon_production_trit_ratio: f32,
86 pub frezon_production_conversion_rate: f32,
87
88 pub fire_minimum_temperature_to_exist: f32,
89 pub oxygen_burn_rate_base: f32,
90
91 pub plasma_upper_temperature: f32,
92 pub plasma_minimum_burn_temperature: f32,
93 pub plasma_super_saturation_ends: f32,
94 pub plasma_super_saturation_threshold: f32,
95 pub plasma_oxygen_fullburn: f32,
96 pub plasma_burn_rate_delta: f32,
97 pub plasma_fire_energy_released: f32,
98
99 pub tritium_minimum_oxyburn_energy: f32,
100 pub tritium_burn_oxy_factor: f32,
101 pub tritium_burn_fuel_ratio: f32,
102 pub tritium_burn_trit_factor: f32,
103 pub hydrogen_fire_energy_released: f32,
104
105 pub n2o_formation_energy: f32,
107
108 pub bz_production_energy: f32,
110 pub healium_production_energy: f32,
111 pub nitrium_production_energy: f32,
112 pub nitrium_decomposition_energy: f32,
113 pub pluoxium_production_energy: f32,
114
115 pub minimum_hydrogen_oxyburn_energy: f32,
117 pub hydrogen_burn_oxy_factor: f32,
118 pub hyper_noblium_production_energy: f32,
119 pub halon_combustion_energy: f32,
120 pub zauker_production_energy: f32,
121 pub zauker_temperature_scale: f32,
122 pub zauker_decomposition_energy: f32,
123 pub zauker_decomposition_max_rate: f32,
124 pub proto_nitrate_production_energy: f32,
125 pub proto_nitrate_conversion_energy: f32,
126 pub proto_nitrate_bz_conversion_energy: f32,
127
128 pub zipion_production_conversion_rate: f32,
130}
131
132impl Default for Atmospherics {
133 fn default() -> Self {
134 let sup_sat_thr = 96.;
135 Self {
136 tmax: 262_144.,
137 minimum_heat_capacity: 0.0003,
138
139 ammonia_oxygen_reaction_rate: 2.,
140
141 n2o_decomposition_rate: 2.,
142
143 frezon_cool_lower_temperature: 23.15,
144 frezon_cool_mid_temperature: 373.15,
145
146 frezon_cool_maximum_energy_modifier: 10.,
147 frezon_cool_rate_modifier: 20.,
148 frezon_nitrogen_cool_ratio: 5.,
149 frezon_cool_energy_released: -600e3,
150 frezon_production_max_efficiency_temperature: 73.15,
151 frezon_production_nitrogen_ratio: 10.,
152 frezon_production_trit_ratio: 50.,
153 frezon_production_conversion_rate: 50.,
154 fire_minimum_temperature_to_exist: T0C + 100.,
155 oxygen_burn_rate_base: 1.4,
156
157 plasma_upper_temperature: 1370. + T0C,
158 plasma_minimum_burn_temperature: 100. + T0C,
159 plasma_super_saturation_ends: sup_sat_thr / 3.,
160 plasma_super_saturation_threshold: sup_sat_thr,
161 plasma_oxygen_fullburn: 10.,
162 plasma_burn_rate_delta: 9.,
163 plasma_fire_energy_released: 160e3,
164
165 tritium_minimum_oxyburn_energy: 143_000.,
166 tritium_burn_oxy_factor: 100.,
167 tritium_burn_fuel_ratio: 2.,
168 tritium_burn_trit_factor: 10.,
169 hydrogen_fire_energy_released: 284e3,
170
171 n2o_formation_energy: 10e3,
172 bz_production_energy: 80e3,
173 healium_production_energy: 9e3,
174
175 nitrium_production_energy: -100e3,
176 nitrium_decomposition_energy: 30e3,
177
178 pluoxium_production_energy: 250.,
179
180 minimum_hydrogen_oxyburn_energy: 143_000.,
181 hydrogen_burn_oxy_factor: 100.,
182
183 hyper_noblium_production_energy: 2e7,
184
185 halon_combustion_energy: -2500.,
186 zauker_production_energy: 5000.,
187 zauker_temperature_scale: 5e-6,
188 zauker_decomposition_energy: 460.,
189 zauker_decomposition_max_rate: 20.,
190
191 proto_nitrate_production_energy: 650.,
192 proto_nitrate_conversion_energy: 2000.,
193 proto_nitrate_bz_conversion_energy: -10_000.,
194
195 zipion_production_conversion_rate: 40.,
196 }
197 }
198}
199
200impl Atmosim {
201 #[must_use]
202 pub fn new(mut game: GameConfig) -> Self {
203 if let ReactionBuffer::Protos(protos) = game.reactions {
205 let mut reactions = protos
206 .iter()
207 .map(|&proto| GasReaction::cache(proto))
208 .collect::<ArrayVec<_, _>>();
209
210 reactions.sort_unstable_by_key(|reaction| Reverse(reaction.priority)); game.reactions = ReactionBuffer::Inited(reactions);
212 }
213
214 let inverses = Inverses {
216 heat_scale: 1. / game.heat_scale,
217 frez_cool_mid_minus_lower_temp: 1.
218 / (game.atmospherics.frezon_cool_mid_temperature
219 - game.atmospherics.frezon_cool_lower_temperature),
220 plasma_upper_minus_min_burn_temp: 1.
221 / (game.atmospherics.plasma_upper_temperature
222 - game.atmospherics.plasma_minimum_burn_temperature),
223 plasma_supsat_thres_minus_ends: 1.
224 / (game.atmospherics.plasma_super_saturation_threshold
225 - game.atmospherics.plasma_super_saturation_ends),
226 plasma_burn_rate_delta: 1. / game.atmospherics.plasma_burn_rate_delta,
227 plasma_o2_full_burn: 1. / game.atmospherics.plasma_oxygen_fullburn,
228 tritium_burn_fuel_ratio: 1. / game.atmospherics.tritium_burn_fuel_ratio,
229 tritium_burn_trit_factor: 1. / game.atmospherics.tritium_burn_trit_factor,
230 tritium_burn_oxy_factor: 1. / game.atmospherics.tritium_burn_oxy_factor,
231 };
232
233 for (_, property) in &mut game.gas_properties.0 {
235 property.specific_heat *= inverses.heat_scale;
236 }
237
238 Self { inverses, game }
239 }
240}
241
242impl GameConfig {
243 #[must_use]
244 pub fn wizden_canister() -> Self {
245 Self {
246 atmospherics: Atmospherics {
247 hydrogen_fire_energy_released: 284e4,
248 ..Default::default()
249 },
250 container: GasContainerPrototype::default_canister(),
251 ..Default::default()
252 }
253 }
254
255 #[must_use]
256 pub fn wizden_pmr() -> Self {
257 Self {
258 atmospherics: Atmospherics {
259 hydrogen_fire_energy_released: 284e4,
260 ..Default::default()
261 },
262 container: GasContainerPrototype::old_default_tank(),
263 ..Default::default()
264 }
265 }
266
267 #[must_use]
268 pub fn goob() -> Self {
269 Self {
270 atmospherics: Atmospherics {
271 tmax: 262_144_000_000.,
272 ..Default::default()
273 },
274 hydrogen_substitute: Gas::WaterVapor,
275 reactions: ReactionBuffer::Protos(
276 [
277 GasReactionPrototype::plasma_fire(),
278 GasReactionPrototype::old_tritium_fire(),
279 GasReactionPrototype::frezon_coolant(),
280 GasReactionPrototype::frezon_production(),
281 GasReactionPrototype::ammonia_oxygen(),
282 GasReactionPrototype::n2o_decomposition(),
283 GasReactionPrototype::funky_bz_formation(),
284 GasReactionPrototype::goob_n2o_formation(),
285 GasReactionPrototype::funky_nitrium_production(),
286 GasReactionPrototype::funky_nitrium_decomposition(),
287 GasReactionPrototype::funky_pluoxium_production(),
288 ]
289 .into_iter()
290 .collect(),
291 ),
292 container: GasContainerPrototype::old_default_tank(),
293 ..Default::default()
294 }
295 }
296
297 #[must_use]
298 pub fn frontier() -> Self {
299 let sup_sat_thr = 30.;
300 Self {
301 atmospherics: Atmospherics {
302 plasma_super_saturation_threshold: sup_sat_thr,
303 plasma_super_saturation_ends: sup_sat_thr / 3.,
304 plasma_upper_temperature: 700.,
305 ..Default::default()
306 },
307 reactions: ReactionBuffer::Protos(
308 [
309 GasReactionPrototype::plasma_fire(),
310 GasReactionPrototype::frontier_tritium_fire(),
311 GasReactionPrototype::frezon_coolant(),
312 GasReactionPrototype::frezon_production(),
313 GasReactionPrototype::ammonia_oxygen(),
314 GasReactionPrototype::n2o_decomposition(),
315 ]
316 .into_iter()
317 .collect(),
318 ),
319 container: GasContainerPrototype::old_default_tank(),
320 ..Default::default()
321 }
322 }
323
324 #[must_use]
325 pub fn monolith() -> Self {
326 Self {
327 hydrogen_substitute: Gas::WaterVapor,
328 reactions: ReactionBuffer::Protos(
329 [
330 GasReactionPrototype::plasma_fire(),
331 GasReactionPrototype::frontier_tritium_fire(),
332 GasReactionPrototype::frezon_coolant(),
333 GasReactionPrototype::frezon_production(),
334 GasReactionPrototype::ammonia_oxygen(),
335 GasReactionPrototype::n2o_decomposition(),
336 GasReactionPrototype::funky_bz_formation(),
337 GasReactionPrototype::mono_nitrium_production(),
338 GasReactionPrototype::funky_nitrium_decomposition(),
339 GasReactionPrototype::funky_pluoxium_production(),
340 ]
341 .into_iter()
342 .collect(),
343 ),
344 gas_properties: GasProperties(gases! {
345 Gas::Healium => MoleProperties { specific_heat: 20., mass: 15. },
347 other => GasProperties::default().0[other] }),
349 container: GasContainerPrototype {
350 volume: 10.,
351 ..GasContainerPrototype::old_default_tank()
352 },
353 ..Self::frontier() }
355 }
356 #[must_use]
357 pub fn funky() -> Self {
358 Self {
359 atmospherics: Atmospherics {
360 tmax: 262_144_000.,
361 ..Default::default()
362 },
363 reactions: ReactionBuffer::Protos(
364 [
365 GasReactionPrototype::plasma_fire(),
366 GasReactionPrototype::tritium_fire(),
367 GasReactionPrototype::frezon_coolant(),
368 GasReactionPrototype::frezon_production(),
369 GasReactionPrototype::ammonia_oxygen(),
370 GasReactionPrototype::n2o_decomposition(),
371 GasReactionPrototype::funky_bz_formation(),
372 GasReactionPrototype::funky_nitrium_production(),
373 GasReactionPrototype::funky_nitrium_decomposition(),
374 GasReactionPrototype::funky_pluoxium_production(),
375 GasReactionPrototype::funky_hydrogen_fire(),
376 GasReactionPrototype::funky_hyper_noblium_production(),
377 GasReactionPrototype::funky_halon_oxygen_absorbtion(),
378 GasReactionPrototype::funky_zauker_production(),
379 GasReactionPrototype::funky_zauker_decomposition(),
380 GasReactionPrototype::funky_proto_nitrate_production(),
381 GasReactionPrototype::funky_proto_nitrate_conversion(),
382 GasReactionPrototype::funky_proto_nitrate_bz_conversion(),
383 ]
384 .into_iter()
385 .collect(),
386 ),
387 container: GasContainerPrototype::old_default_tank(),
388 ..Default::default()
389 }
390 }
391 #[must_use]
393 pub fn starlight() -> Self {
394 Self {
395 atmospherics: Atmospherics {
396 hydrogen_fire_energy_released: 284e4,
397 ..Self::funky().atmospherics
398 },
399 ..Self::funky()
400 }
401 }
402 #[must_use]
404 pub fn klovn() -> Self {
405 Self {
406 reactions: ReactionBuffer::Protos(
407 [
408 GasReactionPrototype::plasma_fire(),
409 GasReactionPrototype::tritium_fire(),
410 GasReactionPrototype::frezon_coolant(),
411 GasReactionPrototype::frezon_production(),
412 GasReactionPrototype::ammonia_oxygen(),
413 GasReactionPrototype::n2o_decomposition(),
414 GasReactionPrototype::klovn_zipion_formation(),
415 GasReactionPrototype::klovn_argon_formation(),
416 GasReactionPrototype::klovn_argon_absorbtion(),
417 ]
418 .into_iter()
419 .collect(),
420 ),
421 ..Self::wizden_pmr()
422 }
423 }
424}
425
426#[derive(Debug)]
428pub(crate) struct Inverses {
429 pub heat_scale: f32,
430
431 pub frez_cool_mid_minus_lower_temp: f32,
432
433 pub plasma_upper_minus_min_burn_temp: f32,
434 pub plasma_supsat_thres_minus_ends: f32,
435 pub plasma_burn_rate_delta: f32,
436 pub plasma_o2_full_burn: f32,
437
438 pub tritium_burn_fuel_ratio: f32,
439 pub tritium_burn_trit_factor: f32,
440 pub tritium_burn_oxy_factor: f32,
441}