Advertisement
neuroticfox

DC 4.1 Branch 2

Dec 24th, 2022 (edited)
1,474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.27 KB | Source Code | 0 0
  1. local component = require("component")
  2. local event = require("event")
  3. local term = require("term")
  4. local unicode= require("unicode")
  5. local gpu = component.gpu
  6.  
  7.  -- Safety Checks
  8.  
  9. if not component.isAvailable("draconic_reactor") then
  10.   print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
  11.   os.exit()
  12. end
  13. reactor = component.draconic_reactor
  14. local flux_gates = {}
  15. for x,y in pairs(component.list("flux_gate")) do
  16.   flux_gates[#flux_gates+1] = x
  17. end
  18. if #flux_gates < 2 then
  19.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  20.   os.exit()
  21. end
  22. flux_in = component.proxy(flux_gates[1])
  23. flux_out = component.proxy(flux_gates[2])
  24. if not flux_in or not flux_out then
  25.   print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
  26.   os.exit()
  27. end
  28.  
  29.  -- Functions
  30.  
  31. function exit_msg(msg)
  32.   term.clear()
  33.   print(msg)
  34.   os.exit()
  35. end
  36.  
  37. function modify_temp(offset)
  38.   local new_temp = ideal_temp + offset
  39.   if new_temp > 9000 then
  40.     new_temp = 9000
  41.   elseif new_temp < 2000 then
  42.     new_temp = 2000
  43.   end
  44.   ideal_temp = new_temp
  45. end
  46.  
  47. local chaosmode = 0
  48. local temp2 = 1
  49. local debuginfo = 0
  50. local highest_use = 1
  51. local highest_temp = 1
  52.  
  53. function modify_field(offset)
  54.   local new_strength = ideal_strength + offset
  55.   if new_strength > 100 then
  56.     new_strength = 100
  57.   elseif new_strength < 0.1 then
  58.     new_strength = 0.5
  59.   end
  60.   ideal_strength = new_strength
  61. end
  62.  
  63.  -- Buttons
  64.  
  65. local adj_button_width = 10
  66. local temp_adjust_x_offset = 56
  67. local temp_adjust_y_offset = 2
  68. local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
  69. local field_adjust_y_offset = 2
  70.  
  71. local buttons = {
  72.   start={
  73.     x=5,
  74.     y=18,
  75.     width=10,
  76.     height=1,
  77.     text="Start",
  78.     action=function()
  79.       if safe then
  80.         state = "Charging"
  81.         reactor.chargeReactor()
  82.       elseif shutting_down then
  83.         state = "Active"
  84.         reactor.activateReactor()
  85.       end
  86.     end,
  87.     condition=function() return safe or shutting_down end
  88.   },
  89.   shutdown={
  90.     x=5,
  91.     y=18,
  92.     width=10,
  93.     height=1,
  94.     text="Shutdown",
  95.     action=function()
  96.       state = "Manual Shutdown"
  97.       reactor.stopReactor()
  98.     end,
  99.     condition=function() return running end
  100.   },
  101.     debug_info={
  102.     x=17,
  103.     y=18,
  104.     width=10,
  105.     height=1,
  106.     text="Debug",
  107.     action=function()
  108.       if debuginfo == 0 then
  109.       debuginfo = 1
  110.       else
  111.       debuginfo = 0
  112.     end
  113.    end,
  114.   },
  115.   invert={
  116.     x=29,
  117.     y=18,
  118.     width=10,
  119.     height=1,
  120.     text="Invert",
  121.     action=function()
  122.       local old_addr = flux_in.address
  123.       flux_in = component.proxy(flux_out.address)
  124.       flux_out = component.proxy(old_addr)
  125.     end,
  126.     condition=function() return safe or cooling end
  127.   },
  128.     chaos_mode={
  129.     x=29,
  130.     y=18,
  131.     width=10,
  132.     height=1,
  133.     text="Chaos",
  134.     action=function()
  135.         if chaosmode == 0 then
  136.             chaosmode = 1
  137.             cutoff_temp = 19750
  138.             ideal_strength = 75
  139.             cutoff_field = 20
  140.             ideal_temp = 69420
  141.         elseif chaosmode == 1 then
  142.             chaosmode = 0
  143.             ideal_strength = 25
  144.             cutoff_field = 0.4
  145.             ideal_temp = 4000
  146.         end
  147.     end,
  148.     condition=function() return running end
  149.   },
  150.   exit={
  151.     x=41,
  152.     y=18,
  153.     width=10,
  154.     height=1,
  155.     text="Exit",
  156.     action=function()
  157.       event_loop = false
  158.     end,
  159.   },
  160.   temp_up_thousand={
  161.     x=temp_adjust_x_offset,
  162.     y=temp_adjust_y_offset,
  163.     width=adj_button_width,
  164.     height=1,
  165.     text="+1000",
  166.     action=function() modify_temp(1000) end
  167.   },
  168.   temp_up_hundred={
  169.     x=temp_adjust_x_offset,
  170.     y=temp_adjust_y_offset+2,
  171.     width=adj_button_width,
  172.     height=1,
  173.     text="+100",
  174.     action=function() modify_temp(100) end
  175.   },
  176.   temp_up_ten={
  177.     x=temp_adjust_x_offset,
  178.     y=temp_adjust_y_offset+4,
  179.     width=adj_button_width,
  180.     height=1,
  181.     text="+10",
  182.     action=function() modify_temp(10) end
  183.   },
  184.   temp_up_one={
  185.     x=temp_adjust_x_offset,
  186.     y=temp_adjust_y_offset+6,
  187.     width=adj_button_width,
  188.     height=1,
  189.     text="+1",
  190.     action=function() modify_temp(1) end
  191.   },
  192.   temp_down_thousand={
  193.     x=temp_adjust_x_offset,
  194.     y=temp_adjust_y_offset+16,
  195.     width=adj_button_width,
  196.     height=1,
  197.     text="-1000",
  198.     action=function() modify_temp(-1000) end
  199.   },
  200.   temp_down_hundred={
  201.     x=temp_adjust_x_offset,
  202.     y=temp_adjust_y_offset+14,
  203.     width=adj_button_width,
  204.     height=1,
  205.     text=" -100",
  206.     action=function() modify_temp(-100) end
  207.   },
  208.   temp_down_ten={
  209.     x=temp_adjust_x_offset,
  210.     y=temp_adjust_y_offset+12,
  211.     width=adj_button_width,
  212.     height=1,
  213.     text="-10",
  214.     action=function() modify_temp(-10) end
  215.   },
  216.   temp_down_one={
  217.     x=temp_adjust_x_offset,
  218.     y=temp_adjust_y_offset+10,
  219.     width=adj_button_width,
  220.     height=1,
  221.     text="-1",
  222.     action=function() modify_temp(-1) end
  223.   },
  224.   field_up_ten={
  225.     x=field_adjust_x_offset,
  226.     y=field_adjust_y_offset,
  227.     width=adj_button_width,
  228.     height=1,
  229.     text="+10",
  230.     action=function() modify_field(10) end
  231.   },
  232.     field_up_five={
  233.     x=field_adjust_x_offset,
  234.     y=field_adjust_y_offset+2,
  235.     width=adj_button_width,
  236.     height=1,
  237.     text="+5",
  238.     action=function() modify_field(5) end
  239.   },
  240.     field_up_one={
  241.     x=field_adjust_x_offset,
  242.     y=field_adjust_y_offset+4,
  243.     width=adj_button_width,
  244.     height=1,
  245.     text="+1",
  246.     action=function() modify_field(1) end
  247.   },
  248.   field_up_half={
  249.     x=field_adjust_x_offset,
  250.     y=field_adjust_y_offset+6,
  251.     width=adj_button_width,
  252.     height=1,
  253.     text="+0.5",
  254.     action=function() modify_field(0.5) end
  255.   },
  256.   field_down_half={
  257.     x=field_adjust_x_offset,
  258.     y=field_adjust_y_offset+10,
  259.     width=adj_button_width,
  260.     height=1,
  261.     text="-0.5",
  262.     action=function() modify_field(-0.5) end
  263.   },
  264.     field_down_one={
  265.     x=field_adjust_x_offset,
  266.     y=field_adjust_y_offset+12,
  267.     width=adj_button_width,
  268.     height=1,
  269.     text="-1",
  270.     action=function() modify_field(-1) end
  271.   },
  272.     field_down_five={
  273.     x=field_adjust_x_offset,
  274.     y=field_adjust_y_offset+14,
  275.     width=adj_button_width,
  276.     height=1,
  277.     text="-5",
  278.     action=function() modify_field(-5) end
  279.   },
  280.     field_down_ten={
  281.     x=field_adjust_x_offset,
  282.     y=field_adjust_y_offset+16,
  283.     width=adj_button_width,
  284.     height=1,
  285.     text="-10",
  286.     action=function() modify_field(-10) end
  287.   }
  288. }
  289.  
  290.  -- main code
  291.  
  292. flux_in.setFlowOverride(0)
  293. flux_out.setFlowOverride(0)
  294. flux_in.setOverrideEnabled(true)
  295. flux_out.setOverrideEnabled(true)
  296.  
  297. local condition = reactor.getReactorInfo()
  298. if not condition then
  299.   print("Incorrect Layout")
  300.   os.exit()
  301. end
  302.  
  303. ideal_strength = 25
  304. ideal_temp = 4000
  305. cutoff_temp = 9005
  306.  
  307.  -- tweakable pid gains
  308.  
  309. inflow_P_gain = 1
  310. inflow_I_gain = 0.04
  311. inflow_D_gain = 0.1
  312.  
  313. outflow_P_gain = 500
  314. outflow_I_gain = 0.5
  315. outflow_II_gain = 0.0000003
  316. outflow_D_gain = 60000
  317.  
  318.  -- initialize main loop
  319.  
  320. inflow_I_sum = 0
  321. inflow_D_last = 0
  322.  
  323. outflow_I_sum = 0
  324. outflow_II_sum = 0
  325. outflow_D_last = 0
  326.  
  327. state = "Standby"
  328. shutting_down = false
  329.  
  330. if condition.temperature > 25 then
  331.   state = "Cooling"
  332. end
  333. if condition.temperature > 2000 then
  334.   state = "Active"
  335. end
  336.  
  337.  -- Possible states:
  338.   --Standby
  339.   --Charging
  340.   --Active
  341.   --Manual Shutdown
  342.   --Emergency Shutdown
  343.   --Cooling
  344.  
  345. event_loop = true
  346. while event_loop do
  347.  
  348.   if not component.isAvailable("draconic_reactor") then
  349.     exit_msg("Reactor disconnected, exiting")
  350.   end
  351.  
  352.   if not component.isAvailable("flux_gate") then
  353.     exit_msg("Flux gates disconnected, exiting")
  354.   end
  355.  
  356.   local info = reactor.getReactorInfo()
  357.  
  358.   local inflow = 0
  359.   local outflow = 0
  360.  
  361.   shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
  362.   running = state == "Charging" or state == "Active"
  363.   safe = state == "Standby" or state == "Cooling"
  364.  
  365.   if state == "Charging" then
  366.     inflow = 3200000
  367.  
  368.     if info.temperature > 2000 then
  369.       reactor.activateReactor()
  370.       state = "Active"
  371.     end
  372.   elseif state == "Cooling" then
  373.     if info.temperature < 25 then
  374.       state = "Standby"
  375.     end
  376.     inflow = 10
  377.     outflow = 20
  378.   elseif state == "Standby" then
  379.     inflow = 10
  380.     outflow = 20
  381.   else
  382.     -- adjust inflow rate based on field strength
  383.  
  384.     local field_error = (info.maxFieldStrength * (ideal_strength / 100)) - info.fieldStrength
  385.     local proportional_field_error = field_error * inflow_P_gain
  386.     inflow_I_sum = inflow_I_sum + field_error
  387.     local integral_field_error = inflow_I_sum * inflow_I_gain
  388.     local derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
  389.     inflow_D_last = field_error
  390.     local inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
  391.     if inflow_correction < 0 then
  392.       inflow_I_sum = inflow_I_sum - field_error
  393.     end
  394.     inflow = inflow_correction
  395.  
  396.     if not shutting_down then
  397.  
  398.       -- adjust outflow rate based on core temperature
  399.  
  400.       local temp_error = ideal_temp - info.temperature
  401.       local proportional_temp_error = temp_error * outflow_P_gain
  402.       outflow_I_sum = outflow_I_sum + temp_error
  403.       local integral_temp_error = outflow_I_sum * outflow_I_gain
  404.       if math.abs(temp_error) < 100 then
  405.         outflow_II_sum = outflow_II_sum + integral_temp_error
  406.       else
  407.         outflow_II_sum = 0
  408.       end
  409.       local second_integral_temp_error = outflow_II_sum * outflow_II_gain
  410.       local derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
  411.       outflow_D_last = temp_error
  412.       local outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
  413.       if outflow_correction < 0 then
  414.         outflow_I_sum = outflow_I_sum - temp_error
  415.       end
  416.       outflow = outflow_correction
  417.  
  418.       -- cut off reactor in case of emergency
  419.       if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 7 or info.temperature > 19750 then
  420.         print("Shutting Down")
  421.         state = "Manual Shutdown"
  422.         reactor.stopReactor()
  423.       end
  424.     else
  425.       if info.temperature < 2000 then
  426.         state = "Cooling"
  427.       end
  428.     end
  429.   end
  430.  
  431.   if state ~= "Active" and not shutting_down then
  432.     inflow_I_sum = 0
  433.     inflow_D_last = 0
  434.     outflow_I_sum = 0
  435.     outflow_II_sum = 0
  436.     outflow_D_last = 0
  437.   end
  438.  
  439.   if inflow < 0 then
  440.     inflow = 0
  441.   end
  442.   if outflow < 0 then
  443.     outflow = 0
  444.   end
  445.  
  446.   inflow = math.floor(inflow)
  447.   outflow = math.floor(outflow)
  448.  
  449.   flux_in.setFlowOverride(inflow)
  450.   flux_out.setFlowOverride(outflow)
  451.  
  452.  -- Fuel Conversion Rate
  453.  
  454. if info.fuelConversionRate > 999 then
  455.     fuelConversionRate = (info.fuelConversionRate / 1000)
  456.     fuelMeasure = " "..(unicode.char(956)).."b/t"
  457.     elseif info.fuelConversionRate > 999999 then
  458.     fuelConversionRate = (info.fuelConversionRate / 1000000)
  459.     fuelMeasure = " mb/t"
  460.     else
  461.     fuelConversionRate = info.fuelConversionRate
  462.     fuelMeasure = " nb/t"
  463. end
  464.  
  465.  -- Burn Stage
  466.  
  467. if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 20 then burnstage = "H"
  468. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 15 then burnstage = "He"
  469. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 10 then burnstage = "C"
  470. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 8 then burnstage = "Ne"
  471. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 6.75 then burnstage = "O"
  472. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 5.5 then burnstage = "Si"
  473. elseif ((1 - info.fuelConversion / info.maxFuelConversion) * 100) > 5 then burnstage = "Fe"
  474. end
  475.  
  476.  -- Debug Info
  477.  --HFuel
  478. if info.fuelConversionRate > highest_use then
  479.     highest_use = info.fuelConversionRate
  480. end
  481.  --HTemp
  482. if info.temperature > highest_temp then
  483.   highest_temp = info.temperature
  484. end
  485.  
  486.  if debuginfo == 1 then
  487.  debugvar1a = "[Debug Information]"
  488.  debugvar1b = "Peak Fuel Usage: "
  489.  debugvar1c = highest_use
  490.  debugvar1d = " nb/t"
  491.  debugvar2a = "Peak Temperature"
  492.  debugvar2b = highest_temp
  493.  debugvar2c = "°C"
  494.  else
  495.   debugvar1a = " "
  496.  debugvar1b = " "
  497.  debugvar1c = " "
  498.  debugvar1d = " "
  499.  debugvar2a = " "
  500.  debugvar2b = " "
  501.  debugvar2c = " "
  502. end
  503.  
  504.   -- Draw screen
  505.  
  506.   if term.isAvailable() then
  507.  
  508.     -- Draw Values
  509.  
  510.     local left_margin = 2
  511.     local spacing = 1
  512.  
  513.     local values = {
  514.       "┌─────────────────────────────────────────────────┐",
  515.       "│ Draconic Control Version 4.1 - Alternate Branch │",
  516.       "│                    [bZhG6Dyj]                   │",
  517.       "├─────────────────────────────────────────────────┘",
  518.       "│ Reactor State        " .. state,
  519.       "│  Field Strength       " .. ((info.fieldStrength / info.maxFieldStrength) * 100) .. "%",
  520.       "│ Saturation           " .. ((info.energySaturation / info.maxEnergySaturation) * 100) .. "%",
  521.       "│  Fuel Remaining       " .. ((1 - info.fuelConversion / info.maxFuelConversion) * 100) .. "%",
  522.       "│ Temperature          " .. info.temperature .. "°C",
  523.       "│  Fuel Usage Rate      " .. fuelConversionRate .. fuelMeasure,
  524.       "│ Energy Consumption   " .. inflow .. " RF/t",
  525.       "│  Energy Production    " .. outflow .. " RF/t",
  526.       "│ Eq. Fusion Stage     " .. burnstage,
  527.       "└──────────────────────────────────────────────────",
  528.       "",
  529.       "",
  530.       "",
  531.       "",
  532.       "",
  533.       "" .. debugvar1a,
  534.       "" .. debugvar1b .. debugvar1c .. debugvar1d,
  535.       "" .. debugvar2a .. debugvar2b .. debugvar2c,
  536.     }
  537.  
  538.     if safe then
  539.       values[#values+1] = "Invert if start is non-functional - Start at 4000 before increasing temperature."
  540.     end
  541.  
  542.     term.clear()
  543.  
  544.     for i, v in ipairs(values) do
  545.       term.setCursor(left_margin, i * spacing)
  546.       term.write(v)
  547.     end
  548.  
  549.     -- Draw button values
  550.  
  551.     term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+8)
  552.     term.write("  " .. ideal_temp .. "°C")
  553.     term.setCursor(field_adjust_x_offset, field_adjust_y_offset+8)
  554.     term.write("   " .. ideal_strength .. "%")
  555.  
  556.     -- Draw Buttons
  557.  
  558.     gpu.setForeground(0x0000FF)
  559.  
  560.     for bname, button in pairs(buttons) do
  561.       if button.depressed then
  562.  
  563.         button.depressed = button.depressed - 1
  564.         if button.depressed == 0 then
  565.           button.depressed = nil
  566.         end
  567.       end
  568.       if button.condition == nil or button.condition() then
  569.         local center_color = 0xBBBBBB
  570.         local highlight_color = 0xCCCCCC
  571.         local lowlight_color = 0x808080
  572.         if button.depressed then
  573.           center_color = 0xAAAAAA
  574.           highlight_color = 0x707070
  575.           lowlight_color = 0xBBBBBB
  576.         end
  577.         gpu.setBackground(center_color)
  578.         gpu.fill(button.x, button.y, button.width, button.height, " ")
  579.         if button.width > 1 and button.height > 1 then
  580.           gpu.setBackground(lowlight_color)
  581.           gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
  582.           gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
  583.           gpu.setBackground(highlight_color)
  584.           gpu.fill(button.x, button.y, 1, button.height, " ")
  585.           gpu.fill(button.x, button.y, button.width, 1, " ")
  586.         end
  587.         gpu.setBackground(center_color)
  588.         term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
  589.         term.write(button.text)
  590.       end
  591.     end
  592.  
  593.     gpu.setBackground(0x999999)
  594.     gpu.setForeground(0x0000FF)
  595.   end
  596.  
  597.   -- Wait for next tick, or manual shutdown
  598.  
  599.   local event, id, op1, op2 = event.pull(0.05)
  600.   if event == "interrupted" then
  601.     if safe then
  602.       break
  603.     end
  604.   elseif event == "touch" then
  605.  
  606.     -- Handle Button Presses
  607.  
  608.     local x = op1
  609.     local y = op2
  610.  
  611.     for bname, button in pairs(buttons) do
  612.       if (button.condition == nil or button.condition()) and x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height then
  613.         button.action()
  614.         button.depressed = 3
  615.       end
  616.     end
  617.   end
  618. end
  619.  
  620. term.clear()
  621.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement