Fixes gas mixture bugs, other bugs, and cleanup

In particular, gas_mixture/remove() was not accounting for
group_multiplier when determining the maximum amount of gas to remove
Also cleans up the interface for gas_mixture/heat_capacity().
This commit is contained in:
mwerezak
2014-08-05 13:30:19 -04:00
parent f50a24163b
commit 018079beb5
7 changed files with 188 additions and 255 deletions

View File

@@ -364,10 +364,10 @@
/proc/calculate_specific_power(datum/gas_mixture/source, datum/gas_mixture/sink) /proc/calculate_specific_power(datum/gas_mixture/source, datum/gas_mixture/sink)
//Calculate the amount of energy required //Calculate the amount of energy required
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
var/specific_entropy = sink.specific_entropy() - source.specific_entropy() //environment is gaining moles, air_contents is loosing var/specific_entropy = sink.specific_entropy() - source.specific_entropy() //sink is gaining moles, source is loosing
var/specific_power = 0 // W/mol var/specific_power = 0 // W/mol
//If specific_entropy is < 0 then transfer_moles is limited by how powerful the pump is //If specific_entropy is < 0 then power is required to move gas
if (specific_entropy < 0) if (specific_entropy < 0)
specific_power = -specific_entropy*air_temperature //how much power we need per mole specific_power = -specific_entropy*air_temperature //how much power we need per mole
@@ -377,10 +377,10 @@
/proc/calculate_specific_power_gas(var/gasid, datum/gas_mixture/source, datum/gas_mixture/sink) /proc/calculate_specific_power_gas(var/gasid, datum/gas_mixture/source, datum/gas_mixture/sink)
//Calculate the amount of energy required //Calculate the amount of energy required
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
var/specific_entropy = sink.specific_entropy_gas(gasid) - source.specific_entropy_gas(gasid) //environment is gaining moles, air_contents is loosing var/specific_entropy = sink.specific_entropy_gas(gasid) - source.specific_entropy_gas(gasid) //sink is gaining moles, source is loosing
var/specific_power = 0 // W/mol var/specific_power = 0 // W/mol
//If specific_entropy is < 0 then transfer_moles is limited by how powerful the pump is //If specific_entropy is < 0 then power is required to move gas
if (specific_entropy < 0) if (specific_entropy < 0)
specific_power = -specific_entropy*air_temperature //how much power we need per mole specific_power = -specific_entropy*air_temperature //how much power we need per mole
@@ -391,7 +391,7 @@
//This proc implements an approximation scheme that will cause area power updates to be triggered less often. //This proc implements an approximation scheme that will cause area power updates to be triggered less often.
//By having atmos machinery use this proc it is easy to change the power usage approximation for all atmos machines //By having atmos machinery use this proc it is easy to change the power usage approximation for all atmos machines
/obj/machinery/proc/handle_power_draw(var/usage_amount) /obj/machinery/proc/handle_power_draw(var/usage_amount)
//***This scheme errs on the side of using more power. Using this will mean that sometimes atmos machines use more power than they need, but won't get power for free. //This code errs on the side of using more power. Using this will mean that sometimes atmos machines use more power than they need, but won't get power for free.
if (usage_amount > idle_power_usage) if (usage_amount > idle_power_usage)
update_use_power(2) update_use_power(2)
else else
@@ -403,50 +403,4 @@
switch (use_power) switch (use_power)
if (0) return 0 if (0) return 0
if (1) return idle_power_usage if (1) return idle_power_usage
if (2 to INFINITY) return active_power_usage if (2 to INFINITY) return max(idle_power_usage, usage_amount)
/* Alternate power usage schemes
//***This scheme has the most accurate power usage, but triggers area power updates too often.
if (usage_amount > active_power_usage - 5)
update_use_power(2)
else
update_use_power(1)
if (usage_amount > idle_power_usage)
use_power(round(usage_amount))
//***This scheme errs on the side of using less power. Using this will mean that sometimes atmos machines get free power.
if (usage_amount > active_power_usage - 5)
update_use_power(2)
else
use_power = 1 //Don't need to update here.
*/
/*
//DEBUG
/var/global/enable_scrubbing = 0
/var/global/enable_vent_pump = 0
/var/global/enable_power_net = 0
/mob/verb/toggle_scrubbing()
set name = "Toggle Scrubbing"
set category = "Debug"
enable_scrubbing = !enable_scrubbing
world << "enable_scrubbing set to [enable_scrubbing]"
/mob/verb/toggle_vent_pump()
set name = "Toggle Vent Pumps"
set category = "Debug"
enable_vent_pump = !enable_vent_pump
world << "enable_vent_pump set to [enable_vent_pump]"
/mob/verb/toggle_pump_powernet()
set name = "Toggle Pump Power Update"
set category = "Debug"
enable_power_net = !enable_power_net
world << "enable_power_net set to [enable_power_net]"
*/

View File

@@ -54,7 +54,7 @@
..() ..()
injecting = 0 injecting = 0
if(!on || stat & NOPOWER) if(!on) //only uses power when injecting
return 0 return 0
var/datum/gas_mixture/environment = loc.return_air() var/datum/gas_mixture/environment = loc.return_air()

View File

@@ -256,6 +256,8 @@
..() ..()
if (get_dist(usr, src) <= 1) if (get_dist(usr, src) <= 1)
usr << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W" usr << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
else
usr << "You are too far away to read the gauge."
/obj/machinery/atmospherics/unary/vent_scrubber/Del() /obj/machinery/atmospherics/unary/vent_scrubber/Del()
if(initial_loc) if(initial_loc)

View File

@@ -36,7 +36,7 @@
return return
if(moles > 0 && abs(temperature - temp) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) if(moles > 0 && abs(temperature - temp) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()*group_multiplier var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = gas_data.specific_heat[gasid] * moles var/giver_heat_capacity = gas_data.specific_heat[gasid] * moles
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0) if(combined_heat_capacity != 0)
@@ -68,14 +68,14 @@
update_values() update_values()
//Merges all the gas from another mixture into this one. Respects group_multiplies and adjusts temperature correctly. //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) /datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
if(!giver) if(!giver)
return return
if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()*group_multiplier var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0) if(combined_heat_capacity != 0)
temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
@@ -94,22 +94,25 @@
. = 0 . = 0
for(var/g in gas) for(var/g in gas)
. += gas_data.specific_heat[g] * gas[g] . += 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. //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) /datum/gas_mixture/proc/add_thermal_energy(var/thermal_energy)
if (temperature < TCMB || total_moles == 0) if (total_moles == 0)
return 0 return 0
var/heat_capacity = heat_capacity()*group_multiplier var/heat_capacity = heat_capacity()
if (thermal_energy < 0) if (thermal_energy < 0)
if (temperature < TCMB)
return 0
var/thermal_energy_limit = -(temperature - TCMB)*heat_capacity //ensure temperature does not go below TCMB var/thermal_energy_limit = -(temperature - TCMB)*heat_capacity //ensure temperature does not go below TCMB
thermal_energy = max( thermal_energy, thermal_energy_limit ) thermal_energy = max( thermal_energy, thermal_energy_limit ) //thermal_energy and thermal_energy_limit are negative here.
temperature += thermal_energy/heat_capacity temperature += thermal_energy/heat_capacity
return thermal_energy return thermal_energy
//Returns the thermal energy change required to get to a new temperature //Returns the thermal energy change required to get to a new temperature
/datum/gas_mixture/proc/get_thermal_energy_change(var/new_temperature) /datum/gas_mixture/proc/get_thermal_energy_change(var/new_temperature)
return heat_capacity()*group_multiplier*(new_temperature - temperature) return heat_capacity()*(new_temperature - 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. //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 #define SPECIFIC_ENTROPY_VACUUM 150000
@@ -152,15 +155,14 @@
//Removes moles from the gas mixture and returns a gas_mixture containing the removed air. //Removes moles from the gas mixture and returns a gas_mixture containing the removed air.
/datum/gas_mixture/proc/remove(amount) /datum/gas_mixture/proc/remove(amount)
var/sum = total_moles amount = min(amount, total_moles * group_multiplier) //Can not take more air than the gas mixture has!
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0) if(amount <= 0)
return null return null
var/datum/gas_mixture/removed = new var/datum/gas_mixture/removed = new
for(var/g in gas) for(var/g in gas)
removed.gas[g] = QUANTIZE((gas[g] / sum) * amount) removed.gas[g] = QUANTIZE((gas[g] / total_moles) * amount)
gas[g] -= removed.gas[g] / group_multiplier gas[g] -= removed.gas[g] / group_multiplier
removed.temperature = temperature removed.temperature = temperature
@@ -181,8 +183,8 @@
removed.group_multiplier = out_group_multiplier removed.group_multiplier = out_group_multiplier
for(var/g in gas) for(var/g in gas)
removed.gas[g] = QUANTIZE(gas[g] * ratio) removed.gas[g] = (gas[g] * ratio * group_multiplier / out_group_multiplier)
gas[g] = ((gas[g] * group_multiplier) - (removed.gas[g] * out_group_multiplier)) / group_multiplier gas[g] = gas[g] * (1 - ratio)
removed.temperature = temperature removed.temperature = temperature
update_values() update_values()
@@ -327,13 +329,13 @@
for(var/g in gas) for(var/g in gas)
full_gas[g] = gas[g] * size full_gas[g] = gas[g] * size
var/full_heat_capacity = heat_capacity() * size var/full_heat_capacity = heat_capacity()
var/list/s_full_gas = list() var/list/s_full_gas = list()
for(var/g in other.gas) for(var/g in other.gas)
s_full_gas[g] = other.gas[g] * share_size s_full_gas[g] = other.gas[g] * share_size
var/s_full_heat_capacity = other.heat_capacity() * share_size var/s_full_heat_capacity = other.heat_capacity()
var/list/avg_gas = list() var/list/avg_gas = list()

View File

@@ -137,8 +137,8 @@ Buildable meters
"bent insulated pipe", \ "bent insulated pipe", \
"gas filter", \ "gas filter", \
"gas mixer", \ "gas mixer", \
"passive gate", \ "pressure regulator", \
"volume pump", \ "high power pump", \
"heat exchanger", \ "heat exchanger", \
"t-valve", \ "t-valve", \
"4-way manifold", \ "4-way manifold", \

View File

@@ -29,8 +29,8 @@
<A href='?src=\ref[src];make=4;dir=1'>Connector</A><BR> <A href='?src=\ref[src];make=4;dir=1'>Connector</A><BR>
<A href='?src=\ref[src];make=7;dir=1'>Unary Vent</A><BR> <A href='?src=\ref[src];make=7;dir=1'>Unary Vent</A><BR>
<A href='?src=\ref[src];make=9;dir=1'>Gas Pump</A><BR> <A href='?src=\ref[src];make=9;dir=1'>Gas Pump</A><BR>
<A href='?src=\ref[src];make=15;dir=1'>Passive Gate</A><BR> <A href='?src=\ref[src];make=15;dir=1'>Pressure Regulator</A><BR>
<A href='?src=\ref[src];make=16;dir=1'>Volume Pump</A><BR> <A href='?src=\ref[src];make=16;dir=1'>High Power Gas Pump</A><BR>
<A href='?src=\ref[src];make=10;dir=1'>Scrubber</A><BR> <A href='?src=\ref[src];make=10;dir=1'>Scrubber</A><BR>
<A href='?src=\ref[src];makemeter=1'>Meter</A><BR> <A href='?src=\ref[src];makemeter=1'>Meter</A><BR>
<A href='?src=\ref[src];make=13;dir=1'>Gas Filter</A><BR> <A href='?src=\ref[src];make=13;dir=1'>Gas Filter</A><BR>

View File

@@ -8,204 +8,179 @@
var/obj/item/weapon/cell/cell var/obj/item/weapon/cell/cell
var/on = 0 var/on = 0
var/open = 0 var/open = 0
var/set_temperature = 50 // in celcius, add T0C for kelvin var/set_temperature = T0C + 50 //K
var/heating_power = 40000 var/heating_power = 40000
flags = FPRINT flags = FPRINT
New() /obj/machinery/space_heater/New()
..() ..()
cell = new(src) cell = new(src)
cell.charge = 1000
cell.maxcharge = 1000
update_icon()
return
update_icon() update_icon()
overlays.Cut()
icon_state = "sheater[on]" /obj/machinery/space_heater/update_icon()
if(open) overlays.Cut()
overlays += "sheater-open" icon_state = "sheater[on]"
if(open)
overlays += "sheater-open"
/obj/machinery/space_heater/examine()
set src in oview(12)
if (!( usr ))
return return
usr << "This is \icon[src] \an [src.name]."
usr << src.desc
examine() usr << "The heater is [on ? "on" : "off"] and the hatch is [open ? "open" : "closed"]."
set src in oview(12) if(open)
if (!( usr )) usr << "The power cell is [cell ? "installed" : "missing"]."
return else
usr << "This is \icon[src] \an [src.name]." usr << "The charge meter reads [cell ? round(cell.percent(),1) : 0]%"
usr << src.desc return
usr << "The heater is [on ? "on" : "off"] and the hatch is [open ? "open" : "closed"]." /obj/machinery/space_heater/emp_act(severity)
if(open) if(stat & (BROKEN|NOPOWER))
usr << "The power cell is [cell ? "installed" : "missing"]."
else
usr << "The charge meter reads [cell ? round(cell.percent(),1) : 0]%"
return
emp_act(severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
return
if(cell)
cell.emp_act(severity)
..(severity) ..(severity)
return
if(cell)
cell.emp_act(severity)
..(severity)
attackby(obj/item/I, mob/user) /obj/machinery/space_heater/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/cell)) if(istype(I, /obj/item/weapon/cell))
if(open) if(open)
if(cell) if(cell)
user << "There is already a power cell inside." user << "There is already a power cell inside."
return return
else else
// insert cell // insert cell
var/obj/item/weapon/cell/C = usr.get_active_hand()
if(istype(C))
user.drop_item()
cell = C
C.loc = src
C.add_fingerprint(usr)
user.visible_message("\blue [user] inserts a power cell into [src].", "\blue You insert the power cell into [src].")
else
user << "The hatch must be open to insert a power cell."
return
else if(istype(I, /obj/item/weapon/screwdriver))
open = !open
user.visible_message("\blue [user] [open ? "opens" : "closes"] the hatch on the [src].", "\blue You [open ? "open" : "close"] the hatch on the [src].")
update_icon()
if(!open && user.machine == src)
user << browse(null, "window=spaceheater")
user.unset_machine()
else
..()
return
/obj/machinery/space_heater/attack_hand(mob/user as mob)
src.add_fingerprint(user)
interact(user)
/obj/machinery/space_heater/interact(mob/user as mob)
if(open)
var/dat
dat = "Power cell: "
if(cell)
dat += "<A href='byond://?src=\ref[src];op=cellremove'>Installed</A><BR>"
else
dat += "<A href='byond://?src=\ref[src];op=cellinstall'>Removed</A><BR>"
dat += "Power Level: [cell ? round(cell.percent(),1) : 0]%<BR><BR>"
dat += "Set Temperature: "
dat += "<A href='?src=\ref[src];op=temp;val=-5'>-</A>"
dat += " [set_temperature]&deg;C "
dat += "<A href='?src=\ref[src];op=temp;val=5'>+</A><BR>"
user.set_machine(src)
user << browse("<HEAD><TITLE>Space Heater Control Panel</TITLE></HEAD><TT>[dat]</TT>", "window=spaceheater")
onclose(user, "spaceheater")
else
on = !on
user.visible_message("\blue [user] switches [on ? "on" : "off"] the [src].","\blue You switch [on ? "on" : "off"] the [src].")
update_icon()
return
/obj/machinery/space_heater/Topic(href, href_list)
if (usr.stat)
return
if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
switch(href_list["op"])
if("temp")
var/value = text2num(href_list["val"])
// limit to 0-90 degC
set_temperature = dd_range(T0C, T0C + 90, set_temperature + value)
if("cellremove")
if(open && cell && !usr.get_active_hand())
usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].")
cell.updateicon()
usr.put_in_hands(cell)
cell.add_fingerprint(usr)
cell = null
if("cellinstall")
if(open && !cell)
var/obj/item/weapon/cell/C = usr.get_active_hand() var/obj/item/weapon/cell/C = usr.get_active_hand()
if(istype(C)) if(istype(C))
user.drop_item() usr.drop_item()
cell = C cell = C
C.loc = src C.loc = src
C.add_fingerprint(usr) C.add_fingerprint(usr)
user.visible_message("\blue [user] inserts a power cell into [src].", "\blue You insert the power cell into [src].") usr.visible_message("\blue [usr] inserts \the [C] into \the [src].", "\blue You insert \the [C] into \the [src].")
else
user << "The hatch must be open to insert a power cell." updateDialog()
return else
else if(istype(I, /obj/item/weapon/screwdriver)) usr << browse(null, "window=spaceheater")
open = !open usr.unset_machine()
user.visible_message("\blue [user] [open ? "opens" : "closes"] the hatch on the [src].", "\blue You [open ? "open" : "close"] the hatch on the [src].") return
/obj/machinery/space_heater/process()
if(on)
if(cell && cell.charge)
var/datum/gas_mixture/env = loc.return_air()
if(env && abs(env.temperature - set_temperature) > 0.1)
var/transfer_moles = 0.25 * env.total_moles
var/datum/gas_mixture/removed = env.remove(transfer_moles)
if(removed)
var/heat_transfer = removed.get_thermal_energy_change(set_temperature)
if(heat_transfer > 0) //heating air
heat_transfer = min( heat_transfer , heating_power ) //limit by the power rating of the heater
removed.add_thermal_energy(heat_transfer)
cell.use(heat_transfer*CELLRATE)
else //cooling air
heat_transfer = abs(heat_transfer)
//Assume the heat is being pumped into the hull which is fixed at 20 C
var/cop = removed.temperature/T20C //coefficient of performance from thermodynamics -> power used = heat_transfer/cop
heat_transfer = min(heat_transfer, cop * heating_power) //limit heat transfer by available power
heat_transfer = removed.add_thermal_energy(-heat_transfer) //get the actual heat transfer
var/power_used = abs(heat_transfer)/cop
cell.use(power_used*CELLRATE)
env.merge(removed)
else
on = 0
update_icon() update_icon()
if(!open && user.machine == src)
user << browse(null, "window=spaceheater")
user.unset_machine()
else
..()
return
attack_hand(mob/user as mob)
src.add_fingerprint(user)
interact(user)
interact(mob/user as mob)
if(open)
var/dat
dat = "Power cell: "
if(cell)
dat += "<A href='byond://?src=\ref[src];op=cellremove'>Installed</A><BR>"
else
dat += "<A href='byond://?src=\ref[src];op=cellinstall'>Removed</A><BR>"
dat += "Power Level: [cell ? round(cell.percent(),1) : 0]%<BR><BR>"
dat += "Set Temperature: "
dat += "<A href='?src=\ref[src];op=temp;val=-5'>-</A>"
dat += " [set_temperature]&deg;C "
dat += "<A href='?src=\ref[src];op=temp;val=5'>+</A><BR>"
user.set_machine(src)
user << browse("<HEAD><TITLE>Space Heater Control Panel</TITLE></HEAD><TT>[dat]</TT>", "window=spaceheater")
onclose(user, "spaceheater")
else
on = !on
user.visible_message("\blue [user] switches [on ? "on" : "off"] the [src].","\blue You switch [on ? "on" : "off"] the [src].")
update_icon()
return
Topic(href, href_list)
if (usr.stat)
return
if ((in_range(src, usr) && istype(src.loc, /turf)) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
switch(href_list["op"])
if("temp")
var/value = text2num(href_list["val"])
// limit to 20-90 degC
set_temperature = dd_range(0, 90, set_temperature + value)
if("cellremove")
if(open && cell && !usr.get_active_hand())
cell.updateicon()
usr.put_in_hands(cell)
cell.add_fingerprint(usr)
cell = null
usr.visible_message("\blue [usr] removes the power cell from \the [src].", "\blue You remove the power cell from \the [src].")
if("cellinstall")
if(open && !cell)
var/obj/item/weapon/cell/C = usr.get_active_hand()
if(istype(C))
usr.drop_item()
cell = C
C.loc = src
C.add_fingerprint(usr)
usr.visible_message("\blue [usr] inserts a power cell into \the [src].", "\blue You insert the power cell into \the [src].")
updateDialog()
else
usr << browse(null, "window=spaceheater")
usr.unset_machine()
return
process()
if(on)
if(cell && cell.charge > 0)
var/turf/simulated/L = loc
if(istype(L))
var/datum/gas_mixture/env = L.return_air()
if(env.temperature != set_temperature + T0C)
var/transfer_moles = 0.25 * env.total_moles
var/datum/gas_mixture/removed = env.remove(transfer_moles)
//world << "got [transfer_moles] moles at [removed.temperature]"
if(removed)
if(removed.temperature < set_temperature + T0C) //heating air
// Added min(set_temperature + T0C, 1000) check to try and avoid wacky superheating issues in low gas scenarios
var/energy_used = min( removed.get_thermal_energy_change(min(set_temperature + T0C, 1000)) , heating_power )
removed.add_thermal_energy(energy_used)
cell.use(energy_used*CELLRATE)
else //cooling air
var/heat_transfer = min(abs(removed.get_thermal_energy_change(set_temperature + T0C)), heating_power)
//Assume the heat is being pumped into the hull which is fixed at 20 C
//none of this is really proper thermodynamics but whatever
var/cop = removed.temperature/T20C //coefficient of performance from thermodynamics -> power used = heat_transfer/cop
heat_transfer = min(heat_transfer, cop * heating_power) //limit heat transfer by available power
heat_transfer = -removed.add_thermal_energy(-heat_transfer) //get the actual heat transfer
cell.use(heat_transfer/cop*CELLRATE)
env.merge(removed)
//world << "turf now at [env.temperature]"
else
on = 0
update_icon()
return