Updated movescript and added lumber farm.
This commit is contained in:
parent
f9f2be629a
commit
f145f5a17e
|
@ -7,21 +7,76 @@ Last Modified: 27-09-2018
|
|||
Description:
|
||||
This library enables string representation of robot movement, for easier
|
||||
robotic control without repeating functions many times.
|
||||
|
||||
Begin a script with "d_" to tell the robot to attempt to destroy blocks in the
|
||||
way of the path of movement.
|
||||
--]]
|
||||
|
||||
local r = require("robot")
|
||||
|
||||
local movescript = {}
|
||||
|
||||
local destructive = true
|
||||
|
||||
local function doUntilSuccess(f)
|
||||
local success = f()
|
||||
while (not success) do
|
||||
success = f()
|
||||
end
|
||||
end
|
||||
|
||||
local function up()
|
||||
while (destructive and r.detectUp()) do
|
||||
r.swingUp()
|
||||
end
|
||||
doUntilSuccess(r.up)
|
||||
end
|
||||
|
||||
local function down()
|
||||
while (destructive and r.detectDown()) do
|
||||
r.swingDown()
|
||||
end
|
||||
doUntilSuccess(r.down)
|
||||
end
|
||||
|
||||
local function forward()
|
||||
while (destructive and r.detect()) do
|
||||
r.swing()
|
||||
end
|
||||
doUntilSuccess(r.forward)
|
||||
end
|
||||
|
||||
local function back()
|
||||
if (destructive) then
|
||||
r.turnAround()
|
||||
while (r.detect()) do
|
||||
r.swing()
|
||||
end
|
||||
r.turnAround()
|
||||
end
|
||||
doUntilSuccess(r.back)
|
||||
end
|
||||
|
||||
local functionMap = {
|
||||
["U"] = r.up,
|
||||
["D"] = r.down,
|
||||
["U"] = up,
|
||||
["D"] = down,
|
||||
["L"] = r.turnLeft,
|
||||
["R"] = r.turnRight,
|
||||
["F"] = r.forward,
|
||||
["B"] = r.back
|
||||
["F"] = forward,
|
||||
["B"] = back,
|
||||
["P"] = r.place,
|
||||
["S"] = r.swing
|
||||
}
|
||||
|
||||
--[[
|
||||
Determines if a string starts with a certain string.
|
||||
str - string: The string to check the prefix of.
|
||||
start - string: The prefix to look for.
|
||||
--]]
|
||||
local function starts_with(str, start)
|
||||
return str:sub(1, #start) == start
|
||||
end
|
||||
|
||||
--[[
|
||||
Executes a single instruction once.
|
||||
c - character: One uppercase character to translate into movement.
|
||||
|
@ -31,10 +86,7 @@ local function executeChar(c)
|
|||
if (f == nil) then
|
||||
return
|
||||
end
|
||||
local success = f()
|
||||
while (not success) do
|
||||
success = f()
|
||||
end
|
||||
f()
|
||||
end
|
||||
|
||||
--[[
|
||||
|
@ -60,6 +112,12 @@ Executes a given script.
|
|||
script - string: The script to execute.
|
||||
--]]
|
||||
function movescript.execute(script)
|
||||
if (starts_with(script, "d_")) then
|
||||
destructive = true
|
||||
script = string.sub(script, 3)
|
||||
else
|
||||
destructive = false
|
||||
end
|
||||
while (script ~= nil and script ~= "") do
|
||||
-- Matches the next instruction, possibly prefixed by an integer value.
|
||||
local next_instruction = string.match(script, "%d*%u")
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# lumber_farm.lua
|
||||
Automatically chop an array of spruce trees.
|
||||
|
||||
## Pastebin
|
||||
[dB0XwcAY](https://pastebin.com/dB0XwcAY)
|
||||
|
||||
## Module Requirements
|
||||
* tractor_beam
|
||||
* inventory_controller
|
||||
* movescript library [4c2AN8Jw](https://pastebin.com/4c2AN8Jw)
|
||||
* A lumber axe of obscenely high durability, or unbreakable.
|
||||
|
||||
## Instructions
|
||||
First, install *movescript* to `/lib/movescript.lua`.
|
||||
|
||||
Then, download this script, and `edit` the downloaded file to set some constants.
|
||||
|
||||
* `ROWS`: The number of rows in the farm.
|
||||
* `COLS`: The number of columns in the farm.
|
||||
* `TREE_SPACING`: The number of blocks between trees.
|
||||
* `DELAY`: The time, in tens of seconds, to wait between chopping and picking up items.
|
||||
* `move_to_start`: A *movescript* describing how to get from the robot's base station to the first tree.
|
||||
* `return_from_start`: A *movescript* describing how to get back to the robot's base station from the first tree. Should usually be the opposite of `move_to_start`.
|
||||
|
||||
Make sure you have a very powerful lumber axe, or one which is unbreakable, and give it to the robot.
|
||||
|
||||
### Farm Setup
|
||||
The construction of the farm should be as follows:
|
||||
|
||||
```
|
||||
R-1 R-2 R-3
|
||||
| [T] | [T] | [T] | Column 1
|
||||
| [T] | [T] | [T] | Column 2
|
||||
| [T] | [T] | [T] | Column 3
|
||||
| [T] | [T] | [T] | Column 4
|
||||
X
|
||||
```
|
||||
|
||||
Where `[T]` denotes a 2x2 tree, `X` denotes the starting location for the robot.
|
||||
|
||||
Each tree should be separated from those adjacent to it by `TREE_SPACING` blocks.
|
|
@ -0,0 +1,180 @@
|
|||
--[[
|
||||
Author: Andrew Lalis
|
||||
File: TreeFarm.lua
|
||||
Version: 1.0
|
||||
Last Modified: 12-06-2018
|
||||
|
||||
Description:
|
||||
This script lets a robot, equipped with a tractor_beam and inventory controller
|
||||
module, chop trees with a Tinker's Construct lumber axe. It will automatically
|
||||
stop when it runs out of saplings or bonemeal, or when its axe is close to
|
||||
breaking. It also can either chop a certain number of trees, or simply chop
|
||||
until its resources are depleted.
|
||||
--]]
|
||||
|
||||
--Require statements and componenent definitions.
|
||||
local robot = require("robot")
|
||||
local component = require("component")
|
||||
local tractor_beam = component.tractor_beam
|
||||
local ic = component.inventory_controller
|
||||
|
||||
--Runtime Constants defined for this robot.
|
||||
local SAPLING_NAME = "minecraft:sapling"
|
||||
local SAPLING_DATA = 0
|
||||
local BONEMEAL_NAME = "minecraft:dye"
|
||||
local BONEMEAL_DATA = 15
|
||||
|
||||
--Global configuration variables.
|
||||
--Flag for if program should run until out of resources.
|
||||
local continuous = false
|
||||
|
||||
--[[
|
||||
Exits the program.
|
||||
--]]
|
||||
local function quit()
|
||||
print("#--------------------------------#")
|
||||
print("# Tree Chopping Program exited. #")
|
||||
os.exit()
|
||||
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
|
||||
|
||||
--[[
|
||||
Select an item, similar to selectItemByName, but if the item cannot be found,
|
||||
the user will be prompted to add it to the robot's inventory and press enter to
|
||||
continue.
|
||||
item_name - string: The id string for an item.
|
||||
item_data - number: The damage value, or variation of an item. Defaults to zero.
|
||||
return - nil: If set to be continuous, then if the item cannot be found, then
|
||||
the program will exit. If not, it will loop until the item is provided by the
|
||||
user.
|
||||
--]]
|
||||
local function selectSafely(item_name, item_data)
|
||||
local success = selectItemByName(item_name, item_data)
|
||||
if continuous and not success then
|
||||
print("Out of "..item_name..", exiting.")
|
||||
quit()
|
||||
end
|
||||
while not success do
|
||||
print("Cannot find "..item_name.." in inventory. Please add some, and press enter.")
|
||||
io.read()
|
||||
success = selectItemByName(item_name, item_data)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Plants a sapling, and if it can't place one at first, loops until it is
|
||||
possible.
|
||||
--]]
|
||||
local function plantSapling()
|
||||
selectSafely(SAPLING_NAME, SAPLING_DATA)
|
||||
local success = robot.place()
|
||||
while not success do
|
||||
print("Unable to place the sapling. Please remove any blocks in front of the robot, and press enter.")
|
||||
io.read()
|
||||
success = robot.place()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Repeatedly applies bonemeal to the sapling until either the sapling has grown,
|
||||
or the robot runs out of bonemeal.
|
||||
--]]
|
||||
local function applyBonemeal()
|
||||
local success, block_type = robot.detect()
|
||||
while block_type ~= "solid" do
|
||||
selectSafely(BONEMEAL_NAME, BONEMEAL_DATA)
|
||||
robot.place()
|
||||
success, block_type = robot.detect()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Uses the robot's axe to chop a tree, and quits if the lumber axe provided has
|
||||
less than 10% durability.
|
||||
--]]
|
||||
local function chopTree()
|
||||
local durability = robot.durability()
|
||||
if continuous and (durability == nil or durability < 0.1) then
|
||||
print("Inadequate tool to chop trees, exiting.")
|
||||
quit()
|
||||
end
|
||||
while (durability == nil) or (durability < 0.1) do
|
||||
print("Please ensure that a lumber axe with at least 10% durability is equipped in the tool slot, and press enter.")
|
||||
io.read()
|
||||
durability = robot.durability()
|
||||
end
|
||||
robot.swing()
|
||||
end
|
||||
|
||||
--[[
|
||||
Uses the tractor_beam module to repeatedly pick up items until there are no
|
||||
more to pick up.
|
||||
--]]
|
||||
local function pickupItems()
|
||||
local success = tractor_beam.suck()
|
||||
while success do
|
||||
success = tractor_beam.suck()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Grows a tree by planting a sapling and applying bonemeal until it is grown.
|
||||
--]]
|
||||
local function growTree()
|
||||
plantSapling()
|
||||
applyBonemeal()
|
||||
end
|
||||
|
||||
--[[
|
||||
The entire cycle of the farm. Grows a tree, harvests the wood, and picks up
|
||||
the items.
|
||||
--]]
|
||||
local function farmTree()
|
||||
growTree()
|
||||
chopTree()
|
||||
os.sleep(2)
|
||||
pickupItems()
|
||||
end
|
||||
|
||||
--[[
|
||||
Main function in which the iterations of the cycle are performed.
|
||||
--]]
|
||||
local function main()
|
||||
print("# Andrew's Tree Chopping Program #")
|
||||
print("# Copyright 2018 Andrew Lalis #")
|
||||
print("#--------------------------------#")
|
||||
print("Please enter the number of trees to chop, or -1 to chop until out of resources.")
|
||||
local choice = tonumber(io.read())
|
||||
if (choice == nil or choice == -1) then
|
||||
continuous = true
|
||||
print(" Chopping trees until out of resources.")
|
||||
while continuous do
|
||||
farmTree()
|
||||
end
|
||||
else
|
||||
print(" Chopping "..choice.." trees.")
|
||||
for i=1,choice do
|
||||
farmTree()
|
||||
end
|
||||
end
|
||||
quit()
|
||||
end
|
||||
|
||||
main()
|
|
@ -0,0 +1,255 @@
|
|||
--[[
|
||||
Author: Andrew Lalis
|
||||
File: lumber_farm.lua
|
||||
Version: 1.0
|
||||
Last Modified: 30-09-2018
|
||||
|
||||
Description:
|
||||
This script will automate the farming of large spruce trees, and manages an
|
||||
array of 2x2 trees which it will replant and collect the saplings of.
|
||||
|
||||
The robot should be given an 'unbreakable' tool with 5 reinforced upgrades.
|
||||
--]]
|
||||
|
||||
--Require statements and componenent definitions.
|
||||
local robot = require("robot")
|
||||
local component = require("component")
|
||||
local ms = require("movescript")
|
||||
local tractor_beam = component.tractor_beam
|
||||
local ic = component.inventory_controller
|
||||
|
||||
local move_to_start = "5F"
|
||||
local return_from_start = "5B"
|
||||
|
||||
local ROWS = 3
|
||||
local COLS = 2
|
||||
local TREE_SPACING = 3
|
||||
local DELAY = 15
|
||||
|
||||
-- Global counter.
|
||||
local TREES_CHOPPED = 0
|
||||
|
||||
--Runtime Constants defined for this robot.
|
||||
local SAPLING_NAME = "minecraft:sapling"
|
||||
local SAPLING_DATA = 1
|
||||
|
||||
--[[
|
||||
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.
|
||||
min_count - number: The minimum number of items to have.
|
||||
return - boolean: True if at least one slot contains the item. That slot is now
|
||||
selected.
|
||||
--]]
|
||||
local function selectItemByName(item_name, item_data, min_count)
|
||||
for i=1,16 do
|
||||
local stack = ic.getStackInInternalSlot(i)
|
||||
if (stack ~= nil and stack.name == item_name and stack.damage == item_data and stack.size >= min_count) then
|
||||
robot.select(i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--[[
|
||||
Select an item, similar to selectItemByName, but if the item cannot be found,
|
||||
the user will be prompted to add it to the robot's inventory and press enter to
|
||||
continue.
|
||||
item_name - string: The id string for an item.
|
||||
item_data - number: The damage value, or variation of an item. Defaults to zero.
|
||||
min_count - number: The minimum number of items to have.
|
||||
--]]
|
||||
local function selectSafely(item_name, item_data, min_count)
|
||||
local success = selectItemByName(item_name, item_data, min_count)
|
||||
while not success do
|
||||
print("Cannot find "..min_count.."x "..item_name.." in inventory. Please add some, and press enter.")
|
||||
io.read()
|
||||
success = selectItemByName(item_name, item_data, min_count)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Gets the total number of items with the given data.
|
||||
item_name - string: The id string for an item.
|
||||
item_data - number: The damage value, or variation of an item. Defaults to zero.
|
||||
--]]
|
||||
local function getItemCount(item_name, item_data)
|
||||
local count = 0
|
||||
for i=1,16 do
|
||||
local stack = ic.getStackInInternalSlot(i)
|
||||
if (stack ~= nil and stack.name == item_name and stack.damage == item_data) then
|
||||
count = count + stack.size
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
--[[
|
||||
return - bool: True if the tree is grown, false otherwise.
|
||||
--]]
|
||||
local function isTreeGrown()
|
||||
local success, str = robot.detect()
|
||||
return (success and str == "solid")
|
||||
end
|
||||
|
||||
--[[
|
||||
Uses the tractor_beam module to repeatedly pick up items until there are no
|
||||
more to pick up.
|
||||
--]]
|
||||
local function pickupItems()
|
||||
local success = tractor_beam.suck()
|
||||
while success do
|
||||
success = tractor_beam.suck()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Uses the robot's axe to chop a tree, and quits if the lumber axe provided has
|
||||
less than 10% durability.
|
||||
return - integer: 1 if the tree was chopped, 0 otherwise.
|
||||
--]]
|
||||
local function chopTree()
|
||||
if (isTreeGrown()) then
|
||||
local durability = robot.durability()
|
||||
while (durability == nil) or (durability < 0.1) do
|
||||
print("Please ensure that a lumber axe with at least 10% durability is equipped in the tool slot, and press enter.")
|
||||
io.read()
|
||||
durability = robot.durability()
|
||||
end
|
||||
ms.execute("SF")
|
||||
os.sleep(1)
|
||||
pickupItems()
|
||||
ms.execute("B")
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
--[[
|
||||
Plants a sapling, and if it can't place one at first, loops until it is
|
||||
possible. Assumes the robot is at the starting position:
|
||||
OO
|
||||
OO
|
||||
R
|
||||
Where O=dirt, R=robot.
|
||||
--]]
|
||||
local function plantTree()
|
||||
--Pick up any remaining items.
|
||||
pickupItems()
|
||||
local success, str = robot.detect()
|
||||
if (success and (str == "passable" or str == "solid" or str == "replaceable")) then
|
||||
return
|
||||
end
|
||||
selectSafely(SAPLING_NAME, SAPLING_DATA, 1)
|
||||
ms.execute("2FRP")
|
||||
selectSafely(SAPLING_NAME, SAPLING_DATA, 1)
|
||||
ms.execute("LBP")
|
||||
selectSafely(SAPLING_NAME, SAPLING_DATA, 1)
|
||||
ms.execute("RP")
|
||||
selectSafely(SAPLING_NAME, SAPLING_DATA, 1)
|
||||
ms.execute("LBP")
|
||||
end
|
||||
|
||||
--[[
|
||||
Moves to the next tree in a row.
|
||||
current_col - integer: The current column.
|
||||
col_count - integer: The total number of columns.
|
||||
--]]
|
||||
local function moveToNextTree(current_col, col_count)
|
||||
if (current_col < col_count) then
|
||||
ms.execute("d_LFR3FRFL"..(TREE_SPACING - 1).."F")
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Moves to the next row.
|
||||
current_row - integer: The row that was just finished.
|
||||
row_count - integer: The total number of rows.
|
||||
col_count - integer: The total number of columns.
|
||||
--]]
|
||||
local function moveToNextRow(current_row, row_count, col_count)
|
||||
local script = "d_LFL"..((TREE_SPACING + 2) * (col_count - 1)).."FLF"
|
||||
if (current_row < row_count) then
|
||||
script = script..(TREE_SPACING + 2).."FL"
|
||||
else
|
||||
script = script.."L"
|
||||
end
|
||||
ms.execute(script)
|
||||
end
|
||||
|
||||
--[[
|
||||
Moves back to the start of the orchard.
|
||||
row_count - integer: The total number of rows.
|
||||
--]]
|
||||
local function moveToOrchardStart(row_count)
|
||||
ms.execute("d_L"..((TREE_SPACING + 2) * (row_count - 1)).."FR")
|
||||
end
|
||||
|
||||
--[[
|
||||
Performs a function at each tree in the orchard.
|
||||
rows - integer: The total number of rows.
|
||||
cols - integer: The total number of columns.
|
||||
func - function: The function to execute at each position.
|
||||
--]]
|
||||
local function doForEachTree(rows, cols, func)
|
||||
ms.execute(move_to_start)
|
||||
for i=1,rows do
|
||||
for k=1,cols do
|
||||
func()
|
||||
moveToNextTree(k, cols)
|
||||
end
|
||||
moveToNextRow(i, rows, cols)
|
||||
end
|
||||
moveToOrchardStart(rows)
|
||||
ms.execute(return_from_start)
|
||||
end
|
||||
|
||||
--[[
|
||||
Chops an array of trees. The robot starts facing the first row.
|
||||
--]]
|
||||
local function chopOrchard(rows, cols)
|
||||
doForEachTree(rows, cols, chopTree)
|
||||
end
|
||||
|
||||
--[[
|
||||
Collects items from an array of trees.
|
||||
--]]
|
||||
local function collectItems(rows, cols)
|
||||
doForEachTree(rows, cols, pickupItems)
|
||||
end
|
||||
|
||||
--[[
|
||||
Plants saplings for the array of trees.
|
||||
--]]
|
||||
local function plantSaplings(rows, cols)
|
||||
local saplings_needed = TREES_CHOPPED * 4
|
||||
if (getItemCount(SAPLING_NAME, SAPLING_DATA) < saplings_needed) then
|
||||
print("Not enough saplings. Needed: "..saplings_needed..". Add some and press ENTER.")
|
||||
io.read()
|
||||
end
|
||||
doForEachTree(rows, cols, plantTree)
|
||||
TREES_CHOPPED = 0
|
||||
end
|
||||
|
||||
--[[
|
||||
Deposits all items into a chest below the robot.
|
||||
--]]
|
||||
local function depositItems()
|
||||
for i=1,16 do
|
||||
robot.select(i)
|
||||
robot.dropDown()
|
||||
end
|
||||
robot.select(1)
|
||||
end
|
||||
|
||||
chopOrchard(ROWS, COLS)
|
||||
depositItems()
|
||||
print("Orchard chopped. Waiting 2.5 min before collecting saplings...")
|
||||
for i=1,(DELAY) do
|
||||
os.sleep(10)
|
||||
print(i*10)
|
||||
end
|
||||
collectItems(ROWS, COLS)
|
||||
plantSaplings(ROWS, COLS)
|
||||
depositItems()
|
Loading…
Reference in New Issue