Advertisement
ondrej008

Untitled

Nov 15th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.90 KB | None | 0 0
  1. local startingPosition = { x = 0, y = 0, z = 0}
  2.  
  3. local blocksExplored = {}
  4. local blocksExploredTravellable = {}
  5. local blockQueue = {}
  6. local logMessages = {}
  7.  
  8. local dirWorld = "north"
  9.  
  10. local file = fs.open("turtle_log", "w")
  11. local blockFile = fs.open("turtle_blocks", "w")
  12.  
  13. term.write("Enter turtle's x coordinate: ")
  14. startingPosition.x = io.read("*l")
  15. term.write("Enter turtle's y coordinate: ")
  16. startingPosition.y = io.read("*l")
  17. term.write("Enter turtle's z coordinate: ")
  18. startingPosition.z = io.read("*l")
  19. local currentPosition = startingPosition
  20.  
  21. local function logMessage(msg)
  22. --logMessages[#logMessages + 1] = tostring(msg)
  23. file.write(tostring(msg) .. "\n")
  24. file.flush()
  25. term.write(tostring(msg) .. "\n")
  26. end
  27.  
  28. local function tableString(tbl)
  29. local str = "{"
  30. local size = 0
  31. for k,v in pairs(tbl) do
  32. size = size + 1
  33. end
  34. local i = 1
  35. for k,v in pairs(tbl) do
  36. str = str .. k .. "=" .. v
  37. if(i ~= size) then str = str .. "," end
  38. i = i + 1
  39. end
  40. str = str .. "}"
  41. return str
  42. end
  43.  
  44. -- help
  45. local function round(n)
  46. return math.floor(n + 0.5)
  47. end
  48.  
  49. local function consumeFuel()
  50. for i = 1, 16, 1 do
  51. local fuelDifference = turtle.getFuelLimit() - turtle.getFuelLevel()
  52. if(fuelDifference < (80 * 64)) then
  53. turtle.refuel()
  54. end
  55. end
  56. --logMessage("[CaveEX]: New fuel amount is " .. turtle.getFuelLevel() .. " actions/moves.")
  57. end
  58.  
  59. local function compactPosition()
  60. return "x: " .. currentPosition.x .. ", y: " .. currentPosition.y .. ", z: " .. currentPosition.z
  61. end
  62.  
  63. local function updatePosition()
  64. if(dirWorld == "north") then
  65. startingPosition.z = startingPosition.z - 1
  66. elseif(dirWorld == "south") then
  67. startingPosition.z = startingPosition.z + 1
  68. elseif(dirWorld == "west") then
  69. startingPosition.x = startingPosition.x - 1
  70. elseif(dirWorld == "east") then
  71. startingPosition.x = startingPosition.x + 1
  72. end
  73. end
  74.  
  75. local function forward()
  76. local success = turtle.forward()
  77. if(not success) then
  78. logMessage("ERROR WHILE MOVING FORWARD: " .. tableString(currentPosition) .. " " .. dirWorld)
  79. end
  80. updatePosition()
  81. end
  82.  
  83. local function noDuplicate(newEntry)
  84. newEntry.x = round(newEntry.x)
  85. newEntry.y = round(newEntry.y)
  86. newEntry.z = round(newEntry.z)
  87. for i, v in pairs(blocksExplored) do
  88. v.x = round(v.x)
  89. v.y = round(v.y)
  90. v.z = round(v.z)
  91. if(v.x == newEntry.x and v.y == newEntry.y and v.z == newEntry.z) then
  92. --logMessage("[CaveEX]: Found duplicate in blocksExplored " .. tableString(newEntry))
  93. return false
  94. end
  95. end
  96.  
  97. for i, v in pairs(blockQueue) do
  98. v.x = round(v.x)
  99. v.y = round(v.y)
  100. v.z = round(v.z)
  101. if(v.x == newEntry.x and v.y == newEntry.y and v.z == newEntry.z) then
  102. --logMessage("[CaveEX]: Found duplicate in blockQueue " .. tableString(newEntry))
  103. return false
  104. end
  105. end
  106.  
  107. return true
  108. end
  109.  
  110. local function dirToOffset()
  111. if(dirWorld == "north") then
  112. return 0, -1
  113. elseif(dirWorld == "south") then
  114. return 0, 1
  115. elseif(dirWorld == "west") then
  116. return -1, 0
  117. elseif(dirWorld == "east") then
  118. return 1, 0
  119. end
  120. end
  121.  
  122. local function leftTurn()
  123. if(dirWorld == "north") then
  124. dirWorld = "west"
  125. elseif(dirWorld == "west") then
  126. dirWorld = "south"
  127. elseif(dirWorld == "south") then
  128. dirWorld = "east"
  129. elseif(dirWorld == "east") then
  130. dirWorld = "north"
  131. end
  132. end
  133.  
  134. local function rightTurn()
  135. if(dirWorld == "north") then
  136. dirWorld = "east"
  137. elseif(dirWorld == "west") then
  138. dirWorld = "north"
  139. elseif(dirWorld == "south") then
  140. dirWorld = "west"
  141. elseif(dirWorld == "east") then
  142. dirWorld = "south"
  143. end
  144. end
  145.  
  146. local function addIfAirFront()
  147. consumeFuel()
  148. if(not turtle.detect()) then
  149. local x0, z0 = dirToOffset()
  150. local newEntry = { x = currentPosition.x + x0, y = currentPosition.y, z = currentPosition.z + z0 }
  151. if(noDuplicate(newEntry)) then
  152. blockQueue[#blockQueue + 1] = newEntry
  153. end
  154. else
  155. local x0, z0 = dirToOffset()
  156. local success, data = turtle.inspect()
  157. local newEntry = { x = currentPosition.x + x0, y = currentPosition.y, z = currentPosition.z + z0, name = data.name, meta = data.metadata }
  158. if(noDuplicate(newEntry)) then
  159. blocksExplored[#blocksExplored + 1] = newEntry
  160. blockFile.write(tableString(newEntry) .. "\n")
  161. blockFile.flush()
  162. end
  163. end
  164. turtle.turnLeft()
  165. leftTurn()
  166. end
  167.  
  168. local function addIfAir()
  169. if(not turtle.detectDown()) then
  170. local newEntry = { x = currentPosition.x, y = currentPosition.y - 1, z = currentPosition.z }
  171. if(noDuplicate(newEntry)) then
  172. blockQueue[#blockQueue + 1] = newEntry
  173. end
  174. else
  175. local success, data = turtle.inspectDown()
  176. local newEntry = { x = currentPosition.x, y = currentPosition.y - 1, z = currentPosition.z, name = data.name, meta = data.metadata }
  177. if(noDuplicate(newEntry)) then
  178. blocksExplored[#blocksExplored + 1] = newEntry
  179. blockFile.write(tableString(newEntry) .. "\n")
  180. blockFile.flush()
  181. end
  182. end
  183.  
  184. if(not turtle.detectUp()) then
  185. local newEntry = { x = currentPosition.x, y = currentPosition.y + 1, z = currentPosition.z }
  186. if(noDuplicate(newEntry)) then
  187. blockQueue[#blockQueue + 1] = newEntry
  188. end
  189. else
  190. local success, data = turtle.inspectUp()
  191. local newEntry = { x = currentPosition.x, y = currentPosition.y + 1, z = currentPosition.z, name = data.name, meta = data.metadata }
  192. if(noDuplicate(newEntry)) then
  193. blocksExplored[#blocksExplored + 1] = newEntry
  194. blockFile.write(tableString(newEntry) .. "\n")
  195. blockFile.flush()
  196. end
  197. end
  198.  
  199. addIfAirFront()
  200. addIfAirFront()
  201. addIfAirFront()
  202. addIfAirFront()
  203.  
  204. for key, value in ipairs(blockQueue) do
  205. if(round(value.x) == round(currentPosition.x) and round(value.y) == round(currentPosition.y) and round(value.z) == round(currentPosition.z)) then
  206. table.remove(blockQueue, key)
  207. end
  208. end
  209. local newEntry = { x = currentPosition.x, y = currentPosition.y, z = currentPosition.z, name = "air", meta = 0 }
  210. if(noDuplicate(newEntry)) then
  211. blockFile.write(tableString(newEntry) .. "\n")
  212. blockFile.flush()
  213. blocksExplored[#blocksExplored + 1] = newEntry
  214. blocksExploredTravellable[#blocksExploredTravellable + 1] = newEntry
  215. end
  216. end
  217.  
  218. term.write("CaveEX starting from " .. compactPosition())
  219.  
  220. local timeStart = os.clock()
  221.  
  222. consumeFuel()
  223.  
  224. -- Populate blockQueue with the blocks around us.
  225.  
  226. addIfAir()
  227.  
  228. local function lowestTable(tbl)
  229. local lowestValue = 999999
  230. local lowest = nil
  231. for key, value in pairs(tbl) do
  232. if(value < lowestValue) then
  233. lowestValue = value
  234. lowest = key
  235. end
  236. end
  237. return lowest
  238. end
  239.  
  240. local function indexTable(tbl, ele)
  241. for key, value in pairs(tbl) do
  242. value.x = round(value.x)
  243. value.y = round(value.y)
  244. value.z = round(value.z)
  245. ele.x = round(ele.x)
  246. ele.y = round(ele.y)
  247. ele.z = round(ele.z)
  248. if(value.x == ele.x and value.y == ele.y and value.z == ele.z) then
  249. return key
  250. end
  251. end
  252. end
  253.  
  254. local function getNeighbours(current)
  255. local returnable = {}
  256. for key, value in pairs(blocksExploredTravellable) do
  257. value.x = round(value.x)
  258. value.y = round(value.y)
  259. value.z = round(value.z)
  260. current.x = round(current.x)
  261. current.y = round(current.y)
  262. current.z = round(current.z)
  263. if(value.x == current.x and value.y == current.y and (value.z == current.z + 1 or value.z == current.z - 1)) then
  264. returnable[#returnable + 1] = value
  265. elseif((value.x == current.x + 1 or value.x == current.x - 1) and value.y == current.y and value.z == current.z) then
  266. returnable[#returnable + 1] = value
  267. elseif(value.x == current.x and (value.y == current.y + 1 or value.y == current.y - 1) and value.z == current.z) then
  268. returnable[#returnable + 1] = value
  269. end
  270. end
  271. end
  272.  
  273. local function h(value, goal)
  274. local xD = goal.x - value.x
  275. local yD = (goal.y - value.y) * 10
  276. local zD = goal.z - value.z
  277. return math.sqrt(xD^2 + yD^2 + zD^2)
  278. end
  279.  
  280. local function tableIn(tbl, ele)
  281. for key, value in pairs(tbl) do
  282. if(round(ele.x) == round(key.x) and round(ele.y) == round(key.y) and round(ele.z) == round(key.z)) then
  283. return true
  284. end
  285. end
  286.  
  287. return false
  288. end
  289.  
  290. local function tablePrepend(tbl, ele)
  291. local returnable = { ele }
  292.  
  293. for key, value in pairs(tbl) do
  294. returnable[key] = value
  295. end
  296.  
  297. return returnable
  298. end
  299.  
  300. local function reconstructPath(cameFrom, current)
  301. totalPath = { current }
  302. while(tableIn(cameFrom, current)) do
  303. current = cameFrom[current]
  304. totalPath = tablePrepend(totalPath, current)
  305. end
  306. return totalPath
  307. end
  308.  
  309. local function aSTAR(start, goal)
  310. local openSet = { start } -- number indexed
  311. local cameFrom = {} -- value indexed
  312.  
  313. local gScore = {} -- value indexed
  314. gScore[start] = 0
  315.  
  316. local fScore = {} -- value indexed
  317. fScore[start] = h(start, goal)
  318.  
  319. while(#openSet > 0) do
  320. local current = lowestTable(fScore) -- check
  321. if(current == goal) then
  322. --term.write("I FRIKKIN GOT IT BOY!")
  323. return reconstructPath(cameFrom, current)
  324. end
  325.  
  326. openSet[indexTable(openSet, current)] = nil -- check
  327. if(getNeighbours(current)) then
  328. for key, value in pairs(getNeighbours(current)) do
  329. local tentative_gScore = gScore[current] + 1
  330. if(tentative_gScore < gScore[value]) then
  331. cameFrom[value] = current
  332. gScore[value] = tentative_gScore
  333. fScore[value] = gScore[value] + h(value, goal)
  334. if(openSet[indexTable(openSet, value)] == nil) then
  335. openSet[#openSet + 1] = value
  336. end
  337. end
  338. end
  339. else
  340. --term.write("No neighbors...")
  341. return { goal }
  342. end
  343. end
  344.  
  345. --term.write("didn't find it, sad!")
  346. end
  347.  
  348. local function moveBasedOnDirection(xD, zD)
  349. --currentPosition.x = currentPosition.x - xD
  350. --currentPosition.z = currentPosition.z - zD
  351. if(xD > 0) then
  352. -- decrease x, west, 101 - 100 = 1
  353. if(dirWorld == "west") then forward()
  354. elseif(dirWorld == "north") then leftTurn() turtle.turnLeft() forward()
  355. elseif(dirWorld == "south") then rightTurn() turtle.turnRight() forward()
  356. elseif(dirWorld == "east") then leftTurn() leftTurn() turtle.turnLeft() turtle.turnLeft() forward() end
  357. end
  358. if(xD < 0) then
  359. -- increase x, east, 100 - 101 = -1
  360. if(dirWorld == "east") then forward()
  361. elseif(dirWorld == "north") then rightTurn() turtle.turnRight() forward()
  362. elseif(dirWorld == "south") then leftTurn() turtle.turnLeft() forward()
  363. elseif(dirWorld == "west") then leftTurn() leftTurn() turtle.turnLeft() turtle.turnLeft() forward() end
  364. end
  365. if(zD > 0) then
  366. -- decrease z, north, 101 - 100 = 1
  367. if(dirWorld == "north") then forward()
  368. elseif(dirWorld == "west") then rightTurn() turtle.turnRight() forward()
  369. elseif(dirWorld == "east") then leftTurn() turtle.turnLeft() forward()
  370. elseif(dirWorld == "south") then leftTurn() leftTurn() turtle.turnLeft() turtle.turnLeft() forward() end
  371. end
  372. if(zD < 0) then
  373. -- increase z, south, 100 - 101 = -1
  374. if(dirWorld == "south") then forward()
  375. elseif(dirWorld == "west") then leftTurn() turtle.turnLeft() forward()
  376. elseif(dirWorld == "east") then rightTurn() turtle.turnRight() forward()
  377. elseif(dirWorld == "north") then leftTurn() leftTurn() turtle.turnLeft() turtle.turnLeft() forward() end
  378. end
  379. end
  380.  
  381. local function moveTo(goal)
  382. logMessage("From: " .. tableString(currentPosition) .. ", To: " .. tableString(goal))
  383. local xD = currentPosition.x - goal.x
  384. local yD = currentPosition.y - goal.y
  385. local zD = currentPosition.z - goal.z
  386.  
  387. local sanityCheck = 0
  388. if(xD ~= 0) then sanityCheck = sanityCheck + 1 end
  389. if(yD ~= 0) then sanityCheck = sanityCheck + 1 end
  390. if(zD ~= 0) then sanityCheck = sanityCheck + 1 end
  391. if(sanityCheck ~= 1) then
  392. logMessage("End my existence, " .. sanityCheck)
  393. logMessage(xD .. " " .. yD .. " " .. zD)
  394. end
  395. if(round(yD) > 0) then
  396. -- move down, 101 - 100 = 1
  397. turtle.down()
  398. currentPosition.y = currentPosition.y - yD
  399. end
  400. if(round(yD) < 0) then
  401. -- move up, 100 - 101 = -1
  402. turtle.up()
  403. currentPosition.y = currentPosition.y - yD
  404. end
  405. moveBasedOnDirection(round(xD), round(zD))
  406. logMessage("Now: " .. tableString(currentPosition))
  407. end
  408.  
  409. local function pathfind()
  410. -- Pathfind our way to the nearest block.
  411. local nearestBlock = { x = 0, y = 0, z = 0 }
  412. local nearestBlockValue = 999999
  413. logMessage("bQ = " .. #blockQueue)
  414. for _,v in pairs(blockQueue) do
  415. local xD = currentPosition.x - v.x
  416. local yD = (currentPosition.y - v.y) * 10 -- height difference mega important
  417. local zD = currentPosition.z - v.z
  418. local distance = math.sqrt(xD^2 + yD^2 + zD^2)
  419. --if(distanceLog) then logMessage("[CaveEX]: New distance " .. distance) end
  420. if(distance < nearestBlockValue) then
  421. nearestBlockValue = distance
  422. nearestBlock = { x = v.x, y = v.y, z = v.z }
  423. end
  424. end
  425. local path = aSTAR(currentPosition, nearestBlock)
  426.  
  427. for key, value in pairs(path) do
  428. logMessage(tableString(value))
  429. end
  430.  
  431. for key, value in pairs(path) do
  432. logMessage("Moving to: " .. key .. " = " .. tableString(value))
  433. moveTo(value)
  434. end
  435. end
  436.  
  437. while(#blockQueue > 0) do
  438. pathfind()
  439. addIfAir()
  440. end
  441.  
  442. --pathfind()
  443.  
  444. local timeEnd = os.clock() - timeStart
  445.  
  446. term.write("CaveEX finished in " .. timeEnd .. " seconds.")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement