Advertisement
HandieAndy

harvest.lua

Sep 27th, 2018
396
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.04 KB | None | 0 0
  1. -- Harvest Program for robots. Uses a hoe and geolyzer for optimal harvesting.
  2. --[[
  3. Author: Andrew Lalis
  4. File: harvest.lua
  5. Version: 1.0
  6. Last Modified: 27-09-2018
  7.    
  8. Description:
  9. This script enables a robot to harvest fields of crops quickly and efficiently.
  10. The robot will traverse the field and only harvest crops considered 'done' by
  11. their crop definition.
  12. --]]
  13.  
  14. local robot = require("robot")
  15. local component = require("component")
  16. local fs = component.filesystem
  17. local serial = require("serialization")
  18. local geolyzer = component.geolyzer
  19. local ic = component.inventory_controller
  20. local sides = require("sides")
  21.  
  22. local CONFIG_FILE = "harvest.conf"
  23.  
  24. local LEFT = 1
  25. local RIGHT = 0
  26.  
  27. -- List of crops which will be harvested.
  28. local crop_definitions = {}
  29.  
  30. -- Repeats the given function until it returns true.
  31. local function doUntilSuccess(func)
  32.     local success = func()
  33.     while (not success) do
  34.         success = func()
  35.     end
  36. end
  37.  
  38. -- Pre-defined path from turtle docking bay to start of harvest area (first crop).
  39. local function goToStart(rows, columns)
  40.     doUntilSuccess(robot.forward)
  41. end
  42.  
  43. -- Pre-defined path back to the turtle docking bay.
  44. local function goBack(rows, columns)
  45.     for i=1,(columns-1) do
  46.         doUntilSuccess(robot.back)
  47.     end
  48.     robot.turnRight()
  49.     for i=1,(rows-1) do
  50.         doUntilSuccess(robot.back)
  51.     end
  52.     robot.turnLeft()
  53.     doUntilSuccess(robot.back)
  54. end
  55.  
  56. --[[
  57. Select an item, given its name and damage value.
  58. item_name - string: The id string for an item.
  59. item_data - number: The damage value, or variation of an item. Defaults to zero.
  60. return - boolean: True if at least one slot contains the item. That slot is now
  61. selected.
  62. --]]
  63. local function selectItemByName(item_name, item_data)
  64.     for i=1,16 do
  65.         local stack = ic.getStackInInternalSlot(i)
  66.         if (stack ~= nil and stack.name == item_name and stack.damage == item_data) then
  67.             robot.select(i)
  68.             return true
  69.         end
  70.     end
  71.     return false
  72. end
  73.  
  74. --[[
  75. Checks if the hoe is equipped. Meant to be done before starting a harvest.
  76. return - boolean: True if a hoe is equipped, or false if not.
  77. --]]
  78. local function isHoeEquipped()
  79.     for i=1,16 do
  80.         local item_stack = ic.getStackInInternalSlot(i)
  81.         if (item_stack == nil) then
  82.             robot.select(i)
  83.             ic.equip()
  84.             new_item_stack = ic.getStackInInternalSlot(i)
  85.             if (new_item_stack ~= nil and string.match(new_item_stack.name, "_hoe")) then
  86.                 return true
  87.             end
  88.             return false
  89.         end
  90.     end
  91.     return false
  92. end
  93.  
  94. --[[
  95. Tries to harvest a plant, if it is one of the crops defined in the crop
  96. definitions table above.
  97. return - boolean: True if a plant was harvested, false otherwise.
  98. --]]
  99. local function harvestPlant()
  100.     local plant_data = geolyzer.analyze(sides.bottom)
  101.     local crop_definition = crop_definitions[plant_data.name]
  102.     if (crop_definition == nil) then
  103.         return false
  104.     end
  105.     if (plant_data.growth >= crop_definition.growth_limit) then
  106.         robot.swingDown()
  107.         selectItemByName(crop_definition.item_name, 0)
  108.         robot.placeDown()
  109.         return true
  110.     else
  111.         return false
  112.     end
  113. end
  114.  
  115. --[[
  116. Harvests one row of crops.
  117. length - int: The number of plants in this row.
  118. return - int: The number of crops that were harvested.
  119. --]]
  120. local function harvestRow(length)
  121.     local harvests = 0
  122.     for i=1,length do
  123.         if (i > 1) then
  124.             doUntilSuccess(robot.forward)
  125.         end
  126.         if (harvestPlant()) then
  127.             harvests = harvests + 1
  128.         end
  129.     end
  130.     return harvests
  131. end
  132.  
  133. --[[
  134. At the end of the row, the robot must rotate into the next row, and this is
  135. dependent on where the start location is.
  136. current_row_index - int: The row the robot is on prior to turning.
  137. start_location - int: Whether the robot starts at the left or right.
  138. --]]
  139. local function turnToNextRow(current_row_index, start_location)
  140.     if (current_row_index % 2 == start_location) then
  141.         robot.turnRight()
  142.     else
  143.         robot.turnLeft()
  144.     end
  145.     doUntilSuccess(robot.forward)
  146.     if (current_row_index % 2 == start_location) then
  147.         robot.turnRight()
  148.     else
  149.         robot.turnLeft()
  150.     end
  151. end
  152.  
  153. --[[
  154. Harvests a two dimensional area defined by rows and columns. The robot starts
  155. by moving forward down the first row.
  156. rows - int: The number of rows to harvest.
  157. columns - int: The number of columns to harvest.
  158. start_location - int: 1 for LEFT, 0 for RIGHT.
  159. return - int: The total number of crops harvested.
  160. --]]
  161. local function harvestField(rows, columns, start_location)
  162.     goToStart(rows, columns)
  163.     -- Begin harvesting.
  164.     robot.select(1)
  165.     local harvests = 0
  166.     for i=1,rows do
  167.         harvests = harvests + harvestRow(columns)
  168.         -- Do not turn to the next row on the last row.
  169.         if (i < rows) then
  170.             turnToNextRow(i, start_location)
  171.         end
  172.     end
  173.     goBack(rows, columns)
  174.     return harvests
  175. end
  176.  
  177. --[[
  178. Drops all carried items into an inventory below the robot.
  179. return - int: The number of items dropped.
  180. --]]
  181. local function dropItems()
  182.     local item_count = 0
  183.     for i=1,16 do
  184.         robot.select(i)
  185.         local stack = ic.getStackInInternalSlot(i)
  186.         if (stack ~= nil) then
  187.             doUntilSuccess(robot.dropDown)
  188.             item_count = item_count + stack.size
  189.         end
  190.     end
  191.     return item_count
  192. end
  193.  
  194. --[[
  195. Reads config from a file.
  196. filename - string: The string path/filename.
  197. return - table|nil: The table defined in config, or nil if the file does not
  198. exist or another error occurs.
  199. --]]
  200. local function loadConfig(filename)
  201.     -- Config file exists.
  202.     local f = io.open(filename, "r")
  203.     if (f == nil) then
  204.         print("No config file " .. filename .. " exists. Please create it before continuing.")
  205.         return nil
  206.     end
  207.     local t = serial.unserialize(f:read())
  208.     f:close()
  209.     return t
  210. end
  211.  
  212. --[[
  213. Guides the user in creating a new config.
  214. return - table: The config created.
  215. --]]
  216. local function createConfig(filename)
  217.     local config = {}
  218.     print("Does your robot start on the left or right of the field?")
  219.     local input = io.read()
  220.     if (input == "left") then
  221.         config.START_LOCATION_RELATIVE = LEFT
  222.     elseif (input == "right") then
  223.         config.START_LOCATION_RELATIVE = RIGHT
  224.     else
  225.         print("Invalid choice. Should be either left or right.")
  226.         return nil
  227.     end
  228.     print("Enter number of rows.")
  229.     config.ROWS = tonumber(io.read())
  230.     print("Enter number of columns.")
  231.     config.COLS = tonumber(io.read())
  232.  
  233.     print("How many crops are being harvested?")
  234.     config.crop_definitions = {}
  235.     for i=1,tonumber(io.read()) do
  236.         print("Crop "..i..": What is the block name? (Use geolyzer to analyze it)")
  237.         local name = io.read()
  238.         config.crop_definitions[name] = {}
  239.         print("  What is the growth threshold for harvesting?")
  240.         config.crop_definitions[name].growth_limit = tonumber(io.read())
  241.         print("  What is the item name of this crop?")
  242.         config.crop_definitions[name].item_name = io.read()
  243.     end
  244.     file = io.open(filename, "w")
  245.     file:write(serial.serialize(config))
  246.     file:close()
  247.     return config
  248. end
  249.  
  250. local function main()
  251.     local config = loadConfig(CONFIG_FILE)
  252.     if (config == nil) then
  253.         config = createConfig(CONFIG_FILE)
  254.     end
  255.     crop_definitions = config.crop_definitions
  256.     local harvest_count = harvestField(config.ROWS, config.COLS, config.START_LOCATION_RELATIVE)
  257.     local drop_count = dropItems()
  258.     print(harvest_count..", "..drop_count)
  259. end
  260.  
  261. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement