This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Gili710's profile picture

XP Turtle v0.1

Started by Gili710, 31 January 2013 - 11:51 PM
Gili710 #1
Posted 01 February 2013 - 12:51 AM
Hey Guys,

This will be my first program here. My post contains a video which will also be my first video ever, so I hope you guys like it. If not, just pretend you do anyway to make me feel good :)/>

So as you probably know, RichardG released a new version of MiscPeripherals, 3.0, which introduces XP Turtles. Since I already had an XP farm set up, I thought I'd take a bit of time to set it up with an XP turtle.

[media]http://www.youtube.com/watch?v=_adejSGTzgI[/media]

What the turtle allows you to do is not only collect XP, but also enchant items directly in the turtle, provided you have the required amount of bookshelves around it.

My program is pretty basic, but I will be expanding it soon. Basically the turtle sits opposite the melee turtles in my xp farm and gathers up the XP until it hits level 30. Then it moves to the enchanting station where it enchants a book and drops it down into a chest before moving back.

The movement phase uses a persistent state, so it will always move back to position 0 even if you shut down the client (or server) while it's moving. It also checks for books and fuel and shuts down if those aren't available. I need to clean this up a little bit because I don't like exiting with 'error' but if I use shell.exit(), the terminal restarts and it loses the exit message. I'm open to suggestions here, haven't had time to research this further.

The best thing is probably to watch the video, it will explain my setup. Now like I said in the video, I know it's not the most efficient setup (of either the mob spawner or the turtle) but since this was what I already had, I'm going with this. You could probably build it so the turtle sits in the right spot, surrounded by the bookshelves with a chest underneath and then it wouldn't have to move which would make it a lot more simple, but also less fun to code :)/>. The other thing is that I'll probably move the chest up above the turtle, so that I can still have a normal enchantment table there for manual enchanting, that'll mean I won't need to build another block of bookshelves.

I've changed the code a bit since the video because I had a few issues. There are probably some bugs since I haven't tested it extensively yet.

If you want to use it and your setup is slightly different, just change some of the numbers. So instead of moveBack(5) you'd have 2, or 6. In the next version I'll make this a little more modular so you can just set a variable and it'll globally change it.

Anyway I hope you like it. I'll be adding the following features soon:

- ability to put different items inside the turtle to enchant, once it has done those it will default back to books
- ability to repair items if the turtle also has an anvil.


<edit>

So I've already updated the code quite a bit. First of all it looks a bit better. It will also now scan for items in slots 2 through 14 and enchant those first, before defaulting to the stack of books in slot 15. Of course this also means that you can just chuck it full of stacks of books (as long as you leave slot 1 open and put fuel in slot 16) and it will just keep going until it runs out completely. But in that case of course you'd need to empty out the inventory it is dropping to. You could replace the chest with a relay though, and pipe items to multiple chests, or use an OpenCCSensors turtle to sort out the good ones, but I'm sure you can figure all that out for yourselves :)/>

Also it has a status display window now which shows the current task as well as the current level. It should also exit out of the program cleanly now, displaying the reason it did so.



<edit2>

Found two rather large bugs, one which would make the program not work on first running it and the other with an incorrectly nested loop causing the turtle to only check for items in slots 2 and 15, rather than 2-14 and then 15. Code has been updated.

The pastebin is here: http://pastebin.com/t3VviwYh
Or you can find the code here:
Spoiler
--TODO :     make check for slot 1 being empty
--            create exit for when chest is full


--Load the saved Turtle state from disk if available, if not set to 0
function loadState()
    if fs.exists("xpTurtleState") then
        local file = fs.open("xpTurtleState","r")
        data = file.readAll()
        file.close()
        data=tonumber(data)
        moveState=data
    else
        print("debug -- no xpTurtleState found, setting movement state to 0\n")
        moveState = 0
    end
end

-- Save the current state to disk
function saveState(a)
    local file = fs.open("xpTurtleState","w")
    file.write(a)
    file.close()
--    io.write(string.format("debug -- wrote %s to file\n",a))

end

-- Check where the turtle is right now, and it it isn't at block 0, move there
function moveToStart()
    loadState()
--    io.write(string.format("debug -- Moving %s blocks to starting point\n", moveState))
    if moveState~=nil then
        printStatus("moving to start", getLvl())
        moveForward(moveState)
    end
end

-- Move forward with checking for blockage and save the move state
function moveForward(nDistance)
    printStatus("moving to start", getLvl())
--    print("moveForward nDistance is  ", nDistance)
    while nDistance > 0 do
        if turtle.forward() then
            nDistance=nDistance-1
            moveState = moveState -1
            saveState(moveState)
        else
            sleep(0.5)
        end
    end
end

-- Move back with checking for blockage and save the move state
function moveBack(nDistance)
    while nDistance > 0 do
        printStatus("moving to enchant area", curLev)
--        print("moveBack () nDistance is  ", nDistance)
        if turtle.back() then
            nDistance=nDistance-1
            moveState = moveState +1
            saveState(moveState)
        else
            sleep(0.5)
        end
    end
end


-- check if there's enough fuel, if not refuel from slot 16. If no fuel available, exit.
function checkFuel()
    if turtle.getFuelLevel()<20 then
        if    turtle.getItemCount(16)>=1 then
            turtle.select(16)
            turtle.refuel(1)
        else
            exitMsg(1)            
        end
    end

end

-- get the current level of the turtle
function getLvl()
    curLev = m.getLevels()
    return curLev
end

-- Check if nLvl(default=30) levels have been reached, if not wait, if yes, return true.
function checkLevel(nLvl)
    getLvl()
    if curLev<nLvl then
        printStatus("gathering XP", curLev)
        return false
    else
        printStatus("moving to enchant area", getLvl())
        return true
    end
    
end

-- Look for items to enchant in slots 2 through 14, if there are none, default to findBooks()
function getItems()
    for i=2,14 do
        if turtle.getItemCount(i)>0 then
            turtle.select(i)
            turtle.transferTo(1,1)
            turtle.select(1)
            return true
        end
    end
--        print("no items found, trying to find books")
    if findBook() then
    --        print("Books found")
        return true
    else
        return false
    end

end

-- Get books from inventory slot 15 and put 1 in slot 1, returning true, if not return false
function findBook()
    if turtle.getItemCount(15)>=1 then
        turtle.select(15)
        turtle.transferTo(1,1)
        turtle.select(1)
        return true
    else
        return false
    end
end

-- enchant the book in slot one and drop it into the chest underneath the turtle
function enchantBook(nLvl)
    if m.enchant(nLvl) then
        turtle.dropDown()
    else
        error("Unexpected error while trying to enchant")
    end
    
end

-- End program with a message

function exitMsg(exitNr)
    if exitNr == 1 then exitStr="Out of fuel. Place more fuel in slot 16 and restart the program"
    elseif exitNr == 2 then exitStr="No more items or books"
--    elseif exitNr == 3 then exitStr=""
--    elseif exitNr == 4 then exitStr=""
--    elseif exitNr == then exitStr=""
    
    end
    term.clear()
    term.setCursorPos(2,2)
    sleep(0.5)
    print(exitStr)
    run.state="end"
end



function printIntro()
    term.clear()
    print("---------------------------------------")
    print("------- XPturtle 0.2 by Gili710 -------")
    print("---------------------------------------")
    print()
    print("This turtle will automatically enchant items in its inventory")
    print("Place any items in slots 2 through 14")
    print("Place some books in slot 15.")
    print("Place some fuel in slot 16")
    print("Press any key to start")
    print()

end

function printStatus(curTask, curLvl)
    term.clear()
    term.setCursorPos(1,1)
    print("------- XPturtle 0.2 by Gili710 -------")
    term.setCursorPos(2,4)
    io.write(string.format("Current Task: %s", curTask))
    term.setCursorPos(2,6)
    io.write(string.format("Current Level: %s", curLvl))
end


--INIT
m=peripheral.wrap("right")
m.setAutoCollect(true)
nLvl=30
run = {}
run.state="running"
screenw, screenh = term.getSize()

-- Main Program

printIntro()
os.pullEvent()
checkFuel()
if run.state=="running" then
    moveToStart()
end



-- start main loop
while run.state=="running" do
    while not checkLevel(nLvl) do
        sleep(1)

    end
    checkFuel()
    loadState()

    --    Extra safety here
    while moveState ~= 5 do
        moveToStart()
        moveBack(5)
    end
    printStatus("enchanting", getLvl())
    sleep(2)
    if getItems() then
        enchantBook(nLvl)
        sleep(2)
        moveForward(5)
    else
        exitMsg(2)
    end
end


Edited on 04 February 2013 - 09:59 PM
civilwargeeky #2
Posted 01 February 2013 - 11:57 AM
Nice program. Almost makes me want to download misc peripherals to use it :)/>

Also, have a tip for exiting. You have two options, in the main program (not a function), the "return" keyword will exit the program. Also if you do error("Your Message", 0) then it will not give a line error, just stop the program and print the message.
Gili710 #3
Posted 01 February 2013 - 08:21 PM
Hey mate,

Gotta have the Misc Periph turtles :)/>

Thanks for the input btw, I did solve the exit stuff now, I just used a variable that needs to be true instead of while true do. And then use an exit function to clear the screen, print a message and change the variable so the main while loop breaks, thus ending the program. Of course using error with a 0 argument is also not a bad idea, that's just as clean really.
OmagaIII #4
Posted 12 February 2013 - 08:40 AM
Hmm, upon trying this I get an error on line 190

'Attempt to index ? (a nill value)

I am using the FTB DireWolf20 pack.

Regards
Gili710 #5
Posted 14 February 2013 - 08:10 PM
Hi, sorry for the late reply. Wasn't around for a couple of days.

That's very odd.. are you using the pastebin version? Line 190 is just m.setAutoCollect(true) which is a built-in function from Misc Peripherals meaning that the turtle will collect XP even if no programs are running.

Make sure that you have the enchanting table on the right side of the turtle, not the left. If it's on the left, you'll have to change the m=peripheral.wrap("right") to ("left"). That's the only thing I could think of that could cause something like this, unless you altered the code in some other way, or added some lines somewhere.
TrovadorUrbano #6
Posted 18 February 2013 - 07:04 PM
awesome, i've written something similar before but it only get the xp, and they had a menu for enchant or repair (Anvil + XP Turtle) but enchanting books are a great idea, thanks for the program, ill let my code if you're interested and a video where you can see my program working (sorry if it's in spanish but anyway you can see the turtle working).
pastebin.com/Ltcbuwi5
http://youtu.be/W8UP7ZRbmJA?t=17m7s
CubeCat #7
Posted 19 February 2013 - 07:03 PM
Tnx. I just added attack line and placed it in my exp farm, works great! :)/>
bigj0n #8
Posted 20 February 2013 - 12:25 PM
Setting movedistance to 0 doesnt work. Is there any way to make it so the little guy doesnt move?
thornhackson #9
Posted 26 February 2013 - 05:47 PM
I've been working on a similar program. It's pretty basic, just three chests. One each for loot, garbage and books/enchantables. I haven't added any refueling yet because the turtle I'm using has 100k+ fuel right now.

I did add the option to assign multiple garbage slots incase you're grinding zombies or something. just use slots 1-? and input the last slot number at the prompt.

Has anyone tried enchanting without bookshelves? I've found that my turtle will consistently use all 30 levels without a single bookshelf around.

http://pastebin.com/jDs2UXsq
Gili710 #10
Posted 17 March 2013 - 11:38 AM
Just for the sake of completeness, it seems you can indeed enchant 30 levels without needing bookshelves when using the turtle.

Personally, I think that should be considered a bug in the Misc Peripherals mod, which will hopefully be addressed in a future version, but yeah for now you can just not use the shelves, which negates the need to move or do anything else. The basic program then becomes very simple. Direwolf just made an XP turtle in his SSP let's play so for a simple implementation you could also check that out.
WhiteWolf1423 #11
Posted 23 March 2013 - 03:49 AM
Could you possibly add somewhere where the turtle will pick up fuel and more books meanwhile? (fx while unloading)
raphie80 #12
Posted 17 April 2013 - 04:01 AM
I have found an odd bugg, everything workes except the moving to the correct spot where the chest is, it just doesn't move plz help me :(/>
improvshark #13
Posted 19 May 2013 - 04:31 PM
hmmm i don't think the turtle can make use of the bookshelves