Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Lua ➜ creating an Auto-Walker (no pre-knowledge)

creating an Auto-Walker (no pre-knowledge)

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Bjorn Ironfist   (5 posts)  Bio
Date Mon 10 Dec 2018 12:57 PM (UTC)
Message
Hello everyone!

I've been playing MUDs since 2003 and always used MushClient to do so, quite a long time I think.
Nevertheless - and since I am not the best when it comes to programming - it wasn't until recent years that I found out (shame to myself) about the very nice implemented timers and triggers functions (I only used aliases so far).
Times change and so do MUDs. When it was uncomfortable to use scripts in the past, lots of players in my MUD nowaydays do so for leveling. This brought me up with the idea trying to figure it out myself - creating new characters and new classes without months/years of manually killing the same creatures over and over again.

I searched this forum for weeks now, read the introduction to Lua, but still I am not quite sure how to fix certain problems that I have to struggle with.
I found this entry very helpful:
http://www.mushclient.com/forum/?id=8613&reply=8

Based on that I tried to write a timer for myself (since the Lua-Add-Timer-function just caused errors for me).

Here is what I came up with:

I want to cast my protection spells(shields and so on), then run a certain path (that loops) in the wild (no exists visible - just a map) and stop when I meet the desired creature to kill. After doing so continuing on my pre-defined path. If my shield, armor or weapon fails to work, I want to go some steps back, search a secure spot in the wilderness (none or harmless creatures on the field) and then cast my shield, repair armor, eat something etc. After that continuing.
To do so I added some Variables(?) that make something true or false and wrote down the path. It looks like this:



route = {
    "e",  "e",  "e",  "e",  "e",  "e",  "e",  "e",  "se", "w",  "w",  "w",  "w",  "w",  "w",  "w",  "w",  "w",  --very long continuing of the path
          }             
 
  forward = true
  backwards = false
  peaceful = false

  if forward == true or backwards == false then
    loc = (loc or 0) + 1 -- maybe put it somewhere else
    return

  
elseif loc > #route then
    loc = 1
   

elseif backward == true then
loc = (loc or 0) - 1  -- I guess this is not correct

elseif peaceful ~= false then -- this too
Send "heal"
Send "cast shield"
    
    
  end

Send (route [loc])



The variables are:

forward = true
You killed *
Your shield is ready.

forward = false
Your shield collapses.
A horrible creature. -- also triggers attack

backward = true
Your shield collapses.
Your axe broke. -- your armor broke etc

backward = false
Your shield is ready.

peaceful = false
A horrible creature. -- and some other creatures

I tried several things, but all of them didn't work out.
I also have the feeling that the timer somehow misinterprets my desired path. Sometimes I run straight forward to the south or somewhere else (although I always reset the timers before I tried it out again). Even when I do not add any further code, just the path.

I guess these are just minor problems and I hope someone can help me understand what I did wrong. I appreciate that you read so far and have a nice day! :)
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #1 on Mon 10 Dec 2018 08:06 PM (UTC)

Amended on Mon 10 Dec 2018 08:08 PM (UTC) by Nick Gammon

Message
Check you are allowed to make bots first! :)

A few tips:




Put this at the start and then you can forget about loc not existing:


loc = loc or 0   -- initialize if first time





Booleans can be tested more simply. Rather than:


  if forward == true or backwards == false then


You can write:


  if forward or not backwards then


However surely forward and backwards are mutually exclusive? You can't move both directions at once, so just use "forward" and then "not forward" is obviously backwards (unless you want to have "not moving" as an option).




Similarly, here:


elseif backward then   -- don't need to compare to true





Spelling! Make up your mind if it is "backward" or "backwards":


  backwards = false
...
elseif backward == true then  --> "backwards"!




You are adding one to loc here, but not sending it:


if forward == true or backwards == false then
    loc = (loc or 0) + 1 -- maybe put it somewhere else
    return


The "return" will leave that part of the code.




You haven't got a test for when you go off the end of the route table after adding 1 to loc. You have the test if you don't add one, which doesn't make sense.




I suggest adding some debugging prints to help you work out what it is doing. eg.



if forward then
    loc = loc + 1 
    if loc > #route then
       loc = 1
    end -- if passed end
    print ("Now going forward using ", route [loc])
    Send (route [loc])
    return


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Bjorn Ironfist   (5 posts)  Bio
Date Reply #2 on Tue 11 Dec 2018 12:38 PM (UTC)
Message
Hey Nick,

Thanks for your fast answer!
I think I understood almost every proposal of yours, except the following:


Nick Gammon said:

You are adding one to loc here, but not sending it:


if forward == true or backwards == false then
    loc = (loc or 0) + 1 -- maybe put it somewhere else
    return


The "return" will leave that part of the code.


That means that "return" will start the code all over again right? So I should put it at the very end?


Nick Gammon said:

I suggest adding some debugging prints to help you work out what it is doing. eg.



if forward then
    loc = loc + 1 
    if loc > #route then
       loc = 1
    end -- if passed end
    print ("Now going forward using", route [loc])
    Send (route [loc])
    return




I put it into the code and it prints it correctly before moving but unfortunately I can't figure out my mistakes.

Nick Gammon said:

You haven't got a test for when you go off the end of the route table after adding 1 to loc. You have the test if you don't add one, which doesn't make sense.


I tried putting it into my new code - hope you meant that:

route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             
 
loc = loc or 0

  forward = true
  backward = false
  peaceful = false

if forward then
    loc = (loc or 0) + 1
    print ("Now going forward using", route [loc])
    Send (route [loc])

    elseif loc > #route then
    loc = 1

        elseif backward then
        loc = (loc or 0) - 1

        elseif loc < #route then
        loc = - 1

        elseif peaceful ~= false then
        Send "heal"
        Send "cast shield"
    
end

return


I get no error messages so far, but still I am running into some unexpected direction - even after deleting the timer and readding it.
I am just copying this code and paste it into the opened timer-window, maybe thats wrong..? (I set interval to 1 and 'Send To "Script"' - where I put Lua as scripting language and enabled it)
Also I don't stop when I meet the desired creature I want to kill - a trigger goes off that attacks the creature (I have no "stand"-command in my Mud), so I put f.eks. "A horrible creature" as trigger for forward = false + attack, but I just keep moving (into some unexpected direction).

Thanks for your help so far and greets to Australia from the other side of the earth ;)
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #3 on Tue 11 Dec 2018 09:35 PM (UTC)
Message
You still seem to be adding 1 but testing for it to exceed the array in a different spot, ditto for subtracting. It makes much more sense to check for exceeding the array bounds immediately after adding or subtracting.

More like this:



route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             
 
loc = loc or 0    -- loc will be nil first time around

forward = true
backward = false
peaceful = false

if forward then
    loc = loc + 1
    -- overflow?
    if loc > #route then
      loc = 1 
    end -- of past end of array
    Tell ("Now going forward using ")

else  -- backward
  loc = loc - 1
  -- underflow?
  if loc < 1 then  -- arrays start at 1
    loc = #route   -- back to end
  end -- if
  Tell ("Now going backward using ")
end -- if forward or backward

Note (route [loc])  -- show direction
Send (route [loc])  -- send the direction

if not peaceful then
  Send "heal"
  Send "cast shield"    
end  -- if not peaceful





Quote:

That means that "return" will start the code all over again right? So I should put it at the very end?


The return means that the code exits. It doesn't start all over again, until it is called next time.




Quote:

Also I don't stop when I meet the desired creature I want to kill - a trigger goes off that attacks the creature (I have no "stand"-command in my Mud), so I put f.eks. "A horrible creature" as trigger for forward = false + attack, but I just keep moving (into some unexpected direction).


The timer will keep firing, so I would expect that. You might need to rework a bit.

Try reading this:

http://www.gammon.com.au/forum/?id=4957

You probably want to have a coroutine set up (as in the examples) where you do something like:


  • Go a direction
  • If a condition is met start fighting
  • If not, wait a moment, and go back to the start

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Bjorn Ironfist   (5 posts)  Bio
Date Reply #4 on Wed 12 Dec 2018 01:38 PM (UTC)
Message
Thanks again for answering so fast!

Nick Gammon said:

You still seem to be adding 1 but testing for it to exceed the array in a different spot, ditto for subtracting. It makes much more sense to check for exceeding the array bounds immediately after adding or subtracting.


I'm not sure if I understood everything correctly, I really tried keeping in mind everything what was written in the introduction to Lua, but it is still very confusing and difficult if you have no knowledge of programming I guess.

I tested your new code and it works correctly for walking the desired path (into one direction).

Nick Gammon said:

The timer will keep firing, so I would expect that. You might need to rework a bit.

Try reading this:

http://www.gammon.com.au/forum/?id=4957

You probably want to have a coroutine set up (as in the examples) where you do something like:


*Go a direction
*If a condition is met start fighting
*If not, wait a moment, and go back to the start



Yes you are right, I am walking nonstop forward. I found your linked post before, like so many others, but I just don't know what to fill in it or where to put it hence I have no understanding of what it is doing. I guess it is easier when someone explains or teaches you - this is my call of course and not yours. It is just very difficult for me to understand, maybe I have to visit some local programming class (it's very intresting I have to admit).

I found this simple code of yours in another post:


<timers>
  <timer 
   enabled="y" 
   second="2.00" 
   offset_second="0.00"    
   send_to="12"
>
  <send>

route = {
  "s", "s", "e", "n",  -- to butcher
  "s", "w", "n", "n",  -- back again
  }

-- stay here if we are fighting or recovering

if fighting or resting then
  return
end  -- if


loc = (loc or 0) + 1  -- next way to walk

-- if past end, go back to start

if loc &gt; #route then
  loc = 1
end -- if

Send (route [loc])
</send>

  </timer>
</timers>


I used it as example to build my timer - since your timer worked very nice. It stopped me when I wrote something I used as trigger for fighting = true or resting = true.
Thats also why I don't understand my mistakes since I just wanted to add a "backward"-function that makes you rest on a save spot (with no creatures) that is not all the way back along the way (since it is a very long path).
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #5 on Wed 12 Dec 2018 08:59 PM (UTC)
Message
Well, if you are using triggers to detect fighting then the other code is probably almost OK. I modified what I posted above a bit:


route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             

-- initialize variables first time we run this
if not loc then
  forward = true
  peaceful = true
  resting = false
  loc = 0
end -- if first time

-- stay here if we are fighting or recovering

if fighting or resting then
  if not peaceful then
    Send "heal"
    Send "cast shield"    
  end  -- if not peaceful
  return   -- don't move
end  -- if


if forward then
    loc = loc + 1
    -- overflow?
    if loc > #route then
      loc = 1 
    end -- of past end of array
    Tell ("Now going forward using ")

else  -- backward
  loc = loc - 1
  -- underflow?
  if loc < 1 then  -- arrays start at 1
    loc = #route   -- back to end
  end -- if
  Tell ("Now going backward using ")
end -- if forward or backward

Note (route [loc])  -- show direction
Send (route [loc])  -- send the direction

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Bjorn Ironfist   (5 posts)  Bio
Date Reply #6 on Fri 14 Dec 2018 02:52 AM (UTC)
Message
Thanks again for your input Nick!

I tried it and it worked at first (except the backward + casting shield on a save-spot idea). It only printed the forward using, so I guess it just didn't work.

These were my first adjustments:


route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             

-- initialize variables first time we run this
if not loc then
  forward = true
  peaceful = true
  backward = false --replaced 'resting' with 'backward'
  loc = 0
end -- if first time

--[[ stay here if we are fighting or recovering
-> I don't need it since I have no trigger for it

if fighting or resting then

if not peaceful then -- It has to be peaceful, meaning there are no creatures on the field, to cast my shield, otherwise I will die, so:
]]

if not forward then
  if backward and peaceful ~= false then

--[[ since I have no trigger for peaceful = true (because there will simply be no creature on the field)
I put ~= false because peaceful = false is triggered if a creature is on the field
]]
    Send "heal"
    Send "cast shield"    
  end  -- if not forward
  return   -- don't move
end  -- if

-- no further changes by me from this point

if forward then
    loc = loc + 1
    -- overflow?
    if loc > #route then
      loc = 1 
    end -- of past end of array
    Tell ("Now going forward using ")

else  -- backward
  loc = loc - 1
  -- underflow?
  if loc < 1 then  -- arrays start at 1
    loc = #route   -- back to end
  end -- if
  Tell ("Now going backward using ")
end -- if forward or backward

Note (route [loc])  -- show direction
Send (route [loc])  -- send the direction


I tried to "activate" the backward-going and casting a shield on a savespot-idea by the following second adjustments to the code:


route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             

-- initialize variables first time we run this
if not loc then
  forward = true 
--true:creature dead,shield ready;false: creature on field

  peaceful = true
--false: creature on field; no true available

  backward = false
--true: shield/weapon/armor broke;false: shield ready
  loc = 0
end -- if first time

  
if not forward then
    if backward and peaceful ~= false then
        Send "heal"
        Send "cast shield" 
    end
    return -- don't move
end

if forward then
    loc = loc + 1
    if loc > #route then
        loc = 1
    end
    print ("Now going forward using  ")
end 
    
if not forward and backward then --might be wrong from here
    loc = loc - 1

    if backward and loc < 1 then
        loc = #route
    end
    print ("Now going backward using ")
end

Note (route [loc])  -- show direction
Send (route [loc])  -- send the direction


It didn't work, but I'm not sure if I have yet another problem to solve than the code itself. Since the first adjustments worked for simply going forwards, stopping to kill a creature and continue (except the going backwards of course) - I retried the timer later on (after I reset it) and it didn't work as before! I just walked into some strange direction again (printing "Now going forward using"). So I think it has something to do with my client or settings or maybe that mush client is in my windows directory?

Kind regards,
Bjorn
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #7 on Fri 14 Dec 2018 06:43 AM (UTC)
Message
I'm not clear why you need both "backward" and "forward". What is the alternative? Surely if you are going forward you are not going backward, so you only need one variable.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Bjorn Ironfist   (5 posts)  Bio
Date Reply #8 on Fri 14 Dec 2018 10:31 PM (UTC)
Message
Nick Gammon said:

I'm not clear why you need both "backward" and "forward". What is the alternative? Surely if you are going forward you are not going backward, so you only need one variable.


Yes you are right again!
Made me think of another idea of simply not walking back to look for a savespot at all, but instead just going straight forward and let the possibly damaged creature be and then look for a savespot to cast my shield and heal up again.

The new code looks like this:

route = {
    "e",  "e",  "e",  "e",  "e",  "e",  -- and so on  
          }             

-- initialize variables first time we run this
if not loc then
  forward = true 
--[[true:creature dead,shield ready,shield collapses, armor breaks, low hp;false: creature on field ]]

  peaceful = true
-- only false: creature on field; no true available

  search = false
--true: shield/weapon/armor broke;false: shield ready
  loc = 0
end -- if first time

if forward and search then
  peaceful = true --needed to set it on true somehow
end


if not forward then
    if search and peaceful ~= false then
        Send "heal" --Possible to fire only once?
        Send "cast shield"
    end
    return -- don't move
end

if forward or search then
    loc = loc + 1
    if loc > #route then
        loc = 1
    end
    print ("Now going forward using  ")
end 
    
Note (route [loc])  -- show direction
Send (route [loc])  -- send the direction


Also this happened again:
Bjorn Ironfist said:

I retried the timer later on (after I reset it) and it didn't work as before! I just walked into some strange direction again.


It seems to work though if I restart MUSHclient, but doing it every time I'm trying something new is no solution I guess.
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #9 on Sat 15 Dec 2018 12:13 AM (UTC)
Message
Quote:

Made me think of another idea of simply not walking back to look for a savespot at all ...


If you only ever go forward, why have a variable that tells you which direction you are going?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,120 posts)  Bio   Forum Administrator
Date Reply #10 on Sat 15 Dec 2018 05:55 AM (UTC)
Message
Quote:


Send "heal" --Possible to fire only once?



Anything is possible. Think of what you would do as a human. You would think "I won't cast another heal if I did one a moment ago". So, you remember when you cast heal last, and check how much time has elapsed. There are ways of finding out the time.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


24,261 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.