Although this project was several years ago, the methods employed are still relevant and would be of interest to any AP seeking to automate baccarat online.
This essay will trace the creation of a successful online Baccarat Bot that I used for two-and-a-half years to beat an online Baccarat game that has now been discontinued. The reason for this post is to share a bit with the (BJ21) community, and for my own satisfaction, as this is the accomplishment I'm proudest of in my gambling career. I've made bigger scores working on other AP projects, but none of those were as personally gratifying or as fun as this one.
From mid-2002 to the start of 2007, when the UIGEA was enforced here in America, I was a full time bonus hustler. I had four or five different Neteller accounts that friends had let me set up and I, basically, had my run of things online. After the UIGEA ended my online exploits, I've been employed at a local University.
I have very little formal computer or mathematics training. Over the years, I've taken two or three courses in basic programming and calculus, so I know how simple computer programs run and I'm not unfamiliar with numbers, but I would describe myself as a programming/math hack.
Despite the disparagement from different gambling authors, Baccarat is a game that can be beaten. The method to beating the game is quite different, however, from linear blackjack counting systems, as noted in Griffin's Theory of Blackjack and other texts. Through combinatorial analysis, a player will find that a deeply dealt Baccarat shoe can offer positive expectation bets, and tie bets, in particular, can yield extremely high returns.
First, the game advertised nearly 98% penetration. The Game Rules stated:
"The cut card is then inserted seven cards from the end of the pack. When the cut card is reached, then either the current coup is completed or a final on is initiated."
Also, the game offered a "Pass" option, so if the player didn't want to play a hand, he could "Pass", and a Baccarat hand would be dealt without any wager. This combination of rules created a situation where a player could simply “Pass” on all negative wagers, saving his bets for end-game positive situations.
The problem, of course, was that to play this game perfectly, one would have to spend hours "passing away" negative EV hands followed by perfectly analyzing the remainder of the deck. These are processes which are time-consuming, monotonous, and require a great deal of calculation. Fortunately, computers are very useful for these types of tasks.
I tested the game in practice mode and soon realized that the game played differently than advertised. The practice game mode seemed to be played out of an 8-deck shoe. Later, I discovered that for real money, the game was, in fact, dealt out of a 6-deck shoe. Also, the penetration wasn't seven cards from the end, but was randomly set somewhere between the 9th and 23rd cards. After further analysis, I determined that, despite the inferior penetration, the game was still beatable and I began constructing a script.
AutoHotKey is an extremely useful macro programming language, which uses fairly simple instructions to automate computing tasks. Programmers have found many uses for it in poker and other gaming applications, and it seemed to be just what I was looking for. My first achievement was to write a script that simply pressed the “Pass” button over and over again. I remember the excitement of actually getting the cursor to act as I wanted it to which encouraged me to continue programming a game-playing script.
At first, I used a timing system to play the game. The script would wait a given number of seconds before clicking on the various buttons, but I found that if there was a delay in the Internet connection the timing would be thrown off and the script wouldn't work properly.
My first important discovery was the concept of image recognition, whereby the script would “look” for visual cues on the screen and act accordingly. I found a script online that could cut out pieces of the desktop and save them as a bitmap file. My program could then look for those pieces of the screen and act when it found them. I had solved the timing issue because the script could now play the game exactly how I would play, that is, by looking for visual cues and taking action.
The instructions for my image recognition technique are:
Short Pause ; without this pause the game client will slow to a crawl or freeze up
Search for the piece of the screen
If found --> break out of the current loop
This process greatly advanced my simple notions of programming in general. A programmer wants his program to "think" as he thinks, act as he acts, and operate tasks in the proper order. I suppose this is the higher definition of the "step-by-step" sequence that introductory programming texts describe. "Step-by-step" not only refers to the way a script is read line-by-line by the computer, but also describes the way you need to think through your algorithm.
The next challenge to get the program to recognize the cards. This turned out to be too easy, because the game would paste the last hand on the left of the game board. So, I made cut-out, bit-map files of all fifty-two cards and after the hand was over, the script would simply read the cards from the left hand side of the board and keep a running total of the remaining denominations.
Now that all the data was made available and the script could play the game, I began the process of actually using the information.
I once heard that, "to iterate is human, but to recurse is divine." Well…I'm human. I know there are powerful methods using combinatorics to compute the expected value (EV) of different baccarat subsets, but that was beyond the scope of my modest mathematics education. Intuitively, I'd guess that calculating the probabilistic likelihood of the hand results based on the remaining cards would be the solution, and maybe if I had the patience I could have figured it out. Basically, I didn't feel like spending a few days learning that "new" math, as I was eager to finish the project.
The next best solution was to use the remaining subset of cards and iterate every possible combination of Baccarat hands to determine the EV of a particular subset. This is limiting, because the number of iterations grows very quickly. For instance a remaining subset of twenty cards would yield 20*19*18*17*16*15 = 27,907,200 combinations for the play of one hand, which would take even a fast machine a while to compute. However, this was the best I could do and I hoped this method would suffice.
The process of writing the combinatorial analyzer was torturous at times. I received some very useful advice on Two Plus Two and other programming forums which helped tremendously. Finally, I was able to iterate all the combinations of an eleven-card subset and run each of those combinations through a baccarat game-play subroutine in about seven-and-a-half minutes. This achievement was a major breakthrough for me, but it needed to be sped up.
I made some adjustments in the script and was able to greatly reduce the number of iterations by eliminating the redundant ones. I also improved the way the script processed each possible hand through the game play subroutine. After a lot of hard work, I was able to calculate a subset of twenty-one cards in about five minutes. Smaller subsets were processed much faster. This was adequate for my purposes, as the bulk of the opportunity in baccarat lies in a depleted shoe. In other words, the advantage I lost by not computing subsets greater than twenty-one cards was trivial.
Computing a twenty-one-card baccarat subset in five minutes isn't a particularly noteworthy achievement in computer science, but it was the best I could do in the time that I spent. Game-play would be running automatically while I was away from the computer, so I could live with a slight loss of efficiency. I just wanted the script to work, because I could always add more computers and accounts later.
At the time, the minimum Punto-Banco bet was a mere three-dollars. I had about thirty bucks left over from my monthly bonus and I quickly burned through that. I deposited another thirty and lost that as well. However, I noticed one evening that the in-game display I created, which shows the EV of placed bets, was exactly the same after each hand. This was too coincidental and something had to be wrong.
I realized, after watching the game play for a while, that the variable in my script containing the string of remaining cards hadn't been initialized. The remaining cards in a given subset were being read, but without initializing the string variable after each hand, the string would remain the same. So with the addition of two characters of code, I was in business.
I deposited another thirty bucks and it started to build. I remember dragging home from a bar one night to find the script calculating, placing, and winning a three-dollar tie bet. A whole twenty-four dollar profit! I was sold. I began running the script day and night.
As time passed and the game played on, I added upgrades to the program that further improved its functionality.
As I mentioned, I created a display that remained in the corner of the screen that showed the progress of the shoe and all the relevant information about the remaining subset. When it came time to calculate any subset of twenty-one cards or less, the window would pause to calculate, then display the player advantage/disadvantage. This is how I discovered my error of not initializing the string variable.
Next, I added a feature that copied the hand information to a notepad every time the EV of the remaining subset was calculated, so I could track my results and relevant statistical data and enter that information into an excel sheet.
I also added a subroutine that exited the casino and re-entered it after playing fifteen shoes. For some unknown reason, resetting the game every few hours made it run faster.
A betting subroutine was added that could flex the bet size when I had a greater advantage. Initially, I set the bet unit size to just the minimum bet. As my bank grew, I adjusted my bet size to two percent of my bankroll, which was too high for my risk tolerance. Finally, I settled on adjusting the bet to roughly half of the Kelly fraction. The betting subroutine could place bets to the nearest one-dollar, which helped with the accuracy of the bet sizing.
Internet delays at the wrong time could potentially throw off the timing of certain events and create inaccuracies, so I added safeguards that insured that, if for some reason, the script miscounted the cards it couldn't place an unwanted bet and would simply shut off. Surprisingly, this feature wasn't used more than a handful of times, as the script was very accurate, and would reset itself correctly after every shoe. However, adding this feature did save me some money in the end.
Over the next few months, I ran the game constantly. My bank swelled to over 1K after making some aggressive bet sizing changes. Waking up in the morning and coming home in the evening was always exciting as I would check my balance to see if I made a score.
I understood there was a great deal of variance involved with large tie bets but I was unaware of just how dramatic those swings could be. Looking back, I realize I got lucky in my initial run, because my bank grew very quickly at first. For instance, one night, while cleaning my apartment, I checked on my script to find it had just placed and won a maximum $300 wager, for a $2400 profit. At the time, my bank was around 2K, so that bet size was too large, even if it was a winner. I continued to win that spring and early summer and after nine months of play, my bank had grown to nearly 8K.
Getting hit with the news of UIGEA was obviously troubling, as it completely changed my lifestyle and sent me back to work. However, for whatever reason, I was able to continue playing at Cryptologic casinos, but I couldn't deposit, withdraw, or open new accounts. I wasn't too concerned about the money in my account, as it was passive income after all. I'd worry about withdrawing later. I wanted to keep playing and see how far I could continue.
At this point, the script was completing about 4.5 shoes per hour and was placing one bet per hour, worth roughly 9% of a bet-unit. Nine-percent of a bet-unit per hour isn't a great win-rate relative to other games, however, the script could run round the clock, there was no heat from the casino, and the ability to add an indefinite number of accounts and machines gave the project unlimited potential.
I was invited to a Las Vegas wedding in Summer 2007, and I'd be gone for five days, so I figured I'd take a shot while I was away. I set my bet unit size to $90 (which was far too large for an 8k bank), and went off to sin city.
While on my trip, I had constant visions that I may come home to find myself 4-5k richer after a big score in a hot shoe. I returned to find the program still running five days later and I had lost about 2k.
Immediately, I paired down my bet size, but continued to lose, until my birthday five months later. As I lay in bed with a serious flu, my program won $1500 in two bets that day, as a little birthday gift.
Despite my birthday win, over the next year-and-a-half I played the game only for intermittent periods, as I began to feel to sting of variance. My bank had slid back down to a low of under 3k, and there was a point where I lost 156 of 160 tie bets placed, which was some serious negative flux considering they were all heavily positive EV bets. I would halt play for a month here and there, trying to protect the money I had won, which was a terrible idea.
At the beginning of 09' I began playing again at the minimum level deciding that I had worked too long and too hard on this program to not play. My bankroll went on another ride in Spring 09'when I'd finally set the bet size to the proper amount. I decided to grind out as many hands as I could.
I bought another computer with the intention of dedicating it to running the script non-stop. This machine processed the script a bit faster than my previous clunker, so I set up the Internet connection and away I went. The minimum and maximum bets had been raised at this point to $10 and $1000, which should have been a sign that someone on the casino side was monitoring the game.
July 2009 was dedicated to the game as I played 3000 shoes that month and finished with a nice run of over 1k in profit. Cyptologic discontinued the game on July 29th, 2009. I finished my Punto-Banco career with my bank just under 5K. Not a bad result from a couple of thirty-dollar deposits.
During my game-play I noticed something quite unusual regarding the play of subsets consisting of exactly 13 or 14 cards.
A Punto-Banco shoe always ends as follows: a bet is placed, then just before dealing the last hand of the shoe, the deck graphic changes size and shape (the deck gets significantly smaller showing that there aren't as may cards remaining) and the last hand is dealt out. For instance, say there are 17 cards left in the shoe, the player bets, the shoe would then change shape, and the last hand would be dealt. If the deck didn't change shape, at least one more hand would be dealt, after the current hand. The game flow of the last hand looks like this:
Bet placed --> shoe changes shape as the cards are dealt --> final hand is played --> cards are reshuffled
In the tens-of-thousands of shoes I ran, I had never witnessed or recorded a subset being dealt with less than 9 cards remaining. In fact, a 9-card subset only occurred maybe once in 50 shoes. However, I did encounter subsets with 13 cards where the deck didn't change shape before the deal and necessarily would dealt out exactly a four-card hand.
When the 13 card anomaly happens the game flow looks like this:
(13 cards remaining) Bet is placed --> shoe doesn't change shape --> exactly 4 and only four cards are dealt --> the final hand of the shoe is played with 9 cards
Given that the deck doesn't change shape, and the game never deals out a subset with less than 9 cards, then it is pre-determined, before the cards are dealt that the next hand will consist of exactly four cards. In other words, before the cards are out of the deck the game somehow "knows" the result of the hand.
This small discovery aroused more interesting questions. How is the cut card placed in the deck? Is it placed before the game deals the first hand of the shoe or does it determine the last hand on the fly with 22 cards or less to go?
Is the entire shoe possibly pre-determined by the Random Number Generator before the first hand is dealt? Is there a discernable pattern to this pre-determination? Simply knowing when the game would deal exactly a 4-card hand could, by itself, be extremely valuable in a casino that offers a .1% cash bonus for every wager (bet player!). Analyzing the remaining subset for that 4-card hand could be even more valuable.
With regard to the pre-determining of hands, I couldn't find any immediate patterns from my data, but, that doesn't mean patterns do not exist.
I believe that my results speak to a fairly dealt game. After all, I did win over a significantly large sample, and my data suggests the cards and individual denominations were dealt as they should, meaning, evenly distributed. However, although the game may be fair that doesn't necessarily mean it's completely random. The game seems to be dealt "randomly" in the sense that it obeys the laws of probability, but what type of randomness is it? I guess I'll never know for sure.
I have to admit that I'm a little sad today. I feel like a dear friend has passed. When I opened the casino client last night to search for "my" game and couldn't find it anywhere, immediately I knew… I knew it was gone forever. There will be others, but not quite like this one.
Before the game was discontinued, I had designs to add a few more computers assigned to international accounts and really make a run at Punto-Banco glory. Winning 2% of a unit per shoe and running 4000 shoes per month is roughly 80 bets won per machine per month. Using the largest optimum bet of $160, $12,800 per month in EV was possible per account. With a large enough bank, and enough computers running, there was no limit to the money I could have made. But alas, my dreams of a professional Punto-Banco career were torpedoed. I just didn't act fast enough.
It was surprising to me how long I could actually sit in front of this boring game with my script running, watching the endless "passing" of each hand and the ebb and flow of cards and numbers. I also enjoyed watching something I created actually succeed. I guess anything you work hard on you grow to enjoy.
I'd like to believe that I had a hand in burning out a game offered to a global gaming population. Clearly, the casino changed the bet sizing and later discontinued the game for a reason, so maybe I was one of the guys that prompted those changes. I've never done that before, so maybe that's something to say.
At the start of a new shoe, the house edge for the player bet is ~1.24 and the banker is ~1.06. The player/ banker edges will shift slightly throughout the shoe, and as the game becomes more penetrated, the shifts become larger. Since the banker and player bets are basically rival bets, the respective house edges are weighed against each other, and the total edge when both bets are added together is always ~2.3%. For instance, if the edge on a player bet is 1% then the edge on a banker bet would be around -3.3%.
In general, a deck rich in low cards are strong for player bets and a deck rich in high cards are strong for the banker bets.
Positive player bets will have a higher potential expectation than banker bets. The largest Player Bet edge I experienced was ~12% and the largest Banker Bet edge was ~5%.
The variance for a player or banker bet is less than 1 unit due to the fact that ties push.
The highest possible tie bet advantage is 800% and that bet is guaranteed to win. This only happens when all the cards remaining are of one denomination. In the game offered by Cryptologic, I calculated that this would occur roughly once in a million shoes.
The highest tie bet EV I ever encountered was 171%. There were 10 cards remaining in the shoe and the remaining deck composition was 6 tens and 4 aces. The 11-unit bet my script placed, lost.
I experienced tie bets with an EV of over 90% 12 times. The 3 highest EV bets were 171%, 106% and 99.6%.
The biggest bet I ever won was a max tie bet of $300. The bet had an expectation of ~96% and the max bet that was placed won, for a $2700 payout.
One tie bet subset that is quite profitable is one that contains all even valued cards, as the banker and player totals can only sum to even totals. The exact advantage on a tie bet in these instances varies, but generally ranges from ~50% and up.
Often, when a shoe offers a positive expectation tie bet, either the player or banker bets will be positive as well, thus it is correct to place a banker or player bet with a tie bet.
The formula for the percent chance that a given tie bet will hit is (player edge + 100%) / 9. This implies that a tie bet yielding an 80% advantage still has an 80% chance of losing.
I believe the ideal tie bet-unit size for this game is roughly 1/6 of the max bet. Therefore any bet over 96% EV would be a max bet, which, practically, is as high an advantage as one can reasonably expect on a regular basis. This bet size takes advantage of the "bet with your edge" feature of Kelly betting, while helping to mitigate variance.
I could run roughly 4.5 shoes per hour, 108 per day, and ~40,000 per year on one machine. That would equal ~80,000% EV which is equal to ~800 bets per year. Betting the maximum $160 per unit, that's ~$128,000 annually. Technically, more money could be made if you simply bet the max whenever you had a positive wager, but the bankroll requirements would be substantially greater, and impractical for an online casino.