diff --git a/DLL-dds_212_l.rtf b/DLL-dds_212_l.rtf new file mode 100644 index 00000000..87d80330 --- /dev/null +++ b/DLL-dds_212_l.rtf @@ -0,0 +1,157 @@ +{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1053{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}{\f1\froman\fprq2\fcharset0 Times New Roman;}} +{\colortbl ;\red0\green0\blue255;\red0\green0\blue0;\red255\green0\blue0;} +{\stylesheet{ Normal;}{\s1 heading 1;}{\s2 heading 2;}{\s3 heading 3;}} +{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\nowidctlpar\lang1053\f0\fs20 Bo Haglund, Bob Richardson\par +Rev L, 2011-10-14\par +Latest DLL issue with this description is available at {\field{\*\fldinst{HYPERLINK "http://www.bahnhof.se/wb758135/"}}{\fldrslt{\ul\cf1 http://www.bahnhof.se/wb758135/}}}\f0\fs20\par +\par +\par +\pard\keepn\nowidctlpar\s2\cf2\ul\b Short description of the DLL functions supported in Double Dummy Problem Solver 2.1.2\par +\pard\nowidctlpar\ulnone\b0\par +\pard\keepn\nowidctlpar\s3\b Callable functions\par +\pard\nowidctlpar\b0\par +extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, \par + int solutions, int mode, struct futureTricks *futp, int threadIndex);\par +\par +extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, \par + int solutions, int mode, struct futureTricks *futp, int threadIndex);\par +\par +extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, \line struct ddTableResults * tablep);\par +\par +extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN\line tableDealPBN, struct ddTableResults * tablep);\par +\par +\par +\pard\keepn\nowidctlpar\s3\b SolveBoard\par +\pard\nowidctlpar\b0\par +SolveBoard is thread-safe, so several threads (max 16) can call SolveBoard in parallel.\par +\par +Before SolveBoard can be called, a structure of type "futureTricks" must be declared. \par +\par +\b SolveBoard\b0 returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line Status codes: \par + 1=No fault, \par + -1=Unknown fault, \par + -2=No of cards = 0, \par + -3=target > Number of tricks left, \par + -4=Duplicated cards, \par + -5=target < -1, \par + -7=target >13, \par + -8=solutions < 1, \par + -9=solutions > 3, \par +-10=No of cards > 52\par +-11=Not used\par +-12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank.\par +-13=Card already played in the current trick is also defined as a remaining card to play.\par +-14=Wrong number of remaining cards for a hand.\par +-15=threadIndex < 0 or > 15.\line \line Structure \rdblquote\b deal\b0\rdblquote defines all data needed to describe the deal to be analyzed.\par +struct deal \{\f1 \par +\f0 int trump; /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3, NT=4 */\f1 \par +\f0 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/\f1 \par + \f0 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in the order played */\par + int currentTrickRank[3]; /* 2-14 for up to 3 cards */\f1\par +\f0 unsigned int remainCards[4][4]; /* 1\super st\nosupersub index hand (0-3), 2\super nd\nosupersub index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2, \'85\'85\'85. bit 14=rank 14, bit 15=0\f1 \f0 for cards remaining after already played cards (cards already played to the current trick are not included in this bitstring). \line The decimal value for a card then range between 4 (=rank 2) and 16384 (Ace=rank 14). */\f1 \par +\f0\};\f1 \f0\par +\par +Parameter \rdblquote\b target\b0\rdblquote is the number of tricks to be won by the side to play, -1 means that the program\f1 \f0 shall find the maximum number. For equivalent cards only the highest is returned. \par +\line Parameter \rdblquote\b solutions\b0\rdblquote defines how many card solutions that SolveBoard must return:\par + target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target whentarget or higher tricks can be won. Otherwise, score \endash 1 is returned if target cannot be reached, or score 0 if no tricks can be won. \line target=-1, solutions=1: Returns only one of the optimum cards and its score.\par + \cf0 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.\cf2\line target 1-13, solutions=2: Return all cards meeting target. Their returned scores are the same as target when target or higher tricks can be won. Otherwise, only one card is returned with score \endash 1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line target \endash 1, solutions=2: Return all optimum cards with their scores.\par + \cf0 target=0, solutions=2: Return all cards legal to play with scores set to 0\cf3 .\cf2\line target irrelevant, solutions=3: Return all cards that can be legally played with their scores in descending order.\par +\par +Parameter \rdblquote\b mode\b0\rdblquote defines the DLL mode of operation.\line mode=0: Do not search to find the score if the hand to play has only one card, including its equivalents, to play. Score is set to \endash 2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don\rquote t \par + mode=1: Always \cf0\lang1033 search to find the score. Even when the hand to play has only one card, with possible equivalents, to play. For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mode=2 is no longer needed in this case, but can still be done for backwards compatibility.\line mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. \par +\pard\nowidctlpar\fi720 1\super st\nosupersub call: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1, i.e. East leads.\par +\pard\nowidctlpar \tab 2\super nd\nosupersub call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads.\par + \tab 3rd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3, i.e. West leads. \par +\pard\nowidctlpar\fi720 4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. \cf2\lang1053\par +\pard\nowidctlpar\par +struct \b futureTricks\b0 \{ /* The DLL provides the score (number of tricks) that can be won by the card to play defined by its suit and rank. Array of all alternative cards. */\f1 \par +\f0 int nodes; /* Number of searched nodes */\par + int cards; /* No of alternative cards */\f1\par +\f0 int suit[13]; /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */\par + int rank[13]; /* 2-14 for 2 through Ace *\b / \par + \b0 int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When there are several \rdblquote equals\rdblquote , the value is the sum of each \rdblquote equal\rdblquote . *\b /\b0\par + int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */\f1 \par +\f0\} ; \par +\par +Parameter \rdblquote\b threadIndex\b0\rdblquote defines the identity of the thread used when calling SolveBoard.\par +Maximum 16 threads can call SolveBoard in parallel, threadIndex must be an integer of the range 0..15.\par +\cf0\lang1033\fs24\par +\pard\keepn\nowidctlpar\s3\cf2\lang1053\b\fs20\par +SolveBoardPBN\par +\par +\b0 In SolveBoardPBN the remaining cards in the deal information are given in PBN text\par +format (e.g. \line W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K) instead of using bits 2-14 in an integer array. Otherwise, SolveboardPBN is identical to SolveBoard.\par +\par +struct dealPBN \{\par + int trump; \par + int first; \par + int currentTrickSuit[3]; \b\par + \b0 int currentTrickRank[3]; \par + char remainCards[80]; /* First character identifies the hand having the cards given first\par + in the string, then the cards of the other hands are given in a\par +\tab\tab\tab clock-wise order, see example above. Null characters fill out\par +\tab\tab\tab the character array at the end. */ \par +\};\par +\b\par +\par +CalcDDtable\par +\pard\nowidctlpar\b0\f1\par +\pard\keepn\nowidctlpar\s1\f0 CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations. \par +\pard\nowidctlpar\cf0\lang1033\fs24\par +\pard\keepn\nowidctlpar\s1\cf2\lang1053\fs20 Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared.\par +\pard\nowidctlpar\b CalcDDtable\b0 returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.\line Status codes: \par + 1=No fault,\par + Other status codes are errors, with codes equal to SolveBoard status codes. \cf0\lang1033\fs24\par +\par +\cf2\lang1053\fs20 Structure \rdblquote\b ddTableDeal\b0\rdblquote defines the dealt cards to be analyzed.\cf0\lang1033\par +struct ddTableDeal \{\par + unsigned int cards[4][4]; /* 1\super st\nosupersub index is hand, 2\super nd\nosupersub index is suit, same coding as for deal.remainCards for SolveBoard. */\par +\};\par +\par +\cf2\lang1053 struct \b ddTableResults\b0 \{ /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */\cf0\lang1033\par + int resTable[5][4];\tab /* 1\super st\nosupersub index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2\super nd\nosupersub index is declarer hand, 0=North, 1=East, 2=South, 3=West */\par +\};\par +\fs24\par +\par +\cf2\lang1053\b\fs20 CalcDDtablePBN\cf0\lang1033\b0\fs24\par +\par +\pard\keepn\nowidctlpar\s3\cf2\lang1053\fs20 In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable.\par +\pard\nowidctlpar\par +struct ddTableDealPBN \{\par + char cards[80];\par +\};\par +\cf0\lang1033\fs24\par +\par +\pard\keepn\nowidctlpar\s1\cf2\lang1053\b\fs20 Revision History\par +\pard\nowidctlpar\b0\par +Rev A, 2006-02-25.\tab\tab First issue.\par +\par +Rev B, 2006-03-20\tab\tab Updated issue.\par +\par +\pard\nowidctlpar\fi-2880\li2880 Rev C, 2006-03-28\tab Updated issue. Addition of the SolveBoard parameter \rdblquote mode\rdblquote .\par +\par +Rev D, 2006-04-05\tab Updated issue. Usage of target=0 to list all cards that are legal to play.\par +\par +Rev E, 2006-05-29\tab Updated issue. New error code \endash 10 for number of cards > 52.\par +\par +Rev F, 2006-08-09\tab Updated issue. New mode parameter value = 2. New error code \endash 11 for calling SolveBoard with mode = 2 and forbidden values of other parameters.\par +\pard\nowidctlpar\par +\pard\nowidctlpar\fi-2880\li2880 Rev F1, 2006-08-14\tab Clarifications on conditions for returning scores for the different combinations of the values for target and solutions.\par +\par +Rev F2, 2006-08-26\tab New error code \endash 12 for wrongly set values of deal.currentTrickSuit and\line deal.currentTrickRank.\par +\par +Rev G, 2007-01-04\tab New DDS release 1.1, otherwise no change compared to isse F2.\par +\par +Rev H, 2007-04-23\tab DDS release 1.4, changes for parameter mode=2.\par +\par +Rev I, 2010-04-10\tab DDS release 2.0, multi-thread support.\par +\par +Rev J, 2010-05-29\tab DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals.\par +\par +Rev K, 2010-10-27\tab Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand.\par +\par +Rev L, 2011-10-14\tab Added SolveBoardPBN and CalcDDtablePBN.\par + \par +\par +} + \ No newline at end of file diff --git a/DLL-dds_21_j.txt b/DLL-dds_212_l.txt similarity index 79% rename from DLL-dds_21_j.txt rename to DLL-dds_212_l.txt index 99ec6db3..92f48d9e 100644 --- a/DLL-dds_21_j.txt +++ b/DLL-dds_212_l.txt @@ -1,16 +1,23 @@ Bo Haglund, Bob Richardson -Rev J, 2010-05-29 +Rev L, 2011-10-14 Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -Short description of the DLL functions supported in Double Dummy Problem Solver 2.1 +Short description of the DLL functions supported in Double Dummy Problem Solver 2.1.2 Callable functions extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex); -extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep); +extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, + int solutions, int mode, struct futureTricks *futp, int threadIndex); + +extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, + struct ddTableResults * tablep); + +extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN + tableDealPBN, struct ddTableResults * tablep); SolveBoard @@ -80,9 +87,27 @@ Parameter ”threadIndex” defines the identity of the thread used when calling Maximum 16 threads can call SolveBoard in parallel, threadIndex must be an integer of the range 0..15. +SolveBoardPBN + +In SolveBoardPBN the remaining cards in the deal information are given in PBN text +format (e.g. +W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K) instead of using bits 2-14 in an integer array. Otherwise, SolveboardPBN is identical to SolveBoard. + +struct dealPBN { + int trump; + int first; + int currentTrickSuit[3]; + int currentTrickRank[3]; + char remainCards[80]; /* First character identifies the hand having the cards given first + in the string, then the cards of the other hands are given in a + clock-wise order, see example above. Null characters fill out + the character array at the end. */ +}; + + CalcDDtable -CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/leading hand combinations. +CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations. Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. CalcDDtable returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure. @@ -95,11 +120,18 @@ struct ddTableDeal { unsigned int cards[4][4]; /* 1st index is hand, 2nd index is suit, same coding as for deal.remainCards for SolveBoard. */ }; -struct ddTableResults { /* For each combination trump suit / leading hand, the DLL provides the double dummy score. */ - int resTable[5][4]; /* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is leading hand, 0=North, 1=East, 2=South, 3=West */ +struct ddTableResults { /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */ + int resTable[5][4]; /* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is declarer hand, 0=North, 1=East, 2=South, 3=West */ }; +CalcDDtablePBN + +In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable. + +struct ddTableDealPBN { + char cards[80]; +}; Revision History @@ -127,4 +159,10 @@ Rev H, 2007-04-23 DDS release 1.4, changes for parameter mode=2. Rev I, 2010-04-10 DDS release 2.0, multi-thread support. -Rec J, 2010-05-29 DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. +Rev J, 2010-05-29 DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. + +Rev K, 2010-10-27 Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand. + +Rev L, 2011-10-14 Added SolveBoardPBN and CalcDDtablePBN. + + diff --git a/DLL-dds_21_j.rtf b/DLL-dds_21_j.rtf deleted file mode 100644 index 5cd7adfb..00000000 --- a/DLL-dds_21_j.rtf +++ /dev/null @@ -1,142 +0,0 @@ -{\rtf1\ansi\ansicpg1252\uc1 \deff1\deflang1033\deflangfe1053{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} -{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;} -{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f22\fswiss\fcharset238\fprq2 Arial CE;}{\f23\fswiss\fcharset204\fprq2 Arial Cyr;}{\f25\fswiss\fcharset161\fprq2 Arial Greek;}{\f26\fswiss\fcharset162\fprq2 Arial Tur;} -{\f27\fswiss\fcharset186\fprq2 Arial Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128; -\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\nowidctlpar\adjustright \f1\cgrid \snext0 Normal;}{ -\s1\nowidctlpar\outlinelevel0\adjustright \f1\cgrid \sbasedon0 \snext0 heading 1;}{\s2\keepn\nowidctlpar\outlinelevel1\adjustright \b\f1\fs20\ul\cf1\lang1053\cgrid \sbasedon0 \snext0 heading 2;}{\s3\keepn\nowidctlpar\outlinelevel2\adjustright -\b\f1\fs20\cf1\lang1053\cgrid \sbasedon0 \snext0 heading 3;}{\*\cs10 \additive Default Paragraph Font;}{\*\cs15 \additive \b \sbasedon10 Strong;}}{\info{\title Bo Haglund, Bob Richardson}{\author Bo Haglund}{\operator Bo Haglund} -{\creatim\yr2007\mo4\dy23\hr19\min18}{\revtim\yr2010\mo5\dy28\hr23\min47}{\version33}{\edmins161}{\nofpages3}{\nofwords1128}{\nofchars6430}{\*\company }{\nofcharsws0}{\vern89}}\margl1417\margr1417\margt1417\margb1417 -\widowctrl\ftnbj\aenddoc\hyphhotz425\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\viewkind4\viewscale100 \fet0\sectd \linex0\headery709\footery709\colsx709\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}} -{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}} -{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9 -\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \nowidctlpar\adjustright \f1\cgrid {\fs20\lang1053 Bo Haglund, Bob Richardson -\par Rev J, 2010-05-29 -\par Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ -\par -\par -\par }\pard\plain \s2\keepn\nowidctlpar\outlinelevel1\adjustright \b\f1\fs20\ul\cf1\lang1053\cgrid {Short description of the DLL functions supported in Double Dummy Problem Solver 2.1 -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\fs20\cf1\lang1053 -\par }\pard\plain \s3\keepn\nowidctlpar\outlinelevel2\adjustright \b\f1\fs20\cf1\lang1053\cgrid {Callable functions -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\fs20\cf1\lang1053 -\par extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, -\par int solutions, int mode, struct futureTricks *futp, int threadIndex); -\par -\par extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep); -\par -\par -\par }\pard\plain \s3\keepn\nowidctlpar\outlinelevel2\adjustright \b\f1\fs20\cf1\lang1053\cgrid {SolveBoard -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\fs20\cf1\lang1053 -\par SolveBoard is thread-safe, so several threads (max 16) can call SolveBoard in parallel. -\par -\par Before SolveBoard can be called, a structure of type "futureTricks" must be declared. -\par -\par }{\b\fs20\cf1\lang1053 SolveBoard}{\fs20\cf1\lang1053 returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line Status codes: -\par 1=No fault, -\par -1=Unknown fault, -\par -2=No of cards = 0, -\par -3=target > Number of tricks left, -\par -4=Duplicated cards, -\par -5=target < -1, -\par -7=target >13, -\par -8=solutions < 1, -\par -9=solutions > 3, -\par -10=No of cards > 52 -\par -11=Not used -\par -12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. -\par -13=Card already played in the current trick is also defined as a remaining card to play. -\par -14=Wrong number of remaining cards for a hand. -\par -15=threadIndex < 0 or > 15.\line \line Structure \'94}{\b\fs20\cf1\lang1053 deal}{\fs20\cf1\lang1053 \'94 defines all data needed to describe the deal to be analyzed. -\par struct deal \{}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 int trump; /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3, NT=4 */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in the order played */ -\par int currentTrickRank[3]; /* 2-14 for up to 3 cards */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 unsigned int remainCards[4][4]; /* 1}{\fs20\cf1\lang1053\super st}{\fs20\cf1\lang1053 index hand (0-3), 2}{\fs20\cf1\lang1053\super nd}{\fs20\cf1\lang1053 in -dex suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2, \'85\'85\'85. bit 14=rank 14, bit 15=0}{\f0\fs20\cf1\lang1053 }{\fs20\cf1\lang1053 -for cards remaining after already played cards (cards already played to the current trick are not included in this bitstring). \line The decimal value for a card then range between 4 (=rank 2) and 16384 (Ace=rank 14). */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 \};}{\f0\fs20\cf1\lang1053 }{\fs20\cf1\lang1053 -\par -\par Parameter \'94}{\b\fs20\cf1\lang1053 target}{\fs20\cf1\lang1053 \'94 is the number of tricks to be won by the side to play, -1 means that the program}{\f0\fs20\cf1\lang1053 }{\fs20\cf1\lang1053 -shall find the maximum number. For equivalent cards only the highest is returned. -\par \line Parameter \'94}{\b\fs20\cf1\lang1053 solutions}{\fs20\cf1\lang1053 \'94 defines how many card solutions that SolveBoard must return: -\par target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target whentarget or higher tricks can be won. Otherwise, score \endash 1 is returned if target cannot be reached, or score 0 if no tricks can be won. \line - target=-1, solutions=1: Returns only one of the optimum cards and its score. -\par }{\fs20\lang1053 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.}{\fs20\cf1\lang1053 \line target 1-13, - solutions=2: Return all cards meeting target. Their returned scores are the same as target when target or higher tricks can be won. Otherwise, only one card is returned with score \endash -1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line target \endash 1, solutions=2: Return all optimum cards with their scores. -\par }{\fs20\lang1053 target=0, solutions=2: Return all cards legal to play with scores set to 0}{\fs20\cf6\lang1053 .}{\fs20\cf1\lang1053 \line target irrelevant, solutions=3: Return all cards that can be legally played with -their scores in descending order. -\par -\par Parameter \'94}{\b\fs20\cf1\lang1053 mode}{\fs20\cf1\lang1053 \'94 defines the DLL mode of operation.\line mode=0: Do not search to find the score if the hand to play has only one card, including its equivalents, to play. Score is set to \endash -2 for this card, indicating that there are no alternative cards. If there are multiple choices for cards to play, search is done to find the score. This mode is very fast but you don\rquote t -\par mode=1: Always }{\fs20 search to find the score. Even when the hand to play has only one card, with possibl -e equivalents, to play. For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mode=2 is n -o longer needed in this case, but can still be done for backwards compatibility.\line - mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL to ensure -that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. -\par }\pard \fi720\nowidctlpar\adjustright {\fs20 1}{\fs20\super st}{\fs20 call: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1, i.e. East leads. -\par }\pard \nowidctlpar\adjustright {\fs20 \tab 2}{\fs20\super nd}{\fs20 call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads. -\par \tab 3rd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3, i.e. West leads. -\par }\pard \fi720\nowidctlpar\adjustright {\fs20 4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. }{\fs20\cf1\lang1053 -\par }\pard \nowidctlpar\adjustright {\fs20\cf1\lang1053 -\par struct }{\b\fs20\cf1\lang1053 futureTricks}{\fs20\cf1\lang1053 \{ /* The DLL provides the score (number of tricks) that can be won by the card to play defined by its suit and rank. Array of all alternative cards. */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 int nodes; /* Number of searched nodes */ -\par int cards; /* No of alternative cards */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 int suit[13]; /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ -\par int rank[13]; /* 2-14 for 2 through Ace *}{\b\fs20\cf1\lang1053 / -\par }{\fs20\cf1\lang1053 int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When there are several \'94equals\'94, the value is the sum of each \'94equal\'94. *}{ -\b\fs20\cf1\lang1053 /}{\fs20\cf1\lang1053 -\par int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */}{\f0\fs20\cf1\lang1053 -\par }{\fs20\cf1\lang1053 \} ; -\par -\par Parameter \'94}{\b\fs20\cf1\lang1053 threadIndex}{\fs20\cf1\lang1053 \'94 defines the identity of the thread used when calling SolveBoard. -\par Maximum 16 threads can call SolveBoard in parallel, threadIndex must be an integer of the range 0..15.}{ -\par }\pard\plain \s3\keepn\nowidctlpar\outlinelevel2\adjustright \b\f1\fs20\cf1\lang1053\cgrid { -\par -\par CalcDDtable -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\f0\fs20\cf1\lang1053 -\par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \f1\cgrid {\fs20\cf1\lang1053 CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/leading hand combinations. -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid { -\par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \f1\cgrid {\fs20\cf1\lang1053 Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\b\fs20\cf1\lang1053 CalcDDtable}{\fs20\cf1\lang1053 returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.\line Status codes: -\par 1=No fault, -\par Other status codes are errors, with codes equal to SolveBoard status codes. }{ -\par -\par }{\fs20\cf1\lang1053 Structure \'94}{\b\fs20\cf1\lang1053 ddTableDeal}{\fs20\cf1\lang1053 \'94 defines the dealt cards to be analyzed.}{\fs20 -\par struct ddTableDeal \{ -\par unsigned int cards[4][4]; /* 1}{\fs20\super st}{\fs20 index is hand, 2}{\fs20\super nd}{\fs20 index is suit, same coding as for deal.remainCards for SolveBoard. */ -\par \}; -\par -\par }{\fs20\cf1\lang1053 struct }{\b\fs20\cf1\lang1053 ddTableResults}{\fs20\cf1\lang1053 \{ /* For each combination trump suit / leading hand, the DLL provides the double dummy score. */}{\fs20 -\par int resTable[5][4];\tab /* 1}{\fs20\super st}{\fs20 index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2}{\fs20\super nd}{\fs20 index is leading hand, 0=North, 1=East, 2=South, 3=West */ -\par \}; -\par }{ -\par -\par -\par -\par }\pard\plain \s1\keepn\nowidctlpar\outlinelevel0\adjustright \f1\cgrid {\b\fs20\cf1\lang1053 Revision History -\par }\pard\plain \nowidctlpar\adjustright \f1\cgrid {\fs20\cf1\lang1053 -\par Rev A, 2006-02-25.\tab \tab First issue. -\par -\par Rev B, 2006-03-20\tab \tab Updated issue. -\par -\par }\pard \fi-2880\li2880\nowidctlpar\adjustright {\fs20\cf1\lang1053 Rev C, 2006-03-28\tab Updated issue. Addition of the SolveBoard parameter \'94mode\'94. -\par -\par Rev D, 2006-04-05\tab Updated issue. Usage of target=0 to list all cards that are legal to play. -\par -\par Rev E, 2006-05-29\tab Updated issue. New error code \endash 10 for number of cards > 52. -\par -\par Rev F, 2006-08-09\tab Updated issue. New mode parameter value = 2. New error code \endash 11 for calling SolveBoard with mode = 2 and forbidden values of other parameters. -\par }\pard \nowidctlpar\adjustright {\fs20\cf1\lang1053 -\par }\pard \fi-2880\li2880\nowidctlpar\adjustright {\fs20\cf1\lang1053 Rev F1, 2006-08-14\tab Clarifications on conditions for returning scores for the different combinations of the values for target and solutions. -\par -\par Rev F2, 2006-08-26\tab New error code \endash 12 for wrongly set values of deal.currentTrickSuit and\line deal.currentTrickRank. -\par -\par Rev G, 2007-01-04\tab New DDS release 1.1, otherwise no change compared to isse F2. -\par -\par Rev H, 2007-04-23\tab DDS release 1.4, changes for parameter mode=2. -\par -\par Rev I, 2010-04-10\tab DDS release 2.0, multi-thread support. -\par -\par Rec J, 2010-05-29\tab DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. -\par }} \ No newline at end of file diff --git a/Makefile.txt b/Makefile.txt new file mode 100644 index 00000000..545325ac --- /dev/null +++ b/Makefile.txt @@ -0,0 +1,24 @@ +CFLAGS=-g -Wall -O2 +PREFIX=/usr/local + +all: libdds.a python + +dds.h: + ln -s dll.h dds.h + +dds.c: + ln -s dds.cpp $@ + +dds.o: dds.c dds.h + +libdds.a: dds.o + ar rc $@ $^ + ranlib $@ + +install: + install -d $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib + install -m644 dll.h $(DESTDIR)$(PREFIX)/include/dds.h + install libdds.a $(DESTDIR)$(PREFIX)/lib + +clean: + rm -f dds.o libdds.a dds.c dds.h diff --git a/dds.cpp b/dds.cpp index 3a1d54df..8daaf192 100644 --- a/dds.cpp +++ b/dds.cpp @@ -1,6 +1,6 @@ -/* DDS 2.1.1 A bridge double dummy solver. */ -/* Copyright (C) 2006-2010 by Bo Haglund */ +/* DDS 2.1.2 A bridge double dummy solver. */ +/* Copyright (C) 2006-2011 by Bo Haglund */ /* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli */ /* */ /* This program is free software; you can redistribute it and/or */ @@ -17,7 +17,7 @@ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc, 51 Franklin Street, 5th Floor, Boston MA 02110-1301, USA. */ -/*#include "stdafx.h"*/ /* Needed by Visual C++ */ +/*#include "stdafx.h"*/ /* Needed by Visual C++ */ #include "dll.h" @@ -40,7 +40,7 @@ int suppressTTlog; int noOfThreads=MAXNOOFTHREADS; /* The number of entries to the transposition tables. There is one entry per thread. */ -int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */ +int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */ #if defined(_MSC_VER) CRITICAL_SECTION solv_crit; @@ -59,7 +59,7 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, if (ul_reason_for_call==DLL_PROCESS_ATTACH) { InitStart(0, 0); #if defined(_MSC_VER) - InitializeCriticalSection(&solv_crit); + InitializeCriticalSection(&solv_crit); #endif } else if (ul_reason_for_call==DLL_PROCESS_DETACH) { @@ -92,9 +92,9 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, if (localVar[k].rel) free(localVar[k].rel); localVar[k].rel=NULL; - if (localVar[k].adaptWins) - free(localVar[k].adaptWins); - localVar[k].adaptWins=NULL; + if (localVar[k].adaptWins) + free(localVar[k].adaptWins); + localVar[k].adaptWins=NULL; } if (highestRank) free(highestRank); @@ -127,6 +127,11 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, unsigned short int aggrRemain; struct movePlyType temp; struct moveType mv; + int hiwinSetSize=0, hinodeSetSize=0; + int hilenSetSize=0; + int MaxnodeSetSize=0; + int MaxwinSetSize=0; + int MaxlenSetSize=0; /*InitStart(0,0);*/ /* Include InitStart() if inside SolveBoard, @@ -193,7 +198,7 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2); if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) { localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2; - localVar[thrId].newDeal=TRUE; + localVar[thrId].newDeal=TRUE; } } } @@ -488,8 +493,8 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, localVar[thrId].nodes=0; localVar[thrId].trickNodes=0; localVar[thrId].iniDepth=cardCount-4; - localVar[thrId].hiwinSetSize=0; - localVar[thrId].hinodeSetSize=0; + hiwinSetSize=0; + hinodeSetSize=0; if (mode==0) { MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, thrId); @@ -538,15 +543,15 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, temp=localVar[thrId].movePly[localVar[thrId].iniDepth]; last=localVar[thrId].movePly[localVar[thrId].iniDepth].last; noMoves=last+1; - localVar[thrId].hiwinSetSize=localVar[thrId].winSetSize; - localVar[thrId].hinodeSetSize=localVar[thrId].nodeSetSize; - localVar[thrId].hilenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].nodeSetSize>localVar[thrId].MaxnodeSetSize) - localVar[thrId].MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>localVar[thrId].MaxwinSetSize) - localVar[thrId].MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>localVar[thrId].MaxlenSetSize) - localVar[thrId].MaxlenSetSize=localVar[thrId].lenSetSize; + hiwinSetSize=localVar[thrId].winSetSize; + hinodeSetSize=localVar[thrId].nodeSetSize; + hilenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==1) localVar[thrId].payOff=localVar[thrId].tricksTarget; else @@ -558,10 +563,10 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; - if (localVar[thrId].tricksTarget>1) + if (localVar[thrId].tricksTarget>1) futp->score[0]=-1; - else - futp->score[0]=0; + else + futp->score[0]=0; } else { futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; @@ -586,23 +591,23 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, if (localVar[thrId].val==TRUE) mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; - localVar[thrId].hiwinSetSize=Max(localVar[thrId].hiwinSetSize, localVar[thrId].winSetSize); - localVar[thrId].hinodeSetSize=Max(localVar[thrId].hinodeSetSize, localVar[thrId].nodeSetSize); - localVar[thrId].hilenSetSize=Max(localVar[thrId].hilenSetSize, localVar[thrId].lenSetSize); - if (localVar[thrId].nodeSetSize>localVar[thrId].MaxnodeSetSize) - localVar[thrId].MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>localVar[thrId].MaxwinSetSize) - localVar[thrId].MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>localVar[thrId].MaxlenSetSize) - localVar[thrId].MaxlenSetSize=localVar[thrId].lenSetSize; + hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); + hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); + hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==FALSE) { - upperbound=tricks-1; - g=upperbound; - } - else { - lowerbound=tricks; - g=lowerbound; - } + upperbound=tricks-1; + g=upperbound; + } + else { + lowerbound=tricks; + g=lowerbound; + } InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, localVar[thrId].initialMoves, first, TRUE, thrId); } @@ -618,13 +623,13 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, futp->score[0]=0; futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; - futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; + futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; } else { futp->score[0]=localVar[thrId].payOff; futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; } localVar[thrId].tricksTarget=localVar[thrId].payOff; } @@ -661,30 +666,26 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, forb++; } } - if (1/*(localVar[thrId].winSetSizelocalVar[thrId].MaxnodeSetSize) - localVar[thrId].MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>localVar[thrId].MaxwinSetSize) - localVar[thrId].MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>localVar[thrId].MaxlenSetSize) - localVar[thrId].MaxlenSetSize=localVar[thrId].lenSetSize; + hiwinSetSize=localVar[thrId].winSetSize; + hinodeSetSize=localVar[thrId].nodeSetSize; + hilenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==TRUE) { localVar[thrId].payOff=localVar[thrId].tricksTarget; futp->cards=ind; futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; futp->score[ind-1]=localVar[thrId].payOff; } else @@ -701,7 +702,7 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, found=FALSE; if ((temp.move[i].suit==futp->suit[0])&& (temp.move[i].rank==futp->rank[0])) { - found=TRUE; + found=TRUE; } if (!found) { futp->suit[1+n]=temp.move[i].suit; @@ -724,47 +725,41 @@ extern "C" BOOL APIENTRY DllMain(HMODULE hModule, g=localVar[thrId].payOff; upperbound=localVar[thrId].payOff; lowerbound=0; - if (0/*(localVar[thrId].winSetSize>SIMILARMAXWINNODES)*/) - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, FALSE, thrId); - else - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, + + InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, localVar[thrId].initialMoves, first, TRUE, thrId); do { if (g==lowerbound) tricks=g+1; else tricks=g; - assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&& + assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&& (localVar[thrId].lookAheadPos.handRelFirst<=3)); localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, localVar[thrId].iniDepth, thrId); if (localVar[thrId].val==TRUE) mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; - localVar[thrId].hiwinSetSize=Max(localVar[thrId].hiwinSetSize, localVar[thrId].winSetSize); - localVar[thrId].hinodeSetSize=Max(localVar[thrId].hinodeSetSize, localVar[thrId].nodeSetSize); - localVar[thrId].hilenSetSize=Max(localVar[thrId].hilenSetSize, localVar[thrId].lenSetSize); - if (localVar[thrId].nodeSetSize>localVar[thrId].MaxnodeSetSize) - localVar[thrId].MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>localVar[thrId].MaxwinSetSize) - localVar[thrId].MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>localVar[thrId].MaxlenSetSize) - localVar[thrId].MaxlenSetSize=localVar[thrId].lenSetSize; + hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); + hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); + hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; if (localVar[thrId].val==FALSE) { - upperbound=tricks-1; - g=upperbound; - } - else { - lowerbound=tricks; - g=lowerbound; - } - if (0/*(localVar[thrId].winSetSize>SIMILARMAXWINNODES)*/) - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, FALSE, thrId); - else - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, TRUE, thrId); + upperbound=tricks-1; + g=upperbound; + } + else { + lowerbound=tricks; + g=lowerbound; + } + + InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, + localVar[thrId].initialMoves, first, TRUE, thrId); } while (lowerbound=2; r--) { + if ((ind & bitMapRank[r])!=0) { + localVar[thrId].rel[ind].relRank[r][s]=ord; + ord++; + } + } for (h=0; h<4; h++) { if (localVar[thrId].game.suit[h][s] & topBitRank) { localVar[thrId].rel[ind].aggrRanks[s]= @@ -1479,53 +1479,120 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { ranks=posPoint->rankInSuit[hand][ss] | posPoint->rankInSuit[partner[hand]][ss]; found=FALSE; rr=0; qtricks=0; - if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[lho[hand]][ss])) { - /* Own side has highest card in suit */ - if ((localVar[thrId].trump==4) || ((ss==localVar[thrId].trump)|| - (posPoint->rankInSuit[lho[hand]][localVar[thrId].trump]==0) - || (posPoint->rankInSuit[lho[hand]][ss]!=0))) { - rr=highestRank[ranks]; - if (rr!=0) { - found=TRUE; - qtricks=1; - } - else - found=FALSE; - } - } - else if ((localVar[thrId].trump!=4) && (ss!=localVar[thrId].trump) && + + if ((localVar[thrId].trump!=4) && (ss!=localVar[thrId].trump) && (((posPoint->rankInSuit[hand][ss]==0) - && (posPoint->rankInSuit[hand][localVar[thrId].trump]!=0))|| - ((posPoint->rankInSuit[partner[hand]][ss]==0) - && (posPoint->rankInSuit[partner[hand]][localVar[thrId].trump]!=0)))) { - /* Own side can ruff */ + && (posPoint->rankInSuit[hand][localVar[thrId].trump]!=0))|| + ((posPoint->rankInSuit[partner[hand]][ss]==0) + && (posPoint->rankInSuit[partner[hand]][localVar[thrId].trump]!=0)))) { + /* Own side can ruff */ if ((posPoint->rankInSuit[lho[hand]][ss]!=0)|| (posPoint->rankInSuit[lho[hand]][localVar[thrId].trump]==0)) { - found=TRUE; + found=TRUE; qtricks=1; } - } - if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { - if ((posPoint->tricksMAX+qtricks>=target)&&(found)&& - (depth!=localVar[thrId].iniDepth)) { - for (k=0; k<=3; k++) - posPoint->winRanks[depth][k]=0; - if (rr!=0) - posPoint->winRanks[depth][ss]= - posPoint->winRanks[depth][ss] | bitMapRank[rr]; - return TRUE; - } } - else { - if (((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target)&& - (found)&&(depth!=localVar[thrId].iniDepth)) { - for (k=0; k<=3; k++) - posPoint->winRanks[depth][k]=0; - if (rr!=0) - posPoint->winRanks[depth][ss]= - posPoint->winRanks[depth][ss] | bitMapRank[rr]; - return FALSE; + + else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[lho[hand]][ss])) { + /* Own side has highest card in suit */ + if ((localVar[thrId].trump==4) || ((ss==localVar[thrId].trump)|| + (posPoint->rankInSuit[lho[hand]][localVar[thrId].trump]==0) + || (posPoint->rankInSuit[lho[hand]][ss]!=0))) { + rr=highestRank[ranks]; + if (rr!=0) { + found=TRUE; + qtricks=1; + } + else + found=FALSE; + } + } + + if ((found)&&(depth!=localVar[thrId].iniDepth)) { + for (k=0; k<=3; k++) + posPoint->winRanks[depth][k]=0; + if (rr!=0) + posPoint->winRanks[depth][ss]=bitMapRank[rr]; + + if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { + if (posPoint->tricksMAX+qtricks>=target) { + return TRUE; + } + else if (localVar[thrId].trump==4) { + if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) + hh=hand; /* Hand to lead next trick */ + else + hh=partner[hand]; + + if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& + (posPoint->secondBest[ss].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; + if (posPoint->tricksMAX+qtricks>=target) { + return TRUE; + } + } + + for (k=0; k<=3; k++) { + if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ + if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) + &&(posPoint->length[partner[hh]][k]==0)) { + qtricks+=counttable[posPoint->rankInSuit[hh][k]]; + if (posPoint->tricksMAX+qtricks>=target) { + return TRUE; + } + } + else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; + if (posPoint->tricksMAX+qtricks>=target) { + return TRUE; + } + } + } + } + } + } + else { + /* MIN node */ + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { + return FALSE; + } + else if (localVar[thrId].trump==4) { + if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) + hh=hand; /* Hand to lead next trick */ + else + hh=partner[hand]; + + if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& + (posPoint->secondBest[ss].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { + return FALSE; + } + } + + for (k=0; k<=3; k++) { + if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ + if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) + &&(posPoint->length[partner[hh]][k]==0)) { + qtricks+=counttable[posPoint->rankInSuit[hh][k]]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { + return FALSE; + } + } + else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { + return FALSE; + } + } + } + } + } } } } @@ -1536,7 +1603,6 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { aggr[ss]=0; for (hh=0; hh<=3; hh++) aggr[ss]=aggr[ss] | posPoint->rankInSuit[hh][ss]; - /* New algo */ posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; } tricks=depth>>2; @@ -1552,7 +1618,7 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { /* Find node that fits the suit lengths */ if (pp!=NULL) { np=pp->posSearchPoint; - if (np==NULL) + if (np==NULL) cardsP=NULL; else cardsP=FindSOP(posPoint, np, hand, target, tricks, &scoreFlag, thrId); @@ -1680,7 +1746,6 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { aggr[ss]=0; for (hh=0; hh<=3; hh++) aggr[ss]=aggr[ss] | posPoint->rankInSuit[hh][ss]; - /* New algo */ posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; } tricks=depth>>2; @@ -1751,7 +1816,7 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { if (ready) InsertSort(localVar[thrId].movePly[depth].last+1, depth, thrId); } - /*#endif*/ + /*#endif*/ localVar[thrId].movePly[depth].current=0; if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { @@ -1768,10 +1833,10 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { Undo(posPoint, depth, thrId); /* Retract current move */ if (value==TRUE) { /* A cut-off? */ - for (ss=0; ss<=3; ss++) + for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - mcurrent=localVar[thrId].movePly[depth].current; + mcurrent=localVar[thrId].movePly[depth].current; localVar[thrId].bestMove[depth]=localVar[thrId].movePly[depth].move[mcurrent]; goto ABexit; } @@ -1795,10 +1860,10 @@ int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { Undo(posPoint, depth, thrId); /* Retract current move */ if (value==FALSE) { /* A cut-off? */ - for (ss=0; ss<=3; ss++) + for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - mcurrent=localVar[thrId].movePly[depth].current; + mcurrent=localVar[thrId].movePly[depth].current; localVar[thrId].bestMove[depth]=localVar[thrId].movePly[depth].move[mcurrent]; goto ABexit; } @@ -2154,7 +2219,7 @@ void Undo(struct pos * posPoint, int depth, int thrId) { struct evalType Evaluate(struct pos * posPoint, int thrId) { - int s, smax=0, max, /*i, j, r, mcurr,*/ k, firstHand, count; + int s, smax=0, max, k, firstHand, count; struct evalType eval; firstHand=posPoint->first[0]; @@ -2202,7 +2267,7 @@ struct evalType Evaluate(struct pos * posPoint, int thrId) { max=0; for (s=0; s<=3; s++) { if (posPoint->rankInSuit[s][k]!=0) - count++; + count++; if (posPoint->rankInSuit[s][k]>max) { smax=s; max=posPoint->rankInSuit[s][k]; @@ -2415,12 +2480,12 @@ int QuickTricks(struct pos * posPoint, int hand, (rhoTrumpRanks==0)) { /* RHO has no trump */ qtricks=qtricks+countOwn; - if (qtricks>=cutoff) + if (qtricks>=cutoff) return qtricks; suit++; if ((trump!=4) && (suit==trump)) suit++; - continue; + continue; } else { suit++; @@ -2546,7 +2611,7 @@ int QuickTricks(struct pos * posPoint, int hand, } } } - } + } /* 08-01-30 */ if (posPoint->winner[suit].rank==0) { if ((trump!=4) && (suit==trump)) { @@ -3161,7 +3226,7 @@ int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, int th posPoint->winRanks[depth][trump]= bitMapRank[posPoint->winner[trump].rank] | bitMapRank[posPoint->secondBest[trump].rank] ; - return FALSE; + return FALSE; } } } @@ -3281,9 +3346,11 @@ int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int th int MoveGen(struct pos * posPoint, int depth, int thrId) { int suit, k, m, n, r, s, t, q, first, state; unsigned short ris; - int scount[4]; - int WeightAlloc(struct pos *, struct moveType * mp, int depth, + int scount[4]; + int WeightAllocTrump(struct pos *, struct moveType * mp, int depth, unsigned short notVoidInSuit, int thrId); + int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int thrId); for (k=0; k<4; k++) localVar[thrId].lowestWin[depth][k]=0; @@ -3322,9 +3389,16 @@ int MoveGen(struct pos * posPoint, int depth, int thrId) { k--; } if (m!=1) { - for (k=0; k<=m-1; k++) - localVar[thrId].movePly[depth].move[k].weight=WeightAlloc(posPoint, - &localVar[thrId].movePly[depth].move[k], depth, ris, thrId); + if (localVar[thrId].trump!=4) { + for (k=0; k<=m-1; k++) + localVar[thrId].movePly[depth].move[k].weight=WeightAllocTrump(posPoint, + &localVar[thrId].movePly[depth].move[k], depth, ris, thrId); + } + else { + for (k=0; k<=m-1; k++) + localVar[thrId].movePly[depth].move[k].weight=WeightAllocNT(posPoint, + &localVar[thrId].movePly[depth].move[k], depth, ris, thrId); + } } localVar[thrId].movePly[depth].last=m-1; @@ -3339,7 +3413,7 @@ int MoveGen(struct pos * posPoint, int depth, int thrId) { } else { /* First hand or void in suit */ for (suit=0; suit<=3; suit++) { - k=14; state=MOVESVALID; + k=14; state=MOVESVALID; while (k>=2) { if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&& (state==MOVESVALID)) { @@ -3363,9 +3437,16 @@ int MoveGen(struct pos * posPoint, int depth, int thrId) { } } - for (k=0; k<=m-1; k++) - localVar[thrId].movePly[depth].move[k].weight=WeightAlloc(posPoint, + if (localVar[thrId].trump!=4) { + for (k=0; k<=m-1; k++) + localVar[thrId].movePly[depth].move[k].weight=WeightAllocTrump(posPoint, &localVar[thrId].movePly[depth].move[k], depth, ris, thrId); + } + else { + for (k=0; k<=m-1; k++) + localVar[thrId].movePly[depth].move[k].weight=WeightAllocNT(posPoint, + &localVar[thrId].movePly[depth].move[k], depth, ris, thrId); + } localVar[thrId].movePly[depth].last=m-1; InsertSort(m, depth, thrId); @@ -3405,27 +3486,318 @@ int MoveGen(struct pos * posPoint, int depth, int thrId) { } -int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, +int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit, int thrId) { int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; - int suitWeightDelta, first, q, trump; + int suitWeightDelta, first, q; + int rRank; int suitBonus=0; int winMove=FALSE; - unsigned short suitCount, suitCountLH, suitCountRH; + unsigned short suitCount, suitCountLH, suitCountRH, aggr; int countLH, countRH; first=posPoint->first[depth]; q=handId(first, posPoint->handRelFirst); suit=mp->suit; - trump=localVar[thrId].trump; + aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][suit]; + rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - /*suitAdd=suitCount+suitCount;*/ - suitAdd=(suitCount<<6)/36; - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=2; + switch (posPoint->handRelFirst) { + case 0: + suitCount=posPoint->length[q][suit]; + suitCountLH=posPoint->length[lho[q]][suit]; + suitCountRH=posPoint->length[rho[q]][suit]; + + if ((posPoint->winner[suit].hand==rho[q])|| + ((posPoint->secondBest[suit].hand!=-1)&& + (posPoint->secondBest[suit].hand==rho[q]))) { + suitBonus-=7/*6*//*12*//*17*/; + } + + else if ((posPoint->winner[suit].hand==lho[q])&& + (posPoint->secondBest[suit].hand==partner[q])) + suitBonus+=34/*37*//*32*//*20*/; + + if (suitCountLH!=0) + countLH=(suitCountLH<<2); + else + countLH=depth+4; + if (suitCountRH!=0) + countRH=(suitCountRH<<2); + else + countRH=depth+4; + + suitWeightDelta=suitBonus-((countLH+countRH)<<5)/(19/*20*//*15*/); + + if (posPoint->winner[suit].rank==mp->rank) + winMove=TRUE; + else if (posPoint->rankInSuit[partner[first]][suit] > + (posPoint->rankInSuit[lho[first]][suit] | + posPoint->rankInSuit[rho[first]][suit])) { + winMove=TRUE; + } + + if (winMove) { + if (posPoint->winner[suit].hand==first) { + if ((posPoint->secondBest[suit].hand!=-1)&& + (posPoint->secondBest[suit].hand==partner[first])) + weight=suitWeightDelta+48/*51*//*50*/+rRank; + else if (posPoint->winner[suit].rank==mp->rank) + weight=suitWeightDelta+35/*34*//*31*/; + else + weight=suitWeightDelta+35/*33*//*27*//*21*/+rRank; + } + else if (posPoint->winner[suit].hand==partner[first]) { + /* If partner has winning card */ + if (posPoint->secondBest[suit].hand==first) + weight=suitWeightDelta+45/*50*/+rRank; + else + weight=suitWeightDelta+33/*35*/+rRank; + } + + if ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=121/*122*//*112*//*73*/; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=18/*17*//*14*/; + } + else { + if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) + ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) + weight=suitWeightDelta+25/*23*//*22*/+rRank; + else if (posPoint->winner[suit].hand==first) { + weight=suitWeightDelta-28/*27*//*12*//*10*/+rRank; + } + else if ((mp->sequence)&& + (mp->rank==posPoint->secondBest[suit].rank)) + weight=suitWeightDelta+42/*36*//*32*/; + else + weight=suitWeightDelta+12/*9*/+rRank; + + if ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=47/*45*//*39*//*38*/; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=17/*16*//*19*//*14*/; + } + + break; + + case 1: + leadSuit=posPoint->move[depth+1].suit; + if (leadSuit==suit) { + if (bitMapRank[mp->rank]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) + winMove=TRUE; + else if (posPoint->rankInSuit[rho[first]][suit]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) + winMove=TRUE; + } + else { + /* Side with highest rank in leadSuit wins */ + if (posPoint->rankInSuit[rho[first]][leadSuit] > + (posPoint->rankInSuit[partner[first]][leadSuit] | + bitMapRank[posPoint->move[depth+1].rank])) + winMove=TRUE; + } + + kk=posPoint->rankInSuit[partner[first]][leadSuit]; + ll=posPoint->rankInSuit[rho[first]][leadSuit]; + k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit */ + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(4/*5*/); + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(5/*8*//*5*/); + + weight=/*60*/-(mp->rank)+suitAdd; + } + else if (k > bitMapRank[mp->rank]) + weight=65/*62*/+rRank; + /* If lowest card for partner to leading hand + is higher than lho played card, playing as low as + possible will give the cheapest win */ + else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& + (posPoint->rankInSuit[first][leadSuit] > ll)) + weight=49+rRank; + /* If rho has a card in the leading suit that + is higher than the trick leading card but lower + than the highest rank of the leading hand, then + lho playing the lowest card will be the cheapest + win */ + else if (mp->rank > posPoint->move[depth+1].rank) { + if (bitMapRank[mp->rank] < ll) + + weight=57/*60*/+rRank; /* If played card is lower than any of the cards of + rho, it will be the cheapest win */ + else if (bitMapRank[mp->rank] > kk) + weight=73-(mp->rank); + /* If played card is higher than any cards at partner + of the leading hand, rho can play low, under the + condition that he has a lower card than lho played */ + } + else if (posPoint->length[rho[first]][leadSuit]>0) { + if (mp->sequence) + weight=50-(mp->rank); + /* Playing a card in a sequence may promote a winner */ + else + weight=48-(mp->rank); + } + /*else + weight=45-(mp->rank);*/ + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/35; + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=5; + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=6/*5*/; + + weight=-(mp->rank)+suitAdd; + + } + else if ((k > bitMapRank[mp->rank])|| + (l > bitMapRank[mp->rank])) + weight=-3+rRank; + /* If lowest rank for either partner to leading hand + or rho is higher than played card for lho, + lho should play as low card as possible */ + else if (mp->rank > posPoint->move[depth+1].rank) { + if (mp->sequence) { + weight=10+rRank; + } + else { + weight=13-(mp->rank); + } + } + else { + weight=-15+rRank; + } + } + + break; + + case 2: + + leadSuit=posPoint->move[depth+2].suit; + if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) { + if (suit==leadSuit) { + if (bitMapRank[mp->rank] > + posPoint->rankInSuit[rho[first]][suit]) + winMove=TRUE; + } + } + else if (posPoint->high[depth+1]==first) { + if (posPoint->length[rho[first]][leadSuit]!=0) { + if (posPoint->rankInSuit[rho[first]][leadSuit] + < bitMapRank[posPoint->move[depth+2].rank]) + winMove=TRUE; + } + else + winMove=TRUE; + } + + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(24/*27*//*30*//*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(4/*2*//*5*/); + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(2/*1*//*2*//*5*/); + + weight=-(mp->rank)+suitAdd; + } + else { + weight=60+rRank; + } + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(21/*26*//*29*//*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(3/*5*/); + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(2/*5*/); + + weight=-(mp->rank)+suitAdd; + } + else { + /*weight=20-(mp->rank);*/ + + if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) { + if (mp->rank==posPoint->secondBest[leadSuit].rank) + weight=25; + else if (mp->sequence) + weight=20-(mp->rank); + else + weight=10-(mp->rank); + } + else + weight=-10-(mp->rank); + } + } + + break; + + case 3: + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(32/*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(6/*5*/); + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(7/*9*//*8*//*5*/); + + weight=30-(mp->rank)+suitAdd; + } + else if ((posPoint->high[depth+1])==(lho[first])) { + /* If the current winning move is given by the partner */ + weight=30-(mp->rank); + } + else if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) + /* If present move is superior to current winning move and the + current winning move is not given by the partner */ + weight=30-(mp->rank); + else { + /* If present move is not superior to current winning move and the + current winning move is not given by the partner */ + weight=14-(mp->rank); + } } + return weight; +} + + +int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int thrId) { + int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; + int suitWeightDelta, first, q, trump, rRank; + int suitBonus=0; + int winMove=FALSE; + unsigned short suitCount, suitCountLH, suitCountRH, aggr; + int countLH, countRH; + + first=posPoint->first[depth]; + q=handId(first, posPoint->handRelFirst); + suit=mp->suit; + trump=localVar[thrId].trump; + aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][suit]; + rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; switch (posPoint->handRelFirst) { case 0: @@ -3433,24 +3805,31 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, suitCountLH=posPoint->length[lho[q]][suit]; suitCountRH=posPoint->length[rho[q]][suit]; - if ((trump!=4) && (suit!=trump) && + if ((suit!=trump) && (((posPoint->rankInSuit[lho[q]][suit]==0) && (posPoint->rankInSuit[lho[q]][trump]!=0)) || ((posPoint->rankInSuit[rho[q]][suit]==0) && (posPoint->rankInSuit[rho[q]][trump]!=0)))) - suitBonus=-10/*12*//*15*/; + suitBonus=-13/*20*//*-10*/; + + if ((suit!=trump)&&(posPoint->length[partner[q]][suit]==0)&& + (posPoint->length[partner[q]][trump]>0)&&(suitCountRH>0)) + suitBonus+=19/*28*/; if ((posPoint->winner[suit].hand==rho[q])|| - ((posPoint->secondBest[suit].hand!=-1)&& + ((posPoint->secondBest[suit].hand!=-1)&& (posPoint->secondBest[suit].hand==rho[q]))) { - suitBonus-=18; + suitBonus-=11/*12*//*13*//*18*/; } + else if ((posPoint->winner[suit].hand==lho[q])&& + (posPoint->secondBest[suit].hand==partner[q])) + suitBonus+=30/*28*//*22*/; - if ((trump!=4)&&(suit!=trump)&&(suitCount==1)&& + if ((suit!=trump)&&(suitCount==1)&& (posPoint->length[q][trump]>0)&& (posPoint->length[partner[q]][suit]>1)&& (posPoint->winner[suit].hand==partner[q])) - suitBonus+=16; + suitBonus+=21/*24*//*19*//*16*/; if (suitCountLH!=0) countLH=(suitCountLH<<2); @@ -3461,17 +3840,18 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, else countRH=depth+4; - suitWeightDelta=suitBonus-((countLH+countRH)<<5)/15; + suitWeightDelta=suitBonus- + ((countLH+countRH)<<5)/(12/*15*/); if (posPoint->winner[suit].rank==mp->rank) { - if ((trump!=4)&&(suit!=trump)) { + if ((suit!=trump)) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) { if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->length[lho[first]][trump]==0))&& ((posPoint->length[rho[first]][suit]!=0)|| (posPoint->length[rho[first]][trump]==0))) - winMove=TRUE; + winMove=TRUE; } else if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->rankInSuit[partner[first]][trump]> @@ -3487,7 +3867,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, else if (posPoint->rankInSuit[partner[first]][suit] > (posPoint->rankInSuit[lho[first]][suit] | posPoint->rankInSuit[rho[first]][suit])) { - if ((trump!=4) && (suit!=trump)) { + if (suit!=trump) { if (((posPoint->length[lho[first]][suit]!=0)|| (posPoint->length[lho[first]][trump]==0))&& ((posPoint->length[rho[first]][suit]!=0)|| @@ -3497,7 +3877,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, else winMove=TRUE; } - else if ((trump!=4)&&(suit!=trump)) { + else if (suit!=trump) { if ((posPoint->length[partner[first]][suit]==0)&& (posPoint->length[partner[first]][trump]!=0)) { if ((posPoint->length[lho[first]][suit]==0)&& @@ -3513,7 +3893,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, (posPoint->length[lho[first]][trump]!=0)) { if (posPoint->rankInSuit[partner[first]][trump] > posPoint->rankInSuit[lho[first]][trump]) - winMove=TRUE; + winMove=TRUE; } else if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) { @@ -3529,72 +3909,68 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, if (winMove) { if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) - weight=suitWeightDelta+40-(mp->rank); + weight=suitWeightDelta+41/*44*//*41*//*51*//*40*/+rRank; else if (posPoint->winner[suit].hand==first) { if ((posPoint->secondBest[suit].hand!=-1)&& (posPoint->secondBest[suit].hand==partner[first])) - weight=suitWeightDelta+50-(mp->rank); + weight=suitWeightDelta+46/*45*//*63*//*53*//*50*/+rRank; else if (posPoint->winner[suit].rank==mp->rank) weight=suitWeightDelta+31; else - weight=suitWeightDelta+19-(mp->rank); + weight=suitWeightDelta+4/*22*//*21*/+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* If partner has winning card */ if (posPoint->secondBest[suit].hand==first) - weight=suitWeightDelta+50-(mp->rank); + weight=suitWeightDelta+34/*35*//*46*//*50*/+rRank; else - weight=suitWeightDelta+35-(mp->rank); + weight=suitWeightDelta+25/*35*/+rRank; } else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+40/*-(mp->rank)*/; + weight=suitWeightDelta+39/*51*//*39*//*40*/; else - weight=suitWeightDelta+30-(mp->rank); + weight=suitWeightDelta+7/*19*//*29*/+rRank; - if ((localVar[thrId].bestMove[depth].suit==mp->suit)&& + if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) - weight+=52; - else if ((localVar[thrId].bestMoveTT[depth].suit==mp->suit)&& + weight+=53/*50*//*52*/; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=11; - /*else if (localVar[thrId].bestMove[depth].suit==mp->suit) - weight+=10;*/ + weight+=13/*15*//*12*//*11*/; } else { if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) - weight=suitWeightDelta+29-(mp->rank); + weight=suitWeightDelta+rRank-2; else if (posPoint->winner[suit].hand==first) { if ((posPoint->secondBest[suit].rank!=0)&& (posPoint->secondBest[suit].hand==partner[first])) - weight=suitWeightDelta+44-(mp->rank); + weight=suitWeightDelta+34/*31*//*35*//*20*/+rRank; else if (posPoint->winner[suit].rank==mp->rank) - weight=suitWeightDelta+25; + weight=suitWeightDelta+36/*25*/; else - weight=suitWeightDelta+13-(mp->rank); + weight=suitWeightDelta-14/*15*//*18*//*12*/+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* If partner has winning card */ if (posPoint->secondBest[suit].hand==first) - weight=suitWeightDelta+44-(mp->rank); + weight=suitWeightDelta+28/*27*/+rRank; else - weight=suitWeightDelta+29-(mp->rank); + weight=suitWeightDelta+28/*34*/+rRank; } else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+29; + weight=suitWeightDelta+31; else - weight=suitWeightDelta+13-(mp->rank); + weight=suitWeightDelta+13-(mp->rank); - if ((localVar[thrId].bestMove[depth].suit==mp->suit)&& + if ((localVar[thrId].bestMove[depth].suit==suit)&& (localVar[thrId].bestMove[depth].rank==mp->rank)) weight+=20; - else if ((localVar[thrId].bestMoveTT[depth].suit==mp->suit)&& + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=9; - /*else if (localVar[thrId].bestMove[depth].suit==mp->suit) - weight+=10;*/ + weight+=(3/*4*//*10*//*9*/); } break; @@ -3605,7 +3981,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, if (bitMapRank[mp->rank]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) { - if ((trump!=4) && (suit!=trump)) { + if (suit!=trump) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) winMove=TRUE; @@ -3621,7 +3997,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, else if (posPoint->rankInSuit[rho[first]][suit]> (bitMapRank[posPoint->move[depth+1].rank] | posPoint->rankInSuit[partner[first]][suit])) { - if ((trump!=4) && (suit!=trump)) { + if (suit!=trump) { if ((posPoint->length[partner[first]][suit]!=0)|| (posPoint->length[partner[first]][trump]==0)) winMove=TRUE; @@ -3633,7 +4009,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, (posPoint->rankInSuit[rho[first]][suit] | posPoint->rankInSuit[partner[first]][suit] | bitMapRank[mp->rank])) { - if ((trump!=4) && (suit!=trump)) { + if (suit!=trump) { if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) { if ((posPoint->length[partner[first]][suit]!=0)|| @@ -3646,16 +4022,16 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, } } else { /* winnerHand is partner to first */ - if ((trump!=4) && (suit!=trump)) { + if (suit!=trump) { if ((posPoint->length[rho[first]][suit]==0)&& (posPoint->length[rho[first]][trump]!=0)) - winMove=TRUE; + winMove=TRUE; } } } else { /* Leading suit differs from suit played by LHO */ - if ((trump!=4) && (suit==trump)) { + if (suit==trump) { if (posPoint->length[partner[first]][leadSuit]!=0) winMove=TRUE; else if (bitMapRank[mp->rank]> @@ -3667,7 +4043,7 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, posPoint->rankInSuit[partner[first]][trump])) winMove=TRUE; } - else if ((trump!=4) && (leadSuit!=trump)) { + else if (leadSuit!=trump) { /* Neither suit nor leadSuit is trump */ if (posPoint->length[partner[first]][leadSuit]!=0) { if (posPoint->rankInSuit[rho[first]][leadSuit] > @@ -3703,79 +4079,95 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit */ if (winMove) { if (!notVoidInSuit) { - if ((trump!=4) && (suit==trump)) - weight=25/*30*/-(mp->rank)+suitAdd; + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(42/*36*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=2; + + if (suit==trump) + weight=25/*23*/-(mp->rank)+suitAdd; else weight=60-(mp->rank)+suitAdd; /* Better discard than ruff since rho - wins anyway */ + wins anyway */ } else if (k > bitMapRank[mp->rank]) - weight=45-(mp->rank); /* If lowest card for partner to leading hand - is higher than lho played card, playing as low as - possible will give the cheapest win */ + weight=38/*41*/+rRank; + /* If lowest card for partner to leading hand + is higher than lho played card, playing as low as + possible will give the cheapest win */ else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& - (posPoint->rankInSuit[first][leadSuit] > ll)) - weight=60-(mp->rank); /* If rho has a card in the leading suit that - is higher than the trick leading card but lower - than the highest rank of the leading hand, then - lho playing the lowest card will be the cheapest - win */ - else if (mp->rank > posPoint->move[depth+1].rank) { + (posPoint->rankInSuit[first][leadSuit] > ll)) + weight=37/*40*/+rRank; + /* If rho has a card in the leading suit that + is higher than the trick leading card but lower + than the highest rank of the leading hand, then + lho playing the lowest card will be the cheapest win */ + + else if (mp->rank > posPoint->move[depth+1].rank) { if (bitMapRank[mp->rank] < ll) weight=75-(mp->rank); /* If played card is lower than any of the cards of - rho, it will be the cheapest win */ + rho, it will be the cheapest win */ else if (bitMapRank[mp->rank] > kk) weight=70-(mp->rank); /* If played card is higher than any cards at partner - of the leading hand, rho can play low, under the - condition that he has a lower card than lho played */ + of the leading hand, rho can play low, under the + condition that he has a lower card than lho played */ else { if (mp->sequence) - weight=60-(mp->rank); + weight=62/*63*//*60*/-(mp->rank); else - weight=45-(mp->rank); + weight=51/*45*/-(mp->rank); } } else if (posPoint->length[rho[first]][leadSuit]>0) { if (mp->sequence) - weight=50-(mp->rank); /* Playing a card in a sequence may promote a winner */ + weight=47/*50*/-(mp->rank); /* Playing a card in a sequence may promote a winner */ + /* Insensistive */ else - weight=45-(mp->rank); + weight=45-(mp->rank); } else - weight=45-(mp->rank); + weight=39/*45*/-(mp->rank); } else { - if (!notVoidInSuit) { - if ((trump!=4) && (suit==trump)) { - weight=15-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(33/*36*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(1/*2*/); + + if (suit==trump) { + weight=16/*15*/-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick costly for the opponents */ } else - weight=-(mp->rank)+suitAdd; + weight=-6-(mp->rank)+suitAdd; } else if ((k > bitMapRank[mp->rank])|| - (l > bitMapRank[mp->rank])) - weight=-(mp->rank); /* If lowest rank for either partner to leading hand - or rho is higher than played card for lho, - lho should play as low card as possible */ + (l > bitMapRank[mp->rank])) + weight=-10/*-9*/+rRank; + /* If lowest rank for either partner to leading hand + or rho is higher than played card for lho, + lho should play as low card as possible */ + else if (mp->rank > posPoint->move[depth+1].rank) { if (mp->sequence) - weight=20-(mp->rank); + weight=22/*19*/-(mp->rank); else weight=10-(mp->rank); } else - weight=-(mp->rank); + weight=-17+rRank; } break; + case 2: leadSuit=posPoint->move[depth+2].suit; if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) { if (suit==leadSuit) { - if ((trump!=4) && (leadSuit!=trump)) { + if (leadSuit!=trump) { if (((posPoint->length[rho[first]][suit]!=0)|| (posPoint->length[rho[first]][trump]==0))&& (bitMapRank[mp->rank] > @@ -3802,57 +4194,60 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, < bitMapRank[posPoint->move[depth+2].rank]) winMove=TRUE; } - else if (trump==4) - winMove=TRUE; - else if ((trump!=4) && (leadSuit==trump)) + else if (leadSuit==trump) winMove=TRUE; - else if ((trump!=4) && (leadSuit!=trump) && + else if ((leadSuit!=trump) && (posPoint->length[rho[first]][trump]==0)) winMove=TRUE; } if (winMove) { if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(42/*36*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(3/*2*/); + if (posPoint->high[depth+1]==first) { - if ((trump!=4) && (suit==trump)) - weight=30-(mp->rank)+suitAdd; /* Ruffs partner's winner */ + if (suit==trump) + weight=30-(mp->rank)+suitAdd; /* Ruffs partner's winner */ else - weight=60-(mp->rank)+suitAdd; + weight=60-(mp->rank)+suitAdd; } else if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) /* Own hand on top by ruffing */ - weight=70-(mp->rank)+suitAdd; - else if ((trump!=4) && (suit==trump)) - /* Discard a trump but still losing */ - weight=15-(mp->rank)+suitAdd; - else - weight=30-(mp->rank)+suitAdd; + weight=70-(mp->rank)+suitAdd; } else - weight=60-(mp->rank); + weight=60-(mp->rank); } else { if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/36; + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(3/*2*/); + if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) /* Own hand on top by ruffing */ - weight=40-(mp->rank)+suitAdd; - else if ((trump!=4) && (suit==trump)) + weight=40-(mp->rank)+suitAdd; + else if (suit==trump) /* Discard a trump but still losing */ - weight=-15-(mp->rank)+suitAdd; + weight=-/*33*/36+rRank+suitAdd; else weight=-(mp->rank)+suitAdd; } else { if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) { if (mp->rank==posPoint->secondBest[leadSuit].rank) - weight=25/*35*/; + weight=25; else if (mp->sequence) - weight=20/*30*/-(mp->rank); + weight=21/*20*/-(mp->rank); else - weight=10/*20*/-(mp->rank); + weight=10-(mp->rank); } else - weight=-10/*0*/-(mp->rank); + weight=-10-(mp->rank); } } @@ -3860,47 +4255,53 @@ int WeightAlloc(struct pos * posPoint, struct moveType * mp, int depth, case 3: if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(27/*36*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(2/*0*//*2*/); + if ((posPoint->high[depth+1])==lho[first]) { /* If the current winning move is given by the partner */ - if ((trump!=4) && (suit==trump)) + if (suit==trump) /* Ruffing partners winner? */ - weight=14-(mp->rank)+suitAdd; + weight=2/*17*/-(mp->rank)+suitAdd; else weight=30-(mp->rank)+suitAdd; } else if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) /* Own hand ruffs */ - weight=30-(mp->rank)+suitAdd; + weight=28/*27*/+rRank+suitAdd; else if (suit==trump) - weight=-(mp->rank); + weight=-13+rRank; else weight=14-(mp->rank)+suitAdd; } else if ((posPoint->high[depth+1])==(lho[first])) { /* If the current winning move is given by the partner */ - if ((trump!=4) && (suit==trump)) + if (suit==trump) /* Ruffs partners winner */ - weight=24-(mp->rank); + weight=11+rRank; else - weight=30-(mp->rank); + weight=17+rRank; } else if (WinningMove(mp, &(posPoint->move[depth+1]), thrId)) /* If present move is superior to current winning move and the current winning move is not given by the partner */ - weight=30-(mp->rank); + weight=22+rRank; else { /* If present move is not superior to current winning move and the current winning move is not given by the partner */ - if ((trump!=4) && (suit==trump)) + if (suit==trump) /* Ruffs but still loses */ - weight=-(mp->rank); + weight=-13+rRank; else - weight=14-(mp->rank); + weight=1+rRank; } } return weight; } + /* Shell-1 */ /* K&R page 62: */ /*void shellSort(int n, int depth) { @@ -4162,17 +4563,17 @@ struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType /* Update SOP node with new values for upper and lower bounds. */ - if ((posPoint->lbound > nodep->lbound) || + if ((posPoint->lbound > nodep->lbound) || (nodep->lbound==-1)) - nodep->lbound=posPoint->lbound; - if ((posPoint->ubound < nodep->ubound) || + nodep->lbound=posPoint->lbound; + if ((posPoint->ubound < nodep->ubound) || (nodep->ubound==-1)) - nodep->ubound=posPoint->ubound; + nodep->ubound=posPoint->ubound; - nodep->bestMoveSuit=posPoint->bestMoveSuit; + nodep->bestMoveSuit=posPoint->bestMoveSuit; nodep->bestMoveRank=posPoint->bestMoveRank; - return nodep; + return nodep; } @@ -4641,8 +5042,6 @@ int NextMove(struct pos *posPoint, int depth, int thrId) { } return FALSE; } - - /* New: */ else { while (localVar[thrId].movePly[depth].current<=localVar[thrId].movePly[depth].last-1) { localVar[thrId].movePly[depth].current++; @@ -4692,11 +5091,11 @@ int DumpInput(int errCode, struct deal dl, int target, fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n", k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]); for (i=0; i<=3; i++) - for (j=0; j<=3; j++) { + for (j=0; j<=3; j++) { fprintf(fp, "index1=%d index2=%d remainCards=%d\n", i, j, dl.remainCards[i][j]); - ranks[i][j]=dl.remainCards[i][3-j]>>2; - } + ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2; + } fprintf(fp, "\n"); fprintf(fp, "target=%d\n", target); fprintf(fp, "solutions=%d\n", solutions); @@ -4998,7 +5397,7 @@ DWORD CALLBACK SolveChunkDDtable (void *) { param.solvedp->solvedBoard[j+k]=fut[j+k]; } else { - return 0; + return res/*0*/; } } } @@ -5025,7 +5424,7 @@ int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp, timeOut=FALSE; if (bop->noOfBoards > MAXNOOFBOARDS) - return -4; + return -101; param.timeSupervision=timeSupervision; if (timeSupervision) { @@ -5036,7 +5435,7 @@ int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp, solveAllEvents[k]=CreateEvent(NULL, FALSE, FALSE, 0); if (solveAllEvents[k]==0) { errCode=GetLastError(); - return -1; + return -102; } } @@ -5047,9 +5446,9 @@ int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp, for (k=0; knoOfBoards > MAXNOOFBOARDS) + return -101; for (i=0; isolvedBoard[i].cards=0; @@ -5102,12 +5504,12 @@ int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp, solvedp->solvedBoard[k]=fut[k]; } else - fail=TRUE; + fail=res; } } - if (fail) - return 0; + if (fail!=1) + return fail; solvedp->noOfBoards=0; for (i=0; i=3) + return 0; + + if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n')) + first=0; + else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e')) + first=1; + else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s')) + first=2; + else + first=3; + + bp++; + bp++; + + handRelFirst=0; suitInHand=0; + + while (bp<80) { + card=IsCard(dealBuff[bp]); + if (card) { + switch (first) { + case 0: + hand=handRelFirst; + break; + case 1: + if (handRelFirst==0) + hand=1; + else if (handRelFirst==3) + hand=0; + else + hand=handRelFirst+1; + break; + case 2: + if (handRelFirst==0) + hand=2; + else if (handRelFirst==1) + hand=3; + else + hand=handRelFirst-2; + break; + default: + if (handRelFirst==0) + hand=3; + else + hand=handRelFirst-1; + } + + remainCards[hand][suitInHand]|=(bitMapRank[card]<<2); + + } + else if (dealBuff[bp]=='.') + suitInHand++; + else if (dealBuff[bp]==' ') { + handRelFirst++; + suitInHand=0; + } + bp++; + } + return 1; +} + +int IsCard(char cardChar) { + switch (cardChar) { + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'T': + return 10; + case 'J': + return 11; + case 'Q': + return 12; + case 'K': + return 13; + case 'A': + return 14; + case 't': + return 10; + case 'j': + return 11; + case 'q': + return 12; + case 'k': + return 13; + case 'a': + return 14; + default: + return 0; + } + } + +#ifdef PBN +int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, + int solutions, int mode, struct futureTricks *futp, int thrId) { + + int res, k; + struct deal dl; + int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); + + if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1) + return -99; + + for (k=0; k<=2; k++) { + dl.currentTrickRank[k]=dlpbn.currentTrickRank[k]; + dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k]; + } + dl.first=dlpbn.first; + dl.trump=dlpbn.trump; + + res=SolveBoard(dl, target, solutions, mode, futp, thrId); + + return res; +} + +int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) { + struct ddTableDeal tableDeal; + int res; + if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) + return -99; + res=CalcDDtable(tableDeal, tablep); + return res; +} +#endif diff --git a/dll.h b/dll.h index d59711e7..a68fbc58 100644 --- a/dll.h +++ b/dll.h @@ -30,6 +30,9 @@ #define DDS_VERSION 20101 /* Version 2.1.1. Allowing for 2 digit minor versions */ + +#define PBN + /*#define BENCH*/ #include @@ -51,8 +54,6 @@ #define SEARCHSIZE 1 #endif -#define CANCELCHECK 200000 - #if defined(INFINITY) # undef INFINITY #endif @@ -95,9 +96,7 @@ All hand identities are given as struct gameInfo { /* All info of a particular deal */ - /*int vulnerable;*/ int declarer; - /*int contract;*/ int leadHand; int leadSuit; int leadRank; @@ -148,6 +147,15 @@ struct deal { }; +struct dealPBN { + int trump; + int first; + int currentTrickSuit[3]; + int currentTrickRank[3]; + char remainCards[80]; +}; + + struct pos { unsigned short int rankInSuit[4][4]; /* 1st index is hand, 2nd index is suit id */ @@ -209,6 +217,7 @@ struct evalType { struct relRanksType { int aggrRanks[4]; int winMask[4]; + char relRank[15][4]; }; struct adaptWinRanksType { @@ -258,6 +267,10 @@ struct ddTableDeal { unsigned int cards[4][4]; }; +struct ddTableDealPBN { + char cards[80]; +}; + struct ddTableResults { int resTable[5][4]; }; @@ -295,12 +308,12 @@ struct localVarType { struct moveType bestMove[50]; struct moveType bestMoveTT[50]; struct winCardType temp_win[5]; - int hiwinSetSize; + /*int hiwinSetSize; int hinodeSetSize; int hilenSetSize; int MaxnodeSetSize; int MaxwinSetSize; - int MaxlenSetSize; + int MaxlenSetSize;*/ int nodeSetSizeLimit; int winSetSizeLimit; int lenSetSizeLimit; @@ -355,7 +368,6 @@ extern struct moveType forbiddenMoves[14]; /* Initial depth moves that will be excluded from the search */ extern struct moveType initialMoves[4]; extern struct moveType highMove; -extern struct moveType * bestMove; extern struct winCardType **pw; extern struct nodeCardsType **pn; extern struct posSearchType **pl; @@ -363,7 +375,6 @@ extern struct posSearchType **pl; extern int * highestRank; extern int * counttable; extern struct adaptWinRanksType * adaptWins; -extern struct winCardType * temp_win; extern unsigned short int bitMapRank[16]; extern unsigned short int relRankInSuit[4][4]; extern int sum; @@ -402,9 +413,6 @@ extern int suppressTTlog; extern unsigned char suitChar[4]; extern unsigned char rankChar[15]; extern unsigned char handChar[4]; -extern int cancelOrdered; -extern int cancelStarted; -extern int threshold; extern unsigned char cardRank[15], cardSuit[5], cardHand[4]; extern unsigned char cardSuitSds[5]; extern struct handStateType handState; @@ -424,9 +432,20 @@ extern int suppressTTlog; EXTERN_C DLLEXPORT int STDCALL SolveBoard(struct deal dl, int target, int solutions, int mode, struct futureTricks *futp, int threadIndex); +#ifdef PBN +EXTERN_C DLLEXPORT int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, + int solutions, int mode, struct futureTricks *futp, int thrId); +#endif + EXTERN_C DLLEXPORT int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep); +#ifdef PBN +EXTERN_C DLLEXPORT int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, + struct ddTableResults * tablep); +#endif + + void InitStart(int gb_ram, int ncores); void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId); void InitSearch(struct pos * posPoint, int depth, diff --git a/release_notes.txt b/release_notes.txt index a79ecf12..e796da87 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -276,6 +276,29 @@ physical memory. The configuration is either done automatically by reading out the physical memory size by the operating system, or by supplying parameter values in InitStart. + +Release Notes DDS 2.1.2 +----------------------- +2 new callable functions have been added: +SolveBoardPBN and CalcDDtablePBN. +They both accept PBN format for the remaining cards in the deal information +instead of the bit codes. + +Code improvements have been done concerning quick tricks detection and move +ordering. 2.1.2 is about 10% faster than 2.1.1. + + +Release Notes DDS 1.1.12 +------------------------ +2 new callable functions have been added: +SolveBoardPBN and CalcDDtablePBN. +They both accept PBN format for the remaining cards in the deal information +instead of the bit codes. + +Code improvements have been done concerning quick tricks detection and move +ordering. 1.1.12 is about 15-20% faster than 1.1.11. + +