Advertisement
neuroticfox

DC 4.1 Branch 3

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