Posted 20 November 2012 - 11:59 AM
I am currently working on a Command & Control computer program that facilitates the setting of states of items around our base area, such as piston drawbridges and wireless melee turtles. This computer has two buttons and a monitor, and displays the states of various items.
So far I have able to overcome various bugs and such, but this one is really proving to be troublesome.
I appear to be having issues with my program not sensing inputs; IE i press the button and the program does nothing, 1 out of 4 times. The best solution would be to set an event to halt the program until that button is pressed, but its not practical as this program also is listening for RedNet messages, and responding with the proper state.
I am having a similar issue with RedNet computers not receiving messages, as I set a short timeout period for rednet.receive() so the program can deal with other inputs, such as a tripwire triggering a melee turtle to attack. The problem is solved on the piston drawbridge control computer, as it only receives during its main loop, so an infinite timeout period is practical.
Here is my code: (please be forgiving, I'm a LUA noob :(/>/>)
Command & Control Computer:
Drawbridge Control Computer:
And for kicks, the Wireless Melee Turtle (or as I have nicknamed them TurtleDrones) Control Program:
In my efforts to come up with a solution, I theorized that if I split off the button inputs into another computer that could have a dedicated button input, sending rednet signals to the C&C comp when buttons were pressed, enabling the C&C comp to work with infinite timeouts. This really wouldn't work with the Turtle's though…
Thanks in advance for the help!
EDIT: Its not really a LUA problem, its more of a question. Maybe now I might get some help.
So far I have able to overcome various bugs and such, but this one is really proving to be troublesome.
I appear to be having issues with my program not sensing inputs; IE i press the button and the program does nothing, 1 out of 4 times. The best solution would be to set an event to halt the program until that button is pressed, but its not practical as this program also is listening for RedNet messages, and responding with the proper state.
I am having a similar issue with RedNet computers not receiving messages, as I set a short timeout period for rednet.receive() so the program can deal with other inputs, such as a tripwire triggering a melee turtle to attack. The problem is solved on the piston drawbridge control computer, as it only receives during its main loop, so an infinite timeout period is practical.
Here is my code: (please be forgiving, I'm a LUA noob :(/>/>)
Command & Control Computer:
Spoiler
--Base Command and Control Script v0.5
--************************************************************************************
--Variables for setting
--************************************************************************************
local modemside = "back" --side with the modem on it
local baseID = "b01" --Base ID
local defaultstate = "auto" --default turtledrone status (passive/aggressive/auto)
local defaultdrawbridge = "down" --default drawbridge status (up/down)
--************************************************************************************
--Initialize Variables
local turtdronestate = defaultstate
local drawbridgestate = defaultdrawbridge
local error = "none"
--Get Monitor Perhperal
mon = peripheral.wrap("top") --aquires monitor object
mX, mY = mon.getSize() --gets size of monitor
--************************************************************************************
--Define functions
--************************************************************************************
--split RedNet messages into base, header, and content
function RedNetSplit(message)
if message==nil then --string.sub doesn't like nil; cant conicate nil
local base = "000"
local header = "herpderp"
local content = "herpderp"
return base,header,content
else
print(id.." "..message)
local base = string.sub(message, 1, 3)
local header = string.sub(message, 4, 11)
local content = string.sub(message, 12)
return base,header,content
end
end
--update monitor with information
function UpdateMonitor(turtledrone, drawbridge)
mon.clear()
mon.setCursorPos(1,1)
mon.write("TurtleDrone Status: "..turtledrone)
mon.setCursorPos(1,2)
mon.write("Drawbridge Status: "..drawbridge)
--Labels for buttons
mon.setCursorPos(1, mY - 1) --set cursor to one line above bottom
mon.write("TurtleDrones")
mon.setCursorPos(mX - 11, mY - 1) --set cursor to one line above bottom and move it over the number of characters
mon.write("Drawbridges")
--update left button with next state
mon.setCursorPos(1,mY)
if turtledrone == "auto" then
mon.write("Left:Set Passive")
elseif turtledrone == "passive" then
mon.write("Left:Set Aggressive")
elseif turtledrone == "aggressive" then
mon.write("Left:Set Auto")
end
--update right button with next state
mon.setCursorPos(mX - 8, mY) --put the cursor in the bottom right, and move it over the number of characters in the string
if drawbridge == "up" then
mon.write("DN :Right")
elseif drawbridge == "down" then
mon.write("UP :Right")
end
print("Monitor Updated") --debug
end
--************************************************************************************
--end functions
--************************************************************************************
--************************************************************************************
--boot sequence
--************************************************************************************
term.clear() --clear terminal
term.setCursorPos(1,1)
mon.clear() --clear monitor
mon.setCursorPos(1,1)
print("Monitor x:"..mX.." Monitor y: "..mY)
mon.write("Base Control Computer v0.5")
mon.setCursorPos(1,2)
mon.write("Booting... ")
sleep(0.5)
mon.write("Please Wait...")
sleep(2)
mon.setCursorPos(1,3)
mon.write("Enabling RedNet...")
if peripheral.getType(modemside)=="modem" then --if a modem is on the side indicated
rednet.open(modemside) --then turn it on!
sleep(0.5)
mon.write("OK")
else --uh oh, no modem
sleep(0.5)
mon.write("ERROR!")
mon.setCursorPos(1,4)
mon.write("ERROR: Modem not Found on side "..modemside)
quit() --this doesn't work as its supposed to, but it does error out the console and stops the program so 'meh'
end
sleep(2)
mon.setCursorPos(1,4)
mon.write("Finding Repeaters...")
--Ping script goes here
mon.write("Disabled")
sleep(2)
--Set Default State for TurtleDrones
mon.setCursorPos(1,5)
mon.write("Turtle default set to "..defaultstate)
sleep(0.5)
mon.setCursorPos(1,6)
mon.write("Setting TurtleDrones to "..defaultstate.."...")
turtdronestate = defaultstate
rednet.broadcast(baseID.."turtdron"..turtdronestate)
print("sent "..baseID.."turtdron"..turtdronestate)
sleep(0.5)
mon.setCursorPos(1,7)
mon.write("Done")
sleep(2)
--Set default state for drawbridges
mon.setCursorPos(1,8)
mon.write("Drawbridges set to default "..defaultdrawbridge)
sleep(0.5)
mon.setCursorPos(1,9)
mon.write("Setting Drawbridges to "..defaultdrawbridge.."...")
drawbridgestate = defaultdrawbridge
rednet.broadcast(baseID.."drawbrid"..drawbridgestate)
print("sent "..baseID.."drawbrid"..drawbridgestate)
sleep(0.5)
mon.setCursorPos(1,10)
mon.write("Done")
sleep(2)
--************************************************************************************
--end boot sequence
--************************************************************************************
mon.clear() --clear monitor
mon.setCursorPos(1,1)
UpdateMonitor(turtdronestate, drawbridgestate) --update the monitor before looping
--************************************************************************************
--Main Loop
--************************************************************************************
while true do
sleep(0)
--Listen for messages
id,message = rednet.receive(1)
base,header,content = RedNetSplit(message)
if base==baseID and header=="commctrl" then
--Respond to Pings
if content=="PING" then
rednet.send(id,baseID..header.."PONG")
print("sent PONG")
--Respond to TurtleDrones requesting state
elseif content=="requeststatus" then
rednet.broadcast(baseID.."turtdron"..turtdronestate)
print("TurtleDrone requested status")
--respond to drawbridge control requesting state
elseif content=="drawbridgestatus" then
rednet.broadcast(baseID.."drawbrid"..drawbridgestate)
print("Drawbridge Control Requested status")
end
end
--Left button toggles TurtleDrone state
if redstone.getInput("left") and not redstone.getInput("right") then
if turtdronestate == "auto" then
turtdronestate = "passive"
elseif turtdronestate == "passive" then
turtdronestate = "aggressive"
elseif turtdronestate == "aggressive" then
turtdronestate = "auto"
else
print("invalid state reached! Defaulting to auto!")
turtdronestate = "auto"
end
rednet.broadcast(baseID.."turtdron"..turtdronestate)
print("sent "..baseID.."turtdron"..turtdronestate)
UpdateMonitor(turtdronestate, drawbridgestate)
sleep(2)
end
--Right button toggles Drawbridge state
if redstone.getInput("right") and not redstone.getInput("left") then
if drawbridgestate=="up" then
drawbridgestate = "down"
elseif drawbridgestate=="down" then
drawbridgestate = "up"
end
rednet.broadcast(baseID.."drawbrid"..drawbridgestate)
print("sent "..baseID.."drawbrid"..drawbridgestate)
UpdateMonitor(turtdronestate, drawbridgestate)
sleep(2)
end
end
--************************************************************************************
--end main loop
--************************************************************************************
--print error that caused loop to end
mon.clear() --clear monitor
mon.setCursorPos(1,1)
mon.write(error)
--turn off modem before you go!
rednet.close(modemside)
Drawbridge Control Computer:
Spoiler
--Drawbridge control comp v0.3
--Configureable variables
local baseID = "b01"
local defaultmode = "up" --default state up/down
local modemside = "right" --side modem is on
--Init variables
local modeset = "false"
--define functions
function RedNetSplit(message)
if message==nil then --string.sub doesn't like nil; cant conecate nil
local base = "000"
local header = "herpderp"
local content = "herpderp"
return base,header,content
else
print(id.." "..message)
local base = string.sub(message, 1, 3)
local header = string.sub(message, 4, 11)
local content = string.sub(message, 12)
return base,header,content
end
end
--Clear Terminal
term.clear()
term.setCursorPos(1,1)
--Bootup
print("Drawbridge Computer v0.3 Starting Up")
write("Activating RedNet modem...")
if peripheral.getType(modemside)=="modem" then --if a modem is on the side indicated
rednet.open(modemside) --then turn it on!
sleep(0.5)
write("OK")
else --uh oh, no modem
sleep(0.5)
print("ERROR: Modem not found on side "..modemside)
quit() --this doesn't work as its supposed to, but it does error out the console and stops the program so 'meh'
end
print("Contacting C&C Computer...")
rednet.broadcast(baseID.."commctrlPING")
id,message,distance = rednet.receive(5)
if message == baseID.."commctrlPONG" then
print("Server reached!")
print(id.." "..message.." dist:"..distance)
serveractive = true
elseif message == nil then
print("Can't reach server! Defaulting to "..defaultmode)
mode = defaultmode
modeset = true
else
print("lines are busy! Defaulting to "..defaultmode)
print(id.." "..message.." dist:"..distance)
mode = defaultmode
modeset = true
end
--if server was reached then get mode
if serveractive == true then
sleep(2)
rednet.broadcast(baseID.."commctrldrawbridgestatus") --get drawbridge status
id,message = rednet.receive(5)
base,header,content = RedNetSplit(message)
if base==baseID and header=="drawbrid" and content == "up" or content == "down" then
print("Recieved mode "..content)
mode = content
modeset = true
else
print("Server sent invalid mode! Defaulting to "..defaultmode)
mode = defaultmode
modeset = true
end
end
--main loop
while true do
sleep(0)
--get any incoming messages
id,message = rednet.receive() --drawbridges really don't need to broadcast anything or do anything else, so just have it wait until a message is recieved (debug not getting RedNet messages)
base,header,content = RedNetSplit(message)
--if addressed to drawbridges set content to state
if base==baseID and header=="drawbrid" and content == "up" or content == "down" then
print("Server sent "..content)
mode = content
modeset = true
end
--set up or down if modeset = true
if mode == "up" and modeset == true then
redstone.setOutput("top", true)--activate piston above
redstone.setOutput("left", true)--activate repeaters around
redstone.setOutput("back", true)--activate repeaters
redstone.setOutput("right", true)--ditto
modeset = false --only set up or down once
elseif mode == "down" and modeset == true then
redstone.setOutput("top", false)--activate piston above
redstone.setOutput("left", false)--activate repeaters around
redstone.setOutput("back", false)--activate repeaters
redstone.setOutput("right", false)--ditto
modeset = false
end
end
And for kicks, the Wireless Melee Turtle (or as I have nicknamed them TurtleDrones) Control Program:
Spoiler
--TurtleDrone control Program V0.5
--Initialize Variables
local serveractive = false
local nTime = os.time()
--Configureable variables
local baseID = "b01"
local defaultmode = "auto" --auto/passive/aggressive
--define functions
function RedNetSplit(message) --returns three strings: base, header, and content only if message was not nil
if message==nil then --string.sub doesn't like nil; cant conecate nil
local base = "000"
local header = "herpderp"
local content = "herpderp"
return base,header,content
else
print(id.." "..message)
local base = string.sub(message, 1, 3)
local header = string.sub(message, 4, 11)
local content = string.sub(message, 12)
return base,header,content
end
end
--Clear Terminal
term.clear()
term.setCursorPos(1,1)
--Bootup
print("TurtleDrone 0.5 Starting Up")
print("Activating RedNet modem...")
if peripheral.getType("right")=="modem" then --if a modem is on the right (wireless turtles are always on the right)
rednet.open("right") --then turn it on!
sleep(0.5)
print("OK")
else --uh oh, this is not a wireless turtle!
sleep(0.5)
print("ERROR! This is not a wireless Turtle!")
quit() --this doesn't work as its supposed to, but it does error out the console and stops the program so 'meh'
end
print("Contacting C&C Computer...")
rednet.broadcast(baseID.."commctrlPING")
id,message,distance = rednet.receive(2)
if message == baseID.."commctrlPONG" then
print("Server reached!")
print(id.." "..message.." dist:"..distance)
serveractive = true
elseif message == nil then
print("Can't reach server! Defaulting to "..defaultmode)
mode = defaultmode
else
print("lines are busy! Defaulting to "..defaultmode)
mode = defaultmode
end
--if server was reached then get mode
if serveractive == true then
sleep(2)
rednet.broadcast(baseID.."commctrlrequeststatus")
id,message = rednet.receive(5)
base,header,content = RedNetSplit(message)
if base==baseID and header=="turtdrone" and content=="aggressive"or content=="passive" or content=="auto" then
print("Recieved mode "..content)
mode = content
else
print("Server sent invalid mode! Defaulting to "..defaultmode)
mode = defaultmode
end
end
--main loop
while true do
sleep(0)
--check what time it is
nTime = os.time()
--get any incoming messages
id,message = rednet.receive(1)
base,header,content = RedNetSplit(message)
--if addressed to turtledrones set content to state
if base==baseID and header=="turtdron" then
if content=="aggressive" or content=="passive" or content=="auto" then
print("Server sent "..content)
mode = content
else
print("ERROR! Invalid State Recieved! Defaulting to "..defaultmode)
mode = defaultmode
end
end
--Set top redstone lamp to true if aggressive or auto and nighttime
if mode == "aggressive" then
redstone.setOutput("top", true)
elseif mode == "auto" then
if nTime < 5 or nTime > 20 then
redstone.setOutput("top", true)
elseif nTime > 5 and nTime < 20 then
redstone.setOutput("top", false)
end
elseif mode == "passive" then
redstone.setOutput("top", false)
else
redstone.setOutput("top", false)
end
--Attack if tripwire true and mode aggressive
if mode=="aggressive" and redstone.getInput("bottom") then
turtle.attack()
print("Die foul Being!")
sleep(0.5)
end
--Open door if tripwire true and mode passive
if mode=="passive" and redstone.getInput("bottom") then
turtle.turnLeft()
redstone.setOutput("front", true)
redstone.setOutput("back", true)
print("Access Granted!")
sleep(5)
redstone.setOutput("front", false)
redstone.setOutput("back", false)
turtle.turnRight()
end
--if auto mode, attack if night, open door if day
if mode=="auto" and redstone.getInput("bottom") then
if nTime > 5 and nTime < 20 then
turtle.turnLeft()
redstone.setOutput("front", true)
redstone.setOutput("back", true)
print("It is Day! Access Granted!")
sleep(5)
redstone.setOutput("front", false)
redstone.setOutput("back", false)
turtle.turnRight()
elseif nTime < 5 or nTime > 20 then
turtle.attack()
print("It is Night! Die foul Being!")
sleep(0.5)
end
end
end
In my efforts to come up with a solution, I theorized that if I split off the button inputs into another computer that could have a dedicated button input, sending rednet signals to the C&C comp when buttons were pressed, enabling the C&C comp to work with infinite timeouts. This really wouldn't work with the Turtle's though…
Thanks in advance for the help!
EDIT: Its not really a LUA problem, its more of a question. Maybe now I might get some help.