Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Harvest Program for robots. Uses a hoe and geolyzer for optimal harvesting.
- --[[
- Author: Andrew Lalis
- File: harvest.lua
- Version: 1.0
- Last Modified: 27-09-2018
- Description:
- This script enables a robot to harvest fields of crops quickly and efficiently.
- The robot will traverse the field and only harvest crops considered 'done' by
- their crop definition.
- --]]
- local robot = require("robot")
- local component = require("component")
- local fs = component.filesystem
- local serial = require("serialization")
- local geolyzer = component.geolyzer
- local ic = component.inventory_controller
- local sides = require("sides")
- local CONFIG_FILE = "harvest.conf"
- local LEFT = 1
- local RIGHT = 0
- -- List of crops which will be harvested.
- local crop_definitions = {}
- -- Repeats the given function until it returns true.
- local function doUntilSuccess(func)
- local success = func()
- while (not success) do
- success = func()
- end
- end
- -- Pre-defined path from turtle docking bay to start of harvest area (first crop).
- local function goToStart(rows, columns)
- doUntilSuccess(robot.forward)
- end
- -- Pre-defined path back to the turtle docking bay.
- local function goBack(rows, columns)
- for i=1,(columns-1) do
- doUntilSuccess(robot.back)
- end
- robot.turnRight()
- for i=1,(rows-1) do
- doUntilSuccess(robot.back)
- end
- robot.turnLeft()
- doUntilSuccess(robot.back)
- end
- --[[
- Select an item, given its name and damage value.
- item_name - string: The id string for an item.
- item_data - number: The damage value, or variation of an item. Defaults to zero.
- return - boolean: True if at least one slot contains the item. That slot is now
- selected.
- --]]
- local function selectItemByName(item_name, item_data)
- for i=1,16 do
- local stack = ic.getStackInInternalSlot(i)
- if (stack ~= nil and stack.name == item_name and stack.damage == item_data) then
- robot.select(i)
- return true
- end
- end
- return false
- end
- --[[
- Checks if the hoe is equipped. Meant to be done before starting a harvest.
- return - boolean: True if a hoe is equipped, or false if not.
- --]]
- local function isHoeEquipped()
- for i=1,16 do
- local item_stack = ic.getStackInInternalSlot(i)
- if (item_stack == nil) then
- robot.select(i)
- ic.equip()
- new_item_stack = ic.getStackInInternalSlot(i)
- if (new_item_stack ~= nil and string.match(new_item_stack.name, "_hoe")) then
- return true
- end
- return false
- end
- end
- return false
- end
- --[[
- Tries to harvest a plant, if it is one of the crops defined in the crop
- definitions table above.
- return - boolean: True if a plant was harvested, false otherwise.
- --]]
- local function harvestPlant()
- local plant_data = geolyzer.analyze(sides.bottom)
- local crop_definition = crop_definitions[plant_data.name]
- if (crop_definition == nil) then
- return false
- end
- if (plant_data.growth >= crop_definition.growth_limit) then
- robot.swingDown()
- selectItemByName(crop_definition.item_name, 0)
- robot.placeDown()
- return true
- else
- return false
- end
- end
- --[[
- Harvests one row of crops.
- length - int: The number of plants in this row.
- return - int: The number of crops that were harvested.
- --]]
- local function harvestRow(length)
- local harvests = 0
- for i=1,length do
- if (i > 1) then
- doUntilSuccess(robot.forward)
- end
- if (harvestPlant()) then
- harvests = harvests + 1
- end
- end
- return harvests
- end
- --[[
- At the end of the row, the robot must rotate into the next row, and this is
- dependent on where the start location is.
- current_row_index - int: The row the robot is on prior to turning.
- start_location - int: Whether the robot starts at the left or right.
- --]]
- local function turnToNextRow(current_row_index, start_location)
- if (current_row_index % 2 == start_location) then
- robot.turnRight()
- else
- robot.turnLeft()
- end
- doUntilSuccess(robot.forward)
- if (current_row_index % 2 == start_location) then
- robot.turnRight()
- else
- robot.turnLeft()
- end
- end
- --[[
- Harvests a two dimensional area defined by rows and columns. The robot starts
- by moving forward down the first row.
- rows - int: The number of rows to harvest.
- columns - int: The number of columns to harvest.
- start_location - int: 1 for LEFT, 0 for RIGHT.
- return - int: The total number of crops harvested.
- --]]
- local function harvestField(rows, columns, start_location)
- goToStart(rows, columns)
- -- Begin harvesting.
- robot.select(1)
- local harvests = 0
- for i=1,rows do
- harvests = harvests + harvestRow(columns)
- -- Do not turn to the next row on the last row.
- if (i < rows) then
- turnToNextRow(i, start_location)
- end
- end
- goBack(rows, columns)
- return harvests
- end
- --[[
- Drops all carried items into an inventory below the robot.
- return - int: The number of items dropped.
- --]]
- local function dropItems()
- local item_count = 0
- for i=1,16 do
- robot.select(i)
- local stack = ic.getStackInInternalSlot(i)
- if (stack ~= nil) then
- doUntilSuccess(robot.dropDown)
- item_count = item_count + stack.size
- end
- end
- return item_count
- end
- --[[
- Reads config from a file.
- filename - string: The string path/filename.
- return - table|nil: The table defined in config, or nil if the file does not
- exist or another error occurs.
- --]]
- local function loadConfig(filename)
- -- Config file exists.
- local f = io.open(filename, "r")
- if (f == nil) then
- print("No config file " .. filename .. " exists. Please create it before continuing.")
- return nil
- end
- local t = serial.unserialize(f:read())
- f:close()
- return t
- end
- --[[
- Guides the user in creating a new config.
- return - table: The config created.
- --]]
- local function createConfig(filename)
- local config = {}
- print("Does your robot start on the left or right of the field?")
- local input = io.read()
- if (input == "left") then
- config.START_LOCATION_RELATIVE = LEFT
- elseif (input == "right") then
- config.START_LOCATION_RELATIVE = RIGHT
- else
- print("Invalid choice. Should be either left or right.")
- return nil
- end
- print("Enter number of rows.")
- config.ROWS = tonumber(io.read())
- print("Enter number of columns.")
- config.COLS = tonumber(io.read())
- print("How many crops are being harvested?")
- config.crop_definitions = {}
- for i=1,tonumber(io.read()) do
- print("Crop "..i..": What is the block name? (Use geolyzer to analyze it)")
- local name = io.read()
- config.crop_definitions[name] = {}
- print(" What is the growth threshold for harvesting?")
- config.crop_definitions[name].growth_limit = tonumber(io.read())
- print(" What is the item name of this crop?")
- config.crop_definitions[name].item_name = io.read()
- end
- file = io.open(filename, "w")
- file:write(serial.serialize(config))
- file:close()
- return config
- end
- local function main()
- local config = loadConfig(CONFIG_FILE)
- if (config == nil) then
- config = createConfig(CONFIG_FILE)
- end
- crop_definitions = config.crop_definitions
- local harvest_count = harvestField(config.ROWS, config.COLS, config.START_LOCATION_RELATIVE)
- local drop_count = dropItems()
- print(harvest_count..", "..drop_count)
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement