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

Alternative to infinite loops?

Started by inkychris, 05 January 2015 - 09:43 PM
inkychris #1
Posted 05 January 2015 - 10:43 PM
I have built a lighthouse made from 8 lamp blocks in a rectangle (but at 45 degrees) where 2 of the 8 that are next to each other light up and this moves round all of them every 0.3 seconds. There is also a beacon on top that flashes every second. I wanted several options such that it could be OFF, Just Beacon, Just main light, or both Beacon and main light.

In addition to this, I also wanted a text command to be used to stop the function/restart it etc. My code works but to me doesn't seem very streamlined but I am very new to Lua. My main question is the following:

Is there a way of waiting until a variable changes before calling a function or is the only way to do as I have with a While True loop with sleep(0) in it?

This is to help me learn Lua more than anything. As I said, the code works but if anyone has any better ideas for how to do what I want that didn't involve what I believe to be calling the setBundledOutput function over and over very fast every second?

Thank you very much for any help or advice you can give,
Chris.

The code is as follows:


function clear()
term.setBackgroundColor(colours.black)
term.clear()
term.setCursorPos(1,1)
end
function beacon()
while true do
  b = 8192
  sleep(1)
  b = 0
  sleep(1)
end
end
function lighthouse()
local t = {9,12,6,34,96,80,32784,32769}
while true do
  for i=1,#t do
  h = t[i]
  sleep(0.3)
  end
end
end
function one()
while true do
  redstone.setBundledOutput("back", B)/>/>/>/>
  sleep(0)
end
end
function two()
while true do
  redstone.setBundledOutput("back", h)
  sleep(0)
end
end
function three()
while true do
  redstone.setBundledOutput("back", b+h)
  sleep(0)
end
end
function input()
while true do
local p = read()
  if p~='' then
   redstone.setBundledOutput("back", 0)
   break
  end
end
end

--MAIN BODY
while true do
print("Select an option: ")
local r=read()

if r=='0' then
  redstone.setBundledOutput("back", 0)
elseif r=='1' then
  parallel.waitForAny(input, one, beacon)
elseif r=='2' then
  parallel.waitForAny(input, lighthouse, two)
elseif r=='3' then
  parallel.waitForAny(input, beacon, lighthouse, three)
elseif r~='0' or '1' or '2' or '3' then
  redstone.setBundledOutput("back", 0)
  break
end

end
TheOddByte #2
Posted 07 January 2015 - 08:57 PM
Well the repeat loop is always an option

local foo
repeat
    foo = read()
until foo == "bar"
print( foo )
Bomb Bloke #3
Posted 08 January 2015 - 03:45 AM
Is there a way of waiting until a variable changes before calling a function or is the only way to do as I have with a While True loop with sleep(0) in it?

If I want to do something along these lines, I'll often consider having the loop call os.pullEvent("myCustomEvent"). It'll then sit there yielding until such time as I call os.queueEvent("myCustomEvent") somewhere else in the code.

That said, in this case I'd do away with all the extra functions and loops and run all the logic in one place, using timers:

Spoiler
local beaconVals = {8192,0}
local lighthouseVals = {9,12,6,34,96,80,32784,32769}
local lighthouseTimer, beaconTimer

term.setTextColour(colours.white)
term.setBackgroundColour(colours.black)
term.clear()
term.setCursorPos(1,1)
print("Select an option (0-3).")
redstone.setBundledOutput("back", 0)

while true do
	local myEvent = {os.pullEvent()}  -- Pull an event, stick all the data in a table.

	if myEvent[1] == "char" then
		if myEvent[2] == "0" then
			print("0: All off.")
			redstone.setBundledOutput("back", 0)
			lighthouseTimer, beaconTimer = nil, nil
			
		elseif myEvent[2] == "1" then
			print("1: Beacon only.")
			lighthouseTimer, beaconTimer = nil, beaconTimer or os.startTimer(0)  -- See "logical operators" at http://lua-users.org/wiki/OperatorsTutorial
			
		elseif myEvent[2] == "2" then
			print("2: Lighthouse only.")
			lighthouseTimer, beaconTimer = lighthouseTimer or os.startTimer(0), nil
			
		elseif myEvent[2] == "3" then
			print("3: Beacon and lighthouse.")
			lighthouseTimer, beaconTimer = lighthouseTimer or os.startTimer(0), beaconTimer or os.startTimer(0)
			
		else
			print("Unknown: Exiting...")
			redstone.setBundledOutput("back", 0)
			break
		end
		
	elseif myEvent[1] == "timer" then
		if myEvent[2] == lighthouseTimer then
			table.insert(lighthouseVals,table.remove(lighthouseVals,1))  -- Take away the first entry in the table, shove it on the end.
			lighthouseTimer = os.startTimer(0.3)
			
		elseif myEvent[2] == beaconTimer then
			table.insert(beaconVals,table.remove(beaconVals,1))
			beaconTimer = os.startTimer(1)
		end
		
		redstone.setBundledOutput("back", (lighthouseTimer and lighthouseVals[1] or 0) + (beaconTimer and beaconVals[1] or 0))  -- See http://lua-users.org/wiki/TernaryOperator
	end
end