Coding Horror

programming and human factors

The Rise of the PokerBots

Computer geeks have a long history of gaming the gaming industry. One of the most notable exploits is documented in the book Bringing Down The House: The Inside Story of Six MIT Students Who Took Vegas for Millions (read an excerpt in Wired). But things have changed now that gambling is moving to the internet in a big way. There's a fascinating article on Wired about the rise of the PokerBots:

For years, there has been chatter among online players about the coming poker bot infestation. WinHoldEm is turning those rumors into reality, and that is a serious problem for the online gambling business. Players come online seeking a "fair" shot - a contest against other humans, not robots. But an invasion of bots implies a fixed game (even though, like their mortal counterparts, they can and do lose if their hands are bad enough or opponents good enough). So the poker sites loudly proclaim that automated play is no big deal. At the same time, they are fighting back by quietly scanning for and eliminating suspicious accounts. "We're making sure we never have bots on our site," says PartyPoker marketing director Vikrant Bhargava.

That's an impossible promise to keep, says Ray E. Bornert II, WinHoldEm's elusive creator. He's trying to flood the online world with his bot - and make a killing in the process. Bornert offers an elaborate justification for what many view as outright cheating: Online poker is already rife with computer-assisted card sharks and - thanks to him - a growing number of outright bots. Players should get wise and arm themselves with the best bot available, which is, of course, WinHoldEm.

There's a quiet knock at the door of a hotel room in Atlanta. It's Bornert. A stocky, wide-faced 43-year-old with a neat goatee and nervous manner, he's carrying a router in a plastic bag. To demonstrate his software, he insists on meeting here in private, several miles from his office. He doesn't want anyone from the poker business to know where he is. "Our guard is constantly up," he says.

For Bornert, a former evangelical student, outsmarting the poker sites is not just a mission, it's a market. A suite of WinHoldEm programs is available for download at www.winholdem.net. For $25, you get a bare-bones setup: run-of-the-mill poker-hand analysis software. For $200, you can buy the full package: a one-year subscription to the team edition, which includes the autoplaying bot and a card-sharing module that allows multiple players to communicate during a game. Bornert won't say how many customers he has; he'll admit only that he makes a living selling WinHoldEm.

I can tell you from personal experience playing free multiplayer internet games that cheating has always been a serious problem. Game developers have to be vigilant and develop countermeasures early. If they don't, popular games rapidly degenerate into a morass of disheartened, unsure players and an unknown number of cheaters. Nothing psyches you out more than the idea that another player can switch to perfect, bot-like skills at will. Did they win because they were better than you, or because they cheated? There's just no way to know. It utterly destroys the game experience.

If people are that willing to cheat for literally nothing, with zero money at stake, imagine what lengths they'll go to when real money is involved.

That's why I tend to believe Mr. Bornert, a former evangelical student, when he compares WinHoldEm to civil disobedience:

"The reality is that the game changed the moment it moved to the Internet," Bornert says. Bots and bot-aided collusion were inevitable. Rather than seduce anyone into thinking such things didn't exist, Bornert had another notion: Put the power in the players' hands. By democratizing computer-assisted firepower, he'd make it part of the competition. "It's like football - if you don't wear a helmet and pads, you're going to get hurt," he says. "A poker bot is your equipment." And if that is considered unethical, then so be it. "I'd rather be unethical than be a victim," he says. "This is intentional civil disobedience."

Despite the protests of the online casino brass, the rise of the bots is completely inevitable. There's simply too much money at stake.

Out of curiosity, I checked out the winholdem support pages. This app is doing true GUI screen-scraping of the poker apps. That's why your poker app settings and Windows display options have to be locked down to known standards.

Of course, online casinos can (and do) fight back:

  1. Make your poker apps (these are regular .exe type apps) scan for instances of winholdem running on your local pc. Some online casinos are already doing this. There's a countermeasure for that, too: run it on a remote computer with an application that transmits screenshots of the poker app to the remote machine.
  2. Periodically strike up a conversation with the "player." That's tougher to combat. You could possibly re-broadcast your chat messages to IM services, if you happen to be near a computer at the time. The bots should limit their play at any given table to prevent a lot of conversation. And definitely have a vast library of canned phrases to respond with-- maybe even an Eliza implementation.
  3. Change the UI every hand. This is the one option that I didn't see explored in the article, but would be the hardest to combat. If the cards vary in size, color, design, and position every hand-- the scraping app is hosed.

In the meantime, if anyone is making a killing on internet poker with their 'bot, more power to you.

Discussion

How to be Lazy, Dumb, and Successful

Philipp Lenssen agrees that inspired laziness is a desirable trait for software developers:

.. only lazy programmers will want to write the kind of tools that might replace them in the end. Only a lazy programmer will avoid writing monotonous, repetitive code. The tools and processes inspired by laziness speed up production.

But Philipp adds one caveat: truly great programmers aren't just lazy. They're dumb, too:

Programmers who know they are smart

a) stop learning
b) stop being critical towards their own work

In the endless battle between programmer and compiler, give up early and admit that it's always you and never the compiler who is at fault.

Nobody is really smart enough to program computers. The only way you'll ever succeed as a software developer is through humility and the Zen concept of beginner's mind: approaching everything as if you were seeing it for the first time. Most of all, that means not being afraid to ask the stupid questions:

.. when confronted with a problem from management, a good programmer will adopt the mindset of being dumb. He will start asking the most simple, child-like questions, because he doesn't accept the parameters someone thinks make up the problem.

Unfortunately, I frequently see developers who are afraid to ask basic questions for fear of looking stupid. Maybe it's our macho smarter-than-thou programming culture. Having the guts to ask basic questions is, ironically enough, a hallmark of the best developers I've ever worked with.

Being lazy and dumb isn't just good career advice: it's the key to running a successful software business, too. As Mark Cuban points out, everyone else is just as lazy and dumb as you are:

It was Aaron Spelling I believe who said that "TV is the path of least resistance from complete boredom". Which is another way of saying that it's easier to watch TV than it is to sit there and do nothing.

Which describes exactly how people make most of their choices in life. They take the easy way. They take the path of least resistance.

There are certain things in life we all have to do. There are certain things in life we choose to do. Then there is everything else. The things we do to kill time. In every case, all things being equal, we choose the path of least resistance.

Understanding this concept is key to making good business decisions.

In other words, the only way to build great software is to make things as easy as possible for your users.

Discussion

Mavis Beacon Ate My Brain!

You may be familiar with the classic Mavis Beacon Teaches Typing* series of software from Broderbund.

Mavis Beacon Teaches Typing... and the perils of late 80s office fashions.

Well, Sega's sublime Typing of the Dead is like Mavis Beacon Teaches Typing ... if Mavis Beacon was a flesh-eating zombie!!

Typing of The Dead. TYPE OR DIE!

Any self-respecting software developer should be a decent typist. Now you can prove how much of a keyboard ninja you really are, because here's the best part: Typing of The Dead supports 2-player competitive network play over TCP/IP, with comprehensive post-game stat tracking (see screenshot).

It's hard to explain just how wondrously bizarre Typing of the Dead is. It's a challenging, remarkably well thought out typing tutor, a tongue-in-cheek b-grade zombie movie, and the most hilarious multiplayer game experience you'll probably ever have-- all at the same time.

As a zombie enthusiast, I bought Typing of the Dead immediately after it was released in 2001, but I can't find any vendors currently selling the PC version of the game on Froogle or eBay. It may legitimately be abandonware and therefore downloadable as a torrent ISO from The Underdogs. Once you obtain the game, legally or otherwise, install the nocd patch from GameCopyWorld, then copy the ~560mb install folder to a network share. Here's how to get a network game going:

  • Copy the game to your hard drive
  • Obtain and write down IP address of host (you'll be prompted for this later)
  • Run game, select Network menu option
  • One person selects Host Session, the other person selects Join Session and types in the IP of the Host
  • Important: if either computer is using Windows Firewall, you must ALT+TAB to desktop, check for Windows Firewall block dialogs, and unblock the game.

Now sit back and watch the hilarity ensue. It's pure genius.

In my testing, network play works flawlessly using current Windows XP SP2 systems as long as you use the original version of the game. Whatever you do, don't install the "ATI patch" for the game, as it completely breaks the network multiplayer functionality!

* Interestingly, Mavis Beacon isn't a real person. She's a logotype persona: an imaginary identity created entirely for the purpose of marketing. So I guess that puts her somewhere in between, say, Peter Norton and Carmen Sandiego.

Discussion

The User Interface Is The Application

Shawn Burke's post Shippin' Ain't Easy (but somebody gotta do it) explains why you have to resist change at the end of a project, no matter how justifiable and rational the reasons may be. Even the smallest change has a real risk of introducing additional bugs. The first commenter quipped:

TeX doesn't have bugs... Perhaps that's the exception that proves the rule :-)

Ian Ringrose immediately replied:

But does it have any users? Is the fact that it's very hard to use not a bug in and of itself?

Touch.

Yukihiro Matsumoto, the creator of Ruby, has strong feelings on this subject:

If you have a good interface on your system, and a budget of money and time, you can work on your system. If your system has bugs or is too slow, you can improve it. But if your system has a bad interface, you basically have nothing. It won't matter if it is a work of the highest craftsmanship on the inside. If your system has a bad interface, no one will use it. So the interface or surface of the system, whether to users or other machines, is very important.

It's also something Joel calls the iceberg secret:

I learned this lesson as a consultant, when I did a demo of a major web-based project for a client's executive team. The project was almost 100% code complete. We were still waiting for the graphic designer to choose fonts and colors and draw the cool 3-D tabs. In the meantime, we just used plain fonts and black and white, there was a bunch of ugly wasted space on the screen, basically it didn't look very good at all. But 100% of the functionality was there and was doing some pretty amazing stuff.

What happened during the demo? The clients spent the entire meeting griping about the graphical appearance of the screen. They weren't even talking about the UI. Just the graphical appearance. "It just doesn't look slick," complained their project manager. That's all they could think about. We couldn't get them to think about the actual functionality. Obviously fixing the graphic design took about one day. It was almost as if they thought they had hired painters.

I had this exact experience on a project recently. We're building all this cool back-end stuff, natch, and we needed a quickie front-end demo app to show it off. So we built a relatively simple demo app. It's decent, but barely competitive with other companies websites.

Guess what the client thought of our project?

I don't care how many kick-ass Visio architecture diagrams you have; as far as the user is concerned, the UI is the application. I know UI is Hard, but you have to build an impressive UI if you want to be taken seriously. Give your UI the high priority it deserves.

Discussion

Microsoft LogParser

Ask yourself this question: what if everything could be queried with SQL? Microsoft's LogParser does just that. It lets you slice and dice a variety of log file types using a common SQL-like syntax. It's an incredibly powerful concept, and the LogParser implementation doesn't disappoint. This architecture diagram from the LogParser documentation explains it better than I could:

logparser_architecture.gif

The excellent forensic IIS log exploration with LogParser article is a good starting point for sample LogParser IIS log queries. Note that I am summarizing just the SQL clauses; I typically output to the console, so the actual, complete commandline would be

logparser "(sql clause)" -rtp:-1

Top 10 items retrieved:

SELECT TOP 10 cs-uri-stem as Url, COUNT(cs-uri-stem) AS Hits
FROM ex*.log
GROUP BY cs-uri-stem
ORDER BY Hits DESC

Top 10 slowest items:

SELECT TOP 10 cs-uri-stem AS Url, MIN(time-taken) as [Min],
AVG(time-taken) AS [Avg], max(time-taken) AS [Max],
count(time-taken) AS Hits
FROM ex*.log
WHERE time-taken < 120000
GROUP BY Url
ORDER BY [Avg] DESC

All Unique Urls retrieved:

SELECT DISTINCT TO_LOWERCASE(cs-uri-stem) AS Url, Count(*) AS Hits
FROM ex*.log
WHERE sc-status=200
GROUP BY Url
ORDER BY Url

HTTP errors per hour:

SELECT date, QUANTIZE(time, 3600) AS Hour,
sc-status AS Status, COUNT(*) AS Errors
FROM ex*.log
WHERE (sc-status >= 400)
GROUP BY date, hour, sc-status
HAVING (Errors > 25)
ORDER BY Errors DESC

HTTP errors ordered by Url and Status:

SELECT cs-uri-stem AS Url, sc-status AS Status, COUNT(*) AS Errors
FROM ex*.log
WHERE (sc-status >= 400)
GROUP BY Url, Status
ORDER BY Errors DESC

Win32 error codes by total and page:

SELECT cs-uri-stem AS Url,
WIN32_ERROR_DESCRIPTION(sc-win32-status) AS Error, Count(*) AS Total
FROM ex*.log
WHERE (sc-win32-status > 0)
GROUP BY Url, Error
ORDER BY Total DESC

HTTP methods (GET, POST, etc) used per Url:

SELECT cs-uri-stem AS Url, cs-method AS Method,
Count(*) AS Total
FROM ex*.log
WHERE (sc-status < 400 or sc-status >= 500)
GROUP BY Url, Method
ORDER BY Url, Method

Bytes sent from the server:

SELECT cs-uri-stem AS Url, Count(*) AS Hits,
AVG(sc-bytes) AS Avg, Max(sc-bytes) AS Max,
Min(sc-bytes) AS Min, Sum(sc-bytes) AS TotalBytes
FROM ex*.log
GROUP BY cs-uri-stem
HAVING (Hits > 100) ORDER BY [Avg] DESC

Bytes sent from the client:

SELECT cs-uri-stem AS Url, Count(*) AS Hits,
AVG(cs-bytes) AS Avg, Max(cs-bytes) AS Max,
Min(cs-bytes) AS Min, Sum(cs-bytes) AS TotalBytes
FROM ex*.log
GROUP BY Url
HAVING (Hits > 100)
ORDER BY [Avg] DESC

There's an entire book about LogParser, and Mike Gunderloy even started an unofficial LogParser fansite.

Here are a few other articles I found that touch on different aspects of LogParser:

Although LogParser is 96.44% awesome, there are a few things that I didn't like about it:

  1. I really, really need a standard deviation function. Min, Max, and Avg are nice but totally inadequate for determining how variable something is.
  2. The graphing output is cool-- but it's also a MS Office dependency. If you try to graph something on a machine without Office installed, you'll get an error.
  3. The automatic detection of column types in CSV files isn't always reliable. This meant I couldn't graph some numeric values in my PerfMon dumps because LogParser decided they were strings. I couldn't find any way to force a column to be detected as a certain type, either.

Of course, the idea of SQL being used to query a bunch of stuff isn't exactly a new one; Microsoft's WQL (WMI Query Language) is similar but more annoying and less powerful. And you'll get tons of hits if you logically extend this concept to querying HTML, too. Just try searching Google for Web Query Language.

Discussion