Decal Development Forums Forum Index Decal Development Forums
www.decaldev.com
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Howto #5: Priority Queues and InputBuffer in Visual Basic

 
Post new topic   Reply to topic    Decal Development Forums Forum Index -> AC FAQ's and Howtos (Archive)
View previous topic :: View next topic  
Author Message
Saitoh_TD



Joined: 19 Apr 2002
Posts: 110
Location: Cornfield, MO

PostPosted: Tue Apr 23, 2002 4:28 pm    Post subject: Howto #5: Priority Queues and InputBuffer in Visual Basic Reply with quote

Howto: Priority Queues and InputBuffer in Visual Basic

Prerequisite: Howto #3: Effectively use InputBuffer in Visual Basic

Definitions:

InputBuffer - An array of "to be executed" commands
FIFO - First In First Out, A queue type where the first action you add, the first action that comes out.
Priority - The value that is set to designat the importance of an action
Queue - an array of pending actions

Concepts:

Since this Howto is a little more advanced, you really should become adept at using InputBuffer first by reading Howto #3: Effectively use InputBuffer in Visual Basic.

So, you wanna bot? In actuallity, you can use priority queues for more than just a bot. But this is where it's usefulness shines. With a priority queue, you can tell your bot to stop what it is doing to do something else more important.

An example of this would be that you want your bot to cast two spells. So, you add the actions of casting spells into your queue. Your bot starts running the actions and after casting the first spell, it's low on mana. What to do? Add a higher priority task of casting Stamina to Mana, so that although you added that task after the two spellcasts, it will still run first.

My reasoning for adding InputBuffer into this fray is because it's really handy for performing actions, works great as a delay mechanism, and also helps to teach queue interactions.

In this tutorial we will, create a priority queue, load it with actions, add immediate and more important actions, and use the InputBuffer. Some of the following code will be pseudocode. I will only use psuedocode for topics that have been discussed in previous Howto's and would add immense amounts of code and not add to the workings of priority queues.

Header:

To make a queue, we just need to make a type for each queue element and then make an array. Also, you will need to create an InputBuffer to use for this example.

Code:

' Create the Elements
Private Type TElement
Action as string
Priority as integer
End Type

'Create the Array
Private MyQueue() as TElement

'Make the InputBuffer
Private InputBuffer as DecalPlugins.InputBuffer

'Is the queue running?
Private QueueRunning as Boolean



Notice how I didn't define a size for the queue? This is because we are going to be resizing it as we go.

Initialize:

The only thing we really need to initialize is the InputBuffer.

Code:

Set Inputbuffer = PluginSite.CreateInputBuffer



Usage:

Lets pretend that we are making a bot that says things, we can easilly just push things from our queue into the input buffer this way. Of course, you could modify your queue for any type of action.

Now, we really only need 2 things to make this work. A subroutine to Add Items to the queue, and one to perform, remove and cleanup.

Adding is easy, we just need to find the maximum size of our queue and then add one.

Code:

Private Sub AddAction(Action as String, Priority as Integer)
'Add one to the array while preserving what is on the array
Redim Preserve MyQueue(ubound(myqueue) + 1)

myqueue(ubound(myqueue)).action = Action
myqueue(ubond(myqueue)).priority = Priority

'If the queue isn't running, start it. It has work to do now!
If QueueRunning = false then performAction
End Sub



Performing and removing is harder? Not exactly, removing would just be us changing the Action and Priority to blanks and zeros. We just want to take it an extra step and remove that element completely. If we don't we can easilly build a massive memory sucking array. The only way I know how to do this is to remove the current element being processed and move everything up one, then clip off the last element.

Code:

Private Sub PerformAction()
Dim Counter as Long
Dim Offset as Long
Dim MaxPriority as Long

Maxpriority = 0

'Make sure we actually have something in here
If Ubound(myqueue) > 0 then
QueueRunning = True
For Counter = lbound(myqueue) to ubound(myqueue)
'Find the first item with the hightest priority, if you wanted the last item with the highest priority, make it >= instead of just >
If myqueue(counter).priority > maxpriority then
offset = counter
maxpriority = myqueue(counter).priority
end if
Next

'Add the action to the queue
inputbuffer.typetext myqueue(offset).action
inputbuffer.run

'Remove the action and push everything up
myqueue(offset).priority = 0
myqueue(offset).action = NULL
For Counter = offset + 1 to ubound(myqueue)
myqueue(counter - 1).priority = myqueue(counter).priority
myqueue(counter - 1).action = myqueue(counter).action
Next
Redim preserve myqueue(ubound(myqueue)-1)
else
QueueRunning = False
End if




Smashing! Now why the inputbuffer? Because it was my plan to use InputBuffer_End as my trigger to run PerformAction for the next item on the queue.

Code:

Private Sub InputBuffer_End()
Call PerformAction
End Sub




Summary:

Now you are another step closer to making a bot.
_________________
- Navi - Navi II - Navi III -
http://www.saigumi.net
http://navi3.sourceforge.net


Last edited by Saitoh_TD on Sat Jul 06, 2002 7:46 pm; edited 4 times in total
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Arkayas
Teh Decal L33T!
Teh Decal L33T!


Joined: 19 Apr 2002
Posts: 501

PostPosted: Wed Apr 24, 2002 10:30 am    Post subject: Hmmm... Reply with quote

'Add one to the array while preserving what is on the array
Redim MyQueue(ubound(myqueue) + 1)

Are you not missing the dreadded key word there???

Preserve
Back to top
View user's profile Send private message
Reron



Joined: 24 Apr 2002
Posts: 3
Location: USA

PostPosted: Wed Apr 24, 2002 2:08 pm    Post subject: Performance considerations Reply with quote

Redimming the array every time you add or remove an item is fairly expensive & slow. Probably not a big deal in cases where the actions are added and removed fairly slowly but if you use a method like this for a more active stack you may want to choose a more performant scheme.

The easiest would be strart with an array of a nominal size (e.g. a few dozen items) and instead of indexing off UBound(array) maintain a separate index variable that you increment/decrement. If you fill the array and need to grow it, grow it by 10% rather than 1 to limit how often you need to redim the array.
_________________
Reron, axe carrying member of DGS, FrostFell
Back to top
View user's profile Send private message
Saitoh_TD



Joined: 19 Apr 2002
Posts: 110
Location: Cornfield, MO

PostPosted: Wed Apr 24, 2002 5:02 pm    Post subject: Reply with quote

Doh.. I remembered Preserve in one place, forgot the other.

ReDimming your array is indeed slow with large array, and actually, you can indeed do resizing and cleanup any time you want. This is just one style. Feel free to adjust your system of adding and removing.
_________________
- Navi - Navi II - Navi III -
http://www.saigumi.net
http://navi3.sourceforge.net
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Guest
Guest





PostPosted: Sun May 05, 2002 4:51 pm    Post subject: Reply with quote

what sort of command string is it looking for? like

MouseClick 200, 200, eMouseInputLeft

equiv of method and params except in string?

secondly there is no AddItem method in DecalPlugins.InputBuffer, there is in DecalControls.InputBuffer though
Back to top
Saitoh_TD



Joined: 19 Apr 2002
Posts: 110
Location: Cornfield, MO

PostPosted: Mon May 06, 2002 4:55 pm    Post subject: Reply with quote

Actually, I got a little ahead of myself I meant to add an AddItem function to the example that would parse the added command to recognize between a mouse or a typetext command.

But for now, I just replaced it with TypeText for the example.
_________________
- Navi - Navi II - Navi III -
http://www.saigumi.net
http://navi3.sourceforge.net
Back to top
View user's profile Send private message Send e-mail Visit poster's website
mat
Guest





PostPosted: Thu May 16, 2002 10:52 am    Post subject: arrays Reply with quote

Using collections would be a whole lot easier and less likely to lead to memory problems. They are very easy to learn how to use too Smile
Back to top
Banli-Zan
Guest





PostPosted: Mon May 20, 2002 6:05 pm    Post subject: Reply with quote

I can not figure out how to make Visual Basic complete the Input Buffer BEFORE moving on...

say my Routine was set up like this

Code:

Private Sub IFilter_ReceivedDirectChat(ChatColor As Long, SenderID As Long, SenderName As String, Message As String, ReceiverID As Long)
On Error Resume Next
If Message = "akka" Then
Call YouGotTheCorrectWord
Call PluginSite.CastSpell(KFilter.SpellInfo.SpellByName("Leadership Mastery Self VI").ID, KFilter.CharacterInfo.ID)
Else
Call YouDidntGetIt
End If
End Sub


ok... if someone tells me "akka" it will call YouGotTheCorrectWord and automaticly start
Code:

Call PluginSite.CastSpell(KFilter.SpellInfo.SpellByName("Leadership Mastery Self VI").ID, KFilter.CharacterInfo.ID)


Without waiting for "Call YouGotTheCorrectWord" to finish
Back to top
Moputu



Joined: 19 Apr 2002
Posts: 22
Location: Sawato, Leafcull

PostPosted: Mon May 20, 2002 6:21 pm    Post subject: Reply with quote

You can have the InputBuffer_End even fire off your SpellCast.

If that isn't the only thing that the input buffer runs, you can always create a flag to tell it to run the command or not.

Code:

Option Explicit
Public lOp As Long

Private Sub IFilter_ReceivedDirectChat(ChatColor As Long, SenderID As Long, SenderName As String, Message As String, ReceiverID As Long)
  On Error Resume Next
  If Message = "akka" Then
    lOp = 1
    Call YouGotTheCorrectWord
  Else
    Call YouDidntGetIt
  End If
End Sub

Private Sub InputBuffer_End()
  Select Case lOp
    Case 1
      Call PluginSite.CastSpell(KFilter.SpellInfo.SpellByName("Leadership Mastery Self VI").ID, KFilter.CharacterInfo.ID)
  End Select
  lOp = 0
'  wtcw "InputBuffer_End"
End Sub

_________________
As Dysfunctional as it gets.
Back to top
View user's profile Send private message
Guest






PostPosted: Wed May 22, 2002 5:34 am    Post subject: Reply with quote

nope its a buff bot... need to have it wait for input buffer to complete.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Decal Development Forums Forum Index -> AC FAQ's and Howtos (Archive) All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group