add sleeping for ZAS connection edges

Edges will sleep and fully balance if compare() passes.
also some small small xgm tweaks.

Signed-off-by: Mloc-Argent <colmohici@gmail.com>
This commit is contained in:
Mloc-Argent
2014-12-21 20:35:40 +00:00
parent fc203f186a
commit debba68c44
5 changed files with 141 additions and 62 deletions

View File

@@ -62,6 +62,7 @@ Class Procs:
/connection_edge/var/list/connecting_turfs = list()
/connection_edge/var/direct = 0
/connection_edge/var/sleeping = 1
/connection_edge/var/coefficient = 0
@@ -88,6 +89,8 @@ Class Procs:
/connection_edge/proc/tick()
/connection_edge/proc/recheck()
/connection_edge/proc/flow(list/movable, differential, repelled)
for(var/i = 1; i <= movable.len; i++)
var/atom/movable/M = movable[i]
@@ -147,35 +150,38 @@ Class Procs:
if(A.invalid || B.invalid)
erase()
return
//world << "[id]: Tick [air_master.current_cycle]: \..."
if(direct)
if(air_master.equivalent_pressure(A, B))
//world << "merged."
erase()
air_master.merge(A, B)
//world << "zones merged."
return
//air_master.equalize(A, B)
A.air.share_ratio(B.air, coefficient)
air_master.mark_zone_update(A)
air_master.mark_zone_update(B)
//world << "equalized."
var/equiv = A.air.share_ratio(B.air, coefficient)
var/differential = A.air.return_pressure() - B.air.return_pressure()
if(abs(differential) < vsc.airflow_lightest_pressure) return
if(abs(differential) >= vsc.airflow_lightest_pressure)
var/list/attracted
var/list/repelled
if(differential > 0)
attracted = A.movables()
repelled = B.movables()
else
attracted = B.movables()
repelled = A.movables()
var/list/attracted
var/list/repelled
if(differential > 0)
attracted = A.movables()
repelled = B.movables()
else
attracted = B.movables()
repelled = A.movables()
flow(attracted, abs(differential), 0)
flow(repelled, abs(differential), 1)
flow(attracted, abs(differential), 0)
flow(repelled, abs(differential), 1)
if(equiv)
if(direct)
erase()
air_master.merge(A, B)
return
else
A.air.equalize(B.air)
air_master.mark_edge_sleeping(src)
air_master.mark_zone_update(A)
air_master.mark_zone_update(B)
/connection_edge/zone/recheck()
if(!A.air.compare(B.air))
air_master.mark_edge_active(src)
//Helper proc to get connections for a zone.
/connection_edge/zone/proc/get_connected_zone(zone/from)
@@ -214,20 +220,27 @@ Class Procs:
if(A.invalid)
erase()
return
//world << "[id]: Tick [air_master.current_cycle]: To [B]!"
//A.air.mimic(B, coefficient)
A.air.share_space(air, dbg_out)
air_master.mark_zone_update(A)
var/equiv = A.air.share_space(air)
var/differential = A.air.return_pressure() - air.return_pressure()
if(abs(differential) < vsc.airflow_lightest_pressure) return
if(abs(differential) >= vsc.airflow_lightest_pressure)
var/list/attracted = A.movables()
flow(attracted, abs(differential), differential < 0)
var/list/attracted = A.movables()
flow(attracted, abs(differential), differential < 0)
if(equiv)
A.air.copy_from(air)
air_master.mark_edge_sleeping(src)
air_master.mark_zone_update(A)
/connection_edge/unsimulated/recheck()
if(!A.air.compare(air))
air_master.mark_edge_active(src)
proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
//This implements a simplistic version of the Stefan-Boltzmann law.
var/energy_delta = ((A.temperature - B.temperature) ** 4) * 5.6704e-8 * connecting_tiles * 2.5
var/energy_delta = ((A.temperature - B.temperature) ** 4) * STEFAN_BOLTZMANN_CONSTANT * connecting_tiles * 2.5
var/maximum_energy_delta = max(0, min(A.temperature * A.heat_capacity() * A.group_multiplier, B.temperature * B.heat_capacity() * B.group_multiplier))
if(maximum_energy_delta > abs(energy_delta))
if(energy_delta < 0)

View File

@@ -75,6 +75,7 @@ Class Procs:
/datum/controller/air_system/var/list/zones_to_update = list()
/datum/controller/air_system/var/list/active_fire_zones = list()
/datum/controller/air_system/var/list/active_hotspots = list()
/datum/controller/air_system/var/list/active_edges = list()
/datum/controller/air_system/var/active_zones = 0
@@ -97,7 +98,7 @@ Class Procs:
set background = 1
#endif
world << "\red \b Processing Geometry..."
world << "<span class='danger'>Processing Geometry...</span>"
sleep(-1)
var/start_time = world.timeofday
@@ -108,10 +109,15 @@ Class Procs:
simulated_turf_count++
S.update_air_properties()
world << {"<font color='red'><b>Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</b>
world << {"<span class='danger'>Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</b></span>
<span class='info'>
Total Simulated Turfs: [simulated_turf_count]
Total Zones: [zones.len]
Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]</font>"}
Total Edges: [edges.len]
Total Active Edges: [active_edges.len ? "<span class='danger'>[active_edges.len]</span>" : "None"]
Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]</font>
</span>"}
// spawn Start()
@@ -169,7 +175,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
if(.)
tick_progress = "processing edges"
for(var/connection_edge/edge in edges)
for(var/connection_edge/edge in active_edges)
edge.tick()
//Process fire zones.
@@ -299,6 +305,22 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
zones_to_update.Add(Z)
Z.needs_update = 1
/datum/controller/air_system/proc/mark_edge_sleeping(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E)
#endif
if(E.sleeping) return
active_edges.Remove(E)
E.sleeping = 1
/datum/controller/air_system/proc/mark_edge_active(connection_edge/E)
#ifdef ZASDBG
ASSERT(istype(E)
#endif
if(!E.sleeping) return
active_edges.Add(E)
E.sleeping = 0
/datum/controller/air_system/proc/equivalent_pressure(zone/A, zone/B)
return A.air.compare(B.air)
@@ -309,12 +331,14 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
if(edge.contains_zone(B)) return edge
var/connection_edge/edge = new/connection_edge/zone(A,B)
edges.Add(edge)
edge.recheck()
return edge
else
for(var/connection_edge/unsimulated/edge in A.edges)
if(has_same_air(edge.B,B)) return edge
var/connection_edge/edge = new/connection_edge/unsimulated(A,B)
edges.Add(edge)
edge.recheck()
return edge
/datum/controller/air_system/proc/has_same_air(turf/A, turf/B)
@@ -325,5 +349,6 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
if(A.temperature != B.temperature) return 0
return 1
/datum/controller/air_system/proc/remove_edge(connection/c)
edges.Remove(c)
/datum/controller/air_system/proc/remove_edge(connection_edge/E)
edges.Remove(E)
if(!E.sleeping) active_edges.Remove(E)

View File

@@ -138,6 +138,10 @@ Class Procs:
graphic_add.len = 0
graphic_remove.len = 0
for(var/connection_edge/E in edges)
if(E.sleeping)
E.recheck()
/zone/proc/dbg_data(mob/M)
M << name
for(var/g in air.gas)

View File

@@ -17,7 +17,8 @@
//List of active tile overlays for this gas_mixture. Updated by check_tile_graphic()
var/list/graphic = list()
//Takes a gas string, and the amount of moles to adjust by. Calls update_values() if update isn't 0.
//Takes a gas string and the amount of moles to adjust by. Calls update_values() if update isn't 0.
/datum/gas_mixture/proc/adjust_gas(gasid, moles, update = 1)
if(moles == 0)
return
@@ -30,6 +31,7 @@
if(update)
update_values()
//Same as adjust_gas(), but takes a temperature which is mixed in with the gas.
/datum/gas_mixture/proc/adjust_gas_temp(gasid, moles, temp, update = 1)
if(moles == 0)
@@ -50,7 +52,8 @@
if(update)
update_values()
//Variadic version of adjust_gas(). Takes any number of gas and mole pairs, and applies them.
//Variadic version of adjust_gas(). Takes any number of gas and mole pairs and applies them.
/datum/gas_mixture/proc/adjust_multi()
ASSERT(!(args.len % 2))
@@ -59,7 +62,8 @@
update_values()
//Variadic version of adjust_gas_temp(). Takes any number of gas, mole, and temperature tuples, and applies them.
//Variadic version of adjust_gas_temp(). Takes any number of gas, mole and temperature associations and applies them.
/datum/gas_mixture/proc/adjust_multi_temp()
ASSERT(!(args.len % 3))
@@ -68,8 +72,10 @@
update_values()
//Merges all the gas from another mixture into this one. Respects group_multipliers and adjusts temperature correctly.
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
//Does not modify giver in any way.
/datum/gas_mixture/proc/merge(const/datum/gas_mixture/giver)
if(!giver)
return
@@ -89,6 +95,25 @@
update_values()
/datum/gas_mixture/proc/equalize(datum/gas_mixture/sharer)
for(var/g in sharer.gas)
var/comb = gas[g] + sharer.gas[g]
comb /= volume + sharer.volume
gas[g] = comb * volume
sharer.gas[g] = comb * sharer.volume
var/our_heatcap = heat_capacity()
var/share_heatcap = sharer.heat_capacity()
temperature = 0
if(our_heatcap + share_heatcap)
temperature = ((temperature * our_heatcap) + (sharer.temperature * share_heatcap)) / (our_heatcap + share_heatcap)
sharer.temperature = temperature
return 1
//Returns the heat capacity of the gas mix based on the specific heat of the gases.
/datum/gas_mixture/proc/heat_capacity()
. = 0
@@ -96,6 +121,7 @@
. += gas_data.specific_heat[g] * gas[g]
. *= group_multiplier
//Adds or removes thermal energy. Returns the actual thermal energy change, as in the case of removing energy we can't go below TCMB.
/datum/gas_mixture/proc/add_thermal_energy(var/thermal_energy)
if (total_moles == 0)
@@ -114,9 +140,11 @@
/datum/gas_mixture/proc/get_thermal_energy_change(var/new_temperature)
return heat_capacity()*(max(new_temperature, 0) - temperature)
//Technically vacuum doesn't have a specific entropy. Just use a really big number (infinity would be ideal) here so that it's easy to add gas to vacuum and hard to take gas out.
#define SPECIFIC_ENTROPY_VACUUM 150000
//Returns the ideal gas specific entropy of the whole mix. This is the entropy per mole of /mixed/ gas.
/datum/gas_mixture/proc/specific_entropy()
if (!gas.len || total_moles == 0)
@@ -127,6 +155,7 @@
. += gas[g] * specific_entropy_gas(g)
. /= total_moles
/*
It's arguable whether this should even be called entropy anymore. It's more "based on" entropy than actually entropy now.
@@ -151,6 +180,7 @@
//var/partial_pressure = gas[gasid] * R_IDEAL_GAS_EQUATION * temperature / volume
//return R_IDEAL_GAS_EQUATION * ( log (1 + IDEAL_GAS_ENTROPY_CONSTANT/partial_pressure) + 20 )
//Updates the total_moles count and trims any empty gases.
/datum/gas_mixture/proc/update_values()
total_moles = 0
@@ -160,12 +190,14 @@
else
total_moles += gas[g]
//Returns the pressure of the gas mix. Only accurate if there have been no gas modifications since update_values() has been called.
/datum/gas_mixture/proc/return_pressure()
if(volume)
return total_moles * R_IDEAL_GAS_EQUATION * temperature / volume
return 0
//Removes moles from the gas mixture and returns a gas_mixture containing the removed air.
/datum/gas_mixture/proc/remove(amount)
amount = min(amount, total_moles * group_multiplier) //Can not take more air than the gas mixture has!
@@ -184,6 +216,7 @@
return removed
//Removes a ratio of gas from the mixture and returns a gas_mixture containing the removed air.
/datum/gas_mixture/proc/remove_ratio(ratio, out_group_multiplier = 1)
if(ratio <= 0)
@@ -205,6 +238,7 @@
return removed
//Removes moles from the gas mixture, limited by a given flag. Returns a gax_mixture containing the removed air.
/datum/gas_mixture/proc/remove_by_flag(flag, amount)
if(!flag || amount <= 0)
@@ -228,8 +262,9 @@
return removed
//Copies gas and temperature from another gas_mixture.
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
/datum/gas_mixture/proc/copy_from(const/datum/gas_mixture/sample)
gas = sample.gas.Copy()
temperature = sample.temperature
@@ -237,8 +272,9 @@
return 1
//Checks if we are within acceptable range of another gas_mixture to suspend processing or merge.
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
/datum/gas_mixture/proc/compare(const/datum/gas_mixture/sample)
if(!sample) return 0
var/list/marked = list()
@@ -264,9 +300,11 @@
return 1
/datum/gas_mixture/proc/react(atom/dump_location)
zburn(null)
//Rechecks the gas_mixture and adjusts the graphic list if needed.
//Two lists can be passed by reference if you need know specifically which graphics were added and removed.
/datum/gas_mixture/proc/check_tile_graphic(list/graphic_add = null, list/graphic_remove = null)
@@ -293,6 +331,7 @@
graphic -= graphic_remove
. = 1
//Simpler version of merge(), adjusts gas amounts directly and doesn't account for temperature or group_multiplier.
/datum/gas_mixture/proc/add(datum/gas_mixture/right_side)
for(var/g in right_side.gas)
@@ -301,6 +340,7 @@
update_values()
return 1
//Simpler version of remove(), adjusts gas amounts directly and doesn't account for group_multiplier.
/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
for(var/g in right_side.gas)
@@ -309,6 +349,7 @@
update_values()
return 1
//Multiply all gas amounts by a factor.
/datum/gas_mixture/proc/multiply(factor)
for(var/g in gas)
@@ -317,6 +358,7 @@
update_values()
return 1
//Divide all gas amounts by a factor.
/datum/gas_mixture/proc/divide(factor)
for(var/g in gas)
@@ -325,6 +367,7 @@
update_values()
return 1
//Shares gas with another gas_mixture based on the amount of connecting tiles and a fixed lookup table.
/datum/gas_mixture/proc/share_ratio(datum/gas_mixture/other, connecting_tiles, share_size = null, one_way = 0)
var/static/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66)
@@ -369,19 +412,13 @@
update_values()
other.update_values()
if(compare(other)) return 1
else return 0
return compare(other)
//A wrapper around share_ratio for spacing gas at the same rate as if it were going into a large airless room.
/datum/gas_mixture/proc/share_space(datum/gas_mixture/unsim_air)
if(!unsim_air)
return 0
return share_ratio(unsim_air, unsim_air.group_multiplier, max(1, max(group_multiplier + 3, 1) + unsim_air.group_multiplier), one_way = 1)
var/old_pressure = return_pressure()
share_ratio(unsim_air, unsim_air.group_multiplier, max(1, max(group_multiplier + 3, 1) + unsim_air.group_multiplier), one_way = 1)
return abs(old_pressure - return_pressure())
//Equalizes a list of gas mixtures. Used for pipe networks.
/proc/equalize_gases(datum/gas_mixture/list/gases)

View File

@@ -9,7 +9,7 @@
#define IDEAL_GAS_ENTROPY_CONSTANT 1164 //(mol^3 * s^3) / (kg^3 * L). Equal to (4*pi/(avrogadro's number * planck's constant)^2)^(3/2) / (avrogadro's number * 1000 Liters per m^3).
//radiation constants
#define STEFAN_BOLTZMANN_CONSTANT 0.0000000567 //W/(m^2*K^4)
#define STEFAN_BOLTZMANN_CONSTANT 5.6704e-8 //W/(m^2*K^4)
#define COSMIC_RADIATION_TEMPERATURE 3.15 //K
#define AVERAGE_SOLAR_RADIATION 200 //W/m^2. Kind of arbitrary. Really this should depend on the sun position much like solars.
#define RADIATOR_OPTIMUM_PRESSURE 110 //kPa at 20 C