Files
vgstation13/code/FEA/FEA_gas_mixture.dm
2015-07-18 02:30:51 -05:00

964 lines
39 KiB
Plaintext

/*
What are the archived variables for?
Calculations are done using the archived variables with the results merged into the regular variables.
This prevents race conditions that arise based on the order of tile processing.
*/
#define SPECIFIC_HEAT_TOXIN 200
#define SPECIFIC_HEAT_AIR 20
#define SPECIFIC_HEAT_CDO 30
#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \
(carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN)
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0001))
/datum/gas
sleeping_agent
specific_heat = 40
oxygen_agent_b
specific_heat = 300
volatile_fuel
specific_heat = 30
var/moles = 0
var/specific_heat = 0
var/moles_archived = 0
/datum/gas_mixture
var/oxygen = 0
var/carbon_dioxide = 0
var/nitrogen = 0
var/toxins = 0
var/volume = CELL_VOLUME
var/temperature = 0 //in Kelvin, use calculate_temperature() to modify
var/group_multiplier = 1
//Size of the group this gas_mixture is representing.
//=1 for singletons
var/graphic
var/list/datum/gas/trace_gases = list()
var/tmp/oxygen_archived
var/tmp/carbon_dioxide_archived
var/tmp/nitrogen_archived
var/tmp/toxins_archived
var/tmp/temperature_archived
var/tmp/graphic_archived
var/tmp/fuel_burnt = 0
//PV=nRT - related procedures
proc/heat_capacity()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/heat_capacity() called tick#: [world.time]")
var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins)
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
heat_capacity += trace_gas.moles*trace_gas.specific_heat
return heat_capacity
proc/heat_capacity_archived()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/heat_capacity_archived() called tick#: [world.time]")
var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived)
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat
return heat_capacity_archived
proc/total_moles()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/total_moles() called tick#: [world.time]")
var/moles = oxygen + carbon_dioxide + nitrogen + toxins
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
moles += trace_gas.moles
return moles
proc/return_pressure()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/return_pressure() called tick#: [world.time]")
if(volume>0)
return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
return 0
proc/return_temperature()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/return_temperature() called tick#: [world.time]")
return temperature
proc/return_volume()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/return_volume() called tick#: [world.time]")
return max(0, volume)
proc/thermal_energy()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/thermal_energy() called tick#: [world.time]")
return temperature*heat_capacity()
//Procedures used for very specific events
proc/check_tile_graphic()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_tile_graphic() called tick#: [world.time]")
//returns 1 if graphic changed
graphic = null
if(toxins > MOLES_PLASMA_VISIBLE)
graphic = "plasma"
else
var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases
if(sleeping_agent && (sleeping_agent.moles > 1))
graphic = "sleeping_agent"
else
graphic = null
return graphic != graphic_archived
proc/react(atom/dump_location)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/react() called tick#: [world.time]")
var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
if(trace_gases.len > 0)
if(temperature > 900)
if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY)
var/datum/gas/oxygen_agent_b/trace_gas = locate(/datum/gas/oxygen_agent_b/) in trace_gases
if(trace_gas)
var/reaction_rate = min(carbon_dioxide*0.75, toxins*0.25, trace_gas.moles*0.05)
carbon_dioxide -= reaction_rate
oxygen += reaction_rate
trace_gas.moles -= reaction_rate*0.05
temperature -= (reaction_rate*20000)/heat_capacity()
reacting = 1
fuel_burnt = 0
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
//world << "pre [temperature], [oxygen], [toxins]"
if(fire() > 0)
reacting = 1
//world << "post [temperature], [oxygen], [toxins]"
return reacting
proc/fire()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/fire() called tick#: [world.time]")
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel/) in trace_gases
if(fuel_store) //General volatile gas burn
var/burned_fuel = 0
if(oxygen < fuel_store.moles)
burned_fuel = oxygen
fuel_store.moles -= burned_fuel
oxygen = 0
else
burned_fuel = fuel_store.moles
oxygen -= fuel_store.moles
trace_gases -= fuel_store
fuel_store = null
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
carbon_dioxide += burned_fuel
fuel_burnt += burned_fuel
//Handle plasma burning
if(toxins > MINIMUM_HEAT_CAPACITY)
var/plasma_burn_rate = 0
var/oxygen_burn_rate = 0
//more plasma released at higher temperatures
var/temperature_scale
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 = 1.4 - temperature_scale
if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (toxins*temperature_scale)/4
else
plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
toxins -= plasma_burn_rate
oxygen -= plasma_burn_rate*oxygen_burn_rate
carbon_dioxide += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate)
if(energy_released > 0)
var/new_heat_capacity = heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
return fuel_burnt
proc/archive()
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/archive() called tick#: [world.time]")
//Update archived versions of variables
//Returns: 1 in all cases
proc/merge(datum/gas_mixture/giver)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/merge() called tick#: [world.time]")
//Merges all air from giver into self. Deletes giver.
//Returns: 1 on success (no failure cases yet)
proc/check_then_merge(datum/gas_mixture/giver)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_then_merge() called tick#: [world.time]")
//Similar to merge(...) but first checks to see if the amount of air assumed is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: 1 on successful merge, 0 if the check failed
proc/remove(amount)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/remove() called tick#: [world.time]")
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
proc/remove_ratio(ratio)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/remove_ratio() called tick#: [world.time]")
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
proc/subtract(datum/gas_mixture/right_side)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/subtract() called tick#: [world.time]")
//Subtracts right_side from air_mixture. Used to help turfs mingle
proc/check_then_remove(amount)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_then_remove() called tick#: [world.time]")
//Similar to remove(...) but first checks to see if the amount of air removed is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: gas_mixture with the gases removed or null
proc/copy_from(datum/gas_mixture/sample)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/copy_from() called tick#: [world.time]")
//Copies variables from sample
proc/share(datum/gas_mixture/sharer)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/share() called tick#: [world.time]")
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
proc/mimic(turf/model)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/mimic() called tick#: [world.time]")
//Similar to share(...), except the model is not modified
//Return: amount of gas exchanged
proc/check_gas_mixture(datum/gas_mixture/sharer)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_gas_mixture() called tick#: [world.time]")
//Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if both checks pass
proc/check_turf(turf/model)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_turf() called tick#: [world.time]")
//Returns: 0 if self-check failed or 1 if check passes
// check_me_then_share(datum/gas_mixture/sharer)
//Similar to share(...) but first checks to see if amount of air moved is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: 1 on successful share, 0 if the check failed
// check_me_then_mimic(turf/model)
//Similar to mimic(...) but first checks to see if amount of air moved is small enough
// that group processing is still accurate (aborts if not)
//Returns: 1 on successful mimic, 0 if the check failed
// check_both_then_share(datum/gas_mixture/sharer)
//Similar to check_me_then_share(...) but also checks to see if amount of air moved is small enough
// that group processing is still accurate for the sharer (aborts if not)
//Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if successful share
proc/temperature_mimic(turf/model, conduction_coefficient)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/temperature_mimic() called tick#: [world.time]")
proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/temperature_turf_share() called tick#: [world.time]")
proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient)
proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_me_then_temperature_share() called tick#: [world.time]")
proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\proc/check_me_then_temperature_turf_share() called tick#: [world.time]")
proc/compare(datum/gas_mixture/sample)
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
archive()
oxygen_archived = oxygen
carbon_dioxide_archived = carbon_dioxide
nitrogen_archived = nitrogen
toxins_archived = toxins
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
trace_gas.moles_archived = trace_gas.moles
temperature_archived = temperature
graphic_archived = graphic
return 1
check_then_merge(datum/gas_mixture/giver)
if(!giver)
return 0
if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
if(giver.trace_gases.len)
for(var/datum/gas/trace_gas in giver.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
return merge(giver)
merge(datum/gas_mixture/giver)
if(!giver)
return 0
if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()*group_multiplier
var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0)
temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
if((group_multiplier>1)||(giver.group_multiplier>1))
oxygen += giver.oxygen*giver.group_multiplier/group_multiplier
carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier
nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier
toxins += giver.toxins*giver.group_multiplier/group_multiplier
else
oxygen += giver.oxygen
carbon_dioxide += giver.carbon_dioxide
nitrogen += giver.nitrogen
toxins += giver.toxins
if(giver.trace_gases.len)
for(var/datum/gas/trace_gas in giver.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier
// del(giver)
return 1
remove(amount)
var/sum = total_moles()
amount = min(amount,sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
removed.oxygen = QUANTIZE((oxygen/sum)*amount)
removed.nitrogen = QUANTIZE((nitrogen/sum)*amount)
removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount)
removed.toxins = QUANTIZE((toxins/sum)*amount)
oxygen -= removed.oxygen/group_multiplier
nitrogen -= removed.nitrogen/group_multiplier
carbon_dioxide -= removed.carbon_dioxide/group_multiplier
toxins -= removed.toxins/group_multiplier
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
removed.trace_gases += corresponding
corresponding.moles = (trace_gas.moles/sum)*amount
trace_gas.moles -= corresponding.moles/group_multiplier
removed.temperature = temperature
return removed
remove_ratio(ratio)
if(ratio <= 0)
return null
ratio = min(ratio, 1)
var/datum/gas_mixture/removed = new
removed.oxygen = QUANTIZE(oxygen*ratio)
removed.nitrogen = QUANTIZE(nitrogen*ratio)
removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio)
removed.toxins = QUANTIZE(toxins*ratio)
oxygen -= removed.oxygen/group_multiplier
nitrogen -= removed.nitrogen/group_multiplier
carbon_dioxide -= removed.carbon_dioxide/group_multiplier
toxins -= removed.toxins/group_multiplier
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
removed.trace_gases += corresponding
corresponding.moles = trace_gas.moles*ratio
trace_gas.moles -= corresponding.moles/group_multiplier
removed.temperature = temperature
return removed
check_then_remove(amount)
//Since it is all proportional, the check may be done on the gas as a whole
var/sum = total_moles()
amount = min(amount,sum) //Can not take more air than tile has!
if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > sum*MINIMUM_AIR_RATIO_TO_SUSPEND))
return 0
return remove(amount)
copy_from(datum/gas_mixture/sample)
oxygen = sample.oxygen
carbon_dioxide = sample.carbon_dioxide
nitrogen = sample.nitrogen
toxins = sample.toxins
trace_gases.len=null
if(sample.trace_gases.len > 0)
for(var/datum/gas/trace_gas in sample.trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles = trace_gas.moles
temperature = sample.temperature
return 1
subtract(datum/gas_mixture/right_side)
oxygen -= right_side.oxygen
carbon_dioxide -= right_side.carbon_dioxide
nitrogen -= right_side.nitrogen
toxins -= right_side.toxins
if((trace_gases.len > 0)||(right_side.trace_gases.len > 0))
for(var/datum/gas/trace_gas in right_side.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles -= trace_gas.moles
return 1
check_gas_mixture(datum/gas_mixture/sharer)
if(!sharer) return 0
var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5
var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5
var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5
var/delta_toxins = (toxins_archived - sharer.toxins_archived)/5
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
if(sharer.trace_gases.len)
for(var/datum/gas/trace_gas in sharer.trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
return 0
else
return 0
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
if(!locate(trace_gas.type) in sharer.trace_gases)
return 0
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return -1
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
if(corresponding)
if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
return -1
else
return -1
return 1
check_turf(turf/model)
var/delta_oxygen = (oxygen_archived - model.oxygen)/5
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/5
var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/5
var/delta_toxins = (toxins_archived - model.toxins)/5
var/delta_temperature = (temperature_archived - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
return 0
return 1
share(datum/gas_mixture/sharer)
if(!sharer) return 0
var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/5
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5
var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/5
var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/5
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
var/heat_capacity_self_to_sharer = 0
var/heat_capacity_sharer_to_self = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
if(delta_air > 0)
heat_capacity_self_to_sharer += air_heat_capacity
else
heat_capacity_sharer_to_self -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
if(delta_carbon_dioxide > 0)
heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
else
heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
if(delta_toxins > 0)
heat_capacity_self_to_sharer += toxins_heat_capacity
else
heat_capacity_sharer_to_self -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()*group_multiplier
old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier
oxygen -= delta_oxygen/group_multiplier
sharer.oxygen += delta_oxygen/sharer.group_multiplier
carbon_dioxide -= delta_carbon_dioxide/group_multiplier
sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier
nitrogen -= delta_nitrogen/group_multiplier
sharer.nitrogen += delta_nitrogen/sharer.group_multiplier
toxins -= delta_toxins/group_multiplier
sharer.toxins += delta_toxins/sharer.group_multiplier
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
var/list/trace_types_considered = list()
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
var/delta = 0
if(corresponding)
delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/5
else
corresponding = new trace_gas.type()
sharer.trace_gases += corresponding
delta = trace_gas.moles_archived/5
trace_gas.moles -= delta/group_multiplier
corresponding.moles += delta/sharer.group_multiplier
if(delta)
var/individual_heat_capacity = trace_gas.specific_heat*delta
if(delta > 0)
heat_capacity_self_to_sharer += individual_heat_capacity
else
heat_capacity_sharer_to_self -= individual_heat_capacity
moved_moles += delta
trace_types_considered += trace_gas.type
if(sharer.trace_gases.len)
for(var/datum/gas/trace_gas in sharer.trace_gases)
if(trace_gas.type in trace_types_considered) continue
else
var/datum/gas/corresponding
var/delta = 0
corresponding = new trace_gas.type()
trace_gases += corresponding
delta = trace_gas.moles_archived/5
trace_gas.moles -= delta/sharer.group_multiplier
corresponding.moles += delta/group_multiplier
//Guaranteed transfer from sharer to self
var/individual_heat_capacity = trace_gas.specific_heat*delta
heat_capacity_sharer_to_self += individual_heat_capacity
moved_moles += -delta
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
return delta_pressure*R_IDEAL_GAS_EQUATION/volume
else
return 0
mimic(turf/model, border_multiplier)
var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/5
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/5
var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/5
var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/5
var/delta_temperature = (temperature_archived - model.temperature)
var/heat_transferred = 0
var/old_self_heat_capacity = 0
var/heat_capacity_transferred = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
heat_transferred -= air_heat_capacity*model.temperature
heat_capacity_transferred -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
heat_capacity_transferred -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
heat_transferred -= toxins_heat_capacity*model.temperature
heat_capacity_transferred -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()*group_multiplier
if(border_multiplier)
oxygen -= delta_oxygen*border_multiplier/group_multiplier
carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier
nitrogen -= delta_nitrogen*border_multiplier/group_multiplier
toxins -= delta_toxins*border_multiplier/group_multiplier
else
oxygen -= delta_oxygen/group_multiplier
carbon_dioxide -= delta_carbon_dioxide/group_multiplier
nitrogen -= delta_nitrogen/group_multiplier
toxins -= delta_toxins/group_multiplier
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/delta = 0
delta = trace_gas.moles_archived/5
if(border_multiplier)
trace_gas.moles -= delta*border_multiplier/group_multiplier
else
trace_gas.moles -= delta/group_multiplier
var/heat_cap_transferred = delta*trace_gas.specific_heat
heat_transferred += heat_cap_transferred*temperature_archived
heat_capacity_transferred += heat_cap_transferred
moved_moles += delta
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
if(border_multiplier)
temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
else
temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
temperature_mimic(model, model.thermal_conductivity, border_multiplier)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
return delta_pressure*R_IDEAL_GAS_EQUATION/volume
else
return 0
check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived))
return -1
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/sharer.heat_capacity
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency
check_me_then_temperature_mimic(turf/model, conduction_coefficient)
var/delta_temperature = (temperature_archived - model.temperature)
var/self_temperature_delta = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
return 1
//Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency
temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature -= heat/(self_heat_capacity*group_multiplier)
sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier)
temperature_mimic(turf/model, conduction_coefficient, border_multiplier)
var/delta_temperature = (temperature - model.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()//_archived()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
if(border_multiplier)
temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier)
else
temperature -= heat/(self_heat_capacity*group_multiplier)
temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
temperature -= heat/(self_heat_capacity*group_multiplier)
sharer.temperature += heat/sharer.heat_capacity
compare(datum/gas_mixture/sample)
if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
return 0
if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
return 0
if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
return 0
if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
return 0
if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
//world << "temp fail [temperature] & [sample.temperature]"
return 0
if(sample.trace_gases.len)
for(var/datum/gas/trace_gas in sample.trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
return 0
else
return 0
if(trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
return 0
else
return 0
return 1