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

return execution to calling function

Started by JamiePhonic, 09 January 2013 - 05:09 AM
JamiePhonic #1
Posted 09 January 2013 - 06:09 AM
I've written a program that acts as the client interface to a mainframe i created to control stuff in my Tekkit world, however its not just me that uses it, some of the other players have access to some of the terminals to do stuff like open doors and so on. this has lead to me having to develop a sort of user account system where there is a different password to access each part, e.g. the fortress and the factory, but also a master admin account that has access to everything. what i want to know is how return execution to calling function after im done.
just now, if you enter the password for the fortress controls, the mainframe validates it and tells the computer to go to a function called fortress which has the controls in it, however if you enter the password for the admin account, it takes you to the admin menu, from which you can choose 1 of the 4 options (say you pick option 1, fortress) and from there it calls upon the same function, fortress.
what i want is to be able to return execution to calling function, admin menu from the fortress function or any other if it was admin menu that called it, (if it didn't, it will go back to the login)

i had a look around the lua website but couldn't find anything i understood and Google wasn't much help either.
i'm doubtful that its as simple as using Return (like in visual basic) but i tried it and got nowhere.
theoriginalbit #2
Posted 09 January 2013 - 06:17 AM
If I'm understanding you correctly then there is nothing you need to do. The language takes care of returning to the previous function that was on the stack. example:



function world()
  print( "SD" )
  print( "Y" )
end

function hello()
  print( "S" )
  world()
  print( "SE")
end

hello()
world()
A rough representation of the function calls is
1.
2. hello
3. hello -> world
4. hello
5.
6. world
7.

and the output would be
S
SD
Y
SE
SD
Y
Alekso56 #3
Posted 09 January 2013 - 06:19 AM
And if he is misunderstanding you then http://www.lua.org/pil/5.1.html would explain stuff.
ChunLing #4
Posted 09 January 2013 - 06:46 AM
Lua does use return, but (like all other Lua keywords) it is uncapitalized. Lua does not require that functions use the return keyword to return, though. If the function reaches it's terminating end, then it will return nil and execution will resume from the next statement after the function call.
JamiePhonic #5
Posted 09 January 2013 - 07:03 AM
here is a (rather large) chunk of the code im on about
Spoiler

--factory user menu
function Factory()
while true do
clear()
print ("Logged on as: Factory")
print ("Enter A Number To Perform The Action")
print ("Type 'exit' to log out")
print ("")
print ("1. Power Plant Engines")
print ("2. Quarry")
print ("3. Refinary")
print ("4. Oil Pumps")
print ("5. Water Pumps")
print ("")
write ("Option: ")
option = read ()
  
if option == "exit" then
  login()
end

if option == "1" then
  rednet.send(relayID, "power_plant_engines")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Power Plant Engines Are " .. responce)
  end
  sleep(2)

elseif option == "2" then
  rednet.send(relayID, "quarry")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Quarry Is " .. responce)
  end
  sleep(2)
elseif option == "3" then
  rednet.send(relayID, "refinary")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Refinary Is " .. responce)
  end
  sleep(2)
elseif option == "4" then
  rednet.send(relayID, "oil_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Oil Pumps are " .. responce)
  end
  sleep(2)

elseif option == "5" then
  rednet.send(relayID, "water_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Water Pumps are " .. responce)
  end
  sleep(2)
end
	end
end
--arena user menu
function Arena()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--banking user menu
function Bank()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--main menu for admins
function AdminMenu()
while true do
clear()
print ("Logged on as: Admin")
print ("Enter A Number To Perform The Action")
print ("Type exit to log off")
print ("")
print ("1. Fortress")
print ("2. Factory")
print ("3. Arena")
print ("4. Bank")
print ("")
write ("Option: ")

option = read ()
  
if option == "exit" then
  print ("Logging Off.")
  sleep(2)
  os.shutdown()
end
if option == "1" then
  Fortress()
elseif option == "2" then
  Factory()
elseif option == "3" then
  Arena()
elseif option == "4" then
  Bank()
end --end if
end --end while loop
end
--Login function
function login()
--check if the server is avalable
while true do
  clear()
  sp = textutils.slowPrint
  sp("Connecting To Mainframe...")
  rednet.broadcast("relay") --check if relay server is on
  relayid, responce = rednet.receive(2) --wait for responce from server
  sleep(2)
  if responce == nil then --if the variable "responce" is "nil"
   term.setCursorPos(27,1)
   sp("Connection Failed.") --append to the end of "connecting to mainframe..."
   sp("Error 1: Failed To Connect To A Local Relay Server")
   sp("Try again later or notify the admin: JamiePhonic")
   print("")
   sleep(1)
   sp("Shutting Down: 5") --Print "shutting down: 5"
   sleep(1) --sleep for a second
   term.setCursorPos(1,4) --set cursor pos to line 4, character 1
   print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 3")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 2")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 1")
   sleep(1)
   os.shutdown() --shut the system down
   else --if the variable "responce" is not nil,
   term.setCursorPos(27,1)
   sp("Connected!") --append to the end of "connecting to mainframe..."
   print("")
   sleep(2)
  end --end if

--request/validate Password
  tries = 5 --set the number of tries
  write ("password: ")
  for triescnt = 1,tries,1 do
   password = read ()
   rednet.send(relayID, "CheckPass")
   local senderID, confirm = rednet.receive(2)
   sleep(0.2)
   if confirm == nil then
	print("Server Failed To Reply")
	else
	rednet.send(relayID, password)
	local senderID, responce = rednet.receive(2)
	 if responce == ("admin") then --if responce = admin
	  print("")
	  print("Welcome Admin!")
	  sleep(2)
	  AdminMenu()
	  break
	 elseif responce == ("fortress") then --if responce = user
	  print("")
	  print("Welcome to the Fortress!")
	  sleep(2)
	  Fortress()
	  break
	 elseif responce == ("factory") then --if responce = user
	  print("")
	  print("Welcome to the factory!")
	  sleep(2)
	  Factory()
	  break
	 elseif responce == ("arena") then --if responce = user
	  print("")
	  print("Welcome to the arena!")
	  sleep(2)
	  Arena()
	  break
	 elseif responce == ("bank") then --if responce = user
	  print("")
	  print("Welcome to the bank!")
	  sleep(2)
	  Bank()
	  break
	 else --otherwise
	  term.setCursorPos(1,3)
	  print ("Access Denied! Server responded with: ",responce)
	  print ("you have ",tries-triescnt," Tries left")
	  print ("")
	  term.clearLine(5)
	  write ("password: ")
	 end --end function call
	if triescnt == tries then --if tries=triescnt
	 print ("Access Denied!") --display denied message
	 sleep(1)
	 os.shutdown() --shutdown the system
	end --end password tries loop
   end --end responce check if
  end --end for loop
end --end while
end --end function
where:

if option == "exit" then
  login()
end
appears is where i want it to return to its calling function instead of the one i specified
remiX #6
Posted 09 January 2013 - 07:15 AM
Try using return, replace it with login()
ChunLing #7
Posted 09 January 2013 - 07:17 AM
Yeah, don't do that. Don't try to get back to the calling function by calling it from the end of the function it called.

That will just recurse your code, and eventually overflow the stack.

Just let the called function end, and Lua will return nil and resume execution of the statements following that function's call.
JamiePhonic #8
Posted 09 January 2013 - 07:45 AM
i tried using return, but all it does is start the function again, break does the same.
i'm assuming no one has read the code because the

if option == "exit" then
  login()
end
part is inside a while loop.
i tried

if option == "exit" then
  break
end
the putting return outside the loop, but no change
Lyqyd #9
Posted 09 January 2013 - 08:46 AM
I read the code. Changing it to return rather than login() should fix it. If it doesn't, post the updated full code with those changes.
JamiePhonic #10
Posted 09 January 2013 - 09:11 AM
I read the code. Changing it to return rather than login() should fix it. If it doesn't, post the updated full code with those changes.
i replaced login() with return (that's all i changed from the original code i posted)
still no change, it just seems to refresh the screen.
Alekso56 #11
Posted 09 January 2013 - 01:02 PM
I read the code. Changing it to return rather than login() should fix it. If it doesn't, post the updated full code with those changes.
i replaced login() with return (that's all i changed from the original code i posted)
still no change, it just seems to refresh the screen.

it's obvious that the function isn't loaded into memory, try putting the functions at the start of the code.
ChunLing #12
Posted 09 January 2013 - 05:59 PM
If you want people to read the entire code then post the entire code.

I suspect that part of the problem is that you use a lot of reboot commands to restart the program rather than having the main program body loop normally. So if a function doesn't "return" to the calling function by calling the calling function, then the calling function just ends and a reboot command resets everything.

But using functions the way you're using them is fundamentally flawed, and it does cause significant problems. However much you need to restructure your code to eliminate this kind of abuse of the stack, you need to do it.
JamiePhonic #13
Posted 10 January 2013 - 06:20 AM
OK, here is the whole, full, client software.
Spoiler

-- CLIENT SOFTWARE
relayID=0
--clear screen function (lazyness)
function clear()
term.clear()
term.setCursorPos(1,1)
end
--fortress user menu
function Fortress()
while true do
clear()
print ("Logged on as: Fortress")
print ("Enter A Number To Perform The Action")
print ("Type 'exit' to log out")
print ("")
print ("1. Toggle Waterfall")
print ("2. Toggle Waterfall Lights")
print ("3. Basement Door")
print ("4. TNT Store Room Door")
print ("5. Back Corridor")
print ("")
write ("Option: ")
option = read ()
  
if option == "back" then
  login()
end
if option == "1" then
  rednet.send(relayID, "toggle_waterfall")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Waterfall Is " .. responce)
  end
sleep(2)
elseif option == "2" then
  rednet.send(relayID, "toggle_waterfall_lights")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Waterfall Lights Are " .. responce)
  end
  sleep(2)
  
elseif option == "3" then
  rednet.send(relayID, "basement_door")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Basement Door Is " .. responce)
  end
  sleep(2)

elseif option == "4" then
  rednet.send(relayID, "TNT_store")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("TNT Room Door Is " .. responce)
  end
  sleep(2)

elseif option == "5" then
  rednet.send(relayID, "admin_area")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Back Corridor " .. responce)
  end
  sleep(2)
  end
end
end
--factory user menu
function Factory()
while true do
clear()
print ("Logged on as: Factory")
print ("Enter A Number To Perform The Action")
print ("Type 'exit' to log out")
print ("")
print ("1. Power Plant Engines")
print ("2. Quarry")
print ("3. Refinary")
print ("4. Oil Pumps")
print ("5. Water Pumps")
print ("")
write ("Option: ")
option = read ()
  
if option == "exit" then
  login()
end

if option == "1" then
  rednet.send(relayID, "power_plant_engines")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Power Plant Engines Are " .. responce)
  end
  sleep(2)

elseif option == "2" then
  rednet.send(relayID, "quarry")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Quarry Is " .. responce)
  end
  sleep(2)
elseif option == "3" then
  rednet.send(relayID, "refinary")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Refinary Is " .. responce)
  end
  sleep(2)
elseif option == "4" then
  rednet.send(relayID, "oil_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Oil Pumps are " .. responce)
  end
  sleep(2)

elseif option == "5" then
  rednet.send(relayID, "water_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Water Pumps are " .. responce)
  end
  sleep(2)
end
	end
end
--arena user menu
function Arena()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--banking user menu
function Bank()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--main menu for admins
function AdminMenu()
while true do
clear()
print ("Logged on as: Admin")
print ("Enter A Number To Perform The Action")
print ("Type exit to log off")
print ("")
print ("1. Fortress")
print ("2. Factory")
print ("3. Arena")
print ("4. Bank")
print ("")
write ("Option: ")

option = read ()
  
if option == "exit" then
  print ("Logging Off.")
  sleep(2)
  os.shutdown()
end
if option == "1" then
  Fortress()
elseif option == "2" then
  Factory()
elseif option == "3" then
  Arena()
elseif option == "4" then
  Bank()
end --end if
end --end while loop
end
--Login function
function login()
--check if the server is avalable
while true do
  clear()
  sp = textutils.slowPrint
  sp("Connecting To Mainframe...")
  rednet.broadcast("relay") --check if relay server is on
  relayid, responce = rednet.receive(2) --wait for responce from server
  sleep(2)
  if responce == nil then --if the variable "responce" is "nil"
   term.setCursorPos(27,1)
   sp("Connection Failed.") --append to the end of "connecting to mainframe..."
   sp("Error 1: Failed To Connect To A Local Relay Server")
   sp("Try again later or notify the admin: JamiePhonic")
   print("")
   sleep(1)
   sp("Shutting Down: 5") --Print "shutting down: 5"
   sleep(1) --sleep for a second
   term.setCursorPos(1,4) --set cursor pos to line 4, character 1
   print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 3")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 2")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 1")
   sleep(1)
   os.shutdown() --shut the system down
   else --if the variable "responce" is not nil,
   term.setCursorPos(27,1)
   sp("Connected!") --append to the end of "connecting to mainframe..."
   print("")
   sleep(2)
  end --end if

--request/validate Password
  tries = 5 --set the number of tries
  write ("password: ")
  for triescnt = 1,tries,1 do
   password = read ()
   rednet.send(relayID, "CheckPass")
   local senderID, confirm = rednet.receive(2)
   sleep(0.2)
   if confirm == nil then
	print("Server Failed To Reply")
	else
	rednet.send(relayID, password)
	local senderID, responce = rednet.receive(2)
	 if responce == ("admin") then --if responce = admin
	  print("")
	  print("Welcome Admin!")
	  sleep(2)
	  AdminMenu()
	  break
	 elseif responce == ("fortress") then --if responce = user
	  print("")
	  print("Welcome to the Fortress!")
	  sleep(2)
	  Fortress()
	  break
	 elseif responce == ("factory") then --if responce = user
	  print("")
	  print("Welcome to the factory!")
	  sleep(2)
	  Factory()
	  break
	 elseif responce == ("arena") then --if responce = user
	  print("")
	  print("Welcome to the arena!")
	  sleep(2)
	  Arena()
	  break
	 elseif responce == ("bank") then --if responce = user
	  print("")
	  print("Welcome to the bank!")
	  sleep(2)
	  Bank()
	  break
	 else --otherwise
	  term.setCursorPos(1,3)
	  print ("Access Denied! Server responded with: ",responce)
	  print ("you have ",tries-triescnt," Tries left")
	  print ("")
	  term.clearLine(5)
	  write ("password: ")
	 end --end function call
	if triescnt == tries then --if tries=triescnt
	 print ("Access Denied!") --display denied message
	 sleep(1)
	 os.shutdown() --shutdown the system
	end --end password tries loop
   end --end responce check if
  end --end for loop
end --end while
end --end function
--Program Starts! detect if a modem is attached, if it is, enable it
if peripheral.getType("top") == "modem" then
rednet.open("top")
login()
elseif peripheral.getType("back") == "modem" then
rednet.open("back")
login()
elseif peripheral.getType("left") == "modem" then
rednet.open("left")
login()
elseif peripheral.getType("right") == "modem" then
rednet.open("right")
login()
elseif peripheral.getType("bottom") == "modem" then
rednet.open("bottom")
login()
else
sp = textutils.slowPrint
clear()
print("Please Connect A Modem And Try Again.")
print("")
sleep(1)
sp("Shutting Down: 5") --Print "shutting down: 5"
sleep(1) --sleep for half a second
term.setCursorPos(1,3) --set cursor pos to line 4, character 1
print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 3")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 2")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 1")
sleep(1)
os.shutdown() --shut the system down
end
i would appreciate it if you at least looked at it before you replied, i know its a mess and its not the cleanest code, but for a server that rarely sees 5 players and is rebooted (the whole machine) almost every night, it does the job.
Lyqyd #14
Posted 10 January 2013 - 06:33 AM
The problem is that you still have login() for your exit options!
JamiePhonic #15
Posted 10 January 2013 - 06:37 AM
The problem is that you still have login() for your exit options!
that is the raw unmodified code. what i am using now until i find a solution that works
Lyqyd #16
Posted 10 January 2013 - 06:41 AM
The problem is that you still have login() for your exit options!
that is the raw unmodified code. what i am using now until i find a solution that works

And the solution is to replace both of those instances of login() with return. There's nothing in your code that would cause the "ignore the return and keep looping in that menu" behavior you've described if you made that change, which is why we want to see the code with those modifications.
JamiePhonic #17
Posted 10 January 2013 - 07:41 AM
modified code with login() replaced with return
Spoiler

-- CLIENT SOFTWARE
relayID=0
--clear screen function (lazyness)
function clear()
term.clear()
term.setCursorPos(1,1)
end
--fortress user menu
function Fortress()
while true do
clear()
print ("Logged on as: Fortress")
print ("Enter A Number To Perform The Action")
print ("Type 'exit' to log out")
print ("")
print ("1. Toggle Waterfall")
print ("2. Toggle Waterfall Lights")
print ("3. Basement Door")
print ("4. TNT Store Room Door")
print ("5. Back Corridor")
print ("")
write ("Option: ")
option = read ()
  
if option == "back" then
  return
end
if option == "1" then
  rednet.send(relayID, "toggle_waterfall")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Waterfall Is " .. responce)
  end
sleep(2)
elseif option == "2" then
  rednet.send(relayID, "toggle_waterfall_lights")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Waterfall Lights Are " .. responce)
  end
  sleep(2)
  
elseif option == "3" then
  rednet.send(relayID, "basement_door")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Basement Door Is " .. responce)
  end
  sleep(2)

elseif option == "4" then
  rednet.send(relayID, "TNT_store")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("TNT Room Door Is " .. responce)
  end
  sleep(2)
 
elseif option == "5" then
  rednet.send(relayID, "admin_area")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Back Corridor " .. responce)
  end
  sleep(2)
  end
end
end
--factory user menu
function Factory()
while true do
clear()
print ("Logged on as: Factory")
print ("Enter A Number To Perform The Action")
print ("Type 'exit' to log out")
print ("")
print ("1. Power Plant Engines")
print ("2. Quarry")
print ("3. Refinary")
print ("4. Oil Pumps")
print ("5. Water Pumps")
print ("")
write ("Option: ")
option = read ()
  
if option == "exit" then
  return
end

if option == "1" then
  rednet.send(relayID, "power_plant_engines")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Power Plant Engines Are " .. responce)
  end
  sleep(2)
 
elseif option == "2" then
  rednet.send(relayID, "quarry")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Quarry Is " .. responce)
  end
  sleep(2)
elseif option == "3" then
  rednet.send(relayID, "refinary")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Refinary Is " .. responce)
  end
  sleep(2)
elseif option == "4" then
  rednet.send(relayID, "oil_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Oil Pumps are " .. responce)
  end
  sleep(2)
 
elseif option == "5" then
  rednet.send(relayID, "water_pump")
  local senderID, responce = rednet.receive(2)
  sleep(0.2)
  clear()
  if responce == nil then
  print("Server Sent No Responce!")
  print("Perhaps it's busy?")
  else
  print("Water Pumps are " .. responce)
  end
  sleep(2)
end
    end
end
--arena user menu
function Arena()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--banking user menu
function Bank()
clear()
print ("NOT AVALABLE")
sleep(2)
os.reboot()
end
--main menu for admins
function AdminMenu()
while true do
clear()
print ("Logged on as: Admin")
print ("Enter A Number To Perform The Action")
print ("Type exit to log off")
print ("")
print ("1. Fortress")
print ("2. Factory")
print ("3. Arena")
print ("4. Bank")
print ("")
write ("Option: ")

option = read ()
  
if option == "exit" then
  return
end
if option == "1" then
  Fortress()
elseif option == "2" then
  Factory()
elseif option == "3" then
  Arena()
elseif option == "4" then
  Bank()
end --end if
end --end while loop
end
--Login function
function login()
--check if the server's avalable
while true do
  clear()
  sp = textutils.slowPrint
  sp("Connecting To Mainframe...")
  rednet.broadcast("relay") --check if relay server is on
  relayid, responce = rednet.receive(2) --wait for responce from server
  sleep(2)
  if responce == nil then --if the variable "responce" is "nil"
   term.setCursorPos(27,1)
   sp("Connection Failed.") --append to the end of "connecting to mainframe..."
   sp("Error 1: Failed To Connect To A Local Relay Server")
   sp("Try again later or notify the admin: JamiePhonic")
   print("")
   sleep(1)
   sp("Shutting Down: 5") --Print "shutting down: 5"
   sleep(1) --sleep for a second
   term.setCursorPos(1,4) --set cursor pos to line 4, character 1
   print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 3")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 2")
   sleep(1)
   term.setCursorPos(1,4)
   print("Shutting Down: 1")
   sleep(1)
   os.shutdown() --shut the system down
   else --if the variable "responce" is not nil,
   term.setCursorPos(27,1)
   sp("Connected!") --append to the end of "connecting to mainframe..."
   print("")
   sleep(2)
  end --end if
 
--request/validate Password
  tries = 5 --set the number of tries
  write ("password: ")
  for triescnt = 1,tries,1 do
   password = read ()
   rednet.send(relayID, "CheckPass")
   local senderID, confirm = rednet.receive(2)
   sleep(0.2)
   if confirm == nil then
    print("Server Failed To Reply")
    else
    rednet.send(relayID, password)
    local senderID, responce = rednet.receive(2)
	 if responce == ("admin") then --if responce = admin
	  print("")
	  print("Welcome Admin!")
	  sleep(2)
	  AdminMenu()
	  break
	 elseif responce == ("fortress") then --if responce = user
	  print("")
	  print("Welcome to the Fortress!")
	  sleep(2)
	  Fortress()
	  break
	 elseif responce == ("factory") then --if responce = user
	  print("")
	  print("Welcome to the factory!")
	  sleep(2)
	  Factory()
	  break
	 elseif responce == ("arena") then --if responce = user
	  print("")
	  print("Welcome to the arena!")
	  sleep(2)
	  Arena()
	  break
	 elseif responce == ("bank") then --if responce = user
	  print("")
	  print("Welcome to the bank!")
	  sleep(2)
	  Bank()
	  break
	 else --otherwise
	  term.setCursorPos(1,3)
	  print ("Access Denied! Server responded with: ",responce)
	  print ("you have ",tries-triescnt," Tries left")
	  print ("")
	  term.clearLine(5)
	  write ("password: ")
	 end --end function call
    if triescnt == tries then --if tries=triescnt
	 print ("Access Denied!") --display denied message
	 sleep(1)
	 os.shutdown() --shutdown the system
    end --end password tries loop
   end --end responce check if
  end --end for loop
end --end while
end --end function
--Program Starts! detect if a modem is attached, if it is, enable it
if peripheral.getType("top") == "modem" then
rednet.open("top")
login()
elseif peripheral.getType("back") == "modem" then
rednet.open("back")
login()
elseif peripheral.getType("left") == "modem" then
rednet.open("left")
login()
elseif peripheral.getType("right") == "modem" then
rednet.open("right")
login()
elseif peripheral.getType("bottom") == "modem" then
rednet.open("bottom")
login()
else
sp = textutils.slowPrint
clear()
print("Please Connect A Modem And Try Again.")
print("")
sleep(1)
sp("Shutting Down: 5") --Print "shutting down: 5"
sleep(1) --sleep for half a second
term.setCursorPos(1,3) --set cursor pos to line 4, character 1
print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 3")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 2")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 1")
sleep(1)
os.shutdown() --shut the system down
end
video that shows the result (box.com shared link, 126 MB in 1 file(s):https://www.box.com/shared/static/dsbg1kf3xlygcqp5d558.avi
126 MB because my monitor runs at 1080p nativley, video was recorded with fraps at 1/2 size.
ChunLing #18
Posted 10 January 2013 - 09:10 AM
Here is your main program structure:
if peripheral.getType("top") == "modem" then
rednet.open("top")
login()
elseif peripheral.getType("back") == "modem" then
rednet.open("back")
login()
elseif peripheral.getType("left") == "modem" then
rednet.open("left")
login()
elseif peripheral.getType("right") == "modem" then
rednet.open("right")
login()
elseif peripheral.getType("bottom") == "modem" then
rednet.open("bottom")
login()
else
sp = textutils.slowPrint
clear()
print("Please Connect A Modem And Try Again.")
print("")
sleep(1)
sp("Shutting Down: 5") --Print "shutting down: 5"
sleep(1) --sleep for half a second
term.setCursorPos(1,3) --set cursor pos to line 4, character 1
print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 3")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 2")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 1")
sleep(1)
os.shutdown() --shut the system down
end
It doesn't loop, except by shutting down the computer. You need to put a loop in your main program, otherwise exiting functions properly will put the execution back on an inexorable path to inevitable shutdown.

Loop your main program, don't emulate a loop by recursing functions. That's not what recursion is for, and sooner or later you will overflow the stack (or worse).
JamiePhonic #19
Posted 10 January 2013 - 10:21 AM
Here is your main program structure:
if peripheral.getType("top") == "modem" then
rednet.open("top")
login()
elseif peripheral.getType("back") == "modem" then
rednet.open("back")
login()
elseif peripheral.getType("left") == "modem" then
rednet.open("left")
login()
elseif peripheral.getType("right") == "modem" then
rednet.open("right")
login()
elseif peripheral.getType("bottom") == "modem" then
rednet.open("bottom")
login()
else
sp = textutils.slowPrint
clear()
print("Please Connect A Modem And Try Again.")
print("")
sleep(1)
sp("Shutting Down: 5") --Print "shutting down: 5"
sleep(1) --sleep for half a second
term.setCursorPos(1,3) --set cursor pos to line 4, character 1
print("Shutting Down: 4") --repeat, subrtacting 1 from the timer each time
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 3")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 2")
sleep(1)
term.setCursorPos(1,3)
print("Shutting Down: 1")
sleep(1)
os.shutdown() --shut the system down
end
It doesn't loop, except by shutting down the computer. You need to put a loop in your main program, otherwise exiting functions properly will put the execution back on an inexorable path to inevitable shutdown.

Loop your main program, don't emulate a loop by recursing functions. That's not what recursion is for, and sooner or later you will overflow the stack (or worse).
ok, taking that into account, would this make a better main program (merging what you quoted above with the login function) or would i be better swapping the main program with the login function and just calling the code that opens rednet as a function instead since it only needs to run once?
(the code that shows the shutdown message and timer on the event of a failure has been moved to a function named shutdown()
Spoiler

while true do
--Program Starts! detect if a modem is attached, if it is, enable it
if peripheral.getType("top") == "modem" then
  rednet.open("top")
  elseif peripheral.getType("back") == "modem" then
  rednet.open("back")
  elseif peripheral.getType("left") == "modem" then
  rednet.open("left")
  elseif peripheral.getType("right") == "modem" then
  rednet.open("right")
  elseif peripheral.getType("bottom") == "modem" then
  rednet.open("bottom")
  else
  clear()
  print("Please Connect A Modem And Try Again.")
  print("")
  sleep(1)
  shutdown()
end
clear()
sp("Connecting To Mainframe...")
rednet.broadcast("relay") --check if relay server is on
relayid, responce = rednet.receive(2) --wait for responce from server
sleep(2)
if responce == nil then --if the variable "responce" is "nil"
  term.setCursorPos(27,1)
  sp("Connection Failed.") --append to the end of "connecting to mainframe..."
  sp("Error 1: Failed To Connect To A Local Relay Server")
  sp("Try again later or notify the admin: JamiePhonic")
  print("")
  sleep(1)
  shutdown()
  else --if the variable "responce" is not nil,
  term.setCursorPos(27,1)
  sp("Connected!") --append to the end of "connecting to mainframe..."
  print("")
  sleep(2)
end --end if

--request/validate Password
tries = 5 --set the number of tries
write ("password: ")
for triescnt = 1,tries,1 do
  password = read ()
  rednet.send(relayID, "CheckPass")
  local senderID, confirm = rednet.receive(2)
  sleep(0.2)
  if confirm == nil then
   print("Server Failed To Reply")
   else
   rednet.send(relayID, password)
   local senderID, responce = rednet.receive(2)
	if responce == ("admin") then --if responce = admin
	 print("")
	 print("Welcome Admin!")
	 sleep(2)
	 AdminMenu()
	 break
	elseif responce == ("fortress") then --if responce = user
	 print("")
	 print("Welcome to the Fortress!")
	 sleep(2)
	 Fortress()
	 break
	elseif responce == ("factory") then --if responce = user
	 print("")
	 print("Welcome to the factory!")
	 sleep(2)
	 Factory()
	 break
	elseif responce == ("arena") then --if responce = user
	 print("")
	 print("Welcome to the arena!")
	 sleep(2)
	 Arena()
	 break
	elseif responce == ("bank") then --if responce = user
	 print("")
	 print("Welcome to the bank!")
	 sleep(2)
	 Bank()
	 break
	else --otherwise
	 term.setCursorPos(1,3)
	 print ("Access Denied! Server responded with: ",responce)
	 print ("you have ",tries-triescnt," Tries left")
	 print ("")
	 term.clearLine(5)
	 write ("password: ")
	end --end function call
   if triescnt == tries then --if tries=triescnt
	print ("Access Denied!") --display denied message
	sleep(1)
	os.shutdown() --shutdown the system
   end --end password tries loop
  end --end responce check if
end --end for loop
end --end while

EDIT: i just face desk'd so hard i broke my desk. i had a quick skim through the code, the updated version i posted above works, i found the problem, in the all the functions, it prints "type exit to logout", the reason it wasn't working is because the part of the code that checks to see if you typed exit was actually looking for "back" instead in the fortress function(the one i tested with), and exit in another (the factory)

now that's sorted, i'm away to get a new desk :-)
ChunLing #20
Posted 10 January 2013 - 10:38 AM
Hmm…yeah, probably login would make a better main program, and the modem check probably should be rewritten as a function with a boolean return.

As written, login seems to like shutting down, taking everything into account. But that seems intentional.
JamiePhonic #21
Posted 10 January 2013 - 10:44 AM
Hmm…yeah, probably login would make a better main program, and the modem check probably should be rewritten as a function with a boolean return.

As written, login seems to like shutting down, taking everything into account. But that seems intentional.
it is intentional, the login function only shuts down the computer on any 1 of 3 occasions.
1. if no modem is detected
2. if the server connects to a relay, but gets no response from the central server to validate a password
3. if a wrong password is entered 5 times

the code i posted above is now what im using. (and it works)
ChunLing #22
Posted 10 January 2013 - 08:25 PM
You also have several of the selectable functions that do nothing but print a warning and shutdown the computer.

Hmm…that last program is a little odd. You've put everything inside of a big loop, but you always shutdown before looping. Maybe you could just reset triescnt to 1 after a successful login (so that valid users aren't treated as having used up a password attempt). Extending a for loop this way isn't exactly usual, but is perfectly acceptable.

On the other hand, working is working.