272 lines
5.3 KiB
Lua
272 lines
5.3 KiB
Lua
local turtleUtils = require('libs/turtle-utils')
|
|
|
|
local NB_ROWS = 8
|
|
local DIRECTION = 'left' -- 'left' | 'right'
|
|
local FILL_BLOCK = 'minecraft:cobblestone'
|
|
|
|
local LEVEL_PER_TIER = 12
|
|
|
|
local formatBlockName = function(tierName)
|
|
return "mysticalagriculture:" .. tierName .. "_growth_accelerator"
|
|
end
|
|
|
|
local BLOCKS_PER_TIER = {
|
|
formatBlockName('inferium'),
|
|
formatBlockName('prudentium'),
|
|
formatBlockName('tertium'),
|
|
formatBlockName('imperium'),
|
|
formatBlockName('supremium')
|
|
}
|
|
|
|
local MAX_LEVEL = LEVEL_PER_TIER * #BLOCKS_PER_TIER
|
|
|
|
local countItems = function(itemName)
|
|
local total = 0
|
|
|
|
for i=1,16,1 do
|
|
local details = turtle.getItemDetail(i)
|
|
if details and details.name == itemName then
|
|
total = total + details.count
|
|
end
|
|
end
|
|
|
|
return total
|
|
end
|
|
|
|
local assertEnoughFillBlocks = function()
|
|
local count = countItems(FILL_BLOCK)
|
|
|
|
if count < MAX_LEVEL then
|
|
error('Not enough fill blocks, please provide at least ' .. MAX_LEVEL .. ' of ' .. FILL_BLOCK)
|
|
end
|
|
end
|
|
|
|
local assertEnoughFuel = function()
|
|
local minFuel = 10 + NB_ROWS + (MAX_LEVEL * 2 * NB_ROWS)
|
|
|
|
if turtle.getFuelLevel() < minFuel then
|
|
error('Not enough fuel')
|
|
end
|
|
end
|
|
|
|
local refuel = function()
|
|
for i=1, 16, 1 do
|
|
local count = turtle.getItemCount(i)
|
|
if count > 0 then
|
|
turtle.select(i)
|
|
turtle.refuel()
|
|
end
|
|
end
|
|
end
|
|
|
|
local MOVES = {
|
|
left = function(strictMode)
|
|
turtle.turnLeft()
|
|
local ok, reason = turtle.forward()
|
|
|
|
if strictMode and not ok then
|
|
error('cannot forward because ' .. tostring(reason), 0)
|
|
end
|
|
|
|
turtle.turnRight()
|
|
return ok, reason
|
|
end,
|
|
right = function(strictMode)
|
|
turtle.turnRight()
|
|
local ok, reason = turtle.forward()
|
|
|
|
if strictMode and not ok then
|
|
error('cannot forward because ' .. tostring(reason), 0)
|
|
end
|
|
|
|
turtle.turnLeft()
|
|
return ok, reason
|
|
end,
|
|
}
|
|
|
|
local getTierFromLevel = function(level)
|
|
return math.floor((level - 1) / LEVEL_PER_TIER) + 1
|
|
end
|
|
|
|
local getBlockNameFromLevel = function(level)
|
|
local tier = getTierFromLevel(level)
|
|
return BLOCKS_PER_TIER[tier]
|
|
end
|
|
|
|
local inspectBlockName = function()
|
|
local ok, block = turtle.inspect()
|
|
|
|
if not ok then
|
|
return nil
|
|
end
|
|
|
|
return block and block.name
|
|
end
|
|
|
|
local selectItem = function(itemName)
|
|
for i=1, 16, 1 do
|
|
local details = turtle.getItemDetail(i)
|
|
if details and details.name == itemName then
|
|
turtle.select(i)
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local replaceBlockAt = function(y)
|
|
local blockName = getBlockNameFromLevel(y);
|
|
|
|
if inspectBlockName() == blockName then
|
|
return false
|
|
end
|
|
|
|
local selected = selectItem(blockName)
|
|
|
|
if not selected then
|
|
return 'error'
|
|
end
|
|
|
|
turtle.dig()
|
|
turtle.place()
|
|
return true
|
|
end
|
|
|
|
local placeDownFillBlock = function()
|
|
selectItem(FILL_BLOCK)
|
|
turtle.placeDown()
|
|
end
|
|
|
|
local placeDownItem = function(itemName)
|
|
if selectItem(itemName) then
|
|
turtle.placeDown()
|
|
else
|
|
placeDownFillBlock()
|
|
end
|
|
end
|
|
|
|
-- Main state and stateful methods
|
|
local function getInitialState()
|
|
return {
|
|
firstPickedItem = nil,
|
|
y = 1,
|
|
initialLevel = 0,
|
|
newLevel = 0,
|
|
errorLevel = nil
|
|
}
|
|
end
|
|
|
|
-- local state = getInitialState()
|
|
|
|
local digAndGoDown = function(state)
|
|
turtle.digDown()
|
|
turtle.down()
|
|
state.y = state.y + 1
|
|
end
|
|
|
|
local goUp = function(state)
|
|
turtle.up()
|
|
state.y = state.y - 1
|
|
end
|
|
|
|
local function tryToSelectEmptySlot()
|
|
if not turtleUtils.selectFirstEmptySlot() then
|
|
turtleUtils.compactInventory()
|
|
if not turtleUtils.selectFirstEmptySlot() then
|
|
error('Fatal error: turtle inventory is full', 0)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 1. down procedure
|
|
local downProcedure = function(state)
|
|
while state.y < 60 do
|
|
local replaced = replaceBlockAt(state.y)
|
|
|
|
if replaced == false then
|
|
state.initialLevel = state.y
|
|
state.newLevel = state.initialLevel
|
|
end
|
|
|
|
if replaced == true then
|
|
state.newLevel = state.y
|
|
end
|
|
|
|
if replaced == 'error' then
|
|
state.errorLevel = state.y
|
|
break
|
|
end
|
|
|
|
if not state.firstPickedItem then
|
|
tryToSelectEmptySlot()
|
|
digAndGoDown(state)
|
|
|
|
local item = turtle.getItemDetail(turtle.getSelectedSlot())
|
|
-- consider FILL_BLOCK if no block was picked
|
|
state.firstPickedItem = (item and item.name) or FILL_BLOCK
|
|
else
|
|
digAndGoDown(state)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
-- 2. up procedure
|
|
local upProcedure = function(state)
|
|
local firstY = getInitialState().y
|
|
|
|
while state.y ~= firstY do
|
|
goUp(state)
|
|
|
|
if state.y == firstY and state.firstPickedItem then
|
|
placeDownItem(state.firstPickedItem)
|
|
else
|
|
placeDownFillBlock()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 3. print report
|
|
local printReport = function(state)
|
|
local baseReport = 'Level ' .. tostring(state.initialLevel) .. ' -> ' .. state.newLevel
|
|
|
|
if state.errorLevel then
|
|
print (baseReport .. ' (tier ' .. getTierFromLevel(state.errorLevel) .. ')')
|
|
else
|
|
print (baseReport)
|
|
end
|
|
end
|
|
|
|
local upgradeProcedure = function()
|
|
turtleUtils.compactInventory()
|
|
|
|
local state = getInitialState()
|
|
|
|
downProcedure(state)
|
|
upProcedure(state)
|
|
printReport(state)
|
|
|
|
return state
|
|
end
|
|
|
|
-- Main function
|
|
local main = function()
|
|
assertEnoughFillBlocks()
|
|
refuel()
|
|
assertEnoughFuel()
|
|
|
|
for i=1, NB_ROWS, 1 do
|
|
upgradeProcedure()
|
|
|
|
if i ~= NB_ROWS then
|
|
MOVES[DIRECTION](true)
|
|
else
|
|
MOVES[DIRECTION](false) -- do not throw if cannot move forward
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
main()
|