local Location = {
	add = function(self, o)
		return vector.new(
			self.x + o.x,
			self.y + o.y,
			self.z + o.z
		)
	end,
	sub = function(self, o)
		return vector.new(
			self.x - o.x,
			self.y - o.y,
			self.z - o.z
		)
	end,
	mul = function(self, m)
		return vector.new(
			self.x * m,
			self.y * m,
			self.z * m
		)
	end,
	div = function(self, d)
		return vector.new(
			self.x / d,
			self.y / d,
			self.z / d
		)
	end,
	left = function(self, noMove)
		self.h = self.h - 1
		if self.h < 1 then self.h = self.h + 4 end
		return noMove or turtle.turnLeft()
	end,
	right = function(self, noMove)
		self.h = self.h + 1
		if self.h > 4 then self.h = self.h - 4 end
		return noMove or turtle.turnRight()
	end,
	forward = function(self, noMove)
		if noMove or turtle then
			if noMove or turtle.forward() then
				self.x = self.x + (self.h - 2) * (self.h % 2)
				self.z = self.z + (self.h - 3) * ((self.h + 1) % 2)
				return true
			end
		end
		return false
	end,
	back = function(self, noMove)
		if turtle then
			if turtle.back() then
				self.x = self.x - (self.h - 2) * (self.h % 2)
				self.z = self.z - (self.h - 3) * ((self.h + 1) % 2)
				return true
			end
		end
		return false
	end,
	up = function(self, noMove)
		if noMove or turtle then
			if noMove or turtle.up() then
				self.y = self.y + 1
				return true
			end
		end
		return false
	end,
	down = function(self, noMove)
		if noMove or turtle then
			if noMove or turtle.down() then
				self.y = self.y - 1
				return true
			end
		end
		return false
	end,
	moveDeltas = function(self)
		return (self.h - 2) * (self.h % 2), (self.h - 3) * ((self.h + 1) % 2)
	end,
	setHeading = function(self, head)
		if not head or head < 1 or head > 4 then return nil, "Heading Not in Range" end
		while self.h ~= head do
			if (self.h + 1) % 4 == head % 4 then
				self:right()
			else
				self:left()
			end
		end
	end,
	tovector = function(self)
		if vector then
			return vector.new(
				self.x,
				self.y,
				self.z
			)
		else
			return nil
		end
	end,
	tostring = function(self)
		return self.x..","..self.y..","..self.z..","..self.h
	end,
	value = function(self)
		return self.x, self.y, self.z, self.h
	end,
}

local lmetatable = {
	__index = Location,
	__add = Location.add,
	__sub = Location.sub,
	__mul = Location.mul,
	__div = Location.div,
	__unm = function(l) return l:mul(-1) end,
	__tostring = function(l) return l:tostring() end,
}

function new( x, y, z, h )
	local l = {
		x = x or 0,
		y = y or 0,
		z = z or 0,
		h = h or 1
	}
	setmetatable( l, lmetatable )
	return l
end

function getOrientation(x, z)
	return ((x + math.abs(x) * 2) + (z + math.abs(z) * 3))
end

--[[
-x 1 (west)
-z 2 (north)
+x 3 (east)
+z 4 (south)

turn right, add one.
turn left, sub one.
--]]