![]() |
|
#71
|
|||
|
|||
|
I know poker stove pre-flop is all tabled out...
I'm not sure what you mean by this, but I'm pretty sure that you don't understand what PokerStove is doing. It doesn't use extensive lookup tables. In fact, it does quite the opposite. If you look at the memory footprint of the program, you'll see that it's right around 6 MB. But once u specify part of the flop, it starts working off tables (or at least not as fast)... I dunno, I get it running at over 200 evals/sec with a flop. So i do think these algorithm's do have a lot of merit for partial flop analysis. I certainly agree with you on that point. PokerStove certainly isn't a complete solution to the evaluation problem. There is lots of improvement available all over the place. - Andrew |
|
#72
|
|||
|
|||
|
[ QUOTE ]
This is true, my program "cheats." I wouldn't call that cheating. But it's an important distinction. If people want to make comparisons, it's useful to agree on what you're comparing. PokerStove can do over 1.5 billion evals/sec by grouping evals together. But that's different from a generic evaluation. - Andrew [/ QUOTE ] Andrew, I'm so disapointed. [img]/images/graemlins/smile.gif[/img] I set up 10 players with "Any Broadway", and the Board to "Ac Kc Qc Jc Tc" What I expected from pokerstove: Text results appended to pokerstove.txt 2,375,880,867,360,000 games 0.005 secs 475,176,173,472,000,000 games/sec Board: Ac Kc Qc Jc Tc Dead: equity (%) win (%) tie (%) Hand 1: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 2: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 3: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 4: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 5: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 6: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 7: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 8: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 9: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} Hand 10: 10.0000 % 00.00% 10.00% { TT+, ATs+, KTs+, QTs+, JTs, ATo+, KTo+, QTo+, JTo} |
|
#73
|
|||
|
|||
|
I'll be honest guys, I'm incredibly dissapointed! I thought I had something near optimum, but I must be missing something obvious! My meak 15 million per second is not much compared to your dozens of millions!
Anyway, incase any of you are interested, this is the best way to sort 7 cards. Please note, this sort algorithm I wrote beats all the classic sorting algorithms (quick sort, merge, insertion, std::Sort). It's basically a precomputed LUT for a pigeonhole sort. // Represent the hand sevenCardHand = ((__int64)1 << c1) | ((__int64)1 << c2) | ((__int64)1 << c3) | ((__int64)1 << c4) | ((__int64)1 << c5) | ((__int64)1 << c6) | ((__int64)1 << c7); // Split 64 bit int into 4 chunks of 16 bits firstChunk = (sevenCardHand & 0xFFFF); secondChunk = (sevenCardHand & 0xFFFF0000) >> 16; thirdChunk = (sevenCardHand & 0xFFFF00000000) >> 32; fourthChunk = (sevenCardHand & 0xFFFF000000000000) >> 48; // Reset pointer to sorted hand array sortedPointer = 0; // Retrieve records numToLoop = intToIndexArr_L1[firstChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[firstChunk][anotherCounter]; numToLoop = intToIndexArr_L1[secondChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[secondChunk][anotherCounter] + 16; numToLoop = intToIndexArr_L1[thirdChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[thirdChunk][anotherCounter] + 32; numToLoop = intToIndexArr_L1[fourthChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[fourthChunk][anotherCounter] + 48; |
|
#74
|
|||
|
|||
|
Where intToIndexArr_L1 holds 8 integers. The first holding the number of indexes to return, and the next 7 the indexes of on bits.
Then the way mine works is by applying an algorithm on the sorted cards into a combination ID to look up in O(1) access time. Algorithm works by summating precomputed choose summations to work out the index. Also please note for the test I gave, I apply the sorting algorithm even though I don't need to, I could just keep a combination counter incrementing on each iteration and use that for an index lookup, this speeds it up hugely. However, in real world cases the hand needs to be sorted, which is why I have left it in. |
|
#75
|
|||
|
|||
|
Just checked out PokerStove as well, incredible. I would love to know how that works, it's baffling for me. 4 cycles per hand!
|
|
#76
|
|||
|
|||
|
Without sorting and just using combination index it gives me around 150 million per second. The sort is slowing it down a lot.
|
|
#77
|
|||
|
|||
|
Yeah, that's a tough one. With only 20 broadway cards, we're five cards short of a feasible scenario.
- Andrew |
|
#78
|
|||
|
|||
|
[ QUOTE ]
I'll be honest guys, I'm incredibly dissapointed! I thought I had something near optimum, but I must be missing something obvious! My meak 15 million per second is not much compared to your dozens of millions! Anyway, incase any of you are interested, this is the best way to sort 7 cards. Please note, this sort algorithm I wrote beats all the classic sorting algorithms (quick sort, merge, insertion, std::Sort). It's basically a precomputed LUT for a pigeonhole sort. // Represent the hand sevenCardHand = ((__int64)1 << c1) | ((__int64)1 << c2) | ((__int64)1 << c3) | ((__int64)1 << c4) | ((__int64)1 << c5) | ((__int64)1 << c6) | ((__int64)1 << c7); // Split 64 bit int into 4 chunks of 16 bits firstChunk = (sevenCardHand & 0xFFFF); secondChunk = (sevenCardHand & 0xFFFF0000) >> 16; thirdChunk = (sevenCardHand & 0xFFFF00000000) >> 32; fourthChunk = (sevenCardHand & 0xFFFF000000000000) >> 48; // Reset pointer to sorted hand array sortedPointer = 0; // Retrieve records numToLoop = intToIndexArr_L1[firstChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[firstChunk][anotherCounter]; numToLoop = intToIndexArr_L1[secondChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[secondChunk][anotherCounter] + 16; numToLoop = intToIndexArr_L1[thirdChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[thirdChunk][anotherCounter] + 32; numToLoop = intToIndexArr_L1[fourthChunk][0]; for(anotherCounter = 1; anotherCounter < numToLoop; anotherCounter++) sortedHand[sortedPointer++] = intToIndexArr_L1[fourthChunk][anotherCounter] + 48; [/ QUOTE ] I'm not fluent in the different flavors of C but here goes. sevenCardHand = ((__int64)1 << c1) | ((__int64)1 << c2) | ((__int64)1 << c3) | ((__int64)1 << c4) | ((__int64)1 << c5) | ((__int64)1 << c6) | ((__int64)1 << c7); int n = 1; int64 bit = 1; for (int x = 0; x < 52; x++, bit <<= 1) { if (sevenCardHand && bit) { switch (n) { case 1 : c1 = x; case 2 : c2 = x; case 3 : c3 = x; case 4 : c4 = x; case 5 : c5 = x; case 6 : c6 = x; case 7 : c7 = x; } n++; } } wouldn't this sort c1..c7 as fast? This could probably also be switch/cased to death and make a large, but fast solution. |
|
#79
|
|||
|
|||
|
[ QUOTE ]
Yeah, that's a tough one. With only 20 broadway cards, we're five cards short of a feasible scenario. - Andrew [/ QUOTE ] What a brain fart.. when I selected any broadway it lit up a group 5x5.. My brain observed that 5x5 = 25 and then subtracted the 5 board cards giving 20 cards left over. I hesitated a moment realizing that Royal holdem only exists for 6 people max for a reason, but I let that line of thought fade. Ok Redo. 7 people with Any Broadway, and a board of Ac Kc Qc Jc Tc. |
|
#80
|
|||
|
|||
|
mykey1961: I've tried looping through each bit individually and dumping it in the array, and it's significantly slower than the solution I proposed. This is a type of pigeon hole sort, and because of the low cards to empty slot ratio looping each bit is too inefficient. The precomputed tables are significantly faster.
|
![]() |
|
|