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

[Lua][Question] Run program until event (not pause until event)

Started by TemporalWolf, 13 March 2012 - 02:18 PM
TemporalWolf #1
Posted 13 March 2012 - 03:18 PM
I'm trying to write a program that will run (and manage a IC nuclear reactor automatically) without input, but which can accept input during the run loop:

W : speeds up the sampling cycle
S : slows down the sampling cycle
Q : quits the automatic manager, dropping you back into the OS.
E : override shutdown
R : override run

The issue I am having is using

while evInterrupt == false do -- while not interrupted
tos.splash(); -- clears and retitles the terminal
if redstone.getInput("left") and timer < maxtime then -- if MFSU is not full &amp; cooldown not required
status = 1; -- turn on
else
status = 0; -- turn off
--snipped code to show status
if status == 1 then
redstone.setOutput("right", true);
timer = timer + sTime; -- increment timer by stepTime
euCyc = euEff * sTime; -- calculate EU/sample(cycle)
euGen = euGen +euCyc; -- Calculate total EU since program started
sleep(sTime); -- let reactor run this cycle
else
redstone.setOutput("right", false);
timer = timer - sTime; --calculate time left to cooldown after this cycle
sleep(sTime); -- let reactor cool this cycle
end
evType, evValue = os.pullEvent()
if (what i'm looking for) then (do stuff)

causes the whole program to wait for an event to fire, so it doesn't run as it should.

I've read somewhere that os.timer works better than sleep for something like this, but I can't find where I read it.

EDIT3:
I'm guessing this is going to be something like replacing the sleep(sTime); with (psudocode)

while eTime < sTime do – While elapsed time is less than sample time
os.startTimer(0.2);
evType, evValue = os.pullEventRaw();
if evType == "key", do
stuff
else
eTime = eTime + 0.2;


that would generate a timer event every 1/5th of a second, which would trigger the os.pullEvent (which it would then discard as not a keypress) and catch ctrl+T (which will be allowed but I'll be inserting the forced shutdown code prior to termination)

Does that make sense?
6677 #2
Posted 13 March 2012 - 05:29 PM
i do apologise, i havent read the code fully as i'm on a smart phone right now.

anyway, to me it seems you need the timer function built into os. start a loop and set a timer for lets say .2 seconds and do an os.pullEvent. If the event is a key input then do whatever that key does. then proceed with your reactor checks regardless of the event type. start the loop over again.
Advert #3
Posted 13 March 2012 - 06:51 PM
You could try something like this:

local reactorFreq = 0.1
local timerTable = os.startTimer(reactorFreq) -- Frequency to run reactor at
local bExit = false -- For breaking out of the loop

function doReactorStuff()
 -- Do stuff to control the reactor.
end

function doUserStuff(key)
 -- do user stuff here, key = the key that's pressed; note that it is case sensetive
 if key == "X" then
  bExit = true -- We want to exit now.
  return
 elseif key == ... then
  ...
 end
end



for sEvent, a, b in os.pullEvent do
 if sEvent == "timer" and a == timerTable then
  timerTable = os.startTimer(reactorFreq) -- Timers only fire once, so we have to re-start it.
  -- Beware using sleep() or read() -- they will ignore other events while reading.
  doReactorStuff() -- Define this function; will be called every reactorFreq seconds.

 elseif sEvent == "char" then
  doUserStuff(a) -- Define this function; will recieve parameter 1: the character that was typed.
 end
 if bExit then
  break -- Stop the for loop
 end
end