Jump to content

# Random 7 card poker hand

## Recommended Posts

I wrote a little function to deal a random 7 card poker hand. It works just fine, it's not slow, and I'm generally happy with it, except for one thing... how the heck can I nest the While loops to clean up the tests against existing cards?

Here's my code:

```Func DealAHand()

dim \$generatedHand[7]
\$DealtCard1 = Random(0, 51, 1)
\$DealtCard2 = Random(0, 51, 1)
\$DealtCard3 = Random(0, 51, 1)
\$DealtCard4 = Random(0, 51, 1)
\$DealtCard5 = Random(0, 51, 1)
\$DealtCard6 = Random(0, 51, 1)
\$DealtCard7 = Random(0, 51, 1)

While \$DealtCard2 = \$DealtCard1
\$DealtCard2 = Random(0, 51, 1)
WEnd
While \$DealtCard3 = \$DealtCard1 Or \$DealtCard3 = \$DealtCard2
\$DealtCard3 = Random(0, 51, 1)
WEnd
While \$DealtCard4 = \$DealtCard1 Or \$DealtCard4 = \$DealtCard2 Or \$DealtCard4 = \$DealtCard3
\$DealtCard4 = Random(0, 51, 1)
WEnd
While \$DealtCard5 = \$DealtCard1 Or \$DealtCard5 = \$DealtCard2 Or \$DealtCard5 = \$DealtCard3 Or \$DealtCard5 = \$DealtCard4
\$DealtCard5 = Random(0, 51, 1)
WEnd
While \$DealtCard6 = \$DealtCard1 Or \$DealtCard6 = \$DealtCard2 Or \$DealtCard6 = \$DealtCard3 Or \$DealtCard6 = \$DealtCard4 Or \$DealtCard6 = \$DealtCard5
\$DealtCard6 = Random(0, 51, 1)
WEnd
While \$DealtCard7 = \$DealtCard1 Or \$DealtCard7 = \$DealtCard2 Or \$DealtCard7 = \$DealtCard3 Or \$DealtCard7 = \$DealtCard4 Or \$DealtCard7 = \$DealtCard5 Or \$DealtCard7 = \$DealtCard6
\$DealtCard7 = Random(0, 51, 1)
WEnd

\$generatedHand[0] = \$DealtCard1
\$generatedHand[1] = \$DealtCard2
\$generatedHand[2] = \$DealtCard3
\$generatedHand[3] = \$DealtCard4
\$generatedHand[4] = \$DealtCard5
\$generatedHand[5] = \$DealtCard6
\$generatedHand[6] = \$DealtCard7

Return \$generatedHand

EndFunc```

I know there's got to be a way to wrap it up more cleanly than this, and I know it's easy, but I've forgotten how to nest loops efficiently.

Thanks for any help!

edit: changed Random range to 0,51, instead of 0, 52. Oops

Edited by jrowe

#### Share this post

##### Share on other sites

It seems to be pretty darn fast, btw. I can generate 1 million random hands in about 50 seconds. Since my evaluator function takes .3 milliseconds per hand, the generator should be the only bottleneck for monte carlo simulation.

Once I understand nesting, things should proceed nicely

#### Share this post

##### Share on other sites

Something like this:

```Func DealAHand()
Local \$GeneratedHand[7]

For \$i = 1 To 7
Assign("DealtCard" & \$i, Random(0, 52, 1), 1)
Next

For \$i = 2 To 7
For \$j = \$i-1 To 1 Step -1
While Eval("DealtCard" & \$i) = Eval("DealtCard" & \$j)
Assign("DealtCard" & \$i, Random(0, 52, 1))
WEnd
Next
Next

\$GeneratedHand[0] = \$DealtCard1
\$GeneratedHand[1] = \$DealtCard2
\$GeneratedHand[2] = \$DealtCard3
\$GeneratedHand[3] = \$DealtCard4
\$GeneratedHand[4] = \$DealtCard5
\$GeneratedHand[5] = \$DealtCard6
\$GeneratedHand[6] = \$DealtCard7

Return \$GeneratedHand
EndFunc```

?

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

My Work...

Spoiler

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating )

* === My topics === *

==================================================

==================================================

AutoIt is simple, subtle, elegant. © AutoIt Team

#### Share this post

##### Share on other sites

Absolutely, much thanks! Although, it takes about twice as long, probably because of the eval. Now that I see the logic, though, it won't be a big leap to the next step. \$DealtCardX is probably redundant, so I'll just post cards directly to \$generatedHand[].

Thanks man!

#### Share this post

##### Share on other sites

Or better:

```#include <Array.au3>

\$aRet = DealAHand(52, 0)

_ArrayDisplay(\$aRet)

Func DealAHand(\$iMax=52, \$iMin=0)
Local \$GeneratedHand[7]

For \$i = 0 To 6
While 1
\$GeneratedHand[\$i] = Random(\$iMin, \$iMax, 1)

For \$j = 0 To 6
If \$j = \$i Then ContinueLoop

If \$GeneratedHand[\$j] = \$GeneratedHand[\$i] Then ContinueLoop 2
Next

ExitLoop
WEnd
Next

Return \$GeneratedHand
EndFunc```
Edited by MrCreatoR

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

My Work...

Spoiler

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating )

* === My topics === *

==================================================

==================================================

AutoIt is simple, subtle, elegant. © AutoIt Team

#### Share this post

##### Share on other sites

Awesome, getting better. Also, the iMin and iMax should be 0 to 51, not 52.

Unless, of course, you have a joker in the deck.

22 seconds to generate 100,000 hands with this func, 8 to deal 100,000 with the original. Any idea how to improve performance? And a big thank you! I appreciate the help.

#### Share this post

##### Share on other sites

I don't really see where you can think of it getting much faster. The while's are basically conditional statements, and a lot of the times you won't be in but a couple if any of them at all. Anything else added or attempted is just a waste of resources IMHO.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

#### Share this post

##### Share on other sites

Yeah, I've spent about 3 hours on it now, and the fastest I can generate hands is by placing the generator function in a For..To..Step/Next loop.

28 seconds for a million hands, not bad.

I'm working on evaluation now, and then I'll post a little poker package in the example scripts section.

#### Share this post

##### Share on other sites

Yeah, I've spent about 3 hours on it now, and the fastest I can generate hands is by placing the generator function in a For..To..Step/Next loop.

28 seconds for a million hands, not bad.

I'm working on evaluation now, and then I'll post a little poker package in the example scripts section.

I have an Array shuffler that I thought may give a run for the money... even after manipulating that ... I proved to myself it had it's own purpose (to shuffle arrays lol). It's faster than the examples above other than yours, but for this task, not quite fast enough (2 x's slower than yours).

Yours over 1 million hands averaged .0007 seconds per cycle.

My array shufller over 1 million hands averaged .0015 seconds per cycle.

On your evaluator, are you going to use a hash?

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

#### Share this post

##### Share on other sites

I'm using the "2 + 2" evaluator, using cactus kev notation, http://www.codingthewheel.com/archives/pok...tor-roundup#2p2

I've already got it in a plugin, and I'm tidying up the source and UDF-afying the implementation.

On just a wonky little test I did just now, I generated, enumerated, and evaluated 1,000,000 hands in 41 seconds (40.606543 seconds, to be exact.)

Granted, that isn't doing a hand vs hand range comparison or any real heavy lifting, but I think I'm a little excited about the potential.

#### Share this post

##### Share on other sites

I'm using the "2 + 2" evaluator, using cactus kev notation, http://www.codingthewheel.com/archives/pok...tor-roundup#2p2

I've already got it in a plugin, and I'm tidying up the source and UDF-afying the implementation.

On just a wonky little test I did just now, I generated, enumerated, and evaluated 1,000,000 hands in 41 seconds (40.606543 seconds, to be exact.)

Granted, that isn't doing a hand vs hand range comparison or any real heavy lifting, but I think I'm a little excited about the potential.

That actually looks like impressive speeds for the tools being used.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

#### Share this post

##### Share on other sites

It should get faster. I'm going to first do monte carlo evaluation vs ranges of hands, and then figure out how to use math to get an absolute evaluation for a given hand across all possible hands of a particular range. I'm guessing that I can plugin-ify the absolute evaluation, and I'll want to do analysis of the Hole cards, Flop + Hole, Flop- Hole, and so forth to the river, to keep a realtime absolute Odds analysis. I can use the Odds to calculate pot odds, pot equity, range equity, and so forth, to build models of opponent strategies and also create optimal strategies for any stage in online poker games.

Yeah, I *could* have had a top-ten hands or bust bot built by now, but what I really want is to learn the math behind hold-em. All I gotta say is "WOW." That's a helluva lot of numbers for a simple-seeming game.

#### Share this post

##### Share on other sites

Well, I'm forsaking neatly readable for speedy and somewhat readable. As for the other poker stuff, well, my code currently looks like this:

```While 1
\$nMsg = GUIGetMsg()
Switch \$nMsg
Case \$GUI_EVENT_CLOSE
Exit
Case \$DealButton
\$begin = TimerInit()
\$myHand = DealAHandOptimum()
\$Analysis = AnalyzeHand(\$myHand[0], \$myHand[1], \$myHand[2], \$myHand[3], \$myHand[4], \$myHand[5], \$myHand[6])
\$HandCategory = BitShift(\$Analysis, 12)
\$HandRankWithinCategory = BitAND(\$Analysis, 0x00000FFF)

;\$k = \$Category[\$HandCategory] - \$HandRankWithinCategory
;;;;;;;;;;;;;;;;;;;;;FUNCIFY THIS ONE. GETS HAND INFORMATION FROM INDEX;;;;;;;;;;;;;;;;;;;;
For \$j = 8 to \$HandCategory-1 step -1
\$k = \$k + \$Category[\$j]
Next
\$position = \$k - \$HandRankWithinCategory + 1
;;;;;;;;;;;;;;;;;;;;;FUNCIFY THIS ONE. GETS HAND INFORMATION FROM INDEX;;;;;;;;;;;;;;;;;;;;

\$dif = TimerDiff(\$begin)
\$HandString = \$cardsList[\$myHand[0]-1] & ", " & \$cardsList[\$myHand[1]-1] & ", " & \$cardsList[\$myHand[2]-1] & ", " & \$cardsList[\$myHand[3]-1] & ", " & \$cardsList[\$myHand[4]-1]& ", " & \$cardsList[\$myHand[5]-1] & ", " & \$cardsList[\$myHand[6]-1]
MsgBox(0,"1", \$HandString & @CRLF &"Type of Hand:"&\$HandRanksArray[\$position][0] &@CRLF& "Best 5 Card Hand:"& \$HandRanksArray[\$position][2] &@CRLF& "Generated and evaluated Hand in :" & \$dif & " milliseconds.")
\$k=0
EndSwitch
WEnd```

There's around 30,000 lines of code, one 123 MB database file, some extremely convoluted benchmarking junk, and around 80 different versions of the code I made this thread for, all of it ugly, except for MrCreators.

Also, an abortive experiment in saving the information in an array as a file for quick \$myArrayVariable = FileRead(array.data)

Anyway, fun stuff and thanks for all the help!

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now

×

• Wiki

• Back

• Git