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

map reading

Started by KingofGamesYami, 28 June 2014 - 03:21 PM
KingofGamesYami #1
Posted 28 June 2014 - 05:21 PM
So, I'm creating a wonderful api that allows the user to create a multiline string which will be turned into a series of commands for a turtle. However, my file is currently erroring when I test it.

Edit: stupid me. Forgot that naming my table table will mess things up. Fixing…

mapreader

function path( mstring, _yield )
	--Find start
	local function findStart()
		local l = 1
		for line in mstring:gmatch( '[^\r\n]+' ) do
			for i = 1, #line do
				if line:sub( i, i ) == "X" then
					return {x = i, y = l}
				end
			end
			l = l + 1
		end
	end
	--update removes already used path bits
	local function update( tbl )
		local l = 1
		local newString = {}
		for line in mstring:gmatch( '[^\r\n]+' ) do
			if l == tbl.y then
				newString[l] = line:sub( 1, tbl.x - 1 ).." "..line:sub( tbl.x + 1, #line )
			else
				newString[l] = line
			end
			l = l + 1
		end
		return table.concat( newString, "\n" )
	end
	--orient function
	local face = "up"
	local function orient( direction )
		if face == "up" and direction == "up" then
			return
		elseif face == "up" and direction == "right" then
			turtle.turnRight()
			face = "right"
		elseif face == "up" and direction == "left" then
			turtle.turnLeft()
			face = "left"
		elseif face == "up" and direction == "down" then
			turtle.turnRight()
			turtle.turnRight()
			face = "down"
		elseif face == "right" and direction == "up" then
			turtle.turnLeft()
			face = "up"
		elseif face == "right" and direction == "right" then
			return
		elseif face == "right" and direction == "left" then
			turtle.turnLeft()
			turtle.turnLeft()
			face = "left"
		elseif face == "right" and direction == "down" then
			turtle.turnRight()
			face = "down"
		elseif face == "left" and direction == "up" then
			turtle.turnRight()
			face = "up"
		elseif face == "left" and direction == "right" then
			turtle.turnRight()
			turtle.turnRight()
			face = "right"
		elseif face == "left" and direction == "left" then
			return
		elseif face == "left" and direction == "down" then
			turtle.turnLeft()
			face = "down"
		elseif face == "down" and direction == "up" then
			turtle.turnLeft()
			turtle.turnLeft()
			face = "up"
		elseif face == "down" and direction == "right" then
			turtle.turnLeft()
			face = "right"
		elseif face == "down" and direction == "left" then
			turtle.turnRight()
			face = "left"
		elseif face == "down" and direction == "down" then
			return
		end
	end
	--Find next position
	local function findNext( tbl )
		mstring = update( tbl )
		local l = 1
		for line in mstring:gmatch( '[^\r\n]+' ) do
			if l == tbl.y - 1 and line:sub( tbl.x, tbl.x ) == "#" then
				--turtle should move "up"
				return function() orient( "up" ) return turtle.forward() end, {x = tbl.x, y = tbl.y - 1}
			elseif l == tbl.y and line:sub( tbl.x - 1, tbl.x - 1 ) == "#" then
				--turtle should move "left"
				return function() orient( "left" ) return turtle.forward() end, {x = tbl.x - 1, y = tbl.y}
			elseif l == tbl.y and line:sub( tbl.x + 1, tbl.x + 1 ) == "#" then
				--turtle should move "right"
				return function() orient( "right" ) return turtle.forward() end, {x = tbl.x + 1, y = tbl.y}
			elseif l == tbl.y + 1 and line:sub( tbl.x, tbl.x ) == "#" then
				--turtle should move "down"
				return function() orient( "down" ) return turtle.forward() end, {x = tbl.x, y = tbl.y + 1}
			end
			l = l + 1
		end
	end

	local place = findStart()
	local path = {}
	while true do
		path[#path + 1], place = findNext( place )
		if not place then
			break
		end
	end
	path.yield = _yield
	path.go = coroutine.create( function()
		for _, move in ipairs( path ) do
			local success = move()
			if path.yield then
				coroutine.yield( success )
			end
		end
	end )
	local mt = {
		__call = function()
			return coroutine.resume( path.go ) or coroutine.status( path.go )
		end,
	}
	setmetatable( path, mt )
	return path
end
test code

os.loadAPI( "mapreader" )
local map = [[
X####
		# --I give up. Stupid spacing
#####
]]
local move = mapreader.path( map, false )
print( "path created" )
move()
Edited on 28 June 2014 - 07:56 PM
KingofGamesYami #2
Posted 28 June 2014 - 08:37 PM
New error! test:9:attempt to call table. I thought that __call would allow me to call the table as a function, but it isn't. Any ideas as to why?

PS: Updated OP with new code
Lyqyd #3
Posted 28 June 2014 - 08:50 PM
__call is meant to be used as a metatable entry, not a table entry.
KingofGamesYami #4
Posted 28 June 2014 - 09:41 PM
…so I need to use setmetatable() at some point? I've seen examples on the internet that do not use it at all, so I didn't think I needed to.
Yep, that fixed it… now:

For some reason it always returns true. I checked this by adding

handle = mapreader.path( map, true ) --#also tried false
print( handle() )
However, the turtle never moves or turns. (Yes, it does have fuel)

PS: updated OP with latest code.
Edited on 28 June 2014 - 07:56 PM
Lyqyd #5
Posted 28 June 2014 - 10:11 PM
You will need to learn more about coroutines. The turtle functions all yield internally, so using coroutine.resume once and returning the result will simply tell you that you successfully resumed the coroutine once. You'll need to create an actual coroutine manager, and pass along the turtle movement events, etc.
KingofGamesYami #6
Posted 28 June 2014 - 10:39 PM
ah, I did not know the turtle functions yielded. I'll have to look into that a bit more.