mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 22:19:30 +01:00
[MIRROR] Optimizations for reactions [MDB IGNORE] (#25788)
* Optimizations for reactions (#80380) ## About The Pull Request 1. Fixes #80365 The lowers the rounding accuracy for reaction rate from `CHEMICAL_VOLUME_ROUNDING(0.01)` to `CHEMICAL_QUANTIZATION_LEVEL(0.0001)`. This stops reactions from abruptly ending when either their temperature/ph/volume become very low values. This also removes a call to `handle_reactions()` after the reaction has finished so it that it doesn't restart reactions that have failed due to failed environmental conditions(low ph/temps far below the optimal value). This not only saves overhead but can also stop potential infinite reaction loops(where if a reaction fails we try to restart it again) 2. Simplifies math for temperature handling and stops each react step from calling `handle_reactions()` when new reagent products are formed thus making reactions slightly faster. Also ensures early return if adding/removing reagents failed at any point & other smaller. nitpicks 3. Removes excess call to `update_total()` in each react step making it even faster ## Changelog 🆑 fix: Reactions whose temps/ph values fall way below their optimal values no longer restart & prevents infinite loops. Made reaction code slightly faster /🆑 * Optimizations for reactions --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
This commit is contained in:
@@ -168,7 +168,7 @@
|
||||
step_target_vol = 0
|
||||
reacted_vol = 0 //Because volumes can be lost mid reactions
|
||||
for(var/product in reaction.results)
|
||||
step_target_vol += (multiplier * reaction.results[product])
|
||||
step_target_vol += multiplier * reaction.results[product]
|
||||
reacted_vol += holder.get_reagent_amount(product)
|
||||
target_vol = reacted_vol + step_target_vol
|
||||
return TRUE
|
||||
@@ -277,7 +277,7 @@
|
||||
//Calculate DeltaT (Deviation of T from optimal)
|
||||
if(!reaction.is_cold_recipe)
|
||||
if (cached_temp < reaction.optimal_temp && cached_temp >= reaction.required_temp)
|
||||
delta_t = (((cached_temp - reaction.required_temp) ** reaction.temp_exponent_factor) / ((reaction.optimal_temp - reaction.required_temp) ** reaction.temp_exponent_factor))
|
||||
delta_t = ((cached_temp - reaction.required_temp) / (reaction.optimal_temp - reaction.required_temp)) ** reaction.temp_exponent_factor
|
||||
else if (cached_temp >= reaction.optimal_temp)
|
||||
delta_t = 1
|
||||
else //too hot
|
||||
@@ -286,7 +286,7 @@
|
||||
return
|
||||
else
|
||||
if (cached_temp > reaction.optimal_temp && cached_temp <= reaction.required_temp)
|
||||
delta_t = (((reaction.required_temp - cached_temp) ** reaction.temp_exponent_factor) / ((reaction.required_temp - reaction.optimal_temp) ** reaction.temp_exponent_factor))
|
||||
delta_t = ((reaction.required_temp - cached_temp) / (reaction.required_temp - reaction.optimal_temp)) ** reaction.temp_exponent_factor
|
||||
else if (cached_temp <= reaction.optimal_temp)
|
||||
delta_t = 1
|
||||
else //Too cold
|
||||
@@ -312,34 +312,39 @@
|
||||
purity *= purity_modifier
|
||||
|
||||
//Now we calculate how much to add - this is normalised to the rate up limiter
|
||||
var/delta_chem_factor = (reaction.rate_up_lim * delta_t) * seconds_per_tick//add/remove factor
|
||||
var/delta_chem_factor = reaction.rate_up_lim * delta_t * seconds_per_tick//add/remove factor
|
||||
//keep limited
|
||||
if(delta_chem_factor > step_target_vol)
|
||||
delta_chem_factor = step_target_vol
|
||||
//Normalise to multiproducts
|
||||
delta_chem_factor = round(delta_chem_factor / product_ratio, CHEMICAL_VOLUME_ROUNDING)
|
||||
delta_chem_factor = round(delta_chem_factor / product_ratio, CHEMICAL_QUANTISATION_LEVEL)
|
||||
if(delta_chem_factor <= 0)
|
||||
to_delete = TRUE
|
||||
return
|
||||
|
||||
//Calculate how much product to make and how much reactant to remove factors..
|
||||
for(var/reagent in reaction.required_reagents)
|
||||
holder.remove_reagent(reagent, (delta_chem_factor * reaction.required_reagents[reagent]))
|
||||
var/required_amount
|
||||
for(var/datum/reagent/requirement as anything in reaction.required_reagents)
|
||||
required_amount = reaction.required_reagents[requirement]
|
||||
if(!holder.remove_reagent(requirement, delta_chem_factor * required_amount))
|
||||
to_delete = TRUE
|
||||
return
|
||||
//Apply pH changes
|
||||
var/pH_adjust
|
||||
if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT)
|
||||
pH_adjust = ((delta_chem_factor * reaction.required_reagents[reagent]) / target_vol) * (reaction.H_ion_release * h_ion_mod)
|
||||
pH_adjust = ((delta_chem_factor * required_amount) / target_vol) * (reaction.H_ion_release * h_ion_mod)
|
||||
else //Default adds pH independant of volume
|
||||
pH_adjust = (delta_chem_factor * reaction.required_reagents[reagent]) * (reaction.H_ion_release * h_ion_mod)
|
||||
holder.adjust_specific_reagent_ph(reagent, pH_adjust)
|
||||
pH_adjust = (delta_chem_factor * required_amount) * (reaction.H_ion_release * h_ion_mod)
|
||||
holder.adjust_specific_reagent_ph(requirement, pH_adjust)
|
||||
|
||||
var/step_add
|
||||
var/total_step_added = 0
|
||||
for(var/product in reaction.results)
|
||||
for(var/datum/reagent/product as anything in reaction.results)
|
||||
//create the products
|
||||
step_add = delta_chem_factor * reaction.results[product]
|
||||
//Default handiling
|
||||
holder.add_reagent(product, step_add, null, cached_temp, purity, override_base_ph = TRUE)
|
||||
step_add = holder.add_reagent(product, delta_chem_factor * reaction.results[product], null, cached_temp, purity, override_base_ph = TRUE, no_react = TRUE)
|
||||
if(!step_add)
|
||||
to_delete = TRUE
|
||||
return
|
||||
|
||||
//Apply pH changes
|
||||
var/pH_adjust
|
||||
@@ -348,6 +353,8 @@
|
||||
else
|
||||
pH_adjust = step_add * (reaction.H_ion_release * h_ion_mod)
|
||||
holder.adjust_specific_reagent_ph(product, pH_adjust)
|
||||
|
||||
//record amounts created
|
||||
reacted_vol += step_add
|
||||
total_step_added += step_add
|
||||
|
||||
@@ -377,14 +384,13 @@
|
||||
//post reaction checks
|
||||
if(!(check_fail_states(total_step_added)))
|
||||
to_delete = TRUE
|
||||
return
|
||||
|
||||
//end reactions faster so plumbing is faster
|
||||
//length is so that plumbing is faster - but it doesn't disable competitive reactions. Basically, competitive reactions will likely reach their step target at the start, so this will disable that. We want to avoid that. But equally, we do want to full stop a holder from reacting asap so plumbing isn't waiting an tick to resolve.
|
||||
if((step_add >= step_target_vol) && (length(holder.reaction_list == 1)))
|
||||
if((step_add >= step_target_vol) && (length(holder.reaction_list) == 1))
|
||||
to_delete = TRUE
|
||||
|
||||
holder.update_total()
|
||||
|
||||
/*
|
||||
* Calculates the total sum normalised purity of ALL reagents in a holder
|
||||
* Currently calculates it irrespective of required reagents at the start, but this should be changed if this is powergamed to required reagents
|
||||
|
||||
@@ -643,7 +643,7 @@
|
||||
reagent_volume = round(reagent.volume, CHEMICAL_QUANTISATION_LEVEL) //round to this many decimal places
|
||||
|
||||
//remove very small amounts of reagents
|
||||
if((reagent_volume <= 0.05 && !is_reacting) || reagent_volume <= CHEMICAL_QUANTISATION_LEVEL)
|
||||
if(!reagent_volume || (reagent_volume <= 0.05 && !is_reacting))
|
||||
//end metabolization
|
||||
if(isliving(my_atom))
|
||||
if(reagent.metabolizing)
|
||||
@@ -663,14 +663,14 @@
|
||||
|
||||
//compute volume & ph like we would normally
|
||||
. += reagent_volume
|
||||
total_ph += (reagent.ph * reagent_volume)
|
||||
total_ph += reagent.ph * reagent_volume
|
||||
|
||||
//reasign rounded value
|
||||
reagent.volume = reagent_volume
|
||||
|
||||
//assign the final values, rounding up can sometimes cause overflow so bring it down
|
||||
total_volume = min(round(., CHEMICAL_VOLUME_ROUNDING), maximum_volume)
|
||||
if(!.)
|
||||
if(!total_volume)
|
||||
ph = CHEMICAL_NORMAL_PH
|
||||
else
|
||||
ph = clamp(total_ph / total_volume, CHEMICAL_MIN_PH, CHEMICAL_MAX_PH)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
//short cut to break when we have found our one exact type
|
||||
if(type_check == REAGENT_STRICT_TYPE)
|
||||
break
|
||||
return total_amount
|
||||
|
||||
return round(total_amount, CHEMICAL_VOLUME_ROUNDING)
|
||||
|
||||
|
||||
@@ -236,8 +236,6 @@
|
||||
is_reacting = FALSE
|
||||
LAZYNULL(previous_reagent_list) //reset it to 0 - because any change will be different now.
|
||||
update_total()
|
||||
if(!QDELING(src))
|
||||
handle_reactions() //Should be okay without. Each step checks.
|
||||
|
||||
/*
|
||||
* Force stops the current holder/reagents datum from reacting
|
||||
|
||||
Reference in New Issue
Block a user