atmosim 0.1.0

A library for calculating most efficient gas bombs in Space Station 14 game
Documentation
use atmosim::prelude::*;

// Modern stuff
// Tanks

#[test]
fn tank_explodes() {
    let engine = Atmosim::default();
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1.,
            Gas::Tritium => 0.5,
            _ => 0.,
        },
        373.149,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    eprintln!("{:?}", tank.state());
    assert!(matches!(
        tank.state(),
        GasContainerState::Exploded { radius: (4.0..5.0) }
    ))
}

#[test]
fn tank_doesnt_explode() {
    let engine = Atmosim::default();
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1.,
            Gas::Plasma => 0.5,
            _ => 0.,
        },
        373.149,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    eprintln!("{:?}", tank.state());
    assert!(matches!(tank.state(), GasContainerState::Idle))
}

// Canisters

#[test]
fn canister_explodes() {
    let engine = Atmosim::new(GameConfig::wizden_canister());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1400.,
            Gas::Tritium => 700.,
            _ => 0.,
        },
        373.149,
    );

    let mut can = GasContainer::new(mix);
    can.step_all();

    eprintln!("{:?}", can.state());
    assert!(matches!(
        can.state(),
        GasContainerState::Exploded {
            radius: (30.0..31.0)
        }
    ))
}

#[test]
fn canister_doesnt_explode() {
    let engine = Atmosim::new(GameConfig::wizden_canister());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1400.,
            Gas::Plasma => 700.,
            _ => 0.,
        },
        373.149,
    );

    let mut can = GasContainer::new(mix);
    can.step_all();

    eprintln!("{:?}", can.state());
    assert!(matches!(can.state(), GasContainerState::Idle))
}

// Tanks pre maxcap rework

#[test]
fn old_tank_explodes() {
    // Full clone of a maxcap I've found with Ilya's atmosim on wizden config. Serialized string:
    // ft=395.97998 fp=548.5 tp=1013.25 tt=293.15 mi=[[tritium,0.62802005],[plasma,0.37198]] pm=[[oxygen,1]]
    let engine = Atmosim::new(GameConfig::wizden_pmr());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 0.953378,
            Gas::Plasma => 0.309855,
            Gas::Tritium => 0.523134,
            _ => 0.,
        },
        373.2523,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    // C++ says this should be 27.55 radius, Rust says 26.79.
    // I'll say this is some floating point issue and move on.
    eprintln!("{:?}", tank.state());
    assert!(matches!(
        tank.state(),
        GasContainerState::Exploded {
            radius: (26.0..28.0)
        }
    ))
}

#[test]
fn old_tank_ruptures() {
    let engine = Atmosim::new(GameConfig::wizden_pmr());
    // holy shit it was geniunely hard to find a mix with trit that doesn't explode lol
    let mix = engine.create_mixture(
        gases! {
            Gas::Frezon => 1.3,
            Gas::Oxygen => 0.15,
            Gas::Tritium => 0.15,
            _ => 0.,
        },
        373.149,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    eprintln!("{:?}", tank.state());
    assert!(matches!(tank.state(), GasContainerState::Ruptured))
}

// Forks
// Goob

#[test]
fn goob_tank_explodes() {
    // that one legendary maxcap everybody knows a.k.a. ticks-20r-7s-OT+P
    let engine = Atmosim::new(GameConfig::goob());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1.550654,
            Gas::Plasma => 0.889429,
            Gas::Tritium => 0.664566,
            _ => 0.,
        },
        381.07294,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    // Matches with C++ - 20.1
    eprintln!("{:?}", tank.state());
    assert!(matches!(
        tank.state(),
        GasContainerState::Exploded {
            radius: (20.0..21.0)
        }
    ))
}

#[test]
fn goob_tank_idles() {
    let engine = Atmosim::new(GameConfig::goob());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 1.,
            Gas::Tritium => 0.5,
            _ => 0.,
        },
        373.149,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    eprintln!("{:?}", tank.state());
    assert!(matches!(tank.state(), GasContainerState::Idle))
}

// Monolith

#[test]
fn monolith_tank_explodes() {
    // ft=263.19998 fp=816.10004 tp=1013.25 tt=449.4 mi=[[tritium,0.24000001],[oxygen,0.76000005]] pm=[[plasma,1]]
    let engine = Atmosim::new(GameConfig::monolith());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 2.834242,
            Gas::Plasma => 0.527630,
            Gas::Tritium => 0.895024,
            _ => 0.,
        },
        377.9979,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    // Matches with C++ - 26
    eprintln!("{:?}", tank.state());
    assert!(matches!(
        tank.state(),
        GasContainerState::Exploded {
            radius: (25.0..26.0)
        }
    ))
}

#[test]
fn monolith_tank_idles() {
    let engine = Atmosim::new(GameConfig::monolith());
    let mix = engine.create_mixture(
        gases! {
            Gas::Oxygen => 2.,
            Gas::Plasma => 0.6,
            Gas::Tritium => 1.,
            _ => 0.,
        },
        373.149,
    );

    let mut tank = GasContainer::new(mix);
    tank.step_all();

    eprintln!("{:?}", tank.state());
    assert!(matches!(tank.state(), GasContainerState::Idle))
}