This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Harcole's profile picture

Stuck with items that take damage when checking contents

Started by Harcole, 27 October 2012 - 01:12 AM
Harcole #1
Posted 27 October 2012 - 03:12 AM
I've got a lua script I'm working on which is meant to monitor and display information regarding a reactor, which I can do! I'm now trying to expand my knowledge and adapt the script to include maintance of said reactor… This is where I hit my problem, as soon as the uranium starts to take "damage" it stops registering as being present in the reactor core and my system requests more Uranium Cell's to burn, which in turn clogs the whole system up…

I've spent ages trying to establish why I've got a problem, I'm sure its to do with the final part of the :sub section but I'm tired and being blind and can't spot the solution, sorry. Any help would be great.

Code is below:


-- Output to monitor
local monside = "left";
if peripheral.isPresent(monside) then
  if peripheral.getType(monside) == "monitor" then
	monitor = peripheral.wrap(monside);
	term.redirect(monitor);
  end
end
--id tags--
name_ucell = 'item.itemCellUran';
name_uneardepleted = 'item.itemCellUranEmpty';
name_ureenriched = 'item.itemCellUranEnriched';
name_ice = 'tile.ice';

-- Content control
local max_ice = 192;
local max_ucell = 15;
local total_ice = 0;
local total_ucell = 0;

-- Master power button
local power = false;

function SortContents(side, sensor, target)
   for i,v in pairs(sensors.getSensorReadingAsDict(side, sensor, target, 'ReactorContent')) do
  -- Ice
  if v:sub(-2-#name_ice, -3) == name_ice then
   i_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_ice = total_ice + i_qty;
  
  -- Depleated Uranium
  elseif v:sub(-2-#name_uneardepleted, -3) == name_uneardepleted then
   -- code to work out how much depleated there is
  
  -- Enriched Uranium
  elseif v:sub(-2-#name_ureenriched, -3) == name_ureenriched then
   -- code to work out how much enriched uranium there is
  
  -- Uranium
  elseif v:sub(-2-#name_ucell, -3) == name_ucell then
   u_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_ucell = total_ucell + u_qty;
  end
end

-- Display information
print("Uranium in Reactor : "..total_ucell.."/ "..max_ucell);
print("Ice in Reactor	 : "..total_ice.."/"..max_ice);

end
-- Loop through the program updating the display
while true do
-- Get Sensor details
local sensor = "Reactor 1";
local side = sensors.getController();
local targets = sensors.getAvailableTargetsforProbe(side, sensor, "Reactor");

-- Use the two lines below to get all available readings on this Probe (debugging)
-- local s = sensors.getAvailableReadings(side, sensor);
-- print(textutils.serialize(s));

-- Get Probe details for Reactor status
local r = sensorsData.getProbe("ic2", "reactor");
local reactor = sensors.getSensorReadingAsDict(side, sensor, targets[1], "Reactor");

-- Get Probe details for Reactor Contents
local contents= sensors.getSensorReadingAsDict(side, sensor, targets[1], "ReactorContent");
-- Clear the screen
term.clear();
term.setCursorPos(1,4);

-- Get Reactor state and adjust as required
if colors.test(rs.getBundledInput("back"), colors.orange) then
  print("Reactor Power: OFF");
  print("! Thermal Cut Off !");
  power = false;

elseif colors.test(rs.getBundledInput("back"), colors.white) then
  print("Reactor Power: OFF");
  print("! Capacitor Full !");
  power = false;
  rs.setBundledOutput("back", colors.yellow);

elseif total_ice < max_ice then
  -- load the reactor with ice (send a pulse)
  print("Reactor Power: ON");
  print("Loading Ice");

else
  power = true;
  print("Reactor Power: ON");

end

-- Get Reactor information
m_cmb = reactor[r.size.val];
m_cur_heat = reactor[r.heat.val];
m_max_heat = reactor[r.size.val]*1000+10000;
m_out = reactor[r.energy.val];

-- Get Ractor Content Information (Make it readable!)
SortContents(side, sensor, targets[1]);

-- Check to see if we need to load Uranium
if total_ucell < max_ucell then
  rs.setBundledOutput("back", colors.lightBlue);
end

-- Check to see if we need ice
if total_ice < max_ice then
   print(total_ice.."<"..max_ice);
   rs.setBundledOutput("back", colors.magenta);
end
-- Set local world and time format
local time = os.time();
time = textutils.formatTime(time, false);
term.setCursorPos(1,2);

-- Display world time
print ("World Time: "..time);
-- Move Cursor then display Reactor information
term.setCursorPos(1, 8);
-- Display information
print ("Reactor Size	   : "..m_cmb);
print ("Cur. Heat		  : "..m_cur_heat);
print ("Max. Heat		  : "..m_max_heat);
print ("Output (Eu/t)	  : "..m_out);
-- Reset totals before next loop
total_ice = 0;
total_ucell = 0;

-- set delay
sleep(0.5);

-- Kill all cable signals
rs.setBundledOutput("back", 0);

-- Check to see if the power kill is on, if it is ensure it gets put back in place
if power == true then
  rs.setBundledOutput("back", colors.yellow);
end;

sleep (0.5);
end
ChunLing #2
Posted 27 October 2012 - 03:47 AM
I'm not a CC sensors expert but it looks like you're not counting anything but the uranium cells. You don't do anything in the cases of enriched or depleted cells.
Harcole #3
Posted 27 October 2012 - 11:35 AM
I am aware that I don't do anything with completely finished Uranium, but when I print(v) in that loop, all the items are still listed as item.itemCellUran@XX where is the damage taken. As soon as this reads anything it stops counting them, I've not got to the point of trying to empty the reactor yet :D/>/>

At the moment it does count the ice and uranium until that first damage appears on the uranium then it reads 0 for those but the ice still works.
ChunLing #4
Posted 27 October 2012 - 03:11 PM
Wait, what does an undamaged uranium cell look like in that table? If the damage value is a different length, then that would make your v:sub stop working.

I think that v:find(name_ucell) might suit your needs better in any case. If you use v:find for the other two elseifs, then they should pull off any enriched or empty cells, so just find should be good enough.
Harcole #5
Posted 27 October 2012 - 04:45 PM
Thank you sir, that indeed was what I was needing :D/>/>

Now to finish the core script, and then to make it more Minecraft friendly as it appears its causing a bit of lag!

New script for those intrested:


-- Output to monitor
local monside = "left";
if peripheral.isPresent(monside) then
  if peripheral.getType(monside) == "monitor" then
	monitor = peripheral.wrap(monside);
	term.redirect(monitor);
  end
end
--id tags--
name_ucell = 'item.itemCellUran';
name_uneardepleted = 'item.itemCellUranEmpty';
name_ureenriched = 'item.itemCellUranEnriched';
name_ice = 'tile.ice';
local max_ice = 192;
local max_ucell = 15;
local total_ice = 0;
local total_ucell = 0;
local total_dcell = 0;
local total_ecell = 0;
local power = false;
function SortContents(side, sensor, target)
   for i,v in pairs(sensors.getSensorReadingAsDict(side, sensor, target, 'ReactorContent')) do
  -- print(v); -- Debug
  -- Ice
  if v:match(name_ice) then
   i_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_ice = total_ice + i_qty;
  
  -- Depleated Uranium
  elseif v:find(name_uneardepleted) then
   d_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_dcell = total_dcell + d_qty;
  
  -- Enriched Uranium
  elseif v:find(name_ureenriched) then
   e_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_ecell = total_ecell + e_qty;
  
  -- Uranium
  elseif v:find(name_ucell) then
   u_qty = tonumber(string.match(v, '^(%d*)%*'));
   total_ucell = total_ucell + u_qty;
  end
end

-- Display information
print("Uranium in Reactor : "..total_ucell.."/ "..max_ucell);
print("Depleated		  : "..total_dcell);
print("Enriched		   : "..total_ecell);
print("Ice in Reactor	 : "..total_ice.."/"..max_ice);

end
-- Loop through the program updating the display
while true do
-- Get Sensor details
local sensor = "Reactor 1";
local side = sensors.getController();
local targets = sensors.getAvailableTargetsforProbe(side, sensor, "Reactor");

-- Use the two lines below to get all available readings on this Probe (debugging)
-- local s = sensors.getAvailableReadings(side, sensor);
-- print(textutils.serialize(s));

-- Get Probe details for Reactor status
local r = sensorsData.getProbe("ic2", "reactor");
local reactor = sensors.getSensorReadingAsDict(side, sensor, targets[1], "Reactor");

-- Get Probe details for Reactor Contents
local contents= sensors.getSensorReadingAsDict(side, sensor, targets[1], "ReactorContent");
-- Clear the screen
term.clear();
term.setCursorPos(1,4);

-- Get Reactor state and adjust as required
if colors.test(rs.getBundledInput("back"), colors.orange) then
  print("Reactor Power: OFF");
  print("! Thermal Cut Off !");
  power = false;
  rs.setBundledOutput("back", colors.yellow);

elseif colors.test(rs.getBundledInput("back"), colors.white) then
  print("Reactor Power: OFF");
  print("! Capacitor Full !");
  power = false;
  rs.setBundledOutput("back", colors.yellow);

elseif total_ice < max_ice then
  -- load the reactor with ice (send a pulse)
  power = true;
  print("Reactor Power: ON");
  print("Loading Ice");

else
  power = true;
  print("Reactor Power: ON");

end

-- Get Reactor information
m_cmb = reactor[r.size.val];
m_cur_heat = reactor[r.heat.val];
m_max_heat = reactor[r.size.val]*1000+10000;
m_out = reactor[r.energy.val];

-- Get Ractor Content Information (Make it readable!)
SortContents(side, sensor, targets[1]);

-- Check to see if we need to load Uranium
if total_ucell < max_ucell then
  if  power == false then
   rs.setBundledOutput("back", colors.lightBlue + colors.yellow);
  elseif power == false and total_ice < max_ice then
   rs.setBundledOutput("back", colors.lightBlue + colors.yellow + colors.magenta);
  else
   rs.setBundledOutput("back", colors.lightBlue);
  end
end

-- Check to see if we need ice and that its not already flagged
if total_ice < max_ice and rs.testBundledInput("back", colors.magenta) == false then
   if power == false then
	rs.setBundledOutput("back", colors.magenta + colors.yellow);
   else
	rs.setBundledOutput("back", colors.magenta);
   end
end
-- Set local world and time format
local time = os.time();
time = textutils.formatTime(time, false);
term.setCursorPos(1,2);

-- Display world time
-- print ("World Time: "..time);
-- Move Cursor then display Reactor information
term.setCursorPos(1, 10);
-- Display information
print ("Reactor Size	   : "..m_cmb);
print ("Cur. Heat		  : "..m_cur_heat);
print ("Max. Heat		  : "..m_max_heat);
print ("Output (Eu/t)	  : "..m_out);
-- Reset totals before next loop
total_ice = 0;
total_ucell = 0;

-- set delay
sleep(1);

-- Check to see if the power kill is on, if it is ensure it gets put back in place
if power == false then
  rs.setBundledOutput("back", colors.yellow);
else
  -- Kill all cable signals
  rs.setBundledOutput("back", 0);
end;

sleep (1);
end

EDIT: Acutally this code isn't lagging as much as the v:sub version was, don't know if that is conincidence or that v:sub is more intensive, but over 60 fps improvement and with the exception of the extraction factory not being done this will keep a reactor in check! A small success I feel. Thank you for the comments and help!
ChunLing #6
Posted 27 October 2012 - 06:20 PM
I bet that the damage value was starting off at zero, so once it got higher than 9 the string.sub was getting "tem.itemCellUran@" instead of "item.itemCellUran". Odd that you're getting lag, I read this as only executing every other second, and nothing in it looks like a performance drain. I'd guess the lag would be from something else.
Harcole #7
Posted 28 October 2012 - 02:43 PM
So I got it all working so far, cleaned up the display out put and applied far better programming practice to it. Still not done the section for emptying the reactor but for maintained auto-filling its done. It should also be very easy to apply this to any other reactor with my new code layout.

I've tested it on a single reactor at 590EU/t and a 6 chambered reactor at 2030 EU/t without failure.

Thanks to ChunLing!

Basic Control Room showing output - http://i.imgur.com/451CU.jpg?1


-- Config bit!
local m_mon_side = "left"; -- Side monitor is attached to
local m_sensor_name = "Reactor 1"; -- Name of the sensor placed down
local m_name_reactor = "Harkole Power Industries: Reactor 1n"; -- name for displaying at top of screen
-- Wire colors and jobs
local m_power_full = colors.white; -- Trigger for EU storage full
local m_overheat = colors.orange; -- Trigger for overheated
local m_ice_feed = colors.magenta; -- Trigger for more ice
local m_ucell_feed = colors.lightBlue; -- Trigger for more fuel
local m_master = colors.yellow; -- Master on/off switch
local m_cutoff_heat = 4900; -- thermal cut off point (Match to thermal control on Reactor)
local m_max_ice = 192; -- 64 * 3 stacks
local m_max_ucell = 15; -- number of uranium slots to use
-- global settings - do not need changed
local m_total_ice = 0;
local m_total_ucell = 0;
local m_total_dcell = 0;
local m_total_ecell = 0;
-- Boolean checks
-- local m_power = true;
local m_restart = false;
-- Sensor controller side
local m_sensor_side = sensors.getController();
-- Reactor Readings
local m_reactor_size = 0;
local m_current_heat = 0;
local m_max_heat = 0;
local m_output = 0;
-- Energy box values
local m_max_storage = 0;
local m_curr_storage = 0;
local m_tier = 0;
-- Item names we will deal with
local m_name_ucell = "item.itemCellUran";
local m_name_dcell = "item.itemCellUranEmpty";
local m_name_ecell = "item.itemCellUranEnriched";
local m_name_ice = "tile.ice";
-- Message handler
local m_message = "";
function GetReactorContents()
-- Get sensor readings
content_target = sensors.getAvailableTargetsforProbe(m_sensor_side, m_sensor_name, "Reactor");
contents = sensors.getSensorReadingAsDict(m_sensor_side, m_sensor_name, content_target[1], "ReactorContent");

-- Get number of items in Reactor
for i, v in pairs(contents) do
  -- Check for ice and count
  if v:find(m_name_ice) then
   i_qty = tonumber(string.match(v, '^(%d*)%*'));
   m_total_ice = m_total_ice + i_qty;
 
  -- Check for Uranium Cells
  elseif v:find(m_name_ucell) then
   u_qty = tonumber(string.match(v, '^(%d*)%*'));
   m_total_ucell = m_total_ucell + u_qty;
 
  -- Enriched Uranium
  elseif v:find(m_name_ureenriched) then
   e_qty = tonumber(string.match(v, '^(%d*)%*'));
   m_total_ecell = m_total_ecell + e_qty;
 
  -- Depleated Uranium
  elseif v:find(m_name_uneardepleted) then
   d_qty = tonumber(string.match(v, '^(%d*)%*'));
   m_total_dcell = m_total_dcell + d_qty;
 
  end
end
end
function GetReactorValues()
-- Get sensor readings
reactor_target = sensors.getAvailableTargetsforProbe(m_sensor_side, m_sensor_name, "Reactor");
r = sensorsData.getProbe("ic2", "reactor");
reactor_value = sensors.getSensorReadingAsDict(m_sensor_side, m_sensor_name, reactor_target[1], "Reactor");

-- Assign values
m_reactor_size = reactor_value[r.size.val];
m_current_heat = reactor_value[r.heat.val];
m_max_heat = reactor_value[r.size.val]*1000+10000;
m_output = reactor_value[r.energy.val];

end
function GetPowerStorage()
-- Get sensor details
mf_targets = sensors.getAvailableTargetsforProbe(m_sensor_side, m_sensor_name, "EUStorage");
mf_value = sensors.getSensorReadingAsDict(m_sensor_side, m_sensor_name, mf_targets[2], "EUStorage");

-- Assign Values
m_max_storage = mf_value.maxStorage;
m_curr_storage = mf_value.energy;
m_tier = mf_value.tier;

end
function Display()
-- Display all gathered information, neatly on screen
print(m_name_reactor);
print(m_message);

-- Fix reactor reading size 0
if m_reactor_size == 0 then
  m_reactor_size = 1;
end

print("Size		  : "..m_reactor_size);
print("Current Heat  : "..m_current_heat.."/"..m_cutoff_heat);
print("Ice Qty	   : "..m_total_ice.."/"..m_max_ice);
print("Fuel Qty	  : "..m_total_ucell.."/"..m_max_ucell);
print("Depleated	 : "..m_total_dcell);
print("Enriched	  : "..m_total_ecell);
print("EU/t		  : "..m_output);
print();

print("Reactor EU Storen");

-- Convert Tier number to named item
if m_tier == 1 then
  m_tier = "Bat Box";
elseif m_tier == 2 then
  m_tier = "MFE";
elseif m_tier == 3 then
  m_tier = "MFSU";
end

-- Get percentage of fill, format the number to make it appear nicely
cur_storage_percent = (m_curr_storage / m_max_storage) * 100;
cur_storage_percent = math.floor(cur_storage_percent);


print("Type		  : "..m_tier);
print("Avail. Storage: "..m_curr_storage.." ("..cur_storage_percent.."%)");
print("Max Storage   : "..m_max_storage);
end
-- Check a monitor is available where specified and redirect if true
if peripheral.isPresent(m_mon_side) then
if peripheral.getType(m_mon_side) == "monitor" then
  monitor = peripheral.wrap(m_mon_side);
  term.redirect(monitor);
end
end
while true do
-- Clear Existing screen data
term.clear();

-- reset message handler
m_message = "";

-- Get all readings
GetReactorContents();
GetReactorValues();
GetPowerStorage();

-- Perform Reactor Service --

-- Check Reactor current situation incase we should shutdown
if colors.test(rs.getBundledInput("back"), m_overheat) then
  m_message = "Reactor Offline - ! OVERHEATED !n";
  m_power = false; -- shut off the power to the reactor to allow more cooling
  rs.setBundledOutput("back", m_master);

elseif colors.test(rs.getBundledInput("back"), m_power_full) then
  m_message = "Reactor Offline - Capacitors Full.n";
  m_power = false; -- shut off the power to the reactor to stop fuel waste
  rs.setBundledOutput("back", m_master);

else
  m_message = "Reactor Onlinen";

end

-- Check to see if we are due a restart from a previous fault
if m_power == false then

  -- set safety cool off
  safe_heat = m_cutoff_heat - 1000;
  -- message for if not cool enough
  if m_current_heat > safe_heat then
   m_message = m_message.."Restart when temp. below ".. safe_heat.."n";
  end

  -- get 75% mark of power storage
  storage_check = (m_max_storage / 100) * 75;
 
  if m_curr_storage > storage_check then
   m_message = m_message.."Restart when EU store below 75%n";
  end
 
  if m_current_heat < safe_heat and m_curr_storage < storage_check then
   m_power = true; -- turn power back on
  end
end

-- Check if Reactor requires Ice or uranium fuel
if m_total_ice < m_max_ice and m_total_ucell < m_max_ucell then
  m_message = m_message.." * Loading Ice ** Loading Fuel *";
 
  if m_power == false then
   rs.setBundledOutput("back", m_ice_feed + m_ucell_feed + m_master); -- trigger both fuel and ice and ensure power is kept off
  else
   rs.setBundledOutput("back", m_ice_feed + m_ucell_feed); -- trigger both fuel and ice
  end
 
elseif m_total_ice < m_max_ice then
  m_message = m_message.." * Loading Ice *";
 
  if m_power == false then
   rs.setBundledOutput("back", m_ice_feed + m_master); -- trigger just ice and ensure power is off
  else
   rs.setBundledOutput("back", m_ice_feed); -- trigger just ice
  end

elseif m_total_ucell < m_max_ucell then
  m_message = m_message.." * Loading Fuel *";
 
  if m_power == false then
   rs.setBundledOutput("back", m_ucell_feed + m_master); -- trigger just uranium cell (fuel) and ensure power is off 
  else
   rs.setBundledOutput("back", m_ucell_feed); -- trigger just uranium cell (fuel)
  end
end

-- Set cursor ready to output
term.setCursorPos(1,2);

-- Display output
Display();

sleep(0.5);

-- reset cables (to pulse fuel feeds) ensure master power switch is still obeyed
if m_power == false then
  rs.setBundledOutput("back", m_master);
else
  -- turn off cable signals off
  rs.setBundledOutput("back", 0);
end

-- Reset counters
m_total_ice = 0;
m_total_ucell = 0;
m_total_dcell = 0;
m_total_ecell = 0;

sleep(0.5);
end
ChunLing #8
Posted 28 October 2012 - 06:40 PM
Well, you tracked it to the sub returns. I'm not really very up to speed on reactor control in general, but this looks very impressive, particularly that you're able to run so close to meltdown temps without problems.