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

Keeping A Function Active Help

Started by revjoe, 07 May 2014 - 04:50 PM
revjoe #1
Posted 07 May 2014 - 06:50 PM
Hi, Ive created a menu program to control my security systems but i need a redstone output to stay active and after being activated the menu to return to the options while keeping the output active. I was told the option return would do it but so far no joy! Plz help.
viluon #2
Posted 07 May 2014 - 06:58 PM
Please post your code so we can see "what's wrong".
revjoe #3
Posted 07 May 2014 - 07:03 PM
Its on the computer online but i can post an example. In line 17 i need a command to leave the redstone true and go back to the start of the menu so it can be deactivated seperately on the options.
  • term.clear()
  • term.setCursorPos(1,1)
  • print("Uber Prison- RevJoes Door Control System")
  • term.setCursorPos(2,2)
  • print("Please select Option")
  • local selection = menu("OpenCell 1","OpenCell 2","OpenCell 3","OpenMaxCell 1","OpenMaxCell 2","Exit")
  • if selection == "OpenCell 1" then
  • term.clear()
  • password = "hold1"
  • term.setCursorPos(1,1)
  • print("Warden Access, Please Enter Security Code:-")
  • pass = read("*")
  • if pass == password then
  • print("Security Code Accepted, Holding Cell 1 Opening")
  • redstone.setBundledOutput("bottom",colors.yellow,true)
  • sleep(5)
  • os.reboot()
  • else
  • term.clear()
  • term.setCursorPos(1,1)
  • print("Wrong Code Entered, Alarm Activating")
  • sleep(0.5)
  • redstone.setBundledOutput("bottom",colors.green,true)
  • sleep(3)
  • redstone.setBundledOutput("bottom",colors.green,false)
  • os.reboot()
  • end
viluon #4
Posted 07 May 2014 - 07:07 PM
Please use tags "code" to post your code, it's far better to read it like that.

What CC version do you use? Normal redstone signal from vanilla MC is set via redstone.setOutput(string side, boolean value) or redstone.setAnalogOutput(string side, number strength)
Edited on 07 May 2014 - 05:51 PM
revjoe #5
Posted 07 May 2014 - 07:18 PM
Im not sure its on tekkit classic the functions all work but i just cant keep them active and return to the options
Lyqyd #6
Posted 07 May 2014 - 07:25 PM
Your redstone functions are messed up, but not for the reasons mentioned above. The setBundledOutput calls only take two parameters, the side and the lines to set high. You can use this to turn them all off:


rs.setBundledOutput("left", 0)

As to the main issue, you seem to be trying to use os.reboot as if it is a goto statement. When you reboot the computer, it resets all of the redstone outputs to off. You should look in to using a while loop instead, if you want to loop infinitely. You may need to re-write minor portions of the code to accommodate using an actual loop.
revjoe #7
Posted 07 May 2014 - 07:43 PM
I believe lua doesnt have a goto altho that is basically what i need after the forcefield is activated by the first option i would like it to goto the start without rebooting so the shield stays active. And thats the only way ive managed to get the bundled outputs to work so far but they activate and deactivate fine.
Lyqyd #8
Posted 07 May 2014 - 07:55 PM
Like I just said, you'll want to put the parts that need to loop into a while loop.
revjoe #9
Posted 07 May 2014 - 07:58 PM
i have no idea how to do the while loop to make it return to the start, i have three options activate shield, deactivate shield and Electrify area. How would i code a while loop to activate the shield and go back to the start and stop the loop when deactivate is activated. Sorry to be a pain.
viluon #10
Posted 07 May 2014 - 08:02 PM
You are not a pain, Ask a Pro is designed for this use

http://www.lua.org/pil/4.3.2.html


local variable=true

while variable do
    DoStuff() --# will be called again and again, won't repeat if variable will be false
end


This could greatly help you in understanding Lua control structures http://lua-users.org/wiki/ControlStructureTutorial
Edited on 09 May 2014 - 04:06 AM
revjoe #11
Posted 07 May 2014 - 08:13 PM
  • local function menu(...) -- ver 0.1
        local sel = 1
        local list = {...}
        local offX,offY = term.getCursorPos()
        local curX,curY = term.getCursorPos()
        while true do
    		    if sel > #list then sel = 1 end
    		    if sel < 1 then sel = #list end
    		    for i = 1,#list do
    				    term.setCursorPos(offX,offY+i-1)
    				    if sel == i then
    						    print("["..list[i].."]")
    				    else
    						    print(" "..list[i].." ")
    				    end
    		    end
    		    while true do
    				    local e,e1,e2,e3,e4,e5,e6 = os.pullEvent()
    				    if e == "key" then
    						    if e1 == 200 then -- up key
    								    sel = sel-1
    								    break
    						    end
    						    if e1 == 208 then -- down key
    								    sel = sel+1
    								    break
    						    end
    						    if e1 == 28 then
    								    term.setCursorPos(curX,curY)
    								    return list[sel],sel
    						    end
    				    end
    		    end
        end
    end
    -- Example Usage
    term.clear()
    term.setCursorPos(1,1)
    print("Uber Prison- RevJoes Security Control System")
    term.setCursorPos(2,2)
    print("Please select Option")
    local selection = menu("Activate Holding Shield", "Deactivate Holding Shield", "Electrify Holding Area")
    if selection == "Activate Holding Shield" then
        term.clear()
        password = "holder"
        term.setCursorPos(1,1)
        print("Warden Access, Please Enter Security Code:-")
        pass = read("*")
        if pass == password then
        print("Security Code Accepted, Activating Holding Shield")
        redstone.setBundledOutput("bottom",colors.black,true)
        return
        else
        term.clear()
        term.setCursorPos(1,1)
        print("Wrong Code Entered, Alarm Activating")
        sleep(0.5)
        redstone.setBundledOutput("bottom",colors.green,true)
        sleep(3)
        redstone.setBundledOutput("bottom",colors.green,false)
        os.reboot()
        end
    elseif selection == "Deactivating Holding Shield" then
        term.clear()
        password = "unhold"
        term.setCursorPos(1,1)
        print("Warden Access, Please Enter Security Code:-")
        pass = read("*")
        if pass == password then
        print("Security Code Accepted, Deactivating Holding Shield")
        redstone.setBundledOutput("bottom",colors.black,false)
        os.reboot()
        else
        term.clear()
        term.setCursorPos(1,1)
        print("Wrong Code Entered, Alarm Activating")
        sleep(0.5)
        redstone.setBundledOutput("bottom",colors.green,true)
        sleep(3)
        redstone.setBundledOutput("bottom",colors.green,false)
        os.reboot()
        end
    elseif selection == "Electrify Holding Area" then
        term.clear()
        password = "shock"
        term.setCursorPos(1,1)
        print("Caution This Will Kill All Vulnerable Players In Holding Area")
        term.setCursorPos(2,2)
        print("Warden Access, Please Enter Security Code:-")
        pass = read("*")
        if pass == password then
        print("Security Code Accepted, Frying Bitch's")
        sleep(1)
        local i = 3
        repeat
        redstone.setBundledOutput("bottom",colors.brown,true)
        sleep(2)
        redstone.setBundledOutput("bottom",colors.brown,false)
        i = i + 1
        until i == 3
        os.reboot()
        else
        term.clear()
        term.setCursorPos(1,1)
        print("Wrong Code Entered, Alarm Activating")
        sleep(0.5)
        redstone.setBundledOutput("bottom",colors.green,true)
        sleep(3)
        redstone.setBundledOutput("bottom",colors.green,false)
        os.reboot()
        end
    end
  • Sorry i couldnt find the tag code option, where would i insert that to make the redstone stay active and go back to options? Ive only just started on this server i dont know where the base/top code come from im workin on the bottom the functions. Something like "goto menu" woulda made life so much easier.
Edited on 07 May 2014 - 06:30 PM
Dog #12
Posted 07 May 2014 - 08:18 PM

variable=true

while variable do
	DoStuff() --# will be called again and again, won't repeat if variable will be false
end

Why set variable = true? And, if you're going to set the variable, why not localize it? Wouldn't it just be easier to do this?


while true do
  DoStuff()
end

@revjoe - please use code tags when posting your code - that makes it much easier to read.
Edited on 07 May 2014 - 06:21 PM
viluon #13
Posted 07 May 2014 - 08:23 PM
In your forum post editor in the top left corner about 3rd or 2nd from left there should be a square like icon with a green bar. When you hover with a mouse over it, it should say something like "Insert special BBCode". Click on it and from the list of different BBCodes select "Code". That should insert the code tags into your post, put your code between them.


variable=true

while variable do
	DoStuff() --# will be called again and again, won't repeat if variable will be false
end

Why set variable = true? And, if you're going to set the variable, why not localize it? Wouldn't it just be easier to do this?


while true do
  DoStuff()
end

@revjoe - please use code tags when posting your code - that makes it much easier to read.
I was trying to explain how a common while loop works, not how an infinite loop works. The variable is not localized to keep things simple. For closer information on loops I linked a tutorial. Was that a mistake?
Edited on 07 May 2014 - 06:21 PM
revjoe #14
Posted 07 May 2014 - 08:32 PM
Just changed it sorry saw that option but wasnt a lua option so thought i may have been in the wrong place. The tutorial scrambled my brain alil its been many years since i done proper code and about a year since i last used lua. Its not coming back to me naturally atm. I just cant seem to figure out how to use a loop to do what i need it to.
Dog #15
Posted 07 May 2014 - 08:41 PM
I was trying to explain how a common while loop works, not how an infinite loop works. The variable is not localized to keep things simple. For closer information on loops I linked a tutorial. Was that a mistake?

I'm probably the last person to judge what is or isn't a 'mistake' (I make 'em all the time) :)/>

However, not localizing your variable doesn't make it simpler, it makes it harder in the long run as it 're-enforces' undesired habits (non localization of variables). I may be wrong, but an example should not just lead the person to a solution, it should also re-enforce good programming habits.

As for the loop. The infinite loop I used is a 'while' loop as yours is, except mine doesn't require the extra step of declaring a variable (which makes the offered solution more complex, not less). Right now revjoe just needs a loop and a simple infinite loop will fit the bill fine. Adding complexity doesn't make it easier to learn.

The link you included is informative, but also very confusing as it covers 'goto' which Lua 5.1 doesn't support (and revjoe was looking for). Although the page does say that Lua 5.1 doesn't support this, it's a bit of stretch to expect revjoe to know which version of Lua ComputerCraft is based on.

My apologies for going so far O/T, and my apologies if I am lecturing.


@revjoe - your first step should probably be to identify which part of your code needs to loop and which parts only need to happen once. Once you've done that, take a look back at the examples given and replace 'DoStuff()' with your code that *should* be looping. Post what you come up with.
Edited on 07 May 2014 - 06:46 PM
viluon #16
Posted 07 May 2014 - 08:46 PM
OK what's the error now? You still seem to be using the wrong call of redstone.setBundledOutput(…)
viluon #17
Posted 07 May 2014 - 08:58 PM
offtopic
Snip
You are basically right but…

You really think that a local boolean helps the RAM usage worth mentioning it?
You really think that localizing example variables will help him understand while loops faster?
You really think that if he need the while loop so quickly it's good to write a wall of text?
You really think that one boolean declaration makes a 4 line code complex?
You really think that writing that post was eventually worth the time?

Seriously, no offense, I'm trying to help and you should more focus on the real problem (my opinion)

Sincerely, Andy aka viluon

Edit: I accept constructive critism and your reasons are basically right but simply not good enough to waste time with, don't you think?
Edited on 07 May 2014 - 07:04 PM
Dog #18
Posted 07 May 2014 - 09:10 PM
viuon, I'd like to continue our conversation (I'm getting value out of it, and I hope you are, too), but I'd like to take it out of this thread - can we continue in PM's?
revjoe #19
Posted 07 May 2014 - 09:11 PM
that call works perfectly for me tho, its a workaround the goto command i need.
viluon #20
Posted 07 May 2014 - 09:27 PM
Although I've got no idea how your code could work, you probably want to change this


print("Please select Option")
local selection = menu("Activate Holding Shield", "Deactivate Holding Shield", "Electrify Holding Area")
To this


print("Please select Option")
while true do
local selection = menu("Activate Holding Shield", "Deactivate Holding Shield", "Electrify Holding Area")
And add an "end" to the end of the code. Remember to get rid of those os.reboot()s
Lyqyd #21
Posted 07 May 2014 - 10:34 PM
For reference, I agree with Dog. Using clean, simple, concise code that follows best practices is important when posting code in Ask a Pro answers. It's good to point out when code posted is not concise, simple, or following best practices, as long as this is done in a polite manner, as Dog did. It is important to teach good habits through answers in Ask a Pro, as this has direct and noticeable impacts in the overall code quality in the community as well as making it easier for askers to learn and grow in their programming skills without picking up bad habits.

revjoe, could you post a copy of your current code? It will be easier to see where the loop should start and end if you can post a current copy. You can use the [co<b></b>de] tags to make it easier to read your code on the forums.
revjoe #22
Posted 07 May 2014 - 10:52 PM
This is the current code, i need the first option to go true and stay true while goin bk to the options so it can be shutdown with a seperate option. So after print("Security Code Accepted, Activating Holding Shield") i need that redstone to stay true. Altho the redstone outputs may not be the usual that is what works on this server.

local function menu(...) -- ver 0.1
	local sel = 1
	local list = {...}
	local offX,offY = term.getCursorPos()
	local curX,curY = term.getCursorPos()
	while true do
					if sel > #list then sel = 1 end
					if sel < 1 then sel = #list end
					for i = 1,#list do
									term.setCursorPos(offX,offY+i-1)
									if sel == i then
													print("["..list[i].."]")
									else
													print(" "..list[i].." ")
									end
					end
					while true do
									local e,e1,e2,e3,e4,e5,e6 = os.pullEvent()
									if e == "key" then
													if e1 == 200 then -- up key
																	sel = sel-1
																	break
													end
													if e1 == 208 then -- down key
																	sel = sel+1
																	break
													end
													if e1 == 28 then
																	term.setCursorPos(curX,curY)
																	return list[sel],sel
													end
									end
					end
	end
end
-- Example Usage
term.clear()
term.setCursorPos(1,1)
print("Uber Prison- RevJoes Security Control System")
term.setCursorPos(2,2)
print("Please select Option")
local selection = menu("Activate Holding Shield", "Deactivate Holding Shield", "Electrify Holding Area")
if selection == "Activate Holding Shield" then
	term.clear()
	password = "holder"
	term.setCursorPos(1,1)
	print("Warden Access, Please Enter Security Code:-")
	pass = read("*")
	if pass == password then
	print("Security Code Accepted, Activating Holding Shield")
	redstone.setBundledOutput("bottom",colors.black,true)
	return
	else
	term.clear()
	term.setCursorPos(1,1)
	print("Wrong Code Entered, Alarm Activating")
	sleep(0.5)
	redstone.setBundledOutput("bottom",colors.green,true)
	sleep(3)
	redstone.setBundledOutput("bottom",colors.green,false)
	os.reboot()
	end
elseif selection == "Deactivating Holding Shield" then
	term.clear()
	password = "unhold"
	term.setCursorPos(1,1)
	print("Warden Access, Please Enter Security Code:-")
	pass = read("*")
	if pass == password then
	print("Security Code Accepted, Deactivating Holding Shield")
	redstone.setBundledOutput("bottom",colors.black,false)
	os.reboot()
	else
	term.clear()
	term.setCursorPos(1,1)
	print("Wrong Code Entered, Alarm Activating")
	sleep(0.5)
	redstone.setBundledOutput("bottom",colors.green,true)
	sleep(3)
	redstone.setBundledOutput("bottom",colors.green,false)
	os.reboot()
	end
elseif selection == "Electrify Holding Area" then
	term.clear()
	password = "shock"
	term.setCursorPos(1,1)
	print("Caution This Will Kill All Vulnerable Players In Holding Area")
	term.setCursorPos(2,2)
	print("Warden Access, Please Enter Security Code:-")
	pass = read("*")
	if pass == password then
	print("Security Code Accepted, Frying Bitch's")
	sleep(1)
	local i = 3
	repeat
	redstone.setBundledOutput("bottom",colors.brown,true)
	sleep(2)
	redstone.setBundledOutput("bottom",colors.brown,false)
	i = i + 1
	until i == 3
	os.reboot()
	else
	term.clear()
	term.setCursorPos(1,1)
	print("Wrong Code Entered, Alarm Activating")
	sleep(0.5)
	redstone.setBundledOutput("bottom",colors.green,true)
	sleep(3)
	redstone.setBundledOutput("bottom",colors.green,false)
	os.reboot()
	end
end
Edited on 07 May 2014 - 08:53 PM
Dog #23
Posted 07 May 2014 - 11:09 PM
The more I look at this the more I wonder if another loop is necessary. I may be off base, but it appears to me that breaking the remaining code (after the menu function) down into two other functions (e.g. 'main' and 'doit') would allow the program to do what revjoe wants; and it would give him something similar to 'goto' by calling back to the 'main' function when the 'doit' function completes.

e.g.

local function menu(...)
  <menu function code>
end

local function main()
  <display screen and invoke menu()>
end

local function doit()
  <actions to be done as selected in menu>
  main() --// instead of os.reboot()
end

main()

…or am I throwing a wrench into this?
Edited on 07 May 2014 - 09:10 PM
Bomb Bloke #24
Posted 07 May 2014 - 11:44 PM
So you're saying you'd have "main" call "menu", "menu" call "doit", and "doit" call "main"?

The problem with that is that it leads to recursive calls - which done badly leads to that "ArrayIndexOutOfBoundsException" error you see people asking about all the time. It can be done, but I wouldn't recommend it.

Without looking at the actual script, I would say have "main" call "menu", have "menu" return whatever was selected back to "main", then "main" can call "doit" based on that.
Dog #25
Posted 07 May 2014 - 11:50 PM
So you're saying you'd have "main" call "menu", "menu" call "doit", and "doit" call "main"?

The problem with that is that it leads to recursive calls - which done badly leads to that "ArrayIndexOutOfBoundsException" error you see people asking about all the time. It can be done, but I wouldn't recommend it.
Oh my goodness, no. That's certainly not what I intended…

Without looking at the actual script, I would say have "main" call "menu", have "menu" return whatever was selected back to "main", then "main" can call "doit" based on that.

Currently, his main() would call menu() using a capture variable - then menu (if I understand the code correctly) would return the necessary value to the variable in main() so it can be passed onto doit(). Then instead of calling main() from doit(), it should probably just 'return'…implying main() will need a loop which means main() might have to be broken into two functions. I need to take another look at this.


IMPORTANT: We haven't forgotten you, revjoe - we're just figuring out how best to proceed :)/>


EDIT: I've looked at the code for a bit and I *think* I have a way to approach this, but it's not necessarily pretty. If any of the more experienced Pros have any input, please chime in.

First things first, though. revjoe - in your code you have two variables that you use for handling passwords (password and pass). Currently you aren't localizing those variables which means they are global. A global variable can be read by any program on the machine which is probably not what you want (especially with passwords). I strongly suggest you localize those variables like you have done with some of your other variables. Doing that will make them slightly more secure (emphasis on 'slightly').

I'm reposting your code with all the indentation tightened up so it's easier for everyone to reference.
Spoiler

local function menu(...) -- ver 0.1
  local sel = 1
  local list = {...}
  local offX,offY = term.getCursorPos()
  local curX,curY = term.getCursorPos()
  while true do
    if sel > #list then sel = 1 end
    if sel < 1 then sel = #list end
    for i = 1,#list do
      term.setCursorPos(offX,offY+i-1)
      if sel == i then
        print("["..list[i].."]")
      else
        print(" "..list[i].." ")
      end
    end
    while true do
      local e,e1,e2,e3,e4,e5,e6 = os.pullEvent()
      if e == "key" then
        if e1 == 200 then -- up key
          sel = sel-1
          break
        end
        if e1 == 208 then -- down key
          sel = sel+1
          break
        end
        if e1 == 28 then
          term.setCursorPos(curX,curY)
          return list[sel],sel
        end
      end
    end
  end
end
-- Example Usage
term.clear()
term.setCursorPos(1,1)
print("Uber Prison- RevJoes Security Control System")
term.setCursorPos(2,2)
print("Please select Option")
local selection = menu("Activate Holding Shield", "Deactivate Holding Shield", "Electrify Holding Area")
if selection == "Activate Holding Shield" then
  term.clear()
  password = "holder"
  term.setCursorPos(1,1)
  print("Warden Access, Please Enter Security Code:-")
  pass = read("*")
  if pass == password then
    print("Security Code Accepted, Activating Holding Shield")
    redstone.setBundledOutput("bottom",colors.black,true)
    return
  else
    term.clear()
    term.setCursorPos(1,1)
    print("Wrong Code Entered, Alarm Activating")
    sleep(0.5)
    redstone.setBundledOutput("bottom",colors.green,true)
    sleep(3)
    redstone.setBundledOutput("bottom",colors.green,false)
    os.reboot()
  end
elseif selection == "Deactivating Holding Shield" then
  term.clear()
  password = "unhold"
  term.setCursorPos(1,1)
  print("Warden Access, Please Enter Security Code:-")
  pass = read("*")
  if pass == password then
    print("Security Code Accepted, Deactivating Holding Shield")
    redstone.setBundledOutput("bottom",colors.black,false)
    os.reboot()
  else
    term.clear()
    term.setCursorPos(1,1)
    print("Wrong Code Entered, Alarm Activating")
    sleep(0.5)
    redstone.setBundledOutput("bottom",colors.green,true)
    sleep(3)
    redstone.setBundledOutput("bottom",colors.green,false)
    os.reboot()
  end
elseif selection == "Electrify Holding Area" then
  term.clear()
  password = "shock"
  term.setCursorPos(1,1)
  print("Caution This Will Kill All Vulnerable Players In Holding Area")
  term.setCursorPos(2,2)
  print("Warden Access, Please Enter Security Code:-")
  pass = read("*")
  if pass == password then
    print("Security Code Accepted, Frying Bitch's")
    sleep(1)
    local i = 3
    repeat
      redstone.setBundledOutput("bottom",colors.brown,true)
      sleep(2)
      redstone.setBundledOutput("bottom",colors.brown,false)
      i = i + 1
    until i == 3
    os.reboot()
  else
    term.clear()
    term.setCursorPos(1,1)
    print("Wrong Code Entered, Alarm Activating")
    sleep(0.5)
    redstone.setBundledOutput("bottom",colors.green,true)
    sleep(3)
    redstone.setBundledOutput("bottom",colors.green,false)
    os.reboot()
  end
end
Edited on 08 May 2014 - 12:35 AM
revjoe #26
Posted 12 May 2014 - 03:33 PM
The servers still under constuction so security aint a problem atm with the passwords, but dis is causing me so much hassle ive been trying to read all the lua and computercraft guides i can but still just hittin my head against a brick wall with it lol
Also sorry would have replied sooner but everytime i tried to get on here lately get a cloudfare error
Edited on 12 May 2014 - 01:39 PM
revjoe #27
Posted 12 May 2014 - 04:49 PM
Could it be than rather than trying to make it simpler by having the menu keep the output active it's actually just making it harder. Could I set a rednet output to activate on a remote terminal and then the program to reboot to the start of the menu. Surely the remote terminal would stay active until the menu sent a false or stop command?
revjoe #28
Posted 12 May 2014 - 06:40 PM
Does anyone know where i can put rednet.open(“top”) in the menu code without it causing an error?