Advertisement
MoonlightOwl

Totoro GeoMiner Alpha

Oct 5th, 2014
680
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.86 KB | None | 0 0
  1. -- Totoro GeoMiner Alpha 0.02 --
  2.  
  3. local computer = require('computer')
  4. local robot = require('robot')
  5. local event = require('event')
  6. local com = require('component')
  7.  
  8. -- Команды --
  9. STOP = 0x000000
  10. START = 0xFFFFFF
  11. COMEBACK = 0xC0FFEE
  12. BEACON = 0xBA0BAB
  13. -- Состояния --
  14. SCANNING = 0x000001
  15. MINING = 0x000002
  16. CHARGING = 0x000003
  17. WAITING = 0x000004
  18. DEADLOCK = 0x000005
  19. CONSTRUSTION = 0x000006
  20. -- Константы --
  21. BEGIN_ON_START = true
  22. START_DIR = 2 -- NORTH
  23. INVENTORY_SIZE = 32
  24. VALUABLE = 2.0
  25. PORT = 27
  26. LAYER_SIZE = 2
  27. LAYER_RAD = 32
  28. ATTEMPTS = 40
  29. MAX = 100
  30. --
  31.  
  32. function trytofind(name)
  33.   if com.isAvailable(name) then
  34.     return com.getPrimary(name)
  35.   else
  36.     return nil
  37.   end
  38. end
  39.  
  40. local tunnel = trytofind('tunnel')
  41. local geo    = trytofind('geolyzer')
  42. local gen    = trytofind('generator')
  43. local modem  = trytofind('modem')
  44.  
  45. --======================================= Н А В И Г А Ц И Я ======================================--
  46. moves = 0
  47. loc = {x=0, y=0, z=0, d=START_DIR}
  48. function forward()
  49.   if robot.forward() then
  50.     if loc.d == 0 then loc.z = loc.z+1
  51.     elseif loc.d == 1 then loc.x = loc.x-1
  52.     elseif loc.d == 2 then loc.z = loc.z-1
  53.     else loc.x = loc.x+1 end
  54.     moves = moves + 1
  55.     return true
  56.   else
  57.     return false
  58.   end
  59. end
  60. function up()
  61.   if robot.up() then
  62.     loc.y = loc.y+1
  63.     moves = moves + 1
  64.     return true
  65.   else
  66.     return false
  67.   end
  68. end
  69. function down()
  70.   if robot.down() then
  71.     loc.y = loc.y-1
  72.     moves = moves + 1
  73.     return true
  74.   else
  75.     return false
  76.   end
  77. end
  78. function turnRight()
  79.   loc.d = (loc.d+1)%4
  80.   robot.turnRight()
  81. end
  82. function turnAround()
  83.   loc.d = (loc.d+2)%4
  84.   robot.turnAround()
  85. end
  86. function turnLeft()
  87.   loc.d = (loc.d+3)%4
  88.   robot.turnLeft()
  89. end
  90.  
  91. --============================= Т О П Л И В О   И   И Н В Е Н Т А Р Ь =============================--
  92. function checkFuel()
  93.   if gen ~= nil then
  94.     if (computer.maxEnergy() - computer.energy()) > 1000 then
  95.       if gen.count() < 64 then
  96.         for i=1, INVENTORY_SIZE do
  97.           robot.select(i)
  98.           if gen.insert() then break end
  99.         end
  100.       end
  101.     end
  102.   end
  103. end
  104.  
  105. --====================================== П О И С К   Р У Д Ы ======================================--
  106. data = {}
  107. function setData(x, z, d)
  108.   if data[x] == nil then data[x] = {} end
  109.   data[x][z] = d
  110. end
  111. function setDataBlock(x, y, z, d)
  112.   data[x][z][y+33] = d
  113. end
  114. function getData(x, z)
  115.   if data[x] ~= nil then return data[x][z] end
  116.   return nil
  117. end
  118. function updateData()
  119.   for k, v in pairs(data) do
  120.     -- обрезаем по координате X
  121.     if math.abs(k - loc.x) > LAYER_RAD then
  122.       data[k] = nil
  123.     else
  124.       for a, b in pairs(v) do
  125.         -- обрезаем по координате Z
  126.         if math.abs(a - loc.z) > LAYER_RAD then
  127.           v[a] = nil
  128.         end
  129.       end
  130.     end
  131.   end
  132. end
  133.  
  134. -- ищем самый плотный блок в колонне
  135. function check(x, z, y, ow, oy)
  136.   if getData(x,z) == nil then return ow, oy end
  137.   if getData(x,z)[y] > ow then return getData(x,z)[y], y end
  138.   return ow, oy
  139. end
  140. function best(x, z)
  141.   local worth = 0.0
  142.   local wy = 0
  143.   for y=33-LAYER_SIZE, 33+LAYER_SIZE do
  144.     if x~=0 or z~=0 or y~=33 then
  145.       worth, wy = check(x, z, y, worth, wy)
  146.     end
  147.   end
  148.   return worth, wy
  149. end
  150.  
  151. -- сканируем колонны по окружности
  152. function scan(dist)
  153.   local value = 0
  154.   local vx = 0
  155.   local vy = 0
  156.   local vz = 0
  157.  
  158.   for z=-dist, dist do
  159.     x = dist - math.abs(z)
  160.  
  161.     if getData(x+loc.x, z+loc.z) == nil then
  162.       while loc.y>0 do forcedown() end
  163.       while loc.y<0 do forceup() end
  164.       setData(x+loc.x, z+loc.z, geo.scan(x, z))
  165.     end
  166.     local w, y = best(x+loc.x, z+loc.z)
  167.     if w >= value then
  168.       value = w
  169.       vx = x; vy = y; vz = z
  170.     end
  171.  
  172.     if x ~= 0 then
  173.       if getData(loc.x-x, z+loc.z) == nil then
  174.         while loc.y>0 do forcedown() end
  175.         while loc.y<0 do forceup() end
  176.         setData(loc.x-x, z+loc.z, geo.scan(-x, z))
  177.       end
  178.       local w, y = best(loc.x-x, z+loc.z)
  179.       if w >= value then
  180.         value = w
  181.         vx = -x; vy = y; vz = z
  182.       end
  183.     end
  184.   end
  185.   return value, vx, vy, vz
  186. end
  187.  
  188. -- сканируем концентрическими окружностями
  189. function search()
  190.   for distance=0, LAYER_RAD do
  191.     print("Дистанция: "..distance)
  192.     v, x, y, z = scan(distance)
  193.     if v >= VALUABLE then
  194.       return true, x+loc.x, y-33, z+loc.z, v
  195.     end
  196.   end
  197.   return false
  198. end
  199.  
  200. --======================================== Д В И Ж Е Н И Е ========================================--
  201. function turnTo(dir)
  202.   while loc.d < dir do turnRight() end
  203.   while loc.d > dir do turnLeft() end
  204. end
  205. function forceforward()
  206.   local c = 0
  207.   while not forward() do
  208.     robot.swing()
  209.     c = c+1
  210.     if c > ATTEMPTS then return false end
  211.   end
  212.   return true
  213. end
  214. function forceup()
  215.   local c = 0
  216.   while not up() do
  217.     robot.swingUp()
  218.     c = c+1
  219.     if c > ATTEMPTS then return false end
  220.   end
  221.   return true
  222. end
  223. function forcedown()
  224.   local c = 0
  225.   while not down() do
  226.     robot.swingDown()
  227.     c = c+1
  228.     if c > ATTEMPTS then return false end
  229.   end
  230.   return true
  231. end
  232. function moveTo(target)
  233.   if loc.x < target.x then
  234.     turnTo(3)
  235.     if forceforward() then return true end
  236.   end
  237.   if loc.x > target.x then
  238.     turnTo(1)
  239.     if forceforward() then return true end
  240.   end
  241.   if loc.z < target.z then
  242.     turnTo(0)
  243.     if forceforward() then return true end
  244.   end
  245.   if loc.z > target.z then
  246.     turnTo(2)
  247.     if forceforward() then return true end
  248.   end
  249.   if loc.y < target.y then
  250.     if forceup() then return true end
  251.   end
  252.   if loc.y > target.y then
  253.     if forcedown() then return true end
  254.   end
  255.   return false
  256. end
  257.  
  258. --======================================= С О С Т О Я Н И Я =======================================--
  259. function setState(code)
  260.   if tunnel ~= nil then tunnel.send(code) end
  261.   if modem ~= nil then modem.broadcast(PORT, code) end
  262.   if code == DEADLOCK then
  263.     active = false
  264.   end
  265. end
  266.  
  267. --==================================== Г Л А В Н Ы Й   Ц И К Л ====================================--
  268. -- в конструкции должен присутствовать геосканер
  269. if geo == nil then
  270.   setState(CONSTRUSTION)
  271.   return false
  272. end
  273. if modem ~= nil then modem.open(PORT) end
  274.  
  275. print("Ожидаю сигнала...")
  276.  
  277. active = BEGIN_ON_START
  278. target = {x=0, y=0, z=0, active=false, worth=0}
  279.  
  280. while true do
  281.   checkFuel()
  282.  
  283.   -- обработка команд
  284.   name, add, _, _, _, message, a,b,c = event.pull(0.1)
  285.   if name == 'modem_message' then
  286.     if message == STOP then
  287.       active = false
  288.     elseif message == START then
  289.       active = true
  290.     end
  291.   end
  292.  
  293.   -- поиск руды и добыча
  294.   if active then
  295.     -- если цель не обнаружена - сканировать
  296.     if not target.active then
  297.       setState(SCANNING)
  298.       target.active, target.x, target.y, target.z, target.worth = search()
  299.       print('Новая цель: ', target.x, target.y, target.z, target.worth)
  300.     -- если есть цель - двигаться к цели
  301.     else
  302.       setState(MINING)
  303.       -- робот двигается блоками по 10
  304.       for i=1, 10 do
  305.         -- если движение прекратилось
  306.         if not moveTo(target) then
  307.           target.active = false
  308.           -- если робот не дошел до цели
  309.           if target.x ~= loc.x or target.y ~= loc.y or target.z ~= loc.z then
  310.             setState(DEADLOCK)
  311.           else
  312.             setDataBlock(loc.x, loc.y, loc.z, 0.0)
  313.             updateData()
  314.           end
  315.           break
  316.         end
  317.       end
  318.     end
  319.   end
  320. end
  321.  
  322. if modem ~= nil then modem.close(PORT) end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement