| Poker-AI.org https://poker-ai.org/phpbb/ |
|
| Best hand evaluator for C# bot? https://poker-ai.org/phpbb/viewtopic.php?f=24&t=2553 |
Page 2 of 3 |
| Author: | Seikez [ Fri Aug 16, 2013 10:37 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: I use this in my bot with a wrapper. I would be interested in having a look at that wrapper. How can I get it? |
|
| Author: | shadehs [ Sat Aug 17, 2013 6:48 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
I wrote the wrapper... I'll try to isolate the functions and write a wrapper that works for the example, so you will see. |
|
| Author: | shadehs [ Sat Aug 17, 2013 11:17 pm ] | ||
| Post subject: | Re: Best hand evaluator for C# bot? | ||
This is an example of how to use XPokerEquity with C#; you should compile it in Release, or it will be very slow. There is also a function to free the memory, because there was a bug that it wasn't freeing the memory allocated. Also exhaustive method is reported to be bugged at river in certain circumstances, so i use only Monte Carlo simulation.
|
|||
| Author: | Seikez [ Sun Aug 18, 2013 10:06 am ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Thanks for sharing shadehs. I'll have a look at it. I am busy with other things now so it might take me a while. |
|
| Author: | PeppaPig [ Sun Aug 18, 2013 1:19 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Hi, I always used the poker-eval c library - pinvoked from c#. However I'd recommend lots pre-calculation and lookup tables. With a bit of effort you can avoid almost all live hand evaluations this way - making the performance of the evaluator fairly irrelevant. In fact this approach opens the door to doing far more complex evaluations than would be possible to calculate in realtime - e.g. calculating equity against a probability distribution of 1326 hands becomes trivial with a pre-calculated matrix - but would be challenging if calculated explicitly. The only place I think live evaluation is necessary is on the river - where the calculations are trivial anyway. - PeppaPig |
|
| Author: | OneDayItllWork [ Mon Aug 19, 2013 9:39 am ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
The only place I do live evaluation is showdown... perfectly possible to pre-calculate everything for the river too. |
|
| Author: | Seikez [ Fri Aug 23, 2013 9:53 am ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: calculating equity against a probability distribution of 1326 hands becomes trivial with a pre-calculated matrix and Quote: The only place I do live evaluation is showdown... perfectly possible to pre-calculate everything for the river too OK guys, I hear what you are saying! Pre-calculation is obviously the best way to speed up hand evaluation. Could you please tell me how to actually do it with 1 to 9 opponents (all with different hand ranges) and for all betting rounds? |
|
| Author: | Sharkfacepoker [ Sat Aug 24, 2013 4:31 am ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Seikez wrote: I need a reliable, easy to use and fast (in that priority order) hand evaluator for my Holdem C# Bot. Preferably with documentation and usage examples. So for this bot It should handle preflop, flop, turn and river (2, 5, 6 and 7 cards). It should handle 1 - 9 opponents. I also need functions to calculate win probability, EV and other things my bot might need. The alternatives I have found are all several years old, which makes me unsure which is the best choice today. I therefore turn to you guys for some advice, it will be greatly appreciated! Hi I was reading through this thread and can tell you from personally coding hand evaluators in both C# and then porting my code to c++ is that C++ is faster. I have two apps that sell in the iTunes app store one is cloud based Windows Azure Single Core processor with C# api engine based a lot of the same approach that Keith Rule did. The other was converted to c++ and Runs for five HORSE games and uses logic and approach from various libraries and own code, none of which are poker eval, although im sure all the ideas derived from that since its pretty much the grandfather of evaluators. I used similar logic and approach for holdem to Stud and Eight or better. I do not use pinvoke and I do not have lookup tables since I can't have an app in the store that is 150mb Pointers make a huge difference and while you can use unsafe code in c# it still is not as fast as moving to raw c++. If you use Keith Rules Code base you should get pretty fast times. If you want to know how equity can be incorporated into it, Here is what I did and its how you could use Keith Rules Library since the if logic is nearly the same for all evaluators. In Keith's the evaluator code where you see a line like for(int i = 0; i < playerCount; i++) { if(pocketHands[i] == bestpocket) { if(bestCount > 1) { //Equity numerator is a "1" its always 1 divided by the number of people participating in the tie. playerEquity[i] += equitynumerator / bestcount; playerties[i] ++; } else { playerwins[i]++; playerEquity[i]++; } } } I have separate arrays since I want wins, ties and equity. Look at Keith's code and you can add a float or double whichever to get the equity on top of wins or ties. The key is knowing how many people tie on each iteration. Is there a faster way to do this ? I imagine sure probably many but that worked for me. Also to make your c# code slightly faster go into the settings and check "allow unsafe code" Your c# will run faster and you will not be jeopardizing anything. I had originally used some of the code logic from Keith Rules project when I had done the C# version but starting deviating and then by the time I had writing the c++ logic more of it was new new besides assigning values to cards. I suspect most of the commercial poker software be it, HUDs, odds calculators are using some evolution of poker eval, Two Plus Two etc. The lookup tables are the fastest but you can still get terrific speeds without. Now do a search for PokerStove evaluator. The guy recently put all of his source code available for download and most people consider that the best Equity Calculator. https://github.com/andrewprock/pokerstove I haven't looked at this yet but bet a lot of his logic is similar to the older libraries. Feel free to email me [email protected] if you have any other questions I like helping out others when I can since if it wasn't for these open source libraries most of the software would never exist at least not as widely as it does today |
|
| Author: | OneDayItllWork [ Sat Aug 24, 2013 9:57 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: The lookup tables are the fastest but you can still get terrific speeds without. I can't say I've done any benchmarking, but I would say this is not strictly true... By far and away the slowest thing a modern PC does is accessing a disk, and the second slowest thing a modern PC does is accessing RAM. A CPU can perform hundreds of calculations in the same amount of time it takes to read something from uncached memory. If you somehow create a lookup you can cram into the CPU cache, then yes, it'll be faster. Also, if you perform sequential lookups, then I suspect the lookup table will be faster. For random hands, depending on the PC setup, I'd guess doing the calculations might win the race. Especially as CPU speeds have increased a lot more than RAM speeds over the years. Maybe I'll do some experimentation sometime. Quote: OK guys, I hear what you are saying! Pre-calculation is obviously the best way to speed up hand evaluation. Could you please tell me how to actually do it with 1 to 9 opponents (all with different hand ranges) and for all betting rounds? Lookup tables. |
|
| Author: | Sharkfacepoker [ Sun Aug 25, 2013 12:34 am ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Let me rephrase I am not sure if they will be fast enough for a bot but for what im doing without using the Major Lookup tables and I say major because I use some of the smaller ones like for Razz lowbits or the ones similar to poker eval for checking straights or flushes, but the ones as used in the Two Plus Two that make up the 100+mb file I do not use and I get sub 600ms response time with a quad core doing Omaha on my Quad core 9550 desktop which is about 5+ years old. The key for that tool is using Cactus kev's Fast lookup with some modifications. I know Pro Poker tools is smoking fast but I believe they are using LUTs and have a nice server I suppose. Could be C or Java implementation. Does anyone here have an iPad or IPhone or iPod touch, I have some free promo codes and can let you see how fast/slow the app is on a device. Omaha takes about 3-4 seconds without a board for iPad2 a bit less on iPad3 or iPhone 5. All the other odds calculations are generally a second or less. Not bad with no major lookups on little mobile processors. This is without community cards of course. With them both hold'em and Omaha are instantaneous. For Omaha heads up is 1 million + hands but in getting that there are about 120 million iterations since each player has 6 hands from their four cards. On a core I7 with no major lookups I can get it down to about 400ms. Again LUTS are probably instantaneous but for what I need that will suffice not having LUT. Again I'm not sure for Bots what is needed. |
|
| Author: | winnie [ Mon Aug 26, 2013 5:54 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
does anybody know or share a postflop lookuptable? I' using the xpoker equity calculator for doing the ev calculations during runtime -> is very often too slow (especially every hand vs every hand in an range for 2 players) atm I have no clue how to do it myself. thanks |
|
| Author: | shalako [ Mon Aug 26, 2013 6:17 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: does anybody know or share a postflop lookuptable? I' using the xpoker equity calculator for doing the ev calculations during runtime -> is very often too slow (especially every hand vs every hand in an range for 2 players) I am having a similar slowness problem post flop. I currently have to pass each combo to the evaluator and it is around 4-5 seconds for an equity decision which is ok for one table but not for multiple. LUTS will not really work for me as the ranges are all broken up into specific hands postflop. Preflop I guess a LUT would work most of the time but for a 3B or 4B you would still need to range a specific set of hands but I guess you could stove all those for a LUT too. Postflop I do not see a LUT working at all..especially on the turn and river for a calling range. If the villain is leading the whole time you could LUT it I guess. Right now I am trying to use the pokerstove code that was just released a few months ago. Since it has been highly optimized over the years I am hoping I can get more speed. |
|
| Author: | Sharkfacepoker [ Mon Aug 26, 2013 6:43 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Post flop should be instantaneous given the iterations are so small. The of where you do the equity should be no different to doing it preflop. It should be in the place where you check for tie and wins. You add a +1 for each win in the iteration and if it's a tie then 1 / number of players who tied on that given iteration. The sum of those divided by number of outcomes Will give you the equity. |
|
| Author: | shalako [ Mon Aug 26, 2013 7:18 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: Post flop should be instantaneous given the iterations are so small. The of where you do the equity should be no different to doing it preflop. Well I must be doing something wrong then because its not fast at all. The only equity that is instantaneous is hand vs random hand which is pretty much useless (such as Timmys) for HU. I think (not positive) that is called absolute equity. For any kind of range equity it seems to take time as winnie and I are having similar problems. I am using the PPT java based command line tool for range equity which is probably most of my problem. Nasher said it might be compiling on each run which would cause a big slowdown. I am not sure if it does that or not so I am trying to build a native solution using the pokerstove code. I did try using Timmys for each 1326 hand combos to see how it would fair and it did terrible. It took about a minute to complete. Pokerstove blew it away in about 3 seconds. |
|
| Author: | Sharkfacepoker [ Mon Aug 26, 2013 11:04 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Poker stove is probably sub 100ms actually when there is a board. I guessing simply because the evaluators I have coded with or tried out are all subsecond with a board. of three or more. Maybe it's something you are doing that is making it take more than a second with that code base. Are you running in release or debug mode ? I should also clarify what hand or is it hand range that you are doing ? |
|
| Author: | Seikez [ Tue Aug 27, 2013 12:57 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Quote: This is an example of how to use XPokerEquity with C#; Thanks shadehs! I have tried it out and it works great. I can also extend your wrapper to call other functions in XPokerEquity from C#. |
|
| Author: | shadehs [ Fri Aug 30, 2013 9:00 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Seikez wrote: Quote: This is an example of how to use XPokerEquity with C#; Thanks shadehs! I have tried it out and it works great. I can also extend your wrapper to call other functions in XPokerEquity from C#. There is a serious bug that i forgot to remove in the files that i uploaded: in HoldemCalculator.cpp row 48, you have to sobstitute Calculate method with this one: Code: /////////////////////////////////////////////////////////////////////////////// // Calculate equities for the specified matchup using either Monte Carlo // or Exhaustive Enumeration. /////////////////////////////////////////////////////////////////////////////// int HoldemCalculator::Calculate(const char* hands, const char* board, const char* dead, __int64 trialCount, double* outResults) { PreCalculate(hands, board, dead, trialCount, outResults); CalculateMonteCarlo(); return PostCalculate(); } Or you will not be able to calculate the river for some hands. |
|
| Author: | AutoFocus [ Mon Oct 27, 2014 5:26 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Thank you for your wrapper that I'm using it's a really nice job !! I only needed to correct a few things in the ranges generation part, in AgnosticHand.cpp Incrementing both first card and second card value wasn't correct in the case of KTo+ for example. KTo+ means KTo, KJo, KQo. Your code was actually returning KTo, AJo that's why it didn't work with ranges. Why were so many mistakes in such an important function, was it to see if we were enough good to use it ? Here is the rewritten hand range combinations function. Regards, Autofocus Quote: ///////////////////////////////////////////////////////////////////////////////
// Take a given agnostic hand, such as "AA" or "AJs+" or "77-TT", along with // an optional collection of "dead" cards, and boil it down into its constituent // specific Hold'em hands, storing these in the 'specificHands' vector passed // in by the client. // XxXx means a full range // You can use the A9o - AQo notation => (A9o, ATo, AJo, AQo) or 77-TT => (77,88,99,TT) // You can use the QQ+ notation => (QQ,KK,AA) or KTS+ => (KTs,KJs,KQs) // You must always specify if you are considering suited and/or offsuited so don't forget the s or o suffix for each range except pockets // There is no special rule regarding connectors, so QJs+ => (QJs) and 98o+ => (98o) // // Returns the number of specific hands the agnostic hand contains. /////////////////////////////////////////////////////////////////////////////// int AgnosticHand::Instantiate(const char* handText, StdDeck_CardMask deadCards, vector<StdDeck_CardMask>& specificHands) { if (strcmp(handText, "XxXx") == 0) { return InstantiateRandom(deadCards, specificHands); } bool isPlus = (NULL != strchr(handText, '+')); bool isSlice = (NULL != strchr(handText, '-')); int handRanks[3] = { 0, 0, 0 }; if (isSlice) // TT - AA, ATo - AQo { const char* index = strchr(handText, '-'); char handCeil[4]; char handFloor[4]; strncpy(handFloor, handText, index - handText); strcpy(handCeil, index + 1); handRanks[0] = Card::CharToRank(handFloor[0]); handRanks[1] = Card::CharToRank(handFloor[1]); handRanks[2] = Card::CharToRank(handCeil[1]); } else // K2s+ or 32s { handRanks[0] = Card::CharToRank(handText[0]); handRanks[1] = Card::CharToRank(handText[1]); } StdDeck_CardMask hand; int combos = 0; if (IsPair(handText)) { StdDeck_CardMask card1, card2; for (int rank = handRanks[0]; rank <= (isSlice ? handRanks[2] : (isPlus ? Card::Ace : handRanks[1])); rank++) { for(int suit1 = StdDeck_Suit_FIRST; suit1 <= StdDeck_Suit_LAST; suit1++) { for (int suit2 = suit1 + 1; suit2 <= StdDeck_Suit_LAST; suit2++) { card1 = StdDeck_MASK( StdDeck_MAKE_CARD(rank, suit1) ); card2 = StdDeck_MASK( StdDeck_MAKE_CARD(rank, suit2) ); StdDeck_CardMask_OR(hand, card1, card2); if (!StdDeck_CardMask_ANY_SET(deadCards, hand)) { specificHands.push_back(hand); combos++; } } } } } else if (IsSuited(handText)) { StdDeck_CardMask card1, card2, hand; for (int rank1 = handRanks[1]; rank1 <= (isSlice ? handRanks[2] : (isPlus ? handRanks[0]-1 : handRanks[1])); rank1++) { for(int suit = StdDeck_Suit_FIRST; suit <= StdDeck_Suit_LAST; suit++) // 4 colors { card1 = StdDeck_MASK(StdDeck_MAKE_CARD(handRanks[0], suit)); card2 = StdDeck_MASK( StdDeck_MAKE_CARD(rank1, suit) ); StdDeck_CardMask_OR(hand, card1, card2); if (!StdDeck_CardMask_ANY_SET(deadCards, hand)) { specificHands.push_back(hand); combos++; } } } } else if (IsOffSuit(handText)) { StdDeck_CardMask card1, card2, hand; for (int rank1 = handRanks[1]; rank1 <= (isSlice ? handRanks[2] : (isPlus ? handRanks[0]-1 : handRanks[1])); rank1++) { for(int suit1 = StdDeck_Suit_FIRST; suit1 <= StdDeck_Suit_LAST; suit1++) { for (int suit2 = StdDeck_Suit_FIRST; suit2 <= StdDeck_Suit_LAST; suit2++) { if (suit1 == suit2) continue; card1 = StdDeck_MASK(StdDeck_MAKE_CARD(handRanks[0], suit1)); card2 = StdDeck_MASK( StdDeck_MAKE_CARD(rank1, suit2) ); StdDeck_CardMask_OR(hand, card1, card2); if (!StdDeck_CardMask_ANY_SET(deadCards, hand)) { specificHands.push_back(hand); combos++; } } } } } return combos; } |
|
| Author: | shadehs [ Mon Oct 27, 2014 9:05 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Thanks for finding the bug, but I tested your code and it was failing at the first test. Got "Vector subscript is out of range". The code is not mine, is from coding the wheel website (now dead). http://web.archive.org/web/201301221754 ... in-poker-1 |
|
| Author: | AutoFocus [ Mon Oct 27, 2014 9:49 pm ] |
| Post subject: | Re: Best hand evaluator for C# bot? |
Hum I also tested many times and all works fine. I must say that I changed a part, you must now enter TT-AA or ATo-AQo instead of AA-TT,AQo-ATo which is best. It can provoque a bug, if the order isn't this one. Please tell me which hands you entered if your bug wasn't because of it, but it's all working for me |
|
| Page 2 of 3 | All times are UTC |
| Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |
|