Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[TODO LIST
- 01. DONE make prompts blink/countdown to make them stand out to the user
- 02. DONE modify FindHome() to prevent turtle from running away
- 03. DONE modify RunMenu() so that the printing code is more compact
- 04. DONE modify menu routine to have +duration/+effect/splash sub menus for each of the primary potions
- 05. DONE allow for 'n' dispensers to be used
- 06. DONE modify menu to indicate what potions were selected for inactive shelves
- 07. DONE make the apothecary double sided for increased capacity
- 08. DONE allow for choosing of build position above/in/below ground
- 09. DONE break up Main() into simpler functions ie select, build, brew
- 10. DONE turtle identifies a fully stocked apothecary and sleeps longer
- 11. DONE make the 'are you sure?' feature remember what you were unsure about
- 12. TODO write more comprehensive instructions (i.e. write a manual)
- 13. DONE update potions list to include latest update
- ]]
- function Main() --Control center for the program DONE
- local potionList, ApothecarySize = GetPotionList()
- Build(ApothecarySize)
- Brew(potionList, ApothecarySize)
- end
- function GetPotionList() --acquires the potion list from file or from user DONE
- local size, potionList
- if DoesOldSaveExist() then
- if IsNewSetWanted() then
- size = GetSize()
- potionList = RunMenu(size,{},{})
- SaveFile(potionList)
- else
- potionList = LoadFile()
- size = #potionList
- end
- else
- size = GetSize()
- potionList = RunMenu(size,{},{})
- SaveFile(potionList)
- end
- return potionList, size
- end
- function Build(size) --constructs the apothecary if required DONE
- if IsBuilderWanted() then
- local orientation = SelectBuildOrientation()
- WaitForInventory(size)
- SurveySite(size,orientation)
- AutoBuilder(size)
- end
- end
- function Brew(potionList, ApothecarySize) --brews the potions DONE
- local inventory, reservedSlots = DefineInventory(potionList)
- FindHome(ApothecarySize)
- CleanUp(reservedSlots)
- local shelfNo = 1
- while true do
- local fullyStocked = true
- if IsShelfFull(shelfNo, reservedSlots) then
- fullyStocked = false
- else
- if IsEnoughIngredients(potionList[shelfNo], inventory) then
- FillBottles(reservedSlots)
- BrewPotion(potionList[shelfNo],inventory)
- RestockShelf(shelfNo)
- else
- RestockTurtle(reservedSlots)
- end
- end
- shelfNo = LoopVariable(shelfNo, ApothecarySize, "+")
- if shelfNo == 1 and fullyStocked then
- Rest(300,"sleep","Fully stocked.")
- elseif shelfNo == 1 then
- Rest(60,"sleep","Cycle complete.")
- end
- end
- end
- --GetPotionList---------------------------------------------------------------------------------------------------------------
- function DoesOldSaveExist() --Is there an old save file existing? DONE
- print("Searching for existing save file..")
- local fileName = os.getComputerID()..".potions" --computer ID with the extension .potions
- local file = io.open(fileName,"r")
- if file == nil then
- return false
- else
- file:close()
- return true
- end
- end
- function IsNewSetWanted() --do you need to choose a new potion set? DONE
- local timeLeft = 20
- local timeInterval = 1 --in seconds
- while timeLeft > 0 do
- local timer = os.startTimer(timeInterval)
- term.clear() term.setCursorPos(1,1)
- print("Would you like to select a new set of potions?? (Y/N) \nProgram will continue in "..timeLeft.." seconds")
- timeLeft = timeLeft - timeInterval
- local event, result = os.pullEvent()
- if event == "key" then
- if result == keys.enter or result == keys.y then return true
- elseif result == keys.n then return false
- end
- end
- end
- return false
- end
- function GetSize() --ask user what size the apothecary should be DONE
- term.clear() term.setCursorPos(1,1)
- local maximum = 12 --maximum due to building materials is 17
- local minimum = 4
- local default = minimum
- while true do
- print("How many different types of potion do you wish to have in stock?")
- print("NOTE: this will change the size of the apothecary")
- print("Max = "..maximum..". Min = "..minimum..". Default = "..default)
- local userInput = string.lower(read())
- if tonumber(userInput) ~= nil then
- if tonumber(userInput) >= minimum and tonumber(userInput) <= maximum then
- return tonumber(userInput)
- else
- term.clear() term.setCursorPos(1,1)
- print("Outside of limits. Try again")
- end
- else
- term.clear() term.setCursorPos(1,1)
- print("Not an integer. Try again")
- end
- end
- end
- function RunMenu(size,potIDforShelfNo,recipeOfShelfNo) --choose a potion class and then tailor it --DONE
- local potionType = {} --2D array of basic potion types {name, base ingr, [second ingr,] maxLVL, maxDUR}
- local XlocOfPotionNo = {} --vector of x locations for each potion
- local YlocOfPotionNo = {} --vector of y locations for each potion
- local currShelfID = 1 --starting choice
- local topRow = 5 --indicates the length of the headings before potions can be printed
- potionType[01] = {"Water Breathing","puff.fish",1,009}
- potionType[02] = {"Fire Resistance","mag.cream",1,009}
- potionType[03] = {"Swiftness", "sugar ",009,009}
- potionType[04] = {"Slowness", "sugar ","fm.sp.eye",009,009}
- potionType[05] = {"Instant Healing","gls.melon",009,1}
- potionType[06] = {"Instant Harming","spiderEye","fm.sp.eye",009,1}
- potionType[07] = {"Regeneration", "ghastTear",009,009}
- potionType[08] = {"Poison", "spiderEye",009,009}
- potionType[09] = {"Night Vision", "gldCarrot",1,009}
- potionType[10] = {"Invisibility", "gldCarrot","fm.sp.eye",1,009}
- potionType[11] = {"Strength", "blzPowder",009,009}
- potionType[12] = {"Weakness", "blzPowder","fm.sp.eye",009,009}
- local itemsPP = math.ceil(#potionType/2) --number of potions that can fit in a column
- for potionID = 1,#potionType do
- local colIndex = math.ceil(potionID/itemsPP)-1
- local rowIndex = potionID - colIndex*itemsPP
- XlocOfPotionNo[potionID] = colIndex*20 + 1
- YlocOfPotionNo[potionID] = rowIndex + topRow
- end
- if #potIDforShelfNo ~= size or #recipeOfShelfNo ~= size then --set selection to the default
- potIDforShelfNo = {}
- recipeOfShelfNo = {}
- for i = 1,size do
- potIDforShelfNo[i] = i
- if #potionType[i] == 4 then
- recipeOfShelfNo[i] = {potionType[i][1], potionType[i][2]}
- else
- recipeOfShelfNo[i] = {potionType[i][1], potionType[i][2], potionType[i][3]}
- end
- end
- end
- local currShelfID = 1
- repeat
- term.clear() term.setCursorPos(1,1)
- --Print the headings
- print("Select your potions: (UDLR Enter)\nPress TAB to customise")
- print(" <<< Shelf "..currShelfID.." of "..#potIDforShelfNo.." >>>")
- PrintCentered(recipeOfShelfNo[currShelfID][1])
- --Print the potions
- for potionID = 1,#potionType do
- term.setCursorPos(XlocOfPotionNo[potionID], YlocOfPotionNo[potionID])
- print(" "..potionType[potionID][1])
- end
- --Print the indicators
- term.setCursorPos(XlocOfPotionNo[potIDforShelfNo[currShelfID]], YlocOfPotionNo[potIDforShelfNo[currShelfID]])
- print(">>>")
- --Print the numbers
- for i = 1,#potIDforShelfNo do
- term.setCursorPos(XlocOfPotionNo[potIDforShelfNo[i]], YlocOfPotionNo[potIDforShelfNo[i]])
- print(i)
- end
- --Receive and process keyboard input
- local eventtype, key = os.pullEvent() --get keyboard input
- if key == 200 then --up key
- local currPotID = potIDforShelfNo[currShelfID]
- currPotID = LoopVariable(currPotID, #potionType, "-")
- --copy and overwrite the ingredients to the recipe matrix
- recipeOfShelfNo[currShelfID] = {}
- for i = 1,#potionType[currPotID] -2 do
- recipeOfShelfNo[currShelfID][i] = potionType[currPotID][i]
- end
- potIDforShelfNo[currShelfID] = currPotID
- elseif key == 208 then --down key
- local currPotID = potIDforShelfNo[currShelfID]
- currPotID = LoopVariable(currPotID, #potionType, "+")
- --copy and overwrite the ingredients to the recipe matrix
- recipeOfShelfNo[currShelfID] = {}
- for i = 1,#potionType[currPotID] -2 do
- recipeOfShelfNo[currShelfID][i] = potionType[currPotID][i]
- end
- potIDforShelfNo[currShelfID] = currPotID
- elseif key == 205 then --right key
- currShelfID = LoopVariable(currShelfID, size, "+")
- elseif key == 203 then --left key
- currShelfID = LoopVariable(currShelfID, size, "-")
- elseif key == 15 then --tab key
- local currPotID = potIDforShelfNo[currShelfID]
- --copy and overwrite the ingredients to the recipe matrix
- recipeOfShelfNo[currShelfID] = {}
- for i = 1,#potionType[currPotID] -2 do
- recipeOfShelfNo[currShelfID][i] = potionType[currPotID][i]
- end
- potIDforShelfNo[currShelfID] = currPotID
- local x = XlocOfPotionNo[currPotID]
- local y = YlocOfPotionNo[currPotID]
- local maxLVL = potionType[currPotID][#potionType[currPotID]-1]
- local maxDUR = potionType[currPotID][#potionType[currPotID]]
- recipeOfShelfNo[currShelfID] = TailorPotion(x, y, maxLVL, maxDUR, recipeOfShelfNo[currShelfID])
- end
- until key == 28
- --print the user selection
- term.clear() term.setCursorPos(1,1)
- local lowestLine = 1 --used in finding where to print the "are you sure"
- print("You have selected:")
- for i = 1,#potIDforShelfNo do
- if YlocOfPotionNo[i]-3 > lowestLine then lowestLine = YlocOfPotionNo[i]-3 end
- term.setCursorPos(XlocOfPotionNo[i], YlocOfPotionNo[i]-3)
- if size > 6 then --shorten the printouts to fit 2 columns to a page
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Water Breathing","WtrBrea")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Fire Resistance","FireRes")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Swiftness" ,"Speed")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Slowness" ,"Slowness")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Instant Healing","InstHeal")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Instant Harming","InstHarm")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Regeneration" ,"Regen.")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Poison" ,"Poison")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Night Vision" ,"NightVis")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Invisibility" ,"Invis.")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Strength" ,"Strength")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Weakness" ,"Weakness")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Duration " ,"Dur")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"Level " ,"lvl")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1]," (splash)" ,"s")
- recipeOfShelfNo[i][1] = string.gsub(recipeOfShelfNo[i][1],"(splash)" ,"s")
- print(" "..NumToString(i, 2)..":"..string.sub(recipeOfShelfNo[i][1],1,15))
- else
- print(" "..NumToString(i, 2)..":"..recipeOfShelfNo[i][1])
- end
- end
- term.setCursorPos(1,lowestLine)
- print("\nAre you happy with this selection?(Y/N)")
- input = string.upper(read())
- term.clear() term.setCursorPos(1,1)
- if input == "Y" then
- return recipeOfShelfNo
- else
- return RunMenu(size,potIDforShelfNo,recipeOfShelfNo)
- end
- end
- function TailorPotion(curX, curY, maxLevel, maxDuration, baseRecipe) --allows customization of level, duration & splash --DONE
- local category = 1 --1=level, 2=duration, 3=splash
- local level = 1
- local duration = 1
- local splash = false
- --find where to print the menu
- local maxX, maxY = term.getSize()
- local menuX, menuY
- local sizeX, sizeY = 17, 5
- local spaceX, spaceY = maxX-curX, maxY-curY
- if spaceX > sizeX then
- menuX = curX
- else
- menuX = curX - sizeX + spaceX
- end
- if spaceY > sizeY then
- menuY = curY + 1
- else
- menuY = curY - sizeY
- end
- repeat --until keypress = enter or tab
- --print the menu
- if splash == true then splashString = "[x]" else splashString = "[ ]" end
- term.setCursorPos(menuX, menuY)
- print("#=(UDLR Enter)==#")
- term.setCursorPos(menuX, menuY+1)
- print("| Level:"..NumToString(level,1).." |")
- term.setCursorPos(menuX, menuY+2)
- print("| Duration:"..NumToString(duration,1).." |")
- term.setCursorPos(menuX, menuY+3)
- print("| Splash:"..splashString.." |")
- term.setCursorPos(menuX, menuY+4)
- print("#===============#")
- if category == 1 then term.setCursorPos(menuX +1,menuY +1) end
- if category == 2 then term.setCursorPos(menuX +1,menuY +2) end
- if category == 3 then term.setCursorPos(menuX +1,menuY +3) end
- print(">")
- --Recieve and process keyboard input
- local eventtype, key = os.pullEvent() --get keyboard input
- if key == 203 then --left key changes category
- if category == 1 then level = LoopVariable(level, maxLevel, "-") duration = 1
- elseif category == 2 then duration = LoopVariable(duration, maxDuration, "-") level = 1
- elseif category == 3 then splash = not splash
- end
- elseif key == 205 then --right key changes category
- if category == 1 then level = LoopVariable(level, maxLevel, "+") duration = 1
- elseif category == 2 then duration = LoopVariable(duration, maxDuration, "+") level = 1
- elseif category == 3 then splash = not splash
- end
- elseif key == 208 then --down key changes number
- category = LoopVariable(category, 3, "+")
- elseif key == 200 then --up key changes number
- category = LoopVariable(category, 3, "-")
- end
- until key == 28 or key == 15 --if keypress = 'enter' or 'tab'
- --tailor the name of the potion
- local suffix = ""
- if duration > 1 then suffix = "Duration "..duration.." " end
- if level > 1 then suffix = "Level "..level.." " end
- if splash == true then suffix = suffix.."(splash)" end
- baseRecipe[1] = baseRecipe[1].." "..suffix
- --adjust the recipe based on the users input
- for i = 1,level-1,1 do baseRecipe[#baseRecipe+1] = "glowstone" end
- for i = 1,duration-1,1 do baseRecipe[#baseRecipe+1] = "redstone " end
- if splash then baseRecipe[#baseRecipe+1] = "gunpowder" end
- return baseRecipe
- end
- function SaveFile(potionShortList) --saves the potion list as an 8 bit number in a file DONE
- print("Saving potion set to file..")
- local fileName = os.getComputerID()..".potions" --computer ID with the extension .potions
- local file = fs.open(fileName,"w")
- for potionNo = 1,#potionShortList do
- local potionString = ""
- for potionItem = 1,#potionShortList[potionNo],1 do
- potionString = potionString..potionShortList[potionNo][potionItem]
- end
- file.writeLine(potionString)
- end
- file:close()
- end
- function LoadFile() --loads the data from file and returns the potion list DONE
- print("Loading potions set from existing file..")
- local fileName = os.getComputerID()..".potions" --computer ID with the extension .potions
- local file = fs.open(fileName,"r")
- local potionShortList = {}
- local dataString = file.readLine()
- local potionNumber = 0
- while dataString ~= null do
- potionNumber = potionNumber + 1
- potionShortList[potionNumber] = {}
- potionShortList[potionNumber][1] = dataString:sub(1,10) --record the potion name
- for potionItem = 1,(dataString:len()-10)/9 do
- local startChar = potionItem*9 + 1 + 1
- local endChar = potionItem*9 + 1 + 9
- potionShortList[potionNumber][potionItem+1] = dataString:sub(startChar,endChar)
- end
- dataString = file.readLine()
- end
- file:close()
- return potionShortList
- end
- --Build-----------------------------------------------------------------------------------------------------------------------
- function IsBuilderWanted() --Ask the user if they require instructions DONE
- local timeLeft = 20
- local timeInterval = 1 --in seconds
- while timeLeft > 0 do
- local timer = os.startTimer(timeInterval)
- term.clear() term.setCursorPos(1,1)
- print("Would you like to use the builder program?? (Y/N) \nProgram will continue in "..timeLeft.." seconds")
- timeLeft = timeLeft - timeInterval
- local event, result = os.pullEvent()
- if event == "key" then
- if result == keys.enter or result == keys.y then return true
- elseif result == keys.n then return false
- end
- end
- end
- return false
- end
- function SelectBuildOrientation() --Asks the user how the apothecary will lie in the ground DONE
- local depth
- term.clear() term.setCursorPos(1,1)
- while true do
- print("How would you like the apothecary to be built? 0|1|2")
- print[[
- [0] ABOVE GROUND [][][][][]
- ____[][][][][]____
- [1] IN GROUND ____[][][][][]____
- [][][][][]
- [2] BELOW GROUND ____ ____
- [][][][][]
- [][][][][] ]]
- depth = read()
- if tonumber(depth) == nil or 0 > tonumber(depth) or tonumber(depth) > 2 then
- term.clear() term.setCursorPos(1,1)
- print("INVALID INPUT. \""..depth.."\" TRY AGAIN.")
- else
- return tonumber(depth)
- end
- end
- end
- function WaitForInventory(size) --Waits for the required building materials DONE
- local reqBM
- if size < 10 then
- reqBM = 11+3*size
- else
- reqBM = 29 - size
- end
- repeat
- term.clear() term.setCursorPos(1,1)
- local inventory = "good"
- turtle.select(1) --building material
- if turtle.getItemCount(1) ~= reqBM then
- print(" - Put exactly "..(11+3*size).." blocks of a building material in slot 1")
- inventory = "bad"
- end
- turtle.select(2) --dispensers
- if turtle.getItemCount(2) ~= size then
- print(" - Put exactly "..size.." dispensers or droppers in slot 2")
- inventory = "bad"
- end
- turtle.select(3) --chest
- if turtle.getItemCount(3) ~= 2 then
- print(" - Put exactly 2 chests in slot 3")
- inventory = "bad"
- end
- turtle.select(4) --brewing stand
- if turtle.getItemCount(4) ~= 1 then
- print(" - Put exactly one brewing stand in slot 4")
- inventory = "bad"
- end
- turtle.select(5) --fuel
- turtle.refuel()
- if turtle.getFuelLevel() < 90 then
- print(" - Put at least 2 coal worth of fuel in slot 5")
- inventory = "bad"
- end
- if inventory == "bad" then sleep(3) end
- until inventory == "good"
- end
- function SurveySite(size,depth) --starting at brewing stand end DONE
- if size > 9 then size = 9 end
- term.clear() term.setCursorPos(1,1)
- print("Surveying site. Clear the blocks I indicate.")
- --moving to account for depth selection
- for i = 1,depth do
- while turtle.detectDown() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove the block below. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.down()
- end
- --survey the main volume
- for layer = 1,2 do
- for i = 1,size+1 do
- while turtle.detect() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove this block. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.turnLeft()
- while turtle.detect() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove this block. TimeStamp = " ..os.clock())
- sleep(2)
- end
- TurnAround()
- while turtle.detect() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove this block. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.turnLeft()
- turtle.forward()
- end
- turtle.forward()
- turtle.turnLeft()
- while turtle.detect() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove this block. TimeStamp = " ..os.clock())
- sleep(2)
- end
- TurnAround()
- while turtle.detect() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove this block. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.turnLeft()
- if layer == 1 then
- while turtle.detectUp() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove the block above. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.up()
- TurnAround()
- end
- end
- turtle.down()
- TurnAround()
- --survey the water well
- turtle.forward() turtle.forward()
- while turtle.detectDown() == true do
- term.clear() term.setCursorPos(1,1)
- print("Remove the block below and fill it with water. TimeStamp = " ..os.clock())
- sleep(2)
- end
- turtle.back() turtle.back()
- end
- function AutoBuilder(noDispensers) --starting at brewing stand end DONE
- local BM = 1 DISP = 2 CH = 3 BS = 4 --remember which slot has what
- local size
- if noDispensers > 9 then size = 9 else size = noDispensers end
- print("Laying bottom layer")
- turtle.select(BM)
- turtle.turnLeft() --build brewing end
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnRight()
- turtle.back()
- turtle.place()
- turtle.turnRight()
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnRight()
- turtle.back()
- turtle.select(BS)
- turtle.place()
- turtle.select(BM)
- turtle.turnRight()
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnLeft()
- for i = 1,size-1 do
- turtle.forward()
- turtle.turnLeft()
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnLeft()
- end
- print("Laying top layer layer")
- turtle.up()
- turtle.placeDown()
- turtle.turnLeft()
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnLeft()
- turtle.back()
- turtle.select(CH)
- turtle.place()
- turtle.placeDown()
- TurnAround()
- for i = 1,size do
- turtle.turnLeft()
- turtle.select(DISP)
- turtle.place()
- TurnAround()
- if i >= size*2-noDispensers then --dispenser or BM?
- turtle.select(BM)
- end
- turtle.place()
- turtle.turnLeft()
- turtle.forward()
- end
- turtle.turnLeft()
- turtle.place()
- TurnAround()
- turtle.place()
- turtle.turnLeft()
- turtle.back()
- turtle.place()
- end
- --Brew-----------------------------------------------------------------------------------------------------------------------
- function DefineInventory(potionShortList) --gives instruction on inventory layout and returns the inventory array DONE
- local inventory = {"bottles ","neth.wart"} --establish the inventory
- for potID = 1,#potionShortList do --loop through all potions
- for ingredient = 2,#potionShortList[potID] do --loop through all the ingredients
- local listed = false --assume the current ingredient not in the inventory array
- for slot = 1,#inventory do
- if inventory[slot] == potionShortList[potID][ingredient] then
- listed = true
- end
- end
- if listed == false then
- inventory[#inventory+1] = potionShortList[potID][ingredient] --append the array
- end
- end
- end
- local resSlotNum = #inventory --calculates the number of reserved slots
- for slot = resSlotNum+1,16 do inventory[slot] = "[empty] " end --mark the empty slots
- --prints the inventory and scans the inventory ensuring it is at least minimally stocked
- local stocked
- repeat
- stocked = true
- for slot = 1,resSlotNum do
- turtle.select(slot)
- if turtle.getItemCount(slot) == 0 then
- stocked = false
- term.clear() term.setCursorPos(1,1)
- print("Stock the inventory to continue.\n\n")
- for x = 0,3 do
- print(inventory[x*4+1].." "..inventory[x*4+2].." "..inventory[x*4+3].." "..inventory[x*4+4].."")
- end
- sleep(1)
- end
- end
- until stocked
- term.clear() term.setCursorPos(1,1)
- return inventory, resSlotNum
- end
- function FindHome(size) --Navigates to home base DONE
- print("\nGetting my bearings...")
- --turtle will find the position above the water and then move to be above the brewing stand
- --orient turtle in the axis of the apothecary
- local turnCount = 4
- while turtle.detect() == true do
- turtle.turnLeft()
- turnCount = turnCount - 1
- if turnCount == 0 then error("NAVIGATION ERROR\nTurtle is lost\nForcing quit\n") end
- end
- --check if it on the top layer or bottom layer based on the length
- for i = 1,size do turtle.forward() end --go to end
- TurnAround()
- for i = 1,size-3 do turtle.forward() end
- if turtle.detect() == false then --the turtle is on the top layer
- turtle.down()
- turtle.forward()
- end
- if turtle.detectDown() == true then --if it is at the far end
- TurnAround()
- for i = 1,size-3 do turtle.forward() end
- end
- if turtle.detectDown() == true then error("NAVIGATION ERROR\nTurtle is lost!\nForcing quit\n") end
- turtle.up()
- turtle.forward()
- end
- function CleanUp(reservedSlotCount) --Clears away any leftovers from the previous run DONE
- print("Cleaning up from last time")
- turtle.suckDown()
- turtle.back()
- turtle.down()
- for i = 1,3 do turtle.suck() end
- TurnAround()
- GoToEnd(9)
- for slot = reservedSlotCount+1,16 do
- turtle.select(slot)
- turtle.drop(64)
- end
- TurnAround()
- turtle.up()
- GoToEnd(9)
- term.clear() term.setCursorPos(1,1)
- end
- function IsShelfFull(shelfID,reservedSlotCount) --counts the contents of a shelf and returns true or false DONE
- print("Inspecting shelf #"..shelfID.."..")
- --calculate distance to shelf and which side it is on
- local distance local turnLeft
- if shelfID > 9 then
- distance = shelfID - 9
- turnLeft = false
- else
- distance = shelfID
- turnLeft = true
- end
- --move into position and face the shelf
- while distance > 1 do
- turtle.back()
- distance = distance - 1
- end
- if turnLeft then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- --attempt to withdraw as many potions as possible
- turtle.select(reservedSlotCount+1)
- for slot = reservedSlotCount+1,16 do
- turtle.suck()
- end
- --count the potions and put them back
- local potionCount = 0
- for slot = reservedSlotCount+1,16 do
- turtle.select(slot)
- if turtle.getItemCount(slot) == 1 then --if there's a potion
- potionCount = potionCount + 1
- elseif turtle.getItemCount(slot) == 0 then --if there's nothing
- break
- else
- print("ERROR: Detected non-potion item. Proceeding regardless")
- end
- turtle.drop()
- end
- --go home
- if turnLeft == false then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- GoToEnd(9)
- --return a result
- local emptySlotCount = 16-reservedSlotCount
- if potionCount < emptySlotCount then --if less than maximum count
- if potionCount > 6 then --if no room for more potions (max:9)
- print("Shelf is full.")
- return true
- else
- print("Shelf is NOT full.")
- return false
- end
- else
- print("Shelf is full.")
- return true
- end
- end
- function IsEnoughIngredients(potionRecipe, inventoryList) --ensures enough supply of raw materials for brewing DONE
- print("Checking internal storage..")
- turtle.select(1) --contains bottles
- if turtle.getItemCount(1) <= 3 then return false end
- turtle.select(2)
- if turtle.getItemCount(2) <= 1 then return false end
- for slot = 3,16 do
- turtle.select(slot)
- if turtle.getItemCount(slot) <= 1 then --check item count first. more likely to be false. saves time
- for ingredient = 2,#potionRecipe do
- if inventoryList[slot] == potionRecipe[ingredient] then
- print("Insufficient internal storage.")
- return false
- end
- end
- end
- end
- if turtle.getFuelLevel() < 200 then return false end
- print("Internal storage is sufficient.")
- return true
- end
- function FillBottles(reservedSlotCount) --DONE
- print("Filling bottles..")
- turtle.back()
- turtle.down()
- for i = 1,3 do
- turtle.select(1) --slot 1 contains empty bottles
- turtle.placeDown()
- turtle.select(reservedSlotCount + 1)
- turtle.drop()
- end
- turtle.up()
- turtle.forward()
- end
- function BrewPotion(potionRecipe, inventoryList) --brews the potion corresponding to the shelfID DONE
- local potionSize = #potionRecipe
- --find the next ingredient in the recipe in the inventory and put it in the stand
- for ingredient = 1,#potionRecipe do --for each ingredient in the potion
- for slot = 2,16 do --for each slot in the inventory
- if inventoryList[slot] == potionRecipe[ingredient] then --compare the recipe step to the inventory slot
- turtle.select(slot)
- turtle.dropDown(1)
- sleep(1) --this is just a buffer in case it takes longer than 20s to brew a step
- term.clear() term.setCursorPos(1,1)
- Rest(20,"brew","Brewing step "..ingredient.." of "..#potionRecipe.." for "..potionRecipe[1])
- end
- end
- end
- end
- function RestockShelf(shelfID) --puts freshly brewed potions on the shelf DONE
- print("Restocking Shelves...")
- --calculate distance to shelf and which side it is on
- local distance local turnLeft
- if shelfID > 9 then
- distance = shelfID - 9
- turnLeft = false
- else
- distance = shelfID
- turnLeft = true
- end
- --move to the brewing stand
- turtle.back()
- turtle.down()
- --extract potions
- for i = 1,3 do
- turtle.suck()
- end
- --move to home
- turtle.up()
- turtle.forward()
- --move into position and face the shelf
- while distance > 1 do
- turtle.back()
- distance = distance - 1
- end
- if turnLeft then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- --identify which slots the potions are stored in
- local slot = 16
- turtle.select(slot)
- while turtle.getItemCount(slot) == 0 do
- slot = slot - 1
- turtle.select(slot)
- end
- --put the potions away
- for i = 1,3 do
- turtle.drop()
- slot = slot - 1
- turtle.select(slot)
- end
- --move to home
- if turnLeft == false then
- turtle.turnLeft()
- else
- turtle.turnRight()
- end
- GoToEnd(9)
- end
- function RestockTurtle(reservedSlotCount) --restocks the turtle from the storage chests DONE
- print("Restocking turtle...")
- TurnAround()
- GoToEnd(9)
- turtle.select(reservedSlotCount+1)
- while turtle.suck() == true do --get a stack of items
- for slot = 1,reservedSlotCount do turtle.transferTo(slot,64) end --shove it in the working inventory
- turtle.refuel() --attempt to refuel with the item
- turtle.dropDown() --dump the item in the temp chest
- end
- while turtle.suckDown() == true do --move items from temp to perm chest
- turtle.drop()
- end
- TurnAround()
- GoToEnd(9)
- if turtle.getFuelLevel() < 100 then
- Rest(300,"sleep","Low on fuel. Slowing down work rate..")
- elseif turtle.getFuelLevel() < 200 then
- Rest(100,"sleep","Low on fuel. Slowing down work rate..")
- end
- end
- --Utilities------------------------------------------------------------------------------------------------------------------
- function Rest(restTime, restType, heading) --makes the turtle sleep for a time with animations DONE
- term.clear() term.setCursorPos(1,1)
- print(heading)
- local restStep
- while restTime > 0 do
- term.setCursorPos(1,2)
- if restType == "brew" then
- restStep = 1 --must be an odd number
- print("Brewing for "..restTime.."s \n")
- if math.fmod(restTime,2) == 0 then
- print[[
- \
- } \ {
- |O \o |
- | o \ |
- \_____/
- ]]
- else
- print[[
- /
- } / {
- | o / O |
- | / o |
- \_____/
- ]]
- end
- elseif restType == "sleep" then
- restStep = 1 --must be an odd number
- print("Sleeping for "..restTime.."s \n")
- if math.fmod(restTime,2) == 0 then
- print[[
- ==== ====
- // // === ===
- // // // //
- ==== ==== === ===
- ]]
- else
- print[[
- ==== ==== === ===
- // // // //
- // // === ===
- ==== ====
- ]]
- end
- end
- restTime = restTime - restStep
- sleep(restStep)
- end
- term.clear() term.setCursorPos(1,1)
- end
- function LoopVariable(i, maximum, direction) --loops variable from 1->maximum->1 DONE
- if direction == "+" and i >= maximum then return 1 end
- if direction == "+" and i < maximum then return i+1 end
- if direction == "-" and i <= 1 then return maximum end
- if direction == "-" and i > 1 then return i-1 end
- end
- function NumToString(x,sigFig) --converts int to string showing significant figures
- local zeros = tostring(x)
- local numberSize = math.ceil(math.log10(x+1))
- for i = numberSize,sigFig-1,1 do
- zeros = "0"..zeros
- end
- return zeros
- end
- function PrintCentered(text)
- local textLength = string.len(tostring(text))
- local pageWidth,pageLength = term.getSize()
- if textLength > pageWidth then error("Error in PrintCentered(). Cannot fit text to screen") end
- local spacerLength = math.ceil(0.5*(pageWidth-textLength))
- local cursorX, cursorY = term.getCursorPos()
- term.setCursorPos(cursorX + spacerLength, cursorY)
- print(text)
- end
- function TurnAround() --turtle performs a 180 leftwise turn DONE
- turtle.turnLeft() turtle.turnLeft()
- end
- function GoToEnd(runCount) --turtle moves until it hits something (break after 8 paces)
- if runCount == nil then print("ERROR in func:GoToEnd()\nDist not specified") runCount = 8 end
- while turtle.forward() == true do
- turtle.forward()
- runCount = runCount - 1
- if runCount == 0 then
- error("\nTurtle is lost!\nForcing quit\n")
- end
- end
- end
- term.clear() term.setCursorPos(1,1)
- print("Starting program 'Potion Robot v1.3' by YardKing42 aka YK7942\n")
- Main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement