Advertisement
yumetodo

Untitled

May 31st, 2021
889
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.86 KB | None | 0 0
  1. -- 高さ2
  2. -- a0 = 9
  3. -- an+1 = an + 8
  4. -- 最初の周回は1週目
  5.  
  6. local TORCH_INTERVAL = 12
  7.  
  8. ---@param ForwardCount integer
  9. local function MoveForwardImpl(ForwardCount)
  10.     for i = 1, ForwardCount do
  11.         if not turtle.forward() then return i - 1 end
  12.     end
  13.     return ForwardCount
  14. end
  15.  
  16. local function TurnBack()
  17.     turtle.turnLeft()
  18.     turtle.turnLeft()
  19. end
  20.  
  21. local function InventoryIsFull()
  22.     for i = 1, 16 do
  23.         if turtle.getItemCount(i) == 0 then return false end
  24.     end
  25.     return true
  26. end
  27.  
  28. ---@class WindmillManager
  29. ---@field LoopCount number
  30. ---@field DistanceFromLineStart number
  31. ---@field ReachedCrossDigPoint fun(self:WindmillManager)
  32. ---@field private __MoveOnEdge fun(self:WindmillManager, FirstTurnFunc:fun(), SecondTurnFunc:fun())
  33. ---@field private __MoveOnCrossLine fun(TurnFunc:fun(), FirstMoveCount:integer, SecondMoveCount:integer)
  34. ---@field private __MoveToChest fun(self:WindmillManager)
  35. ---@field private __MoveFromChest fun(self:WindmillManager)
  36. ---@field SaveItems fun(self:WindmillManager, DropList:"fun(Slot: integer):boolean")
  37. ---@field MoveForward fun(self:WindmillManager)
  38. ---@field ShouldPutTorch fun(self:WindmillManager):boolean
  39. ---@field GetLineDigCount fun(self:WindmillManager):integer
  40. local WindmillManager = {}
  41. WindmillManager.New = function ()
  42.     return{
  43.         LoopCount = 2,
  44.         CurrentProcessLine = 1,
  45.         DistanceFromLineStart = 0,
  46.         ReachedCrossDigPoint = function(self)
  47.             return 4 * self.LoopCount == self.DistanceFromLineStart
  48.         end,
  49.         __MoveOnEdge = function(self, FirstTurnFunc, SecondTurnFunc)
  50.             for i = 1, self.LoopCount do
  51.                 MoveForwardImpl(4)
  52.                 FirstTurnFunc()
  53.                 MoveForwardImpl(4)
  54.                 if i == self.LoopCount then break end
  55.                 SecondTurnFunc()
  56.             end
  57.         end,
  58.         __MoveOnCrossLine = function(TurnFunc, FirstMoveCount, SecondMoveCount)
  59.             MoveForwardImpl(FirstMoveCount)
  60.             TurnFunc()
  61.             MoveForwardImpl(SecondMoveCount)
  62.         end,
  63.         __MoveToChest = function(self)
  64.             self.TurnBack()
  65.             local CrossDigPoint = self.LoopCount * 4
  66.             if  CrossDigPoint < self.DistanceFromLineStart then
  67.                 self.__MoveOnCrossLine(turtle.turnLeft, self.DistanceFromLineStart - CrossDigPoint, CrossDigPoint)
  68.             else
  69.                 MoveForwardImpl(self.DistanceFromLineStart)
  70.                 turtle.turnLeft()
  71.                 self:__MoveOnEdge(turtle.turnLeft, turtle.turnRight)
  72.             end
  73.         end,
  74.         __MoveFromChest = function(self)
  75.             self.TurnBack()
  76.             local CrossDigPoint = self.LoopCount * 4
  77.             if  CrossDigPoint < self.DistanceFromLineStart then
  78.                 self.__MoveOnCrossLine(turtle.turnLeft, CrossDigPoint, self.DistanceFromLineStart - CrossDigPoint)
  79.             else
  80.                 self:__MoveOnEdge(turtle.turnRight, turtle.turnLeft)
  81.                 turtle.turnRight()
  82.                 MoveForwardImpl(self.DistanceFromLineStart)
  83.             end
  84.         end,
  85.         SaveItems = function (self, AllowDropFunc)
  86.             self:__MoveToChest()
  87.             local CurrentSelectedSlot = turtle.getSelectedSlot()
  88.             for i = 1, 16 do
  89.                 if AllowDropFunc(i) then
  90.                     turtle.select(i)
  91.                     turtle.dropUp()
  92.                 end
  93.             end
  94.             turtle.select(CurrentSelectedSlot)
  95.             self:__MoveFromChest()
  96.         end,
  97.         MoveForward = function (self, ForwardCount)
  98.             self.DistanceFromLineStart = self.DistanceFromLineStart + MoveForwardImpl(ForwardCount)
  99.         end,
  100.         ShouldPutTorch = function(self)
  101.             return 1 == self.DistanceFromLineStart % TORCH_INTERVAL
  102.         end,
  103.         GetLineDigCount = function(self)
  104.             return self.LoopCount * 8 - 5
  105.         end,
  106.         ToNext = function(self, ToNextLineFunc, ToNextLoopFunc)
  107.             if self.CurrentProcessLine == 4 then
  108.                 ToNextLoopFunc()
  109.                 self.CurrentProcessLine = 1
  110.                 self.LoopCount = self.LoopCount + 1
  111.             else
  112.                 ToNextLineFunc()
  113.                 self.CurrentProcessLine = self.CurrentProcessLine + 1
  114.             end
  115.         end
  116.     }
  117. end
  118.  
  119. ---@param arr any[]
  120. local function PrintArray(arr)
  121.     local re = "["
  122.     for i, v in ipairs(arr) do
  123.         if i ~= 1 then re = re.."," end
  124.         re = re..v
  125.     end
  126.     print(re.."]")
  127. end
  128.  
  129. ---@class ItemManager
  130. ---@field __ReservedSlot number
  131. ---@field __AllowDropWhenExceed boolean
  132. ---@field private __AllowSave boolean
  133. ---@field private __Slots integer[]
  134. ---@field private __Scanimpl fun(self: ItemManager, WhenFoundFunc: "fun(Slot: integer):void")
  135. ---@field Scan fun(self: ItemManager)
  136. ---@field private __GetItemSlot fun(self:ItemManager):integer|nil
  137. ---@field Place fun(self: ItemManager, place_fn: "fun():boolean,string"):boolean,string
  138. ---@field DropWhenExceed fun(self: ItemManager):void `AllowDropWhenExceed`が`true`のとき、手持ちに1slot分だけ残して後ろにアイテムをすべて吐き出す。`Scan`を呼んだのと同じ事後効果を持つ
  139. ---@field IsSavableSlot fun(self: ItemManager, Slot: integer):boolean
  140. local ItemManager = {}
  141. ---@param ReservedSlot number 管理対象アイテムが必ず存在するスロット番号
  142. ---@param AllowDropWhenExceed boolean 一定数ストックした後はドロップを許可するか
  143. ---@param AllowSave boolean 一定数ストックを残してチェストへの格納を許可するか
  144. ItemManager.New = function (ReservedSlot, AllowDropWhenExceed, AllowSave)
  145.     local re = {
  146.         __ReservedSlot = ReservedSlot,
  147.         __AllowDropWhenExceed = AllowDropWhenExceed,
  148.         __AllowSave = AllowSave,
  149.         __Slots = {},
  150.         ---@param self ItemManager
  151.         ---@param WhenFoundFunc fun(Slot: integer)
  152.         __Scanimpl = function (self, WhenFoundFunc)
  153.             local init_slot = turtle.getSelectedSlot() -- 退避
  154.             ---@type integer[]
  155.             for i = 1, 16 do
  156.                 if i ~= self.__ReservedSlot then
  157.                     turtle.select(i)
  158.                     if turtle.compareTo(self.__ReservedSlot) then
  159.                         WhenFoundFunc(i)
  160.                     end
  161.                 end
  162.             end
  163.             turtle.select(init_slot)
  164.         end,
  165.         ---@param self ItemManager
  166.         Scan = function (self)
  167.             ---@type integer[]
  168.             local re = { self.__ReservedSlot }
  169.             self:__Scanimpl(function (Slot) table.insert(re, re) end)
  170.             self.__Slots = re
  171.             PrintArray(self.__Slots)
  172.         end,
  173.         ---使用するスロット番号を求める
  174.         ---
  175.         ---末尾のスロットから使うようにする
  176.         ---@param self ItemManager
  177.         __GetItemSlot = function (self)
  178.             if #self.__Slots == 0 then
  179.                 return nil
  180.             elseif 1 < #self.__Slots then
  181.                 return #self.__Slots
  182.             elseif turtle.getItemCount(self.__Slots[#self.__Slots]) == 1 then
  183.                 return nil
  184.             end
  185.             return #self.__Slots
  186.         end,
  187.         ---@param self ItemManager
  188.         ---@param place_fn fun():boolean,string
  189.         Place = function (self, place_fn)
  190.             local slot = self:__GetItemSlot()
  191.             if not slot then return false end
  192.             local init_slot = turtle.getSelectedSlot() -- 退避
  193.             turtle.select(slot)
  194.             local re, message = place_fn()
  195.             PrintArray(self.__Slots)
  196.             if re and turtle.getItemCount(self.__Slots[#self.__Slots]) == 0 then
  197.                 table.remove(self.__Slots, #self.__Slots)
  198.             end
  199.             turtle.select(init_slot)
  200.             return re, message
  201.         end,
  202.         ---`AllowDropWhenExceed`が`true`のとき、手持ちに1slot分だけ残して後ろにアイテムをすべて吐き出す。`Scan`を呼んだのと同じ事後効果を持つ
  203.         ---@param self ItemManager
  204.         DropWhenExceed = function (self)
  205.             if not self.__AllowDropWhenExceed then
  206.                 return
  207.             end
  208.             self:__Scanimpl(function (Slot)
  209.                 TurnBack()
  210.                 turtle.drop()
  211.                 TurnBack()
  212.             end)
  213.             self.__Slots = { self.__ReservedSlot }
  214.         end,
  215.         ---@param self ItemManager
  216.         ---@param Slot integer
  217.         IsSavableSlot = function(self, Slot)
  218.             if self.__AllowSave then
  219.                 return Slot ~= self.__ReservedSlot
  220.             end
  221.             for _, value in ipairs(self.__Slots) do
  222.                 if Slot == value then
  223.                     return false
  224.                 end
  225.             end
  226.             return true
  227.         end
  228.     }
  229.     re:Scan()
  230.     return re
  231. end
  232.  
  233. local StoneManager = ItemManager.New(2, true, true)
  234. local TorchManager = ItemManager.New(1, false, false)
  235. ---@param Slot integer
  236. local function IsSavableSlot(Slot)
  237.     --TorchManagerのほうの探索はforが回るので重い
  238.     return StoneManager:IsSavableSlot(Slot) and TorchManager:IsSavableSlot(Slot)
  239. end
  240.  
  241. local Windmill = WindmillManager.New()
  242.  
  243. local function SaveItems()
  244.     WindmillManager:SaveItems(IsSavableSlot)
  245. end
  246.  
  247. local function DigForward()
  248.     if turtle.detect() and InventoryIsFull() then SaveItems() end
  249.     while turtle.detect() do
  250.         local Flag, Message = turtle.dig()
  251.         if not Flag then return Flag, Message end
  252.     end
  253.     return true
  254. end
  255.  
  256. local function DigUp()
  257.     if InventoryIsFull() then SaveItems() end
  258.     return turtle.digUp()
  259. end
  260.  
  261. ---@param TryCount integer
  262. local function DigAndMoveForward(TryCount)
  263.     for i = 1, TryCount do
  264.         DigForward()
  265.         Windmill:MoveForward(1)
  266.         DigUp()
  267.         if not turtle.detectDown() then StoneManager:Place(turtle.placeDown) end
  268.     end
  269. end
  270.  
  271. local function NormalFlow()
  272.     local DigMaxCount = Windmill:GetLineDigCount()
  273.     for i = 1, DigMaxCount do
  274.         DigAndMoveForward(1)
  275.         if i == 1 then
  276.             TurnBack()
  277.             TorchManager:Place(turtle.place)
  278.             TurnBack()
  279.         end
  280.         if Windmill:ReachedCrossDigPoint() then
  281.             turtle.turnRight()
  282.             for j = 1, 3 do
  283.                 -- 進行マス数カウントやインベントリチェックが行われると戻るコードが働かないのでラッパー不使用
  284.                 turtle.dig()
  285.                 turtle.forward()
  286.                 turtle.digUp()
  287.             end
  288.             for j = 1, 3 do turtle.back() end
  289.             turtle.turnLeft()
  290.         end
  291.         if Windmill:ShouldPutTorch() then
  292.             StoneManager:DropWhenExceed()
  293.             TurnBack()
  294.             TorchManager:Place(turtle.place)
  295.             TurnBack()
  296.         end
  297.     end
  298.     StoneManager:DropWhenExceed()
  299. end
  300.  
  301. local function PlaceTorchToBack()
  302.     TurnBack()
  303.     TorchManager:Place(turtle.place)
  304.     TurnBack()
  305. end
  306.  
  307. local function ToNextLineLatterHalfProcess()
  308.     turtle.turnLeft()
  309.     for i = 1, 4 do DigAndMoveForward(1) end
  310.     TurnBack()
  311.     for i = 1, 4 do
  312.         turtle.forward()
  313.         if i == 1 then PlaceTorchToBack() end
  314.     end
  315. end
  316.  
  317. local function ToNextLine()
  318.     for i = 1, 5 do
  319.         DigAndMoveForward(1)
  320.         if i == 2 then PlaceTorchToBack() end
  321.     end
  322.     ToNextLineLatterHalfProcess()
  323. end
  324.  
  325. local function ToNextLoopLatterHalfProcess()
  326.     turtle.turnRight()
  327.     turtle.dig()
  328.     turtle.forward()
  329.     turtle.digDown()
  330.     turtle.down()
  331.     DigAndMoveForward(3)
  332.     ToNextLineLatterHalfProcess()
  333. end
  334.  
  335. local function Initialize()
  336.     local TurningPointProcessByInitialize = function()
  337.         turtle.turnLeft()
  338.         DigAndMoveForward(4)
  339.         turtle.back()
  340.         TorchManager:Place(turtle.place)
  341.         TurnBack()
  342.         DigAndMoveForward(3)
  343.         turtle.turnRight()
  344.         if turtle.detect() then
  345.             -- print("Initialize:: detected")
  346.             DigAndMoveForward(3)
  347.             for i = 1, 3 do turtle.back() end
  348.         end
  349.         turtle.turnLeft()
  350.         -- print("Initialize:: after when detected")
  351.         DigAndMoveForward(1)
  352.         TurnBack()
  353.         TorchManager:Place(turtle.place)
  354.         TurnBack()
  355.     end
  356.     -- print("Initialize:: phase 1")
  357.     DigAndMoveForward(4)
  358.     TurningPointProcessByInitialize()
  359.     -- print("Initialize:: phase 2")
  360.     DigAndMoveForward(3)
  361.     TurningPointProcessByInitialize()
  362.     for i = 1, 3 do
  363.         DigAndMoveForward(i == 3 and 6 or 7)
  364.         if i == 3 then break end
  365.         TurningPointProcessByInitialize()
  366.     end
  367.     ToNextLoopLatterHalfProcess()
  368. end
  369.  
  370. local function ToNextLoop()
  371.     turtle.up()
  372.     MoveForwardImpl(5)
  373.     turtle.turnLeft()
  374.     MoveForwardImpl(4)
  375.     ToNextLoopLatterHalfProcess()
  376. end
  377.  
  378. Initialize()
  379. while true do
  380.     NormalFlow()
  381.     Windmill:ToNext(ToNextLine, ToNextLoop)
  382. end
  383.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement