From 060e1e1dfc34c06b8cb436e1b920474406269308 Mon Sep 17 00:00:00 2001 From: Bo Haglund Date: Sun, 30 Mar 2014 23:47:20 -0400 Subject: [PATCH] historical commit dds 1.1.19 --- DLL-dds_1118_m.rtf => DLL-dds_1119_m.rtf | 29 +- ...s_1118plus_a.rtf => DLL-dds_1119plus_b.rtf | 184 +- dds.cpp | 1521 ++++++++++++----- dll.h | 26 +- release_notes.txt | 5 + 5 files changed, 1292 insertions(+), 473 deletions(-) rename DLL-dds_1118_m.rtf => DLL-dds_1119_m.rtf (96%) rename DLL-dds_1118plus_a.rtf => DLL-dds_1119plus_b.rtf (77%) diff --git a/DLL-dds_1118_m.rtf b/DLL-dds_1119_m.rtf similarity index 96% rename from DLL-dds_1118_m.rtf rename to DLL-dds_1119_m.rtf index da163c2e..4768fa25 100644 --- a/DLL-dds_1118_m.rtf +++ b/DLL-dds_1119_m.rtf @@ -42,9 +42,9 @@ heading 2;}{\s3\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\li \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1053\langfe1053\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1053\langfenp1053 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\kerning32\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 Rubrik 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\ai\af0\afs28 \ltrch\fcs0 \b\i\fs28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 Rubrik 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \ab\af0\afs26 \ltrch\fcs0 \b\fs26\loch\f31502\hich\af31502\dbch\af31501 -\sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Rubrik 3 Char;}}{\*\rsidtbl \rsid812199\rsid1927002\rsid10306343\rsid10776626}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0 -\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy22\hr23\min26}{\revtim\yr2013\mo2\dy23\hr12\min44}{\version4}{\edmins0}{\nofpages4}{\nofwords1213}{\nofchars6432}{\nofcharsws7630}{\vern49275}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.co -m/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect +\sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Rubrik 3 Char;}}{\*\rsidtbl \rsid812199\rsid1927002\rsid5917127\rsid6319433\rsid10306343\rsid10776626}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1 +\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy22\hr23\min26}{\revtim\yr2014\mo3\dy31\hr20\min58}{\version6}{\edmins0}{\nofpages4}{\nofwords1213}{\nofchars6433}{\nofcharsws7631}{\vern49167}}{\*\xmlnstbl {\xmlns1 ht +tp://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120 \dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot1927002 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\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 )}} @@ -55,25 +55,25 @@ m/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt141 \par \hich\af1\dbch\af31505\loch\f1 Latest DLL issue with this description is available at }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid1927002 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 -0000a5ab00000020}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\ul\cf2\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { +0000a5ab000000206865}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\ul\cf2\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \par \par \par }\pard\plain \ltrpar\s2\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 Short description of the DLL functions supported in Do}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 -\b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid1927002\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 uble Dummy Problem Solver 1.1.1}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid10306343 -\hich\af1\dbch\af31505\loch\f1 8}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 +\b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid1927002\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 uble Dummy Problem Solver 1.1.1}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid5917127 +\hich\af1\dbch\af31505\loch\f1 9}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 Callable functions \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 -\par \hich\af1\dbch\af31505\loch\f1 extern "\hich\af1\dbch\af31505\loch\f1 C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, +\par \hich\af1\dbch\af31505\loch\f1 extern \hich\af1\dbch\af31505\loch\f1 "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, \par \hich\af1\dbch\af31505\loch\f1 int solutions, int mode, struct futureTricks *futp); \par \par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, -\par \hich\af1\dbch\af31505\loch\f1 int solutions, int mode,\hich\af1\dbch\af31505\loch\f1 struct futureTricks *futp); +\par \hich\af1\dbch\af31505\loch\f1 int solutions, int mode\hich\af1\dbch\af31505\loch\f1 , struct futureTricks *futp); \par \par \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 @@ -83,8 +83,8 @@ HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \par \hich\af1\dbch\af31505\loch\f1 Before SolveBoard can be called, a structure of type "futureTricks" must be declared. \par \par }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 SolveBoard}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line S\hich\af1\dbch\af31505\loch\f1 -tatus codes: +\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line \hich\af1\dbch\af31505\loch\f1 +Status codes: \par \hich\af1\dbch\af31505\loch\f1 1=No fault, \par \hich\af1\dbch\af31505\loch\f1 -1=Unknown fault, \par \hich\af1\dbch\af31505\loch\f1 -2=No of cards = 0, @@ -165,8 +165,9 @@ olveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads. int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 \hich\af1\dbch\af31505\loch\f1 \hich\f1 (=2) and 8192 (King=rank 13). When there are several \'94\loch\f1 \hich\f1 equals\'94\loch\f1 \hich\f1 , the value is the sum of each \'94\loch\f1 \hich\f1 equal\'94\loch\f1 . *}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 /}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 -\par \hich\af1\dbch\af31505\loch\f1 int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 -\hich\af0\dbch\af31505\loch\f0 +\par \hich\af1\dbch\af31505\loch\f1 int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid6319433 \hich\af1\dbch\af31505\loch\f1 r}{ +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af1\dbch\af31505\loch\f1 of tricks */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 +\f0\fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \hich\af0\dbch\af31505\loch\f0 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\lang1033\langfe1053\langnp1033\insrsid812199\charrsid1927002 \}\hich\af1\dbch\af31505\loch\f1 ; \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \lang1033\langfe1053\langnp1033\insrsid812199 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1053\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1053\langfenp1053 {\rtlch\fcs1 @@ -334,8 +335,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000602d -4f27bb11ce01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000505a +1d34134dcf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DLL-dds_1118plus_a.rtf b/DLL-dds_1119plus_b.rtf similarity index 77% rename from DLL-dds_1118plus_a.rtf rename to DLL-dds_1119plus_b.rtf index 4b343fcd..47af55ed 100644 --- a/DLL-dds_1118plus_a.rtf +++ b/DLL-dds_1119plus_b.rtf @@ -40,27 +40,28 @@ \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1053\langfe1053\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1053\langfenp1053 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\lang1033\langfe0\kerning32\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink1 \slocked \spriority9 Rubrik 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\ai\af0\afs28 \ltrch\fcs0 \b\i\fs28\lang1033\langfe0\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 Rubrik 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \ab\af0\afs26 \ltrch\fcs0 -\b\fs26\lang1033\langfe0\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Rubrik 3 Char;}}{\*\rsidtbl \rsid4538894\rsid4542728\rsid6650094\rsid8617117\rsid16130314\rsid16470149\rsid16608682 -\rsid16655487}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy21\hr14\min22}{\revtim\yr2013\mo2\dy23\hr12\min45}{\version7} -{\edmins31}{\nofpages3}{\nofwords1247}{\nofchars6612}{\nofcharsws7844}{\vern49275}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect +\b\fs26\lang1033\langfe0\loch\f31502\hich\af31502\dbch\af31501\langnp1033\langfenp0 \sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Rubrik 3 Char;}}{\*\rsidtbl \rsid535025\rsid1201643\rsid4538894\rsid4542728\rsid5522304\rsid5969439\rsid6650094 +\rsid8617117\rsid14824249\rsid16130314\rsid16470149\rsid16608682\rsid16655487}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund} +{\creatim\yr2012\mo10\dy21\hr14\min22}{\revtim\yr2014\mo4\dy1\min13}{\version12}{\edmins38}{\nofpages5}{\nofwords1733}{\nofchars9190}{\nofcharsws10902}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120 \dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot4538894 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\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 \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid16470149 \hich\af1\dbch\af31505\loch\f1 Bo Haglund, Bob Richardson -\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid4538894\charrsid16470149 \hich\af1\dbch\af31505\loch\f1 Rev }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid8617117 \hich\af1\dbch\af31505\loch\f1 A}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\insrsid16608682 \hich\af1\dbch\af31505\loch\f1 , 2013-02-19}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid16470149 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid4538894\charrsid16470149 \hich\af1\dbch\af31505\loch\f1 Rev }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid535025 \hich\af1\dbch\af31505\loch\f1 B, 2014-03-30}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\fs20\insrsid6650094\charrsid16470149 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 Latest DLL issue with this description is available at }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\lang1053\langfe1053\langnp1053\insrsid4538894 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 -0000a5ab00000000005a}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\ul\cf2\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 +0000a5ab00000000005a070000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\ul\cf2\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \par \par \par }\pard\plain \ltrpar\s2\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 Short description of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid16655487 -\hich\af1\dbch\af31505\loch\f1 ouble Dummy Problem Solver }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid16130314 \hich\af1\dbch\af31505\loch\f1 1.1.18}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid8617117 +\hich\af1\dbch\af31505\loch\f1 ouble Dummy Problem Solver }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid5522304 \hich\af1\dbch\af31505\loch\f1 1.1.19}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid8617117 \hich\af1\dbch\af31505\loch\f1 plus}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\ul\cf1\insrsid6650094\charrsid4538894 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 @@ -68,28 +69,35 @@ Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\l \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 Callable functions \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\par \hich\af1\dbch\af31505\loch\f1 ext\hich\af1\dbch\af31505\loch\f1 ern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, +\par \hich\af1\dbch\af31505\loch\f1 ex\hich\af1\dbch\af31505\loch\f1 tern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, \par \hich\af1\dbch\af31505\loch\f1 int solutions, int mode, struct futureTricks *futp, }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117 0}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 ); \par \par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, -\par \hich\af1\dbch\af31505\loch\f1 int solutions, \hich\af1\dbch\af31505\loch\f1 int mode, struct futureTricks *futp, }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117 0}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 ); +\par \hich\af1\dbch\af31505\loch\f1 int solutions, int mode, struct futureTricks *futp, }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117 0}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 +\hich\af1\dbch\af31505\loch\f1 ); \par \par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, \line struct ddTableResults * tablep); \par -\par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN\line \hich\af1\dbch\af31505\loch\f1 tableDealPBN, struct ddTableResults * tablep); -\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094 +\par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(stru\hich\af1\dbch\af31505\loch\f1 ct ddTableDealPBN\line tableDealPBN, struct ddTableResults * tablep);}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\fs20\cf1\insrsid6650094 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid1201643 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1201643 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid1201643\charrsid1201643 \hich\af1\dbch\af31505\loch\f1 +extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); +\par +\par \hich\af1\dbch\af31505\loch\f1 extern "C" __declspec(dll\hich\af1\dbch\af31505\loch\f1 import) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, +\par \hich\af1\dbch\af31505\loch\f1 struct ddTableResults * tablep, int vulnerable, struct parResults *presp); }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid1201643\charrsid4538894 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117\charrsid4538894 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 SolveBoard \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\par \hich\af1\dbch\af31505\loch\f1 Before SolveBoard can be called, a structure of type "futureTricks" must be declared. }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094 +\par \hich\af1\dbch\af31505\loch\f1 Before SolveBoard can be called, a structure of type "futureTricks" must be declar\hich\af1\dbch\af31505\loch\f1 ed. }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 SolveBoard}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 - returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTric\hich\af1\dbch\af31505\loch\f1 ks" type structure.\line Status codes: + returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure.\line Status codes: \par \hich\af1\dbch\af31505\loch\f1 1=No fault, \par \hich\af1\dbch\af31505\loch\f1 -1=Unknown fault, \par \hich\af1\dbch\af31505\loch\f1 -2=No of cards = 0, @@ -101,71 +109,72 @@ Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\l \par \hich\af1\dbch\af31505\loch\f1 -9=solutions > 3, \par \hich\af1\dbch\af31505\loch\f1 -10=No of cards > 52 \par \hich\af1\dbch\af31505\loch\f1 -11=Not used -\par \hich\af1\dbch\af31505\loch\f1 -12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. +\par \hich\af1\dbch\af31505\loch\f1 -12=Suit or rank value out of range for deal.currentTrick\hich\af1\dbch\af31505\loch\f1 Suit or deal.currentTrickRank. \par \hich\af1\dbch\af31505\loch\f1 -13=Card already played in the current trick is also defined as a remaining card to play. -\par \hich\af1\dbch\af31505\loch\f1 -14=Wrong number}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117 \hich\af1\dbch\af31505\loch\f1 of rem\hich\af1\dbch\af31505\loch\f1 aining cards for a hand. +\par \hich\af1\dbch\af31505\loch\f1 -14=Wrong number}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid8617117 \hich\af1\dbch\af31505\loch\f1 of remaining cards for a hand. \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \line \hich\af1\dbch\af31505\loch\f1 \line \hich\f1 Structure \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 deal}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 defines all data needed to describe the deal to be analyzed. -\par \hich\af1\dbch\af31505\loch\f1 struct deal \{}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 +\par \hich\af1\dbch\af31505\loch\f1 struc\hich\af1\dbch\af31505\loch\f1 t deal \{}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int trump; /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3, NT=4 */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 -\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int first\hich\af1\dbch\af31505\loch\f1 ; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\rtlch\fcs1 -\af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 -\par \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in the order played */ +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 +\f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 +\par \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int currentTrickSuit[3]; /\hich\af1\dbch\af31505\loch\f1 * 0-2 for up to 3 cards in the order played */ \par \hich\af1\dbch\af31505\loch\f1 int currentTrickRank[3]; /* 2-14 for up to 3 cards */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 unsigned int remainCards[4][4]; /* 1}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\super\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 st}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 index hand (0-3), 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\super\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 \hich\f1 index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2, \'85\'85\'85\loch\f1 -. bit 14=rank 14, bit 15=0}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 -for cards remaining after already played cards (cards already played to the current trick are not included in this bitstri\hich\af1\dbch\af31505\loch\f1 ng). \line The decimal value for a card then range between 4 (=rank 2) and 16384 (Ace=rank 14). */} +. bit\hich\af1\dbch\af31505\loch\f1 14=rank 14, bit 15=0}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 +\hich\af1\dbch\af31505\loch\f1 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). */} {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \}\hich\af1\dbch\af31505\loch\f1 ;}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par -\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 Parameter \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 target}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 is the number of tricks to be won by the side to play, -1 means that the program}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 -\af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 shall find the maximum number. For equivalent cards \hich\af1\dbch\af31505\loch\f1 only the highest is returned. +\par \hich\af1\dbch\af31505\loch\f1 Parameter\hich\af1\dbch\af31505\loch\f1 \hich\f1 \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 target}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 is the number of tricks to be won by the side to play, -1 means that the program}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 +\hich\af0\dbch\af31505\loch\f0 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 shall find the maximum number. For equivalent cards only the highest is returned. \par \line \hich\af1\dbch\af31505\loch\f1 \hich\f1 Parameter \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 solutions}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 defines how many card solutions that SolveBoard must return: -\par \hich\af1\dbch\af31505\loch\f1 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. \hich\af1\dbch\af31505\loch\f1 Otherwise, score \hich\f1 \endash \loch\f1 -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 \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 target=0, solutions=1: Returns only one of the cards legal to play with sco\hich\af1\dbch\af31505\loch\f1 -re set to 0.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \line \hich\af1\dbch\af31505\loch\f1 - 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 \hich\f1 \endash \loch\f1 -1 if target cannot be reached, or score 0 for \hich\af1\dbch\af31505\loch\f1 all cards legal to play if no tricks can be won.\line target \hich\f1 \endash \loch\f1 1, solutions=2: Return all optimum cards with their scores. +\fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\hich\af1\dbch\af31505\loch\f1 defines how many card solutions that SolveBoard must return: +\par \hich\af1\dbch\af31505\loch\f1 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 \hich\f1 \endash \loch\f1 1 is returned if target cannot be r +\hich\af1\dbch\af31505\loch\f1 eached, 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 \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.}{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \line \hich\af1\dbch\af31505\loch\f1 target 1-13, solutions=2: Return all \hich\af1\dbch\af31505\loch\f1 +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 \hich\f1 \endash \loch\f1 +1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line t\hich\af1\dbch\af31505\loch\f1 a\hich\af1\dbch\af31505\loch\f1 rget \hich\f1 \endash \loch\f1 +1, solutions=2: Return all optimum cards with their scores. \par \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 target=0, solutions=2: Return all cards legal to play with scores set to 0}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf6\insrsid6650094\charrsid4538894 .}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \line \hich\af1\dbch\af31505\loch\f1 target irrelevant, solutions=3: Return all cards that \hich\af1\dbch\af31505\loch\f1 can be legally played with their scores in descending order. \par \par \hich\af1\dbch\af31505\loch\f1 \hich\f1 Parameter \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 mode}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 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 \hich\f1 \endash -\hich\af1\dbch\af31505\loch\f1 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\hich\f1 \rquote \loch\f1 t -\par \hich\af1\dbch\af31505\loch\f1 mode=1: Always }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 search to find the score. Even when the hand to play\hich\af1\dbch\af31505\loch\f1 - 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 Sol -\hich\af1\dbch\af31505\loch\f1 v\hich\af1\dbch\af31505\loch\f1 eBoard 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 p\hich\af1\dbch\af31505\loch\f1 r\hich\af1\dbch\af31505\loch\f1 -ogrammer 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. +\loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 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 \hich\f1 \endash \loch\f1 2 for +\hich\af1\dbch\af31505\loch\f1 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\hich\f1 \rquote \loch\f1 t +\par \hich\af1\dbch\af31505\loch\f1 mode=1: Always }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 search to find the score. Even when the hand to play has o\hich\af1\dbch\af31505\loch\f1 +nly 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 SolveBoar +\hich\af1\dbch\af31505\loch\f1 d\hich\af1\dbch\af31505\loch\f1 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 program\hich\af1\dbch\af31505\loch\f1 m\hich\af1\dbch\af31505\loch\f1 +er 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 \ltrpar\ql \fi720\li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 1}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 st}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 call: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1, i.e. East leads. \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 \tab 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 -\hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 call: \hich\af1\dbch\af31505\loch\f1 SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads. +\hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 call: Solve\hich\af1\dbch\af31505\loch\f1 Board(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads. \par \hich\af1\dbch\af31505\loch\f1 \tab 3rd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3, i.e. West leads. \par }\pard \ltrpar\ql \fi720\li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. }{ \rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\par \hich\af1\dbch\af31505\loch\f1 struct }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 futureTric\hich\af1\dbch\af31505\loch\f1 ks}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 \{ /* 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. */}{\rtlch\fcs1 \af0\afs20 -\ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 +\par \hich\af1\dbch\af31505\loch\f1 struct }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 futureTricks}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 +\hich\af1\dbch\af31505\loch\f1 \{ /\hich\af1\dbch\af31505\loch\f1 * 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. */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 +\f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int nodes; /* Number of searched nodes */ \par \hich\af1\dbch\af31505\loch\f1 int cards; /* No of alternative cards */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 -\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int suit[13]; /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int\hich\af1\dbch\af31505\loch\f1 suit[13]; /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ \par \hich\af1\dbch\af31505\loch\f1 int rank[13]; /* 2-14 for 2 through Ace *}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 / \par \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 -int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (Kin\hich\af1\dbch\af31505\loch\f1 \hich\f1 g=rank 13). When there are several \'94\loch\f1 \hich\f1 equals\'94\loch\f1 +int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank\hich\af1\dbch\af31505\loch\f1 \hich\f1 13). When there are several \'94\loch\f1 \hich\f1 equals\'94\loch\f1 \hich\f1 , the value is the sum of each \'94\loch\f1 \hich\f1 equal\'94\loch\f1 . *}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 /}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 -\par \hich\af1\dbch\af31505\loch\f1 int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 - +\par \hich\af1\dbch\af31505\loch\f1 int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid5969439 \hich\af1\dbch\af31505\loch\f1 r}{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 of tricks */}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af0\dbch\af31505\loch\f0 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \}\hich\af1\dbch\af31505\loch\f1 ; \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 @@ -173,11 +182,11 @@ int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. Th \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \par \hich\af1\dbch\af31505\loch\f1 SolveBoardPBN \par -\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 In SolveBoardPBN the remaining cards\hich\af1\dbch\af31505\loch\f1 in the deal information are given in PBN text +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 In SolveBoardPBN the remaining cards in t\hich\af1\dbch\af31505\loch\f1 he deal information are given in PBN text \par \hich\af1\dbch\af31505\loch\f1 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 \hich\af1\dbch\af31505\loch\f1 struct dealPBN \{ -\par \hich\af1\dbch\af31505\loch\f1 in\hich\af1\dbch\af31505\loch\f1 t trump; +\par \hich\af1\dbch\af31505\loch\f1 int tru\hich\af1\dbch\af31505\loch\f1 mp; \par \hich\af1\dbch\af31505\loch\f1 int first; \par \hich\af1\dbch\af31505\loch\f1 int currentTrickSuit[3]; }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \par \hich\af1\dbch\af31505\loch\f1 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 int currentTrickRank[3]; @@ -192,32 +201,32 @@ int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. Th \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\cf1\insrsid6650094\charrsid4538894 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 -\af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations. +\af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump sui\hich\af1\dbch\af31505\loch\f1 t/declarer hand combinations. + \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 -\b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 CalcDDtable}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 returns a status integer,\hich\af1\dbch\af31505\loch\f1 - "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.\line Status codes: +\b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 CalcDDtable}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 + returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structu\hich\af1\dbch\af31505\loch\f1 re.\line Status codes: \par \hich\af1\dbch\af31505\loch\f1 1=No fault, \par \hich\af1\dbch\af31505\loch\f1 Other status codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 \par \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 \hich\f1 Structure \'94}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 -ddTableDeal}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 defines the dealt \hich\af1\dbch\af31505\loch\f1 cards to be analyzed.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 -\fs20\insrsid6650094 +ddTableDeal}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \loch\af1\dbch\af31505\hich\f1 \'94\loch\f1 defines the dealt cards to be analyzed.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \par \hich\af1\dbch\af31505\loch\f1 struct ddTableDeal \{ \par \hich\af1\dbch\af31505\loch\f1 unsigned int cards[4][4]; /* 1}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 st}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 - index is hand, 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 + index is hand, \hich\af1\dbch\af31505\loch\f1 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 index is suit, same coding as for deal.remainCards for SolveBoard. */ \par \}\hich\af1\dbch\af31505\loch\f1 ; \par \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 struct }{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 ddTableResults}{ -\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 \{ /* For each combination trump suit / declarer hand, the DLL\hich\af1\dbch\af31505\loch\f1 provides the double dummy score. */}{\rtlch\fcs1 -\af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 \{ /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\fs20\insrsid6650094 \par \hich\af1\dbch\af31505\loch\f1 int resTable[5][4];\tab /* 1}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 st}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 - index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid6650094 -\hich\af1\dbch\af31505\loch\f1 index is declarer hand, 0=North, 1=East, 2=South, 3=West */ + index is trump (0=Spades, 1=H\hich\af1\dbch\af31505\loch\f1 earts, 2=Diamonds, 3=Clubs, 4=No Trump 2}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\super\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 nd}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\fs20\insrsid6650094 \hich\af1\dbch\af31505\loch\f1 index is declarer hand, 0=North, 1=East, 2=South, 3=West */ \par \}\hich\af1\dbch\af31505\loch\f1 ; \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 \par @@ -233,14 +242,65 @@ ddTableDeal}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsi \par \}\hich\af1\dbch\af31505\loch\f1 ; \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1201643 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\fs20\insrsid1201643\charrsid5522304 \hich\af1\dbch\af31505\loch\f1 CalcPar +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid1201643\charrsid1201643 +\par \hich\af1\dbch\af31505\loch\f1 CalcPar calculates the par score and par con\hich\af1\dbch\af31505\loch\f1 +tracts of a given deal. It also includes calculation and presentation of the double dummy values table otherwise calculated by the CalcDDtable function, since this table is a prerequisite for the par calculations. Thus there is no need to make a CalcDDtab +\hich\af1\dbch\af31505\loch\f1 l\hich\af1\dbch\af31505\loch\f1 e call before calling CalcPar. +\par +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 Before CalcPar can be called, a structure of each type " ddTableResults" and \'93\loch\f1 \hich\f1 parResults\'94\loch\f1 must be declared. +\par \hich\af1\dbch\af31505\loch\f1 CalcPar returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults"\hich\af1\dbch\af31505\loch\f1 \hich\f1 type structure and the par results in the \'93\loch\f1 \hich\f1 +parResults\'94\loch\f1 structure. +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 Calling CalcPar with the structure of type \'93\loch\f1 \hich\f1 ddTableDeal\'94\loch\f1 is done in the same way as for calling CalcDDtable. +\par +\par \hich\af1\dbch\af31505\loch\f1 Status codes: +\par \hich\af1\dbch\af31505\loch\f1 1=No fault, +\par \hich\af1\dbch\af31505\loch\f1 Other status codes are errors, with codes eq\hich\af1\dbch\af31505\loch\f1 ual to SolveBoard status codes. +\par +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 Parameter \'93\loch\f1 \hich\f1 vulnerable\'94\loch\f1 is set according to: +\par \hich\af1\dbch\af31505\loch\f1 0 = None +\par \hich\af1\dbch\af31505\loch\f1 1 = Both sides +\par \hich\af1\dbch\af31505\loch\f1 2 = North / South side vulnerable +\par \hich\af1\dbch\af31505\loch\f1 3 = East / West side vulnerable +\par +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 The structure types \'93\loch\f1 \hich\f1 ddTableDeal\'94\loch\f1 \hich\f1 and \'93\loch\f1 \hich\f1 ddTableResults\'94\loch\f1 are described for the function C\hich\af1\dbch\af31505\loch\f1 alcDDtable. +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 The \'93\loch\f1 \hich\f1 parResults\'94\loch\f1 structure type includes the par score and the par contracts results returned by the call to CalcPar: +\par +\par \hich\af1\dbch\af31505\loch\f1 struct parResults \{ +\par \hich\af1\dbch\af31505\loch\f1 char parScore[2][16];\tab /* index = 0 is from NS view and index =1 is from EW view. */ +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 char parContractsString[2][128]; /* index = 0 is NS view and index = 1 is EW view. By \'93\loch\f1 \hich\f1 view\'94\loch\f1 is +\par \hich\af1\dbch\af31505\loch\f1 here meant which side that starts the bidding. */ +\par \}\hich\af1\dbch\af31505\loch\f1 ; +\par +\par \hich\af1\dbch\af31505\loch\f1 Par score is given as a text string, e.g NS -460. NS lost 460 points. +\par \hich\af1\dbch\af31505\loch\f1 All par contracts for dif\hich\af1\dbch\af31505\loch\f1 ferent suits are listed with comma separating the suits. +\par \hich\af1\dbch\af31505\loch\f1 Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels 3, 4 and 5 in No trumps, are given as 345N. +\par +\par \hich\af1\dbch\af31505\loch\f1 Example of par contracts \hich\af1\dbch\af31505\loch\f1 in different suits: +\par \hich\af1\dbch\af31505\loch\f1 NS:NS 23S,NS 23H +\par \hich\af1\dbch\af31505\loch\f1 This is from the NS view. North and South as declarer make 2 or 3 Spades and Hearts contracts, 2 Spades and 2 Hearts with an overtrick. +\par \hich\af1\dbch\af31505\loch\f1 If only North could make 3 Hearts, the text string would have looked: +\par \hich\af1\dbch\af31505\loch\f1 NS:NS 23S,N 2\hich\af1\dbch\af31505\loch\f1 3H +\par \hich\af1\dbch\af31505\loch\f1 NS before the colon refers to the assumed side that made the initial bid in the process for determining the par score / contracts. +\par \hich\af1\dbch\af31505\loch\f1 Also, DDS calculates the par score / contracts when the assumed side is EW: +\par \hich\af1\dbch\af31505\loch\f1 EW:NS 23S,N 23H +\par \hich\af1\dbch\af31505\loch\f1 Nearly always, the par sc\hich\af1\dbch\af31505\loch\f1 ore / contracts are the same for both starting points. One case where they are not is if both sides can make 1 NT but no other contract. +\par \par +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \b\fs20\insrsid1201643\charrsid5522304 \hich\af1\dbch\af31505\loch\f1 CalcParPBN +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\insrsid1201643\charrsid1201643 +\par \hich\af1\dbch\af31505\loch\f1 \hich\f1 The only difference compared to CalcPar is that the structure type \'93\loch\f1 \hich\f1 ddTableDealPBN\'94\loch\f1 \hich\f1 is used instead of \'93\hich\af1\dbch\af31505\loch\f1 \hich\f1 ddTableDeal\'94\loch\f1 +\hich\f1 . For description of \'93\loch\f1 \hich\f1 ddTableDealPBN\'94\loch\f1 , see CalcDDtablePBN. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1201643 \hich\af1\dbch\af31505\loch\f1 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6650094 \par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\fs20\cf1\insrsid6650094\charrsid4538894 \hich\af1\dbch\af31505\loch\f1 Revision History \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid16608682 \hich\af1\dbch\af31505\loch\f1 Rev A, 2013-02-19}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \tab \tab \hich\af1\dbch\af31505\loch\f1 First issue. \par -\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 +\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid14824249 \hich\af1\dbch\af31505\loch\f1 Rev B, 2014-03-30\tab Added CalcPar and CalcParPBN.}{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \fs20\cf1\insrsid6650094\charrsid4538894 \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 @@ -346,8 +406,8 @@ fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000006064 -be4ebb11ce01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000007092 +69792e4dcf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/dds.cpp b/dds.cpp index 10dd8548..26c4f9c6 100644 --- a/dds.cpp +++ b/dds.cpp @@ -1,6 +1,6 @@ -/* DDS 1.1.18 A bridge double dummy solver. */ -/* Copyright (C) 2006-2012 by Bo Haglund */ +/* DDS 1.1.19 A bridge double dummy solver. */ +/* Copyright (C) 2006-2014 by Bo Haglund */ /* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ @@ -60,6 +60,10 @@ struct winCardType **pw; struct nodeCardsType **pn; struct posSearchType **pl; +int stat_contr[5]={0,0,0,0,0}; +int max_low[3][8]; /* index 1: 0=NT, 1=Major, 2=Minor index 2: contract level 1-7 */ + + #ifdef _MANAGED #pragma managed(push, off) #endif @@ -914,6 +918,14 @@ void InitStart(int gb_ram, int ncores) { cardHand[0]='N'; cardHand[1]='E'; cardHand[2]='S'; cardHand[3]='W'; + max_low[0][0]=0; max_low[1][0]=0; max_low[2][0]=0; + max_low[0][1]=0; max_low[1][1]=0; max_low[2][1]=0; + max_low[0][2]=1; max_low[1][2]=1; max_low[2][2]=1; + max_low[0][3]=0; max_low[1][3]=2; max_low[2][3]=2; + max_low[0][4]=1; max_low[1][4]=0; max_low[2][4]=3; + max_low[0][5]=2; max_low[1][5]=1; max_low[2][5]=0; + max_low[0][6]=0; max_low[1][6]=0; max_low[2][6]=0; + max_low[0][7]=0; max_low[1][7]=0; max_low[2][7]=0; summem=(WINIT+1)*sizeof(struct winCardType)+ (NINIT+1)*sizeof(struct nodeCardsType)+ @@ -1328,7 +1340,7 @@ int ABsearch(struct pos * posPoint, int target, int depth) { the value of the subtree is returned. */ int moveExists, mexists, value, hand, scoreFlag, found; - int ready, hfirst, hh, ss, rr, mcurrent, qtricks, tricks, res, k; + int ready, hfirst, hh, ss, rr, /*mcurrent,*/ qtricks, /*tricks,*/ res, k; unsigned short int makeWinRank[4]; struct nodeCardsType * cardsP; struct evalType evalData; @@ -1338,10 +1350,9 @@ int ABsearch(struct pos * posPoint, int target, int depth) { struct nodeCardsType * tempP; unsigned short int aggr[4]; unsigned short int ranks; + struct movePlyType *mply=&movePly[depth]; struct evalType Evaluate(struct pos * posPoint); - void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth); void Undo(struct pos * posPoint, int depth); /*cardsP=NULL;*/ @@ -1576,7 +1587,7 @@ int ABsearch(struct pos * posPoint, int target, int depth) { /* New algo */ posPoint->orderSet[ss]=rel[aggr[ss]].aggrRanks[ss]; } - tricks=depth>>2; + /*tricks=depth>>2;*/ suitLengths=0; for (ss=0; ss<=2; ss++) for (hh=0; hh<=3; hh++) { @@ -1584,14 +1595,14 @@ int ABsearch(struct pos * posPoint, int target, int depth) { suitLengths|=posPoint->length[hh][ss]; } - pp=SearchLenAndInsert(rootnp[tricks][hand], suitLengths, FALSE, &res); + pp=SearchLenAndInsert(rootnp[depth>>2][hand], suitLengths, FALSE, &res); /* Find node that fits the suit lengths */ if (pp!=NULL) { np=pp->posSearchPoint; if (np==NULL) cardsP=NULL; else - cardsP=FindSOP(posPoint, np, hand, target, tricks, &scoreFlag); + cardsP=FindSOP(posPoint, np, hand, target, depth>>2, &scoreFlag); if ((cardsP!=NULL)/*&&(depth!=iniDepth)*/) { if (scoreFlag==1) { @@ -1704,12 +1715,13 @@ int ABsearch(struct pos * posPoint, int target, int depth) { moveExists=MoveGen(posPoint, depth); /*#if 0*/ - if ((posPoint->handRelFirst==3)&&(depth>=/*29*/33/*37*/)&&(depth!=iniDepth)) { - movePly[depth].current=0; + if ((posPoint->handRelFirst==3)&&(depth>=33/*37*/)&&(depth!=iniDepth)) { + /*movePly[depth].current=0;*/ + mply->current=0; mexists=TRUE; ready=FALSE; while (mexists) { - Make(posPoint, makeWinRank, depth); + Make(posPoint, makeWinRank, depth, mply/*&movePly[depth]*/); depth--; for (ss=0; ss<=3; ss++) { @@ -1718,7 +1730,7 @@ int ABsearch(struct pos * posPoint, int target, int depth) { aggr[ss]|=posPoint->rankInSuit[hh][ss]; posPoint->orderSet[ss]=rel[aggr[ss]].aggrRanks[ss]; } - tricks=depth>>2; + /*tricks=depth>>2;*/ hfirst=posPoint->first[depth]; suitLengths=0; for (ss=0; ss<=2; ss++) @@ -1727,14 +1739,14 @@ int ABsearch(struct pos * posPoint, int target, int depth) { suitLengths|=posPoint->length[hh][ss]; } - pp=SearchLenAndInsert(rootnp[tricks][hfirst], suitLengths, FALSE, &res); + pp=SearchLenAndInsert(rootnp[depth>>2][hfirst], suitLengths, FALSE, &res); /* Find node that fits the suit lengths */ if (pp!=NULL) { np=pp->posSearchPoint; if (np==NULL) tempP=NULL; else - tempP=FindSOP(posPoint, np, hfirst, target, tricks, &scoreFlag); + tempP=FindSOP(posPoint, np, hfirst, target, depth>>2, &scoreFlag); if (tempP!=NULL) { if ((nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) { @@ -1764,7 +1776,7 @@ int ABsearch(struct pos * posPoint, int target, int depth) { return FALSE; } else { - movePly[depth+1].move[movePly[depth+1].current].weight+=100; + mply->move[mply->current]/*movePly[depth+1].move[movePly[depth+1].current]*/.weight+=100; ready=TRUE; } } @@ -1773,26 +1785,26 @@ int ABsearch(struct pos * posPoint, int target, int depth) { Undo(posPoint, depth); if (ready) break; - if (movePly[depth].current<=movePly[depth].last-1) { - movePly[depth].current++; + if (/*movePly[depth].current*/mply->current<=(mply->last-1)/*movePly[depth].last-1*/) { + /*movePly[depth].current++;*/mply->current++; mexists=TRUE; } else mexists=FALSE; } if (ready) - MergeSort(movePly[depth].last+1, movePly[depth].move); + MergeSort(mply->last+1/*movePly[depth].last+1*/, mply->move/*movePly[depth].move*/); } /*#endif*/ - movePly[depth].current=0; + /*movePly[depth].current=0;*/mply->current=0; if (nodeTypeStore[hand]==MAXNODE) { value=FALSE; for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=0; while (moveExists) { - Make(posPoint, makeWinRank, depth); /* Make current move */ + Make(posPoint, makeWinRank, depth, mply/*&movePly[depth]*/); /* Make current move */ value=ABsearch(posPoint, target, depth-1); @@ -1802,15 +1814,15 @@ int ABsearch(struct pos * posPoint, int target, int depth) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - mcurrent=movePly[depth].current; - bestMove[depth]=movePly[depth].move[mcurrent]; + /*mcurrent=movePly[depth].current;*/ + bestMove[depth]=mply->move[mply->current]/*movePly[depth].move[mcurrent]*/; goto ABexit; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] | posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - moveExists=NextMove(posPoint, depth); + moveExists=NextMove(posPoint, depth/*, mply*//*&movePly[depth]*/); } } else { /* A minnode */ @@ -1819,7 +1831,7 @@ int ABsearch(struct pos * posPoint, int target, int depth) { posPoint->winRanks[depth][ss]=0; while (moveExists) { - Make(posPoint, makeWinRank, depth); /* Make current move */ + Make(posPoint, makeWinRank, depth, mply/*&movePly[depth]*/); /* Make current move */ value=ABsearch(posPoint, target, depth-1); @@ -1829,29 +1841,28 @@ int ABsearch(struct pos * posPoint, int target, int depth) { for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - mcurrent=movePly[depth].current; - bestMove[depth]=movePly[depth].move[mcurrent]; + /*mcurrent=movePly[depth].current;*/ + bestMove[depth]=mply->move[mply->current]/*movePly[depth].move[mcurrent]*/; goto ABexit; } for (ss=0; ss<=3; ss++) posPoint->winRanks[depth][ss]=posPoint->winRanks[depth][ss] | posPoint->winRanks[depth-1][ss] | makeWinRank[ss]; - moveExists=NextMove(posPoint, depth); + moveExists=NextMove(posPoint, depth/*, mply*//*&movePly[depth]*/); } } } ABexit: if (depth>=4) { if(posPoint->handRelFirst==0) { - tricks=depth>>2; - /*hand=posPoint->first[depth-1];*/ + /*tricks=depth>>2;*/ if (value) k=target; else k=target-1; if (depth!=iniDepth) - BuildSOP(posPoint, suitLengths, tricks, hand, target, depth, + BuildSOP(posPoint, suitLengths, depth>>2, hand, target, depth, value, k); if (clearTTflag) { /* Wipe out the TT dynamically allocated structures @@ -1978,143 +1989,148 @@ int ABsearch(struct pos * posPoint, int target, int depth) { return value; } -void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth) { - int r, s, t, u, w, firstHand; - int suit, count, mcurr, h, q, done; - struct moveType mo1, mo2; - unsigned short aggr; - for (suit=0; suit<=3; suit++) - trickCards[suit]=0; - firstHand=posPoint->first[depth]; - r=movePly[depth].current; +void Make(struct pos * posPoint, unsigned short int trickCards[4], + int depth, struct movePlyType *mply) { + int t, u, w; + int mcurr, q; + + assert((posPoint->handRelFirst >= 0) && (posPoint->handRelFirst <= 3)); + for (int suit = 0; suit <= 3; suit++) + trickCards[suit] = 0; - if (posPoint->handRelFirst==3) { /* This hand is last hand */ - mo1=movePly[depth].move[r]; - mo2=posPoint->move[depth+1]; - if (mo1.suit==mo2.suit) { - if (mo1.rank>mo2.rank) { - posPoint->move[depth]=mo1; - posPoint->high[depth]=handId(firstHand, 3); + int firstHand = posPoint->first[depth]; + int r = mply->current; + + if (posPoint->handRelFirst == 3) { /* This hand is last hand */ + if (mply->move[r].suit == posPoint->move[depth + 1].suit) { + if (mply->move[r].rank>posPoint->move[depth + 1].rank) { + posPoint->move[depth] = mply->move[r]; + posPoint->high[depth] = handId(firstHand, 3); } else { - posPoint->move[depth]=posPoint->move[depth+1]; - posPoint->high[depth]=posPoint->high[depth+1]; + posPoint->move[depth] = posPoint->move[depth + 1]; + posPoint->high[depth] = posPoint->high[depth + 1]; } } - else if (mo1.suit==trump) { - posPoint->move[depth]=mo1; - posPoint->high[depth]=handId(firstHand, 3); - } + else if (mply->move[r].suit == trump) { + posPoint->move[depth] = mply->move[r]; + posPoint->high[depth] = handId(firstHand, 3); + } else { - posPoint->move[depth]=posPoint->move[depth+1]; - posPoint->high[depth]=posPoint->high[depth+1]; + posPoint->move[depth] = posPoint->move[depth + 1]; + posPoint->high[depth] = posPoint->high[depth + 1]; } /* Is the trick won by rank? */ - suit=posPoint->move[depth].suit; - count=0; - for (h=0; h<=3; h++) { - mcurr=movePly[depth+h].current; - if (movePly[depth+h].move[mcurr].suit==suit) - count++; + int s = posPoint->move[depth].suit; + int count = 0; + if (mply->move[r].suit == s) + count++; + for (int e = 1; e <= 3; e++) { + mcurr = movePly[depth + e].current; + if (movePly[depth + e].move[mcurr].suit == s) { + count++; + /*if (++count>1) + break;*/ + } } - if (nodeTypeStore[posPoint->high[depth]]==MAXNODE) - posPoint->tricksMAX++; - posPoint->first[depth-1]=posPoint->high[depth]; /* Defines who is first - in the next move */ - - t=handId(firstHand, 3); - posPoint->handRelFirst=0; /* Hand pointed to by posPoint->first - will lead the next trick */ - - done=FALSE; - for (s=3; s>=0; s--) { - q=handId(firstHand, 3-s); - /* Add the moves to removed ranks */ - r=movePly[depth+s].current; - w=movePly[depth+s].move[r].rank; - u=movePly[depth+s].move[r].suit; - posPoint->removedRanks[u]|=bitMapRank[w]; - - if (s==0) - posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); - - if ((w==posPoint->winner[u].rank)||(w==posPoint->secondBest[u].rank)) { - aggr=0; - for (h=0; h<=3; h++) - aggr|=posPoint->rankInSuit[h][u]; - posPoint->winner[u].rank=rel[aggr].absRank[1][u].rank; - posPoint->winner[u].hand=rel[aggr].absRank[1][u].hand; - posPoint->secondBest[u].rank=rel[aggr].absRank[2][u].rank; - posPoint->secondBest[u].hand=rel[aggr].absRank[2][u].hand; - } - /* Determine win-ranked cards */ - if ((q==posPoint->high[depth])&&(!done)) { - done=TRUE; - if (count>=2) { - trickCards[u]=bitMapRank[w]; - /* Mark ranks as winning if they are part of a sequence */ - trickCards[u]|=movePly[depth+s].move[r].sequence; - } + if (nodeTypeStore[posPoint->high[depth]] == MAXNODE) + posPoint->tricksMAX++; + posPoint->first[depth - 1] = posPoint->high[depth]; /* Defines who is first + in the next move */ + + t = handId(firstHand, 3); + posPoint->handRelFirst = 0; /* Hand pointed to by posPoint->first + will lead the next trick */ + + int done = FALSE; + for (int d = 3; d >= 0; d--) { + q = handId(firstHand, 3 - d); + /* Add the moves to removed ranks */ + r = movePly[depth + d].current; + w = movePly[depth + d].move[r].rank; + u = movePly[depth + d].move[r].suit; + posPoint->removedRanks[u] |= bitMapRank[w]; + + if (d == 0) + posPoint->rankInSuit[t][u] &= (~bitMapRank[w]); + + if ((w == posPoint->winner[u].rank) || (w == posPoint->secondBest[u].rank)) { + int aggr = 0; + for (int h = 0; h <= 3; h++) + aggr |= posPoint->rankInSuit[h][u]; + posPoint->winner[u].rank = rel[aggr].absRank[1][u].rank; + posPoint->winner[u].hand = rel[aggr].absRank[1][u].hand; + posPoint->secondBest[u].rank = rel[aggr].absRank[2][u].rank; + posPoint->secondBest[u].hand = rel[aggr].absRank[2][u].hand; + } + + + /* Determine win-ranked cards */ + if ((q == posPoint->high[depth]) && (!done)) { + done = TRUE; + if (count >= 2) { + trickCards[u] = bitMapRank[w]; + /* Mark ranks as winning if they are part of a sequence */ + trickCards[u] |= movePly[depth + d].move[r].sequence; + } } } } - else if (posPoint->handRelFirst==0) { /* Is it the 1st hand? */ - posPoint->first[depth-1]=firstHand; /* First hand is not changed in - next move */ - posPoint->high[depth]=firstHand; - posPoint->move[depth]=movePly[depth].move[r]; - t=firstHand; - posPoint->handRelFirst=1; - r=movePly[depth].current; - u=movePly[depth].move[r].suit; - w=movePly[depth].move[r].rank; - posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); + else if (posPoint->handRelFirst == 0) { /* Is it the 1st hand? */ + posPoint->first[depth - 1] = firstHand; /* First hand is not changed in + next move */ + posPoint->high[depth] = firstHand; + posPoint->move[depth] = mply->move[r]; + t = firstHand; + posPoint->handRelFirst = 1; + r = mply->current; + u = mply->move[r].suit; + w = mply->move[r].rank; + posPoint->rankInSuit[t][u] &= (~bitMapRank[w]); } else { - mo1=movePly[depth].move[r]; - mo2=posPoint->move[depth+1]; - r=movePly[depth].current; - u=movePly[depth].move[r].suit; - w=movePly[depth].move[r].rank; - if (mo1.suit==mo2.suit) { - if (mo1.rank>mo2.rank) { - posPoint->move[depth]=mo1; - posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst); + r = mply->current; + u = mply->move[r].suit; + w = mply->move[r].rank; + if (u == posPoint->move[depth + 1].suit) { + if (w>posPoint->move[depth + 1].rank) { + posPoint->move[depth] = mply->move[r]; + posPoint->high[depth] = handId(firstHand, posPoint->handRelFirst); } else { - posPoint->move[depth]=posPoint->move[depth+1]; - posPoint->high[depth]=posPoint->high[depth+1]; + posPoint->move[depth] = posPoint->move[depth + 1]; + posPoint->high[depth] = posPoint->high[depth + 1]; } } - else if (mo1.suit==trump) { - posPoint->move[depth]=mo1; - posPoint->high[depth]=handId(firstHand, posPoint->handRelFirst); - } + else if (u == trump) { + posPoint->move[depth] = mply->move[r]; + posPoint->high[depth] = handId(firstHand, posPoint->handRelFirst); + } else { - posPoint->move[depth]=posPoint->move[depth+1]; - posPoint->high[depth]=posPoint->high[depth+1]; + posPoint->move[depth] = posPoint->move[depth + 1]; + posPoint->high[depth] = posPoint->high[depth + 1]; } - - t=handId(firstHand, posPoint->handRelFirst); + + t = handId(firstHand, posPoint->handRelFirst); posPoint->handRelFirst++; /* Current hand is stepped */ - posPoint->first[depth-1]=firstHand; /* First hand is not changed in - next move */ - - posPoint->rankInSuit[t][u]&=(~bitMapRank[w]); + assert((posPoint->handRelFirst >= 0) && (posPoint->handRelFirst <= 3)); + posPoint->first[depth - 1] = firstHand; /* First hand is not changed in + next move */ + + posPoint->rankInSuit[t][u] &= (~bitMapRank[w]); } - posPoint->length[t][u]--; + posPoint->length[t][u]--; #ifdef STAT - no[depth]++; + localVar[thrId].no[depth]++; #endif - + return; } @@ -2183,26 +2199,25 @@ void Undo(struct pos * posPoint, int depth) { } - -struct evalType Evaluate(struct pos * posPoint) { - int s, smax=0, max, k, firstHand, count; + struct evalType Evaluate(struct pos * posPoint) { + int m, hmax=0, max, k, firstHand, count; struct evalType eval; firstHand=posPoint->first[0]; - for (s=0; s<=3; s++) - eval.winRanks[s]=0; + for (m=0; m<=3; m++) + eval.winRanks[m]=0; /* Who wins the last trick? */ if (trump!=4) { /* Highest trump card wins */ max=0; count=0; - for (s=0; s<=3; s++) { - if (posPoint->rankInSuit[s][trump]!=0) + for (m=0; m<=3; m++) { + if (posPoint->rankInSuit[m][trump]!=0) count++; - if (posPoint->rankInSuit[s][trump]>max) { - smax=s; - max=posPoint->rankInSuit[s][trump]; + if (posPoint->rankInSuit[m][trump]>max) { + hmax=m; + max=posPoint->rankInSuit[m][trump]; } } @@ -2210,7 +2225,7 @@ struct evalType Evaluate(struct pos * posPoint) { if (count>=2) eval.winRanks[trump]=max; - if (nodeTypeStore[smax]==MAXNODE) + if (nodeTypeStore[hmax]==MAXNODE) goto maxexit; else goto minexit; @@ -2228,19 +2243,19 @@ struct evalType Evaluate(struct pos * posPoint) { count=0; max=0; - for (s=0; s<=3; s++) { - if (posPoint->rankInSuit[s][k]!=0) + for (m=0; m<=3; m++) { + if (posPoint->rankInSuit[m][k]!=0) count++; - if (posPoint->rankInSuit[s][k]>max) { - smax=s; - max=posPoint->rankInSuit[s][k]; + if (posPoint->rankInSuit[m][k]>max) { + hmax=m; + max=posPoint->rankInSuit[m][k]; } } if (count>=2) eval.winRanks[k]=max; - if (nodeTypeStore[smax]==MAXNODE) + if (nodeTypeStore[hmax]==MAXNODE) goto maxexit; else goto minexit; @@ -3354,11 +3369,11 @@ int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int MoveGen(struct pos * posPoint, int depth) { - int suit, k, m, r, s, t, state; + int suit, k, m, r, curr, s, state=MOVESVALID; unsigned short ris; int q, first; - int WeightAllocTrump(struct pos *, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int trump); + int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit); int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit); @@ -3371,38 +3386,37 @@ int MoveGen(struct pos * posPoint, int depth) { first=posPoint->first[depth]; q=handId(first, r); - s=movePly[depth+r].current; /* Current move of first hand */ - t=movePly[depth+r].move[s].suit; /* Suit played by first hand */ - ris=posPoint->rankInSuit[q][t]; + curr=movePly[depth+r].current; /* Current move of first hand */ + s=movePly[depth+r].move[curr].suit; /* Suit played by first hand */ + ris=posPoint->rankInSuit[q][s]; if ((r!=0)&&(ris!=0)) { /* Not first hand and not void in suit */ - k=14; state=MOVESVALID; + k=14; /*state=MOVESVALID;*/ while (k>=2) { if ((ris & bitMapRank[k])&&(state==MOVESVALID)) { /* Only first move in sequence is generated */ - movePly[depth].move[m].suit=t; + movePly[depth].move[m].suit=s; movePly[depth].move[m].rank=k; movePly[depth].move[m].sequence=0; m++; state=MOVESLOCKED; } - else if (state==MOVESLOCKED) - if ((posPoint->removedRanks[t] & bitMapRank[k])==0) { - if ((ris & bitMapRank[k])==0) - /* If the card still exists and it is not in own hand */ - state=MOVESVALID; - else - /* If the card still exists and it is in own hand */ - movePly[depth].move[m-1].sequence|=bitMapRank[k]; - } + else if (state==MOVESLOCKED) { + if (ris & bitMapRank[k]) + /* If the card is in own hand */ + movePly[depth].move[m - 1].sequence |= bitMapRank[k]; + else if ((posPoint->removedRanks[s] & bitMapRank[k]) == 0) + /* If the card still exists and it is not in own hand */ + state = MOVESVALID; + } k--; } if (m!=1) { if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { for (k=0; k<=m-1; k++) movePly[depth].move[k].weight=WeightAllocTrump(posPoint, - &movePly[depth].move[k], depth, ris, trump); + &movePly[depth].move[k], depth, ris); } else { for (k=0; k<=m-1; k++) @@ -3434,15 +3448,14 @@ int MoveGen(struct pos * posPoint, int depth) { m++; state=MOVESLOCKED; } - else if (state==MOVESLOCKED) - if ((posPoint->removedRanks[suit] & bitMapRank[k])==0) { - if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])==0) - /* If the card still exists and it is not in own hand */ - state=MOVESVALID; - else - /* If the card still exists and it is in own hand */ - movePly[depth].move[m-1].sequence|=bitMapRank[k]; - } + else if (state == MOVESLOCKED) { + if (posPoint->rankInSuit[q][suit] & bitMapRank[k]) + /* If the card is in own hand */ + movePly[depth].move[m - 1].sequence |= bitMapRank[k]; + else if ((posPoint->removedRanks[suit] & bitMapRank[k]) == 0) + /* If the card still exists and it is not in own hand */ + state = MOVESVALID; + } k--; } } @@ -3450,7 +3463,7 @@ int MoveGen(struct pos * posPoint, int depth) { if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { for (k=0; k<=m-1; k++) { movePly[depth].move[k].weight=WeightAllocTrump(posPoint, - &movePly[depth].move[k], depth, ris, trump); + &movePly[depth].move[k], depth, ris); } } else { @@ -3472,162 +3485,158 @@ int MoveGen(struct pos * posPoint, int depth) { } } - - int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, unsigned short notVoidInSuit) { - int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; - int suitWeightDelta, first, q; - int rRank, thirdBestHand; - int winMove=FALSE; /* If winMove is true, current move can win the current trick. */ - unsigned short suitCount, suitCountLH, suitCountRH, aggr; + + int weight = 0, k, l, kk, ll, suitAdd = 0, leadSuit; + int suitWeightDelta; + int thirdBestHand; + int winMove = FALSE; /* If winMove is TRUE, current move can win the current trick. */ + unsigned short suitCount, suitCountLH, suitCountRH; int countLH, countRH; + int first = posPoint->first[depth]; + int q = handId(first, posPoint->handRelFirst); + int suit = mp->suit; + unsigned short aggr = 0; - first=posPoint->first[depth]; - q=handId(first, posPoint->handRelFirst); - suit=mp->suit; - aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][suit]; - rRank=rel[aggr].relRank[mp->rank][suit]; + for (int m = 0; m <= 3; m++) + aggr |= posPoint->rankInSuit[m][suit]; + int rRank = rel[aggr].relRank[mp->rank][suit]; - switch (posPoint->handRelFirst) { - case 0: - thirdBestHand=rel[aggr].absRank[3][suit].hand; - suitCount=posPoint->length[q][suit]; - suitCountLH=posPoint->length[lho[q]][suit]; - suitCountRH=posPoint->length[rho[q]][suit]; + switch (posPoint->handRelFirst) { + case 0: + /*thirdBestHand=rel[aggr].absRank[3][suit].hand;*/ + suitCount = posPoint->length[q][suit]; + suitCountLH = posPoint->length[lho[q]][suit]; + suitCountRH = posPoint->length[rho[q]][suit]; - if (suitCountLH!=0) { - countLH=(suitCountLH<<2); - } - else - countLH=depth+4; + if (suitCountLH != 0) { + countLH = (suitCountLH << 2); + } + else + countLH = depth + 4; - if (suitCountRH!=0) { - countRH=(suitCountRH<<2); - } - else - countRH=depth+4; + if (suitCountRH != 0) { + countRH = (suitCountRH << 2); + } + else + countRH = depth + 4; - /* Discourage a suit selection where the search tree appears larger than for the - altenative suits: the search is estimated to be small when the added number of - alternative cards to play for the opponents is small. */ + /* Discourage a suit selection where the search tree appears larger than for the + altenative suits: the search is estimated to be small when the added number of + alternative cards to play for the opponents is small. */ - suitWeightDelta=-((countLH+countRH)<<5)/19; - - 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) { - /* Discourage suit if RHO has second best card. - Exception: RHO has singleton. */ - if (posPoint->secondBest[suit].hand==rho[q]) { - if (suitCountRH!=1) - suitWeightDelta-=7; - } - /* Encourage playing suit if LHO has second highest rank. */ - else if (posPoint->secondBest[suit].hand==lho[q]) - suitWeightDelta+=14; - - /* Higher weight if also second best rank is present on current side to play, or - if second best is a singleton at LHO or RHO. */ + suitWeightDelta = -((countLH + countRH) << 5) / 19; - if (((posPoint->secondBest[suit].hand!=lho[first]) - ||(suitCountLH==1))&& - ((posPoint->secondBest[suit].hand!=rho[first]) - ||(suitCountRH==1))) - weight=suitWeightDelta+41/*48*/+rRank; + if (posPoint->length[partner[q]][suit] == 0) + suitWeightDelta += -9; - /* Encourage playing second highest rank if hand also has - third highest rank. */ + if (posPoint->winner[suit].rank == mp->rank) + winMove = TRUE; /* May also have 2nd best, but this card will not be searched. */ + else if (posPoint->rankInSuit[partner[first]][suit] > + (posPoint->rankInSuit[lho[first]][suit] | + posPoint->rankInSuit[rho[first]][suit])) { + winMove = TRUE; + } - else if ((mp->sequence)&& - (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+39; - else - weight=suitWeightDelta+20+rRank; + if (winMove) { + /* Discourage suit if RHO has second best card. + Exception: RHO has singleton. */ + if (posPoint->secondBest[suit].hand == rho[q]) { + if (suitCountRH != 1) + suitWeightDelta += -1; + } + /* Encourage playing suit if LHO has second highest rank. */ + else if (posPoint->secondBest[suit].hand == lho[q]) { + if (suitCountLH != 1) + suitWeightDelta += 22; + else + suitWeightDelta += 16; + } - /* Encourage playing cards that previously caused search cutoff - or was stored as the best move in a transposition table entry match. */ + /* Higher weight if also second best rank is present on current side to play, or + if second best is a singleton at LHO or RHO. */ - if ((bestMove[depth].suit==suit)&& - (bestMove[depth].rank==mp->rank)) - weight+=123/*122*//*112*//*73*/; - else if ((bestMoveTT[depth].suit==suit)&& - (bestMoveTT[depth].rank==mp->rank)) - weight+=24/*20*//*17*//*14*/; - } - else { - /* Discourage suit if RHO has winning or second best card. - Exception: RHO has singleton. */ + if (((posPoint->secondBest[suit].hand != lho[first]) + || (suitCountLH == 1)) && + ((posPoint->secondBest[suit].hand != rho[first]) || (suitCountRH == 1))) + weight = suitWeightDelta + 45 + rRank; + else + weight = suitWeightDelta + 18 + rRank; - if ((posPoint->winner[suit].hand==rho[q])|| - (posPoint->secondBest[suit].hand==rho[q])) { - if (suitCountRH!=1) - suitWeightDelta-=7; - } + /* Encourage playing cards that previously caused search cutoff + or was stored as the best move in a transposition table entry match. */ + if ((bestMove[depth].suit == suit) && + (bestMove[depth].rank == mp->rank)) + weight += 126; + else if ((bestMoveTT[depth].suit == suit) && + (bestMoveTT[depth].rank == mp->rank)) + weight += 24; + } + else { + /* Discourage suit if RHO has winning or second best card. + Exception: RHO has singleton. */ - /* Try suit if LHO has winning card and partner second best. - Exception: partner has singleton. */ + if ((posPoint->winner[suit].hand == rho[q]) || + (posPoint->secondBest[suit].hand == rho[q])) { + if (suitCountRH != 1) + suitWeightDelta += -10; + } - else if ((posPoint->winner[suit].hand==lho[q])&& - (posPoint->secondBest[suit].hand==partner[q])) { - /* This case was suggested by Joël Bradmetz. */ + /* Try suit if LHO has winning card and partner second best. + Exception: partner has singleton. */ + + else if ((posPoint->winner[suit].hand == lho[q]) && + (posPoint->secondBest[suit].hand == partner[q])) { + + /* This case was suggested by Joël Bradmetz. */ + + if (posPoint->length[partner[q]][suit] != 1) + suitWeightDelta += 31; + } - if (posPoint->length[partner[q]][suit]!=1) - suitWeightDelta+=31/*34*//*37*//*32*//*20*/; - } - /* Encourage playing the suit if the hand together with partner have both the 2nd highest and the 3rd highest cards such that the side of the hand has the highest card in the next round playing this suit. */ - if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand)) - suitWeightDelta+=22/*10*/; - else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&& - (posPoint->length[partner[first]][suit]>1))||((posPoint->secondBest[suit].hand==partner[first])&& - (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1))) - suitWeightDelta+=24/*10*/; + thirdBestHand = rel[aggr].absRank[3][suit].hand; - /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ - - 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-20/*24*//*27*//*12*//*10*/+rRank; - } + if ((posPoint->secondBest[suit].hand == partner[first]) && (partner[first] == thirdBestHand)) + suitWeightDelta += 35; + else if (((posPoint->secondBest[suit].hand == first) && (partner[first] == thirdBestHand) && + (posPoint->length[partner[first]][suit]>1)) || ((posPoint->secondBest[suit].hand == partner[first]) && + (first == thirdBestHand) && (posPoint->length[partner[first]][suit]>1))) + suitWeightDelta += 25; - /* Encourage playing second highest rank if hand also has - third highest rank. */ + /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ - else if ((mp->sequence)&& - (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+44/*42*/; + if (((suitCountLH == 1) && (posPoint->winner[suit].hand == lho[first])) + || ((suitCountRH == 1) && (posPoint->winner[suit].hand == rho[first]))) + weight = suitWeightDelta + 28 + rRank; + else if (posPoint->winner[suit].hand == first) { + weight = suitWeightDelta - 17 + rRank; + } + else if ((mp->sequence) && + (mp->rank == posPoint->secondBest[suit].rank)) + weight = suitWeightDelta + 48; else if (mp->sequence) - weight=suitWeightDelta+31/*32*/-rRank; - else - weight=suitWeightDelta+12+rRank; - + weight = suitWeightDelta + 29 - rRank; + else + weight = suitWeightDelta + 12 + rRank; + /* Encourage playing cards that previously caused search cutoff - or was stored as the best move in a transposition table entry match. */ + or was stored as the best move in a transposition table entry match. */ - if ((bestMove[depth].suit==suit)&& - (bestMove[depth].rank==mp->rank)) - weight+=47/*45*//*39*//*38*/; - else if ((bestMoveTT[depth].suit==suit)&& - (bestMoveTT[depth].rank==mp->rank)) - weight+=13/*15*//*16*//*19*//*14*/; + if ((bestMove[depth].suit == suit) && + (bestMove[depth].rank == mp->rank)) + weight += 47; + else if ((bestMoveTT[depth].suit == suit) && + (bestMoveTT[depth].rank == mp->rank)) + weight += 19; } - + break; case 1: @@ -3659,18 +3668,18 @@ int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, /* Discourage suit discard if 2nd highest card becomes singleton. */ if (suitCount==2) - suitAdd-=3; + suitAdd+=-2; } /* Discourage suit discard of highest card. */ else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd-=3; + suitAdd+=-3; /*Encourage discard of low cards in long suits. */ - weight=/*60*/-(mp->rank)+suitAdd; + weight=-4-(mp->rank)+suitAdd; } else { - weight=80+rRank; + weight=81/*80*/+rRank; } } else { @@ -3680,14 +3689,14 @@ int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=7; + suitAdd+=-6; /* Discourage suit discard of highest card. */ else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd-=10; + suitAdd+=-8; /*Encourage discard of low cards in long suits. */ - weight=-(mp->rank)+suitAdd; + weight=2-(mp->rank)+suitAdd; } else { @@ -3712,7 +3721,7 @@ int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, } } else { - weight=-15+rRank; + weight=-11/*15*/+rRank; } } } @@ -3812,25 +3821,25 @@ int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int trump) { - int weight=0, k, l, kk, ll, suit, suitAdd=0, leadSuit; - int suitWeightDelta, first, q, rRank, thirdBestHand; + unsigned short notVoidInSuit) { + int weight=0, k, l, kk, ll, suitAdd=0, leadSuit; + int suitWeightDelta, thirdBestHand; int suitBonus=0; int winMove=FALSE; /* If winMove is true, current move can win the current trick. */ - unsigned short suitCount, suitCountLH, suitCountRH, aggr; + unsigned short suitCount, suitCountLH, suitCountRH; int countLH, countRH; - first=posPoint->first[depth]; - q=handId(first, posPoint->handRelFirst); - suit=mp->suit; - aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][suit]; - rRank=rel[aggr].relRank[mp->rank][suit]; + int first=posPoint->first[depth]; + int q=handId(first, posPoint->handRelFirst); + int suit=mp->suit; + unsigned short aggr=0; + for (int m=0; m<=3; m++) + aggr|=posPoint->rankInSuit[m][suit]; + int rRank=rel[aggr].relRank[mp->rank][suit]; switch (posPoint->handRelFirst) { case 0: - thirdBestHand=rel[aggr].absRank[3][suit].hand; + /*thirdBestHand=rel[aggr].absRank[3][suit].hand;*/ suitCount=posPoint->length[q][suit]; suitCountLH=posPoint->length[lho[q]][suit]; suitCountRH=posPoint->length[rho[q]][suit]; @@ -3842,20 +3851,20 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, (posPoint->rankInSuit[lho[q]][trump]!=0)) || ((posPoint->rankInSuit[rho[q]][suit]==0) && (posPoint->rankInSuit[rho[q]][trump]!=0)))) - suitBonus=-17/*20*//*-10*/; + suitBonus=-12/*9*//*17*/; /* Encourage suit if partner can ruff. */ if ((suit!=trump)&&(posPoint->length[partner[q]][suit]==0)&& (posPoint->length[partner[q]][trump]>0)&&(suitCountRH>0)) - suitBonus+=26/*28*/; + suitBonus+=17/*26*/; /* Discourage suit if RHO has high card. */ if ((posPoint->winner[suit].hand==rho[q])|| (posPoint->secondBest[suit].hand==rho[q])) { if (suitCountRH!=1) - suitBonus-=11/*12*//*13*//*18*/; + suitBonus+=-12/*13*//*11*/; } /* Try suit if LHO has winning card and partner second best. @@ -3867,7 +3876,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, /* This case was suggested by Joël Bradmetz. */ if (posPoint->length[partner[q]][suit]!=1) - suitBonus+=30/*28*//*22*/; + suitBonus+=27/*25*//*30*/; } /* Encourage play of suit where partner wins and @@ -3876,7 +3885,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, (posPoint->length[q][trump]>0)&& (posPoint->length[partner[q]][suit]>1)&& (posPoint->winner[suit].hand==partner[q])) - suitBonus+=23/*24*//*19*//*16*/; + suitBonus+=19/*26*//*23*/; if (suitCountLH!=0) countLH=(suitCountLH<<2); @@ -3892,7 +3901,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, alternative cards to play for the opponents is small. */ suitWeightDelta=suitBonus- - ((countLH+countRH)<<5)/(12/*15*/); + ((countLH+countRH)<<5)/13; if (posPoint->winner[suit].rank==mp->rank) { if ((suit!=trump)) { @@ -3963,7 +3972,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) - weight=suitWeightDelta+39+rRank; + weight=suitWeightDelta+35/*37*//*39*/+rRank; /* Lead hand has the highest card. */ @@ -3972,30 +3981,30 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, /* Also, partner has second highest card. */ if (posPoint->secondBest[suit].hand==partner[first]) - weight=suitWeightDelta+46+rRank; + weight=suitWeightDelta+/*47*/48+rRank; else if (posPoint->winner[suit].rank==mp->rank) /* If the current card to play is the highest card. */ weight=suitWeightDelta+31; else - weight=suitWeightDelta-2+rRank; + weight=suitWeightDelta-3+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* If partner has highest card */ if (posPoint->secondBest[suit].hand==first) - weight=suitWeightDelta+35/*35*//*46*//*50*/+rRank; + weight=suitWeightDelta+42/*35*//*46*//*50*/+rRank; else - weight=suitWeightDelta+24/*35*/+rRank; + weight=suitWeightDelta+28/*24*/+rRank; } /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+41; + weight=suitWeightDelta+40/*41*/; else if (mp->sequence) - weight=suitWeightDelta+17+rRank; + weight=suitWeightDelta+22/*17*/+rRank; else weight=suitWeightDelta+11+rRank; @@ -4004,10 +4013,10 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, if ((bestMove[depth].suit==suit)&& (bestMove[depth].rank==mp->rank)) - weight+=53/*50*//*52*/; + weight+=55/*53*/; else if ((bestMoveTT[depth].suit==suit)&& (bestMoveTT[depth].rank==mp->rank)) - weight+=14/*15*//*12*//*11*/; + weight+=18/*14*/; } else { @@ -4015,19 +4024,21 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, and the 3rd highest cards such that the side of the hand has the highest card in the next round playing this suit. */ + thirdBestHand=rel[aggr].absRank[3][suit].hand; + if ((posPoint->secondBest[suit].hand==partner[first])&&(partner[first]==thirdBestHand)) suitWeightDelta+=20/*22*/; else if(((posPoint->secondBest[suit].hand==first)&&(partner[first]==thirdBestHand)&& (posPoint->length[partner[first]][suit]>1))|| ((posPoint->secondBest[suit].hand==partner[first])&& (first==thirdBestHand)&&(posPoint->length[partner[first]][suit]>1))) - suitWeightDelta+=20/*24*/; + suitWeightDelta+=13/*20*//*24*/; /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) - weight=suitWeightDelta+rRank-2; + weight=suitWeightDelta+rRank+2/*-2*/; else if (posPoint->winner[suit].hand==first) { if (posPoint->secondBest[suit].hand==partner[first]) @@ -4038,34 +4049,34 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, /* Opponents win by ruffing */ - weight=suitWeightDelta+36; + weight=suitWeightDelta+38/*36*/; else - weight=suitWeightDelta-17+rRank; + weight=suitWeightDelta-14/*17*/+rRank; } else if (posPoint->winner[suit].hand==partner[first]) { /* Opponents win by ruffing */ - weight=suitWeightDelta+33+rRank; + weight=suitWeightDelta+34/*33*/+rRank; } /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mp->sequence)&& (mp->rank==posPoint->secondBest[suit].rank)) - weight=suitWeightDelta+31; + weight=suitWeightDelta+35/*31*/; else - weight=suitWeightDelta+13-(mp->rank); + weight=suitWeightDelta+17/*13*/-(mp->rank); /* Encourage playing cards that previously caused search cutoff or was stored as the best move in a transposition table entry match. */ if ((bestMove[depth].suit==suit)&& (bestMove[depth].rank==mp->rank)) - weight+=17; - else if ((bestMoveTT[depth].suit==suit)&& + weight+=18/*17*/; + /*else if ((bestMoveTT[depth].suit==suit)&& (bestMoveTT[depth].rank==mp->rank)) - weight+=(3/*4*//*10*//*9*/); + weight+=4;*/ } break; @@ -4184,21 +4195,21 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(43/*36*/); + suitAdd=(suitCount<<6)/(44/*36*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=2; + /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=2;*/ if (suit==trump) - weight=25/*23*/-(mp->rank)+suitAdd; + weight=24-(mp->rank)+suitAdd; else weight=60-(mp->rank)+suitAdd; /* Better discard than ruff since rho wins anyway */ } else if (k > bitMapRank[mp->rank]) - weight=40/*41*/+rRank; + weight=40+rRank; /* If lowest card for partner to leading hand is higher than lho played card, playing as low as @@ -4206,7 +4217,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& (posPoint->rankInSuit[first][leadSuit] > ll)) - weight=37/*40*/+rRank; + weight=41+rRank; /* If rho has a card in the leading suit that is higher than the trick leading card but lower @@ -4216,49 +4227,49 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, 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 + weight=78-(mp->rank); /* 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=70-(mp->rank); /* If played card is higher than any cards at partner + 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 (mp->sequence) - weight=62/*63*//*60*/-(mp->rank); + weight=62-(mp->rank); else - weight=48/*45*/-(mp->rank); + weight=49-(mp->rank); } } else if (posPoint->length[rho[first]][leadSuit]>0) { - if (mp->sequence) - weight=47/*50*/-(mp->rank); /* Playing a card in a sequence may promote a winner */ + /*if (mp->sequence)*/ + weight=47-(mp->rank); /* Playing a card in a sequence may promote a winner */ /* Insensistive */ - else - weight=45-(mp->rank); + /*else + weight=47-(mp->rank);*/ } else - weight=43/*45*/-(mp->rank); + weight=40-(mp->rank); } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(33/*36*/); + suitAdd=(suitCount<<6)/36; /* Discourage suit discard if 2nd highest card becomes singleton. */ if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(4/*2*/); + suitAdd+=-4; if (suit==trump) { - weight=16/*15*/-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick + weight=15-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick costly for the opponents */ } else - weight=-6-(mp->rank)+suitAdd; + weight=-2-(mp->rank)+suitAdd; } else if ((k > bitMapRank[mp->rank])|| (l > bitMapRank[mp->rank])) - weight=-7/*-9*/+rRank; + weight=-9+rRank; /* If lowest rank for either partner to leading hand or rho is higher than played card for lho, @@ -4266,12 +4277,12 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, else if (mp->rank > posPoint->move[depth+1].rank) { if (mp->sequence) - weight=19/*19*/-(mp->rank); + weight=22-(mp->rank); else weight=10-(mp->rank); } else - weight=-17+rRank; + weight=-16+rRank; } break; @@ -4317,37 +4328,37 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, if (winMove) { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(48/*36*/); + suitAdd=(suitCount<<6)/(50/*36*/); /* Discourage suit discard if 2nd highest card becomes singleton. */ - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(3/*2*/); + /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(3);*/ if (posPoint->high[depth+1]==first) { if (suit==trump) - weight=30-(mp->rank)+suitAdd; /* Ruffs partner's winner */ + weight=48-(mp->rank)+suitAdd; /* Ruffs partner's winner */ else - weight=60-(mp->rank)+suitAdd; + weight=61-(mp->rank)+suitAdd; } else if (WinningMove(mp, &(posPoint->move[depth+1]))) /* Own hand on top by ruffing */ - weight=70-(mp->rank)+suitAdd; + weight=72-(mp->rank)+suitAdd; } else - weight=60-(mp->rank); + weight=58-(mp->rank); } else { if (!notVoidInSuit) { suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/36; + suitAdd=(suitCount<<6)/40; /* Discourage suit discard if 2nd highest card becomes singleton. */ - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(4/*2*/); + /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(4);*/ if (WinningMove(mp, &(posPoint->move[depth+1]))) @@ -4358,9 +4369,9 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, /* Discard a trump but still losing */ - weight=-/*33*/36+rRank+suitAdd; + weight=-32+rRank+suitAdd; else - weight=-(mp->rank)+suitAdd; + weight=-2-(mp->rank)+suitAdd; } else { k=posPoint->rankInSuit[rho[first]][suit]; @@ -4369,21 +4380,21 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, /* If least bit map rank of RHO to lead hand is higher than bit map rank of current card move. */ - weight=-(mp->rank); + weight=-3-(mp->rank); else if (WinningMove(mp, &(posPoint->move[depth+1]))) { /* If current card move is highest so far. */ if (mp->rank==posPoint->secondBest[leadSuit].rank) - weight=25; + weight=29; else if (mp->sequence) - weight=21/*20*/-(mp->rank); + weight=26/*20*/-(mp->rank); else - weight=10-(mp->rank); + weight=18-(mp->rank); } else - weight=-10-(mp->rank); + weight=-12-(mp->rank); } } @@ -4394,7 +4405,7 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, suitCount=posPoint->length[q][suit]; suitAdd=(suitCount<<6)/(24/*36*/); if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(2/*0*//*2*/); + suitAdd-=(2); if ((posPoint->high[depth+1])==lho[first]) { @@ -4453,6 +4464,8 @@ int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, return weight; } + + /* Shell-1 */ /* K&R page 62: */ /*void shellSort(int n, int depth) { @@ -5207,12 +5220,12 @@ void BuildSOP(struct pos * posPoint, long long suitLengths, } } - suitLengths=0; + /*suitLengths=0; for (ss=0; ss<=2; ss++) for (hh=0; hh<=3; hh++) { suitLengths=suitLengths<<4; suitLengths|=posPoint->length[hh][ss]; - } + }*/ np=SearchLenAndInsert(rootnp[tricks][firstHand], suitLengths, TRUE, &res); @@ -5319,6 +5332,7 @@ int CheckDeal(struct moveType * cardp) { } + int NextMove(struct pos *posPoint, int depth) { /* Returns TRUE if at least one move remains to be searched, otherwise FALSE is returned. */ @@ -5378,6 +5392,62 @@ int NextMove(struct pos *posPoint, int depth) { } +#if 0 +int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply) { + /* Returns TRUE if at least one move remains to be + searched, otherwise FALSE is returned. */ + + unsigned short int lw; + unsigned char suit; + struct moveType currMove=mply->move[mply->current]; + + + if (lowestWin[depth][currMove.suit]==0) { + /* A small card has not yet been identified for this suit. */ + lw=posPoint->winRanks[depth][currMove.suit]; + if (lw!=0) + lw=lw & (-lw); /* LSB */ + else + lw=bitMapRank[15]; + if (bitMapRank[currMove.rank]current<=(mply->last-1)) { + mply->current++; + if (bitMapRank[mply->move[mply->current].rank] >= + lowestWin[depth][mply->move[mply->current].suit]) { + return TRUE; + } + } + return FALSE; + } + else { + while (mply->current<=(mply->last-1)) { + mply->current++; + suit=mply->move[mply->current].suit; + if ((currMove.suit==suit) || + (bitMapRank[mply->move[mply->current].rank] >= + lowestWin[depth][suit])) { + return TRUE; + } + } + return FALSE; + } + } + else { + while (mply->current<=(mply->last-1)) { + mply->current++; + if (bitMapRank[mply->move[mply->current].rank] >= + lowestWin[depth][mply->move[mply->current].suit]) { + return TRUE; + } + } + return FALSE; + } +} +#endif + + int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode) { @@ -5887,5 +5957,670 @@ int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, #endif #endif +#ifdef PLUSVER +int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN, +struct ddTableResults * tablep, int vulnerable, struct parResults *presp) { + int res; + struct ddTableDeal tableDeal; + int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); + int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, + struct ddTableResults * tablep, struct parResults *presp); + + if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) + return -99; + + res=CalcPar(tableDeal, vulnerable, tablep, presp); + + return res; +} + +int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, +struct ddTableResults * tablep, struct parResults *presp) { + + int res; + + int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable); + + res=CalcDDtable(tableDeal, tablep); + + if (res!=1) + return res; + + res=Par(tablep, presp, vulnerable); + + return res; + +} +#endif + +int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable) { + /* vulnerable 0: None 1: Both 2: NS 3: EW */ + +/* The code for calculation of par score / contracts is based upon the + perl code written by Matthew Kidd ACBLmerge. He has kindly given me permission + to include a C++ adaptation in DDS. */ + +/* The Par function computes the par result and contracts. */ + + + int denom_conv[5]={4, 0, 1, 2, 3}; + /* Preallocate for efficiency. These hold result from last direction + (N-S or E-W) examined. */ + int i, j, k, m, isvul; + int current_side, both_sides_once_flag, denom_max, max_lower; + int new_score_flag, sc1, sc2; + int prev_par_denom=0, prev_par_tricks=0; + + int ut, t1, t2, tt, score, dr, ke, tu, tu_max, t3, t4, n; + struct par_suits_type par_suits[5]; + char contr_sep[2]={',','\0'}; + char temp[8], buff[4]; + + int par_denom[2] = {-1, -1}; /* 0-4 = NT,S,H,D,C */ + int par_tricks[2] = {6, 6}; /* Initial "contract" beats 0 NT */ + int par_score[2] = {0, 0}; + int par_sacut[2] = {0, 0}; /* Undertricks for sacrifice (0 if not sac) */ + + int rawscore(int denom, int tricks, int isvul); + void IniSidesString(int dr, int i, int t1, int t2, char stri[]); + int CalcMultiContracts(int max_lower, int tricks); + + /* Find best par result for N-S (i==0) or E-W (i==1). These will + nearly always be the same, but when we have a "hot" situation + they will not be. */ + + for (i=0; i<=1; i++) { + /* Start with the with the offensive side (current_side = 0) and alternate + between sides seeking the to improve the result for the current side.*/ + + current_side=0; both_sides_once_flag=0; + while (1) { + + /* Find best contract for current side that beats current contract. + Choose highest contract if results are equal. */ + + k=(i+current_side) % 2; + + isvul=((vulnerable==1)||(k ? (vulnerable==3) : (vulnerable==2))); + + new_score_flag=0; + prev_par_denom=par_denom[i]; + prev_par_tricks=par_tricks[i]; + + /* Calculate tricks and score values and + store them for each denomination in structure par_suits[5]. */ + + for (j=0; j<=4; j++) { + t1 = k ? tablep->resTable[denom_conv[j]][1] : tablep->resTable[denom_conv[j]][0]; + t2 = k ? tablep->resTable[denom_conv[j]][3] : tablep->resTable[denom_conv[j]][2]; + tt = Max(t1, t2); + /* tt is the maximum number of tricks current side can take in + denomination.*/ + par_suits[j].suit=j; + par_suits[j].tricks=tt; + if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) && + (j < par_denom[i]))) + par_suits[j].score=rawscore(j, tt, isvul); + else + par_suits[j].score=rawscore(-1, prev_par_tricks - tt, isvul); + } + + /* Sort the items in the par_suits structure with decreasing order of the + values on the scores. */ + + for (int s = 1; s < 5; s++) { + struct par_suits_type tmp = par_suits[s]; + int r = s; + for (; r && tmp.score > par_suits[r - 1].score ; --r) + par_suits[r] = par_suits[r - 1]; + par_suits[r] = tmp; + } + + /* Do the iteration as before but now in the order of the sorted denominations. */ + + for (m=0; m<=4; m++) { + j=par_suits[m].suit; + tt=par_suits[m].tricks; + + if ((tt > par_tricks[i]) || ((tt == par_tricks[i]) && + (j < par_denom[i]))) { + /* Can bid higher and make contract.*/ + score=rawscore(j, tt, isvul); + } + else { + /* Bidding higher in this denomination will not beat previous denomination + and may be a sacrifice. */ + ut=prev_par_tricks - tt; + if (j >= prev_par_denom) { + /* Sacrifices higher than 7N are not permitted (but long ago + the official rules did not prohibit bidding higher than 7N!) */ + if (prev_par_tricks == 13) + continue; + /* It will be necessary to bid one level higher, resulting in + one more undertrick. */ + ut++; + } + /* Not a sacrifice (due to par_tricks > prev_par_tricks) */ + if (ut <= 0) + continue; + /* Compute sacrifice.*/ + score=rawscore(-1, ut, isvul); + } + if (current_side == 1) + score=-score; + + if (((current_side == 0)&&(score > par_score[i])) || + ((current_side == 1)&&(score < par_score[i]))) { + new_score_flag = 1; + par_score[i] = score; + par_denom[i] = j; + + if (((current_side == 0)&&(score > 0)) || + ((current_side == 1)&&(score < 0))) { + /* New par score from a making contract. + Can immediately update since score at same level in higher + ranking suit is always >= score in lower ranking suit and + better than any sacrifice. */ + par_tricks[i] = tt; + par_sacut[i] = 0; + } + else { + par_tricks[i] = tt + ut; + par_sacut[i] = ut; + } + } + } + + if (!new_score_flag && both_sides_once_flag) + break; + both_sides_once_flag = 1; + current_side = 1 - current_side; + } + } + + presp->parScore[0][0]='N'; + presp->parScore[0][1]='S'; + presp->parScore[0][2]=' '; + presp->parScore[0][3]='\0'; + presp->parScore[1][0]='E'; + presp->parScore[1][1]='W'; + presp->parScore[1][2]=' '; + presp->parScore[1][3]='\0'; + + /*itoa(par_score[0], temp, 10);*/ + sprintf(temp, "%d", par_score[0]); + strcat(presp->parScore[0], temp); + /*itoa(par_score[1], temp, 10);*/ + sprintf(temp, "%d", par_score[1]); + strcat(presp->parScore[1], temp); + + for (i=0; i<=1; i++) { + presp->parContractsString[0][0]='N'; + presp->parContractsString[0][1]='S'; + presp->parContractsString[0][2]=':'; + presp->parContractsString[0][3]='\0'; + presp->parContractsString[1][0]='E'; + presp->parContractsString[1][1]='W'; + presp->parContractsString[1][2]=':'; + presp->parContractsString[1][3]='\0'; + } + + if (par_score[0] == 0) { + /* Neither side can make anything.*/ + return 1; + } + + + for (i=0; i<=1; i++) { + + if ( par_sacut[i] > 0 ) { + + dr = (par_score[i] > 0) ? 0 : 1; + + for (j=0/*par_denom[i]*/; j<=4; j++) { + + t1 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; + t2 = ((dr+i) % 2 ) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; + tt = (t1 > t2) ? t1 : t2; + + tu_max=0; + + for (m=0; m<=4; m++) { + t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; + t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; + tu = (t3 > t4) ? t3 : t4; + if (tu > tu_max) { + tu_max=tu; + denom_max=m; + } + } + + if (j >= par_denom[i]) { + if (((par_tricks[i] - par_sacut[i]) != tt) || ((par_denom[i] < denom_max) && (j > denom_max))) + continue; + } + else if ((denom_max < par_denom[i])&&(j < denom_max)) { + if ((par_tricks[i] - 1 - par_sacut[i]) != tt) + continue; + } + else { + if ((par_tricks[i] - par_sacut[i]) != tt) + continue; + } + + + IniSidesString(dr, i, t1, t2, buff); + + if (presp->parContractsString[i][3]!='\0') + strcat(presp->parContractsString[i], contr_sep); + + strcat(presp->parContractsString[i], buff); + + /*itoa(par_tricks[i]-6, temp, 10);*/ + if ((denom_max < par_denom[i]) && (j < denom_max)) + sprintf(temp, "%d", par_tricks[i]-7); + else + sprintf(temp, "%d", par_tricks[i]-6); + buff[0]=cardSuit[denom_conv[j]]; + buff[1]='x'; + buff[2]='\0'; + strcat(temp, buff); + strcat(presp->parContractsString[i], temp); + + stat_contr[0]++; + } + } + else { + /* Par contract is a makeable contract.*/ + dr = (par_score[i] < 0) ? 0 : 1; + + /* If spades or diamonds, lower major / minor may also be a par contract.*/ + ke = (par_denom[i] == 1 || par_denom[i] == 3) ? 1 : 0; + + for (j=par_denom[i]; j<=par_denom[i]+ke; j++) { + t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; + t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; + tt = (t1 > t2) ? t1 : t2; + + if (tt < par_tricks[i]) { continue; } + + IniSidesString(dr, i, t1, t2, buff); + + tu_max=0; + for (m=0; m<=4; m++) { + t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; + t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; + tu = (t3 > t4) ? t3 : t4; + if (tu > tu_max) { + tu_max=tu; + denom_max=m; /* Lowest denomination if several denominations have max tricks. */ + } + } + + if (presp->parContractsString[i][3]!='\0') + strcat(presp->parContractsString[i], contr_sep); + + strcat(presp->parContractsString[i], buff); + + if (denom_max < par_denom[i]) + max_lower = par_tricks[i] - tu_max - 1; + else + max_lower = par_tricks[i] - tu_max; + + /* max_lower is the maximal contract lowering, otherwise opponent contract is + higher. It is already known that par_score is high enough to make + opponent sacrifices futile. + To find the actual contract lowering allowed, it must be checked that the + lowered contract still gets the score bonus points that is present in par score.*/ + + sc2 = rawscore(par_denom[i], par_tricks[i], isvul); + /* Score for making the tentative lower par contract. */ + while (max_lower > 0) { + if (denom_max < par_denom[i]) + sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max, isvul); + else + sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, isvul); + /* Score for undertricks needed to beat the tentative lower par contract.*/ + if (sc2 < sc1) + break; + else + max_lower--; + /* Tentative lower par contract must be 1 trick higher, since the cost + for the sacrifice is too small. */ + } + + switch (par_denom[i]) { + case 0: k = 0; break; + case 1: case 2: k = 1; break; + case 3: case 4: k = 2; + } + + max_lower = Min(max_low[k][par_tricks[i]-6], max_lower); + + n = CalcMultiContracts(max_lower, par_tricks[i]); + + /*itoa(n, temp, 10);*/ + sprintf(temp, "%d", n); + buff[0]=cardSuit[denom_conv[j]]; + buff[1]='\0'; + strcat(temp, buff); + strcat(presp->parContractsString[i], temp); + + stat_contr[1]++; + } + + + /* Deal with special case of 3N/5m (+400/600) */ + if ((par_denom[i] == 0) && (par_tricks[i] == 9)) { + + for (j=3; j<=4; j++) { + t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; + t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; + tt = (t1 > t2) ? t1 : t2; + + if (tt != 11) { continue; } + + IniSidesString(dr, i, t1, t2, buff); + + if (presp->parContractsString[i][3]!='\0') + strcat(presp->parContractsString[i], contr_sep); + + strcat(presp->parContractsString[i], buff); + + /*itoa(5, temp, 10);*/ + sprintf(temp, "%d", 5); + buff[0]=cardSuit[denom_conv[j]]; + buff[1]='\0'; + strcat(temp, buff); + strcat(presp->parContractsString[i], temp); + + stat_contr[2]++; + } + + } + /* Deal with special case of 2S/2H (+110) which may have 3C and 3D + as additional par contract(s).*/ + if ((par_denom[i] <=2) && (par_denom[i] != 0) && (par_tricks[i] == 8)) { + /* Check if 3C and 3D make.*/ + for (j=3; j<=4; j++) { + t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; + t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; + tt = (t1 > t2) ? t1 : t2; + + if (tt != 9) { continue; } + + IniSidesString(dr, i, t1, t2, buff); + + tu_max=0; + + for (m=0; m<=4; m++) { + t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; + t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; + tu = (t3 > t4) ? t3 : t4; + if (tu > tu_max) { + tu_max=tu; + denom_max=m; + } + } + + if (presp->parContractsString[i][3]!='\0') + strcat(presp->parContractsString[i], contr_sep); + + strcat(presp->parContractsString[i], buff); + + if (denom_max < j) + max_lower = 9 - tu_max - 1; + else + max_lower = 9 - tu_max; + + /* max_lower is the maximal contract lowering, otherwise opponent contract is + higher. It is already known that par_score is high enough to make + opponent sacrifices futile. + To find the actual contract lowering allowed, it must be checked that the + lowered contract still gets the score bonus points that is present in par score.*/ + + sc2 = rawscore(par_denom[i], par_tricks[i], isvul); + /* Score for making the tentative lower par contract. */ + while (max_lower > 0) { + if (denom_max < j) + sc1 = -rawscore(-1, 9/*par_tricks[i] + 1*/ - max_lower - tu_max, isvul); + else + sc1 = -rawscore(-1, 9 - max_lower - tu_max + 1, isvul); + /* Score for undertricks needed to beat the tentative lower par contract.*/ + if (sc2 < sc1) + break; + else + max_lower--; + /* Tentative lower par contract must be 1 trick higher, since the cost + for the sacrifice is too small. */ + } + + switch (par_denom[i]) { + case 0: k = 0; break; + case 1: case 2: k = 1; break; + case 3: case 4: k = 2; + } + + max_lower = Min(max_low[k][3], max_lower); + + n = CalcMultiContracts(max_lower, 9); + + /*itoa(n, temp, 10);*/ + sprintf(temp, "%d", n); + buff[0]=cardSuit[denom_conv[j]]; + buff[1]='\0'; + strcat(temp, buff); + strcat(presp->parContractsString[i], temp); + + stat_contr[3]++; + } + } + /* Deal with special case 1NT (+90) which may have 2C or 2D as additonal par + contracts(s). */ + if ((par_denom[i] == 0) && (par_tricks[i] == 7)) { + for (j=3; j<=4; j++) { + t1 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][0] : tablep->resTable[denom_conv[j]][1]; + t2 = ((dr+i) % 2) ? tablep->resTable[denom_conv[j]][2] : tablep->resTable[denom_conv[j]][3]; + tt = (t1 > t2) ? t1 : t2; + + if (tt != 8) { continue; } + + IniSidesString(dr, i, t1, t2, buff); + + tu_max=0; + for (m=0; m<=4; m++) { + t3 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][0] : tablep->resTable[denom_conv[m]][1]; + t4 = ((dr+i) % 2 == 0) ? tablep->resTable[denom_conv[m]][2] : tablep->resTable[denom_conv[m]][3]; + tu = (t3 > t4) ? t3 : t4; + if (tu > tu_max) { + tu_max=tu; + denom_max=m; + } + } + + if (presp->parContractsString[i][3]!='\0') + strcat(presp->parContractsString[i], contr_sep); + + strcat(presp->parContractsString[i], buff); + + if (denom_max < j) + max_lower = 8 - tu_max - 1; + else + max_lower = 8 - tu_max; + + /* max_lower is the maximal contract lowering, otherwise opponent contract is + higher. It is already known that par_score is high enough to make + opponent sacrifices futile. + To find the actual contract lowering allowed, it must be checked that the + lowered contract still gets the score bonus points that is present in par score.*/ + + sc2 = rawscore(par_denom[i], par_tricks[i], isvul); + /* Score for making the tentative lower par contract. */ + while (max_lower > 0) { + if (denom_max < j) + sc1 = -rawscore(-1, 8 - max_lower - tu_max, isvul); + else + sc1 = -rawscore(-1, 8 - max_lower - tu_max + 1, isvul); + /* Score for undertricks needed to beat the tentative lower par contract.*/ + + if (sc2 < sc1) + break; + else + max_lower--; + /* Tentative lower par contract must be 1 trick higher, since the cost + for the sacrifice is too small. */ + } + + switch (par_denom[i]) { + case 0: k = 0; break; + case 1: case 2: k = 1; break; + case 3: case 4: k = 2; + } + + max_lower = Min(max_low[k][3], max_lower); + + n = CalcMultiContracts(max_lower, 8); + + /*itoa(n, temp, 10);*/ + sprintf(temp, "%d", n); + buff[0]=cardSuit[denom_conv[j]]; + buff[1]='\0'; + strcat(temp, buff); + strcat(presp->parContractsString[i], temp); + + stat_contr[4]++; + } + } + } + } + + return 1; +} + + +int rawscore(int denom, int tricks, int isvul) { + int game_bonus, level, score; + + /* Computes score for undoubled contract or a doubled contract with + for a given number of undertricks. These are the only possibilities + for a par contract (aside from a passed out hand). + + denom - 0 = NT, 1 = Spades, 2 = Hearts, 3 = Diamonds, 4 = Clubs + (same order as results from double dummy solver); -1 undertricks + tricks - For making contracts (7-13); otherwise, number of undertricks. + isvul - True if vulnerable */ + + if (denom==-1) { + if (isvul) + return -300 * tricks + 100; + if (tricks<=3) + return -200 * tricks + 100; + return -300 * tricks + 400; + } + else { + level=tricks-6; + game_bonus=0; + if (denom==0) { + score=10 + 30 * level; + if (level>=3) + game_bonus=1; + } + else if ((denom==1)||(denom==2)) { + score=30 * level; + if (level>=4) + game_bonus=1; + } + else { + score=20 * level; + if (level>=5) + game_bonus=1; + } + if (game_bonus) { + score+= (isvul ? 500 : 300); + } + else + score+=50; + + if (level==6) { + score+= (isvul ? 750 : 500); + } + else if (level==7) { + score+= (isvul ? 1500 : 1000); + } + } + + return score; +} + + +void IniSidesString(int dr, int i, int t1, int t2, char stri[]) { + + if ((dr+i) % 2 ) { + if (t1==t2) { + stri[0]='N'; + stri[1]='S'; + stri[2]=' '; + stri[3]='\0'; + } + else if (t1 > t2) { + stri[0]='N'; + stri[1]=' '; + stri[2]='\0'; + } + else { + stri[0]='S'; + stri[1]=' '; + stri[2]='\0'; + } + } + else { + if (t1==t2) { + stri[0]='E'; + stri[1]='W'; + stri[2]=' '; + stri[3]='\0'; + } + else if (t1 > t2) { + stri[0]='E'; + stri[1]=' '; + stri[2]='\0'; + } + else { + stri[0]='W'; + stri[1]=' '; + stri[2]='\0'; + } + } + return; +} + + +int CalcMultiContracts(int max_lower, int tricks) { + int n; + + switch (tricks-6) { + case 5: if (max_lower==3) {n = 2345;} + else if (max_lower==2) {n = 345;} + else if (max_lower==1) {n = 45;} + else {n = 5;} + break; + case 4: if (max_lower==3) {n = 1234;} + else if (max_lower==2) {n = 234;} + else if (max_lower==1) {n = 34;} + else {n = 4;} + break; + case 3: if (max_lower==2) {n = 123;} + else if (max_lower==1) {n = 23;} + else {n = 3;} + break; + case 2: if (max_lower==1) {n = 12;} + else {n = 2;} + break; + default: n = tricks-6; + } + return n; +} + + diff --git a/dll.h b/dll.h index 63ca7bd2..37dad191 100644 --- a/dll.h +++ b/dll.h @@ -31,11 +31,11 @@ /* end of portability-macros section */ -#define DDS_VERSION 10118 /* Version 1.1.18. Allowing for 2 digit +#define DDS_VERSION 10119 /* Version 1.1.19. Allowing for 2 digit minor versions */ /*#define BENCH*/ -/*#define PBN*/ +#define PBN #define PLUSVER @@ -253,6 +253,19 @@ struct ddTableResults { int resTable[5][4]; }; +struct parResults { + char parScore[2][16]; /* index = 0 is NS view and index = 1 is EW view. */ + char parContractsString[2][128]; /* index = 0 is NS view and index = 1 + is EW view. By “view” is here meant + which side that starts the bidding. */ +}; + +struct par_suits_type { + int suit; + int tricks; + int score; +}; + extern struct gameInfo game; /*extern int newDeal;*/ @@ -332,6 +345,10 @@ EXTERN_C DLLEXPORT int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep); EXTERN_C DLLEXPORT int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep); +EXTERN_C DLLEXPORT int STDCALL CalcPar(struct ddTableDeal tableDeal, int vulnerable, + struct ddTableResults * tablep, struct parResults *presp); +EXTERN_C DLLEXPORT int STDCALL CalcParPBN(struct ddTableDealPBN tableDealPBN, + struct ddTableResults * tablep, int vulnerable, struct parResults *presp); #else EXTERN_C DLLEXPORT int STDCALL SolveBoard(struct deal dl, int target, int solutions, int mode, struct futureTricks *futp); @@ -348,7 +365,7 @@ void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[], int first, int mtd); int ABsearch(struct pos * posPoint, int target, int depth); void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth); + int depth, struct movePlyType *mply); int MoveGen(struct pos * posPoint, int depth); void MergeSort(int n, struct moveType *a); inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2); @@ -376,7 +393,8 @@ int CheckDeal(struct moveType * cardp); int InvBitMapRank(unsigned short bitMap); int InvWinMask(int mask); void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, int target, int depth); -int NextMove(struct pos *posPoint, int depth); +int NextMove(struct pos *posPoint, int depth); +/*int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply);*/ int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode); void Wipe(void); void AddNodeSet(void); diff --git a/release_notes.txt b/release_notes.txt index 541610b9..ec5c51d1 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -397,6 +397,11 @@ Change of license from GPL to Apache 2.0. Some minor changes in the WeightAlloc functions. +Release Notes DDS 1.1.19 +------------------------ +New build of dds.lib for meeting requirements in Visual C++ 2013. +Many code changes to improve performance. +Added par calculation in the "plus" version.