Reformat
This commit is contained in:
9
.luarc.json
Normal file
9
.luarc.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"diagnostics.globals": [
|
||||||
|
"printError",
|
||||||
|
"turtle",
|
||||||
|
"shell",
|
||||||
|
"peripheral",
|
||||||
|
"parallel"
|
||||||
|
]
|
||||||
|
}
|
||||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"Lua.diagnostics.globals": [
|
"Lua.diagnostics.globals": [
|
||||||
"printError",
|
"printError",
|
||||||
"turtle",
|
"turtle",
|
||||||
"shell",
|
"shell",
|
||||||
"peripheral",
|
"peripheral",
|
||||||
"parallel"
|
"parallel"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,96 +1,87 @@
|
|||||||
local dfpwm = require("cc.audio.dfpwm")
|
local dfpwm = require("cc.audio.dfpwm")
|
||||||
local Direction = require("lib.direction")
|
|
||||||
|
---@alias AudioControllerConfig {buffer_length_seconds: number}
|
||||||
---@alias AudioControllerConfig {buffer_length_seconds: number}
|
|
||||||
|
---@class AudioController
|
||||||
---@class AudioController
|
---@field config AudioControllerConfig
|
||||||
---@field config AudioControllerConfig
|
---@field play boolean
|
||||||
---@field play boolean
|
local AudioController = {}
|
||||||
local AudioController = {}
|
AudioController.__index = AudioController
|
||||||
AudioController.__index = AudioController
|
|
||||||
|
---@return AudioController
|
||||||
|
function AudioController:Create()
|
||||||
---@return AudioController
|
local t = {}
|
||||||
function AudioController:Create()
|
setmetatable(t, AudioController)
|
||||||
local t = {}
|
|
||||||
setmetatable(t, AudioController)
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fields
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
-----------------------------------------------------------------------------------------------
|
t.config = {
|
||||||
-- Fields
|
buffer_length_seconds = 1,
|
||||||
-----------------------------------------------------------------------------------------------
|
}
|
||||||
t.config = {
|
t.play = false
|
||||||
buffer_length_seconds = 1
|
|
||||||
}
|
return t
|
||||||
t.play = false
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
return t
|
-- Audio Methods
|
||||||
end
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function AudioController:PlayAudio(filename)
|
||||||
-----------------------------------------------------------------------------------------------
|
self.play = true
|
||||||
-- Audio Methods
|
|
||||||
-----------------------------------------------------------------------------------------------
|
local decoder = dfpwm.make_decoder()
|
||||||
|
while self.play do
|
||||||
|
for chunk in io.lines(("audio/%s.dfpwm"):format(filename), self.config.buffer_length_seconds * 1024) do
|
||||||
function AudioController:PlayAudio(filename)
|
if not self.play then
|
||||||
self.play = true
|
break
|
||||||
|
end
|
||||||
local decoder = dfpwm.make_decoder()
|
|
||||||
while self.play do
|
local buffer = decoder(chunk)
|
||||||
for chunk in io.lines(("audio/%s.dfpwm"):format(filename), self.config.buffer_length_seconds * 1024) do
|
|
||||||
if not self.play then
|
while not self:GetSpeaker().playAudio(buffer) do
|
||||||
break
|
if not self.play then
|
||||||
end
|
break
|
||||||
|
end
|
||||||
local buffer = decoder(chunk)
|
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
while not self:GetSpeaker().playAudio(buffer) do
|
os.pullEvent("speaker_audio_empty")
|
||||||
---@diagnostic disable-next-line: undefined-field
|
end
|
||||||
os.pullEvent("speaker_audio_empty")
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
function AudioController:PlayAudioFactory(filename)
|
||||||
|
local function play()
|
||||||
|
self:PlayAudio(filename)
|
||||||
function AudioController:PlayAudioFactory(filename)
|
end
|
||||||
local function play()
|
|
||||||
self:PlayAudio(filename)
|
return play
|
||||||
end
|
end
|
||||||
|
|
||||||
return play
|
-----------------------------------------------------------------------------------------------
|
||||||
end
|
-- Management Methods
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
---@return table | nil
|
||||||
-- Management Methods
|
function AudioController:GetSpeaker()
|
||||||
-----------------------------------------------------------------------------------------------
|
return peripheral.find("speaker")
|
||||||
|
end
|
||||||
|
|
||||||
---@return table | nil
|
function AudioController:StopPlaying()
|
||||||
function AudioController:GetSpeaker()
|
self.play = false
|
||||||
return peripheral.find("speaker")
|
self:GetSpeaker().stop()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
function AudioController:StopPlaying()
|
-- Main Method
|
||||||
self.play = false
|
-----------------------------------------------------------------------------------------------
|
||||||
self:GetSpeaker().stop()
|
|
||||||
end
|
function AudioController:Run()
|
||||||
|
-- self:Configure()
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
self:PlayAudio("bangarang")
|
||||||
-- Main Method
|
end
|
||||||
-----------------------------------------------------------------------------------------------
|
|
||||||
|
return AudioController
|
||||||
|
|
||||||
function AudioController:Run()
|
|
||||||
-- self:Configure()
|
|
||||||
|
|
||||||
self:PlayAudio("bangarang")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return AudioController
|
|
||||||
|
|||||||
@ -11,322 +11,320 @@ local AudioController = require("controller.audio_controller")
|
|||||||
local ExcavationController = {}
|
local ExcavationController = {}
|
||||||
ExcavationController.__index = ExcavationController
|
ExcavationController.__index = ExcavationController
|
||||||
|
|
||||||
|
|
||||||
---@return ExcavationController
|
---@return ExcavationController
|
||||||
function ExcavationController:Create()
|
function ExcavationController:Create()
|
||||||
local t = {}
|
local t = {}
|
||||||
setmetatable(t, ExcavationController)
|
setmetatable(t, ExcavationController)
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fields
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
t.controller = TurtleController:Create()
|
||||||
-- Fields
|
t.audio = AudioController:Create()
|
||||||
-----------------------------------------------------------------------------------------------
|
t.config = {
|
||||||
|
slice_length = 0,
|
||||||
|
slice_height = 0,
|
||||||
|
center_slice_width = 0,
|
||||||
|
slice_width = 0,
|
||||||
|
slice_padding = 0,
|
||||||
|
slices_left = 0,
|
||||||
|
slices_right = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
t.controller = TurtleController:Create()
|
|
||||||
t.audio = AudioController:Create()
|
|
||||||
t.config = {
|
|
||||||
slice_length = 0,
|
|
||||||
slice_height = 0,
|
|
||||||
center_slice_width = 0,
|
|
||||||
slice_width = 0,
|
|
||||||
slice_padding = 0,
|
|
||||||
slices_left = 0,
|
|
||||||
slices_right = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
-- Behavior Methods
|
-- Behavior Methods
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
---Excavates a single 1x1/1x2 tunnel of configured length.
|
---Excavates a single 1x1/1x2 tunnel of configured length.
|
||||||
---Will leave the turtle wherever it ends up.
|
---Will leave the turtle wherever it ends up.
|
||||||
---Only unstocks/refuels if required.
|
---Only unstocks/refuels if required.
|
||||||
---@param mine_above boolean
|
---@param mine_above boolean
|
||||||
---@param mine_below boolean
|
---@param mine_below boolean
|
||||||
function ExcavationController:Excavate_1x1or2or3xL(mine_above, mine_below)
|
function ExcavationController:Excavate_1x1or2or3xL(mine_above, mine_below)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
if mine_above then
|
if mine_above then
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
end
|
end
|
||||||
if mine_below then
|
if mine_below then
|
||||||
self.controller:EnableMiningBelow()
|
self.controller:EnableMiningBelow()
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:MoveForward(self.config.slice_length)
|
self.controller:MoveForward(self.config.slice_length)
|
||||||
|
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:DisableMiningBelow()
|
self.controller:DisableMiningBelow()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---Excavates a single 1xH partial slice of configured length.
|
---Excavates a single 1xH partial slice of configured length.
|
||||||
---Will leave the turtle in its starting position.
|
---Will leave the turtle in its starting position.
|
||||||
---Only unstocks/refuels if required.
|
---Only unstocks/refuels if required.
|
||||||
function ExcavationController:Excavate_1xHxL()
|
function ExcavationController:Excavate_1xHxL()
|
||||||
self.controller:StorePosition()
|
self.controller:StorePosition()
|
||||||
|
|
||||||
-- We can mine 2 blocks heigh in a single go
|
-- We can mine 2 blocks heigh in a single go
|
||||||
local number_of_1x3xL = math.floor(self.config.slice_height / 3)
|
local number_of_1x3xL = math.floor(self.config.slice_height / 3)
|
||||||
|
|
||||||
-- Prepare for mining the blocks below the turtle
|
-- Prepare for mining the blocks below the turtle
|
||||||
if number_of_1x3xL > 0 then
|
if number_of_1x3xL > 0 then
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveVertical(1)
|
self.controller:MoveVertical(1)
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mine 1x3xL
|
-- Mine 1x3xL
|
||||||
for i = 1,number_of_1x3xL do
|
for i = 1, number_of_1x3xL do
|
||||||
self:Excavate_1x1or2or3xL(true, true)
|
self:Excavate_1x1or2or3xL(true, true)
|
||||||
|
|
||||||
self.controller:TurnRelative(2)
|
self.controller:TurnRelative(2)
|
||||||
|
|
||||||
-- Don't move upwards in the last iteration so we can decide
|
-- Don't move upwards in the last iteration so we can decide
|
||||||
-- how much to move depending on how much we still have to excavate
|
-- how much to move depending on how much we still have to excavate
|
||||||
if i == number_of_1x3xL then
|
if i == number_of_1x3xL then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveVertical(4)
|
self.controller:MoveVertical(4)
|
||||||
self.controller:MoveVertical(-1)
|
self.controller:MoveVertical(-1)
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mine remaining 1x2xL or 1x1xL
|
-- Mine remaining 1x2xL or 1x1xL
|
||||||
if self.config.slice_height % 3 == 2 then
|
if self.config.slice_height % 3 == 2 then
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveVertical(3)
|
self.controller:MoveVertical(3)
|
||||||
self.controller:MoveVertical(-1)
|
self.controller:MoveVertical(-1)
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
|
|
||||||
self:Excavate_1x1or2or3xL(true, false)
|
self:Excavate_1x1or2or3xL(true, false)
|
||||||
elseif self.config.slice_height % 3 == 1 then
|
elseif self.config.slice_height % 3 == 1 then
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveVertical(3)
|
self.controller:MoveVertical(3)
|
||||||
self.controller:MoveVertical(-1)
|
self.controller:MoveVertical(-1)
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
|
|
||||||
self:Excavate_1x1or2or3xL(false, false)
|
self:Excavate_1x1or2or3xL(false, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:EnableMiningBelow()
|
self.controller:EnableMiningBelow()
|
||||||
self.controller:MoveBack()
|
self.controller:MoveBack()
|
||||||
self.controller:DisableMiningBelow()
|
self.controller:DisableMiningBelow()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---Excavates a single WxH slice of configured length (EAST to WEST).
|
---Excavates a single WxH slice of configured length (EAST to WEST).
|
||||||
---Will leave the turtle in its starting position.
|
---Will leave the turtle in its starting position.
|
||||||
---Only unstocks/refuels if required.
|
---Only unstocks/refuels if required.
|
||||||
---@param center_slice boolean | nil
|
---@param center_slice boolean | nil
|
||||||
function ExcavationController:Excavate_WxHxL(center_slice)
|
function ExcavationController:Excavate_WxHxL(center_slice)
|
||||||
self.controller:StorePosition()
|
self.controller:StorePosition()
|
||||||
|
|
||||||
center_slice = center_slice or false
|
center_slice = center_slice or false
|
||||||
local width = center_slice and self.config.center_slice_width or self.config.slice_width
|
local width = center_slice and self.config.center_slice_width or self.config.slice_width
|
||||||
|
|
||||||
for i = 1,width do
|
for i = 1, width do
|
||||||
self:Excavate_1xHxL()
|
self:Excavate_1xHxL()
|
||||||
|
|
||||||
if i == width then
|
if i == width then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:TurnToDirection(Direction.WEST)
|
self.controller:TurnToDirection(Direction.WEST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(1)
|
self.controller:MoveForward(1)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:MoveBack()
|
self.controller:MoveBack()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---Excavates all slices.
|
---Excavates all slices.
|
||||||
---Will leave the turtle refueled and unstocked in its 0x0x0 position.
|
---Will leave the turtle refueled and unstocked in its 0x0x0 position.
|
||||||
function ExcavationController:Excavate()
|
function ExcavationController:Excavate()
|
||||||
-- Enter excavation area
|
-- Enter excavation area
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(1)
|
self.controller:MoveForward(1)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
|
|
||||||
-- Excavate center slice (start from right/back/bottom)
|
-- Excavate center slice (start from right/back/bottom)
|
||||||
-- Uneven center widths will be centered, even center widths will have a block more on the right
|
-- Uneven center widths will be centered, even center widths will have a block more on the right
|
||||||
print("Excavating center slice...")
|
print("Excavating center slice...")
|
||||||
local center_width_right = math.floor(self.config.center_slice_width / 2)
|
local center_width_right = math.floor(self.config.center_slice_width / 2)
|
||||||
self.controller:StorePosition()
|
self.controller:StorePosition()
|
||||||
self.controller:TurnToDirection(Direction.EAST)
|
self.controller:TurnToDirection(Direction.EAST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(center_width_right)
|
self.controller:MoveForward(center_width_right)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
self:Excavate_WxHxL(true)
|
self:Excavate_WxHxL(true)
|
||||||
self.controller:MoveBack() -- (0, 0, 1)
|
self.controller:MoveBack() -- (0, 0, 1)
|
||||||
|
|
||||||
if self.config.slices_right > 0 then
|
if self.config.slices_right > 0 then
|
||||||
-- Move to right slices starting location
|
-- Move to right slices starting location
|
||||||
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
||||||
self.controller:StorePosition()
|
self.controller:StorePosition()
|
||||||
self.controller:TurnToDirection(Direction.EAST)
|
self.controller:TurnToDirection(Direction.EAST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(center_width_right + padded_width_right)
|
self.controller:MoveForward(center_width_right + padded_width_right)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
|
|
||||||
-- Excavate right slices
|
-- Excavate right slices
|
||||||
print("Excavating right slices")
|
print("Excavating right slices")
|
||||||
for i = 1,self.config.slices_right do
|
for i = 1, self.config.slices_right do
|
||||||
self:Excavate_WxHxL()
|
self:Excavate_WxHxL()
|
||||||
|
|
||||||
if i == self.config.slices_right then
|
if i == self.config.slices_right then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Move to the next slice
|
-- Move to the next slice
|
||||||
self.controller:TurnToDirection(Direction.WEST)
|
self.controller:TurnToDirection(Direction.WEST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(self.config.slice_width + self.config.slice_padding)
|
self.controller:MoveForward(self.config.slice_width + self.config.slice_padding)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
end
|
end
|
||||||
self.controller:MoveBack() -- (0, 0, 1)
|
self.controller:MoveBack() -- (0, 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.config.slices_left > 0 then
|
if self.config.slices_left > 0 then
|
||||||
-- Move to left slices starting location
|
-- Move to left slices starting location
|
||||||
local center_width_left = self.config.center_slice_width - center_width_right
|
local center_width_left = self.config.center_slice_width - center_width_right
|
||||||
self.controller:StorePosition()
|
self.controller:StorePosition()
|
||||||
self.controller:TurnToDirection(Direction.WEST)
|
self.controller:TurnToDirection(Direction.WEST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(center_width_left)
|
self.controller:MoveForward(center_width_left)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
|
|
||||||
-- Excavate left slices
|
-- Excavate left slices
|
||||||
print("Excavate left slices")
|
print("Excavate left slices")
|
||||||
for i = 1,self.config.slices_left do
|
for i = 1, self.config.slices_left do
|
||||||
-- Move to the next slice
|
-- Move to the next slice
|
||||||
self.controller:TurnToDirection(Direction.WEST)
|
self.controller:TurnToDirection(Direction.WEST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(self.config.slice_padding)
|
self.controller:MoveForward(self.config.slice_padding)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
|
|
||||||
self:Excavate_WxHxL()
|
self:Excavate_WxHxL()
|
||||||
|
|
||||||
if i == self.config.slices_left then
|
if i == self.config.slices_left then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
self.controller:TurnToDirection(Direction.WEST)
|
self.controller:TurnToDirection(Direction.WEST)
|
||||||
self.controller:EnableMiningForward()
|
self.controller:EnableMiningForward()
|
||||||
self.controller:EnableMiningAbove()
|
self.controller:EnableMiningAbove()
|
||||||
self.controller:MoveForward(self.config.slice_width)
|
self.controller:MoveForward(self.config.slice_width)
|
||||||
self.controller:DisableMiningForward()
|
self.controller:DisableMiningForward()
|
||||||
self.controller:DisableMiningAbove()
|
self.controller:DisableMiningAbove()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
end
|
end
|
||||||
self.controller:MoveBack() -- (0, 0, 1)
|
self.controller:MoveBack() -- (0, 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Finish up
|
-- Finish up
|
||||||
self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction)
|
self.controller:MoveToPosition(0, 0, 0, self.controller.config.storage_direction)
|
||||||
self.controller:DropInventory()
|
self.controller:DropInventory()
|
||||||
self.controller:TurnToDirection(Direction.NORTH)
|
self.controller:TurnToDirection(Direction.NORTH)
|
||||||
self.audio:StopPlaying()
|
self.audio:StopPlaying()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
-- Management Methods
|
-- Management Methods
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
function ExcavationController:Configure()
|
function ExcavationController:Configure()
|
||||||
local config_complete = false
|
local config_complete = false
|
||||||
|
|
||||||
while not config_complete do
|
while not config_complete do
|
||||||
print("How long should each slice be?")
|
print("How long should each slice be?")
|
||||||
self.config.slice_length = tonumber(io.read()) or 3
|
self.config.slice_length = tonumber(io.read()) or 3
|
||||||
|
|
||||||
print("How high should each slice be?")
|
print("How high should each slice be?")
|
||||||
self.config.slice_height = tonumber(io.read()) or 3
|
self.config.slice_height = tonumber(io.read()) or 3
|
||||||
|
|
||||||
print("How wide should the center slice be?")
|
print("How wide should the center slice be?")
|
||||||
self.config.center_slice_width = tonumber(io.read()) or 1
|
self.config.center_slice_width = tonumber(io.read()) or 1
|
||||||
|
|
||||||
print("How wide should the other slices be?")
|
print("How wide should the other slices be?")
|
||||||
self.config.slice_width = tonumber(io.read()) or 1
|
self.config.slice_width = tonumber(io.read()) or 1
|
||||||
|
|
||||||
print("How many blocks should remain between each slice?")
|
print("How many blocks should remain between each slice?")
|
||||||
self.config.slice_padding = tonumber(io.read()) or 0
|
self.config.slice_padding = tonumber(io.read()) or 0
|
||||||
|
|
||||||
print("How many slices should the turtle mine to its right?")
|
print("How many slices should the turtle mine to its right?")
|
||||||
self.config.slices_right = tonumber(io.read()) or 1
|
self.config.slices_right = tonumber(io.read()) or 1
|
||||||
|
|
||||||
print("How many slices should the turtle mine to its left?")
|
print("How many slices should the turtle mine to its left?")
|
||||||
self.config.slices_left = tonumber(io.read()) or 1
|
self.config.slices_left = tonumber(io.read()) or 1
|
||||||
|
|
||||||
local padded_width_left = self.config.slices_left * (self.config.slice_width + self.config.slice_padding)
|
local padded_width_left = self.config.slices_left * (self.config.slice_width + self.config.slice_padding)
|
||||||
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
local padded_width_right = self.config.slices_right * (self.config.slice_width + self.config.slice_padding)
|
||||||
local padded_width = padded_width_left + padded_width_right + self.config.center_slice_width
|
local padded_width = padded_width_left + padded_width_right + self.config.center_slice_width
|
||||||
local mined_width_left = self.config.slices_left * self.config.slice_width
|
local mined_width_left = self.config.slices_left * self.config.slice_width
|
||||||
local mined_width_right = self.config.slices_right * self.config.slice_width
|
local mined_width_right = self.config.slices_right * self.config.slice_width
|
||||||
local mined_width = mined_width_left + mined_width_right + self.config.center_slice_width
|
local mined_width = mined_width_left + mined_width_right + self.config.center_slice_width
|
||||||
|
|
||||||
print("Configuration complete!")
|
print("Configuration complete!")
|
||||||
print(("Mining area spans %d x %d x %d (width x height x forward), totalling %d blocks."):format(
|
print(
|
||||||
padded_width, self.config.slice_height, self.config.slice_length, padded_width * self.config.slice_height * self.config.slice_length
|
("Mining area spans %d x %d x %d (width x height x forward), totalling %d blocks."):format(
|
||||||
))
|
padded_width,
|
||||||
print(("Turtle will mine %d block wide slices (%d wide in the center) with %d blocks of padding, totalling %d mined blocks."):format(
|
self.config.slice_height,
|
||||||
self.config.slice_width, self.config.center_slice_width, self.config.slice_padding, mined_width * self.config.slice_height * self.config.slice_length
|
self.config.slice_length,
|
||||||
))
|
padded_width * self.config.slice_height * self.config.slice_length
|
||||||
print("Do you want to accept the configuration (enter 1, otherwise 0)?")
|
)
|
||||||
config_complete = tonumber(io.read()) == 1
|
)
|
||||||
end
|
print(
|
||||||
|
("Turtle will mine %d block wide slices (%d wide in the center) with %d blocks of padding, totalling %d mined blocks."):format(
|
||||||
|
self.config.slice_width,
|
||||||
|
self.config.center_slice_width,
|
||||||
|
self.config.slice_padding,
|
||||||
|
mined_width * self.config.slice_height * self.config.slice_length
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print("Do you want to accept the configuration (enter 1, otherwise 0)?")
|
||||||
|
config_complete = tonumber(io.read()) == 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
-- Main Method
|
-- Main Method
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
function ExcavationController:Run()
|
function ExcavationController:Run()
|
||||||
self.controller:Configure()
|
self.controller:Configure()
|
||||||
self:Configure()
|
self:Configure()
|
||||||
|
|
||||||
-- Consume our starting fuel and refuel to the full amount
|
-- Consume our starting fuel and refuel to the full amount
|
||||||
turtle.select(1)
|
turtle.select(1)
|
||||||
turtle.refuel()
|
turtle.refuel()
|
||||||
self.controller:RefuelIfEmpty()
|
self.controller:RefuelIfEmpty()
|
||||||
|
|
||||||
parallel.waitForAll(function() self:Excavate() end, self.audio:PlayAudioFactory("bangarang"))
|
parallel.waitForAll(function()
|
||||||
|
self:Excavate()
|
||||||
|
end, self.audio:PlayAudioFactory("bangarang"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return ExcavationController
|
||||||
return ExcavationController
|
|
||||||
|
|||||||
@ -1,211 +1,220 @@
|
|||||||
local Direction = require("lib.direction")
|
local Direction = require("lib.direction")
|
||||||
local TurtleController = require("controller.turtle_controller")
|
local TurtleController = require("controller.turtle_controller")
|
||||||
|
|
||||||
---@class TestingController
|
---@class TestingController
|
||||||
---@field controller TurtleController
|
---@field controller TurtleController
|
||||||
local TestingController = {}
|
local TestingController = {}
|
||||||
TestingController.__index = TestingController
|
TestingController.__index = TestingController
|
||||||
|
|
||||||
|
---@return TestingController
|
||||||
---@return TestingController
|
function TestingController:Create()
|
||||||
function TestingController:Create()
|
local t = {}
|
||||||
local t = {}
|
setmetatable(t, TestingController)
|
||||||
setmetatable(t, TestingController)
|
|
||||||
|
t.controller = TurtleController:Create()
|
||||||
t.controller = TurtleController:Create()
|
|
||||||
|
return t
|
||||||
return t
|
end
|
||||||
end
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Behavior Methods
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
-- Behavior Methods
|
|
||||||
-----------------------------------------------------------------------------------------------
|
function TestingController:TestRelativeMovementWithRelativeRotation()
|
||||||
|
print("Testing relative movement with relative rotation...")
|
||||||
|
|
||||||
function TestingController:TestRelativeMovementWithRelativeRotation()
|
-- N: BackCenter (Center)
|
||||||
print("Testing relative movement with relative rotation...")
|
self.controller:MoveForward(3)
|
||||||
|
self.controller:TurnRelative(1) -- E: FrontCenter (Center)
|
||||||
-- N: BackCenter (Center)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnRelative(2) -- W: FrontRight (Center)
|
||||||
self.controller:TurnRelative(1) -- E: FrontCenter (Center)
|
self.controller:MoveVertical(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnRelative(8) -- W: FrontRight (Top)
|
||||||
self.controller:TurnRelative(2) -- W: FrontRight (Center)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveVertical(3)
|
self.controller:TurnRelative(3) -- S: FrontCenter (Top)
|
||||||
self.controller:TurnRelative(8) -- W: FrontRight (Top)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnRelative(9) -- W: BackCenter (Top)
|
||||||
self.controller:TurnRelative(3) -- S: FrontCenter (Top)
|
self.controller:MoveVertical(-3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnRelative(1) -- N: BackCenter (Center)
|
||||||
self.controller:TurnRelative(9) -- W: BackCenter (Top)
|
|
||||||
self.controller:MoveVertical(-3)
|
print("The turtle should be in its original location.")
|
||||||
self.controller:TurnRelative(1) -- N: BackCenter (Center)
|
print(
|
||||||
|
("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
||||||
print("The turtle should be in its original location.")
|
self.controller.position.x,
|
||||||
print(("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
self.controller.position.y,
|
||||||
self.controller.position.x, self.controller.position.y, self.controller.position.z, self.controller.position.dir
|
self.controller.position.z,
|
||||||
))
|
self.controller.position.dir
|
||||||
print("Press Enter to continue")
|
)
|
||||||
_ = io.read()
|
)
|
||||||
end
|
print("Press Enter to continue")
|
||||||
|
_ = io.read()
|
||||||
|
end
|
||||||
function TestingController:TestRelativeMovementWithAbsoluteRotation()
|
|
||||||
print("Testing relative movement with absolute rotation...")
|
function TestingController:TestRelativeMovementWithAbsoluteRotation()
|
||||||
|
print("Testing relative movement with absolute rotation...")
|
||||||
-- N: BackCenter (Center)
|
|
||||||
self.controller:MoveForward(3)
|
-- N: BackCenter (Center)
|
||||||
self.controller:TurnToDirection(Direction.EAST) -- E: FrontCenter (Center)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnToDirection(Direction.EAST) -- E: FrontCenter (Center)
|
||||||
self.controller:TurnToDirection(Direction.WEST) -- W: FrontRight (Center)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveVertical(3)
|
self.controller:TurnToDirection(Direction.WEST) -- W: FrontRight (Center)
|
||||||
self.controller:TurnToDirection(Direction.WEST) -- W: FrontRight (Top)
|
self.controller:MoveVertical(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnToDirection(Direction.WEST) -- W: FrontRight (Top)
|
||||||
self.controller:TurnToDirection(Direction.SOUTH) -- S: FrontCenter (Top)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveForward(3)
|
self.controller:TurnToDirection(Direction.SOUTH) -- S: FrontCenter (Top)
|
||||||
self.controller:TurnToDirection(Direction.WEST) -- W: BackCenter (Top)
|
self.controller:MoveForward(3)
|
||||||
self.controller:MoveVertical(-3)
|
self.controller:TurnToDirection(Direction.WEST) -- W: BackCenter (Top)
|
||||||
self.controller:TurnToDirection(Direction.NORTH) -- N: BackCenter (Center)
|
self.controller:MoveVertical(-3)
|
||||||
|
self.controller:TurnToDirection(Direction.NORTH) -- N: BackCenter (Center)
|
||||||
print("The turtle should be in its original location.")
|
|
||||||
print(("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
print("The turtle should be in its original location.")
|
||||||
self.controller.position.x, self.controller.position.y, self.controller.position.z, self.controller.position.dir
|
print(
|
||||||
))
|
("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
||||||
print("Press Enter to continue")
|
self.controller.position.x,
|
||||||
_ = io.read()
|
self.controller.position.y,
|
||||||
end
|
self.controller.position.z,
|
||||||
|
self.controller.position.dir
|
||||||
|
)
|
||||||
function TestingController:TestAbsoluteMovementWithoutStack()
|
)
|
||||||
print("Testing absolute movement without stack...")
|
print("Press Enter to continue")
|
||||||
|
_ = io.read()
|
||||||
-- N: BackCenter (Center)
|
end
|
||||||
self.controller:MoveToPosition(0, 0, 3, Direction.EAST) -- E: FrontCenter (Center)
|
|
||||||
self.controller:MoveToPosition(3, 0, 3, Direction.WEST) -- W: FrontRight (Center)
|
function TestingController:TestAbsoluteMovementWithoutStack()
|
||||||
self.controller:MoveToPosition(3, 3, 3, Direction.WEST) -- W: FrontRight (Top)
|
print("Testing absolute movement without stack...")
|
||||||
self.controller:MoveToPosition(0, 3, 3, Direction.SOUTH) -- S: FrontCenter (Top)
|
|
||||||
self.controller:MoveToPosition(0, 3, 0, Direction.WEST) -- W: BackCenter (Top)
|
-- N: BackCenter (Center)
|
||||||
self.controller:MoveToPosition(0, 0, 0, Direction.NORTH) -- N: BackCenter (Center)
|
self.controller:MoveToPosition(0, 0, 3, Direction.EAST) -- E: FrontCenter (Center)
|
||||||
|
self.controller:MoveToPosition(3, 0, 3, Direction.WEST) -- W: FrontRight (Center)
|
||||||
print("The turtle should be in its original location.")
|
self.controller:MoveToPosition(3, 3, 3, Direction.WEST) -- W: FrontRight (Top)
|
||||||
print(("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
self.controller:MoveToPosition(0, 3, 3, Direction.SOUTH) -- S: FrontCenter (Top)
|
||||||
self.controller.position.x, self.controller.position.y, self.controller.position.z, self.controller.position.dir
|
self.controller:MoveToPosition(0, 3, 0, Direction.WEST) -- W: BackCenter (Top)
|
||||||
))
|
self.controller:MoveToPosition(0, 0, 0, Direction.NORTH) -- N: BackCenter (Center)
|
||||||
print("Press Enter to continue")
|
|
||||||
_ = io.read()
|
print("The turtle should be in its original location.")
|
||||||
end
|
print(
|
||||||
|
("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
||||||
|
self.controller.position.x,
|
||||||
function TestingController:TestAbsoluteMovementWithStack()
|
self.controller.position.y,
|
||||||
print("Testing absolute movement with stack...")
|
self.controller.position.z,
|
||||||
|
self.controller.position.dir
|
||||||
-- N: BotCenter (Center)
|
)
|
||||||
self.controller:MoveToPosition(0, 0, 3, Direction.EAST) -- E: TopCenter (Center)
|
)
|
||||||
self.controller:MoveBack() -- N: BotCenter (Center)
|
print("Press Enter to continue")
|
||||||
self.controller:MoveToPosition(3, 3, 3, Direction.WEST) -- W: TopRight (Top)
|
_ = io.read()
|
||||||
self.controller:MoveBack() -- N: BotCenter (Center)
|
end
|
||||||
|
|
||||||
print("The turtle should be in its original location.")
|
function TestingController:TestAbsoluteMovementWithStack()
|
||||||
print(("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
print("Testing absolute movement with stack...")
|
||||||
self.controller.position.x, self.controller.position.y, self.controller.position.z, self.controller.position.dir
|
|
||||||
))
|
-- N: BotCenter (Center)
|
||||||
print("Press Enter to continue")
|
self.controller:MoveToPosition(0, 0, 3, Direction.EAST) -- E: TopCenter (Center)
|
||||||
_ = io.read()
|
self.controller:MoveBack() -- N: BotCenter (Center)
|
||||||
end
|
self.controller:MoveToPosition(3, 3, 3, Direction.WEST) -- W: TopRight (Top)
|
||||||
|
self.controller:MoveBack() -- N: BotCenter (Center)
|
||||||
|
|
||||||
function TestingController:TestUnstocking()
|
print("The turtle should be in its original location.")
|
||||||
print("Testing inventory unloading...")
|
print(
|
||||||
|
("The turtle has internal position (%d, %d, %d) and internal direction %d"):format(
|
||||||
self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
|
self.controller.position.x,
|
||||||
print("Please fill the entire inventory with items.")
|
self.controller.position.y,
|
||||||
print("Press Enter to continue")
|
self.controller.position.z,
|
||||||
_ = io.read()
|
self.controller.position.dir
|
||||||
self.controller:UnstockIfFull(true)
|
)
|
||||||
print("Press Enter to continue")
|
)
|
||||||
_ = io.read()
|
print("Press Enter to continue")
|
||||||
self.controller:MoveBack()
|
_ = io.read()
|
||||||
|
end
|
||||||
print("The turtle should be in its original location.")
|
|
||||||
print("Press Enter to continue")
|
function TestingController:TestUnstocking()
|
||||||
_ = io.read()
|
print("Testing inventory unloading...")
|
||||||
end
|
|
||||||
|
self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
|
||||||
|
print("Please fill the entire inventory with items.")
|
||||||
function TestingController:TestRefueling()
|
print("Press Enter to continue")
|
||||||
print("Testing refueling...")
|
_ = io.read()
|
||||||
|
self.controller:UnstockIfFull(true)
|
||||||
self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
|
print("Press Enter to continue")
|
||||||
print("Please fill multiple inventory slots with items.")
|
_ = io.read()
|
||||||
print("Press Enter to continue")
|
self.controller:MoveBack()
|
||||||
_ = io.read()
|
|
||||||
self.controller:RefuelIfEmpty(true)
|
print("The turtle should be in its original location.")
|
||||||
print("Press Enter to continue")
|
print("Press Enter to continue")
|
||||||
_ = io.read()
|
_ = io.read()
|
||||||
self.controller:MoveBack()
|
end
|
||||||
|
|
||||||
print("The turtle should be in its original location.")
|
function TestingController:TestRefueling()
|
||||||
print("Press Enter to continue")
|
print("Testing refueling...")
|
||||||
_ = io.read()
|
|
||||||
end
|
self.controller:MoveToPosition(3, 0, 3, Direction.WEST)
|
||||||
|
print("Please fill multiple inventory slots with items.")
|
||||||
|
print("Press Enter to continue")
|
||||||
-----------------------------------------------------------------------------------------------
|
_ = io.read()
|
||||||
-- Main Method
|
self.controller:RefuelIfEmpty(true)
|
||||||
-----------------------------------------------------------------------------------------------
|
print("Press Enter to continue")
|
||||||
|
_ = io.read()
|
||||||
|
self.controller:MoveBack()
|
||||||
function TestingController:Run()
|
|
||||||
self.controller:Configure()
|
print("The turtle should be in its original location.")
|
||||||
self.controller:DisableMiningForward()
|
print("Press Enter to continue")
|
||||||
self.controller:DisableMiningAbove()
|
_ = io.read()
|
||||||
self.controller:DisableMiningBelow()
|
end
|
||||||
|
|
||||||
print("There are multiple tests available:")
|
-----------------------------------------------------------------------------------------------
|
||||||
print("1: Relative movement with relative rotation")
|
-- Main Method
|
||||||
print("2: Relative movement with absolute rotation")
|
-----------------------------------------------------------------------------------------------
|
||||||
print("3: Absolute movement without stack")
|
|
||||||
print("4: Absolute movement with stack")
|
function TestingController:Run()
|
||||||
print("5: All movement tests")
|
self.controller:Configure()
|
||||||
print("6: Unloading")
|
self.controller:DisableMiningForward()
|
||||||
print("7: Refueling")
|
self.controller:DisableMiningAbove()
|
||||||
print("8: All non-movement tests")
|
self.controller:DisableMiningBelow()
|
||||||
print("9: All tests")
|
|
||||||
|
print("There are multiple tests available:")
|
||||||
local choice = 0
|
print("1: Relative movement with relative rotation")
|
||||||
while choice < 1 or choice > 9 do
|
print("2: Relative movement with absolute rotation")
|
||||||
print("Choose a test by entering its number:")
|
print("3: Absolute movement without stack")
|
||||||
choice = tonumber(io.read()) or 0
|
print("4: Absolute movement with stack")
|
||||||
end
|
print("5: All movement tests")
|
||||||
|
print("6: Unloading")
|
||||||
if choice == 1 then
|
print("7: Refueling")
|
||||||
self:TestRelativeMovementWithRelativeRotation()
|
print("8: All non-movement tests")
|
||||||
elseif choice == 2 then
|
print("9: All tests")
|
||||||
self:TestRelativeMovementWithAbsoluteRotation()
|
|
||||||
elseif choice == 3 then
|
local choice = 0
|
||||||
self:TestAbsoluteMovementWithoutStack()
|
while choice < 1 or choice > 9 do
|
||||||
elseif choice == 4 then
|
print("Choose a test by entering its number:")
|
||||||
self:TestAbsoluteMovementWithStack()
|
choice = tonumber(io.read()) or 0
|
||||||
elseif choice == 5 then
|
end
|
||||||
self:TestRelativeMovementWithRelativeRotation()
|
|
||||||
self:TestRelativeMovementWithAbsoluteRotation()
|
if choice == 1 then
|
||||||
self:TestAbsoluteMovementWithoutStack()
|
self:TestRelativeMovementWithRelativeRotation()
|
||||||
self:TestAbsoluteMovementWithStack()
|
elseif choice == 2 then
|
||||||
elseif choice == 6 then
|
self:TestRelativeMovementWithAbsoluteRotation()
|
||||||
self:TestUnstocking()
|
elseif choice == 3 then
|
||||||
elseif choice == 7 then
|
self:TestAbsoluteMovementWithoutStack()
|
||||||
self:TestRefueling()
|
elseif choice == 4 then
|
||||||
elseif choice == 8 then
|
self:TestAbsoluteMovementWithStack()
|
||||||
self:TestUnstocking()
|
elseif choice == 5 then
|
||||||
self:TestRefueling()
|
self:TestRelativeMovementWithRelativeRotation()
|
||||||
elseif choice == 9 then
|
self:TestRelativeMovementWithAbsoluteRotation()
|
||||||
self:TestRelativeMovementWithRelativeRotation()
|
self:TestAbsoluteMovementWithoutStack()
|
||||||
self:TestRelativeMovementWithAbsoluteRotation()
|
self:TestAbsoluteMovementWithStack()
|
||||||
self:TestAbsoluteMovementWithoutStack()
|
elseif choice == 6 then
|
||||||
self:TestAbsoluteMovementWithStack()
|
self:TestUnstocking()
|
||||||
self:TestUnstocking()
|
elseif choice == 7 then
|
||||||
self:TestRefueling()
|
self:TestRefueling()
|
||||||
end
|
elseif choice == 8 then
|
||||||
end
|
self:TestUnstocking()
|
||||||
|
self:TestRefueling()
|
||||||
|
elseif choice == 9 then
|
||||||
return TestingController
|
self:TestRelativeMovementWithRelativeRotation()
|
||||||
|
self:TestRelativeMovementWithAbsoluteRotation()
|
||||||
|
self:TestAbsoluteMovementWithoutStack()
|
||||||
|
self:TestAbsoluteMovementWithStack()
|
||||||
|
self:TestUnstocking()
|
||||||
|
self:TestRefueling()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return TestingController
|
||||||
|
|||||||
@ -1,462 +1,457 @@
|
|||||||
local Position = require("lib.position")
|
local Position = require("lib.position")
|
||||||
local Direction = require("lib.direction")
|
local Direction = require("lib.direction")
|
||||||
local Stack = require("lib.stack")
|
local Stack = require("lib.stack")
|
||||||
|
|
||||||
---@alias TurtleControllerConfig {fuel_direction: Direction, fuel_name: string, refuel_amount: number, refuel_safety_margin: number, storage_direction: Direction}
|
---@alias TurtleControllerConfig {fuel_direction: Direction, fuel_name: string, refuel_amount: number, refuel_safety_margin: number, storage_direction: Direction}
|
||||||
|
|
||||||
---@class TurtleController
|
---@class TurtleController
|
||||||
---@field config TurtleControllerConfig
|
---@field config TurtleControllerConfig
|
||||||
---@field position Position
|
---@field position Position
|
||||||
---@field last_positions Stack
|
---@field last_positions Stack
|
||||||
---@field mine_forward boolean
|
---@field mine_forward boolean
|
||||||
---@field mine_above boolean
|
---@field mine_above boolean
|
||||||
---@field mine_below boolean
|
---@field mine_below boolean
|
||||||
local TurtleController = {}
|
local TurtleController = {}
|
||||||
TurtleController.__index = TurtleController
|
TurtleController.__index = TurtleController
|
||||||
|
|
||||||
|
---@return TurtleController
|
||||||
---@return TurtleController
|
function TurtleController:Create()
|
||||||
function TurtleController:Create()
|
local t = {}
|
||||||
local t = {}
|
setmetatable(t, TurtleController)
|
||||||
setmetatable(t, TurtleController)
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fields
|
||||||
-----------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------
|
||||||
-- Fields
|
|
||||||
-----------------------------------------------------------------------------------------------
|
t.config = {
|
||||||
|
fuel_direction = Direction.EAST,
|
||||||
|
fuel_name = turtle.getItemDetail(1) == nil and "" or turtle.getItemDetail(1).name,
|
||||||
t.config = {
|
refuel_amount = 500,
|
||||||
fuel_direction = Direction.EAST,
|
refuel_safety_margin = 160,
|
||||||
fuel_name = turtle.getItemDetail(1) == nil and "" or turtle.getItemDetail(1).name,
|
storage_direction = Direction.WEST,
|
||||||
refuel_amount = 500,
|
}
|
||||||
refuel_safety_margin = 160,
|
t.position = Position:Empty()
|
||||||
storage_direction = Direction.WEST,
|
t.last_positions = Stack:Create()
|
||||||
}
|
t.mine_forward = false
|
||||||
t.position = Position:Empty()
|
t.mine_above = false
|
||||||
t.last_positions = Stack:Create()
|
t.mine_below = false
|
||||||
t.mine_forward = false
|
|
||||||
t.mine_above = false
|
return t
|
||||||
t.mine_below = false
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
return t
|
-- Movement Methods
|
||||||
end
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---Positive numbers turn clockwise, negative numbers turn counterclockwise
|
||||||
-----------------------------------------------------------------------------------------------
|
---@param number_of_turns number
|
||||||
-- Movement Methods
|
function TurtleController:TurnRelative(number_of_turns)
|
||||||
-----------------------------------------------------------------------------------------------
|
if number_of_turns % 4 == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
---Positive numbers turn clockwise, negative numbers turn counterclockwise
|
|
||||||
---@param number_of_turns number
|
-- Turn turtle
|
||||||
function TurtleController:TurnRelative(number_of_turns)
|
local turns = number_of_turns % 4
|
||||||
if number_of_turns % 4 == 0 then
|
if turns == 3 then
|
||||||
return
|
-- print(("Turtle is turning by %d (shortened to %d)..."):format(number_of_turns, -1))
|
||||||
end
|
|
||||||
|
-- If we're rotating by 3, we could turn faster by rotating by 1 in the opposite direction
|
||||||
-- Turn turtle
|
turtle.turnLeft()
|
||||||
local turns = number_of_turns % 4
|
else
|
||||||
if turns == 3 then
|
-- print(("Turtle is turning by %d (shortened to %d)..."):format(number_of_turns, turns))
|
||||||
-- print(("Turtle is turning by %d (shortened to %d)..."):format(number_of_turns, -1))
|
|
||||||
|
for _ = 1, turns do
|
||||||
-- If we're rotating by 3, we could turn faster by rotating by 1 in the opposite direction
|
turtle.turnRight()
|
||||||
turtle.turnLeft()
|
end
|
||||||
else
|
end
|
||||||
-- print(("Turtle is turning by %d (shortened to %d)..."):format(number_of_turns, turns))
|
|
||||||
|
-- Update current_position
|
||||||
for _ = 1,turns do
|
self.position.dir = (self.position.dir + number_of_turns) % 4
|
||||||
turtle.turnRight()
|
end
|
||||||
end
|
|
||||||
end
|
---@param direction Direction
|
||||||
|
function TurtleController:TurnToDirection(direction)
|
||||||
-- Update current_position
|
if self.position.dir == direction then
|
||||||
self.position.dir = (self.position.dir + number_of_turns) % 4
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:TurnRelative(direction - self.position.dir)
|
||||||
---@param direction Direction
|
end
|
||||||
function TurtleController:TurnToDirection(direction)
|
|
||||||
if self.position.dir == direction then
|
---Move forward by a number of blocks depending on the current rotation
|
||||||
return
|
---@param number_of_blocks number
|
||||||
end
|
---@param skip_unstocking boolean | nil
|
||||||
|
---@param skip_refueling boolean | nil
|
||||||
self:TurnRelative(direction - self.position.dir)
|
function TurtleController:MoveForward(number_of_blocks, skip_unstocking, skip_refueling)
|
||||||
end
|
skip_unstocking = skip_unstocking or false
|
||||||
|
skip_refueling = skip_refueling or false
|
||||||
|
if number_of_blocks == 0 then
|
||||||
---Move forward by a number of blocks depending on the current rotation
|
return
|
||||||
---@param number_of_blocks number
|
end
|
||||||
---@param skip_unstocking boolean | nil
|
|
||||||
---@param skip_refueling boolean | nil
|
-- print(("Turtle is moving forward by %d blocks..."):format(number_of_blocks))
|
||||||
function TurtleController:MoveForward(number_of_blocks, skip_unstocking, skip_refueling)
|
|
||||||
skip_unstocking = skip_unstocking or false
|
for _ = 1, math.abs(number_of_blocks) do
|
||||||
skip_refueling = skip_refueling or false
|
if not skip_refueling then
|
||||||
if number_of_blocks == 0 then
|
self:RefuelIfEmpty()
|
||||||
return
|
end
|
||||||
end
|
if not skip_unstocking then
|
||||||
|
self:UnstockIfFull()
|
||||||
-- print(("Turtle is moving forward by %d blocks..."):format(number_of_blocks))
|
end
|
||||||
|
|
||||||
for _ = 1,math.abs(number_of_blocks) do
|
-- Mine/Move
|
||||||
if not skip_refueling then
|
if self.mine_forward then
|
||||||
self:RefuelIfEmpty()
|
while not turtle.forward() do
|
||||||
end
|
turtle.dig()
|
||||||
if not skip_unstocking then
|
end
|
||||||
self:UnstockIfFull()
|
elseif not turtle.forward() then
|
||||||
end
|
error("Turtle failed to move forward!")
|
||||||
|
end
|
||||||
-- Mine/Move
|
if self.mine_above then
|
||||||
if self.mine_forward then
|
turtle.digUp()
|
||||||
while not turtle.forward() do
|
end
|
||||||
turtle.dig()
|
if self.mine_below then
|
||||||
end
|
turtle.digDown()
|
||||||
elseif not turtle.forward() then
|
end
|
||||||
error("Turtle failed to move forward!")
|
|
||||||
end
|
-- Update current position
|
||||||
if self.mine_above then
|
if self.position.dir == Direction.NORTH then
|
||||||
turtle.digUp()
|
self.position.z = self.position.z + 1
|
||||||
end
|
elseif self.position.dir == Direction.SOUTH then
|
||||||
if self.mine_below then
|
self.position.z = self.position.z - 1
|
||||||
turtle.digDown()
|
elseif self.position.dir == Direction.EAST then
|
||||||
end
|
self.position.x = self.position.x + 1
|
||||||
|
elseif self.position.dir == Direction.WEST then
|
||||||
-- Update current position
|
self.position.x = self.position.x - 1
|
||||||
if self.position.dir == Direction.NORTH then
|
end
|
||||||
self.position.z = self.position.z + 1
|
end
|
||||||
elseif self.position.dir == Direction.SOUTH then
|
end
|
||||||
self.position.z = self.position.z - 1
|
|
||||||
elseif self.position.dir == Direction.EAST then
|
---Positive numbers move up, negative numbers move down.
|
||||||
self.position.x = self.position.x + 1
|
---@param number_of_blocks number
|
||||||
elseif self.position.dir == Direction.WEST then
|
---@param skip_unstocking boolean | nil
|
||||||
self.position.x = self.position.x - 1
|
---@param skip_refueling boolean | nil
|
||||||
end
|
function TurtleController:MoveVertical(number_of_blocks, skip_unstocking, skip_refueling)
|
||||||
end
|
skip_unstocking = skip_unstocking or false
|
||||||
end
|
skip_refueling = skip_refueling or false
|
||||||
|
if number_of_blocks == 0 then
|
||||||
---Positive numbers move up, negative numbers move down.
|
return
|
||||||
---@param number_of_blocks number
|
end
|
||||||
---@param skip_unstocking boolean | nil
|
|
||||||
---@param skip_refueling boolean | nil
|
-- print(("Turtle is moving vertically by %d blocks..."):format(number_of_blocks))
|
||||||
function TurtleController:MoveVertical(number_of_blocks, skip_unstocking, skip_refueling)
|
|
||||||
skip_unstocking = skip_unstocking or false
|
local move_function = number_of_blocks > 0 and turtle.up or turtle.down
|
||||||
skip_refueling = skip_refueling or false
|
local mine_function = number_of_blocks > 0 and turtle.digUp or turtle.digDown
|
||||||
if number_of_blocks == 0 then
|
local mine_enabled = number_of_blocks > 0 and self.mine_above or self.mine_below
|
||||||
return
|
|
||||||
end
|
for _ = 1, math.abs(number_of_blocks) do
|
||||||
|
if not skip_refueling then
|
||||||
-- print(("Turtle is moving vertically by %d blocks..."):format(number_of_blocks))
|
self:RefuelIfEmpty()
|
||||||
|
end
|
||||||
local move_function = number_of_blocks > 0 and turtle.up or turtle.down
|
if not skip_unstocking then
|
||||||
local mine_function = number_of_blocks > 0 and turtle.digUp or turtle.digDown
|
self:UnstockIfFull()
|
||||||
local mine_enabled = number_of_blocks > 0 and self.mine_above or self.mine_below
|
end
|
||||||
|
|
||||||
for _ = 1,math.abs(number_of_blocks) do
|
-- Mine
|
||||||
if not skip_refueling then
|
if mine_enabled then
|
||||||
self:RefuelIfEmpty()
|
mine_function()
|
||||||
end
|
end
|
||||||
if not skip_unstocking then
|
|
||||||
self:UnstockIfFull()
|
-- Move
|
||||||
end
|
if not move_function() then
|
||||||
|
error("Turtle failed to move vertically!")
|
||||||
-- Mine
|
end
|
||||||
if mine_enabled then
|
|
||||||
mine_function()
|
-- Update current position
|
||||||
end
|
if number_of_blocks > 0 then
|
||||||
|
self.position.y = self.position.y + 1
|
||||||
-- Move
|
elseif number_of_blocks < 0 then
|
||||||
if not move_function() then
|
self.position.y = self.position.y - 1
|
||||||
error("Turtle failed to move vertically!")
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
-- Update current position
|
|
||||||
if number_of_blocks > 0 then
|
---Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
||||||
self.position.y = self.position.y + 1
|
function TurtleController:StorePosition()
|
||||||
elseif number_of_blocks < 0 then
|
self.last_positions:Push(Position:Copy(self.position))
|
||||||
self.position.y = self.position.y - 1
|
end
|
||||||
end
|
|
||||||
end
|
---Move to an absolute position. Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
||||||
end
|
---@param x number The EAST/WEST axis (grows from WEST to EAST)
|
||||||
|
---@param y number The UP/DOWN axis (grows from DOWN to UP)
|
||||||
|
---@param z number The NORTH/SOUTH axis (grows from SOUTH to NORTH)
|
||||||
---Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
---@param dir Direction
|
||||||
function TurtleController:StorePosition()
|
---@param skip_unstocking boolean | nil
|
||||||
self.last_positions:Push(Position:Copy(self.position))
|
---@param skip_refueling boolean | nil
|
||||||
end
|
function TurtleController:MoveToPosition(x, y, z, dir, skip_unstocking, skip_refueling)
|
||||||
|
-- print(("Turtle is moving to (%d, %d, %d)..."):format(x, y, z))
|
||||||
|
|
||||||
---Move to an absolute position. Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
-- Store the current position on the stack, so we can return using TurtleController:MoveBack()
|
||||||
---@param x number The EAST/WEST axis (grows from WEST to EAST)
|
self.last_positions:Push(Position:Copy(self.position))
|
||||||
---@param y number The UP/DOWN axis (grows from DOWN to UP)
|
|
||||||
---@param z number The NORTH/SOUTH axis (grows from SOUTH to NORTH)
|
-- EAST/WEST axis (do first to not interfere with chests)
|
||||||
---@param dir Direction
|
if self.position.x > x then
|
||||||
---@param skip_unstocking boolean | nil
|
self:TurnToDirection(Direction.WEST)
|
||||||
---@param skip_refueling boolean | nil
|
elseif self.position.x < x then
|
||||||
function TurtleController:MoveToPosition(x, y, z, dir, skip_unstocking, skip_refueling)
|
self:TurnToDirection(Direction.EAST)
|
||||||
-- print(("Turtle is moving to (%d, %d, %d)..."):format(x, y, z))
|
end
|
||||||
|
self:MoveForward(math.abs(x - self.position.x), skip_unstocking, skip_refueling)
|
||||||
-- Store the current position on the stack, so we can return using TurtleController:MoveBack()
|
|
||||||
self.last_positions:Push(Position:Copy(self.position))
|
-- NORTH/SOUTH axis
|
||||||
|
if self.position.z > z then
|
||||||
-- EAST/WEST axis (do first to not interfere with chests)
|
self:TurnToDirection(Direction.SOUTH)
|
||||||
if self.position.x > x then
|
elseif self.position.z < z then
|
||||||
self:TurnToDirection(Direction.WEST)
|
self:TurnToDirection(Direction.NORTH)
|
||||||
elseif self.position.x < x then
|
end
|
||||||
self:TurnToDirection(Direction.EAST)
|
self:MoveForward(math.abs(z - self.position.z), skip_unstocking, skip_refueling)
|
||||||
end
|
|
||||||
self:MoveForward(math.abs(x - self.position.x), skip_unstocking, skip_refueling)
|
-- UP/DOWN axis
|
||||||
|
self:MoveVertical(y - self.position.y, skip_unstocking, skip_refueling)
|
||||||
-- NORTH/SOUTH axis
|
|
||||||
if self.position.z > z then
|
-- Direction
|
||||||
self:TurnToDirection(Direction.SOUTH)
|
self:TurnToDirection(dir or Direction.NORTH)
|
||||||
elseif self.position.z < z then
|
|
||||||
self:TurnToDirection(Direction.NORTH)
|
-- Sanity check
|
||||||
end
|
if not (self.position.x == x and self.position.y == y and self.position.z == z and self.position.dir == dir) then
|
||||||
self:MoveForward(math.abs(z - self.position.z), skip_unstocking, skip_refueling)
|
error("TurtleController:MoveToPosition failed to move to target position!")
|
||||||
|
end
|
||||||
-- UP/DOWN axis
|
end
|
||||||
self:MoveVertical(y - self.position.y, skip_unstocking, skip_refueling)
|
|
||||||
|
---Move by a vector. Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
||||||
-- Direction
|
---@param x number The EAST/WEST axis (grows from WEST to EAST)
|
||||||
self:TurnToDirection(dir or Direction.NORTH)
|
---@param y number The UP/DOWN axis (grows from DOWN to UP)
|
||||||
|
---@param z number The NORTH/SOUTH axis (grows from SOUTH to NORTH)
|
||||||
-- Sanity check
|
---@param dir Direction
|
||||||
if not(self.position.x == x and self.position.y == y and self.position.z == z and self.position.dir == dir) then
|
---@param skip_unstocking boolean | nil
|
||||||
error("TurtleController:MoveToPosition failed to move to target position!")
|
---@param skip_refueling boolean | nil
|
||||||
end
|
function TurtleController:MoveByVector(x, y, z, dir, skip_unstocking, skip_refueling)
|
||||||
end
|
self:MoveToPosition(
|
||||||
|
self.position.x + x,
|
||||||
|
self.position.y + y,
|
||||||
---Move by a vector. Stores the current position on the stack so we can return using TurtleController:MoveBack()
|
self.position.z + z,
|
||||||
---@param x number The EAST/WEST axis (grows from WEST to EAST)
|
dir,
|
||||||
---@param y number The UP/DOWN axis (grows from DOWN to UP)
|
skip_unstocking,
|
||||||
---@param z number The NORTH/SOUTH axis (grows from SOUTH to NORTH)
|
skip_refueling
|
||||||
---@param dir Direction
|
)
|
||||||
---@param skip_unstocking boolean | nil
|
end
|
||||||
---@param skip_refueling boolean | nil
|
|
||||||
function TurtleController:MoveByVector(x, y, z, dir, skip_unstocking, skip_refueling)
|
---Move to the previously stored position and pop this position from the stack.
|
||||||
self:MoveToPosition(self.position.x + x, self.position.y + y, self.position.z + z, dir, skip_unstocking, skip_refueling)
|
---@param skip_unstocking boolean | nil
|
||||||
end
|
---@param skip_refueling boolean | nil
|
||||||
|
function TurtleController:MoveBack(skip_unstocking, skip_refueling)
|
||||||
|
local last_position = self.last_positions:Pop()
|
||||||
---Move to the previously stored position and pop this position from the stack.
|
|
||||||
---@param skip_unstocking boolean | nil
|
if last_position == nil then
|
||||||
---@param skip_refueling boolean | nil
|
error("Failed to obtain last_position to move back!")
|
||||||
function TurtleController:MoveBack(skip_unstocking, skip_refueling)
|
else
|
||||||
local last_position = self.last_positions:Pop()
|
self:MoveToPosition(
|
||||||
|
last_position.x,
|
||||||
if last_position == nil then
|
last_position.y,
|
||||||
error("Failed to obtain last_position to move back!")
|
last_position.z,
|
||||||
else
|
last_position.dir,
|
||||||
self:MoveToPosition(last_position.x, last_position.y, last_position.z, last_position.dir, skip_unstocking, skip_refueling)
|
skip_unstocking,
|
||||||
|
skip_refueling
|
||||||
-- Pop the stack because MoveToPosition pushes our current position
|
)
|
||||||
self.last_positions:Pop()
|
|
||||||
end
|
-- Pop the stack because MoveToPosition pushes our current position
|
||||||
end
|
self.last_positions:Pop()
|
||||||
|
end
|
||||||
|
end
|
||||||
-----------------------------------------------------------------------------------------------
|
|
||||||
-- Inventory Methods
|
-----------------------------------------------------------------------------------------------
|
||||||
-----------------------------------------------------------------------------------------------
|
-- Inventory Methods
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function TurtleController:HasFuel()
|
function TurtleController:HasFuel()
|
||||||
local level = turtle.getFuelLevel()
|
local level = turtle.getFuelLevel()
|
||||||
local distance_home = self.position.x + self.position.y + self.position.z
|
local distance_home = self.position.x + self.position.y + self.position.z
|
||||||
|
|
||||||
return level > distance_home + self.config.refuel_safety_margin
|
return level > distance_home + self.config.refuel_safety_margin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
---@return boolean
|
function TurtleController:HasInventorySpace()
|
||||||
function TurtleController:HasInventorySpace()
|
for slot = 1, 16 do
|
||||||
for slot = 1,16 do
|
if turtle.getItemDetail(slot) == nil then
|
||||||
if turtle.getItemDetail(slot) == nil then
|
return true
|
||||||
return true
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
return false
|
||||||
return false
|
end
|
||||||
end
|
|
||||||
|
---@param slot number
|
||||||
|
---@param count number
|
||||||
---@param slot number
|
---@return boolean
|
||||||
---@param count number
|
function TurtleController:SuckItem(slot, count)
|
||||||
---@return boolean
|
local previous_slot = turtle.getSelectedSlot()
|
||||||
function TurtleController:SuckItem(slot, count)
|
|
||||||
local previous_slot = turtle.getSelectedSlot()
|
turtle.select(slot or 1)
|
||||||
|
local sucked = turtle.suck(count)
|
||||||
turtle.select(slot or 1)
|
|
||||||
local sucked = turtle.suck(count)
|
turtle.select(previous_slot)
|
||||||
|
|
||||||
turtle.select(previous_slot)
|
return sucked
|
||||||
|
end
|
||||||
return sucked
|
|
||||||
end
|
---@param slot number
|
||||||
|
---@param count number
|
||||||
|
---@return boolean
|
||||||
---@param slot number
|
function TurtleController:DropItem(slot, count)
|
||||||
---@param count number
|
local previous_slot = turtle.getSelectedSlot()
|
||||||
---@return boolean
|
|
||||||
function TurtleController:DropItem(slot, count)
|
turtle.select(slot or 1)
|
||||||
local previous_slot = turtle.getSelectedSlot()
|
local dropped = turtle.drop(count)
|
||||||
|
|
||||||
turtle.select(slot or 1)
|
turtle.select(previous_slot)
|
||||||
local dropped = turtle.drop(count)
|
|
||||||
|
return dropped
|
||||||
turtle.select(previous_slot)
|
end
|
||||||
|
|
||||||
return dropped
|
function TurtleController:DropInventory()
|
||||||
end
|
print("Dropping inventory into chest...")
|
||||||
|
|
||||||
|
for slot = 1, 16 do
|
||||||
function TurtleController:DropInventory()
|
turtle.select(slot)
|
||||||
print("Dropping inventory into chest...")
|
turtle.drop()
|
||||||
|
end
|
||||||
for slot = 1,16 do
|
|
||||||
turtle.select(slot)
|
turtle.select(1)
|
||||||
turtle.drop()
|
end
|
||||||
end
|
|
||||||
|
---@param skip_inventory_check boolean | nil
|
||||||
turtle.select(1)
|
function TurtleController:UnstockIfFull(skip_inventory_check)
|
||||||
end
|
skip_inventory_check = skip_inventory_check or false
|
||||||
|
if not skip_inventory_check and self:HasInventorySpace() then
|
||||||
|
return
|
||||||
---@param skip_inventory_check boolean | nil
|
end
|
||||||
function TurtleController:UnstockIfFull(skip_inventory_check)
|
if skip_inventory_check then
|
||||||
skip_inventory_check = skip_inventory_check or false
|
print(("HasInventorySpace() returned %s"):format(self:HasInventorySpace()))
|
||||||
if not skip_inventory_check and self:HasInventorySpace() then
|
end
|
||||||
return
|
|
||||||
end
|
print("Turtle is unstocking...")
|
||||||
if skip_inventory_check then
|
|
||||||
print(("HasInventorySpace() returned %s"):format(self:HasInventorySpace()))
|
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
|
||||||
end
|
self:DropInventory()
|
||||||
|
self:RefuelIfEmpty()
|
||||||
print("Turtle is unstocking...")
|
|
||||||
|
self:MoveBack(true, true)
|
||||||
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
|
end
|
||||||
self:DropInventory()
|
|
||||||
self:RefuelIfEmpty()
|
---@param skip_fuel_check boolean | nil
|
||||||
|
function TurtleController:RefuelIfEmpty(skip_fuel_check)
|
||||||
self:MoveBack(true, true)
|
skip_fuel_check = skip_fuel_check or false
|
||||||
end
|
if not skip_fuel_check and self:HasFuel() then
|
||||||
|
return
|
||||||
|
end
|
||||||
---@param skip_fuel_check boolean | nil
|
if skip_fuel_check then
|
||||||
function TurtleController:RefuelIfEmpty(skip_fuel_check)
|
print(("HasFuel() returned %s"):format(self:HasFuel()))
|
||||||
skip_fuel_check = skip_fuel_check or false
|
end
|
||||||
if not skip_fuel_check and self:HasFuel() then
|
|
||||||
return
|
print("Turtle is refueling...")
|
||||||
end
|
|
||||||
if skip_fuel_check then
|
-- Clear our inventory into the storage chest
|
||||||
print(("HasFuel() returned %s"):format(self:HasFuel()))
|
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
|
||||||
end
|
self:DropInventory()
|
||||||
|
|
||||||
print("Turtle is refueling...")
|
-- Prepare refueling
|
||||||
|
self:TurnToDirection(self.config.fuel_direction)
|
||||||
-- Clear our inventory into the storage chest
|
turtle.select(1)
|
||||||
self:MoveToPosition(0, 0, 0, self.config.storage_direction, true, true)
|
|
||||||
self:DropInventory()
|
-- Include the distance to the last position when refueling
|
||||||
|
-- to keep the amount of work done between refuelings constant
|
||||||
-- Prepare refueling
|
local target_fuel_level = self.config.refuel_amount
|
||||||
self:TurnToDirection(self.config.fuel_direction)
|
local last_position = self.last_positions:Peek()
|
||||||
turtle.select(1)
|
if last_position == nil then
|
||||||
|
error("Failed to obtain last_position while refueling!")
|
||||||
-- Include the distance to the last position when refueling
|
else
|
||||||
-- to keep the amount of work done between refuelings constant
|
target_fuel_level = target_fuel_level + last_position.x + last_position.y + last_position.z
|
||||||
local target_fuel_level = self.config.refuel_amount
|
end
|
||||||
local last_position = self.last_positions:Peek()
|
|
||||||
if last_position == nil then
|
-- Refuel until we hit the refuel_amount
|
||||||
error("Failed to obtain last_position while refueling!")
|
local before_level = turtle.getFuelLevel()
|
||||||
else
|
repeat
|
||||||
target_fuel_level = target_fuel_level + last_position.x + last_position.y + last_position.z
|
if not self:SuckItem(1, 1) then
|
||||||
end
|
error("Failed to suck fuel out of fuel chest!")
|
||||||
|
end
|
||||||
-- Refuel until we hit the refuel_amount
|
turtle.refuel()
|
||||||
local before_level = turtle.getFuelLevel()
|
until turtle.getFuelLevel() >= target_fuel_level
|
||||||
repeat
|
local after_level = turtle.getFuelLevel()
|
||||||
if not self:SuckItem(1, 1) then
|
|
||||||
error("Failed to suck fuel out of fuel chest!")
|
self:MoveBack(true, true)
|
||||||
end
|
|
||||||
turtle.refuel()
|
print(
|
||||||
until turtle.getFuelLevel() >= target_fuel_level
|
("Refuelled %d units, current level is %d (old level was %d)"):format(
|
||||||
local after_level = turtle.getFuelLevel()
|
after_level - before_level,
|
||||||
|
after_level,
|
||||||
self:MoveBack(true, true)
|
before_level
|
||||||
|
)
|
||||||
print(("Refuelled %d units, current level is %d (old level was %d)"):format(after_level - before_level, after_level, before_level))
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
-----------------------------------------------------------------------------------------------
|
-- Management Methods
|
||||||
-- Management Methods
|
-----------------------------------------------------------------------------------------------
|
||||||
-----------------------------------------------------------------------------------------------
|
|
||||||
|
function TurtleController:Configure()
|
||||||
|
local config_complete = false
|
||||||
function TurtleController:Configure()
|
|
||||||
local config_complete = false
|
while not config_complete do
|
||||||
|
-- Check for valid fuel
|
||||||
while not config_complete do
|
while self.config.fuel_name == "" do
|
||||||
-- Check for valid fuel
|
print("Please put valid fuel into the first slot and press Enter!")
|
||||||
while self.config.fuel_name == "" do
|
local _ = io.read()
|
||||||
print("Please put valid fuel into the first slot and press Enter!")
|
self.config.fuel_name = turtle.getItemDetail(1) == nil and "" or turtle.getItemDetail(1).name
|
||||||
local _ = io.read()
|
end
|
||||||
self.config.fuel_name = turtle.getItemDetail(1) == nil and "" or turtle.getItemDetail(1).name
|
|
||||||
end
|
print("A chest with fuel has to be placed beside the turtle's starting position. Is this chest...")
|
||||||
|
print(("...right of the turtle (enter %d)?"):format(Direction.EAST))
|
||||||
print("A chest with fuel has to be placed beside the turtle's starting position. Is this chest...")
|
print(("...behind the turtle (enter %d)?"):format(Direction.SOUTH))
|
||||||
print(("...right of the turtle (enter %d)?"):format(Direction.EAST))
|
print(("...left of the turtle (enter %d)?"):format(Direction.WEST))
|
||||||
print(("...behind the turtle (enter %d)?"):format(Direction.SOUTH))
|
print("By default, the chest is assumed on the left.")
|
||||||
print(("...left of the turtle (enter %d)?"):format(Direction.WEST))
|
self.config.fuel_direction = tonumber(io.read()) or Direction.WEST
|
||||||
print("By default, the chest is assumed on the left.")
|
|
||||||
self.config.fuel_direction = tonumber(io.read()) or Direction.WEST
|
print("A chest to store mined blocks has to be placed beside the turtle's starting position. Is this chest...")
|
||||||
|
print(("...right of the turtle (enter %d)?"):format(Direction.EAST))
|
||||||
print("A chest to store mined blocks has to be placed beside the turtle's starting position. Is this chest...")
|
print(("...behind the turtle (enter %d)?"):format(Direction.SOUTH))
|
||||||
print(("...right of the turtle (enter %d)?"):format(Direction.EAST))
|
print(("...left of the turtle (enter %d)?"):format(Direction.WEST))
|
||||||
print(("...behind the turtle (enter %d)?"):format(Direction.SOUTH))
|
print("By default, the chest is assumed on the right.")
|
||||||
print(("...left of the turtle (enter %d)?"):format(Direction.WEST))
|
self.config.storage_direction = tonumber(io.read()) or Direction.EAST
|
||||||
print("By default, the chest is assumed on the right.")
|
|
||||||
self.config.storage_direction = tonumber(io.read()) or Direction.EAST
|
print("Configuration complete!")
|
||||||
|
print(
|
||||||
print("Configuration complete!")
|
('Turtle will consume "%s" for fuel. Put the desired fuel into the first slot to change.'):format(
|
||||||
print(("Turtle will consume \"%s\" for fuel. Put the desired fuel into the first slot to change."):format(self.config.fuel_name))
|
self.config.fuel_name
|
||||||
print("Do you want to accept the configuration (enter 1, otherwise 0)?")
|
)
|
||||||
config_complete = tonumber(io.read()) == 1
|
)
|
||||||
end
|
print("Do you want to accept the configuration (enter 1, otherwise 0)?")
|
||||||
end
|
config_complete = tonumber(io.read()) == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
function TurtleController:EnableMiningForward()
|
|
||||||
self.mine_forward = true
|
function TurtleController:EnableMiningForward()
|
||||||
end
|
self.mine_forward = true
|
||||||
|
end
|
||||||
|
|
||||||
function TurtleController:DisableMiningForward()
|
function TurtleController:DisableMiningForward()
|
||||||
self.mine_forward = false
|
self.mine_forward = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function TurtleController:EnableMiningAbove()
|
||||||
function TurtleController:EnableMiningAbove()
|
self.mine_above = true
|
||||||
self.mine_above = true
|
end
|
||||||
end
|
|
||||||
|
function TurtleController:DisableMiningAbove()
|
||||||
|
self.mine_above = false
|
||||||
function TurtleController:DisableMiningAbove()
|
end
|
||||||
self.mine_above = false
|
|
||||||
end
|
function TurtleController:EnableMiningBelow()
|
||||||
|
self.mine_below = true
|
||||||
|
end
|
||||||
function TurtleController:EnableMiningBelow()
|
|
||||||
self.mine_below = true
|
function TurtleController:DisableMiningBelow()
|
||||||
end
|
self.mine_below = false
|
||||||
|
end
|
||||||
|
|
||||||
function TurtleController:DisableMiningBelow()
|
return TurtleController
|
||||||
self.mine_below = false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return TurtleController
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
---@enum Direction
|
---@enum Direction
|
||||||
local Direction = {
|
local Direction = {
|
||||||
NORTH = 0,
|
NORTH = 0,
|
||||||
EAST = 1,
|
EAST = 1,
|
||||||
SOUTH = 2,
|
SOUTH = 2,
|
||||||
WEST = 3
|
WEST = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Direction
|
return Direction
|
||||||
|
|||||||
139
lib/position.lua
139
lib/position.lua
@ -1,70 +1,69 @@
|
|||||||
local Direction = require("lib.direction")
|
local Direction = require("lib.direction")
|
||||||
|
|
||||||
---@class Position
|
---@class Position
|
||||||
---@field x number
|
---@field x number
|
||||||
---@field y number
|
---@field y number
|
||||||
---@field z number
|
---@field z number
|
||||||
---@field dir Direction
|
---@field dir Direction
|
||||||
local Position = {}
|
local Position = {}
|
||||||
Position.__index = Position
|
Position.__index = Position
|
||||||
|
|
||||||
|
---@return Position
|
||||||
---@return Position
|
function Position:Empty()
|
||||||
function Position:Empty()
|
local t = {}
|
||||||
local t = {}
|
setmetatable(t, Position)
|
||||||
setmetatable(t, Position)
|
|
||||||
|
t.x = 0
|
||||||
t.x = 0
|
t.y = 0
|
||||||
t.y = 0
|
t.z = 0
|
||||||
t.z = 0
|
t.dir = Direction.NORTH
|
||||||
t.dir = Direction.NORTH
|
|
||||||
|
return t
|
||||||
return t
|
end
|
||||||
end
|
|
||||||
|
---@param x number
|
||||||
---@param x number
|
---@param y number
|
||||||
---@param y number
|
---@param z number
|
||||||
---@param z number
|
---@param dir Direction
|
||||||
---@param dir Direction
|
---@return Position
|
||||||
---@return Position
|
function Position:Create(x, y, z, dir)
|
||||||
function Position:Create(x, y, z, dir)
|
local t = {}
|
||||||
local t = {}
|
setmetatable(t, Position)
|
||||||
setmetatable(t, Position)
|
|
||||||
|
t.x = x
|
||||||
t.x = x
|
t.y = y
|
||||||
t.y = y
|
t.z = z
|
||||||
t.z = z
|
t.dir = dir or Direction.NORTH
|
||||||
t.dir = dir or Direction.NORTH
|
|
||||||
|
return t
|
||||||
return t
|
end
|
||||||
end
|
|
||||||
|
---@param other Position
|
||||||
---@param other Position
|
---@return Position
|
||||||
---@return Position
|
function Position:Copy(other)
|
||||||
function Position:Copy(other)
|
local t = {}
|
||||||
local t = {}
|
setmetatable(t, Position)
|
||||||
setmetatable(t, Position)
|
|
||||||
|
t.x = other.x
|
||||||
t.x = other.x
|
t.y = other.y
|
||||||
t.y = other.y
|
t.z = other.z
|
||||||
t.z = other.z
|
t.dir = other.dir
|
||||||
t.dir = other.dir
|
|
||||||
|
return t
|
||||||
return t
|
end
|
||||||
end
|
|
||||||
|
---@param other Position
|
||||||
---@param other Position
|
function Position:Add(other)
|
||||||
function Position:Add(other)
|
self.x = self.x + other.x
|
||||||
self.x = self.x + other.x
|
self.y = self.y + other.y
|
||||||
self.y = self.y + other.y
|
self.z = self.z + other.z
|
||||||
self.z = self.z + other.z
|
end
|
||||||
end
|
|
||||||
|
---@param other Position
|
||||||
---@param other Position
|
function Position:Subtract(other)
|
||||||
function Position:Subtract(other)
|
self.x = self.x - other.x
|
||||||
self.x = self.x - other.x
|
self.y = self.y - other.y
|
||||||
self.y = self.y - other.y
|
self.z = self.z - other.z
|
||||||
self.z = self.z - other.z
|
end
|
||||||
end
|
|
||||||
|
return Position
|
||||||
return Position
|
|
||||||
|
|||||||
114
lib/stack.lua
114
lib/stack.lua
@ -1,61 +1,53 @@
|
|||||||
local Position = require("lib.position")
|
---@class Stack
|
||||||
|
---@field elements Position[]
|
||||||
---@class Stack
|
local Stack = {}
|
||||||
---@field elements Position[]
|
Stack.__index = Stack
|
||||||
local Stack = {}
|
|
||||||
Stack.__index = Stack
|
---@return Stack
|
||||||
|
function Stack:Create()
|
||||||
|
-- stack table
|
||||||
---@return Stack
|
local t = {}
|
||||||
function Stack:Create()
|
setmetatable(t, Stack)
|
||||||
-- stack table
|
|
||||||
local t = {}
|
-- entry table
|
||||||
setmetatable(t, Stack)
|
t.elements = {}
|
||||||
|
|
||||||
-- entry table
|
return t
|
||||||
t.elements = {}
|
end
|
||||||
|
|
||||||
return t
|
---@param element Position
|
||||||
end
|
function Stack:Push(element)
|
||||||
|
if element == nil or element == {} then
|
||||||
|
printError("Failed to push empty element to the stack!")
|
||||||
---@param element Position
|
return
|
||||||
function Stack:Push(element)
|
end
|
||||||
if element == nil or element == {} then
|
|
||||||
printError("Failed to push empty element to the stack!")
|
table.insert(self.elements, element)
|
||||||
return
|
end
|
||||||
end
|
|
||||||
|
---@return Position | nil
|
||||||
table.insert(self.elements, element)
|
function Stack:Pop()
|
||||||
end
|
if self:Count() == 0 then
|
||||||
|
printError("Failed to pop element from the empty stack!")
|
||||||
|
return nil
|
||||||
---@return Position | nil
|
end
|
||||||
function Stack:Pop()
|
|
||||||
if self:Count() == 0 then
|
return table.remove(self.elements)
|
||||||
printError("Failed to pop element from the empty stack!")
|
end
|
||||||
return nil
|
|
||||||
end
|
---@return Position | nil
|
||||||
|
function Stack:Peek()
|
||||||
return table.remove(self.elements)
|
if self:Count() == 0 then
|
||||||
end
|
printError("Failed to peek element from the empty stack!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
---@return Position | nil
|
|
||||||
function Stack:Peek()
|
return self.elements[#self.elements]
|
||||||
if self:Count() == 0 then
|
end
|
||||||
printError("Failed to peek element from the empty stack!")
|
|
||||||
return nil
|
---@return number
|
||||||
end
|
function Stack:Count()
|
||||||
|
return #self.elements
|
||||||
return self.elements[#self.elements]
|
end
|
||||||
end
|
|
||||||
|
return Stack
|
||||||
|
|
||||||
---@return number
|
|
||||||
function Stack:Count()
|
|
||||||
return #self.elements
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return Stack
|
|
||||||
|
|||||||
62
main.lua
62
main.lua
@ -1,32 +1,30 @@
|
|||||||
local TestingController = require("controller.testing_controller")
|
local TestingController = require("controller.testing_controller")
|
||||||
local ExcavationController = require("controller.excavation_controller")
|
local ExcavationController = require("controller.excavation_controller")
|
||||||
local AudioController = require("controller.audio_controller")
|
local AudioController = require("controller.audio_controller")
|
||||||
|
|
||||||
|
local controllers = {
|
||||||
local controllers = {
|
TestingController:Create(),
|
||||||
TestingController:Create(),
|
ExcavationController:Create(),
|
||||||
ExcavationController:Create(),
|
AudioController:Create(),
|
||||||
AudioController:Create(),
|
}
|
||||||
}
|
|
||||||
|
print("Multiple controllers are available:")
|
||||||
print("Multiple controllers are available:")
|
print("1: Testing Mode")
|
||||||
print("1: Testing Mode")
|
print("2: Volume Excavation")
|
||||||
print("2: Volume Excavation")
|
print("3: Play Bangarang")
|
||||||
print("3: Play Bangarang")
|
|
||||||
|
local choice = 0
|
||||||
local choice = 0
|
while choice < 1 or choice > #controllers do
|
||||||
while choice < 1 or choice > #controllers do
|
print("Choose a controller by entering its number:")
|
||||||
print("Choose a controller by entering its number:")
|
choice = tonumber(io.read()) or 0
|
||||||
choice = tonumber(io.read()) or 0
|
end
|
||||||
end
|
|
||||||
|
controllers[choice]:Run()
|
||||||
controllers[choice]:Run()
|
|
||||||
|
-- TODO: StackOverflow once the inventory is full, unstocking doesn't work...
|
||||||
|
-- Is the InventoryFull check wrong?
|
||||||
-- TODO: StackOverflow once the inventory is full, unstocking doesn't work...
|
-- TODO: Test if there's a chest when dropping/sucking/mining (don't mine chests!)
|
||||||
-- Is the InventoryFull check wrong?
|
-- TODO: Add controller to build rooms with walls of a specified material
|
||||||
-- TODO: Test if there's a chest when dropping/sucking/mining (don't mine chests!)
|
-- TODO: Support specifying the mining height
|
||||||
-- TODO: Add controller to build rooms with walls of a specified material
|
-- TODO: Add configurable trash_list with items that won't be picked up
|
||||||
-- TODO: Support specifying the mining height
|
-- TODO: Add a speaker to the turtle (listen to music while mining)
|
||||||
-- TODO: Add configurable trash_list with items that won't be picked up
|
|
||||||
-- TODO: Add a speaker to the turtle (listen to music while mining)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user