Moves around some ZAS stuff and fixes some things in FEA gas mixtures.

ShareSpace now can take a gas mixture as an argument, alongside the usual list of tiles.
Three new procs on gas mixtures, add() multiply() and divide().  Self explanatory.
Zones with unsimulated tiles that sleep will now reset themselves to the average air.
assume_air will only add air to sleeping zones with unsimulated tiles if it can wake the zone up.

Signed-off-by: Mloc <colmohici@gmail.com>
This commit is contained in:
Mloc
2013-10-23 22:01:48 +01:00
parent 07c4560ded
commit 5234b1394b
2 changed files with 191 additions and 64 deletions

View File

@@ -965,6 +965,7 @@ What are the archived variables for?
//Outputs: 1 if can rebuild, 0 if not.
if(!sample) return 0
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
@@ -972,52 +973,61 @@ What are the archived variables for?
((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)))
((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (carbon_dioxide > (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
var/check_moles
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
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
check_moles = corresponding.moles
else
check_moles = 0
if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \
((check_moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (check_moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
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
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
check_moles = corresponding.moles
else
check_moles = 0
if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \
((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles)))
return 0
return 1
/datum/gas_mixture/proc/compare_unsim(turf/list/samples)
//Purpose: Compares a list of unsimulated tiles to self to see if within acceptable ranges that group processing may be enabled
//Called by: ZAS sleeping detection.
//Inputs: List of unsimulated turfs to compare to
//Outputs: 1 if within an acceptable range to sleep, 0 otherwise.
var/datum/gas_mixture/after_share = new
after_share.copy_from(src)
/datum/gas_mixture/proc/add(datum/gas_mixture/right_side)
oxygen += right_side.oxygen
carbon_dioxide += right_side.carbon_dioxide
nitrogen += right_side.nitrogen
toxins += right_side.toxins
ShareSpace(after_share, samples)
if(trace_gases.len || right_side.trace_gases.len)
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 src.compare(after_share)
update_values()
return 1
/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
//Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle
@@ -1025,18 +1035,42 @@ What are the archived variables for?
//Inputs: Gas mix to remove
//Outputs: 1
oxygen -= right_side.oxygen
carbon_dioxide -= right_side.carbon_dioxide
nitrogen -= right_side.nitrogen
toxins -= right_side.toxins
oxygen = max(oxygen - right_side.oxygen)
carbon_dioxide = max(carbon_dioxide - right_side.carbon_dioxide)
nitrogen = max(nitrogen - right_side.nitrogen)
toxins = max(toxins - right_side.toxins)
if((trace_gases.len > 0)||(right_side.trace_gases.len > 0))
if(trace_gases.len || right_side.trace_gases.len)
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
if(corresponding)
corresponding.moles = max(0, corresponding.moles - trace_gas.moles)
corresponding.moles -= trace_gas.moles
update_values()
return 1
return 1
/datum/gas_mixture/proc/multiply(factor)
oxygen *= factor
carbon_dioxide *= factor
nitrogen *= factor
toxins *= factor
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
trace_gas.moles *= factor
update_values()
return 1
/datum/gas_mixture/proc/divide(factor)
oxygen /= factor
carbon_dioxide /= factor
nitrogen /= factor
toxins /= factor
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
trace_gas.moles /= factor
update_values()
return 1

View File

@@ -10,6 +10,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
var/list/contents //All the tiles that are contained in this zone.
var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out.
var/datum/gas_mixture/air_unsim //Overall average of the air in connected unsimualted tiles.
var/unsim_air_needs_update = 0 //Set to 1 on geometry changes, marks air_unsim as needing update.
var/list/connections //connection objects which refer to connections with other zones, e.g. through a door.
var/list/direct_connections //connections which directly connect two zones.
@@ -126,6 +129,8 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
unsimulated_tiles += T
contents -= T
unsim_air_needs_update = 1
/zone/proc/RemoveTurf(turf/T)
//Same, but in reverse.
if(istype(T, /turf/simulated))
@@ -146,6 +151,45 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
if(!unsimulated_tiles.len)
unsimulated_tiles = null
unsim_air_needs_update = 1
//Updates the air_unsim var
/zone/proc/UpdateUnsimAvg()
if(!unsim_air_needs_update)
return
unsim_air_needs_update = 0
if(!air_unsim)
air_unsim = new /datum/gas_mixture
air_unsim.oxygen = 0
air_unsim.nitrogen = 0
air_unsim.carbon_dioxide = 0
air_unsim.toxins = 0
air_unsim.temperature = 0
var/correction_ratio = max(1, max(max(1, air.group_multiplier) + 3, 1) + unsimulated_tiles.len) / unsimulated_tiles.len
for(var/turf/T in unsimulated_tiles)
if(!istype(T, /turf/simulated))
air_unsim.oxygen += T.oxygen
air_unsim.carbon_dioxide += T.carbon_dioxide
air_unsim.nitrogen += T.nitrogen
air_unsim.toxins += T.toxins
air_unsim.temperature += T.temperature/unsimulated_tiles.len
//These values require adjustment in order to properly represent a room of the specified size.
air_unsim.oxygen *= correction_ratio
air_unsim.carbon_dioxide *= correction_ratio
air_unsim.nitrogen *= correction_ratio
air_unsim.toxins *= correction_ratio
air_unsim.group_multiplier = unsimulated_tiles.len
air_unsim.update_values()
return
//////////////
//PROCESSING//
//////////////
@@ -180,20 +224,23 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
progress = "problem with: ShareSpace()"
if(unsim_air_needs_update)
unsim_air_needs_update = 0
UpdateUnsimAvg()
if(unsimulated_tiles)
if(locate(/turf/simulated) in unsimulated_tiles)
for(var/turf/simulated/T in unsimulated_tiles)
unsimulated_tiles -= T
if(unsimulated_tiles.len)
var/old_pressure = air.return_pressure()
var/moved_air = ShareSpace(air,unsimulated_tiles)
var/moved_air = ShareSpace(air, air_unsim)
if(!air.compare(air_unsim))
interactions_with_unsim++
if(moved_air > vsc.airflow_lightest_pressure)
AirflowSpace(src)
if(old_pressure && (moved_air / old_pressure) > MINIMUM_AIR_RATIO_TO_SUSPEND) //Check if we've moved enough air to be considered awake.
interactions_with_unsim++
else
unsimulated_tiles = null
@@ -310,11 +357,11 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
Z.interactions_with_neighbors++
interactions_with_neighbors++
if(!interactions_with_neighbors && !interactions_with_unsim)
SetStatus(ZONE_SLEEPING)
if(!interactions_with_neighbors && !interactions_with_unsim)
SetStatus(ZONE_SLEEPING)
interactions_with_neighbors = 0
interactions_with_unsim = 0
interactions_with_neighbors = 0
interactions_with_unsim = 0
progress = "all components completed successfully, the problem is not here"
@@ -327,6 +374,11 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
else if(status == ZONE_ACTIVE && new_status == ZONE_SLEEPING)
air_master.active_zones.Remove(src)
status = ZONE_SLEEPING
if(unsimulated_tiles && unsimulated_tiles.len)
UpdateUnsimAvg()
air.copy_from(air_unsim)
if(!archived_air)
archived_air = new
archived_air.copy_from(air)
@@ -342,12 +394,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
var/difference = 0
if(unsimulated_tiles && unsimulated_tiles.len)
if(air.compare_unsim(unsimulated_tiles))
UpdateUnsimAvg()
if(!air.compare(air_unsim))
difference = 1
if(!difference)
for(var/zone/Z in connected_zones) //Check adjacent zones for air difference.
if(air.compare(Z.air))
if(!air.compare(Z.air))
difference = 1
break
@@ -362,11 +415,20 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
return air.merge(giver)
else
if(unsimulated_tiles && unsimulated_tiles.len)
UpdateUnsimAvg()
var/datum/gas_mixture/compare_air = new
compare_air.copy_from(giver)
compare_air.add(air_unsim)
compare_air.divide(air.group_multiplier)
if(air_unsim.compare(compare_air))
return 0
var/result = air.merge(giver)
if(!archived_air.compare(air))
SetStatus(ZONE_ACTIVE)
return result
@@ -443,6 +505,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
if(H)
var/G_avg = (G.moles*size + H.moles*share_size) / (size+share_size)
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
else
H = new G.type
@@ -451,6 +514,15 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
for(var/datum/gas/G in B.trace_gases)
var/datum/gas/H = locate(G.type) in A.trace_gases
if(H)
H = new G.type
A.trace_gases += H
var/G_avg = (G.moles*size) / (size+share_size)
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
A.update_values()
B.update_values()
@@ -459,7 +531,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
//A modified version of ShareRatio for spacing gas at the same rate as if it were going into a large airless room.
if(!unsimulated_tiles || !unsimulated_tiles.len)
if(!unsimulated_tiles)
return 0
var
@@ -472,6 +544,22 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
size = max(1,A.group_multiplier)
var/tileslen
var/share_size
if(istype(unsimulated_tiles, /datum/gas_mixture))
var/datum/gas_mixture/avg_unsim = unsimulated_tiles
unsim_oxygen = avg_unsim.oxygen
unsim_co2 = avg_unsim.carbon_dioxide
unsim_nitrogen = avg_unsim.nitrogen
unsim_plasma = avg_unsim.toxins
unsim_temperature = avg_unsim.temperature
share_size = max(1, max(size + 3, 1) + avg_unsim.group_multiplier)
tileslen = avg_unsim.group_multiplier
else if(istype(unsimulated_tiles, /list))
if(!unsimulated_tiles.len)
return 0
// We use the same size for the potentially single space tile
// as we use for the entire room. Why is this?
// Short answer: We do not want larger rooms to depressurize more
@@ -479,20 +567,25 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
// oh-shit effect when large rooms get breached, but still having small
// rooms remain pressurized for long enough to make escape possible.
share_size = max(1, max(size + 3, 1) + unsimulated_tiles.len)
correction_ratio = share_size / unsimulated_tiles.len
var/correction_ratio = share_size / unsimulated_tiles.len
for(var/turf/T in unsimulated_tiles)
unsim_oxygen += T.oxygen
unsim_co2 += T.carbon_dioxide
unsim_nitrogen += T.nitrogen
unsim_plasma += T.toxins
unsim_temperature += T.temperature/unsimulated_tiles.len
for(var/turf/T in unsimulated_tiles)
unsim_oxygen += T.oxygen
unsim_co2 += T.carbon_dioxide
unsim_nitrogen += T.nitrogen
unsim_plasma += T.toxins
unsim_temperature += T.temperature/unsimulated_tiles.len
//These values require adjustment in order to properly represent a room of the specified size.
unsim_oxygen *= correction_ratio
unsim_co2 *= correction_ratio
unsim_nitrogen *= correction_ratio
unsim_plasma *= correction_ratio
tileslen = unsimulated_tiles.len
else //invalid input type
return 0
//These values require adjustment in order to properly represent a room of the specified size.
unsim_oxygen *= correction_ratio
unsim_co2 *= correction_ratio
unsim_nitrogen *= correction_ratio
unsim_plasma *= correction_ratio
unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen, unsim_co2, unsim_nitrogen, unsim_plasma)
var
@@ -517,8 +610,8 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
if((full_heat_capacity + unsim_heat_capacity) > 0)
temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity)
if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick.
ratio = sharing_lookup_table[unsimulated_tiles.len]
if(sharing_lookup_table.len >= tileslen) //6 or more interconnecting tiles will max at 42% of air moved per tick.
ratio = sharing_lookup_table[tileslen]
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg )
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg )