<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-28618724</id><updated>2011-09-23T00:32:07.590-07:00</updated><title type='text'>Poker for Programmers</title><subtitle type='html'>Poker Algorithms and Tools for the C# Programmer.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-28618724.post-115052203305276974</id><published>2006-06-16T22:04:00.000-07:00</published><updated>2006-11-05T11:38:20.650-08:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;color:#ff6600;"&gt;This Blog Maybe Illegal in Washington State&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Washington State recently enacted a law making &lt;a href="http://seattlepi.nwsource.com/local/271844_internetgambling27.html"&gt;online gambling a felony&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I grew up in Washington State, I was born in Spokane, went to college in Pullman Washington and had a student internship in Renton Washington. I moved to Oregon for my first job more than 20 years ago.&lt;br /&gt;&lt;br /&gt;I hadn't been through the Seattle area since I first moved to Oregon, but last fall needed to drive to Spokane from Clatskanie Oregon. The fastest way there was through Seattle.&lt;br /&gt;&lt;br /&gt;When I moved from Seattle years ago there were no Indian Casinos (just smoke shops and fireworks stands that occasionally blew up). Now there are more Casinos visible from the freeway than McDonald's restaurants.&lt;br /&gt;&lt;br /&gt;Also in the last 20 years Washington State has adopted a state lottery. The Washington State lottery currently advertises regularly on TV along site online poker sites.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Don't Write About Gambling In Washington&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Washington State officials have interpreted the new law very broadly. Not only is gambling online illegal but linking to online casinos, hosting online casino advertising, or &lt;a href="http://www.bellinghamherald.com/apps/pbcs.dll/article?AID=/20060601/NEWS09/606010373/1022/NEWS09"&gt;even talking about gambling&lt;/a&gt;. The irony of these positions hasn't escaped the eye of &lt;span &gt;the &lt;/span&gt;&lt;a href="http://seattletimes.nwsource.com/html/localnews/2003062386_danny15.html"&gt;&lt;span &gt;Seattle Times&lt;/span&gt;&lt;/a&gt;. In a recent article the Times states:&lt;br /&gt;&lt;blockquote&gt;All that, says the state the ads, the linking, even the discussing violates a new state law barring online wagering or using the Internet to transmit "gambling information."&lt;br /&gt;"It's what the feds would call 'aiding and abetting,' " says the director of the state's gambling commission, Rick Day. "Telling people how to gamble online, where to do it, giving a link to it that's all obviously enabling something that is illegal."&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The articles author, Danny Westneat, goes on to say:&lt;br /&gt;&lt;blockquote&gt;Gambling officials told me The Seattle Times may be afoul of the law because we print a poker how-to column, "Card Shark," by gambler Daniel Negreanu. He sometimes tells readers to hone their skills at online casinos. And at the end of each column is a Web address, fullcontactpoker.com, where readers can comment.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;According to the &lt;a href="http://www.wsgc.wa.gov/docs/press_releases/internet_gambling_king_co_journal.pdf"&gt;Washington State Gaming Commission&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;The Washington State Gambling Commission was created to keep the criminal element out of gambling and to protect the public. The recently enacted&lt;br /&gt;legislation supports the Commission's efforts at fulfilling that responsibility.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;But in one added twist, not all online gambling is illegal. In 2004 the Washington State Legislature passed a law to bet on horse races online if you place the bet with a state licensed firm.&lt;br /&gt;&lt;br /&gt;So the bottom line is you can legal gambling in card rooms in Washington, you go to Indian Casinos, you can by Washington Lottery Tickets, and you can play the ponies online. But don't play poker online, link to any poker sites, or even talk about online gambling on your website if you live in Washington.&lt;br /&gt;&lt;br /&gt;Apparently online Casinos are putting the pinch on the states lively hood. Don't get in the way of the governor and his tax revenue, at least not in Washington.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-115052203305276974?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/115052203305276974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=115052203305276974' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/115052203305276974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/115052203305276974'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/06/this-blog-maybe-illegal-in-washington.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114982469627714934</id><published>2006-06-08T20:19:00.000-07:00</published><updated>2006-06-08T20:44:57.510-07:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;color:#ff6600;"&gt;Combinations, Permutations, and Hand Values&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You probably remember covering Permutations and Combinations in your High School math class. In case you missed that day of school, here's a quick summary.&lt;br /&gt;&lt;br /&gt;Permutations are used when you care about order. For example, As Ks would be considered unique from Ks As. Combinations are used when order doesn't matter.&lt;br /&gt;&lt;br /&gt;In Texas Holdem the hole cards As Ks (the ace of spades and the king of spades) are considered equivalent to Ks As. So combinations are used when calculating the number of hands.&lt;br /&gt;&lt;br /&gt;The formula for combinations is  &lt;span style="font-family:courier new;"&gt;nCk=n!/(k!*(n-k)!)&lt;/span&gt;&lt;span &gt;.&lt;/span&gt; To calculate the number of unique hole card combinations in Texas Holdem you substitute the following 52C2= 52!/(2!*(52-2)!) which is 1326 total hands.&lt;br /&gt;&lt;br /&gt;In the Hand Evaluator library (available in the downloads area on the left), we use 52 bits of a 64 bit int as a &lt;strong&gt;hand mask&lt;/strong&gt;. A hand mask describes a specific hand. Each of the 52 bits in the mask describe a specific card. When the bit is on the card is present. Combinations are used to describe the total number of possible unique hand masks.&lt;br /&gt;&lt;br /&gt;The Hand Evaluator library also uses &lt;strong&gt;hand values&lt;/strong&gt;. A hand value is the result of passing a hand mask into the Evaluate() method. What's returned is an integer value that can be used to determine which hands are of higher value than another.&lt;br /&gt;&lt;br /&gt;So looking at the number of unique hand value is also an interesting thing to know. The following table shows the number of hand values, permutations and combinations (hand masks) that a hand of a specific number of cards requires.&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/handcount.png"&gt;&lt;img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/handcount.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first time I saw anyone work through this was &lt;a href="http://www.suffecool.net/poker/evaluator.html"&gt;Cactus Kev&lt;/a&gt;. I found the results for 5 card hands to be, well, shocking. I never expected there to be only 7462 unique hand values for 5 card hands. Cactus Kev uses this fact to create a very fast hand evaluator algorithm.&lt;br /&gt;&lt;br /&gt;What I found even more surprising (at least until I spent sometime thinking about it), was that 6 and 7 card hands have even fewer possible hand values.&lt;br /&gt;&lt;br /&gt;Though this may seem like trivia, understanding this has been quite helpful to me. I hope it's useful for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114982469627714934?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114982469627714934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114982469627714934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114982469627714934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114982469627714934'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/06/combinations-permutations-and-hand.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114965674313062261</id><published>2006-06-06T22:05:00.000-07:00</published><updated>2006-06-08T19:26:57.656-07:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;color:#ff6600;"&gt;A Pocket Query Language &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm sure you've read a book or two on Holdem. One of the things I noticed while reading poker books is that there is a &lt;a href="http://en.wikipedia.org/wiki/De_facto"&gt;de facto standard&lt;/a&gt; for describing pocket cards. Most books use some variant of the following to describe pocket hands.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/pockethand1.png"&gt;&lt;p&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/pockethand1.png" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;Most poker software that parse string representations of pocket hands only supports the first item in the de facto standard.&lt;br /&gt;&lt;br /&gt;I've implemented a much richer query language. I support all of the common poker book syntax plus some extensions.&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/pockethand2.png"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/pockethand2.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I've also added some operators.&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/pockethand3.png"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/pockethand3.png" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt; Why a Pocket Query Language?&lt;/span&gt; &lt;p&gt;&lt;br /&gt;One of the things I've done too many times has been write code to analyze specific matchups. For example, have you ever wondered what the advantage is for have a suited connected verses a non-suited connector?&lt;/p&gt;&lt;p&gt;I'd guess you've probably wondered, but weren't enough of a masochist to write the code. On the other hand, I am enough of a masochist to write the code for many, many match ups. After awhile I decide I had enough of that and wrote a query language so that I could write my matchup analysis once and just put in query strings.&lt;/p&gt;&lt;p&gt;The following is an example of the result of using query strings rather than hard coded match ups. Oh and there is about a 5% advantage for suited connectors.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/PocketAppExam1.png"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/PocketAppExam1.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Using Pocket Queries in Code&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;I've attempted to make it trivial to write analysis code that utilized Pocket Queries. Here's an example.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#000000"&gt;&lt;br /&gt;&lt;div style="background-color: :#fffdf4; font-family: Courier; font-size: 11px; "&gt;&lt;pre&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Collections.Generic;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Text;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;namespace&lt;/FONT&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;FONT color="#0000FF"&gt;class&lt;/FONT&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;void&lt;/FONT&gt; Main(&lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// A Pocket Query Returns an array of all &lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// hands that meet the criterion.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt;[] player1 = PocketHands.Query(&lt;FONT color="#c00000"&gt;"Group3-Group5"&lt;/FONT&gt;);&lt;br /&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt;[] player2 = PocketHands.Query(&lt;FONT color="#c00000"&gt;"Axs"&lt;/FONT&gt;);&lt;br /&gt;   &lt;br /&gt;            &lt;FONT color="#008000"&gt;// Holds stats&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; player1Wins = 0, player2Wins = 0, &lt;br /&gt;                    ties = 0, count = 0;&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Iterate through 10000 trials.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;for&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; trials = 0; trials &amp;lt; 10000; trials++)&lt;br /&gt;            {&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Pick a random pocket hand out of player1's query set&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; player1Mask = Hand.RandomHand(player1, 0UL, 2);&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Pick a random pocket hand for player2&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; player2Mask = Hand.RandomHand(player2, player1Mask, 2);&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Pick a random board&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardMask = Hand.RandomHand(player1Mask |player2Mask, 5);&lt;br /&gt;                &lt;br /&gt;                &lt;FONT color="#008000"&gt;// Create a hand value for each player&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; player1HandValue = Hand.Evaluate(boardMask | player1Mask, 7);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; player2HandValue = Hand.Evaluate(boardMask | player2Mask, 7);&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Calculate Winners&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (player1HandValue &amp;gt; player2HandValue)&lt;br /&gt;                {&lt;br /&gt;                    player1Wins++;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (player1HandValue &amp;lt; player2HandValue)&lt;br /&gt;                {&lt;br /&gt;                    player2Wins++;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt;&lt;br /&gt;                {&lt;br /&gt;                    ties++;&lt;br /&gt;                }&lt;br /&gt;                count++;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;           &lt;br /&gt;            &lt;FONT color="#008000"&gt;// Print results&lt;br /&gt;&lt;/FONT&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"Player1: {0:0.0}%"&lt;/FONT&gt;,&lt;br /&gt;                    (player1Wins + ties/2.0) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)count) * 100.0);&lt;br /&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"Player2: {0:0.0}%"&lt;/FONT&gt;,&lt;br /&gt;                    (player2Wins + ties/2.0) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)count) * 100.0);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/Font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114965674313062261?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114965674313062261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114965674313062261' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114965674313062261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114965674313062261'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/06/pocket-query-language-im-sure-youve.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114904580856779069</id><published>2006-05-30T20:15:00.000-07:00</published><updated>2006-06-05T14:07:01.443-07:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;color:#ff6600;"&gt;Calculating Outs (Part 1) &lt;/span&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Most Hold'em players know what &lt;a href="http://en.wikipedia.org/wiki/Out_(poker)"&gt;Outs &lt;/a&gt;are. According to Wikipedia an out is:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;[A]n out is any unseen card that, if drawn, will improve a player's hand to one that is likely to win&lt;/em&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The question for the programmer is, is this definition sufficent to write a function that returns the cards that are outs?&lt;/p&gt;&lt;p&gt;Let's look at the two key points made by Wikipedia. They are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The hand must improve &lt;/li&gt;&lt;li&gt;The new hand is likely to win.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Let's start by writing a function that meets the first criterion.&lt;br /&gt;&lt;br /&gt;&lt;!-- Start of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 11px; FONT-FAMILY: Courier; BACKGROUND-COLOR: #fffdf4"&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#008000;"&gt;// A first try at calculating outs&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {       &lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; pocket = &lt;span style="color:#c00000;"&gt;"As Ac"&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; board = &lt;span style="color:#c00000;"&gt;"Kd 8h 9c"&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Calcuate the outs&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; outsmask = Outs(Hand.ParseHand(pocket), Hand.ParseHand(board));&lt;br /&gt;&lt;br /&gt;            Console.WriteLine(&lt;span style="color:#c00000;"&gt;"[{0}] {1} : Outs Count {2}"&lt;/span&gt;,&lt;br /&gt;                    pocket, board, Hand.BitCount(outsmask));&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// List the cards&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; card &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Hand.Cards(outsmask))&lt;br /&gt;            {&lt;br /&gt;                Console.Write(&lt;span style="color:#c00000;"&gt;"{0} "&lt;/span&gt;, card);&lt;br /&gt;            }&lt;br /&gt;            Console.WriteLine();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color:#008000;"&gt;// Return a hand mask of the cards that improve our hand&lt;br /&gt;&lt;/span&gt;        &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; Outs(&lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; pocket, &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; board)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; retval = 0UL;&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; hand = pocket  board;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Get original hand value&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; playerOrigHandVal = Hand.Evaluate(hand);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Look ahead one card&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; card &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Hand.Hands(0UL, hand, 1))&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// Get new hand value&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; playerNewHandVal = Hand.Evaluate(hand  card);&lt;br /&gt;&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// If the hand improved then we have an out&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (playerNewHandVal &amp;gt; playerOrigHandVal)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color:#008000;"&gt;// Add card to outs mask&lt;br /&gt;&lt;/span&gt;                    retval = card;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// return outs as a hand mask&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; retval;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Passing this starting hand &lt;span style="color:#000000;"&gt;&lt;span style="font-family:times new roman;"&gt;A♠ A♣&lt;/span&gt;,&lt;/span&gt; &lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#ff0000;"&gt;K♦&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;8♥&lt;/span&gt; &lt;span style="color:#000000;"&gt;9♣&lt;/span&gt;&lt;/span&gt; it into our new method returns the following outs: &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#000000;"&gt;K♠&lt;/span&gt;, &lt;span style="color:#000000;"&gt;9♠&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;9♥&lt;/span&gt;, &lt;span style="color:#000000;"&gt;8♠&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;K♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;9♦&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;8♦&lt;/span&gt;, &lt;span style="color:#000000;"&gt;K♣&lt;/span&gt;, &lt;span style="color:#000000;"&gt;8♣&lt;/span&gt; - Two pair&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#ff0000;"&gt;A♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;A♦&lt;/span&gt; - Trips&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#000000;"&gt;Q♠&lt;/span&gt;, &lt;span style="color:#000000;"&gt;J♠&lt;/span&gt;, &lt;span style="color:#000000;"&gt;T♠&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;Q♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;J♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;T♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;Q♦&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;J♦&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;T♦&lt;/span&gt;, &lt;span style="color:#000000;"&gt;Q♣&lt;/span&gt;, &lt;span style="color:#000000;"&gt;J♣&lt;/span&gt;, &lt;span style="color:#000000;"&gt;T♣&lt;/span&gt; - Improves Kicker &lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;I think most people would agree that super-sizing your kicker probably doesn't help much here. I think most people would also agree that improving the board doesn't help either. So let's add two more rules:&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The hand must improve&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color:#3333ff;"&gt;The new hand improvement must be better than an improved kicker&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color:#3333ff;"&gt;The new combined hand must be stronger than the just the board&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;The new hand is likely to win&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The following example handle these new rules and allows opponent hands to be added.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 11px; FONT-FAMILY: Courier; BACKGROUND-COLOR: #fffdf4"&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#008000;"&gt;// A first try at calculating outs&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {       &lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; pocket = &lt;span style="color:#c00000;"&gt;"As Ac"&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; board = &lt;span style="color:#c00000;"&gt;"Kd 8h 9c"&lt;/span&gt;;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Calcuate the outs&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; outsmask = Outs(Hand.ParseHand(pocket), Hand.ParseHand(board));&lt;br /&gt;&lt;br /&gt;            Console.WriteLine(&lt;span style="color:#c00000;"&gt;"[{0}] {1} : Outs Count {2}"&lt;/span&gt;,&lt;br /&gt;                    pocket, board, Hand.BitCount(outsmask));&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// List the cards&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; card &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Hand.Cards(outsmask))&lt;br /&gt;            {&lt;br /&gt;                Console.Write(&lt;span style="color:#c00000;"&gt;"{0} "&lt;/span&gt;, card);&lt;br /&gt;            }&lt;br /&gt;            Console.WriteLine();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color:#008000;"&gt;// Return a hand mask of the cards that improve our hand&lt;br /&gt;&lt;/span&gt;        &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; Outs(&lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; pocket, &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; board, &lt;span style="color:#0000ff;"&gt;params&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; [] opponents)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; retval = 0UL;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Get original hand value&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; playerOrigHandVal = Hand.Evaluate(pocket  board);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Look ahead one card&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; card &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Hand.Hands(0UL, board  pocket, 1))&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// Get new hand value&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; playerNewHandVal = Hand.Evaluate(pocket  board  card);&lt;br /&gt;               &lt;br /&gt;                &lt;span style="color:#008000;"&gt;// Get new board value&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; boardHandVal = Hand.Evaluate(board  card);&lt;br /&gt;&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// Is the new hand better than the old one?&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; handImproved = playerNewHandVal &amp;gt; playerOrigHandVal &amp;&amp;amp;&lt;br /&gt;                        Hand.HandType(playerNewHandVal) &amp;gt; Hand.HandType(playerOrigHandVal);&lt;br /&gt;&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// This compare ensures we move up in hand type.&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; handStrongerThanBoard =&lt;br /&gt;  Hand.HandType(playerNewHandVal) &amp;gt; Hand.HandType(boardHandVal);&lt;br /&gt;&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// Check against opponents cards&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; handBeatAllOpponents = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (handImproved &amp;&amp;amp; handStrongerThanBoard &amp;&amp;amp;&lt;br /&gt;   opponents != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; &amp;&amp;amp; opponents.Length &amp;gt; 0)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;ulong&lt;/span&gt; opponent &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; opponents)&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span style="color:#0000ff;"&gt;uint&lt;/span&gt; opponentHandVal = Hand.Evaluate(opponent  board  card);&lt;br /&gt;                        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (opponentHandVal &amp;gt; playerNewHandVal)&lt;br /&gt;                        {&lt;br /&gt;                            handBeatAllOpponents = &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;;&lt;br /&gt;                            &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;span style="color:#008000;"&gt;// If the hand improved then we have an out&lt;br /&gt;&lt;/span&gt;                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (handImproved &amp;&amp;amp; handStrongerThanBoard &amp;&amp;amp; handBeatAllOpponents)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color:#008000;"&gt;// Add card to outs mask&lt;br /&gt;&lt;/span&gt;                    retval = card;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// return outs as a hand mask&lt;br /&gt;&lt;/span&gt;            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; retval;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Passing this starting hand &lt;span style="color:#000000;"&gt;&lt;span style="font-family:times new roman;"&gt;A♠ A♣&lt;/span&gt;,&lt;/span&gt; &lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#ff0000;"&gt;K♦&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;8♥&lt;/span&gt; &lt;span style="color:#000000;"&gt;9♣&lt;/span&gt;&lt;/span&gt; to our new method produces following outs:&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#000000;"&gt;K♠&lt;/span&gt;, &lt;span style="color:#000000;"&gt;9♠&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;9♥&lt;/span&gt;, &lt;span style="color:#000000;"&gt;8♠&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;K♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;9♦&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;8♦&lt;/span&gt;, &lt;span style="color:#000000;"&gt;K♣&lt;/span&gt;, &lt;span style="color:#000000;"&gt;8♣&lt;/span&gt; - Two pair&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="color:#ff0000;"&gt;A♥&lt;/span&gt;, &lt;span style="color:#ff0000;"&gt;A♦&lt;/span&gt; - Trips&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This new method is certainly better than our first method. But we can still do better.&lt;/p&gt;&lt;p&gt;Stay tuned for more indepth discussion on improving our outs method.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114904580856779069?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114904580856779069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114904580856779069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114904580856779069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114904580856779069'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/05/calculating-outs-part-1-most-holdem.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114885419600047229</id><published>2006-05-28T15:09:00.000-07:00</published><updated>2006-05-31T19:24:24.306-07:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;"&gt;&lt;span style="color:#ff6600;"&gt;Calculating Win Odds for Multiple Opponents &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:180%;"&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="color:#ff6600;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/WinAsKsTsQs9d.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Probably the most frequent question I received after writing a&lt;a href="http://www.codeproject.com/csharp/pokerhandevaldoc.asp"&gt; poker article &lt;/a&gt;for &lt;a href="http://www.codeproject.com/"&gt;CodeProject &lt;/a&gt;was "How do you calculate win odds for multiple opponents?"&lt;br /&gt;&lt;br /&gt;Writing code to exhaustively calculate the win odds for multiple opponents is very straightforward; unfortunately the time it takes to calculate an answer is prohibitive.&lt;br /&gt;&lt;br /&gt;There are solutions to this problem available on line. One solution is &lt;a href="http://www.brecware.com/Software/software.html"&gt;Hold'em Showdown&lt;/a&gt; by Steve Brecher. Hold'em Showdown is a very fast solution for exhaustively calculating win odds for multiple opponents. However, even using the fastest hand evaluator publicly available and tweaking C code for this specific solution, the maximum opponents is 4 and getting the results takes some time, making this technique not terrible practical for getting answers in real-time.&lt;br /&gt;&lt;br /&gt;Another method is to use precalculated tables. An example of this is &lt;a href="http://games.cs.ualberta.ca/poker/Flop_Table/"&gt;Marv742's tables&lt;/a&gt;. One problem with using tables is they are large (50Megs compressed). Another problem is that Marv's tables only have results for 1, 3, 5 and 9 opponents. &lt;/p&gt;&lt;p&gt;I know a online player that has made good use of Marv742's tables, but using them seemed very unwieldy and limiting to me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;An Alternate Approach&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I prefer using a Monte Carlo approach to calculating win odds. This technique works well at getting good approximate values. The more time you allow for the calculation the more accurate the returned value. My experience is that 0.01 (10 milliseconds) give reasonably results. Of course more time gives even more accurate results. &lt;/p&gt;&lt;p&gt;I used this technique to create the graph in the beginning of this article. The results are very consistent and stable even using fairly small time values. You can use the same method I use by calling Hand.WinOdds() in the Hand Evaluator library found on the downloads section.&lt;/p&gt;&lt;p&gt;The following code shows how to use this technique to calculate approximate win odds for 5 opponents.&lt;br /&gt;&lt;!-- Start of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;div style="background-color: #fffdf4; font-family: Courier; font-size: 12px; "&gt;&lt;pre&gt;&lt;br /&gt;&lt;FONT color="#000000"&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#008000"&gt;// This example calculates the win odds for a player having "As Ks" against &lt;br /&gt;&lt;/FONT&gt;&lt;FONT color="#008000"&gt;// five random players&lt;br /&gt;&lt;/FONT&gt;&lt;FONT color="#0000FF"&gt;namespace&lt;/FONT&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;FONT color="#0000FF"&gt;class&lt;/FONT&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;void&lt;/FONT&gt; Main(&lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Calculate win odds using example code&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; w1 = WinOddsFivePlayerMonteCarlo(Hand.ParseHand(&lt;FONT color="#c00000"&gt;"as ks"&lt;/FONT&gt;), 0UL, 5.0);&lt;br /&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"win: {0:0.00}%, time {1:0.0000}"&lt;/FONT&gt;, w1 * 100.0, 5.0);&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Calcluate win odds using Hand.WinOdds()&lt;br /&gt;&lt;/FONT&gt;            w1 = Hand.WinOdds(Hand.ParseHand(&lt;FONT color="#c00000"&gt;"as ks"&lt;/FONT&gt;), 0UL, 5, 5.0);&lt;br /&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"win: {0:0.00}%, time {1:0.0000}"&lt;/FONT&gt;, w1 * 100.0, 5.0);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;FONT color="#008000"&gt;// An example of how to calculate win odds for five players&lt;br /&gt;&lt;/FONT&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; WinOddsFivePlayerMonteCarlo(&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; pocket, &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; board, &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; duration)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Keep track of stats&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; win = 0, lose = 0, tie = 0;&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Loop through random boards&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardmask &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt; Hand.RandomHands(board, pocket, 5, duration))&lt;br /&gt;            {&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Get random opponent hands&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opp1mask = Hand.RandomHand(boardmask | pocket, 2);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opp2mask = Hand.RandomHand(boardmask | pocket | opp1mask, 2);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opp3mask = Hand.RandomHand(boardmask | pocket | opp1mask | &lt;br /&gt;                                        opp2mask, 2);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opp4mask = Hand.RandomHand(boardmask | pocket | opp1mask | &lt;br /&gt;                                        opp2mask | opp3mask, 2);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opp5mask = Hand.RandomHand(boardmask | pocket | opp1mask | &lt;br /&gt;                                    opp2mask | opp3mask | opp4mask, 2);&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Get hand value for player and opponents&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; playerHandVal = Hand.Evaluate(pocket | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opp1HandVal = Hand.Evaluate(opp1mask | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opp2HandVal = Hand.Evaluate(opp2mask | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opp3HandVal = Hand.Evaluate(opp3mask | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opp4HandVal = Hand.Evaluate(opp4mask | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opp5HandVal = Hand.Evaluate(opp5mask | boardmask);&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Tally results&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (playerHandVal &amp;gt; opp1HandVal &amp;&amp; &lt;br /&gt;                    playerHandVal &amp;gt; opp2HandVal &amp;&amp;&lt;br /&gt;                    playerHandVal &amp;gt; opp3HandVal &amp;&amp; &lt;br /&gt;                    playerHandVal &amp;gt; opp4HandVal &amp;&amp;&lt;br /&gt;                    playerHandVal &amp;gt; opp5HandVal)&lt;br /&gt;                {&lt;br /&gt;                    win++;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (playerHandVal &amp;gt;= opp1HandVal &amp;&amp; &lt;br /&gt;                        playerHandVal &amp;gt;= opp2HandVal &amp;&amp;&lt;br /&gt;                        playerHandVal &amp;gt;= opp3HandVal &amp;&amp; &lt;br /&gt;                        playerHandVal &amp;gt;= opp4HandVal &amp;&amp;&lt;br /&gt;                        playerHandVal &amp;gt;= opp5HandVal)&lt;br /&gt;                {&lt;br /&gt;                    tie++;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt;&lt;br /&gt;                {&lt;br /&gt;                    lose++;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Return stats&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;return&lt;/FONT&gt; ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)(win + tie / 2.0)) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)(win + tie + lose));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/FONT&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End of snippet generated by C#2HTML --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114885419600047229?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114885419600047229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114885419600047229' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114885419600047229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114885419600047229'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/05/calculating-win-odds-for-multiple.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114876570370449156</id><published>2006-05-27T14:33:00.000-07:00</published><updated>2006-06-29T17:32:26.170-07:00</updated><title type='text'></title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/Table1.png"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Using Monte Carlo Analysis In Poker Software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Monte_Carlo_analysis"&gt;Monte Carlo Analysis&lt;/a&gt; can be used in analysing poker hands. There are many reasons people choose to use Monte Carlo Analysis. In poker, the most common reason is to get a quick answer for something that otherwise would take a prohibitively long-time to calculate.&lt;br /&gt;&lt;br /&gt;I resisted using Monte Carlo Analysis for quite some time. I clung to my wish that a sufficently fast Poker Hand Evaluator Library would eliminate the need for needing to use woo-woo techniques like this.&lt;br /&gt;&lt;br /&gt;To convince myself of the value of Monte Carlo Analysis I had to work through how to analyse the win odds for one or more players.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Calculating Win Odds&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Consider the following code. It calculates the win odds for a player being dealt AKs against a random opponent.&lt;br /&gt;&lt;br /&gt;This program takes about 299 seconds (nearly 5 minutes) to calculate with no board cards. That means the code is evaluating 14,084,025 Hands/Sec and a total of 2,097,572,400 (yes billions) of hand match ups. With three cards in the board it takes 0.263 seconds and a total of 1,070,190 hand match ups.&lt;br /&gt;&lt;br /&gt;When there are cards on the board, this function is very usable. However, if you are calculating hole card win probabilities with this, then the algorithm is far too slow to be usable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;!-- Start of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 12px; "&gt;&lt;pre&gt;&lt;FONT color=#000000&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Collections.Generic;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;namespace&lt;/FONT&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;FONT color="#0000FF"&gt;class&lt;/FONT&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;void&lt;/FONT&gt; Main(&lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// This code calculates the probablity of As Ks winning against&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// another random hand.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; pocketmask = Hand.ParseHand(&lt;FONT color="#c00000"&gt;"As Ks"&lt;/FONT&gt;); &lt;FONT color="#008000"&gt;// Hole hand&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; board = Hand.ParseHand(&lt;FONT color="#c00000"&gt;""&lt;/FONT&gt;);           &lt;FONT color="#008000"&gt;// No board cards yet&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; wins = 0, ties = 0, loses = 0, count = 0;&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Iterate through all possible opponent hole cards&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; oppmask &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt; Hand.Hands(0UL, board  pocketmask, 2))&lt;br /&gt;            {&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Iterate through all board cards&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardmask &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt; Hand.Hands(board, pocketmask  oppmask, 5))&lt;br /&gt;                {&lt;br /&gt;                    &lt;FONT color="#008000"&gt;// Evaluate the player and opponent hands and tally the results&lt;br /&gt;&lt;/FONT&gt;                    &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; pocketHandVal = Hand.Evaluate(pocketmask   boardmask, 7);&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; oppHandVal = Hand.Evaluate(oppmask  boardmask, 7);&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (pocketHandVal &amp;gt; oppHandVal)&lt;br /&gt;                    {&lt;br /&gt;                        wins++;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (pocketHandVal == oppHandVal)&lt;br /&gt;                    {&lt;br /&gt;                        ties++;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt;&lt;br /&gt;                    {&lt;br /&gt;                        loses++;&lt;br /&gt;                    }&lt;br /&gt;                    count++;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Prints: Win 67.0446323092352%&lt;br /&gt;&lt;/FONT&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"Win {0}%"&lt;/FONT&gt;,&lt;br /&gt;                (((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)wins) + ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)ties) / 2.0) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)count) * 100.0);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/FONT&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Getting "Good Enough" Results Quickly&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;&lt;/span&gt;&lt;br /&gt;I'm not a perfectionist and appearently neither are many of the successful professional Texas Holdem Players.&lt;br /&gt;&lt;br /&gt;In Phil Gordon's Little Green Book (a very good book I might add) he describes a very simple heuristic that can be calculate in your head that give the approximate odds of hitting your "outs". He calls this "the rule of 4 and 2". The way this heuristic works is that you count your outs. If you've just seen the flop (and not the turn card) then multiply the outs by 4 and you will have the approximate percentage of hitting your outs. If you've seen the turn (but not the river) you multiply the outs by 2 to get the approximate odds of hitting your outs.&lt;br /&gt;&lt;br /&gt;These types of simple estimates are used by many of the professional players to help evaluate their situation. If an estimate is good enough for them, then it's probably good enough for the rest of us -- if used correctly. Monte Carlo Analysis is just a method for a computer to quickly estimate the odds in a specific situation.&lt;br /&gt;&lt;br /&gt;Consider our previous example. It would take 299 seconds to iterate through all the possible situations and give us an exact anwers.&lt;br /&gt;&lt;br /&gt;The following table was calculated using Monte Carlo Analysis. The number on the left is the number of trials, the second number is the estimated win odds (the exact odds were 67.0446323092352%). The third column is the difference between the exact answer and the estimate answer. The fourth column is the time taken in seconds.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2380/3034/1600/Table1.1.png"&gt;&lt;img style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://photos1.blogger.com/blogger/2380/3034/400/Table1.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Notice at 0.0013 seconds (1.3 milleseconds) we have 3 good digits. At 0.007 (7 milliseconds) we have about 4 good digits. At 0.0357 (36 milliseconds) we have 5 good digits. It's easy to see that we can get very good estimates in well less than a second.&lt;br /&gt;&lt;br /&gt;    The following code was used to generate the previous table.&amp;nbsp;&lt;br /&gt;    &lt;br /&gt;    &lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 11px; "&gt;&lt;pre&gt;&lt;FONT color=#000000&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Collections.Generic;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Runtime.InteropServices;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;namespace&lt;/FONT&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;FONT color="#0000FF"&gt;class&lt;/FONT&gt; Program&lt;br /&gt;    {&lt;br /&gt;        [DllImport(&lt;FONT color="#c00000"&gt;"Kernel32.dll"&lt;/FONT&gt;)]&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;private&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;extern&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;bool&lt;/FONT&gt; QueryPerformanceCounter(&lt;FONT color="#0000FF"&gt;out&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; lpPerformanceCount);&lt;br /&gt;        [DllImport(&lt;FONT color="#c00000"&gt;"Kernel32.dll"&lt;/FONT&gt;)]&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;private&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;extern&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;bool&lt;/FONT&gt; QueryPerformanceFrequency(&lt;FONT color="#0000FF"&gt;out&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; lpFrequency);&lt;br /&gt;&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;void&lt;/FONT&gt; Main(&lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// This code calculates the probablity of As Ks winning against&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// another random hand.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; pocketmask = Hand.ParseHand(&lt;FONT color="#c00000"&gt;"As Ks"&lt;/FONT&gt;); &lt;FONT color="#008000"&gt;// Hole hand&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; board = Hand.ParseHand(&lt;FONT color="#c00000"&gt;""&lt;/FONT&gt;);           &lt;FONT color="#008000"&gt;// No board cards yet&lt;br /&gt;&lt;/FONT&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Trial numbers&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt;[] trialsTable = {&lt;br /&gt;                10, 50, 100, 500, 1000, 5000, 10000, 15000, 20000,&lt;br /&gt;                25000, 30000, 40000, 50000, 100000, 150000, 200000,&lt;br /&gt;                500000, 1000000, 2000000, 5000000, 10000000, 20000000&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// timer values&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; start, freq, curtime;&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Get time frequency&lt;br /&gt;&lt;/FONT&gt;            QueryPerformanceFrequency(&lt;FONT color="#0000FF"&gt;out&lt;/FONT&gt; freq);&lt;br /&gt;&lt;br /&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"Trials,Wins,Difference,Duration"&lt;/FONT&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; trials &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt; trialsTable)&lt;br /&gt;            {&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;long&lt;/FONT&gt; wins = 0, ties = 0, loses = 0, count = 0;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Get start time&lt;br /&gt;&lt;/FONT&gt;                QueryPerformanceCounter(&lt;FONT color="#0000FF"&gt;out&lt;/FONT&gt; start);&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Iterate through a series board cards&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardmask &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt;&lt;br /&gt;                    Hand.RandomHands(board, pocketmask, 5, trials))&lt;br /&gt;                {&lt;br /&gt;                    &lt;FONT color="#008000"&gt;// Get a random opponent hand&lt;br /&gt;&lt;/FONT&gt;                    &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; oppmask = Hand.RandomHand(boardmask | pocketmask, 2);&lt;br /&gt;&lt;br /&gt;                    &lt;FONT color="#008000"&gt;// Evaluate the player and opponent hands&lt;br /&gt;&lt;/FONT&gt;                    &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; pocketHandVal = Hand.Evaluate(pocketmask | boardmask, 7);&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; oppHandVal = Hand.Evaluate(oppmask | boardmask, 7);&lt;br /&gt;&lt;br /&gt;                    &lt;FONT color="#008000"&gt;// Calculate Statistics&lt;br /&gt;&lt;/FONT&gt;                    &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (pocketHandVal &amp;gt; oppHandVal)&lt;br /&gt;                    {&lt;br /&gt;                        wins++;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (pocketHandVal == oppHandVal)&lt;br /&gt;                    {&lt;br /&gt;                        ties++;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt;&lt;br /&gt;                    {&lt;br /&gt;                        loses++;&lt;br /&gt;                    }&lt;br /&gt;                    count++;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Get Current Time&lt;br /&gt;&lt;/FONT&gt;                QueryPerformanceCounter(&lt;FONT color="#0000FF"&gt;out&lt;/FONT&gt; curtime);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; duration = ((curtime - start) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)freq));&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Correct answer is 67.0446323092352%&lt;br /&gt;&lt;/FONT&gt;                Console.WriteLine(&lt;FONT color="#c00000"&gt;"{0},{1},{2}%,{3}"&lt;/FONT&gt;,&lt;br /&gt;                    trials,&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;.Format(&lt;FONT color="#c00000"&gt;"{0:0.00}%"&lt;/FONT&gt;, &lt;br /&gt;                        (((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)wins) + ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)ties) / 2.0) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)count) *100.0),&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;.Format(&lt;FONT color="#c00000"&gt;"{0:0.0000}"&lt;/FONT&gt;, &lt;br /&gt;                        67.0446323092352 - ((((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)wins) + &lt;br /&gt;                        ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)ties) / 2.0) / ((&lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt;)count) * 100.0)),&lt;br /&gt;                    &lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;.Format(&lt;FONT color="#c00000"&gt;"{0:0.0000}"&lt;/FONT&gt;, duration));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/FONT&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I use the functions &lt;span style="font-size: 11pt; font-family: Courier New"&gt;QueryPerformanceFrequency&lt;/span&gt;&lt;br /&gt;    and &lt;span style="font-size: 11pt; font-family: Courier New Baltic"&gt;QueryPerformanceCount&lt;/span&gt;&lt;br /&gt;    to get highly accurate time duration information for the table.  The rest of the code should look very much like the program we used to exhaustively calculate the odds. However, you will notice two new methods. They are &lt;span style="font-size: 11pt;&lt;br /&gt;        font-family: Courier New"&gt;Hand.RandomHand()&lt;/span&gt; and &lt;span style="font-size: 11pt;&lt;br /&gt;            font-family: Courier New"&gt;Hand.RandomHands()&lt;/span&gt;.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="font-size:180%;color:#ff6600;"&gt;Monte Carlo Analysis Helper Methods&lt;/span&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;        The following method is intentionally similar to the &lt;span style="font-size: 11pt;&lt;br /&gt;            font-family: Courier"&gt;IEnumerable&amp;lt;ulong&amp;gt; &lt;/span&gt;&lt;font face="Times New Roman CYR"&gt;&lt;br /&gt;                &lt;font face="Courier New"&gt;&lt;span style="font-size: 11pt"&gt;Hands(ulong shared, ulong dead,&lt;br /&gt;                    int ncards) &lt;span style="font-size: 12pt; font-family: Times New Roman"&gt;method&lt;/span&gt;&lt;/span&gt;.&lt;/font&gt;&lt;br /&gt;            &lt;/font&gt;One additional argument is added which is the number of random hands that are to be iterated through by this enumerator.&lt;/p&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;&lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 11px; "&gt;&lt;pre&gt;&lt;FONT color=#000000&gt;&lt;FONT color="#0000FF"&gt;public&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; IEnumerable&amp;lt;&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt;&amp;gt; Hand.RandomHands(&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; shared, &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; dead, &lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; ncards, &lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; trials)&lt;/FONT&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;    This IEnumerable method, allows the foreach command to iterate through random hands. The hands returned must meet the criterion specified. The number of hands specified in the last argument are returned.&lt;/p&gt;&lt;br /&gt;&lt;!-- Start of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 12px; "&gt;&lt;pre&gt;&lt;FONT color=#000000&gt;&lt;FONT color="#0000FF"&gt;public&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; IEnumerable&amp;lt;&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt;&amp;gt; Hand.RandomHands(&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; shared, &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; dead, &lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; ncards, &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; duration) &lt;/FONT&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;    This method is similar to the previous method. However, rather than specifying the number of trials, a time duration is specified. This allows a time budget to be specified for getting an answer. I have a mild preference to using this version of these methods.&lt;/p&gt;&lt;br /&gt;&lt;!-- Start of snippet generated by C#2HTML --&gt;&lt;br /&gt;&lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 11px; "&gt;&lt;pre&gt;&lt;br /&gt;&lt;FONT color=#000000&gt;&lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;public&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; Hand.RandomHand(&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; shared, &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; dead, &lt;FONT color="#0000FF"&gt;int&lt;/FONT&gt; ncards) &lt;/FONT&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;This method allows a random hand to be returned. It must meet the specified input criterion.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Hopefully this is enough to get you started with Monte Carlo Analysis.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114876570370449156?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114876570370449156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114876570370449156' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114876570370449156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114876570370449156'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/05/using-monte-carlo-analysis-in-poker.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28618724.post-114867139633788863</id><published>2006-05-26T12:19:00.000-07:00</published><updated>2007-01-10T22:00:19.500-08:00</updated><title type='text'></title><content type='html'>&lt;span style="color:#ff9900;"&gt;&lt;span style="font-size:180%;"&gt;Enumerating Poker Hands&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Being able to easily and quickly enumerate through available poker hands is essential in doing any poker analysis. C# makes enumeration easy by providing the ablity to build methods that are used with the &lt;span style="font-family:courier new;"&gt;foreach&lt;/span&gt; language construct.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Iterating through hands simply requires toggling all of the possible 7 bit combinations for 7 card hands or 5 bit combinations for 5 card hands. To assist in this task, C# iterators can be used.&lt;br /&gt;&lt;br /&gt;The following method can be used to iterate through all possible hands containing the number of cards specifed.&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="color:#000099;"&gt;&lt;br /&gt;public static &lt;span style="color:#3366ff;"&gt;IEnumerable&lt;&lt;span style="color:#000099;"&gt;ulong&lt;/span&gt;&gt;&lt;/span&gt;&lt;ulong&gt; &lt;span style="color:#000000;"&gt;Hands&lt;/span&gt;(int &lt;span style="color:#000000;"&gt;numberOfCards&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This next method is a little more elaborate. It allows a mask containing &lt;strong&gt;shared&lt;/strong&gt; cards to be passed, along with a mask containing &lt;strong&gt;dead&lt;/strong&gt; cards, and finally the number of cards to be returned. &lt;br /&gt;&lt;br /&gt;Shared cards are cards that must be included in the returned mask, dead cards are cards that must not be included in the return mask&lt;br /&gt;&lt;span style="font-family:Courier New;font-size:85%;color:#000099;"&gt;&lt;br /&gt;public static &lt;span style="color:#3366ff;"&gt;IEnumerable&lt;&lt;span style="color:#000099;"&gt;ulong&lt;/span&gt;&gt;&lt;/span&gt;&lt;ulong&gt; &lt;span style="color:#000000;"&gt;Hands&lt;/span&gt;(ulong &lt;span style="color:#000000;"&gt;shared&lt;/span&gt;, ulong &lt;span style="color:#000000;"&gt;dead&lt;/span&gt;, int &lt;span style="color:#000000;"&gt;numberOfCards&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These methods provide and easy way to count up win/tie/lose stats to figure out what the odds are for a specific player/opponent/board match up. The following example shows how you can calculate such a matchup.&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #FFFDF4; font-family: Courier; font-size: 11px; "&gt;&lt;pre&gt;&lt;br /&gt;&lt;FONT color="#000000"&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Collections.Generic;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; System.Text;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;using&lt;/FONT&gt; HoldemHand;&lt;br /&gt;&lt;br /&gt;&lt;FONT color="#0000FF"&gt;namespace&lt;/FONT&gt; ConsoleApplication1&lt;br /&gt;{&lt;br /&gt;    &lt;FONT color="#0000FF"&gt;class&lt;/FONT&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;FONT color="#0000FF"&gt;static&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;void&lt;/FONT&gt; Main(&lt;FONT color="#0000FF"&gt;string&lt;/FONT&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Keep stats&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;double&lt;/FONT&gt; win = 0.0, lose = 0.0, tie = 0.0;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Parse cards into hand masks&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; pocketcards = Hand.ParseHand(&lt;FONT color="#c00000"&gt;"as ks"&lt;/FONT&gt;);&lt;br /&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; opponentcards = Hand.ParseHand(&lt;FONT color="#c00000"&gt;"5h tc"&lt;/FONT&gt;);&lt;br /&gt;            &lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardcards = Hand.ParseHand(&lt;FONT color="#c00000"&gt;"qs ts 5c"&lt;/FONT&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Loop through all remaining 5 card boards.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// All 5 card boardmask must contain the starting&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// board cards. That's why boardcards is passed in the first argument.&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// Neither player nor opponents cards should be allowed in the boardmask&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// which is why they are ORed together and passed to Hand.Hands()&lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#008000"&gt;// second argument. &lt;br /&gt;&lt;/FONT&gt;            &lt;FONT color="#0000FF"&gt;foreach&lt;/FONT&gt; (&lt;FONT color="#0000FF"&gt;ulong&lt;/FONT&gt; boardmask &lt;FONT color="#0000FF"&gt;in&lt;/FONT&gt; &lt;br /&gt;                Hand.Hands(boardcards, pocketcards | opponentcards, 5))&lt;br /&gt;            {&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Get Hand Values&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; playerhandval = Hand.Evaluate(pocketcards | boardmask);&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;uint&lt;/FONT&gt; opphandval = Hand.Evaluate(opponentcards | boardmask);&lt;br /&gt;&lt;br /&gt;                &lt;FONT color="#008000"&gt;// Compare and update the stats&lt;br /&gt;&lt;/FONT&gt;                &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (playerhandval &amp;gt; opphandval)&lt;br /&gt;                {&lt;br /&gt;                    win += 1.0;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt; &lt;FONT color="#0000FF"&gt;if&lt;/FONT&gt; (playerhandval == opphandval)&lt;br /&gt;                {&lt;br /&gt;                    tie += 1.0;&lt;br /&gt;                }&lt;br /&gt;                &lt;FONT color="#0000FF"&gt;else&lt;/FONT&gt;&lt;br /&gt;                {&lt;br /&gt;                    lose += 1.0;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;FONT color="#008000"&gt;// Print results which is 42.63%&lt;br /&gt;&lt;/FONT&gt;            Console.WriteLine(&lt;FONT color="#c00000"&gt;"Odds of beating opponent {0:0.00}%"&lt;/FONT&gt;, &lt;br /&gt;                (win + tie / 2.0) / (win + tie + lose) * 100.0);&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/FONT&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End of snippet generated by C#2HTML --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28618724-114867139633788863?l=pokerforprogrammers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pokerforprogrammers.blogspot.com/feeds/114867139633788863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28618724&amp;postID=114867139633788863' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114867139633788863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28618724/posts/default/114867139633788863'/><link rel='alternate' type='text/html' href='http://pokerforprogrammers.blogspot.com/2006/05/enumerating-poker-hands-being-able-to.html' title=''/><author><name>Poker Programmer</name><uri>http://www.blogger.com/profile/17857756827074893574</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
