This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
Keeping A Function Active Help
Started by revjoe, 07 May 2014 - 04:50 PMPosted 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.
Posted 07 May 2014 - 06:58 PM
Please post your code so we can see "what's wrong".
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
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)
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
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
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:
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.
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.
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.
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.
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.
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
This could greatly help you in understanding Lua control structures http://lua-users.org/wiki/ControlStructureTutorial
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
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
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
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.
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?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
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.
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
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(…)
Posted 07 May 2014 - 08:58 PM
offtopic
You are basically right but…Snip
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
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?
Posted 07 May 2014 - 09:11 PM
that call works perfectly for me tho, its a workaround the goto command i need.
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()sPosted 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, 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.
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
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.
…or am I throwing a wrench into this?
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
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.
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.
Posted 07 May 2014 - 11:50 PM
Oh my goodness, no. That's certainly not what I intended…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.
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
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
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
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?
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?