Whitemambaa

host

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