Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- 高さ2
- -- a0 = 9
- -- an+1 = an + 8
- -- 最初の周回は1週目
- local TORCH_INTERVAL = 12
- ---@param str string
- local function debug_print(str)
- http.post("http://127.0.0.1:25763/", str)
- end
- ---@param name string
- ---@param arr any[]
- local function PrintArray(name, arr)
- local re = "["
- for i, v in ipairs(arr) do
- if i ~= 1 then re = re.."," end
- re = re..tostring(v)
- end
- debug_print(name..": "..re.."]")
- end
- ---@param ForwardCount integer
- local function MoveForwardImpl(ForwardCount)
- for i = 1, ForwardCount do
- if not turtle.forward() then return i - 1 end
- end
- return ForwardCount
- end
- local function TurnBack()
- turtle.turnLeft()
- turtle.turnLeft()
- end
- local function InventoryIsFull()
- for i = 1, 16 do
- if turtle.getItemCount(i) == 0 then return false end
- end
- return true
- end
- ---@class WindmillManager
- ---@field LoopCount number
- ---@field DistanceFromLineStart number
- ---@field ReachedCrossDigPoint fun(self:WindmillManager)
- ---@field private __MoveOnEdge fun(self:WindmillManager, FirstTurnFunc:fun(), SecondTurnFunc:fun())
- ---@field private __MoveOnCrossLine fun(TurnFunc:fun(), FirstMoveCount:integer, SecondMoveCount:integer)
- ---@field private __MoveToChest fun(self:WindmillManager)
- ---@field private __MoveFromChest fun(self:WindmillManager)
- ---@field SaveItems fun(self:WindmillManager, DropList:"fun(Slot: integer):boolean")
- ---@field MoveForward fun(self:WindmillManager)
- ---@field ShouldPutTorch fun(self:WindmillManager):boolean
- ---@field GetLineDigCount fun(self:WindmillManager):integer
- local WindmillManager = {}
- WindmillManager.New = function ()
- return{
- LoopCount = 2,
- CurrentProcessLine = 1,
- DistanceFromLineStart = 0,
- ReachedCrossDigPoint = function(self)
- return 4 * self.LoopCount == self.DistanceFromLineStart
- end,
- __MoveOnEdge = function(self, FirstTurnFunc, SecondTurnFunc)
- for i = 1, self.LoopCount do
- MoveForwardImpl(4)
- FirstTurnFunc()
- MoveForwardImpl(4)
- if i == self.LoopCount then break end
- SecondTurnFunc()
- end
- end,
- __MoveOnCrossLine = function(TurnFunc, FirstMoveCount, SecondMoveCount)
- MoveForwardImpl(FirstMoveCount)
- TurnFunc()
- MoveForwardImpl(SecondMoveCount)
- end,
- __MoveToChest = function(self)
- self.TurnBack()
- local CrossDigPoint = self.LoopCount * 4
- if CrossDigPoint < self.DistanceFromLineStart then
- self.__MoveOnCrossLine(turtle.turnLeft, self.DistanceFromLineStart - CrossDigPoint, CrossDigPoint)
- else
- MoveForwardImpl(self.DistanceFromLineStart)
- turtle.turnLeft()
- self:__MoveOnEdge(turtle.turnLeft, turtle.turnRight)
- end
- end,
- __MoveFromChest = function(self)
- self.TurnBack()
- local CrossDigPoint = self.LoopCount * 4
- if CrossDigPoint < self.DistanceFromLineStart then
- self.__MoveOnCrossLine(turtle.turnLeft, CrossDigPoint, self.DistanceFromLineStart - CrossDigPoint)
- else
- self:__MoveOnEdge(turtle.turnRight, turtle.turnLeft)
- turtle.turnRight()
- MoveForwardImpl(self.DistanceFromLineStart)
- end
- end,
- SaveItems = function (self, AllowDropFunc)
- self:__MoveToChest()
- local CurrentSelectedSlot = turtle.getSelectedSlot()
- for i = 1, 16 do
- if AllowDropFunc(i) then
- turtle.select(i)
- turtle.dropUp()
- end
- end
- turtle.select(CurrentSelectedSlot)
- self:__MoveFromChest()
- end,
- MoveForward = function (self, ForwardCount)
- self.DistanceFromLineStart = self.DistanceFromLineStart + MoveForwardImpl(ForwardCount)
- end,
- ShouldPutTorch = function(self)
- return 1 == self.DistanceFromLineStart % TORCH_INTERVAL
- end,
- GetLineDigCount = function(self)
- return self.LoopCount * 8 - 5
- end,
- ToNext = function(self, ToNextLineFunc, ToNextLoopFunc)
- if self.CurrentProcessLine == 4 then
- ToNextLoopFunc()
- self.CurrentProcessLine = 1
- self.LoopCount = self.LoopCount + 1
- else
- ToNextLineFunc()
- self.CurrentProcessLine = self.CurrentProcessLine + 1
- end
- DistanceFromLineStart = 0
- end
- }
- end
- ---@class ItemManager
- ---@field __ReservedSlot number
- ---@field __AllowDropWhenExceed boolean
- ---@field private __AllowSave boolean
- ---@field private __Slots integer[]
- ---@field private __GetName fun(self: ItemManager):string
- ---@field private __Scanimpl fun(self: ItemManager, WhenFoundFunc: "fun(Slot: integer):void")
- ---@field Scan fun(self: ItemManager)
- ---@field private __GetItemSlot fun(self:ItemManager):integer|nil
- ---@field Place fun(self: ItemManager, place_fn: "fun():boolean,string"):boolean,string
- ---@field DropWhenExceed fun(self: ItemManager):void `AllowDropWhenExceed`が`true`のとき、手持ちに1slot分だけ残して後ろにアイテムをすべて吐き出す。`Scan`を呼んだのと同じ事後効果を持つ
- ---@field IsSavableSlot fun(self: ItemManager, Slot: integer):boolean
- local ItemManager = {}
- ---@param ReservedSlot number 管理対象アイテムが必ず存在するスロット番号
- ---@param AllowDropWhenExceed boolean 一定数ストックした後はドロップを許可するか
- ---@param AllowSave boolean 一定数ストックを残してチェストへの格納を許可するか
- ItemManager.New = function (ReservedSlot, AllowDropWhenExceed, AllowSave)
- local re = {
- __ReservedSlot = ReservedSlot,
- __AllowDropWhenExceed = AllowDropWhenExceed,
- __AllowSave = AllowSave,
- __Slots = {},
- ---@param self ItemManager
- ---@param WhenFoundFunc fun(Slot: integer)
- __Scanimpl = function (self, WhenFoundFunc)
- local init_slot = turtle.getSelectedSlot() -- 退避
- ---@type integer[]
- for i = 1, 16 do
- if i ~= self.__ReservedSlot then
- turtle.select(i)
- if turtle.compareTo(self.__ReservedSlot) then
- WhenFoundFunc(i)
- end
- end
- end
- turtle.select(init_slot)
- end,
- __GetName = function (self)
- return turtle.getItemDetail(self.__ReservedSlot).name
- end,
- ---@param self ItemManager
- Scan = function (self)
- ---@type integer[]
- local re = { self.__ReservedSlot }
- self:__Scanimpl(function (Slot) table.insert(re, Slot) end)
- self.__Slots = re
- PrintArray(self:__GetName(), self.__Slots)
- end,
- ---使用するスロット番号を求める
- ---
- ---末尾のスロットから使うようにする
- ---@param self ItemManager
- __GetItemSlot = function (self)
- if #self.__Slots == 0 then
- return nil
- elseif 1 < #self.__Slots then
- return self.__Slots[#self.__Slots]
- elseif turtle.getItemCount(self.__Slots[#self.__Slots]) == 1 then
- return nil
- end
- return self.__Slots[#self.__Slots]
- end,
- ---@param self ItemManager
- ---@param place_fn fun():boolean,string
- Place = function (self, place_fn)
- local slot = self:__GetItemSlot()
- if not slot then return false end
- local init_slot = turtle.getSelectedSlot() -- 退避
- debug_print(string.format("ItemManager(%s): %d -> %d", self:__GetName(), init_slot, slot))
- turtle.select(slot)
- local re, message = place_fn()
- PrintArray(self:__GetName(), self.__Slots)
- if re and turtle.getItemCount(self.__Slots[#self.__Slots]) == 0 then
- table.remove(self.__Slots, #self.__Slots)
- end
- debug_print(string.format("ItemManager(%s): %d -> %d", self:__GetName(), slot, init_slot))
- turtle.select(init_slot)
- return re, message
- end,
- ---`AllowDropWhenExceed`が`true`のとき、手持ちに1slot分だけ残して後ろにアイテムをすべて吐き出す。`Scan`を呼んだのと同じ事後効果を持つ
- ---@param self ItemManager
- DropWhenExceed = function (self)
- if not self.__AllowDropWhenExceed then
- return
- end
- self:__Scanimpl(function (Slot)
- TurnBack()
- turtle.drop()
- TurnBack()
- end)
- self.__Slots = { self.__ReservedSlot }
- end,
- ---@param self ItemManager
- ---@param Slot integer
- IsSavableSlot = function(self, Slot)
- if self.__AllowSave then
- return Slot ~= self.__ReservedSlot
- end
- for _, value in ipairs(self.__Slots) do
- if Slot == value then
- return false
- end
- end
- return true
- end
- }
- re:Scan()
- return re
- end
- local StoneManager = ItemManager.New(2, true, true)
- local TorchManager = ItemManager.New(1, false, false)
- ---@param Slot integer
- local function IsSavableSlot(Slot)
- --TorchManagerのほうの探索はforが回るので重い
- return StoneManager:IsSavableSlot(Slot) and TorchManager:IsSavableSlot(Slot)
- end
- local Windmill = WindmillManager.New()
- local function SaveItems()
- WindmillManager:SaveItems(IsSavableSlot)
- end
- local function DigForward()
- if turtle.detect() and InventoryIsFull() then SaveItems() end
- while turtle.detect() do
- local Flag, Message = turtle.dig()
- if not Flag then return Flag, Message end
- end
- return true
- end
- local function DigUp()
- if InventoryIsFull() then SaveItems() end
- return turtle.digUp()
- end
- ---@param TryCount integer
- local function DigAndMoveForward(TryCount)
- for i = 1, TryCount do
- DigForward()
- Windmill:MoveForward(1)
- DigUp()
- if not turtle.detectDown() then StoneManager:Place(turtle.placeDown) end
- end
- end
- local function PlaceTorchToBack()
- TurnBack()
- debug_print(TorchManager:__GetName())
- TorchManager:Place(turtle.place)
- TurnBack()
- end
- local function NormalFlow()
- local DigMaxCount = Windmill:GetLineDigCount()
- debug_print(string.format("NormalFlow:: Dig count: %d", DigMaxCount))
- for i = 1, DigMaxCount do
- DigAndMoveForward(1)
- if i == 1 then
- TurnBack()
- TorchManager:Place(turtle.place)
- TurnBack()
- end
- if Windmill:ReachedCrossDigPoint() then
- turtle.turnRight()
- for j = 1, 3 do
- -- 進行マス数カウントやインベントリチェックが行われると戻るコードが働かないのでラッパー不使用
- turtle.dig()
- turtle.forward()
- turtle.digUp()
- end
- for j = 1, 3 do turtle.back() end
- turtle.turnLeft()
- end
- if Windmill:ShouldPutTorch() then
- StoneManager:DropWhenExceed()
- PlaceTorchToBack()
- end
- end
- StoneManager:DropWhenExceed()
- end
- local function ToNextLineLatterHalfProcess()
- turtle.turnLeft()
- DigAndMoveForward(4)
- TurnBack()
- for i = 1, 4 do
- turtle.forward()
- if i == 1 then PlaceTorchToBack() end
- end
- end
- local function ToNextLine()
- for i = 1, 5 do
- DigAndMoveForward(1)
- if i == 2 then PlaceTorchToBack() end
- end
- ToNextLineLatterHalfProcess()
- end
- local function ToNextLoopLatterHalfProcess()
- turtle.turnRight()
- turtle.dig()
- turtle.forward()
- turtle.digDown()
- turtle.down()
- DigAndMoveForward(3)
- ToNextLineLatterHalfProcess()
- end
- local function Initialize()
- local CommonProcessOnFirstLineAndOthers = function()
- turtle.turnLeft()
- DigAndMoveForward(4)
- turtle.back()
- TorchManager:Place(turtle.place)
- TurnBack()
- DigAndMoveForward(4)
- PlaceTorchToBack()
- DigAndMoveForward(3)
- end
- debug_print("Initialize:: phase 1")
- DigAndMoveForward(4)
- CommonProcessOnFirstLineAndOthers()
- debug_print("Initialize:: phase 2")
- for i = 1, 4 do
- CommonProcessOnFirstLineAndOthers()
- turtle.turnRight()
- if turtle.detect() then
- debug_print("Initialize:: detected")
- DigAndMoveForward(3)
- for j = 1, 3 do turtle.back() end
- end
- turtle.turnLeft()
- DigAndMoveForward(4)
- end
- debug_print("Initialize:: phase 3")
- turtle.turnLeft()
- DigAndMoveForward(1)
- PlaceTorchToBack()
- DigAndMoveForward(3)
- debug_print("Initialize:: phase 4")
- turtle.turnRight()
- DigAndMoveForward(1)
- PlaceTorchToBack()
- DigAndMoveForward(3)
- ToNextLineLatterHalfProcess()
- end
- local function ToNextLoop()
- turtle.up()
- MoveForwardImpl(5)
- turtle.turnLeft()
- MoveForwardImpl(4)
- ToNextLoopLatterHalfProcess()
- end
- Initialize()
- while true do
- NormalFlow()
- Windmill:ToNext(ToNextLine, ToNextLoop)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement