This software when placed in the startup of a turtle, allows the turtle to be controlled via Rednet wireless. It is smart enough to send complext sequences of commands in one go.
USAGE
once the software is running on the turtle, it can be controlled by sending character sequences to the turtle via rednet.
once the turtle has done the command sequence, it sends bot/done back to the computer the send the commands
SYNTAX
The turtle accepts commands seperated by the / character. Commands can have parameters added, by adding a double-point seperator ( :P/>/> and the parameters following it
COMMANDS
D = Down Optional parameter: number of times to go down (default:1)
U = Up Optional parameter: number of times to go up (default:1)
R = Turn Rignt Optional parameter: number of times to go right (default:1)
L = Turn Left Optional parameter: number of times to go left (default:1)
F = Move Forward Optional parameter: number of times to go forward (default:1)
B = Move Back Optional parameter: number of times to go back (default:1)
PL = place a block Optional parameters: 1 parameter: slot in inventory to use 2nd parameter: up/down/left/right for placing up/down/left/right (ex. PL:1:down)
DG break a block Optional parameters: 1 parameter: slot in inventory to use 2nd parameter: up/down/left/rightfor digging up/down/left/right (ex. DG:2:down = digs the block above and puts the content in slot 2 of the bots inventory)
REP Repeat a number of commands a number of times Syntax: REP:<number of times>:[commandsTobeRepeated]
EXAMPLES
send with : rednet.send(TurtleID,"commands here")
u:3/f/pl/d:3 = Go up 3 times, then go forward, and place a block, then go down 3 times
rep:3:[u/pl] = makes a pillar of 3 blocks
rep:3:[rep:3:[u/pl]/d:3/r/f/l] = makes a 3x3 wall
rep:10:[f/pl:1:up] = places a line of blocks above the turtle, for 10 block forward
CODE
-- ==========================================================
-- TURTLE REMOTE CONTROL PROGRAM
-- ==========================================================
rednet.open('right')
local function nz(val) if val then return val else return '' end end
local function iif(c,y,n) if c then return y else return n end end
local function isIn(c,...) for i,v in ipairs({...}) do if v==c then return true end end return false end
local split = function(str, pattern)
pattern = pattern or "[^%s]+"
if pattern:len() == 0 then pattern = "[^%s]+" end
local parts = {__index = table.insert}
setmetatable(parts, parts)
str:gsub(pattern, parts)
setmetatable(parts, nil)
parts.__index = nil
return parts
end
w,h = term.getSize()
local xpos=0
local ypos=0
local zpos=0
local rotation=0
local log={}
local logLines=h-4
local turtleCommands={}
local function addLog(message)
table.insert(log, message)
if #log>logLines then
table.remove(log,1)
end
for n=1,#log do
term.setCursorPos(1,4+n)
term.clearLine()
write(log[n])
end
end
local function updateScreen()
term.setCursorPos(1,3)
write("X: "..xpos.." Y: "..ypos.." Z: "..zpos.." ROT: "..rotation)
end
local function doTurnRight(params)
local times=tonumber(params[1]) or 1
for i=1,times do
rotation = (rotation+1)%4
turtle.turnRight()
end
updateScreen()
end
local function doTurnLeft(params)
local times=tonumber(params[1]) or 1
for i=1,times do
rotation = (rotation-1)%4
turtle.turnLeft()
end
updateScreen()
end
local function doForward(params)
local bUpdated=false
local times=tonumber(params[1]) or 1
for i=1,times do
if turtle.forward() then
xpos = xpos + iif(rotation==0,1,iif(rotation==2,-1,0))
ypos = ypos + iif(rotation==1,1,iif(rotation==3,-1,0))
bUpdated=true
end
end
if bUpdated then updateScreen() end
end
local function doBack(params)
local bUpdated=false
local times=tonumber(params[1]) or 1
for i=1,times do
if turtle.back() then
xpos = xpos - iif(rotation==0,1,iif(rotation==2,-1,0))
ypos = ypos - iif(rotation==1,1,iif(rotation==3,-1,0))
bUpdate=true
end
end
if bUpdated then updateScreen() end
end
local function doUp(params)
local bUpdated=false
local times=tonumber(params[1]) or 1
for i=1,times do
if turtle.up() then
zpos = zpos + 1
bUpdated=true
end
end
if bUpdated then updateScreen() end
end
local function doDown(params)
local bUpdated=false
local times=tonumber(params[1]) or 1
for i=1,times do
if turtle.down() then
zpos = zpos - 1
bUpdated=true
end
end
if bUpdated then updateScreen() end
end
local function doPlace(params)
turtle.select(tonumber(params[1]) or 1)
if #params>1 then
local where=params[2]:lower()
if where=="up" then
turtle.placeUp()
elseif where=="down" then
turtle.placeDown()
elseif where=="left" then
turtle.turnLeft()
turtle.placeDown()
turtle.turnRight()
elseif where=="right" then
turtle.turnRight()
turtle.placeDown()
turtle.turnLeft()
elseif where=="back" then
turtle.turnRight()
turtle.turnRight()
turtle.place()
turtle.turnRight()
turtle.turnRight()
end
else
turtle.place()
end
end
local function doDig(params)
turtle.select(tonumber(params[1]) or 1)
if #params>1 then
local where=params[2]:lower()
if where=="up" then
turtle.digUp()
elseif where=="down" then
turtle.digDown()
elseif where=="left" then
turtle.turnLeft()
turtle.digDown()
turtle.turnRight()
elseif where=="right" then
turtle.turnRight()
turtle.digDown()
turtle.turnLeft()
elseif where=="back" then
turtle.turnRight()
turtle.turnRight()
turtle.dig()
turtle.turnRight()
turtle.turnRight()
end
else
turtle.dig()
end
end
local function parseBracket(source,startPos)
local level=0
for n=startPos,source:len() do
local fChar=source:sub(n,n)
if fChar=="[" then
level = level + 1
elseif fChar=="]" then
level=level - 1
if level==0 then
return true, n, source:sub(startPos+1,n-1)
end
end
end
return false,-1,""
end
local function tableToString(tbl,delimiter)
local result = ""
if not delimiter then delimiter="," end
for n=1,#tbl do
result=result..iif(n>1,delimiter,"")..tbl[n]
end
return result
end
-- Sample syntax: REP:3:[code]/u/ u/
local function parseCommands(commands)
local cmd=""
local cmdParams={}
local bHandleCommand = false
commands=commands.."/"
local buildCmd=function(cmdElement)
if cmd=="" then
cmd=cmdElement:lower()
else
table.insert(cmdParams,cmdElement)
end
end
while commands~="" do
local fCharPos=commands:find("[/:%[]")
local fChar = ""
if not fCharPos then
fCharPos=commands:len()+1
fChar=""
else
fChar=commands:sub(fCharPos,fCharPos)
end
if fChar=="" then
buildCmd(commands)
bHandleCommand=true
commands=""
elseif fChar=="[" then
local success, endPos, foundString = parseBracket(commands,fCharPos)
if success then
buildCmd(foundString)
commands=commands:sub(endPos+1)
else
commands=""
end
elseif fChar==":" then
foundString=commands:sub(1,fCharPos-1)
buildCmd(foundString)
commands=commands:sub(fCharPos+1)
elseif fChar=="/" then
foundString=commands:sub(1,fCharPos-1)
buildCmd(foundString)
commands=commands:sub(fCharPos+1)
bHandleCommand=true
else
addLog(commands)
end
if bHandleCommand then
--addLog("exec:"..cmd.."("..tableToString(cmdParams)..")")
local cmdToExecute=turtleCommands[cmd]
if cmdToExecute then
cmdToExecute(cmdParams)
else
addLog("Invalid command from cpu#"..cpu.." :"..cmd)
end
cmd=""
cmdParams={}
bHandleCommand=false
end
end
end
local doRepeat=function(params)
if #params>1 then
local times=tonumber(params[1]) or 1
for i=1,times do
parseCommands(params[2])
end
else
addLog("Not enough parameters for REP")
end
end
local doFill=function(params)
local times=tonumber(params[1]) or 1
for i=1,times do
rs.setOutput("left",true)
sleep(0.2)
rs.setOutput("left",false)
sleep(0.2)
end
end
turtleCommands={
right=doTurnRight,r=doTurnRight,
left=doTurnLeft,l=doTurnLeft,
up=doUp,u=doUp,
down=doDown,d=doDown,
forward=doForward,f=doForward,
back=doBack,b=doBack,
place=doPlace,pl=doPlace,
dig=doDig,dg=doDig,
rep=doRepeat,
fill=doFill
}
-- Initialize interface, let other computers know i'm alive
term.clear()
term.setCursorPos(1,1)
print("Rednet Monitor CPU#"..os.getComputerID())
print(string.rep("=",w-1))
term.setCursorPos(1,4)
print("-[log]"..string.rep("-",w-7))
rednet.broadcast("bot/active/"..os.getComputerID())
updateScreen()
-- Start listening to commands
while true do
sleep(0.1)
event,cpu,message=os.pullEvent()
if event=="rednet_message" then
parseCommands(message)
rednet.send(cpu,"bot/done")
end
end