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

Several issues with a 7x7 wheat farming turtle.

Started by ThePhoenixSol, 31 January 2016 - 08:50 AM
ThePhoenixSol #1
Posted 31 January 2016 - 09:50 AM
Let me start off by saying that I have little to no knowledge of LUA, all my knowledge is what I learned from looking at other code and testing it with a turtle in game, before putting it in this.

My overall goal with this program was to make a turtle that would go through a 7x7 farm of wheat in a clockwise spiral, scanning to see if the wheat was grown before farming it, and then returning to a final position and crafting bread, then dropping its contents and refueling if need be. However, while i fixed several of the issues that arised, i still have a few.

When it does its initial movement into the field, it doesnt attempt to farm, it makes its turn, scans and farms properly. But then when it moves again it goes forward 2 blocks rather than 1. I have no idea as to why it does this because when I look at the code i see no reason it should move twice, and without farming non the less.

This is a picture of the farm, turtle placement, and path it should take.
Spoiler

My code:
Spoiler

--[[aWheatFarm]]--
--[[By: ThePhoenixSol]]--
--[[VARIABLES]]--
local fuelLevel = turtle.getFuelLevel()
local success, data = turtle.inspectDown()
local cycle = true
local cyc = 6
local cycTwo = 4
local cycThree = 2
local incNum = 0
--[[FUNCTIONS]]--
function refuel()
  if fuelLevel < 300 then
	turtle.turnRight()
	turtle.select(1)
	turtle.suck()
	turtle.refuel()
	turtle.turnLeft()
  end
end
function InvEmp()
  for i = 1, 4 do
	turtle.select(i)
	turtle.dropDown()
  end
  for i = 8, 16 do
	turtle.select(i)
	turtle.dropDown()
  end
	turtle.select(8)
	turtle.dropDown()
end
function craft()
  turtle.turnLeft()
  turtle.select(1)
  turtle.drop()
  turtle.select(2)
  turtle.drop()
  InvEmp()
  turtle.select(16)
  turtle.craft()
  turtle.dropDown()
  turtle.select(1)
  turtle.suck()
  turtle.select(2)
  turtle.suck()
  turtle.turnRight()
end
function replant()
  turtle.select(2)
  turtle.suckDown(64)
  turtle.placeDown()
end
function harvest()
  for i = 5, 7 do
	if turtle.getItemCount(i) > 64 then
	  turtle.select(i)
	end
	if data.metadata == 7 then
	  turtle.digDown()
	end
  end  
end
function forwFarm()
  turtle.forward()
  if data.metadata == 7 then
	os.sleep(5)
	harvest()
	os.sleep(5)
	replant()
  end
end
function rightForwLayOne()
  turtle.turnRight()
  while cyc > incNum do
	forwFarm()
	os.sleep(5)
	incNum = incNum + 1
  end
  incNum = 0
end
function rightForwLayTwo()
  turtle.turnRight()
  while cycTwo > incNum do
	forwFarm()
	os.sleep(5)
	incNum = incNum + 1
  end
  incNum = 0
end
function rightForwLayThree()
  turtle.turnRight()
  while cycThree > incNum do
	forwFarm()
	os.sleep(5)
	incNum = incNum + 1
  end
  incNum = 0
end
function returnHome()
  turtle.turnRight()
  turtle.forward()
  turtle.turnLeft()
  turtle.forward()
  turtle.forward()
  turtle.forward()
  turtle.down()
  turtle.turnLeft()
  turtle.turnLeft()
end
function status()
  turtle.up()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  forwFarm()
  forwFarm()
  rightForwLayOne()
  rightForwLayOne()
  rightForwLayOne()
  turtle.turnRight()
  forwFarm()
  forwFarm()
  forwFarm()
  turtle.turnRight()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  forwFarm()
  rightForwLayTwo()
  rightForwLayTwo()
  rightForwLayTwo()
  turtle.turnRight()
  forwFarm()
  forwFarm()
  turtle.turnRight()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  rightForwLayThree()
  rightForwLayThree()
  rightForwLayThree()
  returnHome()
end
--[[MAIN]]--
while cycle do
  refuel()
  status()
  craft()
end

If you need any other information to assist me, merely ask and I will do what I can to help.
Bomb Bloke #2
Posted 31 January 2016 - 11:14 AM
One problem existing within your harvest() function:

if turtle.getItemCount(i) > 64 then

You were presumably going for a "less than" symbol. That function will also attempt to dig regardless as to which slot is selected, and should ideally "break" its loop once a suitable slot has been found.

These lines up the top:

local fuelLevel = turtle.getFuelLevel()
local success, data = turtle.inspectDown()

… assign the values returned by the functions to fuelLevel / success / data, but don't magically keep them up to date as the script progresses. If you want fresh data (eg after the turtle has moved), you need to call the functions and perform the assignments again.
Edited on 31 January 2016 - 10:19 AM
ThePhoenixSol #3
Posted 01 February 2016 - 07:38 AM
One problem existing within your harvest() function:

if turtle.getItemCount(i) > 64 then

You were presumably going for a "less than" symbol. That function will also attempt to dig regardless as to which slot is selected, and should ideally "break" its loop once a suitable slot has been found.

These lines up the top:

local fuelLevel = turtle.getFuelLevel()
local success, data = turtle.inspectDown()

… assign the values returned by the functions to fuelLevel / success / data, but don't magically keep them up to date as the script progresses. If you want fresh data (eg after the turtle has moved), you need to call the functions and perform the assignments again.

alright, i went and moved those 2 lines, and switched that to a < symbol…. but the way you said that confused me. While yes you were right, i want ideally for it to dig and place it in a proper slot, im confused if what you were saying is that its not possible, or if i need to do it some other way.
Dragon53535 #4
Posted 01 February 2016 - 08:05 AM
So the two lines, I'll try and explain it. If I run this code:

local x = 1
for i = 1,25 do
  print(x)
  sleep(1)
end
Every second it will only print out '1', however if I change it to this:

local x = 1
for i = 1,25 do
  x = i
  print(x)
  sleep(1)
end
Then it will start to print out 1-25. The same goes for those two lines, if I just set them once, they will only remember the value of what it was when I set them.

As an example with turtle.getFuelLevel:

local fuel = turtle.getFuelLevel()
while true do
  print(fuel)
  turtle.forward()
  turtle.turnLeft()
end
This will make the turtle move in a square, and print out that you have the same fuel each time.
However if you were to change it to this:

local fuel = turtle.getFuelLevel()
while true do
  print(fuel)
  turtle.forward()
  turtle.turnLeft()
  fuel = turtle.getFuelLevel()
end
Then it will continuously update the fuel level.
Edited on 01 February 2016 - 07:06 AM
Bomb Bloke #5
Posted 01 February 2016 - 08:52 AM
An in regards to the harvesting function, there's most always a way!

In this particular case is mostly a matter of re-ordering your logic so you're not digging regardless as to the slot selected. You also need to confirm that there's something under the turtle to harvest at the present point in time.

local function harvest()
  local success, data = turtle.inspectDown()
  if success and data.name == "minecraft:wheat" and data.metadata == 7 then  --# No point continuing unless all of this is true - attempting to get name/metadata keys from the data table will error if success is false, so we check that first.
    for i = 5, 7 do
      if turtle.getItemCount(i) < 64 then
        turtle.select(i)
        turtle.digDown()
        return  --# Done everything we came to do, no need to continue checking the other slots.
      end
    end
  end
end
ThePhoenixSol #6
Posted 01 February 2016 - 11:23 AM
An in regards to the harvesting function, there's most always a way!

In this particular case is mostly a matter of re-ordering your logic so you're not digging regardless as to the slot selected. You also need to confirm that there's something under the turtle to harvest at the present point in time.

local function harvest()
  local success, data = turtle.inspectDown()
  if success and data.name == "minecraft:wheat" and data.metadata == 7 then  --# No point continuing unless all of this is true - attempting to get name/metadata keys from the data table will error if success is false, so we check that first.
	for i = 5, 7 do
	  if turtle.getItemCount(i) < 64 then
		turtle.select(i)
		turtle.digDown()
		return  --# Done everything we came to do, no need to continue checking the other slots.
	  end
	end
  end
end

Ahhh, alright. that makes a lot of sense. now, for what my main issue is, when is it not moving right. to reiterate, the initial forward farm that gets it into the feild, it doesnt attempt to check for wheat then farm it, then it turns left, moves forward one and farms when needed, but doesnt replant. Then after that instead of moving 1 space and checking, it moves 2. and then i havent tested much past that, but the first time i ran it, it wasnt checking anything to farm, and it made that lower left corner fine, but it went waaay past the upper left corner before turning right, id like to fix the movement issues before getting much farther into other things XD

My current code, after edits
Spoiler

--[[aWheatFarm]]--
--[[By: ThePhoenixSol]]--
--[[Version 3.2]]

--[[VARIABLES]]--
local cycle = true
local cyc = 6
local cycTwo = 4
local cycThree = 2
local incNum = 0

--[[FUNCTIONS]]--

function refuel()
  local fuelLevel = turtle.getFuelLevel()
  if fuelLevel < 300 then
    turtle.turnRight()
    turtle.select(1)
    turtle.suck()
    turtle.refuel()
    turtle.turnLeft()
  end
end

function InvEmp()
  for i = 1, 4 do
    turtle.select(i)
    turtle.dropDown()
  end
  for i = 8, 16 do
    turtle.select(i)
    turtle.dropDown()
  end
    turtle.select(8)
    turtle.dropDown()
end

function craft()
  turtle.turnLeft()
  turtle.select(1)
  turtle.drop()
  turtle.select(2)
  turtle.drop()
  InvEmp()
  turtle.select(16)
  turtle.craft()
  turtle.dropDown()
  turtle.select(1)
  turtle.suck()
  turtle.select(2)
  turtle.suck()
  turtle.turnRight()
end

function replant()
  turtle.select(2)
  turtle.suckDown(64)
  turtle.placeDown()
end

function harvest()
  local success, data = turtle.inspectDown()
  if success and data.name == "minecraft:wheat" and data.metadata == 7 then
    for i = 5, 7 do
      if turtle.getItemCount(i) < 64 then
        turtle.select(i)
        turtle.digDown()
        return
      end
    end 
  end  
end

function forwFarm()
  local success, data = turtle.inspectDown()
  turtle.forward()
  if data.metadata == 7 then
    harvest()
    os.sleep(1)
    replant()
  end
end

function rightForwLayOne()
  turtle.turnRight()
  while cyc > incNum do
    forwFarm()
    os.sleep(5)
    incNum = incNum + 1
  end
  incNum = 0
end

function rightForwLayTwo()
  turtle.turnRight()
  while cycTwo > incNum do
    forwFarm()
    os.sleep(5)
    incNum = incNum + 1
  end
  incNum = 0
end

function rightForwLayThree()
  turtle.turnRight()
  while cycThree > incNum do
    forwFarm()
    os.sleep(5)
    incNum = incNum + 1
  end
  incNum = 0
end

function returnHome()
  turtle.turnRight()
  turtle.forward()
  turtle.turnLeft()
  turtle.forward()
  turtle.forward()
  turtle.forward()
  turtle.down()
  turtle.turnLeft()
  turtle.turnLeft()
end

function status()
  turtle.up()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  forwFarm()
  forwFarm()
  rightForwLayOne()
  rightForwLayOne()
  rightForwLayOne()
  turtle.turnRight()
  forwFarm()
  forwFarm()
  forwFarm()
  turtle.turnRight()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  forwFarm()
  rightForwLayTwo()
  rightForwLayTwo()
  rightForwLayTwo()
  turtle.turnRight()
  forwFarm()
  forwFarm()
  turtle.turnRight()
  forwFarm()
  turtle.turnLeft()
  forwFarm()
  rightForwLayThree()
  rightForwLayThree()
  rightForwLayThree()
  returnHome()
end

--[[MAIN]]--

while cycle do
  refuel()
  status()
  craft()
end
Bomb Bloke #7
Posted 01 February 2016 - 10:21 PM
now, for what my main issue is, when is it not moving right. to reiterate, the initial forward farm that gets it into the feild, it doesnt attempt to check for wheat then farm it, then it turns left, moves forward one and farms when needed, but doesnt replant.

Well:

function forwFarm()
  local success, data = turtle.inspectDown()  --# Check what's under the turtle.
  turtle.forward()                            --# Move somewhere else...
  if data.metadata == 7 then                  --# Compare what WAS under the turtle...
    harvest()
    os.sleep(1)
    replant()
  end
end

Move first, THEN check. But since the harvest function checks anyway, why have the movement function repeat the same action? Consider just doing:

function forwFarm()
  repeat until turtle.forward()  --# Keep trying until a movement attempt succeeds (eg wait for mobs to move out of the way).
  harvest()                      --# This function will only dig if it's suitable to do so.
end

Then add the replant() call to the harvest() function, rigged to run only if it actually digs something up:

function harvest()
  local success, data = turtle.inspectDown()
  if success and data.name == "minecraft:wheat" and data.metadata == 7 then
    for i = 5, 7 do
      if turtle.getItemCount(i) < 64 then
        turtle.select(i)
        turtle.digDown()
        replant()
        return
      end
    end 
  end  
end
ThePhoenixSol #8
Posted 02 February 2016 - 12:01 AM
now, for what my main issue is, when is it not moving right. to reiterate, the initial forward farm that gets it into the feild, it doesnt attempt to check for wheat then farm it, then it turns left, moves forward one and farms when needed, but doesnt replant.

Well:

function forwFarm()
  local success, data = turtle.inspectDown()  --# Check what's under the turtle.
  turtle.forward()							--# Move somewhere else...
  if data.metadata == 7 then				  --# Compare what WAS under the turtle...
	harvest()
	os.sleep(1)
	replant()
  end
end

Move first, THEN check. But since the harvest function checks anyway, why have the movement function repeat the same action? Consider just doing:

function forwFarm()
  repeat until turtle.forward()  --# Keep trying until a movement attempt succeeds (eg wait for mobs to move out of the way).
  harvest()					  --# This function will only dig if it's suitable to do so.
end

Then add the replant() call to the harvest() function, rigged to run only if it actually digs something up:

function harvest()
  local success, data = turtle.inspectDown()
  if success and data.name == "minecraft:wheat" and data.metadata == 7 then
	for i = 5, 7 do
	  if turtle.getItemCount(i) < 64 then
		turtle.select(i)
		turtle.digDown()
		replant()
		return
	  end
	end
  end  
end

Thanks! I had it repeat that action cause i was just throwing stuff around attempting to make it work, and it kinda did, but not enough for the whole program to work XD.

anyways, it ran a full cycle, and followed the right path. now the only real issue is, when it farms, how can i tell it to put seeds in slot 2, cause when it ran that cycle it put all the wheat in 5, and seeds in 6 and 7, and that cause it to not replant, because it goes to slot 2 for that. and then im not sure what caused it, but when it got back to "Home" it checked if it needed refuel, then checked if it needed to craft like it was supposed to, but then when it started leaving that spot, it didnt go up a block, and it wasnt following the right path, it was just going straight, not turning or anything…. had to retill the ground XD
ThePhoenixSol #9
Posted 03 February 2016 - 11:46 AM
So, i looked into the turtle API a little bit. And i know to fix the replant issue i need to use getItemDetail, and transferTo, but im not 100% sure how to do it, and I cant find code that does what i need for me to look at, edit, and learn from.

this is what im trying to do, and i didnt get very far before getting stuck, but i think it gives enough of an idea for you more knowledgeable guys to be able to help :P/>

function organize()
  for i = 1, 16 do
    if turtle.getItemDetail(i) == data.name == "minecraft:wheat_seeds"
  end
end

im well aware im probably doing this completely wrong XD

All i know is that i want to search the inventory for seeds to move to slot 2, so that when i run replant() it actually has seeds to use. And im considering using this function to organize the entire inventory, in case any extra wheat is picked up, or any extra seeds, so input on that idea would also be nice
KingofGamesYami #10
Posted 03 February 2016 - 01:43 PM

for i = 1, 16 do
  local data = turtle.getItemDetail()
  if data and data.name == "minecraft:wheat_seeds" then
     --#stuff
  end
end
ThePhoenixSol #11
Posted 04 February 2016 - 06:48 PM
Alright, i have everything put together, ran several test runs of it, and it seems to be working fine! I even added some convenience stuff, like printing out what the turtle is doing at the moment.

So, thanks a lot to all of you who helped. and for anyone who wanted this, or wants to see how it was done, here is my final code: http://pastebin.com/6CKQa7gS