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

User Friendly Program combining several useful functions

Started by ChunLing, 11 October 2012 - 09:19 PM
ChunLing #1
Posted 11 October 2012 - 11:19 PM
I use ComputerCraft mainly as a way to have some useful robots around, rather than as a way to get all fancy building up a fully automated machine nation or anything like that. To that end, I made a program that combines a number of functions that I find pretty useful. The program is self-contained and should run on the basic API of ComputerCraft…I hope. So it should be ideal for new CC users to start getting some actual work out of their turtles right away.

Probably the best part of the program is the function based on the very flexible and useful replacement for go utility (which I refer to as "gox") by tele_iz_dva4a. This function accepts a string of commands encompassing most of the available turtle functions and allows loops and enumerated iterations, so it can do most of the things that novice users spend time programing to get some basic utility out of their turtles.

I've also included a function based on the nifty Satellite Builder by dustpuppy. Though this is a somewhat more specialized function, which just launches a four-node GPS array to the top of the map, it can be a real time saver for a new world (it also illustrates some of the principles of turtle/computer interaction that are of interest to those who want to eventually have an automated machine nation). It can be used to place multiple arrays and makes an effort to keep them consistent with each other (though success is spotty, sometimes the automatic GPS finding works and sometimes it doesn't). The function only overrides the user provided coordinates if it finds a valid GPS system in place, so if it doesn't work then nothing bad happens.

I also included a couple of functions that I find useful, such as a simple bone-meal based wheat farmer (to use up all the bones you aren't feeding to dogs), a gravel sifter (in case you want to turn a hundreds of blocks of gravel into flint rather than using it to make paths that collapse when their underlayment gets removed), and a basic remote control function.

I now have a user guide for clfn in the spoiler below.
SpoilerOkay, a complete user guide to the remote functions of clfn. These are the rednet messages that you can send to the clfn turtle when it is in remote controlled mode.

Any turtle API function, without the "turtle." and without (). Where a parameter is used, the default will be 1, otherwise you can specify it with a number. Thus turtle.forward() is "forward", and turtle.select(8) is "select 8". The clfn turtle will respond with a message that contains the value of the return.

Any of the functions described below:
"dfd", "dup", "ddn" move forward, up, or down (digging and attacking to remove obsticles). If the turtle cannot move then it outputs the reason it couldn't move and returns false.

"tnl" digUp, digDown, then dfd as described above.

"bmb" placeDown a block from the selected slot, then output redstone power to it. If the block is successfully placed and then becomes an entity or item, bmb returns true, otherwise false (note that this returns true for sand and gravel as well as tnt, and for some items that are successfully used with placeDown, but it returns false for buckets of water and lava).

"pckup" executes the suck commands. Needs revision to be more useful (I assumed it did more than it does cause I named it too clearly).

"chst" place a block from slot 16 and drops everthing else into it. Returns false if the block couldn't be placed, otherwise returns true. Do not use this command if slot 16 doesn't contain a placeable block with an inventory sufficient to hold the dump.

"slct" increments the selection value (rolling around if it is 16) and selects that slot. Returns a string specifying the newly selected slot and the stack size over the stack limit

"rfl" Outputs the current fuel level, attempts to use the currently selected slot as fuel, and returns a string containing the new fuel level if successful or false if the selected slot does not contain fuel

"gpslct" returns a string containing the GPS coordinates, or nil if it cannot get a GPS fix.
"gpshst" allows the turtle to act as a temporary GPS host to help extend the range of an existing GPS system. The turtle replies with the message "Serving GPS from x,y,z" (where x,y,z are it's GPS coordinates). When it receives "PING", it responds to the sender as a GPS host but also outputs the ID of the PING sender and the distance from which it was PINGed. If the turtle is out of range of a consistent system or receives the "gpshst" command a second time, it returns "GPS hosting terminated".

The following commands require additional parameters and explaination.

"gox "..command_string executes a series of commands, in iterations and loops, specified by command_string. The commands are single characters, mapped to commands by the following key:

f,b,u,d, are the movement commands, moving the turtle forward, back, up, or down. b is the normal turtle back command, while f,u,and d use the "dfd","dup", and "ddn" commands described above and will attempt to dig/attack obsticles.
t, uses the "tnl" command above, digging up and down as it moves.
l,r, are to turn left and right.
p,P,o, are the place, placeUp, and placeDown commands
x,X,z, are the drop, dropUp, and dropDown commands
e,E,w, are the dig, digUp, and digDown commands
v,V,c, are the suck, suckUp, and suckDown commands
R,S,B,C, use the "rfl","slct","bmb", and "chst" commands as described above.

Following a command by a number will cause the command to be repeated that many times.

Enclosing a sequence of commands in square brackets (i.e. []) will cause those commands to be executed in a loop that will end when the last command in the loop returns false or nil, unless the closing bracket is followed by a number, in which case the loop will end after that many iterations. Non-iterated loops (not following the closing "]" with a number) should only be used with caution. A command string like "gox [t]" probably won't stop till it hits bedrock or an unloaded chunk, or the turtle runs out of fuel.

You can put loops inside of loops, and thus build up fairly complex actions. "gox [[Pobp]5l]4" will build a nice little 6 meter square enclosure (the final bp doesn't happen, though). "gox [[Pobp]5l]4bpS[[ob]4lbl[ob]4rbr]2" will complete the wall, switch the selected slot, and put down a nice floor. You can extend this to "gox [[[[Pobp]5l]4bpS[[ob]4lbl[ob]4rbr]2u3frfS]8" to reposition the turtle on top of the corner of the wall and repeat the wall/floor building 8 times (at which point you will be pretty much all out of building materials). More simply, you can encode an excavate type program, with use of C to dump off materials when you are likely to be getting full. (edited to make the brackets match up, match your brackets or brick your turtle, also, test your command strings in sections before assembling anything this complex).

The "gox" command shouldn't be underestimated as to it's usefulness or as to the dangers of using it carelessly, it's as easy to program it to destroy as create (a bit easier, really). And a missed turn or movement can make an entire command sequence behave quite strangely.

"rcvfl "..filename.." "..filebodytext allows the turtle to receive a text file over rednet. The rcvfl function takes the first "word" of non space characters to be the name of the file to be created/overwritten, and everything after that to be the text of the file. The file contents will not begin with a space but can contain spaces (the function can be modified to allow a space at the beginning of the file but currently this is not desired). When the file is written the function returns filename.." updated". The main intended purpose is to allow writing short control files like startup or very simple programs that are going to be used later, but it can also be used as the receiving half of a file transfer protocal.

"srvfl "..filename allows the turtle to serve a specified file over rednet. The file is served as a rednet message (and mirrored on the turtle's console), and the function returns filename.." served". The main intended purpose is to allow viewing short control files like startup or very simple programs that are going to be used later, but it can also be used as the serving half of a file transfer protocal (but not corresponding directly to rcvfl).

"xqtfl "..filename allows the turtle to execute a program file. After the file has run, the startup file on the turtle is rewritten to run clfn in remote control mode with the current controllerID. Certain command line parameters (those with entirely alphanumberic form) can be passed, separated by spaces from each other and the program filename.

"ldstrng "..luacodestring allows the turtle to execute a supplied lua code string. It is intended for expert use only, and returns the function if the provided string is successfully interpreted as one or the error message generated if the string was not valid lua code. Note, code that is syntactically valid but throws errors will terminate clfn, resulting in losing remote control of the turtle.

That's pretty much the laundry list of what clfn can do by remote control and using gox command strings. The other clfn actions should be easier to use, but if there are questions about them then feel free to ask.

The rcpda and rctrl functions are intended to be used with clfn remote control mode and make sending most of the available commands pretty simple. See their program descriptions for more details.

The program can be considered more of a starting point, if you want to build on it. The code is in the following spoiler, check the bottom of this post for the pastebin links.
Spoiler
local tArgs = { ... }
local cldt = {}
local tfnctns = {}
local mvfncs = {{turtle.forward,turtle.detect,turtle.dig,turtle.attack},
		{turtle.up,turtle.detectUp,turtle.digUp,turtle.attackUp},
		{turtle.down,turtle.detectDown,turtle.digDown,turtle.attackDown},}
local function trply(mssgstr) -- e.g. "unbreakable block in path"
	print(mssgstr)
	if cldt.rcID then rednet.send(cldt.rcID,mssgstr) end
end
local function mvdgK(drctn) -- i.e.(1 = forward, 2 = up, 3 = down)
	local itr8 = 0
	while not mvfncs[drctn][1]() do
		if mvfncs[drctn][2]() then
			if not mvfncs[drctn][3]() then trply("unbreakable block in path") return false end
		elseif turtle.getFuelLevel() == 0 then trply("Out of fuel" ) return false
		else mvfncs[drctn][4]() end
		if itr8 > 64 then trply("persistent impediment") return false end
		itr8 = itr8+1
	end
	return true
end
local rctfncs = {
tnl = function() turtle.digUp() turtle.digDown() return mvdgK(1) end,
dfd = function() return mvdgK(1) end,
dup = function() return mvdgK(2) end,
ddn = function() return mvdgK(3) end,
bmb = function()
	if turtle.placeDown() then redstone.setOutput("bottom",true)
		sleep(0.5) redstone.setOutput("bottom",false)
	if not turtle.detectDown() then return true end end
return false end,
pckup = function() if turtle.suck() then return turtle.suckUp() else return turtle.suckDown() end end,
chst = function()
	turtle.select(16)
	if turtle.place() then for i = 1,15 do turtle.select(i) turtle.drop() end return true end
return false end,
slct = function()
	cldt.slt = math.fmod(cldt.slt,16)+1
	turtle.select(cldt.slt)
	local stcksz = turtle.getItemCount(cldt.slt)
	return "Slot "..cldt.slt..", "..stcksz.."/"..stcksz+turtle.getItemSpace(cldt.slt)
end,
rfl = function()
	turtle.select(cldt.slt)
	trply("Current fuel level is "..turtle.getFuelLevel())
	if turtle.refuel() then return "New fuel level is "..turtle.getFuelLevel()
	else return false end
end,
gox = function(cmmnds)
	cmmnds = cmmnds:match("%S+")
	return tfnctns[6](cmmnds)
end,
gpslct = function() local x,y,z = gps.locate(2) if x then return "GPS = "..x..", "..y..", "..z
else return false end end,
gpshst = function()
	local tp = {gps.locate(2)}
	if tp[1] then trply("Serving GPS from "..tp[1]..", "..tp[2]..", "..tp[3]) end
	repeat tp[4],tp[5],tp[6] = rednet.receive()
		if tp[5] == "PING" then rednet.send(tp[4], textutils.serialize({tp[1],tp[2],tp[3]}))
			trply("PINGed by "..tp[4].." at "..tp[6].." meters")
		elseif cldt.rcID == tp[4] and tp[5] == "gpshst" then tp[1] = nil end
	until not tp[1]
return "GPS hosting terminated"
end,
rcvfl = function(flnm)
	local cntnt
	flnm,cntnt = flnm:match("(%S+)%s*(.*)")
	 local hndl = fs.open(flnm,"w") hndl.writeLine(cntnt) hndl.close()
return flnm.." updated" end,
srvfl = function(flnm)
	flnm = flnm:match("%S+")
	local flbdy = fs.open(flnm,"r")
	trply(flbdy.readAll()) flbdy.close()
return flnm.." served" end,
xqtfl = function(prms)
	local tprm,ndx = {},1
	for v in prms:gmatch("%w+") do tprm[ndx] = v ndx = ndx+1 end
	shell.run(unpack(tprm))
	local hndl = fs.open("startup","w")
	hndl.writeLine("shell.run("clfn",1,"..cldt.rcID..")") hndl.close()
return tprm[1].." executed" end,
ldstrng = function(luacd)
	local tmpfnc,rrmssg = loadstring(luacd)
	if tmpfnc then return tmpfnc()
	else return rrmssg end
end,
}
local cmdlst = {f=rctfncs.dfd,b=turtle.back,u=rctfncs.dup,d=rctfncs.ddn,
	l=turtle.turnLeft,r=turtle.turnRight,t= rctfncs.tnl,
	p=turtle.place,P=turtle.placeUp,o=turtle.placeDown,
	x=turtle.drop,X=turtle.dropUp,z=turtle.dropDown,
	e=turtle.dig,E=turtle.digUp,w=turtle.digDown,
	v=rctfncs.pckup,V=turtle.suckUp,c=turtle.suckDown,
	R=rctfncs.rfl,S=rctfncs.slct,B=rctfncs.bmb,C=rctfncs.chst
}
tfnctns = {
function(rtID)
	cldt.rcID = tonumber(rtID)
	rednet.open("right")
	if cldt.rcID then cldt.slt = 1 turtle.select(cldt.slt) else
		write("Enter controller ID> ") cldt.rcID = tonumber(read())
	end
	print("Turtle "..os.computerID().." controlled by console "..cldt.rcID)
	local hndl = fs.open("startup","w")
	hndl.writeLine("shell.run("clfn",1,"..cldt.rcID..")") hndl.close()
	while cldt.rcID do
		repeat cldt[1],cldt[2] = rednet.receive() until cldt[1] == cldt.rcID
		cldt[3], cldt[4] = cldt[2]:match("^(%a+)%s*(.*)")
		if cldt[4] == "" then cldt[4] = "1" end
		if turtle[cldt[3]] then trply(tostring(turtle[cldt[3]](tonumber(cldt[4]))))
		elseif rctfncs[cldt[3]] then trply(tostring(rctfncs[cldt[3]](cldt[4])))
		elseif cldt[2] == "trmn8RC" then trply("Remote Control Terminated")
			cldt.rcID = nil
		end
	end
end,
function()
	cldt.slt = 16
	write("Place fuel in Slot 16 and enter") read()
	print(cmdlst.R())
end,
function()
	write("Place material to be sifted in Slots 1-15nLeave Slot 16 empty") read()
	repeat
		turtle.place()
		if turtle.getItemCount(cldt.slt) < 1 then rctfncs.slct() end
		if not turtle.dig() then print("Error") break end
	until cldt.slt > 15
end,
function()
	write("Place seeds in Slot 1nBonemeal in Slots 2-15nLeave Slot 16 empty") read()
	cldt.slt = 2
	repeat
		turtle.select(1)
		if not turtle.place() then print("There must be tilled dirt to plant") break end
		turtle.select(cldt.slt)
		if not turtle.place() then print("Process requires Bonemeal to continue") break end
		if turtle.getItemCount(cldt.slt) < 1 then rctfncs.slct() end
		turtle.dig()
	until cldt.slt > 15
end,
function(x3Ps,z3Ps,fcng,dmn)
	x3Ps,z3Ps,fcng,dmn = tonumber(x3Ps),tonumber(z3Ps),tonumber(fcng),tonumber(dmn)
	local x1Ps,y1Ps,z1Ps,x2Ps,z2Ps = 0,255,0,1,0
	local cntntstng = [[fs.copy("disk/rnhst","rnhst") shell.run("rnhst","host",]]
	if fs.exists("rom/programs/rnhst") then  cntntstng = [[shell.run("rnhst","host",]]
	elseif not fs.exists("rnhst") then print("Must have available rnhst program to execute")
	return false end
	local function gpsnode(xPos,yPos,zPos)
		turtle.select(2) cmdlst.p()
		turtle.select(4) cmdlst.x()
		if fs.exists("rnhst") and not fs.exists("disk/rnhst") then fs.copy("rnhst","disk/rnhst") end
		local strtfl = fs.open("disk/startup","w")
		strtfl.writeLine(cntntstng..xPos..","..yPos..","..zPos..","..dmn..")")
		strtfl.close()
		local cmdstrng = {"u","f","l","b",}
		for i = 1,#cmdstrng do cmdlst[cmdstrng[i]]() end
		turtle.select(1) cmdlst.p() cmdlst.b()
		turtle.select(3)
		cmdstrng = {"p","l","f","r","f","f","r",}
		for i = 1,#cmdstrng do cmdlst[cmdstrng[i]]() end
		peripheral.call("front","turnOn")
		cmdlst.d() cmdlst.v()
	end
	local function plcaxis(xPos,yPos,zPos)
		x1Ps,y1Ps,z1Ps = gps.locate(2,true)
		cmdlst.f()
		if x1Ps then --there is a GPS system, use it to determine coordinates and facing
			x2Ps,yPos,z2Ps = gps.locate(2)
			x2Ps,z2Ps = x2Ps-x1Ps,z2Ps-z1Ps
		else x1Ps,y1Ps,z1Ps = xPos,yPos,zPos end
		cmdlst.d()
		gpsnode(x1Ps+(x2Ps*2),y1Ps,z1Ps+(z2Ps*2))
	-- Go back 2 and set the second node
		cmdlst.r() cmdlst.r()
		for c=1,2 do turtle.forward() end
		gpsnode(x1Ps-(x2Ps*2),y1Ps,z1Ps-(z2Ps*2))
	end
	while not(x3Ps and z3Ps and fcng and dmn) do
		write([[Fill inventory as follows
Slot 1 > 4+ Computers
Slot 2 > 4+ Disk drives
Slot 3 > 4+ Wireless Modems (4x)
Slot 4 > Floppy disk
Enter turtle's current x> ]]) x3Ps = tonumber(read())
		write("Enter turtle's current z> ") z3Ps = tonumber(read())
		write("Enter turtle's current facing> ") fcng = tonumber(read())
		write("Enter initial admin access ID") dmn = tonumber(read())
	end
	for i=1, fcng+1 do turtle.turnLeft() end
	while turtle.getFuelLevel() < 500 do
		trply("Low Fuel Warning!")
		write("Place fuel in Slot 16 and press Enter") read()
		cldt.slt = 16 print(cmdlst.R())
	end
-- launch turtle
	while cmdlst.u() do end
	plcaxis(x3Ps,255,z3Ps)
-- Go back to the middle and turn
	x2Ps,z2Ps = 0,1
	cmdlst.b() cmdlst.r()
	plcaxis(x3Ps,254,z3Ps)
	cmdlst.b()
	while turtle.down() do end
end,
function(cmndstrng) -- Go commands
-- non-nil array length
local function lngth(lst)
	if lst then return #lst else return 0 end
end
local function gtNmbr(strg)
	local nmbr,rmndr = strg:match("^(%d+)(.*)$")
	return nmbr,lngth(strg)-lngth(rmndr)
end
local function gtLoop(strg)
	local loop,rmndr = strg:match("^(%b[])(.*)$")
	if loop then return loop:sub(2,-2),lngth(strg)-lngth(rmndr)
	else return nil,0 end
end
local function gox(cmnds)
	if not #cmnds then return false end
	local ndx,prvCmnd,result = 1,""
	while ndx <= #cmnds do
		local char = cmnds:sub(ndx,ndx)
		local nxtCh = cmnds:sub(ndx+1, ndx+1)
		if cmdlst[char] then
			ndx,result = ndx+1,cmdlst[char]()
		else
			local nmbr, nLen = gtNmbr(cmnds:sub(ndx))
			local loop, lpLen = gtLoop(cmnds:sub(ndx))
			if nmbr then
				for i = 2,tonumber(nmbr) do gox(prvCmnd) end
				ndx = ndx+nLen
			elseif loop then
				local nmbr, nLen = gtNmbr(cmnds:sub(ndx+lpLen))
				if nmbr then
					for i = 1,tonumber(nmbr) do gox(loop) end
					ndx = ndx+nLen
				else while gox(loop) do end end
				ndx = ndx+lpLen
		end	end
		prvCmnd = char
	end
	return result
end
if not cmndstrng then
	print([[enter a string of commands/loops
f b u d l r to move, t to tunnel
p P o to place[U/Dn], x X z to drop
e E w to dig [U/Dn], v V c to suck
R to refuel, S to select next slot
[...] loop while last command succeeds
number for fixed loop]])
	cmndstrng = read() end
	return gox(cmndstrng)
end,
}
shell.run('clear')
cldt[1] = tonumber(tArgs[1])
if cldt[1] and tArgs[2] then tfnctns[cldt[1]](unpack(tArgs,2)) else
repeat
	cldt.slt = 1
	turtle.select(cldt.slt)
	print("Select function by number")
	print([[1: Remote Control
2: Refuel
3: Sift Gravel
4: Auto Farm
5: Launch GPS Array
6: GoX commands
Or other to exit]])
	sclfn = tfnctns[tonumber(read())]
	if sclfn then sclfn() end
until not sclfn
end
Hopefully this is easy to use and works with the basic ComputerCraft API. Let me know if it doesn't work. For those seeking to understand the logic about certain parts of the program, just ask. I didn't really comment it all that well and the code is designed to be easy for me to understand rather than for others.

On the other hand, if you spot areas where the functionality (not just the notation style) of the code can be improved, please share.

Oh, I should include the program for controlling a turtle remotely. It isn't strictly necessary (you can just send the commands by rednet in lua mode), but it could be helpful.
Spoiler
local tvnt,cnslID,rcID = {},os.computerID()
local rcmdlst = {
	[0] = "bmb",[79] = "place",[80] = "back",[81] = "ddn",[75] = "turnLeft",[76] = "tnl",
	[77] = "turnRight",[71] = "placeUp",[72] = "dfd",[73] = "dup",[82] = "placeDown",
	[83] = "drop8",[74] = "rfl",[78] = "slct",[181] = "gpshst",[55] = "gpslct",[28] = "pckup",
	[210] = "place",[211] = "dig",[199] = "chst",[207] = "suck",[201] = "up",[209] = "down",
	[200] = "forward",[208] = "back",[203] = "turnLeft",[205] = "turnRight",[26] = "digUp",
	[27] = "digDown",[51] = "suckUp",[52] = "suckDown",[29] = "trmn8RC",
}
local function opnmdm()
	for i,v in pairs(rs.getSides()) do	
		if peripheral.getType(v) == "modem" then
			if not rednet.isOpen(v) then rednet.open(v) end
		return true end
	end
return false end
local function pntxt(x,y,txt) term.setCursorPos(x,y) write(txt) end
local mnutxt = {"Access Control","Transmit file","Receive file","Find GPS Hosts","Exit Menu",}
local mnufnc = {
function () local tp = {}
pntxt(1,6,"Enter an ID to alter access level for it on rnhst"..rcID) tp[2] = read()
write("add or ban this ID?")
repeat tp[1] = read() if tp[1]:find("^[aA]") then
tp[1] = "add" elseif tp[1]:find("^[bB]") then tp[1] = "ban" end
until tp[1] == "add" or tp[1] == "ban"
write("Change Admin or User list?")
repeat tp[3] = read() if tp[3]:find("^[aAdD]") then
tp[3] = "dmnlst" elseif tp[3]:find("^[uUxX]") then tp[3] = "xclst" end
until tp[3] == "dmnlst" or tp[3] == "xclst"
print(cnslID..">"..rcID..": access "..tp[1].." "..tp[2].." "..tp[3])
rednet.send(rcID,"access "..tp[1].." "..tp[2].." "..tp[3])
return 1 end,
function () local tp = {}
pntxt(1,6,"Enter name of file to send")
repeat tp[1] = read() until fs.exists(tp[1])
tp[2] = fs.open(tp[1],"r") tp[3] = tp[2].readAll() tp[2].close()
print(cnslID..">"..rcID..": "..tp[1].." by FTP")
rednet.send(rcID,"flrcv "..tp[1].." "..tp[3])
return 3 end,
function () local tp = {}
pntxt(1,6,"Enter name of file to get") tp[1] = read()
rednet.send(rcID,"flsrv "..tp[1])
print(rcID..">"..cnslID..": "..tp[1].." by FTP")
repeat tp[2],tp[3] = rednet.receive(1) until tp[2] == rcID or not tp[2]
if tp[2] then tp[4] = fs.open(tp[1],"w") tp[4].writeLine(tp[3]) tp[4].close()
else write("Could not get file") end
return 2 end,
function () local tp = {} rednet.send(rcID,"hsts")
pntxt(1,6,"Getting Host data from "..rcID)
repeat tp[1],tp[2] = rednet.receive(3) until tp[1] == rcID and tp[2] ~= "PING" or not tp[1]
if tp[1] then tp[3] = fs.open("GPSHSTS"..rcID,"w") tp[3].writeLine(tp[2]) tp[3].close()
	print("Saving data as GPSHSTS"..rcID)
else print("Could not get file") end
return 5 end,
function () pntxt(1,6,"Exiting Menu") return nil end,
}
local function menu() local ndx = 1
	term.clear() pntxt(1,6,"Use up/down to select option")
	repeat for i = 1,5 do pntxt(1,i," "..mnutxt[i]) end pntxt(1,ndx,">")
		tvnt = {os.pullEvent()}
		if tvnt[1] == "key" and (tvnt[2] == 200 or tvnt[2] == 201) then
			ndx = math.fmod(ndx+3,5)+1
		elseif tvnt[1] == "key" and (tvnt[2] == 208 or tvnt[2] == 209) then
			ndx = math.fmod(ndx,5)+1
		elseif tvnt[1] == "key" and tvnt[2] == 28 then ndx = mnufnc[ndx]()
		elseif tvnt[1] == "rednet_message" then
			pntxt(1,6,"Message from "..tvnt[2]) print(tvnt[3])
		end
	until not ndx
end
local function setID() write("Enter receiver ID> ") return tonumber(read()) end
shell.run('clear')
if not opnmdm() then print("Modem Access Error") return false end
repeat	 rcID = setID() until rcID
write("Receiver ID set to "..rcID)
print("Press "h" for help")
repeat
	tvnt = {os.pullEvent()}
	if tvnt[1] == "key" and rcmdlst[tvnt[2]] then rednet.send(rcID,rcmdlst[tvnt[2]])
		if tvnt[2] == 29 then rcID = setID() end
	elseif tvnt[1] == "rednet_message" then print(tvnt[2]..": "..tvnt[3])
		if tvnt[3]:find("^send") then rednet.send(tvnt[2],read()) end
	elseif tvnt[2] == "S" then rednet.send(rcID,read())
	elseif tvnt[2] == "R" then rcID = setID()
	elseif tvnt[2] == "M" then menu()
	elseif tvnt[2] == "h" or tvnt[2] == "H" then
		print([[Use "R" change receiver ID
Use "S" to send text string
Change receiver to nil to exit rcpda
Use numberpad to control turtles:
284693 to digmove, 5 to tunnel
170 to place, '.' Home End, to drop
Enter, <, >, to suck
Del, [, ] to dig
Direction Keys and PgUp/Dn to move
lCtrl to exit]])
	end
until not rcID
The Remote Controller code is unfinished basic, it works but I was hoping to use it with CCinput only I never got the remote working, so it may be a little odd in some details, it also doesn't currently allow separate control of multiple turtles though the turtle function would support this (you can have synchronized control of multiple turtles, which might be fun but not very useful).

User/customization guide for rctrl, also substantially applicable to rcpda:
SpoilerWhen started, rctrl tries to open a modem, if it can't find one, it prints "Modem Access Error" and returns false. if it does find one, it prompts you do enter a receiver ID. This can be a wireless turtle running clfn remote control or an rnhst node, or anything really, but most of the programs options will be pretty useless. You can of course just use the rednet send/receive functionality to chat with someone else running rctrl or some other rednet messaging program, but that is not optimal (you'll tend to miss some messages while inputting yours).

Anyhow, once you enter a number to be the receiver ID (and the program won't accept anything else, so enter a number), you'll see the message:"Receiver ID set to ID Press "h" for help" (where ID is the number you put in. If you press h, you'll get the help text for key command of a clfn turtle. It looks like this:

Use "R" change receiver ID
Use "S" to send text string
Change receiver to nil to exit rcpda
Use numberpad to control turtles:
284693 to digmove, 5 to tunnel
170 to place, '.' Home End, to drop
Enter, <, >, to suck
Del, [, ] to dig
Direction Keys and PgUp/Dn to move
lCtrl to exit

Note: the rcpda help is similar but formatted differently due to the restrictions of the PDA screen.

"R" and "S" mean the capital letter, so use Shift+R and Shift+S to activate these options. The turtle command keys should work pretty much as described on most keyboards.

A word about changing the receiver ID or sending a text message, while you're doing either you can miss incoming rednet messages. If you want to use a computer as a monitor to collect all incoming messages, then you'll need a different program. But for basic control of clfn remote turtles or rnhst nodes this is not a major concern.

The heart of turtle control is really the key controls, to instantly send pre-configured command messages to a clfn turtle. This is controlled through a table called rcmdlst, defined right up near the top of the program (in the rctrl program, it is actually quite far down in the rcpda program file, past a bunch of functions that you probably don't want to muck about with unless you are confident in your programming skills). If you want to modify the key mapping, it's quite easy. The table looks like this:
local rcmdlst = {
	[0] = "bmb",[79] = "place",[80] = "back",[81] = "ddn",[75] = "turnLeft",[76] = "tnl",
	[77] = "turnRight",[71] = "placeUp",[72] = "dfd",[73] = "dup",[82] = "placeDown",
	[83] = "drop8",[74] = "rfl",[78] = "slct",[181] = "gpshst",[55] = "gpslct",[28] = "pckup",
	[210] = "place",[211] = "dig",[199] = "chst",[207] = "suck",[201] = "up",[209] = "down",
	[200] = "forward",[208] = "back",[203] = "turnLeft",[205] = "turnRight",[26] = "digUp",
	[27] = "digDown",[51] = "suckUp",[52] = "suckDown",[29] = "trmn8RC",
}
All you need to do to change the key mapping of an existing command is to change the keycode value next to the command. A standard keymap is here. If you want to have, say, the B key issue the "bmb" command, then just change '[0] = "bmb",' to '[48] = "bmb",' and you have a different "bmb" key. Two points to note. First, you must use the numeric key code, not the character. The second point is that you cannot have two different commands issued by the same key (there is a way around this, which is to have a key that activates "gox fbudlrBS" or something like that, replace "fbudlrBS" with the commands you actually want activated by that key, in the sequence you want them activated, but it is still a single gox command). You may, on the other hand, have two different keys activate the same command. I have the turnLeft/Right commands on both the arrow keys and the numberpad, and there are other duplicates as well. Perhaps it would be more appropriate to have the numberpad left-4/right-6 keys mapped to "gox lf" and "gox rf" respectively. It's entirely valid.

Because the keys are activated in the same loop that checks for rednet messages, key control never interferes with rednet reception. You'll get all rednet messages sent to you (even by different turtles or nodes than the one your currently controlling). But the limits of key control, that a particular key is mapped to a particular command, means that it is unsuitable for commands that require complex variable input (like a ldstrng command, or most of the rnhst commands).

There is a menu available for friendlier (I hope) usage of the more difficult rnhst functions. The menu is accessed by pressing Shift+M (this is also a character event based selection, like "R" and "S"). It should be relatively self-explanitory, if it is not, then give some feedback on how it can be improved (usability only, no snazzy graphics suggestions, which I find tend to reduce readability anyway).

The use of "S" to enter a rednet text message is essential for complex gox usage, as well as the less frequent (I hope) use of srvfl, rcvfl, xqtfl, and ldstrng. Since these commands require additional parameters in their strings, it is probably impractical to have them mapped to keys in most cases (though I noted an exception for gox above).

Using "R" to change the current turtle controlled is also quite important, unless you are using an rnhst node relay to boost range to your turtles, in which case you'll be switching control of the current turtle using "S" to send "rly ID" (where ID is the turtle ID) to the rnhst node to switch control.

Hopefully this guide helps you get the most out of rctrl, and helps you hunt out bugs. If something doesn't work the way this says it should, then report it!

The code has been updated and now provides the ability for the remote control terminal to send entered strings, and the remote turtle will now accept loadstring commands (Shift+s to enter text send, send "loadstring", when the turtle gets the command you'll be prompted to "send lua code chunk"). If the text is not valid lua code then you'll get back the error message, but if you send syntactically valid lua code that produces an error then the remote control function will terminate. The functions "rcvfl" and "srvfl" have also been added, so that you can remotely write/read files on the turtle (or on a disk in a drive next to the turtle).

The code has been updated again and now supports passing a numeric variable to the turtle API commands. This means that you can now use turtle.select(n) by sendind "select n" (where n is the number of the slot to select). The turtle also responds to all turtle commands by reporting the function result (if any). The "loadstring" command has been replaced by "ldstrng" (to avoid confusion in the code). I think there were also some other minor improvements, but don't remember what they are.

Fixed inability to remote terminate remote control.

Early versions of clfn and rctrl posted on pastebin. Newer versions are in development, later in the thread. These will be posted to pastebin after some more development and testing.

Newest versions of clfn and rctrl now posted. There is also a version of rctrl that utilizes the CCPortable pda, named rcpda. The newest version of clfn is designed to work with rnhst, in development in the Programs forum (specifically, the Launch GPS Array functionality now launches an array of rnhst nodes rather than standard gps nodes). If you cannot (or just don't wish to) install rnhst in rom, then a copy has to be on the turtle that places the array (this is also useful because turtles can be used as temporary rnhst nodes themselves). The copy on the turtle will be copied to the disk and thence to the computers in the array.

Mad props to Ralnick for patient testing of bugged versions, the latest bugfix/update is up.

Experimental rcpda with menu for easy access to rnhst options, and now the ability to use up/down and PgUp/PgDn keys to revisit previous inputs (and returns) when sending text. Feedback always welcome. Another new version of clfn, this one adds a chst command that places a block from slot 16 and attempts to dump the rest of the inventory into it. It can be used with gox as "C". Bugfix/update for clfn (bugs discovered while reading the code to create the user guide, none found in "chst"/"C"), new updates for latest rcpda and rctrl.

Further development will require separation into an api and other parts, and thus clfn will no longer be an integrated, standalone program. Therefore, this will probably be the final update for the standalone clfn, barring the discovery of any further bugs, which I shan't be doing because I'll be using an api based collection of programs I'm developing.
Edited on 18 November 2012 - 10:09 PM
ChunLing #2
Posted 12 October 2012 - 06:28 PM
I'm continuing to update these programs so if anyone is interested in seeing newer versions (with things like command line parameter support, remote loadstring() use, and file receive/serve), then let me know.
ChunLing #3
Posted 13 October 2012 - 06:19 PM
I've put the latest version in the first post. With the addition of command line parameter support and the file functions, you can make it so that the turtle will always enter remote control mode on startup ( the command should be shell.run("clfn",1,"password"), there is room for a third parameter that will set the ID of the remote controller, so that there is no chance of the turtle being hacked in SMP). Or you can store a description of the contents of the turtle so that you know what you're placing remotely.

I've also added the "gox" command, so you can send a string of commands/loops, but using this remotely isn't recommended unless you are very familiar with the usage (cause it's easy to write a string that means "go far away until you run out of fuel" or something like that). The new commands "gox", "rcvfl", and "srvfl" as well as the use of "loadstring" are all accessed by using Shift+s, since they all require additional rednet string input.
ChunLing #4
Posted 15 October 2012 - 09:50 PM
Another update. Some new functionality to better support a (theoretical) program that controlled a turtle automatically. Could also be useful for those wanting feedback on their turtle through the provided control program.
ChunLing #5
Posted 16 October 2012 - 09:57 PM
Crap, I broke the termination code when I improved the turtle command code. Why nobody tell me that? I say to tell me things like that. You not tell me things like that, you maybe not deserve fixed version.
Fixed version edited into initial post.
Ralnick #6
Posted 17 October 2012 - 02:59 AM
no I am not following you. (maybe)

but cool code.. I will give it a try.. and let you know if I can break it.
ChunLing #7
Posted 17 October 2012 - 03:12 AM
I'm so happy that someone replied that I don't care about not knowing what I said that couldn't be followed.
Ralnick #8
Posted 17 October 2012 - 03:18 AM
about not knowing what I said that couldn't be followed.
sorry it was ment to be a joke.
Ralnick #9
Posted 18 October 2012 - 12:26 AM
working great, I like the "gox" commands.. (nice work to the original programmer tele_iz_dva4a ) updated the refuel function (just needed a space)

Spoiler
refuel = function()
trply("Current fuel level is"..turtle.getFuelLevel())
if not turtle.refuel(turtle.getItemCount(cldt.slt)) then
trply("Slot "..cldt.slt.." does not contain fuel")
else trply("New fuel level is"..turtle.getFuelLevel()) end

to

Spoiler
refuel = function()
trply("Current fuel level is "..turtle.getFuelLevel())
if not turtle.refuel(turtle.getItemCount(cldt.slt)) then
trply("Slot "..cldt.slt.." does not contain fuel")
else trply("New fuel level is "..turtle.getFuelLevel()) end


All in all … really nice work..

can you tell me how to install the remote, still not sure on this one…

thanks
ChunLing #10
Posted 18 October 2012 - 12:49 AM
The remote control code currently runs from the controlling computer and simply packages a number of the activating rednet commands to be sent by key/presses on the numeric/direction keys (you can still send a general command by pushing Shift+S).

If you mean the remote from CCInput, sadly I haven't been able to get that to work on my system. I'm currently working with the CCPortable PDA, which needs an operating system that I haven't written. But the pda_key event can be supported by adding in a couple of lines after the "key" event handler, like so:
repeat
    cldt[4],cldt[5],cldt[6] = os.pullEvent()
    if cldt[4] == "key" and rcmdlst[cldt[5]] then rednet.broadcast(rcmdlst[cldt[5]])
        if cldt[5] == 45 then cldt[3] = true end
    elseif cldt[4] == "pda_key" and rcmdlst[cldt[6]] then rednet.broadcast(rcmdlst[cldt[6]])
        if cldt[6] == 45 then cldt[3] = true end
    elseif cldt[4] == "rednet_message" then print(cldt[5]..": "..cldt[6])
        if cldt[6]:find("^send") then rednet.send(cldt[5],io.read()) end
    elseif cldt[5] == "S" then write("Enter message") rednet.broadcast(io.read()) end
until cldt[3]
Ralnick #11
Posted 18 October 2012 - 02:39 AM
Sweet.

let me ask you this.

you already have a remote control set up using the CC computer is it possible to use that same program with a new item block kind of like (as an example) the powercraft mod for the "weasel". If you are holding or have in your action bar the activartion crystal you can control the weasel.


in this idea, you enter the password for the turtle that you want to control and as long as the PDA is in your action bar you can control it with the number keys.

anyway thanks for the hard work.
ChunLing #12
Posted 18 October 2012 - 05:00 AM
Well, the CCPortable PDA requires that you have it selected and "open" to send pda_key and pda_char events back to the computer that has the receiver. So just having it in your action bar won't work with that mod. I believe that the CCInput mod also requires that you have the remote selected and turned on, not just have it in your action bar.

Of course, rumblings are that in an upcoming version of ComputerCraft there will be a PDA item that will have the ability to run simple programs and send/receive rednet (but will not be able to interface with peripherals or redstone as the current "desktop" computers do). Such an item should be able to run the control program directly to control the turtle without the need for modification.

But until them I'm working on making it so that the CCPortable PDA can act as a complete interface for a computer. It's a bit slow going, though. The PDA currently has little functional support, so it's kinda starting from scratch.
Ralnick #13
Posted 19 October 2012 - 01:25 AM
is there a way to add more commands to this?

for example adding: 7 - run "program name"
ChunLing #14
Posted 19 October 2012 - 02:17 AM
Yes. First add the new function to the table rctfncs in the clfn program on the turtle. For something that ran another program, the function would look like:
runfl = function()
    trply("send file path/name")
    repeat cldt[2], cldt[3] = rednet.receive() until cldt[2] == cldt.rcID
    shell.run("..cldt[3]..")
end,
THIS CODE NOT TESTED, but I think it will work.

Then you add the name of the function to the table rcmdlst at the start of the rctrl program on the control terminal.
[8] = "runfl"
8 is the key code value for the "7" key. Then, when you press 7, the rctrl program sends the message "runfl".

To test out a function, try using the "ldstrng" command. This prompts the turtle to accept a lua code string and attempt to run it. You can access the text sending function by pressing Shift+S in the rctrl program, this prompts you to enter a text string to send to the turtle. If you send "ldstrng", the turtle will reply with "send lua code chunk" and you can then type in a function for it to execute. This functionality allows you to command the turtle to do pretty much anything it can be programmed to do, but it's a bit unwieldy and dangerous. Using it to test a potential new function before adding it to clfn is a good use, though.

Be aware that the virtual environment created by loadstring doesn't have access to any of the existing data/code loaded by clfn, so you can't do things like call rctfncs.gox and have it work. Also, while loadstring can recover from a string that doesn't parse as lua code, a syntactically correct string can then throw an error that will terminate clfn.
ChunLing #15
Posted 19 October 2012 - 02:24 AM
On another note, I've managed to put together a version of the control program that uses a PDA (from [MC 1.2.5 / CC 1.4.1] CCPortable - And not even overpowerd) for the input/feedback. But it's kinda ugly and clunky at this point. It's nice to be able to get the feedback and do text string entry remotely, but man, ugly code ahead:

I'm still experimenting with whether there is a way to make it so that the PDA reconnects remotely after a logout/login event, so far looks like no. But this does seem to work. You need a CCPortable receiver attached to your control terminal, and a PDA. Use the PDA on the receiver to attach it. I posted a simple testing program in the CCPortable thread that lets you get a feel for how the PDA functions, if you haven't used it before.

Oops, gotta hide that ugly code. Help making that work better will be appreciated, but not expected. Cause it's pretty ugly.

Latest versions are linked in the top post. (Why did I post so many versions?)
Edited on 24 October 2012 - 10:43 PM
Ralnick #16
Posted 19 October 2012 - 11:34 AM
ok so I got the "CCPortable" (NICE work G3R4RD. ) installed and have a receiver and PDA connected, I am guessing your program needs to be ran from the PC itself. or does it go to the Turtle. I want to control?


i installed the "test" program form CCPortable. tried to run it.. gives error — pdatest:38: attempt to index ? (a nil value)

i installed the program from here.. pdaremote (I called it that for ease of use). it works for the most part. but I might not have things in the right area. tells me I pressed a button says the test loop is active.. but if I am reading the code correctly.. (i am lua ignorant). it should allow access to turtle. for movement and the like.

let me know if I can help… (remember I am LUA ignorant)

PS: would it be possible to get this on pastebin (so i don't have to reload game every time) ?
ChunLing #17
Posted 19 October 2012 - 06:26 PM
Sorry, the rcpda program is something of a Frankenstein. If the test loop is working, then you need to press Shift+X to exit the test mode. Then you should receive a prompt to enter the password for the turtle. This will loop until a turtle responds with "password accepted", after which you should be in control of that turtle.

The code on the peripherals forum did work but wasn't throughly bug tested. Looking at it, I can only guess what went wrong. I should go ahead and post a revision.

By the way, if you change the names of the programs, you need to change the names of their shell.run references. On line 58 of the rcpda program, it has "strtfl.writeLine("shell.run("rcpda",""..pdat.chnl.."")") strtfl.close()" This saves the restart information for the program so that the program will autorun on startup. You can change "rcpda" to the new program name, or just delete that line (along with the preceding line which opens the startup file for writing). The corresponding line in clfn is at line 111 (in the latest version of the code) "hndl.writeLine("shell.run("clfn",1,""..cldt[1].."")") hndl.close()". It is not recommended to delete this as it properly allows an activated turtle to restart after a game/chunk save/load or other reboot event.

I didn't want to pastebin until I had something that worked on other computers, but I suppose it is time for an initial beta. I'll post a link once I have it posted.
ChunLing #18
Posted 19 October 2012 - 07:30 PM
Okay, current versions of clfn and rctrl posted on pastebin. These programs are considered provisionally ready for initial beta release. Feedback on errors/bugs/usability is still needed.

The suggestion for a "run program" function will have to wait on tighter division between global and local scopes for some of the data, as the global data usage in clfn currently may conflict with other programs running correctly.
Ralnick #19
Posted 19 October 2012 - 09:18 PM
i have to be doing something wrong here, I have rcpda clfn and rctrl all installed on a command PC and a turtle.

i used rcpda got the test loop tested – shift X – for control and it asked for confirmation Password I enter it via PDA and it says entered then returns to enter text – waiting for the password – screenshot

I look on the turtle. and it is saying input from PDAEnter confirmation password for remote turtle control
input form PDA screenshot

no where does it allow a password to be entered or confirmed via turtle access.

pda and turtle are talking just not getting the option to enter info from turtleOS

please let me know if I am doing something wrong.
ChunLing #20
Posted 20 October 2012 - 12:22 AM
Did you start clfn on the turtle, put it in remote mode, and give it a password? The turtle needs to be in remote control mode, waiting for a password. Otherwise the password send on the rctrl and rcpda programs never gets the password accepted message back. You can start the turtle in remote mode with a given password by using "clfn 1 password" from the command line.

I should probably rewrite those, eventually I'll want to support selective control of multiple turtles, and the password loop only really allows the program to work with a single turtle at a time.

Yeah, I took a close look at your second screen. You're running rcpda on the turtle, with it positioned on top of a receiver block. That won't work, you need a control terminal setup (like where you would have run rctrl before, but with the pda receiver added), and that communicates with the PDA and interprets the PDA input as rednet commands for the turtle. You can't use the PDA directly on the turtle because once the turtle moves, it won't be next to the receiver anymore and you'll lose input capability.
Edited on 19 October 2012 - 10:28 PM
Ralnick #21
Posted 20 October 2012 - 02:08 AM
thanks for all the help with this..
looks like it is working.. the info for control of the turtle is too big for screen but if you know what it says on the PC then you shouldn't have much of a problem. I am guessing if you wanted to go out long distance the networking program would need to be running some how in the background or have a satellite system up and working… no idea how this would work but for now.. playing around with it.. is fun..

nice work to all involved with this.
ChunLing #22
Posted 20 October 2012 - 03:18 AM
I was going to fix that (or rather, I already tried to fix it because the first time all the instructions were on a single line and you could only see the very first bit of it), but got distracted. It's hard to think of how to compress what I want to say into the new space limit.

And I really am going to eventually rewrite the rcpda to allow you to switch control from one turtle to another, and I have a rednet relay host that allows me to use GPS hosts as two way relays. So I'll be changing the control description some anyway.

Eventually, I'd hope that someone will develop a program to let a rednet computer coordinate several turtles, perhaps even dynamically picking up new turtles ("enlisting" them, so to speak). I'm not currently up for that project myself, but I've tried to make sure that the clfn program has everything necessary to make it possible.
ChunLing #23
Posted 20 October 2012 - 08:57 PM
Okay, newest version of rctrl. This version allows you to switch receiver ID and only sends to that turtle. Thus, you can have multiple turtles set up for remote control, and just switch between them. If this works correctly, then I'll update the rcpda program to have the same functionality.

Kinda wish there was a button to add the spoiler tags.

Latest versions are linked in the top post.
Edited on 24 October 2012 - 10:14 PM
ChunLing #24
Posted 21 October 2012 - 12:17 AM
Here's an initial conversion of rcpda to support switching receiver ID.

The interface with the PDA screen may be a bit confusing. Right now I'm using line 0 on the PDA as the input line, but the screen is updated with older messages higher (which is the normal way to read things in a chronological order). Partly that's because line 0 is the part of the interface that is marked out distinctly, but this is just a matter of how the png is arranged. I could as easily make line 20 the input line and have the text above it, or keep line 0 as the input and have the text cascade down with the older messages toward the bottom.

Also, there are several other PDA functions that I'm not using, like the icon, title, or alerts.

Latest versions are linked in the top post.
Edited on 24 October 2012 - 10:15 PM
Ralnick #25
Posted 21 October 2012 - 06:03 AM
nice work.

Will try them out..

rctrl does not have option to get password for turtle access ..

old rctrl
Spoilerrcmdlst = {
[0] = "bmb",[79] = "place",[80] = "back",[81] = "ddn",[75] = "turnLeft",[76] = "tnl",
[77] = "turnRight",[71] = "placeUp",[72] = "dfd",[73] = "dup",[82] = "placeDown",
[83] = "drop",[74] = "refuel",[78] = "slct",[181] = "gpshst",[55] = "gpslct",[28] = "pckup",
[210] = "place",[211] = "dig",[199] = "dropUp",[207] = "dropDown",[201] = "up",[209] = "down",
[200] = "forward",[208] = "back",[203] = "turnLeft",[205] = "turnRight",[26] = "digUp",
[27] = "digDown",[51] = "suckUp",[52] = "suckDown",[45] = "trmn8RC",
}
local cldt = {}
function opnmdm()
for i,v in pairs(rs.getSides()) do
if peripheral.getType(v) == "modem" then
if not rednet.isOpen(v) then rednet.open(v) end
return true end
end
return false end

shell.run('clear')
if not opnmdm() then print("Modem Access Error") return false end
repeat
print("Enter confirmation password for remote turtle control")
rednet.broadcast(io.read())
cldt[1],cldt[2] = rednet.receive(2)
if cldt[1] then print(cldt[1]..": "..cldt[2]) end

until cldt[2] == "password accepted"
print("Use numberpad to control turtleID"..cldt[1].."n"..[[284693 for dig-moves, 5 to tunnel
170 to place[Up/Down]
'.' Home End, to drop[Up/Down]
Enter, <, >, to suck[Up/Down]
Del, [, ] to dig [Up/Down] without moving
Direction Keys and PgUp/Dn to move
Press x to end Remote Control]])
cldt[3] = false
repeat
cldt[4],cldt[5],cldt[6] = os.pullEvent()
if cldt[4] == "key" and rcmdlst[cldt[5]] then rednet.broadcast(rcmdlst[cldt[5]])
if cldt[5] == 45 then cldt[3] = true end
elseif cldt[4] == "rednet_message" then print(cldt[5]..": "..cldt[6])
if string.find(cldt[6],"^send") then rednet.send(cldt[5],io.read()) end
elseif cldt[5] == "S" then write("Enter message> ") rednet.broadcast(io.read()) end
until cldt[3]

new rctrl
Spoilerlocal rcmdlst = {
[0] = "bmb",[79] = "place",[80] = "back",[81] = "ddn",[75] = "turnLeft",[76] = "tnl",
[77] = "turnRight",[71] = "placeUp",[72] = "dfd",[73] = "dup",[82] = "placeDown",
[83] = "drop",[74] = "refuel",[78] = "slct",[181] = "gpshst",[55] = "gpslct",[28] = "pckup",
[210] = "place",[211] = "dig",[199] = "dropUp",[207] = "dropDown",[201] = "up",[209] = "down",
[200] = "forward",[208] = "back",[203] = "turnLeft",[205] = "turnRight",[26] = "digUp",
[27] = "digDown",[51] = "suckUp",[52] = "suckDown",[45] = "trmn8RC",
}
local function opnmdm()
for i,v in pairs(rs.getSides()) do
if peripheral.getType(v) == "modem" then
if not rednet.isOpen(v) then rednet.open(v) end
return true end
end
return false end

shell.run('clear')
if not opnmdm() then print("Modem Access Error") return false end
local rcID,tvnt = nil
repeat print("Enter receiver ID> ")
rcID = tonumber(read())
until rcID
print("Sending input to "..rcID..", press "h" for help")
while rcID do
tvnt = {os.pullEvent()}
if tvnt[1] == "key" and rcmdlst[tvnt[2]] then rednet.send(rcID,rcmdlst[tvnt[2]])
elseif tvnt[1] == "pda_key" and rcmdlst[tvnt[3]] then rednet.send(rcID,rcmdlst[tvnt[3]])
elseif tvnt[1] == "rednet_message" then print(tvnt[2]..": "..tvnt[3])
if tvnt[3]:find("^send") then rednet.send(tvnt[2],read()) end
elseif tvnt[2] == "S" then write("Enter message> ") rednet.send(rcID,read())
elseif tvnt[2] == "R" then write("Enter new receiver ID> ") rcID = tonumber(read())
elseif tvnt[2] == "X" then print("Remote Control terminated: Enter new receiver ID> ")
rcID = tonumber(read())
elseif tvnt[2] == "H" or tvnt[2] == "h" then print([[Use Shift+R to change receiver ID
Use Shift+S to send text string
Change ID to nil to exit rctrl
Use numberpad to control turtles
284693 for dig-moves, 5 to tunnel
170 to place[Up/Down]
'.' Home End, to drop[Up/Down]
Enter, <, >, to suck[Up/Down]
Del, [, ] to dig [Up/Down] without moving
Direction Keys and PgUp/Dn to move
Shift+X to end Remote Control]]) end
end


looks like the new code took out the password receive and verify function.
but I could be wrong.


looks like the same thing for rcpda,

Spoilerpdfnc.wrtln("Enter confirmation password for remote turtle control")
rednet.broadcast(pdfnc.rdln())
cldt[1],cldt[2] = rednet.receive(2)
if cldt[1] then pdfnc.wrtln(cldt[1]..": "..cldt[2]) end
until cldt[2] == "password accepted"
pdfnc.wrtln("Use numberpad to control turtleID"..cldt[1])

but again I could be wrong.
Edited on 21 October 2012 - 05:20 AM
ChunLing #26
Posted 21 October 2012 - 11:31 AM
Yes, the password verification is no longer prompted. This is due to the fact that you can switch 'channels' from one turtle to another, and the turtles don't advertise that they are available for remote control, they only wait for the correct password and then communicate only with the ID that sent it.

You have to input the ID of the turtle you wish to control, and then use the Shift+S option to send the password. The turtle should respond with "password accepted" as before. Shift+S is also necessary to activate several of the functions that require additional parameters or input, such as the turtle commands "turtle.select(slot)", "turtle.getItemCount(slot)", and "turtle.compareTo(slot)", and the gox, srvfl, rcvfl, and ldstrng commands. To pass a parameter, simply put a space between the command and the parameter–i.e. "select 1".

To switch to controlling a different turtle, use Shift+R to change the receiver ID. Changing the ID to nil will terminate the program (but not necessarily take any turtles out of remote control mode, so you might be able to restart the program and continue controlling them).
Ralnick #27
Posted 21 October 2012 - 05:59 PM
ahhh ok.. got it now…

so enter the ID of the turtle with shift r and if turtle is waiting for a password enter that with shift s. then turtle is active..

so each time if needed to change to a different turtle. Shift r for turtle ID — IF new Turtle then shift s for password.

Got it.
ChunLing #28
Posted 21 October 2012 - 08:12 PM
It's possible to take out the password and sender ID checks if you're only going to use it in SSP…and actually, the current system isn't quite secure enough for heavy SMP, for security the clfn should require input of the controller ID rather than granting access to whoever sends the password first. The problem is just making sure the the right controller ID is input, it seemed more user-friendly to use a user-set password.

What do you think, easier to set the controller ID from the outset or keep using the password?
Ralnick #29
Posted 21 October 2012 - 08:54 PM
.

… What do you think, easier to set the controller ID from the outset or keep using the password?

with trying to remember what turtle is what.. and what password is what.. it would be near the same either way.

I am mainly single player (for now) but turtle IDs are maybe the best idea. at least you can write them down or something.

would it be possible to get a few other commands list in there.. besides "turtle.select(slot)", "turtle.getItemCount(slot)", and "turtle.compareTo(slot)", and the gox, srvfl, rcvfl, and ldstrng commands. .. refuel would be a good one. or being we are able to enter text now. maybe a Shift - V or something like that to send a command to run a program if it is in the turtle.

just an idea…

thanks for all the work you have done,.
ChunLing #30
Posted 21 October 2012 - 09:07 PM
You should be able to access the turtle.refuel(n) command as well as all the other turtle API. Just "refuel n" All the commands that take parameters need to be activated through the Shift+S message send rather than by key, but you can still activate all of them.

I think that I will go ahead and use inputting the controller ID (not the turtle's ID) and have the message say something like "control of turtle ..os.computerID().. handed over to rednet ID..cldt.rcID". That way you have a reminder of which ID is the turtle.

Still need to test the execute file function. Then I'll replace the password with a specified controller ID and paste the result.
ChunLing #31
Posted 22 October 2012 - 12:18 AM
Okay, here's the new clfn. It now has a very simple xqtfl function that runs a program (still need to check if it can do parameters and stuff, it should be possible if you format the run string correctly). I also changed the security so that you enter the controller ID rather than a password, and the turtle can only be controlled by rednet messages from that ID. Also made some minor adjustments to some of the feedback.

]I also did some revision to rcpda, so that the wrtpdln function can handle longer strings by splitting it onto multiple lines

A lot of the cases where I was getting messages too long to display were just because I was having the turtle send overly verbose replies, but I figured that I might as well make it so that longer messages would be supported.

I'll pastebin these after some more testing.

Latest versions are linked in the top post.
Edited on 24 October 2012 - 10:40 PM
ChunLing #32
Posted 22 October 2012 - 04:26 AM
Or, I will decide to go through and make a bunch of changes to the code. This version of clfn should have very little noticeable difference in functionality, but has been revised to better support automatic feedback to the controller. This may be useful in the project to create an automated controller that coordinates several (or perhaps several hundred?) turtles remotely.

I did add a function to set off the GPS array launcher, but it doesn't pass the values correctly yet (fixed). The commands that require a string of additional information now take it as a parameter with the command, so instead of using Shift+S to send "gox" and then being promped to send the command string, you send "gox [f4l]4" ("[f4l]4" is a command string that makes the turtle move about in a square, returning to it's original position/facing). The same is true for the file handling options, they take the command followed by the filename, separated by a space. This should streamline the use of these commands quite a bit. If not, I can revert the behavior easily enough.

Latest versions are linked in the top post.
Edited on 24 October 2012 - 10:41 PM
ChunLing #33
Posted 22 October 2012 - 10:07 PM
Okay, revisions of clfn and rcpda, and a first look at rnhst, a GPS host replacement that allows relaying messages as well as sending and receiving files and some other stuff. I include it because this version of clfn places rnhst arrays rather than conventional gps arrays…I'm basically never going to use the existing gps program again. So, getting down to it, here's the new clfn:

The new rcpda:

And the brand new rnhst:
At some point I'm going to have to write up a full user guide, because these programs are all somewhat less basic than when I started.

Okay, fixed now…and fixed again. But be sure and check the top post for pastebins of the most recent versions.

Latest versions are linked in the top post.
Edited on 24 October 2012 - 10:42 PM
Ralnick #34
Posted 22 October 2012 - 10:17 PM
will this new rnhst extend the network for the pda and turtles. for movment and control?

.
ChunLing #35
Posted 22 October 2012 - 11:04 PM
Yes. I've been using it myself, and you can control a turtle 200 meters from the control terminal (further than that, I think that you risk the control terminal's chunk being unloaded, but if you have world anchors, then there is no real limit).

Setup is…a little tricky. What you want to do is start rcpda, and then tell it to talk to the rnhst node rather than directly to the turtle. You start the turtle and give it the ID of the array node as well. Then you send "rly ID" from rcpda to the rnhst node. After that, the turtle recognizes all messages from that rnhst node as valid, and sends it's input back to the node. The node should then relay those messages to you. Conversely, when you send it any message that is not a relay command, it relays it directly to the turtle.

This needs more testing, but it should be working…or not…looks like I broke something. I need to work on this a bit, for now the rcpda and clfn should be working, but rnhst isn't relaying my messages anymore.
ChunLing #36
Posted 23 October 2012 - 12:02 AM
I made some late night edits to support the authorized user option in rnhst, and messed up the logic. But it works now.
Ralnick #37
Posted 23 October 2012 - 04:42 AM
ok so my understanding is startup rcpda then connect the pda shift x then use pda to send rly plus the id of the pc receiver "rly 10" for example. that sends a command to the turtle and to the pc above to send receive.
correct?
love the range boost with this.
thanks
ChunLing #38
Posted 23 October 2012 - 04:57 AM
You need to set your pda to communicate with the rnhst node ID, then send "rly ID" (ID being the ID of the turtle/computer on the other side of the node). After you have the relay set on the node, it should be just like if you were communicating with the other turtle/computer directly except that the messages you get back are from the relay node. Also be sure to set the turtle to receive from the relay node rather than directly.

There were some usability errors in the previous version of rnhst, it works for simple relay but there were problems that would undermine a network. But as this older version does work for the remote control purpose, I'll be doing rnhst updates in the Programs forum.
Ralnick #39
Posted 24 October 2012 - 12:26 AM
sorry haven't been playing… umm where does the new program go.. into the computer or turtle?

and I am guessing the new Control PC is the one with the satellites. so no longer needs a land based PC for connection to PDA before the test loop is closed with Shift X?
ChunLing #40
Posted 24 October 2012 - 12:54 AM
The rnhst can work on a wireless turtle or a wireless computer, but it should probably be on a computer because it isn't meant to move or do anything but receive/send rednet. I use them in place of GPS arrays, since they have that functionality.

You can also give them a list of allowed users, to restrict unauthorized access to the command options (including "PING", the gps hosting function). But there's not much point in that unless you're in SMP. If you are, then you'll want the version posted in Programs, since that one has improved logic and better access control.
ChunLing #41
Posted 25 October 2012 - 12:02 AM
Praise the Lord and pass the ammunition, the latest bugfix for clfn is up. This version contains some tweaks and repairs to the bugged remote file functions and the operation of the GPS Array Launcher. The GPS Launcher now checks for whether rnhst is in the rom/programs directory, and if not then checks if there is a local copy on the turtle, if not then it requests that the file be copied to it and terminates. I'll be going through and trying to clean out bugged versions (or just referencing them all to the top post, I guess).
Ralnick #42
Posted 26 October 2012 - 12:13 AM
working great. PDA and rcpda connect at start up. (remember to put PDA in action bar if not there) then with PDA hit SHIFT-X enter the ID of the terminal (normally the relay satellites at lvl 250 or so) get one of thier IDs to use. then shift s to enter the command "rly tID" (tID = Turtle ID) then you have full access to that turtle.

ZOMG!! the Range increase with the new rnhst is great. I was playing around with it. and yeah, almost lost sight of the hut!

"gox" programs work great. (if you know what you are doing.(I don't! my hut can testify to that))

"select n" to change the slot for fuel, if you need to "refuel" plus a bunch more.

I am sure there will be a how to use coming out sooner or later as things get more settled. With all available commands listed out for us.


I really think this is a great remote program for the turtles.

Thanks for the time and work it took to get this working… +1
ChunLing #43
Posted 26 October 2012 - 02:17 AM
You can also just press Numpad + to cycle through your inventory slots, and get feedback on how full they are (no way to tell what is in them unless you are very clever about it). You can use the built in refueling command by pressing Numpad -, this only works reliably if you use Numpad + to cycle your inventory selection rather than sending "select n", but it gives feedback on how much fuel you have, even if you use it on a slot that doesn't contain fuel.

I'm currently working on an improved interface for the rcpda to make use of the administrator functions of the rnhst nodes. I'm also considering how to upgrade the rnhst program to support easier administration.
Ralnick #44
Posted 26 October 2012 - 04:10 AM
oh now that is cool.. did not know that… so yeah.. refuel a couple of times when the turtle is near, then send it to do it's job…just remember to give it lunch (a full slot of coal) or something to get it home after a hard day at the mine

more and more reasons to use this program…
ChunLing #45
Posted 26 October 2012 - 05:16 AM
I've got to post a complete user's guide up top, sometime. But for now I'll focus a bit on the rcpda/rnhst upgrades.
ChunLing #46
Posted 26 October 2012 - 01:17 PM
A new version of rcpda is up. This one contains a menu for easier access to the rnhst administrator options and support for using remote FTP to rnhsts. It is likely that there may be bugs, recommend calling it xrcpda or some other name to avoid overwriting existing rcpda, and only installing it on a single computer. This is designed to work with revised commands in the latest version of rnhst (notably flsrv and flrcv, previously called srvfl and rcvfl), as well as the new access command which sets permissions for the rnhst.
Edited on 26 October 2012 - 11:21 AM
dustpuppy #47
Posted 26 October 2012 - 05:33 PM
The programs you make are good, but there is 1 very important reason, why i will not use them. flsrv, flrcv, srvfl, rcvfl, rnhst <- that's why. If i have a code, i want to read it easy and that's impossible. Why are you not using names that will tell on the first view what they are for?
ChunLing #48
Posted 26 October 2012 - 07:31 PM
Sorry, it's a habit. The problem with an identifier that is easy to read as meaningful is that it is inherently untrue at the outset unless it is predefined as part of the language or implementation you're using. When I'm coding, I need to see "through" what I intended for an identifier to mean to the code that has assigned it a value. Identifiers that are clearly not words helps me to do this.

I know that this is opposite of how most people approach readable code, my brain just works opposite I guess.

It should be easy enough to go through and assign meaningful terms by find/replace. If you consistently change every instance of an identifier then codewise it is still fine. Maybe I should use released versions with that already done, but I'm not good at picking identifiers that will be meaningful and transparent for others since for me meaningfulness and transparency are opposed.
ChunLing #49
Posted 28 October 2012 - 12:13 AM
New version of clfn posted with a new command 'chst' which causes the turtle to place a block from slot 16 and attempt to dump everything else into that block. It can be accessed by gox using "C".

I've got to write a usage guide for all of this one day, so help me. Right now I just read the usage out of the code, but probably not everyone can do that.
ChunLing #50
Posted 28 October 2012 - 05:58 AM
Okay, new user guide for clfn (and latest bugfix/update for clfn) posted in the top post.

If you see something (meaning a bug), say something! For current purposes, inaccuracies in the user guide count as bugs.

This topic is now marked "Hot", and most of the posts are by me :D/>/>

Save me from the mortification, post a bug report today!
Edited on 28 October 2012 - 05:00 AM
ChunLing #51
Posted 28 October 2012 - 11:11 AM
Okay, new user guide for rctrl and rcpda is in the top post. I've missed a whole bunch of playing minecraft to write those guides. Hopefully they're helpful.
Cruor #52
Posted 28 October 2012 - 11:23 AM
ChunLing, you do know that there is a edit button right? At the bottom of the post? found it yet? yeah… use it. So this is how you manage 50+ posts a day :D/>/>
Tiin57 #53
Posted 28 October 2012 - 11:39 AM
ChunLing, you do know that there is a edit button right? At the bottom of the post? found it yet? yeah… use it. So this is how you manage 50+ posts a day :D/>/>
Unfortunately, too many people do this.
ChunLing #54
Posted 28 October 2012 - 12:03 PM
I'm just happy someone else is reading my posts. I am editing the main post, I just want to let people know when a new version is available. Just in case anyone is interested.
Ralnick #55
Posted 28 October 2012 - 08:17 PM
i have said most of everything I can say.. good program.. works great.. havn't updated to the new clfn, rcpda being the system i have now is good for me.. I understand it.. no need to change what is already (now, not always in the past) simple. not sure I need a menu for commands.

I have seen this program grow so much over the last few weeks, from a basic remote to a fully functioning long range remote with features that are great for GPS, intergrated 2 if not more programs from others that has giving a lot more control to the user.

A suggestion I could give would be to maybe put up some screen shots of the program and the new menu system. that might give others a better understanding of the program and, why not a Video showing what the program can do.. words are great.; but maybe a video will be better to understand for some. not everyone can understand code (I know i can't)

anyway.. I am here if you need testing on something new. not sure I really want to change what i already have.

unless ofcourse it addes something new like a inventory and crafting system, the turtles know where things are and can get them and/or make them (BC2 pipes are great but i think it causes lag when they are busy with a few quarries and crafting tables)

thanks for the hard work..

PS IMO posting on own thread for an update to what has changed or has been added to an already read post is not over posting, I would not know about most changes to this and meny other programs if the newest posts did not tell me there were changes.



New version of clfn posted with a new command 'chst' which causes the turtle to place a block from slot 16 and attempt to dump everything else into that block. It can be accessed by gox using "C".

I've got to write a usage guide for all of this one day, so help me. Right now I just read the usage out of the code, but probably not everyone can do that.

what would be cool is if the turtle would return to the same chest and continue to fill it. Not have to place a new chest a few minutes later if it is clearing a large area .

or maybe have a slave turtle go and get the get the stuff from the mining turtles chest. (I think there was a post or something like that about this same thing on a different program. ) the gps relay system that is active now in this program is great… extends the range of control but are there some other ways to use it.. for automation of turtles. but I am guessing it would need help from other sub modes like ccsensors or the like…

anyway if I was as able to write code I wouldn't have others doing all the hard work. and me just throwing ideas..

again Great program,

thank you.

EDIT:
I am guessing if a few of the well known porgramers got together and worked together to make a really good program for all of ComputerCraft, using turtles and the Computers along with the sub mods like CCSensors, but that might be asking too much.
Edited on 28 October 2012 - 07:28 PM
ChunLing #56
Posted 28 October 2012 - 10:27 PM
I'm not really going to incorporate any AI into clfn itself because if I do create an AI I want it to have central control of all the turtles (and rnhsts), and making clfn have too much autonomy would interfere with that. So, for now you have rcpda allowing efficient control of multiple turtles, but eventually I'm thinking of rcpda being primarily a tool to talk to the local central computer. Envisioning something like this:
   # #--------# #
	/	#					# 
  /	  |						  
T	  M-C----Y			   T  
You get to be Y, someone wandering about with a pda. C is the rcpda computer and receiver. M is the master computer, which controls all the rnhsts (the #'s) by rednet and relay. Then the T's are turtles being controlled by the signals relayed from the central computer. Thus clfn, the program run by the turtles, is the bottom layer of control. The rnhst nodes are kinda the next level up. Right now I skip over M because that's going to be really crazed to create (I'm still kinda hoping that someone else does it for me), and the system is controlled from the rcpda program, but eventually rcpda will really just be the interface to a system controlled from M.

There will have to be multiple master computers, since there are constraints of the chunk loading radius. But that makes things easier, it means that when the master computer does eventually contain an internal map of the area it controls, the map will only be so big. You can then just input the map of the area the way you want it and the master control will attempt to use turtles to do that. Is all very much in the future.

When I know that rnhst and clfn work reliably, then I feel I can proceed with more confidence using them as a basis for the master control program (which as of yet does not have a name).

The ascii art, why is it so difficult to make?
Edited on 28 October 2012 - 09:29 PM
Ralnick #57
Posted 02 November 2012 - 06:57 PM
let me know if you get anything going… I am still watching this thread.. and willing to help if needed.

master computers… sounds like fun.. :D/>/>
ChunLing #58
Posted 03 November 2012 - 04:37 AM
I think I may need to add a couple of functions to clfn. Then I need to figure out which part to make first, the inventory system, the crafting bots, or the excavation and building functions. Of course it pretty well has to be the inventory system first (gugh). Oh well. I guess that it should be single turtle to chest array style, that's the most expandable. Gotta track stack sizes and chest content…gugh. For a while the master control computer sounded fun, now I remember why I just wanted a remote control turtle.