| View previous topic :: View next topic |
| Author |
Message |
Saitoh_TD
Joined: 19 Apr 2002 Posts: 110 Location: Cornfield, MO
|
Posted: Tue Apr 23, 2002 4:28 pm Post subject: Howto #5: Priority Queues and InputBuffer in Visual Basic |
|
|
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 |
|
 |
Arkayas Teh Decal L33T!


Joined: 19 Apr 2002 Posts: 501
|
Posted: Wed Apr 24, 2002 10:30 am Post subject: Hmmm... |
|
|
'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 |
|
 |
Reron
Joined: 24 Apr 2002 Posts: 3 Location: USA
|
Posted: Wed Apr 24, 2002 2:08 pm Post subject: Performance considerations |
|
|
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 |
|
 |
Saitoh_TD
Joined: 19 Apr 2002 Posts: 110 Location: Cornfield, MO
|
Posted: Wed Apr 24, 2002 5:02 pm Post subject: |
|
|
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 |
|
 |
Guest Guest
|
Posted: Sun May 05, 2002 4:51 pm Post subject: |
|
|
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
|
Posted: Mon May 06, 2002 4:55 pm Post subject: |
|
|
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 |
|
 |
mat Guest
|
Posted: Thu May 16, 2002 10:52 am Post subject: arrays |
|
|
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  |
|
| Back to top |
|
 |
Banli-Zan Guest
|
Posted: Mon May 20, 2002 6:05 pm Post subject: |
|
|
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
|
Posted: Mon May 20, 2002 6:21 pm Post subject: |
|
|
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 |
|
 |
Guest
|
Posted: Wed May 22, 2002 5:34 am Post subject: |
|
|
| nope its a buff bot... need to have it wait for input buffer to complete. |
|
| Back to top |
|
 |
|
|
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
|