Overview
This was a fun little weekend project.  We'd been discussing, "Object Thinking" at our little study group at work so I used this as an excuse to try and focus on creating clean seperations of concerns and well defined objects.  I think it was a step in the right direction.

If you aren't familar with fishing in the MMORPG game, the World of Warcraft, the gist of how it works is that you press a button in the game and your character casts with his or her virtual fishing pole.  A bobber randomly appears in the general area where you were casting.  Then you watch the bobber and when a fish bites, you click on the bobber and, if you are lucky, you've successfully caught the fish.

Sticking with the theme of an old fishman - I broke up the various taks involved into the different body parts you'd expect to be responsible.  So, for example, the Ears class listens for a sudden spike in volume that would indicate a fish while the 'eyes' class can see when the mouse cursor changes as you pass over the bobber. 

All in all, I was amazed at how well the program worked and how quickly I was able to put it together.  I'll touch on some of the specifics; but I've included the full-source for download. 

Detecting a Fish Splash (Ears.vb)
One of the most difficult things to accomplish in programs of that nature is responding to things that are displayed visual for the user.  The other fishbots I've seen try to scan pixels on the screen for color changes and end up with a fairly poor success rate.  Instead, I decided to listen for the audio 'splash' that accompanies a fish.

You'll see a reference to CoreAudioAPI in the project.  It exposes the AudioMeterInformation.MasterPeakvalue which let's us see the current sound output level.  I've done some trivial averaging with a Queue to help minimize the impact of the game's normal background sounds that vary from zone to zone.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Private Sub tmeTimer_Tick()
 
        ' Get the current level 
        Dim currentVolumnLevel As Integer = CType(SndDevice.AudioMeterInformation.MasterPeakValue * 100, Integer)
        VolumeQueue.Enqueue(currentVolumnLevel)
 
        ' Keep a running queue of the last X sounds as a reference point 
        If VolumeQueue.Count >= MAX_VOLUME_QUEUE_LENGTH Then 
             VolumeQueue.Dequeue()
        End If
 
        ' Determine if the current level is high enough to be a fish 
        If currentVolumnLevel - GetAverageVolume() >= My.Settings.SplashLimit Then 
             RaiseEvent HearsAFish()
        End If
End Sub
Finding the Bobber (Eyes.vb)
Finding the bobber on the screen wasn't quite as elegant as monitoring the sound; but we still managed to avoid interpreting colors of individual pixels.  When we mouse over the bobber the cursor's icon will change.  Thankfully, there is a Win32 API that will let us inspect this.  Essentially, all I'm doing here is moving the mouse around the screen looking for the cursor to change.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<StructLayout(LayoutKind.Sequential)> _
Public Structure CURSORINFO
     Public cbSize As Int32
     Public flags As Int32
     Public hCursor As IntPtr
     Public ptScreenPos As POINT
End Structure
 
<StructLayout(LayoutKind.Sequential)> _
Public Structure POINT
     Public x As Int32
     Public y As Int32
End Structure
 
Public Shared Function GetCurrentCursor() As CURSORINFO
     Dim myInfo As CURSORINFO
     myInfo.cbSize = Marshal.SizeOf(myInfo)
     GetCursorInfo(myInfo)
     Return myInfo
End Function


There is a decent amount of Win32 API calls required to get the job done.  I think the biggest struggle I had was getting the correct datatypes passed into the Win32API calls.  Finding the WoW application Window, moving the mouse, sending key strokes and getting the cursor info...so if you find yourself wanting to do those same tasks in .Net the Win32API class included in the project might be a good starting point.
*** Using Bots on Official WoW Servers May Result In Your Accout Being Banned ***