View difference between Paste ID: Kkf2crjf and Xziv6utc
SHOW: | | - or go back to the newest paste.
1
local component = require 'component'
2
local modem = component.modem
3
4-
local QUEEN = {}
4+
local PAWN = {}
5
6
7
local FIRMWARE = {
8
[[
9-
r= component.proxy(component.list('radar')())
9+
10-
n= component.proxy(component.list('navigation')())
10+
11
Channel = 2413
12
ResponseChannel = 2403
13-
Channel = 2412
13+
14-
ResponseChannel = 2402
14+
15
m.open(Channel)
16-
m.setStrength(math.huge)
16+
17-
drone_inv = "inv_q"
17+
18-
isDroneQueen = true
18+
drone_inv = "inv_s"
19
isDroneQueen = false
20-
broadcastGPS = false
20+
21
22-
gpsRequestChannel = 20
22+
gpsSats={}
23-
m.open(gpsRequestChannel)
23+
cmdTRGPos={}
24
]]
25
,
26
[[
27
function sleep(timeout) 
28
	checkArg(1, timeout, 'number', 'nil')
29
	local deadline = computer.uptime() + (timeout or 0)
30
	repeat
31
		computer.pullSignal(deadline - computer.uptime())
32
	until computer.uptime() >= deadline
33
end
34
]]
35
,
36
[[
37-
function sub_vec(A,B) return {A[1]-B[1],A[2]-B[2],A[3]-B[3]} end
37+
floor, sqrt, abs = math.floor, math.sqrt, math.abs
38-
function math.trunc(v)
38+
39-
    local t = math.modf(v)
39+
function round(v, m) return {x = floor((v.x+(m*0.5))/m)*m, y = floor((v.y+(m*0.5))/m)*m, z = floor((v.z+(m*0.5))/m)*m} end
40-
	return t
40+
function cross(v, b) return {x = v.y*b.z-v.z*b.y, y = v.z*b.x-v.x*b.z, z = v.x*b.y-v.y*b.x} end
41
function len(v) return sqrt(v.x^2+v.y^2+v.z^2) end
42
function dot(v, b) return v.x*b.x+v.y*b.y+v.z*b.z end
43
function add(v, b) return {x=v.x+b.x, y=v.y+b.y, z=v.z+b.z} end
44-
		return {math.trunc(A[1]),math.trunc(A[2]),math.trunc(A[3])}
44+
function sub(v, b) return {x=v.x-b.x, y=v.y-b.y, z=v.z-b.z} end
45
function mul(v, m) return {x=v.x*m, y=v.y*m, z=v.z*m} end
46
function norm(v) return mul(v, 1/len(v)) end
47
	
48
function arr_length(a)
49
  local c = 0
50
  for k,_ in pairs(a) do c=c+1 end
51-
function getPlayerCoord(e_name) 
51+
  return c
52-
	checkArg(1,e_name,'string','nil') 
52+
53-
	for k,v in ipairs(r.getPlayers()) do 
53+
function trunc(v) local t = math.modf(v) return t end
54-
		if v.name == e_name then
54+
55-
			return {v.x,v.y,v.z},v.distance
55+
56-
		end 
56+
		return {x=trunc(A.x),y=trunc(A.y),z=trunc(A.z)}
57
	end
58
	return nil
59
end
60
]]
61
,
62
63-
function move(x,y,z) 
63+
64-
	checkArg(1,x,'number','nil')
64+
function add2GPSTable(r_addr,x,y,z,dist)
65-
	checkArg(1,y,'number','nil')
65+
  if arr_length(gpsSats) < 7 then gpsSats[r_addr] = {x=x,y=y,z=z,d=dist} end 
66-
	checkArg(1,z,'number','nil')
66+
67-
	if x and y and z then
67+
68-
			d.setLightColor(0x00FFAF)
68+
69-
			d.move(x,y,z)
69+
70
function replyInv(add)
71
	m.send(add,ResponseChannel,"stats",isFree,isDroneQueen)--Queens send "true"
72
end
73
]]
74
,
75
[[
76
acts = {
77
	[drone_inv] = function(r_add) d.setLightColor(0x00FFBB) replyInv(r_add) end,
78
	["commit"] = function() d.setLightColor(0x5E00FF) isFree = false end,
79
	["uncommit"] = function() isFree = true end,
80
81
	["gps"] = function(r_addr,x,y,z,dist) add2GPSTable(r_addr,x,y,z,dist) end,
82-
function QgpsBroadcast(c)
82+
	["trg"] = function(_,x,y,z,dist) cmdTRGPos={c={x,y,z},d=dist} end,
83-
	if broadcastGPS and c[1] then
83+
	["formup"] = function(_,x,y,z,_,trgC) d.setStatusText(gpsMoveToTarget({x=x,y=y,z=z},trgC)) end,	
84-
		--m.broadcast(gpsChannel,"gps",-c[1],-(c[2]+1),-c[3])
84+
	["orbit"] = function(_,x,y,z,_,trgC) d.setStatusText("orbiting") d.setStatusText(gpsOrbitTRG({x=x,y=y,z=z},trgC)) end,
85-
		m.broadcast(gpsChannel,"gps",c[1],c[2],c[3])
85+
86-
		d.setLightColor(0x00FFCC)
86+
87
]]
88
,
89
[[
90
actsWhileMoving = {
91
	[drone_inv] = function(r_add) replyInv(r_add) end,
92-
function gpsReply(addr)
92+
93-
	if gpsSatPos[1] then
93+
94-
		m.send(addr,gpsChannel,"gps",gpsSatPos[1],gpsSatPos[2],gpsSatPos[3])
94+
	["gps"] = function(r_addr,x,y,z,dist) add2GPSTable(r_addr,x,y,z,dist) end,
95
	--["trg"] = function(_,x,y,z,dist) cmdTRGPos={c={x=x,y=y,z=z},d=dist} d.setStatusText("trg2:"..tostring(cmdTRGPos.c.x))  end,
96
	["HUSH"] = function() d.setLightColor(0xFF0000) sleep(1) computer.shutdown() end
97
}
98
]]
99
,
100
[[
101-
	["go"] = function(_,tag) d.setLightColor(0x00FF00) d.setStatusText(navMoveToPlayer(tag)) end,
101+
function trilaterate(A, B, C)
102-
    ["bzz"] = function(_,tag) d.setLightColor(0x0000FF) d.setStatusText(navSwarmPlayer(tag)) end,
102+
	local a2b = {x=B.x-A.x, y=B.y-A.y, z=B.z-A.z}
103-
	["move"] = function(_,_,x,y,z) move(x,y,z) end,
103+
	local a2c = {x=C.x-A.x, y=C.y-A.y, z=C.z-A.z}
104-
	[drone_inv] = function(r_add) d.setLightColor(0xFF00BB) replyInv(r_add) end,
104+
	if abs(dot(norm(a2b), norm(a2c))) > 0.999 then return nil end
105
	local d, ex = len(a2b), norm(a2b)
106
	local i = dot(ex, a2c)
107-
	["formup"] = function(_,tag,x,y,z) d.setStatusText(navMoveToPlayerWOffset(tag,x,y,z)) end,
107+
	local exMi = mul(ex, i)
108-
	["setgpspos"] = function(_,_,x,y,z) gpsSatPos = {x,y,z} end,
108+
	local ey = norm(sub(a2c, mul(ex, i)))
109-
	["startgps"] = function() broadcastGPS = true end,
109+
	local j, ez = dot(ey, a2c), cross(ex, ey)
110-
	["stopgps"] = function() broadcastGPS = false end,
110+
	local r1, r2, r3 = A.d, B.d, C.d
111-
	["reqgps"] = function(r_add) gpsReply(r_add) end,
111+
	local x = (r1^2 - r2^2 + d^2) / (2*d)
112
	local y = (r1^2 - r3^2 - x^2 + (x-i)^2 + j^2) / (2*j)
113
	local result = add(A, add(mul(ex, x), mul(ey, y)))
114
	local zSquared = r1^2 - x^2 - y^2
115
	if zSquared > 0 then
116
		local z = sqrt( zSquared )
117
		local result1 = add(result, mul(ez, z))
118
		local result2 = sub(result, mul(ez, z))
119
		local rnd1, rnd2 = result1,result2
120
		if rnd1.x ~= rnd2.x or rnd1.y ~= rnd2.y or rnd1.z ~= rnd2.z then
121-
	["setgpspos"] = function(_,_,x,y,z) gpsSatPos = {x,y,z} end,
121+
			return rnd1, rnd2
122-
	["startgps"] = function() broadcastGPS = true end,
122+
123-
	["stopgps"] = function() broadcastGPS = false end,
123+
			return rnd1
124
		end
125
	end
126
	return result
127
end
128
]]
129-
function navMoveToPlayer(e_name)
129+
130-
	checkArg(1,e_name,"string","nil")
130+
131-
	local trgPos = {n.getPosition()},msg,r_add
131+
function narrow(p1, p2, fix)
132-
 
132+
	local d1 = abs(len(sub(p1, fix))-fix.d)
133-
	if not trgPos[1] then d.setLightColor(0xFF0000) return "Out Of\nRange" end
133+
	local d2 = abs(len(sub(p2, fix))-fix.d)
134-
 
134+
	if abs(d1-d2) < 0.01 then 
135-
	trgPos = vec_trunc(trgPos)
135+
		return p1, p2
136-
	local mv = {0,0,0}
136+
	elseif d1 < d2 then 
137-
	local mapRange = n.getRange()
137+
		return p1,nil
138-
 
138+
	else 
139
		return p2,nil
140-
		local v = getPlayerCoord(e_name)
140+
141-
		if not v then 
141+
142-
			d.setLightColor(0xFF0000)
142+
143-
			d.setStatusText("Out Of\nRange")
143+
144
[[
145-
			v = vec_trunc(v)
145+
function getGPSlocation()
146-
			local npos = {n.getPosition()}
146+
	local fixes = {}
147-
			if npos[1] then
147+
	local pos1, pos2 = nil, nil
148-
				npos = vec_trunc(npos)
148+
	for addr,fix in pairs(gpsSats) do
149-
				local Qpn = {npos[1] + v[1], npos[2] + v[2] + 2, npos[3] + v[3]}
149+
		if fix.d == 0 then 
150-
				mv = sub_vec(Qpn,trgPos)
150+
			pos1, pos2 = {x=fix.x, y=fix.y, z=fix.z}, nil
151-
				if math.abs(Qpn[1]) < mapRange-5 and math.abs(Qpn[3]) < mapRange-5 then
151+
		else 
152-
					d.move(mv[1],mv[2],mv[3])
152+
			table.insert(fixes, fix)
153-
					trgPos = Qpn
153+
154
	end
155-
			else
155+
	if #fixes >= 3 then
156-
				d.setLightColor(0xFF0000)
156+
		if not pos1 then
157-
				d.setStatusText("Out Of\nRange")
157+
			pos1, pos2 = trilaterate(fixes[1], fixes[2], fixes[3])
158-
				d.move(-mv[1],-mv[2],-mv[3])
158+
159
		if pos1 and pos2 then
160
			for f=4,#fixes do
161-
		_,_,r_add,_,_,msg = computer.pullSignal(0.5)
161+
				pos1, pos2 = narrow(pos1, pos2, fixes[f])
162
				if pos1 and not pos2 then break end
163-
			actsWhileMoving[msg](r_add)
163+
164
		end
165-
	until msg == "stop"
165+
	end        
166
167
	if pos1 and pos2 then
168
		d.setStatusText("ps12")
169
		return nil
170
	elseif pos1 then
171-
function navSwarmPlayer(e_name)
171+
		local c = round(pos1,1)
172-
	checkArg(1,e_name,"string","nil")
172+
		return {x=c.x,y=c.y,z=c.z}
173-
	local trgPos = {n.getPosition()},msg,r_add
173+
	else 
174-
 
174+
		d.setStatusText("else")
175-
	if not trgPos[1] then d.setLightColor(0xFF0000) return "Out Of\nRange" end
175+
		return nil
176-
 
176+
177-
	trgPos = vec_trunc(trgPos)
177+
178-
	local mv = {0,0,0}
178+
179-
	local mapRange = n.getRange()
179+
180-
 
180+
181
refreshGPSInterval = 0
182-
		local v = getPlayerCoord(e_name)
182+
function refreshGPSTable()
183-
		if not v then 
183+
	if refreshGPSInterval >= 17 then gpsSats={} refreshGPSInterval = 0 end
184-
			d.setLightColor(0xFF0000)
184+
	refreshGPSInterval = refreshGPSInterval + 1
185-
			d.setStatusText("Out Of\nRange")
185+
186
187-
			v = vec_trunc(v)
187+
function getTRGPos()
188-
			local npos = {n.getPosition()}
188+
	return cmdTRGPos
189-
			if npos[1] then
189+
190-
				npos = vec_trunc(npos)
190+
191-
				local Qpn = {npos[1] + v[1] +math.random(-3,3), npos[2] + v[2] +math.random(-3,3), npos[3] + v[3]+math.random(-3,3)}
191+
192-
				mv = sub_vec(Qpn,trgPos)
192+
193-
				if math.abs(Qpn[1]) < mapRange-5 and math.abs(Qpn[3]) < mapRange-5 then
193+
function gpsMoveToTarget(offset,trgChannel)
194-
					d.move(mv[1],mv[2],mv[3])
194+
	d.setLightColor(0xFFFFFF)
195-
					trgPos = Qpn
195+
	gpsSats={}
196
	m.open(gpsChannel)
197-
			else
197+
	local ctrlTRGPos = nil
198-
				d.setLightColor(0xFF0000)
198+
199-
				d.setStatusText("Out Of\nRange")
199+
		if arr_length(gpsSats)>=3 then
200-
				d.move(-mv[1],-mv[2],-mv[3])
200+
			ctrlTRGPos = getGPSlocation()
201
		end
202
	
203-
		_,_,r_add,_,_,msg = computer.pullSignal(0.5)
203+
		if ctrlTRGPos then ctrlTRGPos = vec_trunc(ctrlTRGPos) 
204
		else d.setLightColor(0xFF0000) d.setStatusText("No GPS:") end
205-
			actsWhileMoving[msg](r_add)
205+
	
206
		_,_,r_addr,_,dist,msg,x,y,z,trgCh = computer.pullSignal(0.5)
207-
	until msg == "stop"
207+
		
208
		if actsWhileMoving[msg] then
209
			actsWhileMoving[msg](r_addr,x,y,z,dist)
210
		end
211
		refreshGPSTable()
212
	until msg == "stop" or ctrlTRGPos
213-
gpsSatPos={}
213+
214-
function navMoveToPlayerWOffset(e_name,xo,yo,zo)
214+
	if ctrlTRGPos then
215-
	checkArg(1,e_name,"string","nil")
215+
		m.close(gpsChannel)
216-
	local trgPos = {n.getPosition()}
216+
		d.setLightColor(0xFFFFFF)
217-
	if not trgPos[1] then d.setLightColor(0xFF0000) return "Out Of\nRange" end
217+
		m.open(trgChannel)
218-
	trgPos = vec_trunc(trgPos)
218+
		local mv = {x=0,y=0,z=0},msg,r_add,dist,x,y,z
219-
	local mv = {0,0,0},msg,r_add
219+
		local trgUpdate = {}
220-
	local mapRange = n.getRange()
220+
			repeat
221
				_,_,r_addr,_,dist,msg,x,y,z,trgCh = computer.pullSignal(0.5)
222-
		local v = getPlayerCoord(e_name)
222+
	
223-
		if not v then 
223+
				if msg == "trg" then
224-
			d.setLightColor(0xFF0000)
224+
					trgUpdate = {c={x=x,y=y,z=z},d=dist}
225-
			d.setStatusText("Out Of\nRange")
225+
226
				local trgPos = trgUpdate
227-
			v = vec_trunc(v)
227+
228-
			--QgpsBroadcast(v)
228+
				if trgPos.d and trgPos.d < 50 then
229
					trgPos.c = vec_trunc(trgPos.c)
230-
			--gpsSatPos = {-v[1],-(v[2]+1),-v[3]} --offset origin to tablet position (above player's head)
230+
					local trgPosOffset = add(trgPos.c, offset)
231-
			--gpsSatPos = {-v[1],-v[2],-v[3]}
231+
					mv = sub(trgPosOffset,ctrlTRGPos)
232
					d.move(mv.x,mv.y,mv.z)
233-
			local npos = {n.getPosition()}
233+
					ctrlTRGPos = trgPosOffset
234-
			if npos[1] then
234+
					d.setLightColor(0x00FF00)
235-
				npos = vec_trunc(npos)
235+
					d.setStatusText(d.name())
236-
				local Qpn = {npos[1] + v[1] + xo, npos[2] + v[2] + yo, npos[3] + v[3] + zo}
236+
				else
237-
				mv = sub_vec(Qpn,trgPos)
237+
					d.setLightColor(0xFF0000)
238-
				if math.abs(Qpn[1]) < mapRange-5 and math.abs(Qpn[3]) < mapRange-5 then
238+
					d.setStatusText("Out Of\nRange")
239-
					d.move(mv[1],mv[2],mv[3])
239+
					d.move(-mv.x,-mv.y,-mv.z)
240-
					trgPos = Qpn
240+
241
				if actsWhileMoving[msg] then
242-
			else
242+
					actsWhileMoving[msg](r_addr,x,y,z,dist)
243-
				d.setLightColor(0xFF0000)
243+
244-
				d.setStatusText("Out Of\nRange")
244+
			until msg == "stop"
245-
				d.move(-mv[1],-mv[2],-mv[3])
245+
246
	m.close(trgChannel)
247
	return d.name()
248-
		_,_,r_add,_,_,msg = computer.pullSignal(0.5)
248+
249
]]
250-
			actsWhileMoving[msg](r_add)
250+
251
[[
252-
	until msg == "stop"
252+
function rotatePoint(rad,point)
253
	local s = math.sin(rad);
254
	local c = math.cos(rad);
255
256
	// rotate point
257
	float xnew = point.x * c - point.y * s;
258
	float ynew = point.x * s + point.y * c;
259-
local cmd,tag,x,y,z
259+
260-
d.setLightColor(0xFFAF00)
260+
	return point
261
end
262-
	_,_,r_add,_,_,cmd,tag,x,y,z = computer.pullSignal(0.5)
262+
263-
	if d.name():match("^Q%d+$") then
263+
264-
		if acts[cmd] then
264+
265-
			acts[cmd](r_add,tag,x,y,z)
265+
function gpsOrbitTRG(offset,trgChannel)
266
	d.setLightColor(0xFFFFFF)
267-
		QgpsBroadcast(gpsSatPos)
267+
	gpsSats={}
268
	m.open(gpsChannel)
269
	local ctrlTRGPos = nil
270
	repeat
271
		if arr_length(gpsSats)>=3 then
272
			ctrlTRGPos = getGPSlocation()
273
		end
274
	
275-
function QUEEN.broadcastFirmWare(port)
275+
		if ctrlTRGPos then ctrlTRGPos = vec_trunc(ctrlTRGPos) 
276
		else d.setLightColor(0xFF0000) d.setStatusText("No GPS:") end
277
	
278
		_,_,r_addr,_,dist,msg,x,y,z,trgCh = computer.pullSignal(0.5)
279
		
280
		if actsWhileMoving[msg] then
281-
return QUEEN
281+
			actsWhileMoving[msg](r_addr,x,y,z,dist)
282
		end
283
		refreshGPSTable()
284
	until msg == "stop" or ctrlTRGPos
285
286
	if ctrlTRGPos then
287
		m.close(gpsChannel)
288
		d.setLightColor(0xFFFFFF)
289
		m.open(trgChannel)
290
		local mv = {x=0,y=0,z=0},msg,r_add,dist,x,y,z
291
		local trgUpdate = {}
292
		local currentAngle = 0 -- in radians
293
		local rotationInterval = 0.785 -- PI/4
294
			repeat
295
				_,_,r_addr,_,dist,msg,x,y,z,trgCh = computer.pullSignal(0.5)
296
	
297
				if msg == "trg" then
298
					trgUpdate = {c={x=x,y=y,z=z},d=dist}
299
				end
300
				local trgPos = trgUpdate
301
302
				if trgPos.d and trgPos.d < 50 then
303
					trgPos.c = vec_trunc(trgPos.c)
304
305
					if currentAngle >= 6.3832 then currentAngle = 0 end
306
					local rotatedOffset = rotatePoint(currentAngle,offset)
307
					currentAngle = currentAngle + rotationInterval
308
	
309
					local trgPosOffset = add(trgPos.c, rotatedOffset)
310
	
311
					mv = sub(trgPosOffset,ctrlTRGPos)
312
					d.move(mv.x,mv.y,mv.z)
313
					ctrlTRGPos = trgPosOffset
314
					d.setLightColor(0x00FF00)
315
					d.setStatusText(d.name())
316
				else
317
					d.setLightColor(0xFF0000)
318
					d.setStatusText("Out Of\nRange")
319
					d.move(-mv.x,-mv.y,-mv.z)
320
				end
321
				if actsWhileMoving[msg] then
322
					actsWhileMoving[msg](r_addr,x,y,z,dist)
323
				end
324
			until msg == "stop"
325
	end
326
	m.close(trgChannel)
327
	return d.name()
328
end
329
]]
330
,
331
[[
332
d.setAcceleration(100)
333
d.setLightColor(0x007B62)
334
while true do
335
	_,_,r_addr,_,dist,msg,x,y,z,trgCh = computer.pullSignal(0.5)
336
	if d.name():match("^S%d+$") then
337
		if msg =="orbit"then d.setStatusText("orbitter") end
338
		if acts[msg] then
339
			acts[msg](r_addr,x,y,z,dist,trgCh)
340
		end
341
	end
342
	--d.setLightColor(0xFFAF00)
343
	--d.setLightColor(0x77FF77)
344
end
345
]]
346
}
347
348
PAWN.master = "" --control tablet modem address, set before broadcasting firmware
349
350
function PAWN.broadcastFirmWare(port)
351
	modem.broadcast(port,
352
	[[
353
		master = ]]..PAWN.master..[[
354
	]]
355
	)
356
	for _,part in ipairs(FIRMWARE) do
357
		modem.broadcast(port,part)
358
	end
359
end
360
361
return PAWN
362