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

[LUA] Global vector keeps getting reset?

Started by wackozacko, 08 September 2012 - 01:03 AM
wackozacko #1
Posted 08 September 2012 - 03:03 AM
So, I've just started with ComputerCraft and LUA, but I come from a programming background so it hasn't been too hard to pick up. Until now.

As a part of learning, I'm trying to write a simple program for a mining turtle so that, starting from a chest, it will dig a shaft N by M down. When it runs low on fuel or fills it's inventory up, it will return to the chest and dump everything before refuelling. I'm doing my path-finding with vectors. The start location is vector <0,0,0>, the mineshaft starts at vector <2,0,0> (2 blocks away from the chest), and every time I move I increase the vector appropriately.

The plan was, when the turtle does need to return to the chest, it can record it's current location as a vector, navigate to <0,0,0> to drop everything, and then use the previously recorded position to return to where it was last.

The problem is that reading the vector in, that I thought I'd stored, always returns <0,0,0> no matter what, so the turtle starts from where it's at and destroys the chest it just dumped everything into.

I think it's a scoping issue, but despite researching it for the last couple of hours, I haven't figured it out.

The relevant code is as follows:
Spoiler

local mineLocation = vector.new(2,0,0)
local location = vector.new(0,0,0)

-- miners start pointing backwards towards their chest.
-- '0' indicates positive x, '1' positive y, '2' negative x, '3' negative y
-- a right turn adds 1 to direction, a left turn subtracts
-- every time direction is modified, it is also normalized to remain between 0 and 3 inclusive
local direction = 2

local toMine = function()
	print("Going to Mine")
	print("Retreiving Mine Location")
        -- THIS ALWAYS PRINTS (0,0,0) --
	print("(" .. mineLocation.x .. "," .. mineLocation.y .. "," .. mineLocation.z .. ")")
	print("")
	tmpVec = mineLocation - location
	
	-- if positive x
	if tmpVec.x > 0 then
		-- face positive x
		while direction ~= 0 do
			right()
		end
                -- move in that direction
		for i=1,tmpVec.x do
			forward()
		end
	end
	-- if negative x
	if tmpVec.x < 0 then
		-- face negative x
		while direction ~= 2 do
			right()
		end
                -- move in that direction
		for i=tmpVec.x,-1 do
			forward()
		end
	end
	
	-- if positive y
	if tmpVec.y > 0 then
		-- face positive y
		while direction ~= 1 do
			right()
		end
                -- move in that direction
		for i=1,tmpVec.y do
			forward()
		end
	end
	--if negative y
	if tmpVec.y < 0 then
		-- face negative y
		while direction ~= 3 do
			right()
		end
                -- move in that direction
		for i=tmpVec.y,-1 do
			forward()
		end
	end
	
	-- if positive z
	if tmpVec.z > 0 then
		for i=1,tmpVec.z do
			down()
		end
	end
        -- if negative z
	if tmpVec.z < 0 then
		for i=tmpVec.z,-1 do
			up()
		end
	end
end

while true do
	if refuel() then
		toMine(mineLocation) -- THIS WORKS FINE AND MOVES TURTLE TO <2,0,0>
		while (turtle.getFuelLevel() > 1600) do
			for j=1,tArgs[2] do -- ROWS
				for i=2,tArgs[1] do -- COLUMNS (-1 from column length as you need to move one less space than you need to dig)
					if turtle.detectDown() then
						turtle.digDown()
					end
					forward()
				end
				turtle.digDown()
				
				if turtle.getItemCount(15) ~= 0 then -- If all slots now have something in them we're pretty full. Might as well empty the inventory.
					mineLocation = location -- THIS IS WHERE I THINK EVERYTHING IS GOING WRONG --
					print("Recording Mine Location")
                                        -- THIS PRINTS THE RIGHT VALUES --
					print("(" .. mineLocation.x .. "," .. mineLocation.y .. "," .. mineLocation.z .. ")")
					print("")
					returnToStart() -- PRACTICALLY THE SAME ALGORITHM AS toMine() BUT DOESN'T TOUCH mineLocation AT ALL --
					refuel()
					toMine()
				end
			end
			returnToCorner()
			down()
		end
	else
		print("Ran out of fuel")
		sleep(120)
	end
end
Lettuce #2
Posted 08 September 2012 - 03:09 AM
I'm unsure if vectors work in ComputerCraft. I know tables do, try using that. You can find a lot of ComputerCraft stuff on the wiki. Just Google it. Tables are pretty simple.
wackozacko #3
Posted 08 September 2012 - 03:12 AM
Vectors do work, though they are somewhat basic. I'm more just using them to store x,y,z coordinates than any complex mathematics.

http://computercraft...tle=Vector_(API)
MysticT #4
Posted 08 September 2012 - 03:26 AM
Well, I don't see any part that modifies the vectors. I guess you do it in the movement functions (forward, back, etc.), so you should post them.
Lettuce #5
Posted 08 September 2012 - 03:32 AM
I see. Personally, I've never used them. Learn something new everyday, eh? I like variables, and I have done the same things with them.
(x, y, z coordinates) If you are dead-set on vectors, I can't help you, I'm inexperienced with them. Someone else will eventually pick this up. But if you are willing to use a table, I'll be happy to lend what knowledge I do have. I'm not incredibly experienced, but I know enough to get most of my programs running.
–Lettuce
wackozacko #6
Posted 08 September 2012 - 03:33 AM
Well, I don't see any part that modifies the vectors. I guess you do it in the movement functions (forward, back, etc.), so you should post them.

The only vector that is regularly being modified is the location vector to keep track of where the turtle is. All the code that references mineLocation has been posted above.

For reference I'm including my movement functions and a couple of the supporting functions below.
Spoiler
local naturalizeDirection = function(z)
	dir = direction + z
	if dir > 3 then
		dir = dir % 4
	end
	if dir < 0 then
		dir = dir + 4
	end
	return dir
end

local turnTo = function(d)
    if direction == d then
        return true
    else
        change = d - direction
        if change == 2 or change == -2 then
            right()
            right()
        elseif change == 1 or change == -3 then
            right()
        elseif change == 3 or change == -1 then
            left()
        end
    end
end

local right = function()
	turtle.turnRight()
	direction = naturalizeDirection(1)
end

local left = function()
	turtle.turnLeft()
	direction = naturalizeDirection(-1)
end

local up = function()
	if not turtle.up() then
		return false
	end
	location.z = location.z - 1
	return true
end

local down = function()
	if not turtle.down() then
		return false
	end
	location.z = location.z + 1
	return true
end

local forward = function()
	if turtle.detect() then
		turtle.dig()
	end
	if not turtle.forward() then
		return false
	end
	if direction == 0 then
		location.x = location.x + 1
	elseif direction == 1 then
		location.y = location.y + 1
	elseif direction == 2 then
		location.x = location.x - 1
	elseif direction == 3 then
		location.y = location.y - 1
	end
	return true
end

local back = function()
	if not turtle.back() then
		return false
	end
	if direction == 0 then
		location.x = location.x - 1
	elseif direction == 1 then
		location.y = location.y - 1
	elseif direction == 2 then
		location.x = location.x + 1
	elseif direction == 3 then
		location.y = location.y + 1
	end
	return true
end
wackozacko #7
Posted 08 September 2012 - 03:35 AM
I see. Personally, I've never used them. Learn something new everyday, eh? I like variables, and I have done the same things with them.
(x, y, z coordinates) If you are dead-set on vectors, I can't help you, I'm inexperienced with them. Someone else will eventually pick this up. But if you are willing to use a table, I'll be happy to lend what knowledge I do have. I'm not incredibly experienced, but I know enough to get most of my programs running.
–Lettuce
I figure it's possible to do it with tables and other variables, but I don't know if that would solve the problem I've run into. My other vectors seem to be working fine so I don't know what the problem is. I don't really want to go through a whole rewrite of the code just cause a single vector doesn't want to work and the rest do.
Xtansia #8
Posted 08 September 2012 - 04:37 AM
I'm not sure if it might be a reference issue, where mineLocation just becomes a 'pointer' to the exact same object as location instead of a copy
Try changing:
mineLocation = location
to:
mineLocation = vector.new(location.x,location.y,location.z)
Lyqyd #9
Posted 08 September 2012 - 05:02 AM
First, if you're not opposed to using an external API, you could check out my Location API, which is very similar to the vector API with a few added things to make turtle tracking much easier. The latest version can be found here; the discussion topic on these forums is found here. Even if you don't choose to use it, please feel free to take a look through the code. It's not very long and it may help you tighten up some of your code. If you have any questions about it, feel free to ask here or PM me.

Also, when printing vectors (and locations, if using my API), passing the vector or location to tostring() will output a reasonably formatted (comma-separated) string output.

I would most likely suspect that mineLocation = location line, that does assign mineLocation to simply point to whatever table location points to already, so they are then linked until either of them is set to a new value.
wackozacko #10
Posted 08 September 2012 - 10:23 AM
I'm not sure if it might be a reference issue, where mineLocation just becomes a 'pointer' to the exact same object as location instead of a copy
Try changing:
mineLocation = location
to:
mineLocation = vector.new(location.x,location.y,location.z)

SUCCESS!! Thanks so much for your insight. Wish I had asked on these forums sooner.

First, if you're not opposed to using an external API, you could check out my Location API, which is very similar to the vector API with a few added things to make turtle tracking much easier. The latest version can be found here; the discussion topic on these forums is found here. Even if you don't choose to use it, please feel free to take a look through the code. It's not very long and it may help you tighten up some of your code. If you have any questions about it, feel free to ask here or PM me.

Also, when printing vectors (and locations, if using my API), passing the vector or location to tostring() will output a reasonably formatted (comma-separated) string output.

I would most likely suspect that mineLocation = location line, that does assign mineLocation to simply point to whatever table location points to already, so they are then linked until either of them is set to a new value.

I'm not opposed to an external API, but the purpose of this exercise was learning LUA, not actually getting a working miner. I did take a look at the API and might well use it, or at least integrate part of it, in future. Very clean. Going to have to learn LUA coding standards as well as just the language.