Whitemambaa

home

Aug 19th, 2013
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.12 KB | None | 0 0
  1. --By xXxMoNkEyMaNxXx
  2. --elsez
  3. local type,next=type,next
  4. local tonumber,tostring=tonumber,tostring
  5.  
  6. local concat=table.concat
  7. local remove=table.remove
  8.  
  9. local abs=math.abs
  10. local floor=math.floor
  11. local rand=math.random
  12.  
  13. local tick=os.clock
  14.  
  15. math.randomseed(os.time())
  16. math.random()
  17.  
  18. local arg={...}
  19.  
  20. if peripheral then
  21. for _,side in next,{"left","right","front","back","bottom","top"} do
  22.     if peripheral.getType(side)=="modem" then
  23.         rednet.open(side)
  24.     end
  25. end
  26. end
  27.  
  28. local nans={tostring(1/0),tostring(-1/0),tostring(-(0/0)),tostring(0/0)}
  29. local function isnan(x)
  30.     local s=tostring(x)
  31.     for i,v in next,nans do
  32.         if s==v then
  33.             return i
  34.         end
  35.     end
  36. end
  37.  
  38. local function nonenan(t)
  39.     for i=1,#t do
  40.         if isnan(t[i]) then
  41.             return false,i
  42.         end
  43.     end
  44.     return true
  45. end
  46.  
  47. local function GPS(e0,e1,e2,e3,e4)
  48.     local x0,y0,z0,t0=e0[1],e0[2],e0[3],e0[4]
  49.     local x1,y1,z1,t1=e1[1],e1[2],e1[3],e1[4]
  50.     local x2,y2,z2,t2=e2[1],e2[2],e2[3],e2[4]
  51.     local x3,y3,z3,t3=e3[1],e3[2],e3[3],e3[4]
  52.     local x4,y4,z4,t4=e4[1],e4[2],e4[3],e4[4]
  53.  
  54.     --I left brackets in some because it's easier to see the grouping
  55.     local s1=x1-x0
  56.     local s3=y1-y0
  57.     local s7=z1-z0
  58.     local s10=t1-t0
  59.     local s2=(x2-x0)/s1
  60.     local s5=(x3-x0)/s1
  61.     local s9=(x4-x0)/s1
  62.     local s6=(y2-y0)-s2*s3
  63.     local s13=(z2-z0)-s2*s7
  64.     local s16=(t2-t0)-s2*s10
  65.     local s11=((y3-y0)-s5*s3)/s6
  66.     local s17=((z3-z0)-s5*s7)-s11*s13
  67.     local s21=((t3-t0)-s5*s10)-s11*s16
  68.     local s15=((y4-y0)-s9*s3)/s6
  69.     local s20=(((z4-z0)-s9*s7)-s15*s13)/s17
  70.     local s4=x0^2+y0^2+z0^2-t0^2
  71.     local s12=((x1^2+y1^2+z1^2-t1^2)-s4)/2
  72.     local s14=((x2^2+y2^2+z2^2-t2^2)-s4)/2-s2*s12
  73.     local s19=((x3^2+y3^2+z3^2-t3^2)-s4)/2-s5*s12-s11*s14
  74.  
  75.     --Calculators weren't good enough for this!  I solved it by hand ;D
  76.     local t=-(((x4^2+y4^2+z4^2-t4^2)-s4)/2-s9*s12-s15*s14-s20*s19)/((((t4-t0)-s9*s10)-s15*s16)-s20*s21)
  77.     local z=(s21*t+s19)/s17
  78.     local y=(s16*t-s13*z+s14)/s6
  79.     local x=(s10*t-s3*y-s7*z+s12)/s1
  80.     return {floor(x+0.5),floor(y+0.5),floor(z+0.5),t}
  81. end
  82.  
  83. local rec=rednet.receive
  84. local broadcast=rednet.broadcast
  85. local unserialize=textutils.unserialize
  86. local function receive(timeout)
  87.     local id,msg,d=rec(timeout)
  88.     local ret=msg and unserialize(msg) or {}
  89.     ret.senderId=id
  90.     ret.message=msg
  91.     ret.distance=d
  92.     return ret
  93. end
  94.  
  95. local function locate(timeout,period)
  96.     timeout=timeout or 5
  97.     period=period or 1
  98.     local t0=tick()
  99.     broadcast("PING")
  100.     local p={}
  101.     local sat={}
  102.     repeat
  103.         local data=receive(period)
  104.         if #data==4 then
  105.             local e={}
  106.             for i=1,4 do
  107.                 local v=data[i]
  108.                 if type(v)=="number" then
  109.                     e[i]=v
  110.                 else
  111.                     break
  112.                 end
  113.             end
  114.             if #e==4 then
  115.                 sat[#sat+1]=e
  116.             end
  117.         elseif #data==3 and type(data.distance)=="number" then
  118.             local e={}
  119.             for i=1,3 do
  120.                 local v=data[i]
  121.                 if type(v)=="number" then
  122.                     e[i]=v
  123.                 else
  124.                     break
  125.                 end
  126.             end
  127.             if #e==3 then
  128.                 e[4]=-data.distance
  129.                 sat[#sat+1]=e
  130.             end
  131.         else
  132.             print'Not enough hosts, needs more.'
  133.             broadcast'PING'
  134.         end
  135.         if #sat>=5 then
  136.             local chosen={}
  137.             for i=1,5 do
  138.                 chosen[i]=remove(sat,rand(#sat))
  139.             end
  140.             p=GPS(unpack(chosen))
  141.             local n=#sat
  142.             for i=1,5 do
  143.                 sat[n+i]=chosen[i]
  144.             end
  145.         end
  146.     until #p==4 and nonenan(p) and abs(p[4])<0.001 or tick()-t0>timeout
  147.     return p
  148. end
  149.  
  150. --[[ Working test!
  151. local t=math.random()
  152. local p0,p1,p2,p3,p4={math.random(),math.random(),math.random()},{math.random(),math.random(),math.random()},{math.random(),math.random(),math.random()},{math.random(),math.random(),math.random()},{math.random(),math.random(),math.random()}
  153. local p={math.random(),math.random(),math.random(),t}
  154. print(unpack(GPS({p0[1],p0[2],p0[3],t-math.sqrt((p[1]-p0[1])^2+(p[2]-p0[2])^2+(p[3]-p0[3])^2)},{p1[1],p1[2],p1[3],t-math.sqrt((p[1]-p1[1])^2+(p[2]-p1[2])^2+(p[3]-p1[3])^2)},{p2[1],p2[2],p2[3],t-math.sqrt((p[1]-p2[1])^2+(p[2]-p2[2])^2+(p[3]-p2[3])^2)},{p3[1],p3[2],p3[3],t-math.sqrt((p[1]-p3[1])^2+(p[2]-p3[2])^2+(p[3]-p3[3])^2)},{p4[1],p4[2],p4[3],t-math.sqrt((p[1]-p4[1])^2+(p[2]-p4[2])^2+(p[3]-p4[3])^2)})))
  155. print(unpack(p))
  156. --]]
  157.  
  158. local dirs={
  159.     North=1,
  160.     East=0,
  161.     South=3,
  162.     West=2,
  163.     N=1,
  164.     E=0,
  165.     S=3,
  166.     W=2,
  167.     north=1,
  168.     east=0,
  169.     south=3,
  170.     west=2,
  171.     n=1,
  172.     e=0,
  173.     s=3,
  174.     w=2,
  175.     ["0"]=0,
  176.     ["1"]=1,
  177.     ["2"]=2,
  178.     ["3"]=3,
  179.     ["4"]=0,
  180. }
  181.  
  182. local function setHome(v)
  183.     local f=io.open("home.csv","w")
  184.     f:write(concat(v,","))
  185.     f:close()
  186. end
  187.  
  188. local function getHome()
  189.     local f=io.open("home.csv","r")
  190.     if f then
  191.         local v={}
  192.         for a in f:read'*a':gmatch'[^%s,]+' do
  193.             v[#v+1]=tonumber(a)
  194.         end
  195.         return v
  196.     else
  197.         error'Error: No home set.'
  198.     end
  199. end
  200.  
  201. if arg[1]=="set" then
  202.     if #arg==5 then
  203.         local x,y,z,f=unpack(arg,2,5)
  204.         if tonumber(x) and tonumber(y) and tonumber(z) and dirs[f] then
  205.             setHome{x,y,z,dirs[f]}
  206.         else
  207.             error'Invalid coordinates'
  208.         end
  209.     elseif #arg==2 and type(arg[2])=="string" and arg[2]~="here" then
  210.         local x,y,z,f=arg[2]:match'(.+),(.+),(.+),(.+)'
  211.         if tonumber(x) and tonumber(y) and tonumber(z) and dirs[f] then
  212.             setHome{x,y,z,dirs[f]}
  213.         end
  214.     else
  215.         local p=locate()
  216.         print(concat(p,", "))
  217.         setHome(p)
  218.     end
  219. else
  220.     local p=locate()
  221.     print(concat(p,", "))
  222.     local h=getHome()
  223.     print(concat(h,", "))
  224. end
Advertisement
Add Comment
Please, Sign In to add comment