ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 6th, 2014 at 2:11:40 PM permalink
I'm trying to make a pay-table analyzer for Jacks or Better video poker. I'm looking up the odds on the Wizard's page here: https://wizardofodds.com/games/video-poker/tables/jacks-or-better/ but I'm getting slightly different results.

Could the difference be due to precision errors?

Examples:

9-6 video poker:
His: 0.99543904
Mine: 0.995359875519285

976-9-6:
His: 1.000000
Mine: 0.999922148379832

"6/5" Jacks or Better
His: 0.949961
Mine: 0.949882112106347

If this is a precision error, which is more accurate? I'm guessing his, since 976-9-6 is exactly one in his method. Any suggestions on how to remedy the issue?

Thanks,

Chris Ellis
tringlomane
tringlomane
  • Threads: 8
  • Posts: 6284
Joined: Aug 25, 2012
March 6th, 2014 at 2:49:37 PM permalink
My guess is you have a tiny evaluation error somewhere, which may be difficult to find. :( 976/9/6 JoB should be exactly 100%.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 6th, 2014 at 2:56:50 PM permalink
Quote: tringlomane

My guess is you have a tiny evaluation error somewhere, which may be difficult to find. :( 976/9/6 JoB should be exactly 100%.



That's exactly what I was worried about. With such a tiny issue it's going to be really difficult to find. Thanks for your time, though.
tringlomane
tringlomane
  • Threads: 8
  • Posts: 6284
Joined: Aug 25, 2012
March 6th, 2014 at 3:00:53 PM permalink
Quote: ChrisE

That's exactly what I was worried about. With such a tiny issue it's going to be really difficult to find. Thanks for your time, though.



No problem. With such a small error, here could be one educated guess. Does A2345 suited evaluate to a straight flush?
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 6th, 2014 at 3:12:42 PM permalink
No, but good guess. The right number of each type of hand is coming out on the deal. Something is happening after the deal when evaluating the arrays. I'm using info found here: https://wizardofodds.com/games/video-poker/methodology/ and here: http://www.vpgenius.com/articles/analyzing-video-poker-hands.aspx to do the evaluations. My code is a total mess, (you can see what I'm talking about in the mass of small arrays instead of one jagged array at line 196) but you can see it if you're interested. I'm taking the "Make it work, then make it better" approach.

http://pastebin.com/RXW0jAn4
tringlomane
tringlomane
  • Threads: 8
  • Posts: 6284
Joined: Aug 25, 2012
March 6th, 2014 at 3:15:23 PM permalink
In the car on the way to Chicago (g/f driving of course); I'll try to take a peek at it later though.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 6th, 2014 at 3:19:01 PM permalink
Thanks, I really appreciate it... and again apologize for the sloppy code!

I got a little chuckle imaging your browsing some forums while driving. Don't make yourself car sick!
MathExtremist
MathExtremist
  • Threads: 88
  • Posts: 6526
Joined: Aug 31, 2010
March 6th, 2014 at 4:10:19 PM permalink
You're getting close so it's going to be something subtle. Have you compared EVs for all 32 draws of a given hand with known results?
Pick a representative hand of each rank and print out your evaluations for all 32 draws. Then compare against
http://www.vpgenius.com/video-poker/custom-video-poker-game.aspx
All 32 evaluations should match perfectly, not just the maximum one. I'd use the VPGenius version rather than the Wizard's (no offense, Mike) because it gives exact hand frequencies for all draw possibilities rather than only EVs. Your error is in there somewhere, and I'd bet that you'll find it by looking at those 9 hands.
"In my own case, when it seemed to me after a long illness that death was close at hand, I found no little solace in playing constantly at dice." -- Girolamo Cardano, 1563
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
March 7th, 2014 at 11:04:41 AM permalink


for (int k = 0; k < 5; k++)
for (int l = k + 1; l < 5; l++)
for (int m = l + 1; m < 5; m++)
for (int n = m + 1; n < 5; n++)
fourHold5[HandIndex4(conHand[k], conHand
, conHand[m], conHand[n])]
++;


I doubt this is the problem, but if I were doing this, I think I would do:

for(int k = 0; k < 1; k++)
for(int l = k + 1; l < 2; l++)
for(int m = l + 1; m < 3; m++)
for(int n = m + 1; n < 4; n++)
...
I heart Crystal Math.
MathExtremist
MathExtremist
  • Threads: 88
  • Posts: 6526
Joined: Aug 31, 2010
March 7th, 2014 at 11:12:05 AM permalink
I don't think that's what you meant. That only does one iteration. The original code only does 5, though, so I think there are more efficient ways of doing whatever it is he wants to do anyway.
"In my own case, when it seemed to me after a long illness that death was close at hand, I found no little solace in playing constantly at dice." -- Girolamo Cardano, 1563
Wizard
Administrator
Wizard
  • Threads: 1520
  • Posts: 27126
Joined: Oct 14, 2009
March 7th, 2014 at 2:09:58 PM permalink
I suspect a rounding error somewhere. That is why I indicate the number of combinations of every hand, to get a form of the exact answer. If your return is a floating point number defined as the sum over all hands of the (probability of the hand)*(EV of hand) then you may be losing some precision.
"For with much wisdom comes much sorrow." -- Ecclesiastes 1:18 (NIV)
MathExtremist
MathExtremist
  • Threads: 88
  • Posts: 6526
Joined: Aug 31, 2010
March 7th, 2014 at 3:06:36 PM permalink
Good catch - he's storing all the internal counts as doubles instead of longs. He should use integers throughout until dividing for the EV at the very end.
"In my own case, when it seemed to me after a long illness that death was close at hand, I found no little solace in playing constantly at dice." -- Girolamo Cardano, 1563
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 7th, 2014 at 7:03:05 PM permalink
I think 2, 3, 4, 5 works... but the code in the loop doesn't get executed anyway because at 5 the second loop hits > 5.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
March 7th, 2014 at 7:23:40 PM permalink
I think there is a problem with tempResult[10].

I think the 29 should be a 30.
I heart Crystal Math.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 7th, 2014 at 8:45:26 PM permalink
I seriously can't believe you weeded through that code and found that for me! I checked that section at least five times... probably closer to ten... and completely looked over it. I'll be looking over it even more now.

Sadly, the results are even further off, with 976 giving a result of 0.940741487243407. But every error needs to be caught before it comes up right... and if one is wrong in there I probably missed more too.
socks
socks
  • Threads: 15
  • Posts: 364
Joined: Jul 13, 2011
March 7th, 2014 at 9:47:17 PM permalink
Quote: ChrisE

Sadly, the results are even further off


I hate it when that happens. I went back and forth with my BJ analyzer. I got very close, but I'm still not quite there. At least, I think I'm close.
JB
Administrator
JB
  • Threads: 334
  • Posts: 2089
Joined: Oct 14, 2009
March 8th, 2014 at 12:12:46 AM permalink
Quote: CrystalMath

for (int k = 0; k < 5; k++)
for (int l = k + 1; l < 5; l++)
for (int m = l + 1; m < 5; m++)
for (int n = m + 1; n < 5; n++)
fourHold5[HandIndex4(conHand[k], conHand
, conHand[m], conHand[n])]
++;

I doubt this is the problem, but if I were doing this, I think I would do:
for(int k = 0; k < 1; k++)
for(int l = k + 1; l < 2; l++)
for(int m = l + 1; m < 3; m++)
for(int n = m + 1; n < 4; n++)
...



The more elegant approach (in my opinion) is to reverse the order and do this:
for (int c5 = 4; c5 < 52; c5++) {
for (int c4 = 3; c4 < c5; c4++) {
for (int c3 = 2; c3 < c4; c3++) {
for (int c2 = 1; c2 < c3; c2++) {
for (int c1 = 0; c1 < c2; c1++) {

...

} } } } }

This is the approach used in the Wizard's video poker calculator.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
March 8th, 2014 at 6:50:15 AM permalink
Can you explain what convert_hand is supposed to do? To me, it looks like the results would always be 0.
I heart Crystal Math.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 8th, 2014 at 9:30:01 AM permalink
Quote: JB

Quote: CrystalMath

for (int k = 0; k < 5; k++)
for (int l = k + 1; l < 5; l++)
for (int m = l + 1; m < 5; m++)
for (int n = m + 1; n < 5; n++)
fourHold5[HandIndex4(conHand[k], conHand
, conHand[m], conHand[n])]
++;

I doubt this is the problem, but if I were doing this, I think I would do:
for(int k = 0; k < 1; k++)
for(int l = k + 1; l < 2; l++)
for(int m = l + 1; m < 3; m++)
for(int n = m + 1; n < 4; n++)
...



The more elegant approach (in my opinion) is to reverse the order and do this:
for (int c5 = 4; c5 < 52; c5++) {
for (int c4 = 3; c4 < c5; c4++) {
for (int c3 = 2; c3 < c4; c3++) {
for (int c2 = 1; c2 < c3; c2++) {
for (int c1 = 0; c1 < c2; c1++) {

...

} } } } }

This is the approach used in the Wizard's video poker calculator.



52 wouldn't be applicable in this section of code. This is part of getting all 32 ways to play a starting hand, specifically how to get 4 out of 5 cards.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 8th, 2014 at 9:32:00 AM permalink
Quote: CrystalMath

Can you explain what convert_hand is supposed to do? To me, it looks like the results would always be 0.



I'm using the CactusKev method of hand ranking, and that's converting from that card-format to numbers from 0-51. I confirmed through a debug statement that all 52 cards convert properly.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
March 8th, 2014 at 9:38:58 AM permalink
There are some incorrect numbers in your combin_array.

Specifically, combin_array[0][1...5] and combin_array[1][2...5] should be 0, but they evaluate to 1.

This doesn't affect your hand indexing routine, but I use a different routine that is affected.
I heart Crystal Math.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 11th, 2014 at 9:55:05 PM permalink
I tried outputting the results for every type of hand and I'm way off right now, even in my total.

This is what I came out with for 976-9-6" Jacks or Better.

TOTAL: 19,958,334,252,030

Royal Flush: 438,645,936
Straight Flush: 1,772,710,452
Four of a Kind: 48,319,093,980
Full House: 153,251,132,940
Flush: 105,729,540,072
Straight: 148,596,266,250
Three of a Kind: 1,545,959,958,318
Two Pair: 2,711,125,745,874
High Pair: 4,359,131,748,360
Low Pair: 5,697,076,473,936
No Pair: 5,186,932,935,912


With how convoluted this code has become I'll probably have to start over from scratch and try again.
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 13th, 2014 at 5:09:58 PM permalink
For now I've decided to leave out this feature, and hopefully add it in later. I can brute force my way into the EVs and best way to play for a given hand in just 188 ms, so I'm going to go with that for now.

Thanks for all the help, it was greatly appreciated. I'll be using the advice here when I go back and try to tackle the problem again.
MathExtremist
MathExtremist
  • Threads: 88
  • Posts: 6526
Joined: Aug 31, 2010
March 13th, 2014 at 7:18:11 PM permalink
7 hours of runtime is a lot, though. It would take you less time to improve your code and analyze ten paytables than it would to just run ten paytables with your current code.
"In my own case, when it seemed to me after a long illness that death was close at hand, I found no little solace in playing constantly at dice." -- Girolamo Cardano, 1563
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 13th, 2014 at 7:21:08 PM permalink
Haha, that's true, but not what I meant! I mean I'm going to leave out the feature of letting you find the expected return for a paytable as a whole... and instead just have a single hand analyzer and "best play" trainer.
teliot
teliot
  • Threads: 43
  • Posts: 2871
Joined: Oct 19, 2009
March 13th, 2014 at 7:23:46 PM permalink
Quote: ChrisE

Haha, that's true, but not what I meant! I mean I'm going to leave out the feature of letting you find the expected return for a paytable as a whole... and instead just have a single hand analyzer and "best play" trainer.

I can run the whole cycle for a pay table in about 2 seconds. You are doing something inefficient. Mike has written at length about how to write efficient VP analyzer code, you should read that.
Climate Casino: https://climatecasino.net/climate-casino/
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 13th, 2014 at 7:31:25 PM permalink
Quote: teliot

I can run the whole cycle for a pay table in about 2 seconds. You are doing something inefficient. Mike has written at length about how to write efficient VP analyzer code, you should read that.



Yes, I've read it, and the VPGenius article he mentions and there's just some things that I'm missing. I was trying to get it working, then optimize it... but since it's not working I'm going to move on and come back to it later.
teliot
teliot
  • Threads: 43
  • Posts: 2871
Joined: Oct 19, 2009
March 13th, 2014 at 7:38:13 PM permalink
Quote: ChrisE

Yes, I've read it, and the VPGenius article he mentions and there's just some things that I'm missing. I was trying to get it working, then optimize it... but since it's not working I'm going to move on and come back to it later.

You don't need to optimize anything. It runs fast. Even poorly written code will execute a full cycle in under 5 seconds. I do not use nested for loops. I use one for loop that runs from 1 to 134459.
Climate Casino: https://climatecasino.net/climate-casino/
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 13th, 2014 at 7:45:38 PM permalink
Quote: teliot

You don't need to optimize anything. It runs fast. Even poorly written code will execute a full cycle in under 5 seconds. I do not use nested for loops. I use one for loop that runs from 1 to 134459.



I'm fairly certain my problem is somewhere in populating the arrays before you even get to the 134459 hands portion... but I really don't know.
teliot
teliot
  • Threads: 43
  • Posts: 2871
Joined: Oct 19, 2009
March 13th, 2014 at 8:14:10 PM permalink
Quote: ChrisE

I'm fairly certain my problem is somewhere in populating the arrays before you even get to the 134459 hands portion... but I really don't know.

I have an array that is 134459x10 that I store as a separate binary file; I read it in one row at a time and process that.
Climate Casino: https://climatecasino.net/climate-casino/
RicardoEsteban
RicardoEsteban
  • Threads: 0
  • Posts: 16
Joined: Feb 7, 2014
March 14th, 2014 at 1:29:43 AM permalink
[ ] skilled programmer giving programming advice ITT

[ x ] failed AP giving programming advice ITT
Mission146
Mission146
  • Threads: 142
  • Posts: 16832
Joined: May 15, 2012
March 14th, 2014 at 6:33:30 AM permalink
Quote: RicardoEsteban

[ ] skilled programmer giving programming advice ITT

[ x ] failed AP giving programming advice ITT



It's clear that you have no purpose here other than to follow Teliot around and attempt to insult him. Were I so obsessed with a person, I'd probably send flowers, or something.

NUKED-Trolling, Personal Insult
https://wizardofvegas.com/forum/off-topic/gripes/11182-pet-peeves/120/#post815219
AxelWolf
AxelWolf
  • Threads: 170
  • Posts: 22701
Joined: Oct 10, 2012
March 15th, 2014 at 3:17:54 AM permalink
Quote: Mission146

Quote: RicardoEsteban

[ ] skilled programmer giving programming advice ITT

[ x ] failed AP giving programming advice ITT



It's clear that you have no purpose here other than to follow Teliot around and attempt to insult him. Were I so obsessed with a person, I'd probably send flowers, or something.

NUKED-Trolling, Personal Insult

:(
♪♪Now you swear and kick and beg us That you're not a gamblin' man Then you find you're back in Vegas With a handle in your hand♪♪ Your black cards can make you money So you hide them when you're able In the land of casinos and money You must put them on the table♪♪ You go back Jack do it again roulette wheels turinin' 'round and 'round♪♪ You go back Jack do it again♪♪
socks
socks
  • Threads: 15
  • Posts: 364
Joined: Jul 13, 2011
March 16th, 2014 at 8:46:03 PM permalink
I've never really thought about video poker math, but this thread piqued my interest. I've been reading over the Wizard's article as well as the other 2 he linked to. It's not super obvious to me though, how easy this technique is to generalize or apply more broadly. What do you need to make it applicable?

Correct me if I'm wrong, but it looks like the technique described, using the results tables for partial hand results, and then going back and forth, adding and subtracting totals, can be used to calculate the ending totals any time you have a single deck with cards removed from it?
ChrisE
ChrisE
  • Threads: 2
  • Posts: 32
Joined: Apr 13, 2013
March 24th, 2014 at 5:05:27 PM permalink
For anyone interested here's what I have so far on my game.

https://dl.dropboxusercontent.com/u/22699631/PokerEV/PokerEV.html

It still has a long way to go, but it will show the best play, plus if you push the Best Play button you'll get a list of all the EVs. They seem to check out with vpgenius so I think I've got that going correctly.
socks
socks
  • Threads: 15
  • Posts: 364
Joined: Jul 13, 2011
March 25th, 2014 at 2:42:23 AM permalink
Quote: ChrisE

For anyone interested here's what I have so far on my game.

https://dl.dropboxusercontent.com/u/22699631/PokerEV/PokerEV.html

It still has a long way to go, but it will show the best play, plus if you push the Best Play button you'll get a list of all the EVs. They seem to check out with vpgenius so I think I've got that going correctly.


I tried to look, but even after I stall "unity player", it wouldn't run. It's probably my aging (4yo) Macbook Air that I don't keep up to date.
socks
socks
  • Threads: 15
  • Posts: 364
Joined: Jul 13, 2011
March 26th, 2014 at 7:49:44 AM permalink
I finally got around to looking at it on my other computer. It looks good, especially the Best Play option that shows the values of the top 4 plays.

Did you get all the bugs worked out in your analyzer? I've been struggling trying to do the same thing (in a different language) since I saw this post. It's more of a pain than I thought it would be.
  • Jump to: