How I Built a Working Online Poker Bot, Part 4: The Poker Botting Erector Set
Friday, June 27, 2008   

Introduction

Today we're going to build a simple online poker bot—the simplest possible online poker bot—in just a few hundred lines of code.

But first: have you ever tinkered around with an erector set?

You remember. Colorful cardboard boxes with see-through fronts. Girders and gears, nuts and bolts, even the occasional electric motor.

A classic brand with over 90 years of building experience, Erector introduces an incredible 50-Model building set. It has a whopping 605 pieces for building 50 different models, including a helicopter, a construction truck with crane, a scooter and more. A powerful 6V motor brings life to your creations, and special mechanical functions create unique and exciting movements.

Set includes an assortment of construction materials and fasteners, plus detailed, step-by-step instructions with photographs -- no reading required. Requires 3 "AA" batteries, not included.

The thing that always appealed to me about Erector Sets? Ingredients. Dozens of components, each with a specific, and yet generic, purpose. Not to mention the recipes: instructions for assembling those components. With a little time and some careful screwdriver work, you could build just about anything. 

Charles Babbage's Difference Engine #2, Built by Tim Robinson

Charles Babbage, eat your heart out.

But what do erector sets have to do with poker, programming, and poker botting?

Well, a lot of people have written me or left comments to the effect of: show us the code, buddy. And for the past couple weeks I've struggled with how to do that.

  • First, there's a lot of code. We're talking a sizeable production code base, with various versions and branches, and a lot of half-finished one-off tools. Utility libraries, hand evaluators, history analyzers, DLL injectors, you name it.
  • Second, I don't have complete control over said code. Before too long, I'll introduce my poker buddy, botting partner, former client, and general co-conspirator, Mr. Anonymous. He has a stake in all this, too.
  • Third, the code is quite valuable on its face. Not because I'm such a superb programmer, or poker player—I've made more than my share of mistakes in both arenas—but because it's had the benefit of thousands of hours of work.

And as we start to publicize it, that value, that potential energy, depreciates.

So what to do?

Sell it? Open-source it? Discuss it?

And that's when a friend sent me a link to the above picture and I thought: aha!

Erector sets.

Self-Contained Experimental Botting Goodness

Programmers, like poker players, have a behavioral profile. They prefer a certain language, a certain methodology, a certain environment. My favorite languages are C# and C++. Yours might be Java and PHP.

When it comes to botting (or software automation in general) we're all hoping to take something different away from the table. Some come to learn. Some want to make money. Some have a product they'd like to build, or a built product they'd like to automate. Some are interested in poker, others spend their time on World of Warcraft, and still others invest their energy in the stock market. Some want specific code they can download, build, and use. Others just want the techniques.

So rather than posting isolated code samples without any context, and rather than posting a hundred thousand source lines of code without any focus, we'll take the middle ground: the software erector set. That's a self-contained package of ingredients—source code, tools, information—together with instructions for turning those ingredients into something real and, as we progress further into the series, something useful.

That means various flavors of bots:

  • FoldBots
  • TrashBots
  • Autofolders
  • ShortBots
  • DeepBots
  • General (non-poker) software automation tools

Various poker-related tools:

  • Simulators
  • Hand Evaluators
  • History Analyzers
  • Poker Calculators

And some other stuff as well.

Obviously this is a little much to handle in a single series—you'd end up with 400 articles, and I'd have to start saying things like: "In Part 267, I pointed out, for the fifty-sixth time, that DLL Injection isn't the only way to build a bot."

The poker botting series will continue indefinitely. But software automation and human emulation, poker-related and otherwise, will now be a primary content line on Coding the Wheel.

After all, that's kind of what the name means.

Or did you think I just woke up one day and decided to start blogging about poker bots?

The Simplest of All Possible Bots: Introducing the FoldBot

The first code sample/erector set I'd like to present is what happens when you start to apply iterative, incremental development to online poker botting. Before we tackle generic poker A.I., let's see if we can get a proof of concept up and running. Let's see if we can create a bot which:

  • Reads our hole cards
  • Clicks a button (it doesn't matter which)

This is what you might call the Ground Zero of software automation. It's where everything begins: software with the ability to see and touch. (And when I say "see" I don't mean image recognition, or at least, I don't mean image recognition exclusively. For a poker bot, "seeing" might be the ability to extract text from a window by snooping on window memory, sending a WM_GETTEXT, etc. But the end result is the same.)

Here's a picture of the FoldBot in action: 

Simple. The FoldBot is the simplest of all possible online poker bots. It doesn't understand, want to understand, or need to understand, poker. It doesn't understand online poker. It doesn't even know how to recognize a poker hand. It only knows how to do three things:

  • INPUT: Extract your hole cards and other table information from one or more online poker tables.
  • PROCESSING: Decide to fold every hand (yes, even pocket Aces).
  • OUTPUT: Click the Fold button when it's your turn to act.

That's the simplest possible Input stage, the simplest possible Processing stage, and the simplest possible Output stage.

And yet, with some additional work, the FoldBot can become a TrashBot (a bot intended to fold garbage hands) which in turn becomes an Autofolder (a bot intended to automate preflop play) which in turn becomes a ShortBot, which in turn becomes a DeepBot capable of playing deep-stacked poker on all rounds of betting, and so forth. We'll explore all of these at some point, and we'll follow the long-established practice of giving short, often cute or cryptic, names to our bots.

Which Online Poker Venues Does It Support?

The FoldBot is specialized for the PokerTime online poker venue (http://www.pokertime.com) so you'll need to download the (free) software and set up a (play-money) account in order to see it in action.

Why are we using PokerTime, instead of a more popular venue like PokerStars or Full Tilt?

Because it makes our Input stage very simple.

But don't worry: we'll add support for Poker Stars, Full Tilt, and other major poker venues, shortlyin case they should feel left out of the botting extravaganza. Extracting text from Poker Stars is slightly more difficult than PokerTime, but only slightly. Botting rules apply here:

Botting Rule #68: It's virtually impossible for a program to display human-readable text on the screen without exposing that text to other programs running on the machine. You might as well not even try.

This is especially the case when the text has to be easy to read, as it does in online poker, where 4x and 8x multi-tabling is commonplace. But even if we allow the text to be difficult to read, well, we're fast approaching the time where if a human can read it, software can too. As Jeff Atwood points out in CAPTCHA Is Dead, Long Live CAPTCHA!, even CAPTCHAs which were once thought to be unbreakable—Google, Yahoo, Hotmail—have since been broken.

2008 is shaping up to be a very bad year indeed for CAPTCHAs:

Which means I am now 0 for 3. Understand that I am no fan of CAPTCHA. I view them as a necessary and important evil, one of precious few things separating average internet users from a torrential deluge of email, comment, and forum spam.

In fact, I believe the text-only CAPTCHA is doomed to failure, as a long-term mechanism for separating the humans from the bots.

But I digress. On to the code.

About the Code

Download the FoldBot Source Code (C++/Windows 145KB).

The FoldBot code consists of two small projects, both implemented in C++.

The purpose of each project is straightforward:

  • XPokerBot.MfcView is the (simple and minimalistic) GUI. This is a standard Windows executable (.EXE).
  • XPokerBot.Hook is the payload containing the meat of the bot's "intelligence". This is a standard Windows dynamic-link library (.DLL).

In order to build them, you'll need:

  • Microsoft Visual Studio 2003, 2005, or 2008. VS2005 and VS2008 are both available as fully-functional, 90-day trial editions.
  • The C++ Boost libraries (for regular expression support).

This version of the bot has only been tested on Windows XP, so if you're running Vista or Windows 2000, you might have to do a little tweaking.

But far and away the most difficult part of building the source code is dealing with the Boost libraries. For step-by-step instructions, check out Boost: Getting Started on Windows. If you run into specific problems, you can try posting to the Boost Configuration forums on Nabble. And if all else fails, why, you can simply comment out the Boost code. It's only used in a couple places, for regular expression support. Rewriting that code to use plain vanilla string manipulation should be straightforward.

How It Works

The FoldBot, while simple, makes use of some interesting techniques:

  • Windows Hooks
  • DLL Injection
  • Window Subclassing
  • Rich Text Interception
  • Interprocess Communication (IPC)
  • Regular Expressions
  • Input Simulation

Here's what it does in a nutshell:

  1. Inject the botting DLL into the poker client's address space.
  2. Respond to (poker table) window create notifications via the CBT hook.
  3. Subclass the poker table's (RichEdit control) chat window.
  4. Intercept chat window text by listening for and parsing EM_STREAMIN messages.
  5. Parse the text using simple regular expressions.
  6. Simulate input (clicking the Fold button) at the right time, based on those messages.
  7. Transmit hole card and table information to the poker bot GUI via simple IPC.

Not too bad. No rocket science here. Now let's look at the individual steps.

Step 1: Inject the DLL

The first thing the bot does is inject a DLL (XPokerBot.Hook.dll) into the poker client process, using the same CBT Hook injection technique I mentioned in Part 1:

bool XPOKERBOTHOOK_API InstallHook()
{
    g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, g_hInstance, 0);

    return g_hHook != NULL;
}

That causes the DLL to be mapped into the address space of every process on the machine, including the poker client. Normally we might be concerned about overhead, but this DLL is fairly small. More to the point, it's almost completely inert when instantiated in an irrelevant (non-poker) process. As we start adding functionality to the DLL and it grows larger, we can switch to the two-stage injection approach:

But for now it's not necessary.

Step 2: Detect the opening and closing of poker windows

Another benefit of the CBT Hook approach is that it gives us a handy way to detect the opening and closing of poker table windows, and any other top-level windows of interest:

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode < 0)
        return CallNextHookEx(g_hHook, nCode, wParam, lParam);
    else if (!g_pClient)
        return 0;

    // Window was activated. We currently use this to detect window creation also.
    // Why not use HCBT_CREATE? Because often the window doesn't yet have a caption
    // when HCBT_CREATE is called, and our sample window-detection logic looks
    // at the window caption to determine the type.
    HWND hWnd = (HWND)wParam;
    if (!hWnd)
        return 0;

    if (nCode == HCBT_ACTIVATE)
    {
        if (!g_pClient->IsRegisteredWindow(hWnd))
            g_pClient->TryRegisterWindow(hWnd, NULL);
    }
    else if (nCode == HCBT_DESTROYWND)
    {
        if (g_pClient->IsRegisteredWindow(hWnd))
            g_pClient->UnregisterWindow(hWnd);
    }

    // Return 0 to allow window creation/destruction/activation to proceed as normal.
    return 0;
}

Here we can guess that that the HCBT_ACTIVATE message is sent when a given top-level window is activated, and that the HCBT_DESTROYWND message is sent when a given top-level window is closed. And we have some simple code to store or remove the window to or from the list of "managed" windows in each case.

The only thing to note here is that we can't really use HCBT_CREATEWND notification when we're answering the "is this a poker table window?" question by examining the window caption. That's because the window caption is usually empty at the time the HCBT_CREATEWND notification is sent. There are ways around this such as delayed creation but we don't need to go to such lengths, certainly not for this incarnation of the bot.

Step 3: Subclass the Chat Window

Now that we're able to detect when poker table windows are opened and closed, we need to extract text from the table chat window. The technique I'm describing here will only work on certain windows, such as the Windows rich edit control, so it may or may not be appropriate for a particular poker client or other gaming application.

Basically we want to subclass the chat window, listen for the EM_STREAMIN message, and replace the callback function provided by the poker client with one of our own. In this sample, I'm subclassing the window when it's first recruited into the poker botting runtime, but strictly speaking, the subclass doesn't have to be installed until the user/bot actually sits down, or even until the user issues a command saying, "okay, automate this table for me."

For each newly-created poker table window, the OnlinePokerClient::TryRegisterWindow method creates a corresponding OnlineTableWindow-derived object—in this case, a PokerTimeTableWindow object. During the construction of that object, we subclass the table's chat window, allowing us to intercept messages sent (by the PokerTime application) to this window:

PokerTimeTableWindow::PokerTimeTableWindow(HWND hWnd, PokerTimePokerClient* client) :
    OnlineTableWindow(hWnd, client)
{
    // Find the chat box...
    HWND hwndChat = ::FindWindowEx(hWnd, NULL, _T("RichEdit20W"), NULL);
    if (hwndChat)
    {
        // And subclass it!
        PokerTimeTableWindow::OldRichWndProc = (WNDPROC)::GetWindowLongPtr(hwndChat, GWL_WNDPROC);
        ::SetWindowLongPtr(hwndChat, GWL_WNDPROC, (LONG_PTR)PokerTimeTableWindow::MyRichWndProc);
    }
}

Step 4: Intercept chat window text

Technically speaking, the chat text window (on PokerTime) is a Rich Edit control. In order to fill this window with text, the Poker Time client sends it a standard EM_STREAMIN message, which our code intercepts:

LRESULT PokerTimeTableWindow::MyRichWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    EDITSTREAM* es = (EDITSTREAM*) lParam;

    if (msg == EM_STREAMIN)
    {
        // Store the original EDITSTREAMCALLBACK and replace it with our own..
        PokerTimeTableWindow::OldRichEditCB = es->pfnCallback;
        es->pfnCallback = PokerTimeTableWindow::MyEditStreamCallback;
        // Hack - keep track of current window
        PokerTimeTableWindow::CurrentChatWindow = hWnd;
    }

    // Call the original window procedure, with our new EDITSTREAMCALLBACK in place
    LRESULT lRet = ::CallWindowProc(PokerTimeTableWindow::OldRichWndProc, hWnd, msg, wParam, lParam);

    if (msg == EM_STREAMIN)
    {
        // Restore the original EDITSTREAMCALLBACK function
        es->pfnCallback = PokerTimeTableWindow::OldRichEditCB;
    }

    return lRet;
}

If you've ever worked with EM_STREAMIN before, you know that you have to provide it with a callback function—specifically, an EDITSTREAMCALLBACK function. That's just what the PokerTime client is doing. What we want to do is somehow replace that callback function (which we'll call A) with our own (which we'll call B). We want Windows to call our callback (B), which will in turn call the PokerTime callback (A) to retrieve the text. That's the purpose of these two lines of code:

// Store the original EDITSTREAMCALLBACK and replace it with our own..
PokerTimeTableWindow::OldRichEditCB = es->pfnCallback;
es->pfnCallback = PokerTimeTableWindow::MyEditStreamCallback;

We're actually overwriting the EDITSTREAMCALLBACK member of the EDITSTREAM structure passed in by the client. So as far as Windows is concerned, it's processing a perfectly normal EM_STREAMIN message. And as far as the PokerTime client is concerned, it's sending a perfectly normal EM_STREAMIN message which it expects to be handled by Windows.

Step 5: Parse the Chat Text

In the meantime, we get a chance to parse the text generated by the poker client using a couple simple regular expressions:

DWORD CALLBACK PokerTimeTableWindow::MyEditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG numberOfBytes, LONG* actualBytes)
{
    // Call the original (PokerTime-provided) callback to get the text..
    DWORD dwRet = PokerTimeTableWindow::OldRichEditCB(dwCookie, pbBuff, numberOfBytes, actualBytes);
    if (0 == dwRet && actualBytes && *actualBytes > 0)
    {
        // 
        // do some busy work...
        // 

        // We're looking for the line (in the PokerTime text window) that looks like this:
        //> Dealing Hole Cards(8d Kc )
        boost::smatch what;
        if( boost::regex_match(line, what, regHoleCards, boost::match_default|boost::match_single_line) && what.size() == 3)
        {
            string sCard1 = what[1];
            string sCard2 = what[2];

            ApplicationProxy::TransmitHoleCards((sCard1 + sCard2).c_str(), hPokerTable);
        }
        //> JohnDoe, you have 10 seconds to respond
        //> JohnDoe, you have 5 seconds to respond
        else if (boost::regex_match(line, what, regWakeUp, boost::match_default|boost::match_single_line) && what.size() == 3)
        {
            string theActor = what[1];
            if (theActor == g_pClient->LoggedInAs)
                OnlinePokerExecutor::PerformAction(hPokerTable);
        }

Specifically, we're looking for two pieces of text:

  • "Dealing Hole Cards(Ah Ad)"
  • "JohnDoe, you have 10 seconds to respond"

The equivalent regular expressions, stripped of the redundant C++ backslash escapes (really makes you long for the world of verbatim @ strings such as we enjoy in C#, doesn't it?), look like this:

  • ^\s*>\s*Dealing\ Hole\ Cards(?:\((.{2,3})\ (.{2,3})\ \))?\s*$
  • ^\s*>\s*(.*),\ you\ have\ (\d+)\ seconds\ to\ respond\s*$

There are better regular expressions out there, but these are just an example. Ultimately we'll want to create a generic regular expression engine which is powerful enough to analyze text from multiple poker venues, using named capture groups. But that's a topic for another post.

Step 6: Simulate User Input

The "JohnDoe, you have 10 seconds to respond" message is our v1.0 method of detecting when it's our turn to act. We're obviously going to have to improve on that before we turn the bot loose, but for now, it's an easy way to queue the logic to click the Fold button. Once we know it's our turn to act, we leverage our bot's impressive A.I...

Fold all hands without exception.

...and invoke our not-too-imaginatively named OnlinePokerExecutor object to perform the actual click of the Fold button.

//> JohnDoe, you have 10 seconds to respond
//> JohnDoe, you have 5 seconds to respond
else if (boost::regex_match(line, what, regWakeUp, boost::match_default|boost::match_single_line) && what.size() == 3)
{
    string theActor = what[1];
    if (theActor == g_pClient->LoggedInAs)
        OnlinePokerExecutor::PerformAction(hPokerTable);
}

The implementation of that, unfortunately, is a little messy. No matter; we can abstract the details of input simulation away into an easy-to-use class. For now, here's a hard-coded, somewhat kludgy attempt:

void OnlinePokerExecutor::PerformAction(HWND hPokerTable)
{
    // Coordinates of our click spot (relative to poker table client area)
    POINT ptCoords;
    ptCoords.x = 290;
    ptCoords.y = 513;
    //ptCoords.x = 450;
    //ptCoords.y = 354;

    // Convert client coords to screen
    ::ClientToScreen(hPokerTable, &ptCoords);

    // Get the screen resolution
    HDC hdc = ::GetDC(NULL);
    int screenWidth = ::GetDeviceCaps(hdc, HORZRES);
    int screenHeight= ::GetDeviceCaps(hdc, VERTRES);
    ::ReleaseDC(NULL, hdc);

    // Convert our screen coordinates to world coordinates
    double temp1 = 65535 * ptCoords.x;
    double dX = temp1 / screenWidth;
    temp1 = 65535 * ptCoords.y;
    double dY = temp1 / screenHeight;

    // Now lets create our mouse inputs..
    INPUT input[4];
    MOUSEINPUT mouseInput;

    // Move the mouse to the button...
    input[0].type=INPUT_MOUSE;
    mouseInput.dx = (int)dX;
    mouseInput.dy = (int)dY;
    mouseInput.mouseData = NULL;
    mouseInput.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
    mouseInput.time = 0;
    mouseInput.dwExtraInfo = 1001;
    input[0].mi = mouseInput;

    // Left-click the mouse down
    input[1].type=INPUT_MOUSE;
    mouseInput.dx = (int)dX;
    mouseInput.dy = (int)dY;
    mouseInput.mouseData = NULL;
    mouseInput.dwFlags = MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_ABSOLUTE;
    mouseInput.time = 0;
    mouseInput.dwExtraInfo = 1001;
    input[1].mi = mouseInput;

    // ..and release it
    input[2].type=INPUT_MOUSE;
    mouseInput.dx = (int)dX;
    mouseInput.dy = (int)dY;
    mouseInput.mouseData = NULL;
    mouseInput.dwFlags = MOUSEEVENTF_LEFTUP|MOUSEEVENTF_ABSOLUTE;
    mouseInput.time = 0;
    mouseInput.dwExtraInfo = 1001;
    input[2].mi = mouseInput;

    // Move the mouse to where it was before
    input[3].type=INPUT_MOUSE;
    mouseInput.dx = (int)dX;
    mouseInput.dy = (int)dY;
    mouseInput.mouseData = NULL;
    mouseInput.dwFlags = MOUSEEVENTF_MOVE|MOUSEEVENTF_ABSOLUTE;
    mouseInput.time = 0;
    mouseInput.dwExtraInfo = 1001;
    //input[3].mi = mouseInput;

    int numberOfInputs = 3;

    // Remember which window has the focus, so we can restore it to that window.
    GUITHREADINFO info;
    ::ZeroMemory(&info, sizeof(info));
    info.cbSize = sizeof(info);
    ::GetGUIThreadInfo(NULL, &info);

    // Also get the current mouse position, so we can restore that.
    POINT ptCursor;
    if (::GetCursorPos(&ptCursor))
    {
        numberOfInputs++;

        temp1 = 65535 * ptCursor.x;
        mouseInput.dx = (int)(temp1 / screenWidth);
        temp1 = 65535 * ptCursor.y;
        mouseInput.dy = (int)(temp1 / screenHeight);
        input[3].mi = mouseInput;
    }

    // Make sure this window isn't obscured behind some other window
    ::BringWindowToTop(hPokerTable);

    // Now actually send the mouse input
    ::SendInput(numberOfInputs, input, sizeof(INPUT));

    // Reset the focus to the previous window
    if (info.hwndFocus)
        ::SetFocus(info.hwndFocus);
}

Another problem with the above input simulation is that the mouse coordinates (button locations) are hard-coded. This is really the type of data you want to "file and forget" in an external XML or other settings file—which is just what we'll do, in future versions of the bot. We'll also want to add random (or normal distribution) input timing along with a few other features. And of course, SendInput is just one way of several ways to simulate user input.

Step 7: Update the GUI

The last piece is to somehow get this data (our hole cards and open tables) to display in the bot's UI. The problem is that the bot user interface lives in one process, and our hook DLL lives in another. So whatever we do is going to involve some sort of inter-process communication or IPC. (Note, however, that you can create a full botting GUI, living entirely in the poker client's process, without a separate .EXE at all.)

For now, let's throw some "poor man's IPC" at the problem by manhandling the data into a WM_COPYDATA message. We'll look at cleaner and more robust approaches as needed.

void ApplicationProxy::TransmitHoleCards(LPCSTR cards, HWND hPokerTable)
{
    HWND hWnd = ::FindWindow(NULL, _T("FoldBot v1.0a"));
    if (hWnd)
    {
        COPYDATASTRUCT cds;
        ::ZeroMemory(&cds, sizeof(COPYDATASTRUCT));
        cds.dwData = (DWORD)hPokerTable;
        cds.lpData = (PVOID)cards;
        cds.cbData = strlen(cards) + 1;
        ::SendMessage(hWnd, WM_COPYDATA, (WPARAM)hPokerTable, (LPARAM)&cds);
    }
}

Meanwhile, the code sitting on the other side of that message can implement a WM_COPYDATA handler, extract the data, and display it appropriately.

Revisiting the Choice of Language

In Part One of this series, I suggested that the ideal language for bot-building was C++. A lot of people took that as a sort of language elitism. So I'd would now like to qualify that statement.

Build the bot in whatever language you're most comfortable with. When it comes to DLL injection, API hooking, log file snooping, stealth, and other "close to the metal" techniques, you'll find these are easier in C and C++ than in other languages (the greatest weakness of C/C++ also happens to be its greatest strength). It saves you the considerable trouble of accomplishing these things through P/Invoke or Interop or other virtualization layers. But the bot's domain modelling and A.I. aspects can and should be built in whatever langage you prefer. It depends on your level of comfort with your current language, with C/C++, and with the Windows API.

I used C++ (and later, C#) exclusively in the creation of the bot. That's C++ for the close-to-the-metal components, and C# for domain modelling and A.I. So the code samples I publish, today and in the future, will more or less reflect that. If you'd rather see these techniques in another language: what are you waiting for? The code isn't going to walk out of the compiler and migrate itself.

Disclaimer

Like many programmers, I have an almost superhuman ability to produce ugly, buggy, downright evil code. While the "production" botting source code has had the benefit of constant use and refactoring, the same can't be said for all of the samples I'll be publishing. In order to highlight particular techniques without burying innocent bystanders under an avalanche of sloc, I've had to manhandle the source in various ways:

  • By removing error handling.
  • By collapsing objects or object hierarchies into global variables or removing them entirely.
  • By occasionally introducing classes, methods, etc., which we'll end up throwing away as we put together more powerful abstractions.
  • By relying on quick hacks and naive solutions when necessary to keep the code samples relevant.
  • By severing important dependencies.
  • By ignoring bugs when they're irrelevant to the topic at hand.

And so forth. So it should go without saying that the code is intended to illustrate practical techniques, rather than proper coding style.

Using the FoldBot

The instructions for use are bundled with the software, but here are the basic steps.

  1. Build the FoldBot.
  2. Download the PokerTime client. Create a play-money account.
  3. Launch the FoldBot.
  4. Launch the PokerTime client.
  5. Open one or more poker table windows.
  6. The table name(s) should appear in the Fold Bot GUI.
  7. Sit down at one or more tables and wait for a hand.
  8. Your hole cards should appear in the FoldBot GUI.
  9. When it's your turn to act, don't do anything. Wait.
  10. Continue waiting until the PokerTime client prompts you with the message "so-and-so, you have 10 seconds to respond".
  11. Your hand should now be folded.
  12. Leave the table(s).
  13. The table(s) should disappear from the FoldBot GUI.

The acid test for whether or not the FoldBot is actually working, is whether it displays PokerTime tables as you open them.

Look Ma! No Hands!

Even if you shut the FoldBot application (.EXE) down, it will continue folding your hands on any table which you opened up when the FoldBot was running. Any tables opened after you close the FoldBot GUI won't be folded.

This has to do with the fact that, although we "pin" the Hook DLL in the poker client's address space via a redundant call to LoadLibrary, the Windows CBT hook itself dies when the FoldBot GUI shuts down. So the Hook DLL is still mapped, but you no longer receive CBT notifications, which means new windows don't get subclassed. This behavior is pretty easy to change but it's good to see an EXE-less, GUI-less bot in practice.

Conclusion

Believe it or not, we covered a lot of ground today. Although this code isn't going to be too useful for established botters, except perhaps as a way to compare notes, it's illustrative. We'll take these techniques and add them to our arsenal for the next incarnation of the bot: the TrashBot, a.k.a., the first "useful" bot.

We'll also reintroduce Detours, with a twist. We'll talk about what poker has to do with the Fastest Gun in the West. And I might even tell you about how the Twelve of Spades changed my life, though I have a hard and fast rule to never, ever tell a bad beat story over the web. And at some point we'll have to take a stroll through the underbelly of poker, before too long. Unscrupulous business practices; routinely poor quality of service; and the fact that yes, sometimes your opponents really CAN see your hole cards.

Until then: thanks for reading, as always, and good luck to you in your poker and programming struggles.


Posted by James Devlin   229 comment(s)

Finally! I fired up google reader and saw your entry and I was so happy! Just in time for the weekend. I got a hold of Windows Via C/C++ and I'm gonna try to extend this before your next article for learning/hacking purposes. Thanks man.

Jesus DeLaTorre on 6/27/2008 10:57 PM (621 days ago)

James- Just ran it over here. Haven't spent too much time with it but looks good. I for one would like to see some C# as well... any of that in the pipeline?

Keith on 6/27/2008 11:51 PM (621 days ago)

How whould you read the hole cards, in case the client doesnt display them in the chat.

Anonymous on 6/27/2008 11:59 PM (621 days ago)

@Jesus, @Kevin: thanks! Yes we'll do some C# as well.

@Anonymous: make sure that the chat window is actually visible (it can be collapsed). Also: set the PokerTime game text option to "Full Detail". The easiest thing is probably just to make sure you're using the "Large View" (where the text box is displayed along the right side of the window).

I'll add these details to the instructions above.

James Devlin on 6/28/2008 1:04 AM (620 days ago)

Thanks for the continuation of this most interesting series! I know people told you before, you do have a clear writing style even when you're writing about code.

paul on 6/28/2008 1:18 AM (620 days ago)

Excellent series of articles. I have been following your analysis since the first article and I am looking forward for the next ones. I became nostalgic of my student days and the late night talks with friends after reading 'Bringing Down the House' ;)

Patroklos Argyroudis on 6/28/2008 2:15 AM (620 days ago)

@paul: Thanks- if I can fumble my way around a topic without botching it too badly, I'm happy ;)

@Patroklos: Thanks also. That by the way is an excellent book and a fun read. Writing about blackjack in such a way as to make it interesting? Tough. And then BDTH came out.

James Devlin on 6/28/2008 3:44 AM (620 days ago)

Thanks for another well-written and captivating article. Hope to see them coming Smile

One question: What do you think about VS 2008 Express Edition as the coding platform of choice? Is it functional enough?

Peter on 6/28/2008 5:57 AM (620 days ago)

Man!! you really rock!!!, dont show me the code, show me the money!!

Really good work, i am very glad to read your blog!

Eugenio from Argentina

Eugenio on 6/28/2008 6:30 AM (620 days ago)

A nice set of articles and easy to read. I'm not a C++ programmer, although i understand most code and regularly port C++ into my language of choice: VB6. I have developed several bots in VB6 and they've been quite successful. The evaluation code is probably slow by today's standards due to VB6's Rnd() function, however i'm happy with the ~80,000 Monte Carlo simulations per sec. 10,000 simulations has proven to be plenty fast enough to get an accurate result.

I'm now getting deeper into C++ as i hate the whole framework/managed code thing and ms have killed off VB6. My own bots used BitBlt() to take screen captures, however that was a kludgy fix and i'm now researching deeper methods, with the intention of hooking into the SSL packet decryption. Finding it hard work but it'll be worth it.

Keep up the good work, it's sites like this that inspire "hobby" coders like me...

BotBotcher on 6/28/2008 6:45 AM (620 days ago)

As always excellent article. I look forward to seeing how you implement this for PokerStars. What I would like to do is create the DLL in C++ and do all of my logic and interface in C#. Can't wait for the next article!

Anonymous on 6/28/2008 7:07 AM (620 days ago)

great article!!! Finally some code

zerocode on 6/28/2008 8:11 AM (620 days ago)

Thanks for interesting read and for showing what can be done to noobs in programming world like me.
I like to learn through "live" examples and this one is perfect. Thanks!

The Black on 6/28/2008 8:33 AM (620 days ago)

Dude! PokerBots so totally ROCK! www.FireMe.To/udi

James Dean on 6/28/2008 8:39 AM (620 days ago)

I have to say "You Rock!!". Thank you for sharing your hard earned knowledge. You are bringing together a considerable amount of valuable and difficult to find information. This Blog has the potential of becoming a cornerstone for extending existing applications of all kinds! I am now going to google "botting rule #68" to find the rest!

Ron on 6/28/2008 11:19 AM (620 days ago)

Please quit your day job and continue the series full time. I can't wait another couple weeks for part 5.

Anonymous on 6/28/2008 12:53 PM (620 days ago)

Great post James. I look forward to more!

Andrew G. on 6/28/2008 1:00 PM (620 days ago)

Hi James. Another great post you have there but can I ask what client you're using in the FoldBot picture? I've never seen it before.

Thanks

Poker Forum - League Starts Soon with Added Prizes! on 6/28/2008 2:05 PM (620 days ago)

^^^^^
If you actually READ the articles, he tells you!!

BotBotcher on 6/28/2008 2:08 PM (620 days ago)

I can't help but wonder: Is it legal to use a bot to earn you money in online poker rooms?

And by legal i mean, legal in the sense that you will not get thrown to jail - not whether the poker room allows it or not. And of course laws can differ a great deal depending on where you are, but i'd be interested in hearing what you think is the case in europe and the US. I am personally from Denmark, but any european country where you have knowledge of the laws will be of interest.
(I asked this on reddit as well, so sorry for being a bit spammy Smile)

Casper on 6/28/2008 3:14 PM (620 days ago)

Great articles. Thank you for taking the time writing these Smile

So I built your FoldBot and it can detect holecars from the tables i join, but it doesn't seem to fold them. Do i need to setup the client in a specific way to make it work?

Anonymous on 6/28/2008 4:57 PM (620 days ago)

The hard part is programming a winning (or break even) poker bot... was that achieved ? That's the question ;)
Still a great tutorial about advanced stuff. Thanks.

Anonymous on 6/28/2008 5:12 PM (620 days ago)

I'm an experienced developer (although in the very different world of web development), and I have to say this is a fantastic series. I can't wait to read more.

Anonymous on 6/28/2008 6:14 PM (620 days ago)

I enjoyed this article very much. I built it (you're right, the boost was the trickiest part, but not very) and it works well except the table names aren't erased from the list when I leave the table. Speaking of boost, vb.NET has a regular expression library. I haven't used C++ in a long (like 10 years) time and it's not as easy for me to follow as other languages. What are the disadvantages to writing it all in vb.NET?
Also, I'm trying to follow it in the debugger and it doesn't work when I set breakpoints in the dll section. Any tips?
Now I'm trying to add Stars to the equation. I figure I'll learn more trying to do it first and when you show how you do it, I can absorb it even more quickly.
Thanks again.

Pro Bot on 6/28/2008 10:48 PM (620 days ago)

"Give a man a fish and he'll eat for a day, teach a man to fish and you have fed him for a lifetime"

Perhaps instead of providing bulk code you should instead providing us with the logic behind developing that code. *How* you decided on what messages to intercept, *how* you figured out what you needed to do. That would be far more useful!

1esproc on 6/28/2008 11:35 PM (620 days ago)

The regular expression only seems to match the Hold'em game table so the bot will only work with the Hold'em game. The other problem is when you leave a table it is not removed from the "open tables" list.

Samurai on 6/28/2008 11:51 PM (620 days ago)

@Peter: VS Express is fine up to a point but my recommendation is always for the full 90-day trial of VS2008 Pro.

www.codingthewheel.com/.../microsoft-vs-the-system-clock

@Casper: Poker botting is almost certainly not illegal unless online poker itself is illegal in your jurisdiction. However, do you consider violation of a EULA (even an unenforceable EULA) to be illegal? In that case we need to go after every college kid who's ever written a World of Warcraft bot and so forth. I'd like to post about this here shortly, we'll see if it happens.

@Pro Bot: Under .NET there's System.Text.RegularExpression which makes things a lot easier (one thing the C++ std lib has lacked for a long time is regex support, hence Boost). And VB.NET will work fine but you might want to consider going with a dual approach - small C++ hook, everything else in VB.NET.

@Samurai: yes, the current regex only matches Hold'em. I didn't want to spend too much time on hard-coded regex since ultimately we'll load the regexes from file and so forth.

As for the issue where hole cards aren't being removed from the GUI- the 2nd line in the WM_DESTROY handle in XPokerBot.MfxViewDlg.cpp should read:

int itemIndex = FindListItemByParam(hWnd);

I've updated the source code to reflect this.

James Devlin on 6/29/2008 1:15 AM (619 days ago)

I do so love WM_COPYDATA.... ;) So if that's your "just do it approach" which IPC mechanisms do you actually use? Not that there's much difference for this purpose... even with many tables running that's a relatively small amount of data floating across process boundaries.

Anonymous on 6/29/2008 1:30 AM (619 days ago)

@ Casper, James
pokerbots are not illegal, you'll not go to jail or will be prosecuted. But on every better known pokersite like Full Tilt,UB, Party,Stars, with opening an account you agree not to collude,cheat and use software thats blacklisted or gives you an advantage to other players (Pokertracker and other stat software are allowed because you have the information that other players have too). Botting is not allowed on these sites and if they catch you they will freeze your account with the money on it. That's ok if you're botting for sport or small amounts. Not much money to take. Besides colluding, thew sites put much of they resources in bot-searching. Party has sometimes a window to pt some numbers in it, they scan the memory and so on. Often people tell them suspicious players and they check the history. Conclusion: Not illegal by law but you're risking your bankroll. So don't try with an account with much money on it






bonzo on 6/29/2008 2:05 AM (619 days ago)

After compiling in VS 2008 (if it helps any other readers. you can get a full copy if you have a .edu email) in Vista, when I run it and open a window, the window does not show in the list. I am assuming that this is due to the increased security in Vista that apparently disables DLL injections.

Anonymous on 6/29/2008 2:41 AM (619 days ago)

Vista doesn't disable DLL injection! Stay tuned..

The anonymous commenter is referring to Microsoft Dreamspark, which offers free versions of:

-Visual Studio 2008
-Windows Server 2003
-Expression Studio
-XNA Game Studio

for students.

https://downloads.channel8.msdn.com/Default.aspx

James Devlin on 6/29/2008 3:36 AM (619 days ago)

Fold bots are evil! However, it's amazing how some players can simply "sit out" to let their hand fold, and still OFTEN make it into the payout in play money sit & go tournaments. There are usually 2 or 3 players auto-sitting out at all of those tables, amassing play money for unknown reasons...

I enjoyed the article and forward to reading future parts of the series! Keep it up.

Poker Bot on 6/29/2008 3:40 PM (619 days ago)

May I suggest you show HOW you find out what processes or objects you need to 'hook into' in Poker application to get the info you need. What tools, etc.?
Thanks, it's a great series.

Pro Bot on 6/30/2008 10:22 AM (618 days ago)

I hope you don't plan on including any .NET Frown I like the old school way of doing things as it shows more actual how-to than all the shortcuts you can take within that massive framework; and I don't need to mention the footprint...

great article though. I've been toying around since the first article and I got to a stopping point with PStars so was hoping you could give a little insight. I used detours to grab all text being passed (with drawtext) and actually am seeing everything but I can't figure out which window it is being pointed to since all I get is a HDC. any help here? or some more detail on subclassing and figuring out WHAT messages are being passed in? as 1esproc said, more "how" you are figuring stuff out would be great. I don't think releasing functional bots is helping as much...

thanks

Michael on 6/30/2008 11:42 AM (618 days ago)

Someone ... Anyone...

I have Winspector and Detours Express but have not figured out how to grab dealer text messages from PStars. I would welcome any specific advice or example.

F. Bueller on 6/30/2008 1:34 PM (618 days ago)

hello,
james i really appreciate your good work and looking forward to new interesting topics.

F. Bueller: take a look at the Detours examples, especially at traceapi and simple. if you compiled the detours tidily, you will find a withdll.exe in the bin directory. this dll is injecting a giving dll into a proess and starts it (e.g. withdll.exe /d:traceapi.dll "C:\Program Files\PokerStars\PokerStars.exe"). traceapi will output the calls into a logging client(syelogd.exe).
if you dont want to trace all api calls included in the traceapi dll, you can simplfy write your own using the source code of the traceapi.dll(especially in the _win32.cpp file).
i copied some code which writes all TextOutW calls in C:\a.txt: click. compile this as a dll an run: withdll.exe /d:mydll.dll "C:\Program Files\PokerStars".
i hope i could help you and if you have problems with compiling detours with vs2008, take a look at http://forums.msdn.microsoft.com/en-US/vcgeneral/thread/fcb5a809-5404-481f-82c0-40ffa6f58c9b/.
greets

Anonymous on 6/30/2008 1:59 PM (618 days ago)

oh i'm sorry for the typing and grammar mistakes, but i can't edit my previous post.
if anyone compile the code above, then please concern that withdll expects an export function. i declared the NullExport function, but it's important to add "/export:NullExport" into the Additional Options at the Linker Properties of your project.

Anonymous on 6/30/2008 2:06 PM (618 days ago)

thanks Anon!

I will give it a try.

Bueller

Bueller on 6/30/2008 2:08 PM (618 days ago)

Great article. I am also trying to get started. Also downloaded Detour, but am having trouble running the initial "nmake" command.

Read the readme.txt which says "To build the libraries and the sample applications, type "nmake"."
I assume this is from a command prompt (is that correct?)
Open Command Prompt in Windows Accessories
cd to Program Files\Microsoft Research\Detours Express 2.1\
type nmake (enter) and got
"'rc' is not recognized as an internal or external command, program or batch file"
NMAKE Fatal Error U1077 return code '0x1' and '0x2'

I admit to being weak in programming, but would like to at least be able to complete this simple step.

Bot Envy on 6/30/2008 6:06 PM (618 days ago)

Bot Envy... when you're in the cmd window, you've got to run a file called vsvars32.bat to set your environment variables before you run nmake. That file is located in c:\program files\microsoft visual studio 8\common7\tools on my machine.

Pro Bot on 6/30/2008 8:18 PM (618 days ago)

@Bot Envy
I have not tried it yet, but found this at
www.devsource.com/.../

"You might think that accessing the command line is a simple matter of clicking the Start\Programs\Accessories\Command Prompt shortcut. That shortcut opens a command prompt, but it's not the right one. This command prompt lacks the required environment variables, especially the path information to Visual Studio.

Instead, open a development command line by clicking the \Start\Programs\Microsoft Visual Studio\Visual Studio Tools\2005 Visual Studio 2005 Command Prompt shortcut."

Hope that helps

EnviroMan on 6/30/2008 8:19 PM (618 days ago)

Excellent series and really educational. I am reaaaaly looking forward to knowing exactly how you detect the whole cards of PT and FT. I am a professional programmer, but I know next to nothing about graphics and I have a hard time imaging how to do screen scraping in a timely manner.

Michael, you wrote "I used detours to grab all text being passed (with drawtext) and actually am seeing everything". What does seeing everything means? Does it include the whole cards which isn't written to the status window???

+rEbEl on 7/1/2008 2:32 AM (617 days ago)

HI. In my computer, the FoldBot perfectly works with Windows vista, without making any change.

In fact, the most tricky part, is building the boost library, but any programmer can do it Smile

Thanks for sharing all this stuff, but I have a question for you.

Do you think tha amount of BOTs will dramatically increase because of this blog??
What will be the result of this? I think the poker rooms will increase their security.
Will it be possible to do all this stuff in the future?


Thanks for your work

WFB on 7/1/2008 2:41 AM (617 days ago)

Thank you to Pro Bot and EnviroMan. Following your advice, I was able to do the nmake properly, and now have withdll.exe, simple, traceapi, etc.

Will attempt to run some detours examples, including the one provided by Anonymous.

Interesting stuff.

Bot Envy on 7/1/2008 2:49 AM (617 days ago)

Where can I download detours? MS-download-link seems to be broken.
reg. popo

popo on 7/1/2008 11:12 AM (617 days ago)

Detours is at
http://research.microsoft.com/sn/detours/

Bueller on 7/1/2008 12:19 PM (617 days ago)

Cool. We have evolved from just waiting for the next article to actually helping each other understand the tools and concepts better.

Arthur on 7/1/2008 6:45 PM (617 days ago)

Thx James. I don't know the first thing about codes or programming, so for me this seems like a crazy hard task, but I am determined to build a fold bot, and keep up with the series. I would love to ask some questions, but I'm going to exhaust the research first. Peace and elbow grease.

Anonymous on 7/1/2008 8:26 PM (617 days ago)

The link to the mydll.dll code by Anonymous above has stopped working, but here is the excellent code that he provided as an example:

#include <windows.h>
#include <detours.h>
#include <stdio.h>

BOOL (__stdcall * Real_TextOutW)(HDC a0,
int a1,
int a2,
LPCWSTR a3,
int a4)
= TextOutW;

BOOL __stdcall Mine_TextOutW(HDC a0,
int a1,
int a2,
LPCWSTR a3,
int a4)
{
FILE *file;
file = fopen("C:\\a.txt","a+");
fprintf(file, "TextOutW(%p,%p,%p,%ls,%p)\n", a0, a1, a2, a3, a4);

BOOL rv = 0;
__try {
rv = Real_TextOutW(a0, a1, a2, a3, a4);
} __finally {
fprintf(file, "TextOutW(,,,,) -> %p\n", rv);
};
fclose(file);
return rv;
}

VOID NullExport()
{
}

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH) {
printf("simple.dll: Starting.\n");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_TextOutW, Mine_TextOutW);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)Real_TextOutW, Mine_TextOutW);
DetourTransactionCommit();
}
return TRUE;
}

Code Warrier on 7/2/2008 12:52 AM (616 days ago)

Anonymous wrote:
oh i'm sorry for the typing and grammar mistakes, but i can't edit my previous post.
if anyone compile the code above, then please concern that withdll expects an export function. i declared the NullExport function, but it's important to add "/export:NullExport" into the Additional Options at the Linker Properties of your project.

Thank you for the clarification, but I have just started using VS (following James Devlin's suggestion) and am not sure where to add the "/export:NullExport". Is it in the code you supplied, near the

VOID NullExport()
{
}

or is it in the Mydll Property Pages, Configuration Properties, General, Output File?

Thank you for your patience.

Quinton T. on 7/2/2008 5:03 PM (616 days ago)

almost

It is found in mydll Properties, Configuration Properties, Linker, General, Output File (type /export:NullExport here)

Don't give up.

Fred on 7/2/2008 8:03 PM (616 days ago)

1esproc said

""Give a man a fish and he'll eat for a day, teach a man to fish and you have fed him for a lifetime"

Perhaps instead of providing bulk code you should instead providing us with the logic behind developing that code. *How* you decided on what messages to intercept, *how* you figured out what you needed to do. That would be far more useful!"

i also would love to hear about how you know which ones to intercept. ive been working on a bot like this but sometimes figureing out which to intercept are hard. anyhelp on that would be appreicated.

james on 7/2/2008 9:12 PM (616 days ago)

Any commandline compiler for the foldbot out there? Currently not enough diskspace for VS Wink.

Anybody tried the foldbot on stars without issues/anoying e-mail-notifications?

Hope we stay on C++ not NET Smile.

popo on 7/2/2008 9:27 PM (616 days ago)

Thank you Bueller,
the detours-download-link on MS ist ftp, therefore I had to prepair my browser.

popo on 7/2/2008 9:29 PM (616 days ago)

Great work, everybody.

We'll talk about some other Detours tricks here in the next post, but if you've gotten Detours installed, built, and running in ANY application (poker or otherwise) that's half the battle.

@Michael: If you haven't gotten an answer to your HDC question, stay tuned.. we'll be talking about HDC-to-HWND mapping shortly. It's a messy topic.

@BotEnvy: Glad you got the RC issue figured out, I've run into that one myself. Even if you run vcvars32.bat, sometimes you'll get pesky error messages like that one. Particularly when running a command line build. If vcvars32 doesn't fix it, the next step is to find the tool it's complaining about and add its folder to your PATH environment var. NMAKE has always been somewhat of a murky proposition, but once you get the kinks worked out, it's clean.

James Devlin on 7/3/2008 1:08 AM (615 days ago)

Thanks for the effort James, it is being a really instructional trip for me Smile

In the line of those requesting more information on how to collect information on how the poker clients work, I have tried to build a tool for BossMedia that maps keystrokes to mouse actions like folding and raising for faster interaction while multitabling and ran into some weird stuff. The sendInput command works because I have tried it in other clients, but on BossMedia it only moves the mouse but doesn't perfoms the MOUSEEVENTF_LEFTDOWN and MOUSEEVENTF_LEFTUP events.

Any guidelines on how to follow up in my research of whats happening?

Paburo on 7/3/2008 4:37 PM (615 days ago)

Great!. Need the next article. I'm stopped now. I need catch text from textout or drawtext. The window only shows 'wm_paint' event. 'Wm_paint' is generated for everything, not useful for my program. I need another way.

Berto on 7/3/2008 7:29 PM (615 days ago)

I am trying to compile the dll example posted by Code Warrier above, but am getting the following errors during linking:

1>Linking...
1>detourcode.obj : error LNK2019: unresolved external symbol _DetourDetach@8 referenced in function _DllMain@12
1>detourcode.obj : error LNK2019: unresolved external symbol _DetourTransactionCommit@0 referenced in function _DllMain@12
1>detourcode.obj : error LNK2019: unresolved external symbol _DetourAttach@8 referenced in function _DllMain@12
1>detourcode.obj : error LNK2019: unresolved external symbol _DetourUpdateThread@4 referenced in function _DllMain@12
1>detourcode.obj : error LNK2019: unresolved external symbol _DetourTransactionBegin@0 referenced in function _DllMain@12
1>/export:NullExport : fatal error LNK1120: 5 unresolved externals

Would appreciate any advice on how to resolve these.

Juan on 7/5/2008 4:34 AM (613 days ago)

I just installed the Boost Regex library and added it to VS 2008, when I compile the solution I get some warnings about strcpy being unsafe and that I should use a strcpy_c, and also I get a warning about a command line option Wp64 being deprecated. Then at the end I get this:

Linking...
LINK : C:\Users\kasra\Desktop\XPokerBot\XPokerBot\bin\XPokerBot.MfcView.exe not found or not built by the last incremental link; performing full link
Embedding manifest...
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
Build log was saved at "file://c:\Users\kasra\Desktop\XPokerBot\XPokerBot\XPokerBot.MfcView\Debug\BuildLog.htm"
XPokerBot.MfcView - 0 error(s), 4 warning(s)
========== Rebuild All: 2 succeeded, 0 failed, 0 skipped ==========

When I run the exe that this creates, and then run the PokerTime app and join a table, the table does not show up in the list at all and nothing happens.

Anonymous on 7/5/2008 5:32 AM (613 days ago)

I successfully build detours, now
I am trying to compile the dll example posted by Code Warrier above too!

I physicaly copied the detours.h into my project-dir and added it to the header tree on the left side of the VS IDE.

In PHP it would include it as long as the include-file exists but I m not an include professional on VS...what ist wrong, any idea?

It says:

------ Build started: Project: mydll, Configuration: Debug Win32 ------
Compiling...
mydll.cpp
c:\dokumente und einstellungen\popop\eigene dateien\visual studio 2008\projects\mydll\mydll\mydll.cpp(2) : fatal error C1083: Cannot open include file: 'detours.h': No such file or directory
Build log was saved at "file://c:\Dokumente und Einstellungen\popo\Eigene Dateien\Visual Studio 2008\Projects\mydll\mydll\Debug\BuildLog.htm"
mydll - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

popo on 7/5/2008 8:06 AM (613 days ago)

Anonymous:

The strcpy_s functions are version of strcpy with security enhancements. You can ignore the warning for this purpose. in your open poker table windows, make sure you're using Normal or Large table views and that the chat window is visible and set to Full Detail. Sometimes you have to click an up-arrow to get it to appear.

Hope that helps...

JeremyX on 7/5/2008 8:17 AM (613 days ago)

Juan, should wie link something, thought only build/compile mydll.dll?
What is the exact procedure? And what is linking Wink?

popo on 7/5/2008 1:05 PM (613 days ago)

Anonymouse wrote
"oh i'm sorry for the typing and grammar mistakes, but i can't edit my previous post.
if anyone compile the code above, then please concern that withdll expects an export function. i declared the NullExport function, but it's important to add "/export:NullExport" into the Additional Options at the Linker Properties of your project."

I think I was doing this correct, but may be not.

Juan on 7/5/2008 1:08 PM (613 days ago)

Juan, the problem is that the linking of your detours lib isnt working. you probably forgot to add the detours libs to the linker options. if you add the detours include dir to the VC++ include dir, it's also important to tell the linker that he should link detours.lib and detoured.lib to your project.
for that, add "detours.lib detoured.lib" to die Additional Dependencies at the Linker -> Input configuration properties of your project (VS2008).

Anonymous on 7/5/2008 1:25 PM (613 days ago)



========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========

Thank you Anonymous. That was it.

Juan on 7/5/2008 2:04 PM (613 days ago)

I added the two .libs to my Input because I was having the same problem Juan was having, but one of the errors I got before adding them did not go away;
mydll.obj : error LNK2005: _DllMain@12 already defined in dllmain.obj
>mydll.dll/export:NullExport : fatal error LNK1169: one or more multiply defined symbols found

Anonymous on 7/5/2008 4:36 PM (613 days ago)

Juan says; "Thank you Anonymous. That was it."

Another Anonymous later: "I added the two .libs to my Input because..."

Could someone tell more? Or better give a small summery how to get
mydll.dll working. May a step by step tut. how to include or what to link
to get it.

Im using VC Express and when I go to project>mydll property pages>linker>input
there are several fields which could have user-text-input.

Would be nice to get a short perfect formulated advice (all menu-items and input-fields) for vc newbies.

So we all can benefit from the great mydll.dll - script.

popo on 7/5/2008 7:27 PM (613 days ago)

I m not using VC Express. I m using VS Express sorry Wink.

popo on 7/5/2008 7:31 PM (613 days ago)

OK, did some research... we have to tell vc the detours include path by going to tools>options>vc++directories...then choose pulldown show directories for include path...and then add a new path for example:
c:\Programme\Microsoft Research\Detours Express 2.1\include
we can do the same for the library files...so linking is no longer a problem...and remeber not to type any backslash for output file
like "/export:NullExport", seems to be "export:NullExport"

1. create an emty dll-project
2. copy paste the code
3. set the include and library pathes for detours as metioned above
4. build and compile

mydll - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

popo on 7/5/2008 8:10 PM (613 days ago)

Thanks Popo (and others). That helped me.

I found three files in
C:\Documents and Settings\Terry\My Documents\Visual Studio 2008\Projects\mydll\

they are:
mydll (VC+++ Intellisense Database)
mydll (Microsoft Visual Studio Solution)
mydll (Visual Studio User Options)

Is the second one the desired dll?

The example says to run: withdll.exe /d:mydll.dll "C:\Program Files\PokerStars".

is that done from the Start\Programs\Accessories\Command Prompt
or from withine VS?

Anonymous on 7/5/2008 8:53 PM (613 days ago)


and when i rebuild:

LINK : fatal error LNK1104: cannot open file '/export:NullExport'

what the heck we are doing here?

popo on 7/5/2008 9:21 PM (613 days ago)

popo:
When compiled, the files go to /bin/debug in the folder where your project lies.
Anonymous before popo:
You first compile the solution (or recompile if you already have and encountered errors), then go to /bin/debug in your Projects/mydll folder to find your .dll

Anonymous on 7/5/2008 9:22 PM (613 days ago)

everyone breathe normally!

thank you Anonymous, I will look there

Anonymous on 7/5/2008 9:27 PM (613 days ago)

oh thx i did not noticed that i have two debug folders into my project-dir
what did you typed in the linker/general/Output File - Field "/export:NullExport" or "export:NullExport" ?

Still get the error:
LINK : fatal error LNK1104: cannot open file '/export:NullExport'

popo on 7/5/2008 9:36 PM (613 days ago)

i have two mydll folders and two debug folders!

using export:NullExport

Anonymous on 7/5/2008 9:38 PM (613 days ago)

looks like the second one is created if you select Build, Rebuild Solution

Anonymous on 7/5/2008 9:42 PM (613 days ago)

after rebuild i get


mydll : error PRJ0021 : Tool 'Linker', Property 'Output File' contains invalid file name.

and you do the same without any error-messages?
i use vs 2008 express, and you?

popo on 7/5/2008 9:45 PM (613 days ago)

i still don't have a mydll.dll file

not exactly intuitive, but making some progress

Anonymous on 7/5/2008 9:45 PM (613 days ago)

may someone is kidding us.

popo on 7/5/2008 9:48 PM (613 days ago)

i am using micro VS pro edition

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

just can't find mydll.dll !

Anonymous on 7/5/2008 9:50 PM (613 days ago)

it is possible

but i think it should compile into a dll

Anonymous on 7/5/2008 9:52 PM (613 days ago)

how about this?

if anyone has compiled the above code into a dll, please post the file size here

Anonymous on 7/5/2008 9:55 PM (613 days ago)

the location of mydll.dll varies but it depends on using
the export:NullExport hint or not. i get a mydll.dll when
i m not using the export:NullExport. But then i get a prompt message:
mydll.dll does not export function with ordinal #1

after hours of research...its so disappointing...was someone successfull? pleas make a detailed post.

popo on 7/5/2008 10:03 PM (613 days ago)

compare settings and code:

in Solution Explorer i have
1 header file: header.h
0 resource files
1 source file: detourcode.cpp (or whatever you want to call it)

what do you have in your source file?

Anonymous on 7/5/2008 10:26 PM (613 days ago)

this is all "extra credit" anyway

Anonymous on 7/5/2008 10:37 PM (613 days ago)

All: I'm putting together a Detours post which will be out later today. In the meantime: please verify that your Detours installation is working correctly by doing the following:

1. Open up an MS-DOS command prompt. Navigate to the Detours BIN folder. Type in:

SYELOGD 1.TXT

2. Open up a 2nd MS-DOS command prompt. Navigate to the Detours BIN folder. Type in:

WITHDLL /D:TRACEAPI.DLL C:\PROGRAM FILES\POKERSTARS\POKERSTARS.EXE

(You can replace the path to the PokerStars client with the path to any .EXE on your system)

You should see the Poker Stars client load, and a flood of messages appear in the SYELOGD monitor window. These message will also be streamed to the text file you specified (in this case, MYOUTPUTFILE.TXT).

Please verify that this works, and stay tuned for Part 5, which will be out today.

James Devlin on 7/6/2008 4:02 AM (612 days ago)

as a further hint, once youve gotten detours running like James describes, open up the TRACEAPI.DLL source code and start commenting out the functions you don't want. you can selected from the top and scroll down to the bottom, comment them all using edit->advanced->comment Selection, and then go in and turn on the individual funcs you want to trace.

Anonymous on 7/6/2008 4:49 AM (612 days ago)

Thank you folks, unfortunately I get this strange message on my command

prompt wenn triggering withdll:

LoadLibraryEx(TRACEAPI.DLL) failed with error 126

TRACEAPI.DLL does not export function with ordinal #1

popo on 7/6/2008 7:34 AM (612 days ago)


I m trying to rebuild XPokerBot and get the following output:

------ Rebuild All started: Project: XPokerBot.Hook, Configuration: Debug Win32 ------
Deleting intermediate and output files for project 'XPokerBot.Hook', configuration 'Debug|Win32'
Compiling...
cl : Command line warning D9035 : option 'Wp64' has been deprecated and will be removed in a future release
ApplicationProxy.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(91) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(92) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\applicationproxy.cpp(132) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
OnlinePokerClient.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(91) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(92) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
OnlinePokerExecutor.cpp
OnlineTableWindow.cpp
PokerTimeCaptionDecoder.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(91) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(92) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\pokertimecaptiondecoder.cpp(78) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\pokertimecaptiondecoder.cpp(86) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
PokerTimePokerClient.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(91) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(92) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
PokerTimeTableWindow.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(91) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\tablesummary.h(92) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\programme\microsoft visual studio 9.0\vc\include\string.h(74) : see declaration of 'strcpy'
stdafx.cpp
XPokerBot.Hook.cpp
Generating Code...
Compiling manifest to resources...
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
Linking...
LINK : fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_35.lib'
Build log was saved at "file://c:\00000_poker_ai_bauen\XPokerBot\XPokerBot\XPokerBot.Hook\Debug\BuildLog.htm"
XPokerBot.Hook - 1 error(s), 14 warning(s)
------ Rebuild All started: Project: XPokerBot.MfcView, Configuration: Debug Win32 ------
Deleting intermediate and output files for project 'XPokerBot.MfcView', configuration 'Debug|Win32'
Compiling...
cl : Command line warning D9035 : option 'Wp64' has been deprecated and will be removed in a future release
stdafx.cpp
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.mfcview\stdafx.h(57) : fatal error C1083: Cannot open include file: 'afxwin.h': No such file or directory
Build log was saved at "file://c:\00000_poker_ai_bauen\XPokerBot\XPokerBot\XPokerBot.MfcView\Debug\BuildLog.htm"
XPokerBot.MfcView - 1 error(s), 1 warning(s)
========== Rebuild All: 0 succeeded, 2 failed, 0 skipped =========

Think the main errors are include-erros, but i pointed VS to the boost-dir.

Could someone help, please?

Environment: WinXP, VS Express, Boost 1.35.0

popo on 7/6/2008 11:56 AM (612 days ago)

popo: All of the problems you're seeing will go away if you download Visual Studio 2008 Professional. This is available as a free, fully-functional 90-day trial. If you're a college student, then you get it for free (without the 90-day expiration). It's a big download so grab a DL manager before you start. This will save you hours and hours in the long run.

msdn.microsoft.com/.../cc268305.aspx

James Devlin on 7/6/2008 12:25 PM (612 days ago)

I should mention, the afxwin.h include error you're seeing means that your IDE doesn't know where the standard MFC library includes are located. I don't know off the top of my head whether VS Express comes with/supports MFC but my inclination is to say no. And in any case, you want the real VS2008 developer toolset.

James Devlin on 7/6/2008 12:29 PM (612 days ago)

Hm, yes I would do so...but right now I have to less diskspace Wink...have to wait to buy some DVD's to free some space...but since several days I play break even by hand, may I will earn some money to get it Wink.

Thanks for your advise james.

I figured out that there is an installer for boost (was realtivly hidden on the page you mentioned), fo first I got the source-distribution Wink. The Link is: http://www.boostpro.com/products/free

popo on 7/6/2008 12:33 PM (612 days ago)

exciting stuff. this site is the tip of the spear

@james: you > me

Anonymous on 7/6/2008 12:37 PM (612 days ago)

Could someone bring up an example how to point Visual Studio correctly to boost?

to avoid such things like this:
c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.hook\stdafx.h(100) : fatal error C1083: Cannot open include file: 'regex.hpp': No such file or directory
OnlinePokerClient.cpp

my boost is located in:
C:\Programme\boost

[...]
This directory (XPokerBot/boost) contains Debug and Release versions of the Boost regex library. You can link to these binaries assuming you've installed the Boost header files, even if you haven't gone to the trouble of building Boost yourself.
[...]
...and which header-files should I put where...any idea?
I used the boost installer.

popo on 7/6/2008 2:58 PM (612 days ago)

popo, you need to add the following two directories to your IDE options (Tools->Options):

-C:\Programme\Boost\boost_1_33_1\
-C:\Programme\Boost\boost_1_33_1\boost

In VS2008, go to Tools->Options. Select 'Projects and Solutions' followed by 'VC++ Directories'. Then change the dropdown to say 'Show Directories for: INCLUDE files'. And add the above two lines to the list. Not sure how to get at this setting in VC Express but thats in VS2008.

You can also if worst comes to worst add the full path to the include:

#include "c:\programs\...etc\regex.hpp"

Kind of a hack. Oh and if you've installed some other version of Boost you'll need to tweak the above directories approp.



JeremyX on 7/6/2008 4:32 PM (612 days ago)

Thank you Jeremyx, I forgot that I solved this problem befor playing with the dir-locations. You rembered me the right notation.

I know VC Express is not the right IDE but can someone tell me where this files normaly resist when using VS Pro.?

LINK : fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_35.lib'

c:\00000_poker_ai_bauen\xpokerbot\xpokerbot\xpokerbot.mfcview\stdafx.h(57) : fatal error C1083: Cannot open include file: 'afxwin.h': No such file or directory

XPokerBot.MfcView - 1 error(s), 1 warning(s)

popo on 7/6/2008 7:09 PM (612 days ago)

For all VS Express user, I found this comment which underlines James idea:

You're missing MFC to get afxwin.h and the Platform SDK for <windows.h>. They don't come included with the Express edition. MFC is a no-go but you can get the Platform SDK; search this forum for "SDK".

popo on 7/6/2008 7:16 PM (612 days ago)


when trying
WITHDLL /D:TRACEAPI.DLL C:\PROGRAM FILES\POKERSTARS\POKERSTARS.EXE
I got the same message as Popo.

withdll.exe: LoadLibraryEx(TRACEAPI.DLL) failed with error 126.
withdll.exe: Error: TRACEAPI.DLL does not export funtion with ordinal #1.

also, does it matter if it is?
WITHDLL /D:TRACEAPI.DLL C:\PROGRAM FILES\POKERSTARS\POKERSTARS.EXE
or
WITHDLL /D:TRACEAPI.DLL "C:\PROGRAM FILES\POKERSTARS\POKERSTARS.EXE"

Attila on 7/6/2008 8:54 PM (612 days ago)

Hi Attila, popo - the 126 error is a "module not found" and the most likely reason is that TRACEAPI.DLL either isn't built (you have to run a separate NMAKE to build the Detours samples) or it is built, but not present in the directory where you're running the MS-DOS command windows.

Please verify that WITHDLL.EXE, TRACEAPI.DLL, and SYELOGD.EXE all exist in your Detours "bin" folder and that you have navigated to that folder in both of the MS-DOS command prompt windows.

James Devlin on 7/6/2008 10:43 PM (612 days ago)

Hello James,
what is the syntax to nmake a traceapi?

popo on 7/6/2008 11:02 PM (612 days ago)

open ms-dos cmd prompt, navigate to the detour "samples" folder.. then it is good for you to type 'nmake' and it will build the samples..

(you may get some error during nmake. as with me it was a problem with the "RC" tool. i had to find rc.exe on the machine and add it to system path. maybe this is not happening for you.)

Rammohan on 7/6/2008 11:30 PM (612 days ago)

Thank you Rammohan...what a wonder it does not work Wink:

cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\syelog"
if not exist ..\include mkdir ..\include
if not exist ..\lib mkdir ..\lib
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\simple"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\slept"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\setdll"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\withdll"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\cping"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\disas"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\dtest"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\dumpe"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\dumpi"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\einst"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\excep"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\commem"
if not exist ..\..\bin mkdir ..\..\bin
cd "E:\Programme\Microsoft Research\Detours Express 2.1\samples\findfunc"
cl /nologo /Zi /MT /Gm- /W4 /WX /O1 "/I..\..\include" "/I..\include" /Gs /DDETOURS_X86=1 /D_X86_ /Fe..\..\bin\symtest.exe /Fd..\..\bin\symtest.pdb symtest.cpp /link /release /machine:x86 "..\lib\syelog.lib" "..\..\lib\detours.lib" "..\..\lib\detoured.lib" kernel32.lib gdi32.lib user32.lib shell32.lib /subsystem:console /incremental:no /fixed:no ..\..\bin\target.lib
symtest.cpp
symtest.cpp(270) : error C2664: 'BOOL (HANDLE,PSYM_ENUMMODULES_CALLBACK64,PVOID)' : cannot convert parameter 2 from 'overloaded-function' to 'PSYM_ENUMMODULES_CALLBACK64'
None of the functions with this name in scope match the target type

...but thank you for your tip.

popo on 7/7/2008 8:18 AM (611 days ago)

Nice posts, all of them! tried to open the solutin in VS2005 (after convert) but couldnt build them:
Error 1 fatal error C1083: Cannot open include file: 'regex.hpp': No such file or directory c:\documents and settings\brian_h\desktop\xpokerbot\xpokerbot.hook\stdafx.h 100

if i comment out the above line then it says that the line: map<HWND, OnlineTableWindow*> myTables; is wrong: Error 4 error C2143: syntax error : missing ';' before '<' c:\documents and settings\brian_h\desktop\xpokerbot\xpokerbot.hook\onlinepokerclient.h 54

along with 92 other errors..

Anyone???


Sry but im not so much into C++. Love to see the solution in C# though..

H4mm3rHead on 7/7/2008 9:30 AM (611 days ago)

H4mm3rHead...take a look at post: "JeremyX on 7/6/2008 4:32:37 PM (17 hours ago)". Solves the regex-include problem.

popo on 7/7/2008 10:01 AM (611 days ago)

When I try nmake of Detours I get error U1077. I have standard default installs of Detours 2.1 Express and Visual Studio 2008 version 9.0, running Win XP.

Google of "nmake U1077" shows that this is a widespread problem. Have not found a solution that works for me yet.

I think that there is some config setting in VS that is wrong but still looking.

Mark on 7/7/2008 11:52 AM (611 days ago)

"i hope i could help you and if you have problems with compiling detours with vs2008, take a look at forums.msdn.microsoft.com/.../.
greet"
especially the 2nd post from austin.

Anonymous on 7/7/2008 11:54 AM (611 days ago)

I stumbled on your articles here and I cant say much else than WOW...Im currently building a poker bot and have reach quite much further than you'r articles so faar. But its still damn interesting reading.
Im doing my bot in pure c# and its just as you mention. You cant do the really lowlevel programming with that language. But so faar its no problems.

I just wanted to ask about your opinion when it comes to DLL-injection. Isnt it "fairly" easy to just run a hash check on your own application ( poker client's in this case ). If the hash does not match an DLL injection has been made? Or?
Guess the real question is if Im doing a lot of uneccessary work when Im working without DLL injections.

Would love to see you combining both C# and C++ in your application.

Thanks for great reading!

Macke on 7/7/2008 2:59 PM (611 days ago)

Hey Jim...looks like you've been busy...

Very impressive posts!

Give me a call or shoot me an email

Keith L from Dallas on 7/7/2008 4:31 PM (611 days ago)

Anonymous on 7/7/2008 5:23 PM (611 days ago)


traceapi.dll is 96.0 KB (98,366 bytes) on my system

Joe on 7/7/2008 5:47 PM (611 days ago)


"It looks like Visual Studio 2008 ships with standard libraries with different types to what detours expects. At this stage, I'm not sure what the best work-around is: you could always try building with VS 2005."
forums.msdn.microsoft.com/.../

Detoured on 7/8/2008 1:57 PM (610 days ago)

If any of you players or bot writers need hand histories for your stats (PT, HM etc) databases you should head to HandHQ.com.

handhq on 7/9/2008 9:41 AM (609 days ago)

Hi there.
I'm pretty interested in this project as long as I'm making my way to a pro-style playing, but also I enjoy coding.

I'm not intended to cheat on poker sites, but I would like to make this bot a personal coach approach. I'd love to make him evaluate my sessions and discovering my leaks or any similar approach.

I'll be tune to this blog ... thanks.

marciano on 7/9/2008 12:28 PM (609 days ago)

hi,

I have a small problem with folderbot, I get an error (0xc0150002), I am using visual net 2005, I am using windows vista

Thanks

alex on 7/9/2008 3:48 PM (609 days ago)

hi!
maybe we should create some sort of forum for this?

i'm sure tons of people will have questions or ideas to bring up.
if we had a more organized way to deal with this, we could answer each other's questions and have set areas to discuss new ideas and so forth.

what do you guys think?

Anonymous on 7/9/2008 4:12 PM (609 days ago)

I would agree a forumn could be good. I would like to trade code with people that are hoooking into other sites. My action bot is working with this one but no one really seems to play on this site.

Ok on 7/9/2008 5:46 PM (609 days ago)

There are already other forums out there, but this is where the action is now. If you don't like it here leave.

This is as good as it gets on 7/9/2008 6:03 PM (609 days ago)

fold bot works, but I lost all my $$$...

wtf?

chipless on 7/9/2008 11:37 PM (609 days ago)

looking forward to part 5, when can we expect it?

james on 7/10/2008 12:32 AM (608 days ago)

J.D.:
on http://www.codingthewheel.com/image.axd?picture=multitabling_safe.jpg
you use muliple Screens, one screen only for the bot.
Is it a mult-screen environment or a multiple computer-environment?
Is it a special save environment?

and can wie expect such I nice ready to go GUI like:
http://www.codingthewheel.com/image.axd?picture=poker_bot_profile.gif

I love you Smile
popo

popo on 7/10/2008 6:52 AM (608 days ago)

>I would agree a forumn could be good. I would like to trade code with people
>that are hoooking into other sites. My action bot is working with this one
>but no one really seems to play on this site.


The next post will cover Poker Stars and Full Tilt. We started with Poker Time because it's a little easier.

@james: I meant to have it out yesterday!

@popo: yes, and the OPC GUI is based on Outlook, which is probably overkill for a single bot. But as we'll see the bot itself becomes one module out of several, and the Outlook-style navigation interface starts to make sense. Or maybe it's that I hate staring at command prompt UIs for hours on end ;)

James Devlin on 7/10/2008 7:26 AM (608 days ago)

I have managed to capture the text chat Pokerstars, but I would like to obtain information from users nro playing, who is the one who wins.

how to get the events of the pokerstarstableframeclass.

if someone knows some method to obtain it.

alex on 7/10/2008 2:04 PM (608 days ago)

another option

www.codeplex.com/.../ProjectReleases.aspx

Hooker on 7/11/2008 11:19 AM (607 days ago)

Hello James. Phenominal info here. I have really enjoyed all your recent information, but as many here, I am most interested in your poker bot. I am hoping you may be able to help me. I am a fairly proficient c# programmer and will probably be recoding much of your examples in c# as that is my current language of choice. I downloaded the DetoursExpress install and when I attempted the install I get an error code 2908. Exact error message: "The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2908." Tried uninstall/reinstall, repair, redownloading, etc. all to no avail. Any ideas where to start? TIA.

Jim on 7/11/2008 11:27 AM (607 days ago)

Jim, is your Detours Express Download 544KB?

Anonymous on 7/11/2008 12:53 PM (607 days ago)

sorry..it is exactly 566,544 bytes

Anonymous on 7/11/2008 12:54 PM (607 days ago)

yes

Jim on 7/11/2008 1:31 PM (607 days ago)

Well...actually...I checked the files size from windows explorer and it shows 544KB, but when I check the file's properties, it shows 556,544 (where you asked if it was 566,544), so the answer is yes ... and ... no.

;)

Jim on 7/11/2008 1:48 PM (607 days ago)

Ahhhhhh need the new article. How do you read hole cards in PS? I can't find the log file.

Ken on 7/11/2008 2:55 PM (607 days ago)

PokerStars.log

Anonymous on 7/11/2008 4:52 PM (607 days ago)

donde carajo esta el pokerstars.log, i dont find

alex on 7/11/2008 5:50 PM (607 days ago)

Hi all,

still got this errors:

LINK : fatal error LNK1104: Datei "libboost_regex-vc90-mt-gd-1_35.lib" kann nicht geöffnet werden.
LINK : fatal error LNK1104: Datei "..\bin\XPokerBot.Hook.lib" kann nicht geöffnet werden.

I've added the paths as shown above but nothing helps....
I'm using vista+vs2008

I've tested boost with that little program an the boost homepage and it seems to work.

I would be pleased for any help

Fritz on 7/11/2008 6:37 PM (607 days ago)

Alex its PokerStars.log.0 on my comp, in the pokerstars folder.

Cant wait till part 5!

Tyler on 7/11/2008 6:50 PM (607 days ago)

Fritz, in addition to the two Boost include folders, add the Boost/lib folder to your IDE options.

In VS2008, go to Tools->Options. Select 'Projects and Solutions' followed by 'VC++ Directories'. Then change the dropdown this time to say 'Show Directories for: LIBRARY files'. Add "C:\Boost\lib" (or your equivalent) to this list.

And let's see.. you might want to make sure the file

libboost_regex-vc90-mt-gd-1_35.lib

exists in this location, and copy it over to XPokerBot/boost just for the fun of it (not sure if this is necessary or not).


JeremyX on 7/11/2008 8:25 PM (607 days ago)

Thanks Jeremy,

I just saw that the first file

"libboost_regex-vc90-mt-gd-1_35.lib"

does not exist in ..boost\lib

there is only a file called "libboost_regex-vc90-mt-sgd-1_35"

do I have to install additional libs for boost?

Fritz on 7/12/2008 4:19 AM (606 days ago)

Bloody hell, its saturday afternoon and I am sitting at my PC looking to see if the next bot article was up.
I need at bot to kick my ass out of here (and why isn't it up yet :-D)...

+rEbEl on 7/12/2008 3:55 PM (606 days ago)

Hi,
now everything is fine, I did not install all variants from boostpro.....

Fritz on 7/12/2008 8:00 PM (606 days ago)

Fritz,

Visit www.quantnet.org/.../showpost.php

I think that this can be your solution because i had the same problem.

You have to put the paths for include files

C:\Boost\include\boost-1_35
C:\Boost\include\boost-1_35\boost
C:\Boost\lib

and in library path

C:\Boost\lib

this work for me

good luck

------------------

This articles are the best. Thanks a lot for all and sorry about my english!!!!!

Waiting for the next chapter!!!

Somatxigun on 7/12/2008 8:25 PM (606 days ago)

Thanks Somatxigun,

with my last post I wanted to express that I already fixed my problem Wink

Fritz on 7/13/2008 8:09 AM (605 days ago)

I know Fritz Laughing!!!!

I didnt see your last post!!!!

Waiting for the next chapter!!!!!

Somatxigun on 7/13/2008 11:35 AM (605 days ago)

Thanks very much for the article and the idea. Over the I was able to put together a Trashbot in AutoIt and it abso-frickin-lutely rocks. Tonight I'm going to add some PixelChecksum functions to screenscrape the flop cards.

Awesome. Many Thanks.

EH

Anonymouse on 7/14/2008 11:49 AM (604 days ago)

I have a question for anyone reading... How are you handling the case in which a message is duplicated? Here is an example from a hooked ExtTextOutW to illustrate...

Hooked Function - Table Name = Message
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: The flop is [Ts 7s 8h]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: Pritt95 bets $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: bordos calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: Pritt95 bets $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: bordos calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: The turn is [3c]
MyExtTextOutW-Alto (6 max) - $5/$10 - Limit Hold'em=Dealer: SwimmingPool raises to $10
MyExtTextOutW-Alto (6 max) - $5/$10 - Limit Hold'em=Dealer: gambleallday folds
MyExtTextOutW-Alto (6 max) - $5/$10 - Limit Hold'em=Dealer: MGAMW calls $5
MyExtTextOutW-Alto (6 max) - $5/$10 - Limit Hold'em=Dealer: The flop is [Js 5d 6s]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: bordos calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: The turn is [3c]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: Pritt95 bets $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: The turn is [3c]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: Pritt95 bets $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=Dealer: bordos calls $10

Notice how the turn is "dealt" several times? Also how several bets are duplicated. How can we handle this sort of thing?

Robert on 7/14/2008 6:48 PM (604 days ago)

Robert,

Interesting. I wonder if that is spoofing.

Anonymous on 7/14/2008 7:01 PM (604 days ago)

Are you using Detours to hook?

Looks like you will need to write a filtering routine. The extent of the filtering will be determined by the frequency and extent of the duplicates. Do the duplicates occur on every hand? Is it always the turn?

Lone Ranger on 7/14/2008 7:09 PM (604 days ago)

>Interesting. I wonder if that is spoofing.

A sort of natural spoofing I think, where new messages entering the window cause cascading redraws as text is moved upward line by line. It depends on how exactly the client performs drawing but usually we expect the duplicates. But for example on PS the drawing's a little different, and we can bypass the dupes altogether.

>Looks like you will need to write a filtering routine.

Yes and one quick and dirty way is to filter by Y value. Provided you don't resize the window or touch the scroll bar, new text tends to enters the window at a constant Y because of the glue effect. Or at least, for any give X,Y associated with a TextOut call, you can answer the question "is this text at the bottom of the window?" The Y may or may not be constant, but it will always be higher than the Y of duped, pushed-upward text.

We'll cover this and some other approaches tomorrow, but there's no getting around the fact that TextOut hooking is a little messy.

James Devlin on 7/14/2008 8:45 PM (604 days ago)

You are 100% on the money James...

Another Example with more data:
Hooked Process - Window Name = int x int y (*lprc).top (*lprc).left (*lprc).bottom (*lprc).right = Message
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Hand #7224220307
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: Uncalled bet of $5 returned to sundog123
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: sundog123 mucks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: sundog123 wins the pot ($19)
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: Hand #7224220307
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: E-money posts the small blind of $2.50
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: sundog123 mucks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: sundog123 wins the pot ($19)
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: Hand #7224220307
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: E-money posts the small blind of $2.50
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames posts the big blind of $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: sundog123 wins the pot ($19)
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: Hand #7224220307
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: E-money posts the small blind of $2.50
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: MrGames posts the big blind of $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Zegai folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: Hand #7224220307
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: E-money posts the small blind of $2.50
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: MrGames posts the big blind of $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: Zegai folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Keysmark folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: E-money posts the small blind of $2.50
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: MrGames posts the big blind of $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: Zegai folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: Keysmark folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Tamburlaine folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: MrGames posts the big blind of $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: Zegai folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: Keysmark folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: Tamburlaine folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: sundog123 raises to $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: Zegai folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: Keysmark folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: Tamburlaine folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: sundog123 raises to $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: E-money folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: Keysmark folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: Tamburlaine folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: sundog123 raises to $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: E-money folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: Tamburlaine folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: sundog123 raises to $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: E-money folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: MrGames calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: The flop is [6d Jd Jh]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: sundog123 raises to $10
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: E-money folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: MrGames calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: The flop is [6d Jd Jh]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames checks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: E-money folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: MrGames calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: The flop is [6d Jd Jh]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: MrGames checks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: sundog123 bets $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: MrGames calls $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: The flop is [6d Jd Jh]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: MrGames checks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: sundog123 bets $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=0 top=0 left=0 bottom=16 right=412 =Dealer: The flop is [6d Jd Jh]
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=16 top=16 left=0 bottom=32 right=412 =Dealer: MrGames checks
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=32 top=32 left=0 bottom=48 right=412 =Dealer: sundog123 bets $5
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=48 top=48 left=0 bottom=64 right=412 =Dealer: MrGames folds
MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Uncalled bet of $5 returned to sundog123



Now that you've mentioned it it makes sense. Account for new text only entering when Y=64 (in this case for a maximized window)...

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Hand #7224220307

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: E-money posts the small blind of $2.50

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames posts the big blind of $5

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Zegai folds

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Keysmark folds

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Tamburlaine folds

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: sundog123 raises to $10

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: E-money folds

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames calls $5

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: The flop is [6d Jd Jh]

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames checks

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: sundog123 bets $5

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: MrGames folds

MyExtTextOutW-Alexandra (6 max) - $5/$10 - Limit Hold'em=X=3 Y=64 top=64 left=0 bottom=80 right=412 =Dealer: Uncalled bet of $5 returned to sundog123

Huzzah! The game makes sense!

Thanks for sharing your thoughts, I hope some other individuals can dervice some benefit from this.

Robert on 7/14/2008 8:48 PM (604 days ago)

Hi James,

first let me congratulate you on your very interesting article series.
Really great work.

I'm a professional programmer and interested in poker bots since about two years.
Actually I'm doing it right now more and more professionally.

For your readers who are not so deep in programing I have an interesting site.

Openholdem is an open source project.

You can download it for free and contribute code when you want.

Forum here: http://www.maxinmontreal.com/forums/index.php?c=34


Advantages:

- you can concentrate on the poker logic

- autoplayer, table scraping, etc. already included

- a lot of in-built functions like for example Pokertracker usage

- as said free and source code available

- you can write the poker logic for Limit Holdem, NL Holdem, PL Holdem, SNGs or MTTs

- big forum with many experts

Disadvantages:

- supports currently only Texas Holdem - not Omaha or 7 Stud

- you still need to write the poker logic which is the most difficult part
(most pokerbots are losers estimated 10% are winners)





OpenHoldem Botter on 7/14/2008 11:21 PM (604 days ago)

Hi James,

first of all, thank you for this very intresting articles!

I'm actualy working on a poker tool too, not a bot, or maybe not yet. This program is for 7-stud, not for hold'em and thats my biggest problem. The informations in the chat box dont have all infos on stud games (pokerstars).

Long time ago, I've tried to get some infos with API Hook, but it's failed. So I was working with screen-capturing, but it frusrating me!

I'm not a Windows API and C++ expert. Java and .NET is more my corner. Maybe u can help me, or some one else, to solve this problem and pointing that in the next part. I know one commercial program, that can do this well, Poker Pal. So I think it's possible.

Thank you!

Dima on 7/15/2008 10:43 AM (603 days ago)

Whens the new part coming?

Sorry Ive refreshed this page a million times over the last week, just curiousTong

tyler on 7/15/2008 9:50 PM (603 days ago)

^^ Yeah, tyler's right!

When will be the new part released?

My F5 key is dying...

Please, save my F5 key Smile

Anonymous on 7/16/2008 5:12 AM (602 days ago)

Hi!

I'm also working on a poker bot and I have a question for you.

I'm building my bot in .NET (C#) and decided to use screen scraping to get the info i need to build my domain model. I found a pretty god ocr sdk that I'm currently using. But now I'm leaning more and more to using dll injection.

So my question is:
.NET doesn't support global hooks (according to a several articles on msdn), do I have to use a global hook? I know that you are talking in favor of using C++ for the dll injection but I'm want to know if it's even possible to use .NET to accomplish this?

Sorry if my English is weird but I'm from Sweden and I took for granted that your Swedish is worse than my English Smile

jonny on 7/16/2008 5:37 AM (602 days ago)

>Whens the new part coming?

Apologies for the delay guys. The post should be out later today. It's a handful of new posts, not just one. We'll be at part 8 or 9 in the series within 24 hours.. knock on wood.

>.NET doesn't support global hooks (according to a several articles on msdn), do I have to use a global hook?

You can call any necessary injection functions (such as SetWindowsHookEx or various Detours APIs) using P/Invoke or by creating a small "wrapper" DLL in native or managed C++. There are some other ways also.

You can inject a native DLL into a managed process easily. But to inject a managed DLL into a native or managed process, but you have to load or attach to the CLR. That's a little messy but not too bad. Stay tuned..

James Devlin on 7/16/2008 7:31 AM (602 days ago)

I finally got something up and running, i decided to translate the C++ part into Delphi (thats what i know best after C#) and managed to get a global hook into processes. My plan is to send everything from the client chat to my managed C# application, but problems: Pokerstars doesnt seem to display holecards any longer??? or have i missed something?? Tried Full Tilt they have rigged their chat control to return an empty string when doing GetWindowText, any suggestions on how to get the information? I know u guys probably will say "Detours" but isnt there someway manual to get the same information? I am really not that good with C++ and dont know where to start with detours... any help will be appreciated.

Cheers...

H4mm3rHead on 7/16/2008 4:06 PM (602 days ago)

"...dont know where to start with detours... "

welcome to the club. can't do the nmake

Oscar on 7/16/2008 4:12 PM (602 days ago)

Woohoo! New parts later today!

Adam on 7/16/2008 4:20 PM (602 days ago)

wait a minute, have to prepare some disk space...Wink

popo on 7/16/2008 4:58 PM (602 days ago)

@H4mm3rHead & Oscar

Detours really is a nice software package, At full tilt it can be used in order to hook into ExtTextOutW to get the chat window text as it is output (thought it does require some buffering to ensure you are not processing the same text over and over again). There is a ton of sample code on how to use the detour's library and you really should consider giving it a shot.

The problem you are having with nmake is that you are not exporting the variables from the visual studio environment properly. You can solve this by either launching the command shell from within visual studio or you can execute vcvars32.bat (it's inside of the visual studio directory) which will add the path of nmake to your path as well as correcting several other possible problems with compilation.

Hope that helps! In my opinion the hardest thing was the dll injection (I used the CreateRemoteThread method) so the API hooking shouldn't be beyond your skill levels.

Robert on 7/16/2008 5:04 PM (602 days ago)

You are correct H4mm3rHead, Pokerstars no longer passes the hole cards to the chat window. Could be they got wind of this series? ;) ...And if that is so, I don't know that a hook or Detours will help if you are looking to hook the chat window. I am sure there is a memory location (variable) that contains a value for each of your current hole cards. If there is a way to "peek" into that it would be a simple interpretation. Otherwise, you may be back to a kludgy screen scraper as they have to let the user "see" their hole cards one way or another.

Jim on 7/16/2008 5:25 PM (602 days ago)

current hole cards shown in PokerStars.log or PokerStars.log.0

Anonymous on 7/16/2008 5:39 PM (602 days ago)

I got everything compiled. I did get a number of warnings during the compilation process, but everything did build.

I am using VS.NET 2005 Professional on XP.

I set PokerBot.MfcView to be the main application, and started it. It fails. I get "The application failed to initialize properly..." dialog.

The output window gives the following information:
LDR: LdrpWalkImportDescriptor() failed to probe c:\Documents and Settings\Administrator\Desktop\XPokerBot\XPokerBot\bin\XPokerBot.Hook.dll for its manifest, ntstatus 0xc0150002
Debugger:: An unhandled non-continuable exception was thrown during process load
The program '[332] XPokerBot.MfcView.exe: Native' has exited with code -1072365566 (0xc0150002).


Any ideas?

chipset on 7/16/2008 7:20 PM (602 days ago)

We'll be at part 8 or 9 in the series within 24 hours.. knock on wood.

Just 6 hours left...

I can barely see the text written on my F5 key...

Anonymous on 7/17/2008 2:24 AM (601 days ago)

My F5 key is dead....

Now using CTRL + R Smile

Anonymous on 7/17/2008 8:16 AM (601 days ago)

I was able to build it successfully, but somehow the Xpokerbot doesn't detect Poker time window. I'm assuming there's something that I need to change with the

"LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) ..."

Unfortunately, my programming exp is limited to Freshman and Sophomore level. I did understand most of the theory and a decent amount of the code, but I'm wondering how do I change the code so it'll detect pokertime.

I only saw CBTproc used one other time at

"bool XPOKERBOTHOOK_API InstallHook()
{
g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, g_hInstance, 0);

return g_hHook != NULL;
}"

Thanks!

Oky on 7/23/2008 10:46 PM (595 days ago)

I won't bother u with yet more praise on your articles... U seem to be getting enuf to know they're well appreciated, I just want to ask one non poker or programming realted Q, and provide (hopefully) something helpful for poker botting..

1st) That photo of the Difference Engine build with connector set... Can u lay your hands on the plans... that would be so sweet to build...

2nd) PokerAcademyPro is perfect for testing your poker logic, although u need to code it in Java... U can play it against the UofA bots, and play it yourself... so I find this a good tool for workin on my poker logic (which I am cutting in Java anyway so that restriction not bother me)
[and before I get all the comments about Java not being fast enough... Its all Visual J# compatible code, so it does get native compiled, not to mention gcj]

Aaron on 8/18/2008 3:17 AM (569 days ago)

Actually on second thought... You dont need to code a PokerAcademy Bot in Java at all... just use the JNI a write a small Java class to interface with PA and then call into your native code poker logic... This is the approach a mate of mine is using... Works perfectly, and only took him about an hour to get the JNI workin, and he never has to touch it again...

Aaron on 8/18/2008 3:21 AM (569 days ago)

Hi - very cool set of examples and some great code and architecture ideas, thanks!!

For those of you looking for a forum to discuss this further in a more structed manner I've set up one specifically for this topic at:

http://www.pokerbot.org/index.php/Coding-the-Wheel/

cheers!

pokerbot.org on 8/19/2008 4:18 PM (568 days ago)

So I just got started on this and I am running into this:
2>Linking...
2>LINK : fatal error LNK1104: cannot open file '..\bin\XPokerBot.Hook.lib'

and

1>LINK : fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_35.lib'

just-starting on 8/20/2008 9:11 AM (567 days ago)

This is a great series and it's nice to see all these code snippets brought together as a useful series. But now i'm kinda throwing a spanner in the works, because i'm not in the majority. Some of use Linux (or MAC) rather than Windows. And that means that we play poker via none-download browser versions which use either Java Applets or Flash. Hell, i'm sure there are also loads of Windows users out there who prefer not to download poker software...

So the question is: How do you read game info from a browser client? I know that it's possible to download an Applet, decompile the Jar, modify it and then re-compile so that you run the Applet as a localised file, but is there a more generic method? Can we perhaps hook into the JVM or catch the SSL encrypt/decrypt as it passes through memory? Has anyone successfully built a browser-based game monitor/bot??

LinuxUser on 8/28/2008 10:35 AM (559 days ago)

Here's a dumb question, but in Visual Studio 2005 if I was going to create a new .Hook what project type would it be? MFC DLL?

Anonymous on 9/3/2008 8:21 AM (553 days ago)

So the question is: How do you read game info from a browser client?

We'll investigate this at some point. There are certain things we can do because for example a Java app will still end up executing native code on the machine. Internal to the JVM. The same for Flash and others.

Here's a dumb question, but in Visual Studio 2005 if I was going to create a new .Hook what project type would it be?

Probably a plain-vanilla Win32 DLL is your best bet. An MFC DLL can be made to work, but why bring in the extra overhead?

James Devlin on 9/3/2008 11:15 PM (553 days ago)

Hi, I'm having some trouble with PokerStars when analyzing a table:

¿How can I know how many players are sitting at the table, who is the dealer, and where am I sitting? I can't find that information in chat window or in log file. And I do need that information when it's my turn to decide my next action.

The log file has some lines like these:

MSG_TABLE_SUBSCR_DEALPLAYERCARDS
sit0
nCards=2
sit1
nCards=2
sit2
nCards=2
sit3
nCards=2
sit4
nCards=2
sit8
nCards=2
dealerPos=8

But they are not associated to a window handle, so I can't know which table has those players and dealer pos. Anyway, from those lines I still don't know which my position is.

Any ideas?

Anonymous on 9/4/2008 6:37 AM (552 days ago)

This is what i get in the log file:
-----------------------------------------
MSG_TABLE_SUBSCR_DEALPLAYERCARDS
::: 11c
sit0
::: 14d
nCards=2
------ 000E0C50
sit1
Table::OnPlayerCards, myCards.changed=0, n=2, flags=0
nCards=2
myCards.changed=1
sit2
nCards=2
sit4
nCards=2
sit5
nCards=2
sit6
nCards=2
sit7
nCards=2
sit8
nCards=2
dealerPos=7
---------------------------------------

Having sit0 displayed with my hole cards [AdJc] i assume that would be my position?
and the number of players is the number of sitX lines in the log... (not the highest X)
In your example it seems there are 6 other players than you, and i would guess you are seated somewhere 6-7-8 (as they are missing from the list, and whichever you are, the other 2 are empty.

I dont know all of this for sure, but it seems logical to me...

Hope something here helps

Aaron on 9/7/2008 4:16 AM (549 days ago)

btw: I actually used the XMonitorBot tool to grab that info...

Aaron on 9/7/2008 4:20 AM (549 days ago)

Interesting, thank you. I think it could help, but seems not to be always that way. I'll try some things...

Anonymous on 9/7/2008 6:12 PM (549 days ago)

I'm a graduate-level programmer, yet not too familiar with both the windows API and C++ for that matter. During reading the code I came across function calls which start with a double colon. Like:

return ::GetModuleHandle(_T("MPPOKER.EXE")) != NULL;

Could anyone enlighten me what that means? [removing the colons does not break the application]

wachtwoord on 9/20/2008 4:52 PM (536 days ago)

Great article

Poker Bot on 10/13/2008 4:43 AM (513 days ago)

James, first - thanks! This is exactly what I've been searching for. It was easy to set up and ran exactly as you said it would.

Did you ever cover the duplicate elimination approach that you mentioned on 7/14?

happygolucky on 10/31/2008 10:04 PM (495 days ago)

The users of this forum are very helpful. It took me a 10 minutes to download and install the boost stuff, and get this thing working.

The following posts were all I needed...

1) BOOST INSTALLER -> popo on 7/6/2008 12:33:20 PM
2) VS doesn't find boost header files -> JeremyX on 7/6/2008 4:32:37 PM
3) LINKing boost libs fails -> JeremyX on 7/11/2008 8:25:30 PM

Search for those three posts and you should have no problem.

Thanks everyone!

happygolucky on 11/2/2008 8:45 AM (493 days ago)

PokerTime does not accept US accounts - is there a way to create an account for PLAY MONEY only, or does everyone have to have a house in Europe *wink wink*

happygolucky on 11/2/2008 4:06 PM (493 days ago)

Nice breakdown on creating a foldbot, thanks for yet another highly interesting article on creating an online poker bot! Smile

UK Poker Betting on 11/5/2008 10:36 AM (490 days ago)

I really like the poker bot erector set principle, it's a good method of approaching the sharing of this kind of information, kudos, and thank you.

Video Poker Guide on 11/5/2008 10:38 AM (490 days ago)

Hi , i'm ate very starting level of c++ programming at so low level so maybe i will make a stupid question....
From what i can undestand i can say that the MFCview starts the process of dllinjection and api hooking but i don't understand where is delcared wich dll will be injected ( in our case XPokerBot.Hook.dll )???

frengo on 11/22/2008 2:11 AM (473 days ago)

Ok now i found it .... there is the includsion of XPokerBot.Hook.h ...
And if i would like to use this dll from c# ? Should i write a dll just to be used in conjunction with c#?

frengo on 11/22/2008 2:33 AM (473 days ago)

As a Java programmer, with ZERO Visual Studio or C++ experience, I'm struggling (if that's what you call 2.5 hours of trying everything I can think of) to do what Robert posted on 7/14/08.

Can someone tell me what (*lprc) is referring to? My guess is that lprc is a pointer to something. The question is what is that something?

Which kind of object is he using that has a .top, .bottom, .left and .right that I can use?

I'd really appreciate it if someone would post a snippet of code to eliminate the duplicates in Full Tilt Chat.

I plan on sending the data to a seperate Java application. It'll be in the Java app that I do all of my "fun stuff" - I just want to eliminate the dupicates in the C++ code before sending it to the Java app for processing.

Thanks in advance

happygolucky on 11/25/2008 12:05 AM (471 days ago)

Built the bot at work but it run under

OS Name Microsoft Windows XP Professional
Version 5.1.2600 Service Pack 2 Build 2600

Any idea what tweak it needs?

jay on 11/27/2008 9:28 PM (468 days ago)

I get these two errors:
X 15 fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_37.lib
X 16 fatal error LNK1104: cannot open file '..\bin\XPokerBot.Hook.lib'

How do I fix this

Demon King on 12/6/2008 11:13 PM (459 days ago)

Someone please help me.

Error 1 fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_36.lib'
Error 2 fatal error LNK1104: cannot open file '..\bin\XPokerBot.Hook.lib'


I have built boost to get rid of its errors, I have Visual Studio Pro, I have built detours through the VS command prompt
<<

f:\Program Files\Microsoft Visual Studio 9.0\VC>nmake "F:\Program Files\Microsof
t Research\Detours Express 2.1\makefile"

Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.

'"F:\Program Files\Microsoft Research\Detours Express 2.1\makefile"' is up-to-da
te

>>

I am still getting the errors after doing all of that and cant think of anything else to do please help.

Ben on 12/17/2008 7:29 AM (448 days ago)

Can anyone confirm me that this code is still working today ?
The bot is running but when I join a table, nothing happens, the Fold Bot GUI is empty.

James, great work !! Thanks

Eric on 1/11/2009 12:44 PM (423 days ago)

yes it still works. just tested it.

guan on 1/20/2009 11:23 AM (414 days ago)

Hi!

while compiling project I had some mistake:
1)cannot open file include: regex.hpp

would you be so kind to explaine me how to solve this problem?
thanx ^^

getbraine on 1/27/2009 3:49 PM (407 days ago)

It's amazing! We almost wrote the bot for the other poker room. And now I find people who does the same things. I'll test FoldBot today.

EvGenius on 1/28/2009 11:12 AM (406 days ago)

Nice Series. Does anyone have a copy of the boost version boost_1_33_1. I would love to try this out and see it work. anyone please. I tried the boost.org site and it gives me an error message.

Could someone help?

AB on 2/1/2009 3:13 PM (402 days ago)

Can anybody confirm that this app is still working ?
The bot is running but the Fold Bot GUI is empty - I have opened 1-3 tables.

pepe on 2/2/2009 1:07 PM (401 days ago)

Great pictures well done!

Poker on 2/13/2009 3:53 PM (390 days ago)

OK for those that want explicit instructions to get it to build:

(I am using VS2008 pro on vista)
Step1: go to http://www.boostpro.com/products/free and install latest version of boost. I wasn't sure which variants to choose so just selected all of them.

Step2: open solution with VS

Step3: Select Tools->Options... on left-hand side select "Projects and Solutions", then "VC++ Directories".

Step4: Under "Show directories for:" dropdown list select "Include files" and add the following two lines:
C:\Program Files\boost\boost_1_37
C:\Program Files\boost\boost_1_37\boost (may vary depending on library version)

Step5: Under "Show directories for:" dropdown list select "Library files" and add the following:

C:\Program Files\boost\boost_1_37\lib (again, may vary slightly)

Step6: Build

gazzaaa87 on 2/26/2009 5:21 PM (377 days ago)

"So I just got started on this and I am running into this:
2>Linking...
2>LINK : fatal error LNK1104: cannot open file '..\bin\XPokerBot.Hook.lib'

and

1>LINK : fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_35.lib'"

(just-starting on 8/20/2008 9:11:12 AM)

Step5 above solves the *second* issue. To solve the first, simple re-extract the bin files from the XPokerBot.zip file and rebuild.

gazzaaa87 on 2/26/2009 6:52 PM (377 days ago)

"Can anybody confirm that this app is still working ?
The bot is running but the Fold Bot GUI is empty - I have opened 1-3 tables."

(pepe on 2/2/2009 1:07:16 PM)

I am running on vista and I also have this issue. James you mention that "This version of the bot has only been tested on Windows XP, so if you're running Vista or Windows 2000, you might have to do a little tweaking."

Has anyone worked out specifically what this tweaking is? Thanks Smile

gazzaaa87 on 2/26/2009 7:03 PM (377 days ago)

Nice job!

We did something similar here:
http://www.pokerbot-smart.com/

POKERBOT on 3/1/2009 12:03 PM (374 days ago)

[b]*** EMPTY TABLE SOLUTION ***[b]

I have worked out why the information doesn't populate the app window and why it doesn't fold. You will be pleased to hear it is an easy fix:

Step 1: (PokerTimeCaptionDecoder::decode method)

replace
[i]boost::regex regA("^Poker\\ Time\\ \\-\\ (?:[i] etc...
with
[i]boost::regex regA("^PokerTime\\.net\\ \\-\\ (?:[i] etc...

..the rest of the regex is correct.

Step 2: (CXPokerBotMfcViewDlg::OnCopyData method)

replace
[i]int itemIndex = FindListItemByParam((HWND)pCopyDataStruct->dwData);[i]
with
[i]int itemIndex = FindListItemByParam(hWnd);[i]

..this just ensures the table info is deleted when you leave a table.

[b]NB[b] Clearly these changes are independent of the OS you are running and I am running Vista. I can therefore confirm the bot still works on both XP [b]and[b] Vista. Kudos to James. Enjoy.

gazzaaa87 on 3/3/2009 12:46 PM (372 days ago)

*** EMPTY TABLE SOLUTION ***

I have worked out why the information doesn't populate the app window and why it doesn't fold. You will be pleased to hear it is an easy fix:

Step 1: (PokerTimeCaptionDecoder::decode method)

replace
boost::regex regA("^Poker\\ Time\\ \\-\\ (?: etc...
with
boost::regex regA("^PokerTime\\.net\\ \\-\\ (?: etc...

..the rest of the regex is correct.

Step 2: (CXPokerBotMfcViewDlg::OnCopyData method)

replace
int itemIndex = FindListItemByParam((HWND)pCopyDataStruct->dwData);
with
int itemIndex = FindListItemByParam(hWnd);

..this just ensures the table info is deleted when you leave a table.

NB Clearly these changes are independent of the OS you are running and I am running Vista. I can therefore confirm the bot still works on both XP and Vista. Kudos to James. Enjoy.

gazzaaa87 on 3/3/2009 12:47 PM (372 days ago)

Great job

poker bot software on 3/9/2009 7:13 AM (366 days ago)

***DETOURS HELP***

I have had a nightmare of a day trying to get my project to build but have finally worked it out and so thought I would share my solution to save anyone else this time.

To Build..

i) Download installer here.

ii) Instructions say to run 'nmake' but if you use the standard command prompt to do this you won't have the right environment variables. Use VS's command prompt instead (Tools->Visual Studio 2008 Command Prompt).

NB if you are using VS2008 you will still run into some errors - see this for the required fixes.

iii) Build should now succeed and therefore you should have the required detours.lib and detoured.lib files in the lib directory. Done! Smile

Integration with VS (2008)

i) Select Tools->Options.

ii) Select Projects and Solutions->VC++ Directories (on the left).

iii) Select Include files from the Show directories for: drop-down list and add the following line, (may be slightly different on your machine), and the select OK.

C:\Program Files\Microsoft Research\Detours Express 2.1\include

iv) Right-click on the project in Solution Explorer and select Properties at the bottom.

v) Select Configuration Properties->Linker->General (on the left) and add the following line to the Additional Library Directories field:

"C:\Program Files\Microsoft Research\Detours Express 2.1\lib"

vi) Select Configuration Properties->Linker->Input and add detours.lib detoured.lib to the Additional Dependencies field and finally select OK.

vii) Ensure your .cpp file has the following line:

#include <detours.h>

You should now be able to call detours methods without any compilation errors! Phew..

gazzaaa87 on 3/26/2009 3:01 PM (349 days ago)

It would have been nice if someone at any point in this thread corrected Fred on 7/2/2008 8:03:04 PM. The "/export:NullExport" text does NOT get written in "mydll Properties, Configuration Properties, Linker, General, Output File" textbox - that is for the name of your compiled DLL. This explains why popo and a small army of Anons could not find their compiled DLLs. The "/export:NullExport" text should be written in "mydll Properties, Configuration Properties, Linker, Command Line, Additional Options" textbox.

Dan on 4/6/2009 6:00 PM (338 days ago)

Some of the comments are a little over my head, but this isn't your regular blog audience, I guess.

Cali Poker Rooms on 4/25/2009 10:44 PM (319 days ago)

James,

Is there a particular reason you choose to use a CBT hook as opposed to spawning a remote thread in the poker client's process to call LoadLibraryEx?

Thanks,
Marc.

Marc on 5/13/2009 9:54 AM (301 days ago)

>Is there a particular reason you choose to use a CBT hook as opposed to spawning a remote thread in the poker client's process to call LoadLibraryEx?

Well, not really. The CBT Hook approach gives you a quick and dirty way of responding to window create/destroy/activate in the poker process via HCBT_CREATEWND etc. That's really the only reason I use it.

CreateRemoteThread etc. should work fine.

But in practice, you really want to hook the poker client at load time and suspend it, getting prima nocta on the target process so your code always runs first. In that case neither CBT Hooks nor CreateRemoteThread are really ideal.

James Devlin on 5/14/2009 1:47 AM (300 days ago)


But in practice, you really want to hook the poker client at load time and suspend it, getting prima nocta on the target process so your code always runs first. In that case neither CBT Hooks nor CreateRemoteThread are really ideal.


Any hints about what I should look into in order to achieve that? My initial guess would be to spawn a poker client process in suspended mode, and hook it at that point, but I bet there is a better way.
BTW, I love the use of prime nocta in this context Smile

Marc on 5/14/2009 9:30 AM (300 days ago)

Hi James,

A question concerning the approach of subclassing the chat window. If we attach the application to multiple windows, specially when we are working with two clients using the same software, there exists race conditions on the static callback for the EDITSTREAM callback, in your approach you've used a static HWND to save the handle to the chatbox every time you use the callback. However, when multiple windows access this callback at the same time, it would've overwritten the value of HWND and "could" proxy the intercepted message to the client app as part of the wrong window?

Is there an easy way around this? I've been playing with trampoline functions to map the callback to a non-static member function on the class itself, however inside an EDITSTREAMCALLBACK we have no detail about the window itself, nor can we pass this information to the function?

Ryno Smit on 5/18/2009 3:23 AM (296 days ago)

Clearly a bit early in the morning for me, ignore the working with two clients part, that would be impossible Tong seeing as we are in different address spaces. But hopefully you catch my drift...

Ryno Smit on 5/18/2009 3:29 AM (296 days ago)

Hi James,
can I have your e-mail adress or can you contact me on this one a-x-c@hotmail.fr ?

I've some questions and ideas about the poker bot...
So is it possible to talk with you by e-mail ?

(sorry for my faults, I'm french ^^)

Thanks,
Alex

Alex on 5/19/2009 10:57 AM (295 days ago)

Can someone verify the program still works? Built the solution, ran the exe, launched PokerTime, sat down, lists the tables I'm at, but doesn't see the hole cards or fold them during a hand. I'm playing 1 table, large view, with the Full Detail chat maximized on the right side. Any ideas?

CJ on 6/5/2009 2:47 AM (278 days ago)

CJ: My program also stopped working sometime in the past few days. Like you said, windows are recognized but it seems that no messages are recieved via the chat window. Something funky is happening in MyRichWndProc where it doesn't go ahead and call MyEditStreamCallback... Will try to look into it tomorrow.

Anonymous on 6/8/2009 11:05 PM (275 days ago)

Looks like Pokertime's been on the agressive lately. The EM_STREAMIN message which is normally 1097 is now 1092, but simply looking for 1092 instead doesn't seem to fix the problem...

Anonymous on 6/9/2009 12:47 AM (274 days ago)

that is the point of the OO design. my implementation uses the Windows API to switch between windows as required to make actions on multiple tables

gazzaaa87 on 7/18/2009 11:43 AM (235 days ago)

Okay, I successfully compiled, got my PokerTime Account, and nothing. I dont think Im launching the application correctly. I can find an executable /bin/XPokerBot.MfcView.exe that produces a gui and will populate some fields (table names) when I am on the PokerTable site, but the autofolding that I expect does not occur.
1. how to correctly launch the app?
2. does it matter that PokerTable message is "...15 seconds to act" and not "...10 seconds to act" as per readme file that came with code?

Hopefully someone is still reading this post and knows what Im talking about...
Thanks,
Craig

craig on 7/24/2009 5:49 PM (229 days ago)

I have the same problem as above poster. How do we remedy this?

xiN on 8/18/2009 8:13 AM (204 days ago)

Hey, I haven't programmed since I was a sophmore in college (1998) when I was programming in C++. So I don't remember a lot, and dont know a lot of the newer windows stuff, but I'm getting back into it. A couple things: 1. Is this article finished or will some more stuff be put out on this? 2. I was thinking about some ways to get around the poker site finding your program and freezing your account. A couple ideas I'm not sure whether they would work or not, but could you write a program that hooks the poker client, and just read the whole cards, board cards, evaluate your hand, and maybe give pot odds, something similar to some approved programs, then write the bot AI and automation stuff into a program that hooks into the first program, then hide that program with a rootkit? Another option would maybe be to hook into an approved poker program that reads the cards and get the information needed from that program, then you aren't hooking into the poker client at all. Not sure if that would work or not, but am curious about your opinions. Thanks and great article.

jkb on 9/5/2009 2:48 PM (186 days ago)

My mind boggles when reading your posts.

Texas Holdem Poker on 10/5/2009 6:06 PM (156 days ago)

Hi everyone,

I would like to congratulate James Devlin because your web site is really amazing. From the technical point of view, it is 7 stars, not 5. It is outstanding.

Right now, I would like to find someone to cooperate with me on a poker software project whose goal is to improve SNG table selection (Pokerstars). As James Devlin states, table selection is very, very important and I need to improve that area. What I am looking for is someone that is able to develop a software that retrieves the content of any listbox on Pokerstars. I have already developed all the software needed to evaluate if we should or should not register on each specific tournament taking into account some statistic criteria ....

If you are interested, please post your email on a comment and I will contact you afterward.

Poker of Aces on 11/22/2009 9:48 PM (108 days ago)

Hey Poker of Aces,
I work on another Poker project. I focus on cash games. But maybe we could exchange some knowledge and how to investigate new Poker rooms.

Feel free to write me an email: Klabautermann176@web.de

Klabautermann on 11/25/2009 8:12 PM (105 days ago)

Cool pictures its is really fun.

Unibet on 12/14/2009 1:11 AM (86 days ago)

Hi,
I tried to use detours with PokerTime. It works, meaning that I can see chat text and so on. But I cannot see the text that is being printed on a game table. Could you comment on that: what do they use to draw text there?

Anonymous on 12/27/2009 5:30 AM (73 days ago)

Hi!

I'm trying to follow your tutorial, when I compile the code under Windows 7 and VS2008 it has one error:

Error 1 fatal error LNK1104: cannot open file 'libboost_regex-vc90-mt-gd-1_42.lib' XPokerBot.Hook XPokerBot.Hook

Before it I had problems with regex but I installed boost, added the reference and put:

#include <boost\regex.hpp>

and no more problems with this

JuanPa on 2/4/2010 2:59 PM (34 days ago)

Thanks for sharing about the ingredients of online poker bot, so helpful it is. Online poker games is really a new step forward for science. Now rakeback poker games is the newest addition of poker industry. In this field a top rated site offers an unbelievable rakeback for all of us. Just enjoy it!

Poker on 2/8/2010 3:59 PM (30 days ago)

Hi all, very interesting and great feedback. I'm only at the Foldbot stage. And, I can't get it to work. It built properly and runs but it doesn't appear to interact with the PokerTime tables. I open a table and nothing happens with the app, I sit down and nothings happens either. I'm using XP Media Center SP 3. Using VS 2008 Full 90 day trial. Today is Feb. 17, 2010. Has anyone had this work for them recently and if so what are the tricks? Thanks.

DBH on 2/17/2010 12:30 PM (21 days ago)

Hi DBH,

I have the same problem; no population of de GUI-fields at all.
I am using Vista, MVS2008, detours ex2.1, boost_1_42.

- Boost build and tested
- Detours build and tested
- XPokerbot succesfull build
- replaced;
boost::regex regA("^Poker\\ Time\\
with
boost::regex regA("^PokerTime\\.net\\

Can someone confirm the app is still running today on pokertime?
thx

RAL on 3/1/2010 8:39 AM (9 days ago)

Hi,

I'm a bit late to the game here, and this post seems to be infested by spam, but I wonder if someone could give me a hand with getting a Hook to work, I am having problems.

I am trying to make a basic console application install a hook. I can check to see if it has worked by putting a breakpoint in the CBTProc function, and as it is, it seems the dll is not being called at all.

Running the code supplied in this post, the CBTProc function is called over and over once the hook has been installed. I tried to cut out the GUI by using the following code:

int _tmain(int argc, _TCHAR* argv[]){
bool bbbb = InstallHook();
Sleep(2000);
return 0;
}

Short I know, but I am just trying to get it to do anything at all.

I know that this code is installing the Hook correctly (bbbb returns true, and a breakpoint inside the InstallHook function is hit) but the CBTProc function is not called at all. By comparison, the call in the supplied GUI code is buried in the function: BOOL CXPokerBotMfcViewApp::InitInstance()

This code runs fine - it installs the hook, and the CBTProc function gets multiple hits.

I have made no other changes to the code, all I am trying to do is set it up so that the hook dll sends its information to a little program running in console rather than a gui (I am planning to use networking/sockets and stuff.)

I am still learning C++, and the Windows API is new to me. Could someone explain where I am going wrong here? Why does it seem that the hook is being installed, by not maintained? What do I have to do to get the hook working when installed from a console application?

Many thanks,
Oliver

Oliver on 3/2/2010 3:49 PM (8 days ago)

The foldbot is not working for me either. Builds ok but no tables are added to the gui. Windows XP SP3. VS2008 trial. Please heeeeeelp!

trendy on 3/6/2010 8:51 PM (4 days ago)

ASP.NET
(prerequisite for installing Visual Studio 2008, as instructed)

Went to IIS Manager as the READ ME instructed on the Visual Studio 2008...
But could not "ENABLE ASP.NET 2.0.5727" as instructed because I could not find any ASP.NET to enable.
Am I missing something?

How do I enable ASP.NET 2.0.5727?

Please advise.
Much thanks.

Tracy on 3/8/2010 6:53 PM (2 days ago)

Comment on this post:

Thanks for your interest in Coding the Wheel. All fields are optional.