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

Friendly/neutral mobs running turtle off course

Started by grizzlebizzle, 02 August 2012 - 06:25 AM
grizzlebizzle #1
Posted 02 August 2012 - 08:25 AM
Is there a good way to handle this? These friendly and neutral mobs run into my turtle on occasion (zombie pigmen are the worst cause they are everywhere in the nether) and throw it off course. Hostiles arent as much of a problem because they go straight for me and leave the turtle alone. It would be preferrable to stop execution once it gets hit rather than continuing to build off course. Any ideas on how to detect for that?

Before I move I am using detect, then trying to dig it if there is something there, then detecting again to see if it clear which will catch if there is bedrock or something there but doesnt seem to help with mobs.
BigSHinyToys #2
Posted 02 August 2012 - 08:35 AM
most (I think all actually) turtle movement functions return true if they were executed and false if not.
example

if turtle.forward() then
   print("moved")
else
   print("failed")
end
we can make it keep retrying with something like

local function goForward()
    while not turtle.forward() do
        sleep(1)
    end
end
the above will loop until the turtle moves. call it instead of turtle.forward()
just make one for each move function and you are all set
grizzlebizzle #3
Posted 02 August 2012 - 08:51 AM
That works perfectly… thanks.
Teraminer #4
Posted 02 August 2012 - 01:25 PM
Or if you Overengineer this make a turtle with a sword that gets a signal(coords) from the first one and attacks the mob :ph34r:/>/>
Lyqyd #5
Posted 02 August 2012 - 03:23 PM
For future reference, questions like this also belong in the Ask a Pro section.
D3matt #6
Posted 02 August 2012 - 05:20 PM
Or if you Overengineer this make a turtle with a sword that gets a signal(coords) from the first one and attacks the mob :ph34r:/>/>
Or put a sword on the mining turtle :)/>/>
slango20 #7
Posted 09 October 2012 - 02:32 PM
Or just stick the mob with the pickaxe
ChunLing #8
Posted 09 October 2012 - 07:19 PM
I use a function like this

local function mvdgK(mvcmd, drctn) -- i.e.(turtle.up, "Up")
local itr8 = 0
while not mvcmd() do
  local fncnm = "detect"..drctn
  if turtle[fncnm]() then
   fncnm = "dig"..drctn
   if not turtle[fncnm]() then trply("unbreakable block in path") return false end
  elseif turtle.getFuelLevel() == 0 then trply( "Out of fuel" ) return false
  else
   fncnm = "attack"..drctn
   turtle[fncnm]()
  end
  if itr8 > 64 then trply("persistent impediment") return false end
  itr8 = itr8+1
end
return true
end
It uses another function, trply(), that is useful for remote control turtles. But it can be replaced with print() if you're not using remote control.
BigSHinyToys #9
Posted 12 October 2012 - 01:34 AM
I use a function like this

local function mvdgK(mvcmd, drctn) -- i.e.(turtle.up, "Up")
local itr8 = 0
while not mvcmd() do
  local fncnm = "detect"..drctn
  if turtle[fncnm]() then
   fncnm = "dig"..drctn
   if not turtle[fncnm]() then trply("unbreakable block in path") return false end
  elseif turtle.getFuelLevel() == 0 then trply( "Out of fuel" ) return false
  else
   fncnm = "attack"..drctn
   turtle[fncnm]()
  end
  if itr8 > 64 then trply("persistent impediment") return false end
  itr8 = itr8+1
end
return true
end
It uses another function, trply(), that is useful for remote control turtles. But it can be replaced with print() if you're not using remote control.

that is one way of doing it. also could you not just send in ("up") then use turtle[mvcmd] to make it less nit picky
ChunLing #10
Posted 12 October 2012 - 05:14 AM
Sorry, what do you mean?

This function uses the commands turtle.forward, turtle.up, and turtle.down and one of the strings "" (an empty string), "Up", or "Down". It loops while the movement command fails, checking whether there is a block in the way and attempting to mine it if there is, checking fuel, and then just attacking towards the obstacle. It's not very "nit picky", as I understand the term.
robhol #11
Posted 12 October 2012 - 10:15 AM
I use a function like this

local function mvdgK(mvcmd, drctn) -- i.e.(turtle.up, "Up")
local itr8 = 0
while not mvcmd() do
  local fncnm = "detect"..drctn
  if turtle[fncnm]() then
   fncnm = "dig"..drctn
   if not turtle[fncnm]() then trply("unbreakable block in path") return false end
  elseif turtle.getFuelLevel() == 0 then trply( "Out of fuel" ) return false
  else
   fncnm = "attack"..drctn
   turtle[fncnm]()
  end
  if itr8 > 64 then trply("persistent impediment") return false end
  itr8 = itr8+1
end
return true
end
It uses another function, trply(), that is useful for remote control turtles. But it can be replaced with print() if you're not using remote control.

Holy f…, can I hire you as a script obfuscator?

On another note, it's really just a matter of checking if you managed to proceed, for example

while not turtle.forward() do sleep(0.1); end
dan200 #12
Posted 12 October 2012 - 10:24 AM
*snip*

Or more pertinent:


while not turtle.forward() do turtle.attack() end

>:)/>/>
ChunLing #13
Posted 12 October 2012 - 03:08 PM
The problem is that neither of those deals with the most likely cause of not proceeding, which is having a block in the way.

Looking at my function, I realize that it is a little confusing to read. But because essentially the same function structure can be used for forward, up, and down, I decided to make a single function that would do any of the three. The code for it is a bit longer than just the code for moving forward, but much shorter than having all three movement functions separate.

And since nothing except the movement function gets executed if the movement succeeds, I don't feel it's too inefficient.
BigSHinyToys #14
Posted 12 October 2012 - 05:52 PM
Sorry, what do you mean?

This function uses the commands turtle.forward, turtle.up, and turtle.down and one of the strings "" (an empty string), "Up", or "Down". It loops while the movement command fails, checking whether there is a block in the way and attempting to mine it if there is, checking fuel, and then just attacking towards the obstacle. It's not very "nit picky", as I understand the term.

I meant having to give it two variables is could be annoying over time
robhol #15
Posted 12 October 2012 - 06:50 PM
Efficiency isn't the issue, it's the fact that your code is extremely hard to read for no valid reason.
ChunLing #16
Posted 12 October 2012 - 11:01 PM
I consider efficiency a very valid reason. Still, I know it's hard to read, that's why I explained it.

As for having two variables, I just go ahead and store the basic versions in three smaller functions, like so:
rctfncs = {
dfd = function() return mvdgK(turtle.forward,"") end,
dup = function() return mvdgK(turtle.up,"Up") end,
ddn = function() return mvdgK(turtle.down,"Down") end,
}
They don't have to be in a table like that, but with them all in the table I can easily call them using my remote control program (so I don't have to use a bunch of elseif then statements like most remote control functions I've seen use).
BigSHinyToys #17
Posted 13 October 2012 - 09:37 AM
I consider efficiency a very valid reason. Still, I know it's hard to read, that's why I explained it.

As for having two variables, I just go ahead and store the basic versions in three smaller functions, like so:
rctfncs = {
dfd = function() return mvdgK(turtle.forward,"") end,
dup = function() return mvdgK(turtle.up,"Up") end,
ddn = function() return mvdgK(turtle.down,"Down") end,
}
They don't have to be in a table like that, but with them all in the table I can easily call them using my remote control program (so I don't have to use a bunch of elseif then statements like most remote control functions I've seen use).

or you could do this

local function mvdgK(drctn) -- i.e.(turtle.up, "Up")
local mvcmd = turtle[drctn]
local itr8 = 0
while not mvcmd() do
  local fncnm = "detect"..drctn
  if turtle[fncnm]() then
   fncnm = "dig"..drctn
   if not turtle[fncnm]() then trply("unbreakable block in path") return false end
  elseif turtle.getFuelLevel() == 0 then trply( "Out of fuel" ) return false
  else
   fncnm = "attack"..drctn
   turtle[fncnm]()
  end
  if itr8 > 64 then trply("persistent impediment") return false end
  itr8 = itr8+1
end
return true
end
robhol #18
Posted 13 October 2012 - 09:58 AM
I consider efficiency a very valid reason. Still, I know it's hard to read, that's why I explained it.

The clue here is that "wellFormedClearVariableNameThatExplainsWhatItsFor" isn't (significantly, if at all) less efficient than "wllFrmdClrVrblNmThtXplnsWhttsFr", it's just a nightmare to try and decipher.
ChunLing #19
Posted 13 October 2012 - 04:21 PM
Sorry, my brain works opposite. A variable name that looks like a variable name is easier for me to understand than a "meaningful" name when I'm reading code. But I get your point.

BST, I'm sorry but the revised code doesn't work because "turtle.up" and ""turtle.dig/attackUp" are case mismatched, the same is true for down, and forward is an even worse mismatch. Yeah, I might wish that the functions provided by the API were named differently, but we work with what we've got, or we just wish.

But it's true that I could set the values automatically by using a simple table to associate the direction variable with the functions needed. The thing is, for my remote control program I wanted functions that could be called without needing arguments, which the structure I've used gives me. But now that I think about it, there is no reason I shouldn't use a table that points to the existing functions instead of messing with strings. That would be faster and more adaptable.

So, seeing if I can serve two masters…

function movedigKill(direction) -- i.e.(1 = forward, 2 = up, 3 = down)
local itr8 = 0
local action_list = {{turtle.forward,turtle.detect,turtle.dig,turtle.attack},
  {turtle.up,turtle.detectUp,turtle.digUp,turtle.attackUp},
  {turtle.down,turtle.detectDown,turtle.digDown,turtle.attackDown}}
while not action_list[direction][1]() do
  if action_list[direction][2]() then
   if not action_list[direction][3]() then trply("unbreakable block in path") return false end
  elseif turtle.getFuelLevel() == 0 then trply("Out of fuel" ) return false
  else action_list[direction][4]() end
  if itr8 > 64 then trply("persistent impediment") return false end
  itr8 = itr8+1
end
return true
end

Sorry, looks like I might have failed. But I think I am going to use this new version. It seems faster/better