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

Check block name against array

Started by Exitialis, 02 June 2015 - 10:31 AM
Exitialis #1
Posted 02 June 2015 - 12:31 PM
Hey,

I started teaching myself Lua the other day and have enjoyed making my turtle move around. My current goal is a turtle that is able to clear a wooded area of trees so that I can deploy a Buildcraft quarry. If you're wondering why not use a mining turtle it's because I like recycling the junk to turn into UU matter with IC2.

My question is how do I have the turtle compare what it has detected against a list of things? My current rather inelegant solution is below but this will make for a rather wide and unwieldy script.


if string.match(data.name, "dirt") or string.match(data.name, "grass") or string.match(data.name, "stone") or string.match(data.name, "sand") then
  if not turtle.up() then
   turtle.digUp()
  end
  do return end
end

If it helps my background is self taught intermediate Powershell and the script in full is below:

Spoiler

print("Felling start")
function CheckFuel()
	if turtle.getFuelLevel() <= 100 then
  turtle.refuel(1)
  print ("Turtle refuelled by 1")
  print("Turtle fuel level: ", turtle.getFuelLevel())
	end
end
--[[function TurtleInspect(direction)
if direction == "down" then
  local Inspect, data = turtle.inspectDown()
end
end]]
function CheckGround()
local GroundPresent, data = turtle.inspectDown()
while not GroundPresent do
  GroundPresent, data = turtle.inspectDown()
  turtle.down()
end
end
function ObstacleTest()
if string.match(data.name, "log") then
  print("Tree found")
  CutTree()
end
if string.match(data.name, "leaves") then
  turtle.dig()
  do return end
end
local ObstacleUp, dataUp = turtle.inspectUp()
if ObstacleUp then
  if string.match(dataUp.name, "leaves") then
   turtle.digUp()
   do return end
  end
end
if string.match(data.name, "dirt") or string.match(data.name, "grass") or string.match(data.name, "stone") or string.match(data.name, "sand") then
  if not turtle.up() then
   turtle.digUp()
  end
  do return end
end
if not turtle.up() then
  turtle.dig()
end
end
function AvoidObstacle()
--local AvoidItems = {"dirt", "grass", "stone"}
ObstaclePresent, data = turtle.inspect()
while ObstaclePresent do
  CheckFuel()
  ObstacleTest()
  ObstaclePresent, data = turtle.inspect()
end
turtle.forward()
print("Obstacle avoided")
end
function CutTree()
CheckFuel()
turtle.dig()
turtle.forward()
local TreeDown, data = turtle.inspectDown()
local k = 0
while string.match(data.name, "log") do
  turtle.digDown()
  turtle.down()
  k = k+1
  TreeDown, data = turtle.inspectDown()
end
while k > 0 do
  turtle.up()
  k = k-1
end
local TreeUp, data = turtle.inspectUp()
while TreeUp do
  if string.match(data.name, "log") then
   turtle.digUp()
   turtle.up()
  else
   do break end
  end
  TreeUp, data = turtle.inspectUp()
end
CheckGround()
CheckFuel()
print("Tree cut down")
end
function ScanRow()
for i=1,50 do
  CheckFuel()
  CheckGround()
  local TreeDown, data = turtle.inspectDown()
  if TreeDown and string.match(data.name, "log") then
   print("Tree found")
   CutTree()
  end
  local detected, data = turtle.inspect()
  if detected then
   if string.match(data.name, "log") then
	print("Tree found")
	CutTree()
   else
	AvoidObstacle()
   end
  else
   turtle.forward()
  end
end
end
for j=1,50,2 do
CheckFuel()
ScanRow()
print("j = ", j)
turtle.turnRight()
turtle.forward()
turtle.turnRight()
CheckFuel()
ScanRow()
print("j = ", j+1)
turtle.turnLeft()
turtle.forward()
turtle.turnLeft()
end

Any help is very much appreciated :)/>
flaghacker #2
Posted 02 June 2015 - 03:34 PM
Loop through the table:


whiteList = {"grass", "stone", "..."}

function isWhiteListed (name)
  for _, v in pairs (whiteList) do
    if v == name then
      return true
    end
  end
  return false
end

print (isWhiteListed ("grass") --true
print (isWhiteListed ("diamond") --false

Just in case you're going to ask, "_" is a normal variable name that is used as a dummy variable by convention.

If you're interested, you can learn more about tables here.

And I hope you are using a mining turtle, you wont get far otherwise :P/>.
Edited on 02 June 2015 - 01:41 PM
Exitialis #3
Posted 02 June 2015 - 04:05 PM
Ah awesome thank you! That makes a lot of sense, I'm still getting used to not having arrays.

Would you mind explaining this line to me please?


for _, v in pairs (whiteList) do

I can see that it means "for each item in the passed table do the following" however I don't understand what "v in pairs" means or does.

I thought that when you called return you had to either do it at the end of a block or wrap it like this:


do return end

Or is your way allowed because it is at the end of the if block?

This is being used on a turtle with an axe equipped, it's there to avoid these blocks instead of breaking them. Although it does seem more than capable of breaking dirt, sand and sandstone (I haven't tested it on anything else just yet).

Thank you :)/>
Edited on 02 June 2015 - 02:19 PM
Lyqyd #4
Posted 02 June 2015 - 05:19 PM
Both of those returns are at the end of a block.

You can also structure the table so that the names of the materials are the keys to the table:


local materials = {
  ["minecraft:stone"] = true,
  ["minecraft:grass"] = true,
  ["minecraft:dirt"] = true,
}

local info = turtle.inspect()
if info and materials[info.name] then
  --# there is a block and it is in our table
elseif info then
  --# there is a block and it is not in our table
else
  --# there is no block
end
flaghacker #5
Posted 02 June 2015 - 05:20 PM
1)

for k, v in pairs (t) do
will loop through the table t, setting k to the key and v to the value. Eg:

t = {a=3, b="hello", foo="bar"}
for k, v in pairs (t) do
  print (k, "=", v)
end
will output

a = 3
b = hallo
foo = bar

I named "v" to "_" in my function to indicate that I don't need/use it. You can choose any variable names instead.

2)
Yes, return has to be at the end of a block because any code after it wouldn't be executed anyway because return exits the function immediately. The first return in my code is at the end of the if block.

Edit: :ph34r:/>'d
Edited on 02 June 2015 - 03:25 PM
KingofGamesYami #6
Posted 02 June 2015 - 05:24 PM
for _, v in pairs( whitelist ) do

…is a generic for loop

pairs is a function that's a little difficult to explain. Eventually, it is possible to write and use your own functions (in place of pairs) that do fun things.

return does have to be called at the end of a block, but this includes any block (if / do / for / while / etc.)
Exitialis #7
Posted 02 June 2015 - 08:45 PM
Thank you for your help everyone!

In the end I decided to go with the following code:


BlackList = {"grass", "dirt", "stone", "sand"}
for index,BlockType in pairs (BlackList) do
  if string.match(data.name, BlockType) then
   if not turtle.up() then
    turtle.digUp()
   end
  do return end
  end
end

Having looked into pairs I think that I shall have to do some more reading up…
KingofGamesYami #8
Posted 02 June 2015 - 09:24 PM
If you're looking into pairs, you may appreciate this link. It's how I figured it out, and I still go back to it when I forget.
Exitialis #9
Posted 02 June 2015 - 10:17 PM
I'm not sure on this forums etiquette so apologies if I should start a new thread but would anyone mind helping me work out why this discards everything?


function DiscardNotWood()
WhiteList = {"log", "coal"}
for k=1,16 do
  Item = turtle.getItemDetail(k)
  if Item ~= nil then
   for index,BlockType in pairs (WhiteList) do
    if not string.match(Item.name, BlockType) then
	 turtle.select(k)
	 turtle.drop()
	 print("Dropping: ", Item.name)
    end
   end
  end
end
end

Thank you for the link on pairs, I shall start reading.
Lyqyd #10
Posted 02 June 2015 - 10:37 PM
Because you are looping through the list and discarding the item any time any of the items don't match, you would only keep items that match everything on the list, like "coal log" or "log of coal". You should separate out the list-checking into a separate function, and have that function pass its results back, then only act on the final result to keep or discard the item.