Basic overview over the dll structure & examples
If you are not following my guide “Compiling the first dll” there might be slight differences in the basic files you use, since i already added some code, which is needed anyway.
The OH-DLL.cpp
#define WHUSER_EXPORTS #include "OH-DLL.h" #include <windows.h> ///////////////////////////////////// //card macros #define RANK(c) ((c>>4)&0x0f) #define SUIT(c) ((c>>0)&0x0f) #define ISCARDBACK(c) (c==0xff) #define ISUNKNOWN(c) (c==0) ///////////////////////////////////// //////////////////////////////////// //consecutive states holdem_state m_holdem_state[256]; unsigned char m_ndx; //////////////////////////////////// //////////////////////////////////// //versus list & prwin phl1k_t m_phl1k; pp13 prw1326; //////////////////////////////////// //////////////////////////////////// //WH symbols pfgws_t m_pget_winholdem_symbol; //////////////////////////////////// double gws(int chair, const char* name, bool& iserr) { return (*m_pget_winholdem_symbol)(chair,name,iserr); } double gws(const char* name) { bool iserr; int mychair = (int)gws(0,"userchair",iserr); return gws(mychair,name,iserr); } bool hlset( int rank0, int rank1, int listnum, bool onoff ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2] = onoff); } bool hlget( int rank0, int rank1, int listnum ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2]); } double process_query(const char* pquery){ if(pquery==NULL) return 0; //example if(strcmp(pquery,"dll$test")==0) return 101; return 0; } double process_state(holdem_state* pstate){ if(pstate!=NULL) m_holdem_state[ (++m_ndx)&0xff ] = *pstate; return 0; } ///////////////////////////////////////////////////// //WINHOLDEM RUNTIME ENTRY POINT ///////////////////////////////////////////////////// WHUSER_API double process_message(const char* pmessage, const void* param) { if(pmessage==NULL){ return 0; } if(param==NULL) return 0; if(strcmp(pmessage,"state")==0) return process_state( (holdem_state*)param ); if(strcmp(pmessage,"phl1k")==0) { m_phl1k = (phl1k_t)param; return 0; } if(strcmp(pmessage,"prw1326")==0) { prw1326 = (pp13)param; return 0; } if(strcmp(pmessage,"query")==0) return process_query((const char*)param); if(strcmp(pmessage,"pfgws")==0) { m_pget_winholdem_symbol = (pfgws_t)param; return 0; } return 0; } ///////////////////////////////// //DLLMAIN ///////////////////////////////// BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }
gws function
double gws(const char* name) { bool iserr; int mychair = (int)gws(0,"userchair",iserr); return gws(mychair,name,iserr); }
This function you see here, is very important, because you can access all symbols, which are available for Openholdem with it. E.g: gws("userchair") returns the value of the userchair symbol.
hlset & hlget
bool hlset( int rank0, int rank1, int listnum, bool onoff ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2] = onoff); } bool hlget( int rank0, int rank1, int listnum ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2]); }
These functions can be used to access and dynamically modify versus lists during play e.g:
hlset( 14, 13, 5, 1);
this sets AKs on list 5 to true. More details can be found here: http://www.maxinmontreal.com/wiki/index.php5?title=Phl1k.!!!
process_query function
double process_query(const char* pquery){ if(pquery==NULL) return 0; //example if(strcmp(pquery,"dll$test")==0) return 101; return 0; }
Inside this scope you can define symbols which you can access with the OH formula editor.
E.g: If you add " = dll$test" in the OH formula editor in the debug tab, you’ll get the value "101". You can experiment with it if you want and try some values from the gws function, but remember to recompile each time you change something in the code.
process_state function
double process_state(holdem_state* pstate){ if(pstate!=NULL) m_holdem_state[ (++m_ndx)&0xff ] = *pstate; return 0; }
The OH-DLL.h Header
#ifndef _whuser_h_ #define _whuser_h_ #ifdef WHUSER_EXPORTS #define WHUSER_API __declspec(dllexport) #else #define WHUSER_API __declspec(dllimport) # endif struct holdem_player{ char m_name[16]; //player name if known double m_balance; //player balance double m_currentbet; //player current bet unsigned char m_cards[2] ; //player cards unsigned char m_name_known : 1 ; //0=no 1=yes unsigned char m_balance_known : 1 ; //0=no 1=yes unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler bytes }; struct holdem_state{ char m_title[64] ; //table title double m_pot[10] ; //total in each pot unsigned char m_cards[5] ; //common cards unsigned char m_is_playing : 1 ; //0=sitting-out, 1=sitting-in unsigned char m_is_posting : 1 ; //0=autopost-off, 1=autopost-on unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler byte unsigned char m_dealer_chair ; //0-9 holdem_player m_player[10] ; //player records }; struct sprw1326_chair{ int level; //indicates weighting level for ’always consider’ int limit; //max index into weight array - used for computational efficiency int ignored; //if non-zero no weighting will be applied to this chair int rankhi[1326]; //higher ranked card number in pocket cards int ranklo[1326]; //lower ranked card number in pocket cards int weight[1326]; //the significance value for this hand double scratch; //for future reference }; struct sprw1326{ int useme; //unless set to 1326 the normal OH prwin will be used int preflop; //unless set to 1326 the normal OH prwin will be used pre-flop int usecallback; //unless set to 1326 the callback function will not be invoked double (*prw_callback)(void); //if enabled will be invoked before the prwin calculation pass double scratch; //for future reference int bblimp; //if non-zero no weighting will be applied if a chair has put nothing in the pot //will be precalculated by OH at startup - convenience values sprw1326_chair vanilla_chair; sprw1326_chair chair[10]; //structures for each chair }; typedef double (*process_message_t)(const char* message, const void* param ); WHUSER_API double process_message( const char* message, const void* param ); typedef double (*pfgws_t)( int c, const char* psym, bool& iserr ); typedef bool hl1k_t[1000][13][13]; // list number, rank0, rank1 // rank0>=rank1 == suited, rank0<rank1 == unsuited typedef hl1k_t* phl1k_t; typedef sprw1326* pp13; #endif
Here you have some definitions of datatypes. The important definitions are the two structs, you can basically compare a "struct"-datatype to an object with some attributes, these attributes are accessed by using the "." operator, look in the examples section below.
The struct holdem_state
struct holdem_state{ char m_title[64] ; //table title double m_pot[10] ; //total in each pot unsigned char m_cards[5] ; //common cards unsigned char m_is_playing : 1 ; //0=sitting-out, 1=sitting-in unsigned char m_is_posting : 1 ; //0=autopost-off, 1=autopost-on unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler byte unsigned char m_dealer_chair ; //0-9 holdem_player m_player[10] ; //player records };
- What you basically have here is the information of a OH state which was scraped.
- You can access information like the tabletitle/potsize/dealerchair etc. Ofcourse that is nothing new, as you have symbols formost of that at the formula level.
- It also holds information about the players which is saved in the "struct" "holdem_player".
The struct holdem_player
struct holdem_player{ char m_name[16] ; //player name if known double m_balance ; //player balance double m_currentbet ; //player current bet unsigned char m_cards[2] ; //player cards unsigned char m_name_known : 1 ; //0=no 1=yes unsigned char m_balance_known : 1 ; //0=no 1=yes unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler bytes };
Pretty obvious that this contains information about the players at the table. You can access balances / currentbets /cards (if yours or at showdown) / names.
prw1326 Datastructures
You can find all information and examples on it in these articles: http://www.maxinmontreal.com/wiki/index.php5?title=Prw1326, http://www.maxinmontreal.com/wiki/index.php5?title=Enhanced_Prwin.!!!
Examples
Acessing information from the "struct" "holdem_state"
double process_query(const char* pquery){ if(pquery==NULL) return 0; //example if(strcmp(pquery,"dll$test")==0) return 101; if(strcmp(pquery,"dll$dealerchair")==0) return m_holdem_state[(m_ndx)&0xff].m_dealer_chair; if(strcmp(pquery,"dll$currentbet3")==0) return m_holdem_state[(m_ndx)&0xff].m_player[3].m_currentbet; return 0; }
You can see in the code example above, how you have to use the point operator on a struct to access the information stored in the struct of the scraped state.
A function returning the flush rank of the player
For convinience we restructure the code, by adding another header file:
-
Click on project -> Add New Item -> select "Header File (.h)" -> name it "OH-general", you can also do it in the solution explorer by clicking on the "Header Files" folder.
///////////////////////////////////// //card macros #define RANK(c) ((c>>4)&0x0f) #define SUIT(c) ((c>>0)&0x0f) #define ISCARDBACK(c) (c==0xff) #define ISUNKNOWN(c) (c==0) ///////////////////////////////////// //////////////////////////////////// //consecutive states holdem_state m_holdem_state[256]; unsigned char m_ndx; //////////////////////////////////// //////////////////////////////////// //versus list & prwin phl1k_t m_phl1k; pp13 prw1326; //////////////////////////////////// //////////////////////////////////// //WH symbols pfgws_t m_pget_winholdem_symbol; //////////////////////////////////// double gws(int chair, const char* name, bool& iserr) { return (*m_pget_winholdem_symbol)(chair,name,iserr); } double gws(const char* name) { bool iserr; int mychair = (int)gws(0,"userchair",iserr); return gws(mychair,name,iserr); } bool hlset( int rank0, int rank1, int listnum, bool onoff ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2] = onoff); } bool hlget( int rank0, int rank1, int listnum ) { return ((*m_phl1k)[listnum][rank0-2][rank1-2]); }
- Cut / paste the code above from the "OH-DLL.cpp" file to the "OH-general.h" header file.
- We will also need another include now, its a standart library of c++, wich contains a datatype called bitset.
- The bitset datatype converts integer values to their binary representation, we will need this because we are going to work with "srankbits".
- You can read more about how rankbit values are obtained in the chapter about OpenHoldem symbols; look at the very bottom of the page.
- You can find documentation on the C++ library here: http://www.cppreference.com/wiki/stl/bitset/start.
After you’re done with cut-pasting add the "bitset" include and also "using namespace std;" this is neccessary line, don’t think much about it, but the include would not work without it. Your OH-DLL.cpp “#includes” section should look like this now:
#define WHUSER_EXPORTS #include "OH-DLL.h" #include <windows.h> #include <bitset> using namespace std; #include "OH-general.h"
Now we can begin with the actual coding, in the next step open "OH-general.h" and add the following code:
int srankhiplayer; int srankbits; int flushrank;
int set_flush_rank(){ bitset<16> srb( srankbits ); srb = (~srb ) >>= srankhiplayer; return (int)srb.count(); }
This function will determine the flush rank via some bitset operations, 1 = nutflush, 2 = 2nd nutflush, etc.
void int_oh_symbols(){ srankbits = (int)gws("srankbits"); srankhiplayer = (int)gws("srankhiplayer"); flushrank = set_flush_rank(); }
This function will update the values each time a new state is scraped.
You also need to modify the "OH-DLL.cpp" to include this new symbol:
double process_query(const char* pquery) { if(pquery==NULL) return 0; //example if(strcmp(pquery,"dll$test")==0) return 101; if(strcmp(pquery,"dll$dealerchair")==0) return m_holdem_state[(m_ndx)&0xff].m_dealer_chair; if(strcmp(pquery,"dll$currentbet3")==0) return m_holdem_state[(m_ndx)&0xff].m_player[3].m_currentbet; if(strcmp(pquery,"dll$flushrank")==0) return flushrank; return 0; }
double process_state(holdem_state* pstate){ if(pstate!=NULL){m_holdem_state[ (++m_ndx)&0xff ] = *pstate;} int_oh_symbols(); return 0; }
If all went well you can access the flush rank with "dll$flushrank" on formula level now.
Files
The files for this tutorial can be found here: http://www.maxinmontreal.com/wiki/index.php5?title=Image:OH-DLL-B.rar.
Document generated by eLyXer 1.2.5 (2013-03-10) on 2014-12-28T23:15:59.109000