Advertisement
asweigart

hare (book)

Jul 28th, 2016
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.10 KB | None | 0 0
  1. -- "Hare" utility library
  2. -- By Al Sweigart
  3. -- turtleappstore.com/users/AlSweigart
  4. -- Provides useful utility functions.
  5.  
  6. hareVersion = "4"
  7.  
  8. -- fuelSpace() returns how much space
  9. -- for fuel there is left
  10. function fuelSpace()
  11. if turtle.getFuelLimit() == 'unlimited' then
  12. return 0
  13. else
  14. return turtle.getFuelLimit() - turtle.getFuelLevel()
  15. end
  16. end
  17.  
  18. -- findItem() returns inventory slot
  19. -- that has the named item, or nil if not found
  20. function findItem(name)
  21. local slot, item
  22.  
  23. -- first try to find an exact name match
  24. for slot = 1, 16 do
  25. item = turtle.getItemDetail(slot)
  26. if item ~= nil and item['name'] == name then
  27. return slot
  28. end
  29. end
  30.  
  31. -- don't try a similar match if name
  32. -- has a colon (like "minecraft:")
  33. if string.find(name, ':') ~= nil then
  34. return nil -- couldn't find item
  35. end
  36.  
  37. -- next try to find a similar name match
  38. for slot = 1, 16 do
  39. item = turtle.getItemDetail(slot)
  40. if item ~= nil and string.find(item['name'], name) then
  41. return slot
  42. end
  43. end
  44.  
  45. return nil -- couldn't find item
  46. end
  47.  
  48.  
  49. -- selectItem() selects the inventory
  50. -- slot with the named item, returns
  51. -- true if found and false if not
  52. function selectItem(name)
  53. -- selects inventory slot that has the named item
  54. -- return true if found, false if not found
  55. local slot = findItem(name)
  56.  
  57. if slot ~= nil then
  58. turtle.select(slot)
  59. return true
  60. else
  61. return false -- couldn't find item
  62. end
  63. end
  64.  
  65.  
  66. -- findEmptySlot() finds inventory slot
  67. -- that is empty, returns slot number
  68. -- if found, returns nil if no empty spaces
  69. function findEmptySlot()
  70. -- loop through all slots
  71. local slot
  72. for slot = 1, 16 do
  73. if turtle.getItemCount(slot) == 0 then
  74. return slot
  75. end
  76. end
  77. return nil -- couldn't find empty space
  78. end
  79.  
  80.  
  81. -- selectEmptySlot() selects inventory
  82. -- slot that is empty, returns true if
  83. -- found, false if no empty spaces
  84. function selectEmptySlot()
  85. -- loop through all slots
  86. local slot = findEmptySlot()
  87. if slot ~= nil then
  88. turtle.select(slot)
  89. return true
  90. else
  91. return false -- couldn't find empty space
  92. end
  93. end
  94.  
  95.  
  96. -- findBlock() spins around searching
  97. -- for the named block next to the turtle
  98. function findBlock(name)
  99. local foundBlock = false
  100. local i
  101. for i = 1, 4 do
  102. local result, block = turtle.inspect()
  103. if block ~= nil and block['name'] == name then
  104. return true
  105. end
  106. turtle.turnRight()
  107. end
  108. return false
  109. end
  110.  
  111.  
  112. function sweepField(forward, left, sweepFunc)
  113. local x = 0
  114. local y = 0
  115. local i
  116.  
  117. while true do
  118. -- moving forward AWAY from the home space
  119. while y < forward - 1 do
  120. if sweepFunc ~= nil then
  121. sweepFunc(x, y)
  122. end
  123.  
  124. if not turtle.forward() then return false end
  125. y = y + 1
  126. end
  127.  
  128. -- call the sweep function at the furthest row from the home space
  129. if sweepFunc ~= nil then
  130. sweepFunc(x, y)
  131. end
  132.  
  133. -- check if this is the last column
  134. if x == left - 1 then
  135. break
  136. end
  137.  
  138. -- turn left to next
  139. turtle.turnLeft()
  140. if not turtle.forward() then return false end
  141. x = x + 1
  142. turtle.turnLeft()
  143.  
  144. -- moving forward TOWARDS from the home space
  145. while y > 0 do
  146. if sweepFunc ~= nil then
  147. sweepFunc(x, y)
  148. end
  149.  
  150. if not turtle.forward() then return false end
  151. y = y - 1
  152. end
  153.  
  154. -- call the sweep function at the closest row from the home space
  155. if sweepFunc ~= nil then
  156. sweepFunc(x, y)
  157. end
  158.  
  159. -- check if this is the last column
  160. if x == left - 1 then
  161. break
  162. end
  163.  
  164. -- turn right to next
  165. turtle.turnRight()
  166. if not turtle.forward() then return false end
  167. x = x + 1
  168. turtle.turnRight()
  169. end
  170.  
  171. -- move back to the home space
  172. if left % 2 == 0 then
  173. -- even number of columns traversed means we ended closest to the home row
  174. turtle.turnLeft()
  175. for i = 1, left - 1 do
  176. if not turtle.forward() then return false end
  177. end
  178. turtle.turnLeft()
  179. else
  180. -- odd number of columns traversed means we ended furtherst from the home row
  181. for i = 1, forward - 1 do
  182. if not turtle.back() then return false end
  183. end
  184. turtle.turnRight()
  185. for i = 1, left - 1 do
  186. if not turtle.forward() then return false end
  187. end
  188. turtle.turnLeft()
  189. end
  190.  
  191. return true
  192. end
  193.  
  194.  
  195. -- sweepField() moves across the rows
  196. -- and columns of an area in front and
  197. -- to the left of the turtle, calling
  198. -- the provided sweepFunc at each point
  199. function sweepFieldXXX(rows, columns, sweepFunc)
  200. local turnLeftNext = true
  201. local columnStep = 1
  202. local rowStep = 1
  203. for columnStep = 1, columns do
  204. if sweepFunc ~= nil then
  205. sweepFunc(columnStep - 1, rowStep - 1, rows, columns)
  206. end
  207.  
  208. -- move forward through rows
  209. for rowStep = 2, rows do
  210. if not turtle.forward() then return false end
  211.  
  212. -- call the sweepFunc function
  213. if sweepFunc ~= nil then
  214. sweepFunc(columnStep - 1, rowStep - 1, rows, columns)
  215. end
  216. end
  217.  
  218. if columnStep == columns then
  219. -- don't turn on the last column
  220. break
  221. end
  222.  
  223. -- turn to the next column
  224. if turnLeftNext then
  225. turtle.turnLeft()
  226. if not turtle.forward() then return false end
  227. turtle.turnLeft()
  228. turnLeftNext = false
  229. else
  230. turtle.turnRight()
  231. if not turtle.forward() then return false end
  232. turtle.turnRight()
  233. turnLeftNext = true
  234. end
  235. end
  236.  
  237. -- move back to the start
  238. if columns % 2 == 0 then
  239. turtle.turnLeft()
  240. else
  241. for i = 1, rows - 1 do
  242. if not turtle.back() then return false end
  243. end
  244. turtle.turnRight()
  245. end
  246. for i = 1, columns - 1 do
  247. if not turtle.forward() then return false end
  248. end
  249. turtle.turnLeft()
  250.  
  251. return true
  252. end
  253.  
  254.  
  255. -- countItems() returns the total number
  256. -- of items with the exact name in the
  257. -- turtle's inventory
  258. function countItems(name)
  259. local total = 0
  260. local slot
  261. for slot = 1,16 do
  262. local item = turtle.getItemDetail(slot)
  263. if item ~= nil and item['name'] == name then
  264. total = total + item['count']
  265. end
  266. end
  267. return total
  268. end
  269.  
  270.  
  271. -- countInventory() returns the total
  272. -- number of items in the inventory
  273. function countInventory()
  274. local total = 0
  275. local slot
  276. for slot = 1, 16 do
  277. total = total + turtle.getItemCount(slot)
  278. end
  279. return total
  280. end
  281.  
  282.  
  283. -- buildRectangleFloor() builds a rectangle
  284. -- shaped floor out of the blocks in the
  285. -- inventory
  286. function buildRectangleFloor(length, width)
  287. if countInventory() < length * width then
  288. return false, 'Not enough blocks.' -- not enough blocks
  289. end
  290. turtle.up()
  291. sweepField(length, width, selectAndPlaceDown)
  292. end
  293.  
  294.  
  295. -- selectAndPlaceDown() selects a nonempty
  296. -- slot and places it under the turtle
  297. function selectAndPlaceDown()
  298. local slot
  299. for slot = 1, 16 do
  300. if turtle.getItemCount(slot) > 0 then
  301. turtle.select(slot)
  302. turtle.placeDown()
  303. break
  304. end
  305. end
  306. end
  307.  
  308.  
  309. -- buildWall() creates a wall stretching
  310. -- in front of the turtle
  311. function buildWall(length, height)
  312. if countInventory() < length * height then
  313. return false -- not enough blocks
  314. end
  315.  
  316. turtle.up()
  317.  
  318. local currentHeight, currentLength
  319. local movingForward = true
  320. for currentHeight = 1, height do
  321. for currentLength = 1, length do
  322. selectAndPlaceDown() -- place the block
  323. if movingForward and currentLength ~= length then
  324. turtle.forward()
  325. elseif not movingForward and currentLength ~= length then
  326. turtle.back()
  327. end
  328. end
  329. if currentHeight ~= height then
  330. turtle.up()
  331. end
  332. movingForward = not movingForward
  333. end
  334.  
  335. -- done building wall, move to end position
  336. local i
  337. if movingForward then
  338. -- turtle near the start position
  339. for i = 1, length do
  340. turtle.forward()
  341. end
  342. else
  343. -- turtle near the end position
  344. turtle.forward()
  345. end
  346.  
  347. -- move down to the ground
  348. for i = 1, height do
  349. turtle.down()
  350. end
  351. end
  352.  
  353.  
  354. --
  355. function buildRoom(length, width, height)
  356. if countInventory() < ((length * height * height) - ((length - 1) * (height - 1) * height)) then
  357. return false -- not enough blocks
  358. end
  359.  
  360. -- build the four walls
  361. buildWall(length - 1, height)
  362. turtle.turnRight()
  363.  
  364. buildWall(width - 1, height)
  365. turtle.turnRight()
  366.  
  367. buildWall(length - 1, height)
  368. turtle.turnRight()
  369.  
  370. buildWall(width - 1, height)
  371. turtle.turnRight()
  372. end
  373.  
  374.  
  375. -- buildCircleFloor() builds a circle
  376. -- shaped floor out of the blocks in the
  377. -- inventory, centered on the turtle's
  378. -- starting position
  379. function buildCircleFloor(radius)
  380. -- this is an overestimation of the blocks needed
  381. local diameter = radius * 2 + 1
  382. if countInventory() < (diameter * diameter) then
  383. return false, 'Not enough blocks.' -- not enough blocks
  384. end
  385.  
  386. -- move to start of sweep area
  387. local i
  388. turtle.up()
  389. turtle.turnLeft()
  390. for i = 1, math.floor(radius) do
  391. turtle.forward()
  392. end
  393. turtle.turnRight()
  394. for i = 1, math.floor(radius) do
  395. turtle.back()
  396. end
  397.  
  398. -- place blocks
  399. sweepField(radius * 2 + 1, radius * 2 + 1, selectAndPlaceDownInCircle)
  400.  
  401. -- move back to center
  402. for i = 1, math.floor(radius) do
  403. turtle.forward()
  404. end
  405. turtle.turnRight()
  406. for i = 1, math.floor(radius) do
  407. turtle.forward()
  408. end
  409. turtle.turnLeft()
  410. end
  411.  
  412.  
  413. -- selectAndPlaceDownInCircle() selects
  414. -- a nonempty slot and places it under
  415. -- the turtle if it is within the circle's
  416. -- radius
  417. function selectAndPlaceDownInCircle(x, y, length, width)
  418. local radius = math.floor(length / 2)
  419. local centerx = math.ceil(length / 2)
  420. local centery = math.ceil(width / 2)
  421.  
  422. local xdistance = centerx - x
  423. local ydistance = centery - y
  424.  
  425. if (math.sqrt(xdistance * xdistance + ydistance * ydistance) < radius) then
  426. selectAndPlaceDown()
  427. print(x, y, length, width, 'yes')
  428. else
  429. print(x, y, length, width, 'no')
  430. end
  431. end
  432.  
  433.  
  434. -- digUntilClear() keeps digging until
  435. -- there are no more blocks (used when
  436. -- sand or gravel can fall into the path)
  437. function digUntilClear()
  438. while turtle.detect() do
  439. turtle.dig()
  440. end
  441. end
  442.  
  443.  
  444. -- digUpUntilClear() keeps digging until
  445. -- there are no more blocks (used when
  446. -- sand or gravel can fall into the path)
  447. function digUpUntilClear()
  448. while turtle.detectUp() do
  449. turtle.digUp()
  450. end
  451. end
  452.  
  453.  
  454. -- digDownUntilClear() keeps digging until
  455. -- there are no more blocks (used when
  456. -- sand or gravel can fall into the path)
  457. function digDownUntilClear()
  458. while turtle.detectDown() do
  459. turtle.digDown()
  460. end
  461. end
  462.  
  463.  
  464.  
  465. -- Print contents of `tbl`, with indentation.
  466. -- `indent` sets the initial level of indentation.
  467. function tprint (tbl, indent)
  468. if not indent then indent = 0 end
  469. for k, v in pairs(tbl) do
  470. formatting = string.rep(" ", indent) .. k .. ": "
  471. if type(v) == "table" then
  472. print(formatting)
  473. tprint(v, indent+1)
  474. elseif type(v) == 'boolean' then
  475. print(formatting .. tostring(v))
  476. else
  477. print(formatting .. v)
  478. end
  479. end
  480. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement