Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions byond-extools/src/monstermos/GasMixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void GasMixture::merge(const GasMixture &giver) {
for(int i = 0; i < TOTAL_NUM_GASES; i++) {
moles[i] += giver.moles[i];
}
set_dirty(true);
}

GasMixture GasMixture::remove(float amount) {
Expand Down Expand Up @@ -161,6 +162,14 @@ float GasMixture::share(GasMixture &sharer, int atmos_adjacent_turfs) {
float their_moles = sharer.total_moles();;
return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume;
}
if(moved_moles > 0)
{
sharer.set_dirty(true);
}
else
{
set_dirty(true);
}
return 0;
}

Expand All @@ -176,6 +185,14 @@ void GasMixture::temperature_share(GasMixture &sharer, float conduction_coeffici
temperature = std::max(temperature - heat/self_heat_capacity, TCMB);
if(!sharer.immutable)
sharer.temperature = std::max(sharer.temperature + heat/sharer_heat_capacity, TCMB);
if(temperature_delta > 0)
{
sharer.set_dirty(true);
}
else
{
set_dirty(true);
}
}
}
}
Expand All @@ -202,11 +219,13 @@ int GasMixture::compare(GasMixture &sample) const {
void GasMixture::clear() {
if (immutable) return;
memset(moles, 0, sizeof(moles));
set_dirty(false);
}

void GasMixture::multiply(float multiplier) {
if (immutable) return;
for (int i = 0; i < TOTAL_NUM_GASES; i++) {
moles[i] *= multiplier;
}
set_dirty(true);
}
4 changes: 3 additions & 1 deletion byond-extools/src/monstermos/GasMixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class GasMixture
inline float get_volume() const { return volume; }
inline void set_volume(float new_vol) { volume = new_vol; }
inline float get_last_share() const { return last_share; }

inline void set_dirty(bool dirty) { dirty_react = dirty; }
inline float sleeping() { return !dirty_react || total_moles() == 0; }
private:
GasMixture();
float moles[TOTAL_NUM_GASES];
Expand All @@ -57,6 +58,7 @@ class GasMixture
float last_share = 0;
float min_heat_capacity = 0;
bool immutable = false;
bool dirty_react = true;
// you might thing, "damn, all the gases, wont that use up more memory"?
// well no. Let's look at the average gas mixture in BYOND land containing both oxygen and nitrogen:
// gases (28+8 bytes)
Expand Down
258 changes: 258 additions & 0 deletions byond-extools/src/monstermos/Reaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#include "Reaction.h"

#include "reaction_defines.h"

#include <algorithm>

using namespace monstermos::constants;

extern std::unordered_map<std::string, int> gas_id_strings;

extern int o2,plasma,co2,tritium,water_vapor,n2o,bz,no2;

bool ByondReaction::check_conditions(GasMixture& air)
{
auto temp = air.get_temperature();
auto ener = air.thermal_energy();
if(temp < min_temp_req || ener < min_ener_req)
{
return false;
}
else
{
for(int i = 0; i < TOTAL_NUM_GASES; i++)
{
if(air.get_moles(i) < min_gas_reqs[i])
{
return false;
}
}
}
return true;
}

int ByondReaction::react(GasMixture& air,Value src,Value holder)
{
return (int)(float)(Core::get_proc(proc_id).call({src,holder}));
}
/*
bool PlasmaFire::check_conditions(GasMixture& air)
{
return air.get_temperature() > PLASMA_MINIMUM_BURN_TEMPERATURE &&
air.get_moles(plasma) > MINIMUM_MOLE_COUNT &&
air.get_moles(o2) > MINIMUM_MOLE_COUNT;
}

int PlasmaFire::react(GasMixture& air,Value src,Value holder)
{
bool superSaturation = false;
float temperature_scale;
float plasma_burn_rate;
float oxygen_burn_rate;
float energy_released = 0.0;
auto initial_oxygen = air.get_moles(o2);
auto initial_plasma = air.get_moles(plasma);
auto old_energy = air.thermal_energy();
auto temperature = air.get_temperature();
Container results = src.get("reaction_results");
results["fire"] = 0.0;
if(temperature > PLASMA_UPPER_TEMPERATURE)
{
temperature_scale = 1;
}
else
{
temperature_scale = (temperature - PLASMA_MINIMUM_BURN_TEMPERATURE) / (PLASMA_UPPER_TEMPERATURE - PLASMA_MINIMUM_BURN_TEMPERATURE);
}
if(temperature_scale > 0)
{
oxygen_burn_rate = (OXYGEN_BURN_RATE_BASE-temperature_scale);
superSaturation = (initial_oxygen/initial_plasma>SUPER_SATURATION_THRESHOLD);
if(initial_oxygen>initial_plasma*PLASMA_OXYGEN_FULLBURN)
{
plasma_burn_rate = initial_plasma*temperature_scale/PLASMA_BURN_RATE_DELTA;
}
else
{
plasma_burn_rate = (temperature_scale*(initial_oxygen/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA;
}
plasma_burn_rate = std::min(plasma_burn_rate,std::min(initial_plasma,initial_oxygen/oxygen_burn_rate));
air.set_moles(plasma,initial_plasma - plasma_burn_rate);
air.set_moles(o2,initial_oxygen - (plasma_burn_rate*oxygen_burn_rate));
if(superSaturation)
{
air.set_moles(tritium,air.get_moles(tritium) + plasma_burn_rate);
}
else
{
air.set_moles(co2,air.get_moles(co2) + plasma_burn_rate);
}
energy_released = FIRE_PLASMA_ENERGY_RELEASED * plasma_burn_rate;
results["fire"] = plasma_burn_rate*(1+oxygen_burn_rate);
}
if(energy_released > 0)
{
air.set_temperature((old_energy+energy_released)/air.heat_capacity());
}
if(holder.type == DataType::TURF)
{
temperature = air.get_temperature();
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
{
holder.invoke("hotspot_expose",{temperature, CELL_VOLUME});
IncRefCount(src.type,src.value);
holder.invoke("temperature_expose",{src,temperature,CELL_VOLUME});
}
}
return results.at("fire") > 0.0 ? REACTING : NO_REACTION;
}

bool TritFire::check_conditions(GasMixture& air)
{
return air.get_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_EXIST &&
air.get_moles(tritium) > MINIMUM_MOLE_COUNT &&
air.get_moles(o2) > MINIMUM_MOLE_COUNT;
}

#include <random>

#include "../core/proc_management.h"

int TritFire::react(GasMixture& air,Value src,Value holder)
{
float energy_released = 0.0;
float old_heat_capacity = air.heat_capacity();
float temperature = air.get_temperature();
Container results = src.get("reaction_results");
results["fire"] = 0.0;
float burned_fuel = 0.0;
if(air.get_moles(o2) < air.get_moles(tritium))
{
burned_fuel = air.get_moles(o2)/TRITIUM_BURN_OXY_FACTOR;
air.set_moles(tritium, air.get_moles(tritium)-burned_fuel);
}
else
{
burned_fuel = air.get_moles(tritium)*TRITIUM_BURN_TRIT_FACTOR;
air.set_moles(tritium, air.get_moles(tritium)-air.get_moles(tritium)/TRITIUM_BURN_TRIT_FACTOR);
air.set_moles(o2,air.get_moles(o2)-air.get_moles(tritium));
}
if(burned_fuel > 0.0)
{
energy_released += FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel;
if(holder.type == TURF && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY)
{
std::random_device rd;
std::mt19937 gen(rd());
if(std::generate_canonical<float,10>(gen) < 0.1)
{
IncRefCount(holder.type,holder.value);
Core::get_proc("/proc/radiation_pulse").call({holder, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR});
}
air.set_moles(water_vapor, air.get_moles(water_vapor) + burned_fuel/TRITIUM_BURN_OXY_FACTOR);
results["fire"] = burned_fuel;
}
}
if(energy_released > 0.0)
{
auto new_heat_capacity = air.heat_capacity();
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
{
air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity);
}
}
if(holder.type == DataType::TURF)
{
temperature = air.get_temperature();
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
{
holder.invoke("hotspot_expose",{temperature, CELL_VOLUME});
IncRefCount(src.type,src.value);
holder.invoke("temperature_expose",{src,temperature,CELL_VOLUME});
}
}
return results.at("fire") > 0.0 ? REACTING : NO_REACTION;
}

#define _USE_MATH_DEFINES

#include <math.h>

#include <cmath>

bool Fusion::check_conditions(GasMixture& air)
{
return air.get_temperature() > FUSION_TEMPERATURE_THRESHOLD &&
air.get_moles(tritium) > FUSION_TRITIUM_MOLES_USED &&
air.get_moles(plasma) > FUSION_MOLE_THRESHOLD &&
air.get_moles(co2) > FUSION_MOLE_THRESHOLD;
}

extern float gas_fusion_power[TOTAL_NUM_GASES];

int Fusion::react(GasMixture& air,Value src,Value holder)
{
Container analyzer_results = src.get("analyzer_results");
auto old_heat_capacity = air.heat_capacity();
auto initial_plasma = air.get_moles(plasma);
auto initial_carbon = air.get_moles(co2);
auto scale_factor = air.get_volume() / M_PI;
auto toroidal_size = 2*M_PI+atan((air.get_volume()-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN);
auto gas_power = 0.0;
for(int i = 0;i < TOTAL_NUM_GASES;i++)
{
gas_power += gas_fusion_power[i] * air.get_moles(i);
}
auto instability = fmod(pow(gas_power*INSTABILITY_GAS_POWER_FACTOR,2), toroidal_size);
auto plasma_2 = (initial_plasma - FUSION_MOLE_THRESHOLD)/scale_factor;
auto carbon_2 = (initial_carbon - FUSION_MOLE_THRESHOLD)/scale_factor;
plasma_2 = fmod(plasma_2 - (instability * sin(carbon_2)),toroidal_size);
carbon_2 = fmod(carbon_2 - plasma_2, toroidal_size);
air.set_moles(plasma,plasma_2*scale_factor + FUSION_MOLE_THRESHOLD);
air.set_moles(co2,carbon_2*scale_factor + FUSION_MOLE_THRESHOLD);
auto delta_plasma = initial_plasma - air.get_moles(plasma);

float reaction_energy = delta_plasma * PLASMA_BINDING_ENERGY;
if(instability < FUSION_INSTABILITY_ENDOTHERMALITY)
{
reaction_energy = std::max((double)reaction_energy,0.0);
}
else if(reaction_energy < 0.0)
{
reaction_energy *= std::sqrtf(instability-FUSION_INSTABILITY_ENDOTHERMALITY);
}
if(air.thermal_energy() + reaction_energy < 0)
{
air.set_moles(plasma,initial_plasma);
air.set_moles(co2,initial_carbon);
return NO_REACTION;
}
air.set_moles(tritium,-FUSION_TRITIUM_MOLES_USED);
if(reaction_energy > 0)
{
air.set_moles(o2,air.get_moles(o2)+FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT));
air.set_moles(n2o,air.get_moles(o2)+FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT));
}
else
{
air.set_moles(bz,air.get_moles(o2)+FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT));
air.set_moles(no2,air.get_moles(o2)+FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT));
}
if(reaction_energy != 0.0)
{
if(holder.type != DataType::NULL_D)
{
auto particle_chance = (PARTICLE_CHANCE_CONSTANT/(reaction_energy/PARTICLE_CHANCE_CONSTANT)) + 1;
auto rad_power = std::max((FUSION_RAD_COEFFICIENT/instability) + FUSION_RAD_MAX,0.0);
IncRefCount(holder.type,holder.value);
Core::get_proc("/proc/fusion_effects").call({holder,(float)particle_chance,(float)rad_power});
}
auto new_heat_capacity = air.heat_capacity();
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
{
air.set_temperature(std::clamp(air.get_temperature()*old_heat_capacity+reaction_energy,TCMB,INFINITY));
}
return REACTING;
}
return NO_REACTION;
}*/
Loading