summaryrefslogtreecommitdiff
path: root/cactus.lua
blob: 36eb25d0402fc96eccd44b01247a0996674d790b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
local numutil = require 'numutil'

local function ensure_equipped(ptype, item)
	local cur = peripheral.getType"left"
	print(cur)
	if cur == ptype then return true end
	for i = 1,16 do
		local det = turtle.getItemDetail(i)
		if det and det.name == item then
			turtle.select(i)
			return turtle.equipLeft()
		end
	end
	return false, "couldn't find "..item
end

local function ensure_modem() return ensure_equipped("modem","computercraft:wireless_modem_normal") end

local POS, FACING
local function turtle_pos_init()
	assert(ensure_modem())

	POS = vector.new(gps.locate())

	while turtle.detect() do turtle.turnRight() end
	turtle.forward()
	local newpos = vector.new(gps.locate())
	turtle.back()
	FACING = newpos - POS
	print("init with",POS,FACING)
end


local function moveby_y(delta)
	local fn = turtle.up
	if delta < 0 then fn = turtle.down  delta = -delta  end
	for i=1,delta do fn() end
	POS.y = POS.y + delta
end

local function rotatev(v,nq)
	-- rotates v by n quarters, clockwise (rightwards)
	nq = nq%4
	if nq == 0     then return vector.new( v.x,  v.y,  v.z)
	elseif nq == 1 then return vector.new(-v.z,  v.y,  v.x)
	elseif nq == 2 then return vector.new(-v.x,  v.y, -v.z)
	elseif nq == 3 then return vector.new( v.z,  v.y, -v.x)
	end
end

local function turn_right()
	FACING = rotatev(FACING,1)
	turtle.turnRight()
end
local function turn_left()
	FACING = rotatev(FACING,-1)
	turtle.turnLeft()
end

local function turn_to_face(newfacing)
	if newfacing == FACING then return
	elseif newfacing == -FACING then turn_right() turn_right()
	elseif newfacing == rotatev(FACING,1) then turn_right()
	elseif newfacing == rotatev(FACING,-1) then turn_left()
	else error("invalid facing "..tostring(newfacing),2)
	end
end

local function move_linear(n)
	local dir = turtle.forward
	if n < 0 then dir = turtle.back end
	for i = 1,math.abs(n) do dir() end
	POS = POS + FACING*n
end

local function moveby_xz(dv)
	if FACING.x ~= 0 then
		move_linear(dv:dot(FACING))
		if dv.z ~= 0 then
			turn_to_face(vector.new(0,0,numutil.sign(dv.z)))
			move_linear(dv:dot(FACING))
		end
	elseif FACING.z ~= 0 then
		move_linear(dv:dot(FACING))
		if dv.x ~= 0 then
			turn_to_face(vector.new(numutil.sign(dv.x),0,0))
			move_linear(dv:dot(FACING))
		end
	end
end

local function moveby(delta)
	moveby_y(delta.y)
	moveby_xz(delta)
end
local function moveto(target)
	print("moving to",target)
	moveby(target - POS)
end

local function do_column()
	if turtle.detectDown() then
		turtle.digDown()
		turtle.down()
		turtle.digDown()
		turtle.up()
	end
end

local function dump_and_refuel()
	print("dumping produce")
	os.sleep(1)
	local modem = peripheral.wrap"top"
	local self = modem.getNameLocal()
	print("i am",self)
	local ch = peripheral.find"sc-goodies:diamond_barrel"
	for i=1,16 do
		ch.pullItems(self, i)
	end
	while turtle.getFuelLevel() < 2000 do
		print("refuelling")
		for k,v in pairs(ch.list()) do
			if v.name == "minecraft:lava_bucket" then
				ch.pushItems(self, k, 1, 1)
				turtle.select(1)
				turtle.refuel()
				ch.pullItems(self, 1)
				goto nextfuel
			end
			goto nofuel
		end
		::nextfuel::
	end
	::nofuel::
end
	
local datum = vector.new(-18, 128, -1837)

local function setup()
	turtle_pos_init()

	moveto(datum)
	turn_to_face(vector.new(0,0,1))
	dump_and_refuel()

end

local function loop()
	print("harvesting")
	repeat
		repeat
			do_column()
			move_linear(1)
		until POS.z == -1826
		do_column()
		turn_right()
		move_linear(1)
		turn_right()

		repeat
			do_column()
			move_linear(1)
		until POS.z == datum.z
		do_column()
		turn_left()
		move_linear(1)
		turn_left()

	until POS.x <= -29

	moveto(datum)
	turn_to_face(vector.new(0,0,1))

	dump_and_refuel()

	os.sleep(120)
end

local function main()
	setup()
	while true do loop() end
end

while true do
	local ok, err = pcall(main)
	if not ok then print("err",err) end
	os.sleep(5)
end