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

Auto Crafty Turtle

Started by meigrafd, 25 July 2015 - 01:25 PM
meigrafd #1
Posted 25 July 2015 - 03:25 PM
Hi all.
First off: sorry for my bad english


I've created a program for 'Crafty Turtle' which automatically craft Recipes solong it haves needed Items or it had a given Redstone signal..

Over this way Auto Crafting is faster than with the classic 'Auto Workbench' and also more reliable.


Description:

A Turtle have a total of 16 Slots: 4 rows with each 4 columns. (4 x 4 = 16)
For crafting the first 3 row and each 3 columns are used and must match an valid recipe. All other Slots must be empty.
E.g.:
x | x | x | -
x | x | x | -
x | x | x | -
- | - | - | -
the x fields are used for the recipe.

Place a valid recipe into Turtle before first Script Start up.

You can place up to 5 Chests around the Turtle - one on each Side - for Items. The 6.Chest needs to be for the crafted Stuff (drop/output). But only use one Chest for one Type of Item!

On first start the Script will scan all Items and saves its Name, Damage and Count locally into files: Main directory is 'recipe' and for each slot it creates a sub-directory with files 'name' , 'damage' and 'count' in it.
The Reason why it also saves Damage is because some Items have the same Name (e.g.: 'Tin Plate' and 'Iron Plate' from IC2) but different Damage values.

It saves the recipe for future startups - so you can give the turtle a label and place it somewhere else without inserting the recipe again.. On next start it reloads it from the files. Delete the directory 'recipe' if you want to use another recipe..

After the recipe got saved it tries to identify the Items from the Chests around the Turtle - except the OutDirection side (where it drops the crafted stuff to). The fastest Sides are: "top", "bottom" or "front". For all other it must turn around..
The Turtle doesnt need Fuel because it doesnt move.

E.g.:
If you want to craft '60k Coolant Cell's you need 'Tin Plate', 'Iron Plate' and '30k Coolant Cell'.
So you place one Chest for 'Tin Plate' on the "bottom" of the Turtle.
Another Chest for 'Iron Plate' on "top".
One Chest for '30k Coolant Cell' on the "front".
The Output-Chest can than be "left"..
After the recipe got saved the Turtle will suck one Item from a valid Side and compares it with the recipe, for each slot, and drop it back before it goes to next side.
After that the Script knows the Chest-Side's for each slot.

If theres a Redstone signal on the configured Side (e.g. "right") it then starts crafting as many Items in the Chests are available.

I'm using Applied Energistics (ME) for Input and Output and also the 'ME Level Emitter' as Redstone signal. But thats up to you :)/>


I hope everything is clear and easy to understand?


Get the code:

pastebin get Rq4Yt9Zx startup

Always credit " meigrafd " if you want to use something of it. Thanks!


Spoiler

--[[

v0.1 by meigrafd @ 24.07.2015

Requires:
   ComputerCraft >=1.5

A Turtle have 16 Slots. For crafting the first 3 rows and slots are used and must match an valid recipe. All other Slots must be free!
Place a valid recipe into Turtle before first Script Start up.
Place Chests around the Turtle as Input and Drop.. Only use one Chest for one Type of Item!
Script will inspect each Side and trys to detect the Item in each Chest.
After that it saves all data for future startups and starts auto-crafting.
For a later use of another recipe simple delete the directory 'recipe'.

--]]


---[[ CONFIG - START ]]


-- Chest Side for crafted item. Only valid sides: top, bottom, left, right, front, back
-- NOTE: Fastest will be "top", "bottom" or "front". For all other it must turn around..
-- BTW: Put the most needed Items in the 'fastest' chest to speedup crafting :)/>/>/>
local OutDirection = "front"

-- Redstone signal Side to turn crafting on/off.
-- NOTE: "left" doesnt work.
local ControlSignal = "right"


---[[ CONFIG - END ]]


---[[ functions ]]


-- http://stackoverflow.com/questions/1426954/split-string-in-lua
function split(pString, pPattern)
	local Table = {}  -- NOTE: use {n = 0} in Lua-5.0
	local fpat = "(.-)" .. pPattern
	local last_end = 1
	local s, e, cap = pString:find(fpat, 1)
	while s do
		if s ~= 1 or cap ~= "" then
			table.insert(Table, cap)
		end
		last_end = e+1
		s, e, cap = pString:find(fpat, last_end)
	end
	if last_end <= #pString then
		cap = pString:sub(last_end)
		table.insert(Table, cap)
	end
	return Table
end

function stringMatch(text, find)
	if string.find(string.lower(text), string.lower(find)) then
		return true
	else
		return false
	end
end

function lappend(list, delimiter, value)
	if list == '' then
		local list = value
	else
		local list = list..delimiter..value
	end
	return list
end


local turn = function(side)
	if side == "left" then
		turtle.turnLeft()
	elseif side == "right" then
		turtle.turnRight()
	elseif side == "front" then
		turtle.turnRight()
		turtle.turnRight()
	elseif side == "back" then
		turtle.turnLeft()
		turtle.turnLeft()
	end
end

local suck = function(direction, amount)
	amount = amount or 1
	s = {
		["top"] = function() turtle.suckUp(amount); end,
		["bottom"] = function() turtle.suckDown(amount); end,
		["front"] = function() turtle.suck(amount); end,
		["left"] = function() turn("left"); turtle.suck(amount); turn("right"); end,
		["right"] = function() turn("right"); turtle.suck(amount); turn("left"); end,
		["back"] = function() turn("back"); turtle.suck(amount); turn("front"); end
	}
	s[direction]()
end

local drop = function(direction, amount)
	amount = amount or 1
	d = {
		["top"] = function() turtle.dropUp(amount); end,
		["bottom"] = function() turtle.dropDown(amount); end,
		["front"] = function() turtle.drop(amount); end,
		["left"] = function() turn("left"); turtle.drop(amount); turn("right"); end,
		["right"] = function() turn("right"); turtle.drop(amount); turn("left"); end,
		["back"] = function() turn("back"); turtle.drop(amount); turn("front"); end
	}
	d[direction]()
end

local craft = function()
	turtle.select(OutSlot)
	turtle.craft()
	drop(OutDirection, turtle.getItemCount(OutSlot))
	Count = Count + 1
	print("crafted: "..Count)
end

local saveRecipe = function()
	print("Trying to get Recipe..")
	for i=1, #InSlots do
		local data = turtle.getItemDetail(InSlots[i])
		if data then
			local n = data.name
			local d = data.damage
			local c = data.count
			--maybe same name but hopeful different damage
			print(InSlots[i]..": "..n.." -> damage: "..d)
			RecipeItemName[InSlots[i]] = n
			RecipeItemDamage[InSlots[i]] = d
			RecipeItemCount[InSlots[i]] = c

			-- create own dir for each slot and save data..
			if not fs.isDir("recipe/"..InSlots[i]) then
				fs.makeDir("recipe/"..InSlots[i])
			end

			if fs.exists("recipe/"..InSlots[i].."/name") then
				fs.delete("recipe/"..InSlots[i].."/name")
			end
			local fileObject = fs.open("recipe/"..InSlots[i].."/name", "w")
			fileObject.write(tostring(n))
			fileObject.close()

			if fs.exists("recipe/"..InSlots[i].."/damage") then
				fs.delete("recipe/"..InSlots[i].."/damage")
			end
			local fileObject = fs.open("recipe/"..InSlots[i].."/damage", "w")
			fileObject.write(tostring(d))
			fileObject.close()

			if fs.exists("recipe/"..InSlots[i].."/count") then
				fs.delete("recipe/"..InSlots[i].."/count")
			end
			local fileObject = fs.open("recipe/"..InSlots[i].."/count", "w")
			fileObject.write(tostring(c))
			fileObject.close()
		end
	end
end



--[[ Internal values ]]


-- Mapping of slots in the turtle's inventory used for recipe.
InSlots = {1,2,3, 5,6,7, 9,10,11}
OutSlot = 16

ChestItem = {}
RecipeItemName = {}
RecipeItemDamage = {}
RecipeItemCount = {}

Count = 0


--[[ Main program ]]


if not fs.isDir("recipe") then
	-- Verify valid recipe
	if turtle.craft(0) == false then
		print("ERROR: Invalid recipe! Please set up correctly.")
		error()
	end
	fs.makeDir("recipe")
	saveRecipe()
	-- craft recipe once to get all slots free
	craft()
else
	-- get recipe out saved data files for each slot..
	print("Trying to get saved Recipe..")
	local flistTable = fs.find("/recipe/*/name")
	for _,file in pairs(flistTable) do
		local directory = fs.getDir(file)
		local tmp = split(directory,"/")
		local slot = tmp[2]
		local fileObject = fs.open(directory.."/name", "r")
		local n = fileObject.readLine()
		fileObject.close()
		local fileObject = fs.open(directory.."/damage", "r")
		local d = fileObject.readLine()
		fileObject.close()
		local fileObject = fs.open(directory.."/count", "r")
		local c = fileObject.readLine()
		fileObject.close()
		print(slot..": "..n.." -> damage: "..d)
		RecipeItemName[slot] = n
		RecipeItemDamage[slot] = d
		RecipeItemCount[slot] = c
	end
end

-- Verify needed items for recipe with items in each chest..
print("Trying to get Sides for each Item..")
turtle.select(OutSlot)
for i,side in pairs(rs.getSides()) do
	if (side ~= OutDirection) and (peripheral.isPresent(side)) then
		suck(side)
		for slot in pairs(RecipeItemName) do
			local data = turtle.getItemDetail(OutSlot)
			if data then
				local n = data.name
				local d = data.damage
				local c = data.count
				--maybe same name but hopeful also same damage -> same item
				if (stringMatch(RecipeItemName[slot], n)) and (stringMatch(RecipeItemDamage[slot], d)) then
					ChestItem[slot] = side
					print("for slot "..slot..": "..side..": "..n..")
				end
			end
		end
		drop(side)
	end
end


-- main loop

Err0r = false
while true do
	-- check Redstone signal..
	if (rs.getInput(ControlSignal) == true) then
		-- suck in all the required slots
		for slot in pairs(RecipeItemName) do
			turtle.select(tonumber(slot))
			while turtle.getItemCount(slot) == 0 do
				suck(ChestItem[slot], tonumber(RecipeItemCount[slot]))
			end
		end
		if turtle.craft(0) == false then
			drop(OutDirection, turtle.getItemCount(OutSlot))
			if Err0r == false then
				print("ERROR: Invalid recipe! Please set up correctly.")
				Err0r = true
			end
		else
			craft()
		end
	else
		os.sleep(1)
	end
end


--
-- EOF
--
Edited on 04 August 2015 - 07:32 PM
Moseself #2
Posted 28 July 2015 - 04:16 PM
So question, how would you make or edit the program so that it doesn't take the damage into account? Currently trying to make it so that the turtle combines swords and such from my mob spawner, so that I can fit them all into my JABBA Barrel. Thanks!
Worthdwarf #3
Posted 10 January 2016 - 10:24 PM
When I try to use this program it doesn't check all sides and gets stuck with "the trying to get sides for each item" text