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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"execution": "cpp",
"future": "cpp",
"queue": "cpp",
"set": "cpp"
"set": "cpp",
"variant": "cpp"
}
}
9 changes: 5 additions & 4 deletions byond-extools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ project(byond-extools)
if (WIN32)
enable_language(ASM)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(SRC_DIR ${CMAKE_SOURCE_DIR}/src)
Expand All @@ -37,9 +37,10 @@ if (WIN32)
set_property(TARGET byond-extools PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
if (MSVC OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
target_compile_options(byond-extools PRIVATE "/MP")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:RELWITHDEBINFO>:/Ob2;/Zc:inline;/arch:AVX;/Oi;/Ot;/fp:fast;/Qvec-report:1;/std:c++latest>")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:RELEASE>:/Ob2;/Zc:inline;/arch:AVX;/Oi;/Ot;/fp:fast;/Qvec-report:1;/std:c++latest>")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:MINSIZEREL>:/Ob2;/Zc:inline;/arch:AVX;/Oi;/Os;/fp:fast;/Qvec-report:1;/std:c++latest>")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:RELWITHDEBINFO>:/Ob2;/Zc:inline;/arch:AVX;/fp:fast;/Oi;/Ot;/Qvec-report:1")
target_link_options(byond-extools PRIVATE "$<$<CONFIG:RELWITHDEBINFO>:/PDBSTRIPPED:RelWithDebInfo/smallpdb.pdb;/OPT:REF,ICF>")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:RELEASE>:/Ob2;/Zc:inline;/arch:AVX;/Oi;/Ot;/fp:fast;/Qvec-report:1>")
target_compile_options(byond-extools PRIVATE "$<$<CONFIG:MINSIZEREL>:/Ob2;/Zc:inline;/arch:AVX;/Oi;/Os;/fp:fast;/Qvec-report:1>")
else()
target_link_libraries(byond-extools PRIVATE "ws2_32" "psapi" "-static-libgcc" "-static-libstdc++" "-static")
endif()
Expand Down
98 changes: 66 additions & 32 deletions byond-extools/src/monstermos/GasMixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ std::vector<float> gas_specific_heat;

extern int total_num_gases;

void GasMixture::garbage_collect() {
int last_non_zero = 0;
for(int i=0;i<moles.size();i++)
{
if(moles[i] >= GAS_MIN_MOLES)
{
last_non_zero = i;
}
}
moles.resize(last_non_zero+1);
}

GasMixture::GasMixture(float v)
{
if(v < 0) v = 0;
Expand All @@ -26,6 +38,20 @@ GasMixture::GasMixture(float v)

GasMixture::GasMixture() {}

float GasMixture::get_moles(int gas_type) const {
return moles.size() > gas_type ? moles[gas_type] : 0.0;
}

void GasMixture::set_moles(int gas_type, float new_moles) {
if(!immutable) {
if(gas_type > moles.size())
{
moles.resize(gas_type+1);
}
moles[gas_type] = new_moles;
}
}

float GasMixture::total_moles() const {
return std::reduce(std::execution::seq,moles.cbegin(),moles.cend());
}
Expand Down Expand Up @@ -83,6 +109,7 @@ void GasMixture::merge(const GasMixture &giver) {
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity;
}
}
moles.resize(std::max(moles.size(),giver.moles.size()));
std::transform(
std::execution::seq,
moles.begin(),moles.end(),
Expand All @@ -107,13 +134,9 @@ GasMixture GasMixture::remove_ratio(float ratio) {
moles.begin(),moles.end(),
removed.moles.begin(),
[&ratio](auto& gas) {
if(gas < GAS_MIN_MOLES) {
return (float)(0.0);
} else {
return gas * ratio;
}
return gas * ratio;
});
if(!immutable)
if(!immutable) [[likely]]
{
std::transform(std::execution::seq,
moles.begin(),moles.end(),
Expand All @@ -123,6 +146,8 @@ GasMixture GasMixture::remove_ratio(float ratio) {
return myGas-removedGas;
});
}
removed.garbage_collect();
garbage_collect();
return removed;
}

Expand All @@ -132,38 +157,44 @@ void GasMixture::copy_from_mutable(const GasMixture &sample) {
temperature = sample.temperature;
}

float GasMixture::share(GasMixture &sharer, int atmos_adjacent_turfs) {
float temperature_delta = temperature_archived - sharer.temperature_archived;
float abs_temperature_delta = std::abs(temperature_delta);
float old_self_heat_capacity = 0;
float old_sharer_heat_capacity = 0;
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) {
old_self_heat_capacity = heat_capacity();
old_sharer_heat_capacity = sharer.heat_capacity();
}
float GasMixture::share(GasMixture &sharer, const int atmos_adjacent_turfs) {
const float temperature_delta = temperature_archived - sharer.temperature_archived;
const float abs_temperature_delta = std::abs(temperature_delta);
const float old_self_heat_capacity = heat_capacity();
const float old_sharer_heat_capacity = sharer.heat_capacity();
float heat_capacity_self_to_sharer = 0;
float heat_capacity_sharer_to_self = 0;
float moved_moles = 0;
float abs_moved_moles = 0;
auto capacities = gas_specific_heat; // cache for sanic speed (yeah, seriously)
for(int i = 0; i < moles.size(); i++) {
float delta = (moles_archived[i] - sharer.moles_archived[i])/(atmos_adjacent_turfs+1);
if(std::abs(delta) >= GAS_MIN_MOLES) {
if((abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)) {
float gas_heat_capacity = delta * capacities[i];
if(delta > 0) {
heat_capacity_self_to_sharer += gas_heat_capacity;
} else {
heat_capacity_sharer_to_self -= gas_heat_capacity;
}
const int max_size = std::max(std::max(moles_archived.size(),sharer.moles_archived.size()),std::max(moles.size(),sharer.moles.size()));
moles.resize(max_size);
sharer.moles.resize(max_size);
moles_archived.resize(max_size);
sharer.moles_archived.resize(max_size);
auto moles_copy = moles;
auto sharer_copy = sharer.moles;
std::vector<float> heat_cap_deltas(max_size);
for(int i = 0; i < max_size; i++) {
const float delta = (moles_archived[i] - sharer.moles_archived[i])/(atmos_adjacent_turfs+1);
heat_cap_deltas[i] = delta * capacities[i];
moles_copy[i] -= delta;
sharer_copy[i] += delta;
moved_moles += delta;
abs_moved_moles += std::abs(delta);
}
if((abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)) {
for(int i=0;i<max_size;i++) {
const float gas_heat_capacity = heat_cap_deltas[i];
if(gas_heat_capacity > 0) {
heat_capacity_self_to_sharer += gas_heat_capacity;
} else {
heat_capacity_sharer_to_self -= gas_heat_capacity;
}
if(!immutable) moles[i] -= delta;
if(!sharer.immutable) sharer.moles[i] += delta;
moved_moles += delta;
abs_moved_moles += std::abs(delta);
}
}

if(!immutable) moles = moles_copy;
if(!sharer.immutable) sharer.moles = sharer_copy;
last_share = abs_moved_moles;

if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) {
Expand All @@ -186,6 +217,8 @@ float GasMixture::share(GasMixture &sharer, int atmos_adjacent_turfs) {
}
}
}
garbage_collect();
sharer.garbage_collect();
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || std::abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) {
float our_moles = total_moles();
float their_moles = sharer.total_moles();
Expand Down Expand Up @@ -248,7 +281,8 @@ int GasMixture::compare(GasMixture &sample) const {

void GasMixture::clear() {
if (immutable) return;
std::fill(moles.begin(),moles.end(),(float)0.0);
moles.clear();
moles_archived.clear();
}

void GasMixture::multiply(float multiplier) {
Expand All @@ -259,4 +293,4 @@ void GasMixture::multiply(float multiplier) {
[&multiplier](auto& gas) {
return gas*multiplier;
});
}
}
9 changes: 7 additions & 2 deletions byond-extools/src/monstermos/GasMixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

#include "atmos_defines.h"

#include "../third_party/robin_hood.h"

#include <vector>

#define GAS_MIN_MOLES 0.00000005
#define MINIMUM_HEAT_CAPACITY 0.0003

extern std::vector<float> gas_specific_heat;

using gas_entry = std::pair<int,float>;

class GasMixture
{
public:
GasMixture(float volume);
void garbage_collect();
void mark_immutable();
inline bool is_immutable() const {return immutable;}

Expand All @@ -33,11 +38,11 @@ class GasMixture
int compare(GasMixture &sample) const;
void clear();
void multiply(float multiplier);
float get_moles(int gas_type) const;
void set_moles(int gas_type, float new_moles);

inline float get_temperature() const { return temperature; }
inline void set_temperature(float new_temp) { if(!immutable) temperature = new_temp; }
inline float get_moles(int gas_type) const {return moles[gas_type] >= GAS_MIN_MOLES ? moles[gas_type] : 0;}
inline void set_moles(int gas_type, float new_moles) { if(!immutable) moles[gas_type] = new_moles; }
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; }
Expand Down
26 changes: 12 additions & 14 deletions byond-extools/src/monstermos/Reaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Reaction::Reaction(Value v)
List min_reqs = v.get("min_requirements");
if(min_reqs.at("TEMP").type == DataType::NUMBER) min_temp_req = min_reqs.at("TEMP");
if(min_reqs.at("ENER").type == DataType::NUMBER) min_ener_req = min_reqs.at("ENER");
if(min_reqs.at("MAX_TEMP").type == DataType::NUMBER) max_temp_req = min_reqs.at("MAX_TEMP");
for(unsigned int i=0;i < total_num_gases;i++)
{
auto gasReq = min_reqs.at(gas_id_to_type[i]);
Expand All @@ -17,36 +18,33 @@ Reaction::Reaction(Value v)
min_gas_reqs[i] = gasReq;
}
}
major_gas = gas_ids[v.get("major_gas").value];
priority = v.get("priority");
auto proc = Core::try_get_proc(Core::stringify(v.get("type")) + "/react");
if(!proc)
{
Core::alert_dd("Could not find proc for reaction! " + Core::stringify(v.get("type")) + "/react");
}
else
{
Core::alert_dd("Found proc for reaction: " + Core::stringify(v.get("type")) + "/react");
}
proc_id = proc->id;
}

bool Reaction::check_conditions(const GasMixture& air) const
{
if(air.get_temperature() < min_temp_req || air.thermal_energy() < min_ener_req)
{
if(!air.get_moles(major_gas)) [[likely]] {
return false;
}
else
if(air.get_temperature() < min_temp_req || air.get_temperature() > max_temp_req) [[likely]]
{
for(auto& info : min_gas_reqs)
{
if(air.get_moles(info.first) < info.second)
{
return false;
}
return false;
}
if(min_ener_req > 0.0) [[unlikely]] {
if(air.thermal_energy() < min_ener_req) {
return false;
}
}
return true;
return std::all_of(min_gas_reqs.cbegin(),min_gas_reqs.cend(),[&](auto& info) {
return air.get_moles(info.first) >= info.second;
});
}

int Reaction::react(GasMixture& air,Value src,Value holder) const
Expand Down
12 changes: 8 additions & 4 deletions byond-extools/src/monstermos/Reaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

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

#include <unordered_map>
#include "../third_party/robin_hood.h"

extern std::vector<Value> gas_id_to_type;

extern std::unordered_map<unsigned int, int> gas_ids;

extern int total_num_gases;

class Reaction
Expand All @@ -21,10 +23,12 @@ class Reaction
Reaction(Value v);
private:
Reaction();
unsigned int major_gas;
float priority;
float min_temp_req = -1.0;
float min_ener_req = -1.0;
std::unordered_map<unsigned int,float> min_gas_reqs;
float min_temp_req = 0.0;
float max_temp_req = std::numeric_limits<float>::max();
float min_ener_req = 0.0;
robin_hood::unordered_map<int,float> min_gas_reqs;
unsigned int proc_id;
};

Expand Down
37 changes: 18 additions & 19 deletions byond-extools/src/monstermos/monstermos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ trvh gasmixture_unregister(unsigned int args_len, Value* args, Value src)
uint32_t v = src.get_by_id(str_id_extools_pointer).value;
if (v != 0) {
next_gas_ids.emplace_back(v);
gas_mixtures[v-1].clear();
SetVariable(src.type, src.value, str_id_extools_pointer, Value::Null());
}
return Value::Null();
Expand Down Expand Up @@ -222,6 +223,10 @@ trvh gasmixture_set_temperature(unsigned int args_len, Value* args, Value src)
float vf = args_len > 0 ? args[0].valuef : 0;
if (std::isnan(vf) || std::isinf(vf)) {
Runtime("Attempt to set temperature to NaN or Infinity");
get_gas_mixture(src).set_temperature(293.15);
} else if(vf < 0) {
Runtime("Attempt to set temperature to negative number");
get_gas_mixture(src).set_temperature(2.7);
} else {
get_gas_mixture(src).set_temperature(vf);
}
Expand All @@ -247,7 +252,16 @@ trvh gasmixture_set_moles(unsigned int args_len, Value* args, Value src)
if (args_len < 2 || args[0].type != DATUM_TYPEPATH)
return Value::Null();
int index = gas_ids[args[0].value];
get_gas_mixture(src).set_moles(index, args[1].valuef);
float vf = args[1].valuef;
if (std::isnan(vf) || std::isinf(vf)) {
Runtime("Attempt to set moles to NaN or Infinity");
get_gas_mixture(src).set_moles(index, 0);
} else if(vf < 0) {
Runtime("Attempt to set moles to negative number");
get_gas_mixture(src).set_moles(index, 0);
} else {
get_gas_mixture(src).set_moles(index, vf);
}
return Value::Null();
}

Expand Down Expand Up @@ -654,12 +668,6 @@ trvh SSair_update_ssair(unsigned int args_len, Value* args, Value src) {
return Value::Null();
}

long long react_check_benchmark = 0;

long long react_total_benchmark = 0;

long reacts_done = 0;

trvh gasmixture_react(unsigned int args_len, Value* args, Value src)
{
GasMixture &src_gas = get_gas_mixture(src);
Expand All @@ -673,22 +681,13 @@ trvh gasmixture_react(unsigned int args_len, Value* args, Value src)
{
holder = args[0];
}
std::vector<bool> can_react(cached_reactions.size());
std::transform(std::execution::seq, //par introduces 2000 ns overhead, so, if this ever gets to be more than 2000 ns...
cached_reactions.begin(),cached_reactions.end(),
can_react.begin(),
[&src_gas](auto& reaction) {
return reaction.check_conditions(src_gas);
}
);
for(int i=0;i<cached_reactions.size();i++)
for(auto& reaction : cached_reactions)
{
if(can_react[i])
if(reaction.check_conditions(src_gas)) [[unlikely]]
{
auto &reaction = cached_reactions[i];
IncRefCount(src.type,src.value); // have to do this or the gas mixture will be GC'd at the end of the function
IncRefCount(holder.type,holder.value); // i'm assuming this would also end up GC'd--even worse
ret |= cached_reactions[i].react(src_gas,src,holder);
ret |= reaction.react(src_gas,src,holder);
}
if(ret & STOP_REACTIONS) return Value((float)ret);
}
Expand Down
Loading