From c852cc2650a2484b924fab5eb46327ae97bc09fc Mon Sep 17 00:00:00 2001 From: Bo Haglund Date: Mon, 26 May 2014 16:37:08 -0400 Subject: [PATCH] historical commit dds 2.5.2 --- DLL-dds_251_t.rtf => DLL-dds_252_t.rtf | 1476 +-- DLL-dds_252_t.txt | 345 + dds.cpp | 14258 ++++++++++++----------- dll.h | 1100 +- readme.txt | 128 +- release_notes.txt | 6 + 6 files changed, 8846 insertions(+), 8467 deletions(-) rename DLL-dds_251_t.rtf => DLL-dds_252_t.rtf (98%) create mode 100644 DLL-dds_252_t.txt diff --git a/DLL-dds_251_t.rtf b/DLL-dds_252_t.rtf similarity index 98% rename from DLL-dds_251_t.rtf rename to DLL-dds_252_t.rtf index 596dd876..f82d0f7d 100644 --- a/DLL-dds_251_t.rtf +++ b/DLL-dds_252_t.rtf @@ -1,739 +1,739 @@ -{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1053\deflangfe1053\themelang1053\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} -{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} -{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} -{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} -{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} -{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} -{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} -{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} -{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} -{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} -{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} -{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} -{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} -{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} -{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} -{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} -{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} -{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} -{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} -{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} -{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} -{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} -{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} -{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} -{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} -{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} -{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} -{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; -\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp -\fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 -\rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 -\rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink15 \sqformat heading 1;}{ -\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink16 \sqformat -heading 2;}{\s3\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 -\sbasedon0 \snext0 \slink17 \sqformat heading 3;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* -\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 -\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;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid488565\rsid490522\rsid532764 -\rsid543320\rsid556337\rsid617158\rsid750573\rsid876335\rsid930020\rsid940090\rsid1187219\rsid1190356\rsid1191142\rsid1202844\rsid1258951\rsid1261441\rsid1445386\rsid1706832\rsid1770393\rsid2060511\rsid2112235\rsid2112392\rsid2181632\rsid2260548 -\rsid2427760\rsid2443070\rsid2446079\rsid2641133\rsid2894529\rsid3036029\rsid3347855\rsid3547548\rsid3819803\rsid4460640\rsid4538894\rsid4542728\rsid4602097\rsid4675069\rsid4679726\rsid4981561\rsid5332441\rsid5462095\rsid5525810\rsid5712409\rsid6228168 -\rsid6309374\rsid6309794\rsid6362316\rsid6436444\rsid6499600\rsid6569652\rsid6633554\rsid6650094\rsid6845226\rsid6950962\rsid7041439\rsid7089377\rsid7167315\rsid7421144\rsid7616262\rsid7683346\rsid7807046\rsid7949161\rsid7952569\rsid8000484\rsid8001475 -\rsid8090374\rsid8137115\rsid8527940\rsid8541195\rsid8593145\rsid8799536\rsid8983788\rsid8999377\rsid9002512\rsid9047914\rsid9125746\rsid9175287\rsid9314635\rsid9515749\rsid9530285\rsid9907738\rsid10245607\rsid10426263\rsid10631094\rsid11078728 -\rsid11279197\rsid11297517\rsid12068517\rsid12087407\rsid12156867\rsid12530193\rsid12595779\rsid12732549\rsid12788235\rsid12854747\rsid12982360\rsid12986669\rsid12992185\rsid13174672\rsid13180120\rsid13250408\rsid13316938\rsid13319718\rsid13336457 -\rsid13714332\rsid13915886\rsid14095979\rsid14102810\rsid14169293\rsid14295269\rsid14370947\rsid14892228\rsid15031452\rsid15620535\rsid15821976\rsid16147558\rsid16405367\rsid16470149\rsid16610750\rsid16655487\rsid16724586}{\mmathPr\mmathFont34\mbrkBin0 -\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy21\hr14\min22}{\revtim\yr2014\mo3\dy7\hr17\min56}{\version101}{\edmins831}{\nofpages10}{\nofwords3136} -{\nofchars16621}{\nofcharsws19718}{\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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Bo Haglund, Bob Richardson -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12992185 \hich\af31506\dbch\af31505\loch\f31506 Rev T, 2014-03-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 Latest DLL issue with this description is available at }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\lang1053\langfe1053\langnp1053\insrsid4538894\charrsid13915886 {\*\datafield -00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 -0000a5ab00000000004b00000079000000000075000b00006d000000000b01000000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\ul\cf2\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\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 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Short description of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid11078728 -\hich\af31506\dbch\af31505\loch\f31506 ouble Dummy Problem Solver 2.4}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 -\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 -\f31506\cf1\insrsid6650094\charrsid13915886 -\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, -\par \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); -\par -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, -\par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); -\par -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, \line struct ddTableResults * tablep); -\par -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDt\hich\af31506\dbch\af31505\loch\f31506 ablePBN(struct ddTableDealPBN\line tableDealPBN, struct ddTableResults * tablep);}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid488565 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 extern \'93\loch\f31506 \hich\f31506 C\'94\loch\f31506 -__declspec(dllimport) int __stdcall }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 CalcAllTables(struct ddTableDeals *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \line }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 struct ddTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 \hich\af37\dbch\af31505\loch\f37 Res *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 -\hich\af37\dbch\af31505\loch\f37 struct allParResults}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7041439 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 \hich\f37 extern \'93\loch\f37 \hich\f37 C\'94\loch\f37 -__declspec(dllimport) int __stdcall CalcAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 -(struct ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN\line *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], struct ddTablesRes *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 -\par \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 struct allParResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid488565 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveAll\hich\af31506\dbch\af31505\loch\f31506 Boards(struct boardsPBN *bop, -\par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards *solvedp); }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12992185 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid12992185 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 \hich\af37\dbch\af31505\loch\f37 extern "C" __declspec(dllimport) int __stdcall SolveAll}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185 \hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 -\hich\af37\dbch\af31505\loch\f37 (struct boardsPBN *bop, -\par \hich\af37\dbch\af31505\loch\f37 struct solvedBoards *}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185 \hich\af37\dbch\af31505\loch\f37 solved, int chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 -\hich\af37\dbch\af31505\loch\f37 );}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12992185\charrsid13915886 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid12986669 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); -\par -\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, -\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2894529 \hich\af31506\dbch\af31505\loch\f31506 esults * tablep, int vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 , struct parResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 -\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 SolveBoard is threa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 d-safe, so several threads }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 can call SolveBoard in parallel.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 The actual}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 maximum number is configured at initial start-up, this number is maximum 16. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 - -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Before SolveBoard can be called, a structure of type "futureTricks" must be declared. -\par -\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveBoard}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - returns a status integer, "no fault" means the DLL supplies the trick data in\hich\af31506\dbch\af31505\loch\f31506 the "futureTricks" type structure.\line Status codes: -\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, -\par \hich\af31506\dbch\af31505\loch\f31506 -1=Unknown fault, -\par \hich\af31506\dbch\af31505\loch\f31506 -2=No of cards = 0, -\par \hich\af31506\dbch\af31505\loch\f31506 -3=target > Number of tricks left, -\par \hich\af31506\dbch\af31505\loch\f31506 -4=Duplicated cards, -\par \hich\af31506\dbch\af31505\loch\f31506 -5=target < -1, -\par \hich\af31506\dbch\af31505\loch\f31506 -7=target >13, -\par \hich\af31506\dbch\af31505\loch\f31506 -8=solutions < 1, -\par \hich\af31506\dbch\af31505\loch\f31506 -9=solutions > 3, -\par \hich\af31506\dbch\af31505\loch\f31506 -10=No of cards > 52 -\par \hich\af31506\dbch\af31505\loch\f31506 -11=Not used -\par \hich\af31506\dbch\af31505\loch\f31506 -12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. -\par \hich\af31506\dbch\af31505\loch\f31506 -13=Card already played in the current trick is also defined as a remaining card to play. -\par \hich\af31506\dbch\af31505\loch\f31506 -14=Wrong number of remaining cards for a hand. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -15=threadIndex < 0 or >=noOfThreads, noOfThreads is the configured maximum number of threads}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 .\line \hich\af31506\dbch\af31505\loch\f31506 \line \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines all data needed to describe the deal to be analyzed. -\par \hich\af31506\dbch\af31505\loch\f31506 struct deal \{}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int trump; /\hich\af31506\dbch\af31505\loch\f31506 -* 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 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\rtlch\fcs1 \af0 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in \hich\af31506\dbch\af31505\loch\f31506 -the order played */ -\par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickRank[3]; /* 2-14 for up to 3 cards}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6436444 \hich\af31506\dbch\af31505\loch\f31506 . Suits and ranks set to 0 otherwise.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6436444\charrsid6436444 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 unsigned int remainCards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\super\insrsid6650094\charrsid13915886 -\hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index hand (0-3), 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 , \'85\'85\'85\loch\f31506 . bit 14=rank 14, bit 15=0}{\rtlch\fcs1 \af0 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -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 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par -\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 is the number of tricks to be won by the side to play, -1 means that the program}{\rtlch\fcs1 \af0 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 shall find the }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 maximum number. For equivalent }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 cards only the highest is returned. -\par \line \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 solutions}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\hich\af31506\dbch\af31505\loch\f31506 defines how many card solutions that SolveBoard must return: -\par \hich\af31506\dbch\af31505\loch\f31506 target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target when}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target or higher tricks can be won. Otherwise, score \hich\f31506 \endash \loch\f31506 1 is returned if target cannot be -\hich\af31506\dbch\af31505\loch\f31506 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\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 target 1-13, solutions=2: Return all\hich\af31506\dbch\af31505\loch\f31506 - 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\f31506 \endash \loch\f31506 -1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 arget \hich\f31506 \endash \loch\f31506 -1, solutions=2: Return all optimum cards with their scores. -\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=2: Return all cards legal to play with scores set to 0}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf6\insrsid6650094\charrsid13915886 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 - target irrelevant, solutions=3: Return all cards that can be legally played w}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 ith their scores in descendin\hich\af31506\dbch\af31505\loch\f31506 g }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 order. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 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\f31506 \endash \loch\f31506 2 for this card, indicating that there are no alternative c -\hich\af31506\dbch\af31505\loch\f31506 ards. 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\f31506 \rquote \loch\f31506 t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 -\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115 \hich\af37\dbch\af31505\loch\f37 a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115\charrsid8137115 \hich\af37\dbch\af31505\loch\f37 -lways search to find the score. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par \hich\af31506\dbch\af31505\loch\f31506 mode=1: Always }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 search to find the score. Even when the hand to play has only one card, with -\hich\af31506\dbch\af31505\loch\f31506 - possible equivalents, to play. For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mod -\hich\af31506\dbch\af31505\loch\f31506 e\hich\af31506\dbch\af31505\loch\f31506 =2 is no longer needed in this case, but can still be done for backwards compatibility.\line - mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL t\hich\af31506\dbch\af31505\loch\f31506 o\hich\af31506\dbch\af31505\loch\f31506 - 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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - 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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \tab 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call: SolveBoard(deal, -1, 1, -\hich\af31506\dbch\af31505\loch\f31506 2, &fut, 0), deal.first=2, i.e. South leads. -\par \hich\af31506\dbch\af31505\loch\f31506 \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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 futureTricks}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\hich\af31506\dbch\af31505\loch\f31506 \{ /* The DLL provides \hich\af31506\dbch\af31505\loch\f31506 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 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int nodes; /* Number of searched nodes */ -\par \hich\af31506\dbch\af31505\loch\f31506 int cards; /* No of alternative cards */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int suit[13]; \hich\af31506\dbch\af31505\loch\f31506 /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ -\par \hich\af31506\dbch\af31505\loch\f31506 int rank[13]; /* 2-14 for 2 through Ace *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 / -\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 -int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When there are several \'94\loch\f31506 \hich\f31506 equals\'94\loch\f31506 \hich\f31506 -, the value is the sum of each \'94\loch\f31506 \hich\f31506 equal\'94\loch\f31506 . *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 /}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 int score[13]; /* -1 indicates th\hich\af31506\dbch\af31505\loch\f31506 at target was not reached, otherwise target or max numbe of tricks */}{\rtlch\fcs1 \af0 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par -\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 threadIndex}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the identity of the thread used when calling SolveBoard. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 A configured maximum number of}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\hich\af31506\dbch\af31505\loch\f31506 threads can call SolveBoard in parallel, threadIndex must}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 b\hich\af31506\dbch\af31505\loch\f31506 -e an integer in the range 0..max number of threads - 1. This maximum number is configured at DLL initial start-up and cannot exceed 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 SolveBoardPBN -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 In SolveBoardPBN the remaining cards in the deal information are given in PBN text -\par \hich\af31506\dbch\af31505\loch\f31506 format (e.g. \line W:T5.K\hich\af31506\dbch\af31505\loch\f31506 -4.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\af31506\dbch\af31505\loch\f31506 struct dealPBN \{ -\par \hich\af31506\dbch\af31505\loch\f31506 int trump; -\par \hich\af31506\dbch\af31505\loch\f31506 int first; -\par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int curre\hich\af31506\dbch\af31505\loch\f31506 ntTrickRank[3]; -\par \hich\af31506\dbch\af31505\loch\f31506 char remainCards[80]; /* First character identifies the hand having the cards given first -\par \hich\af31506\dbch\af31505\loch\f31506 in the string, then the cards of the other hands are given in a -\par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 clock-wise order, see example \hich\af31506\dbch\af31505\loch\f31506 above. Null characters fill out -\par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 the character array at the end. */ -\par \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 -\par -\par \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable -\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 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 -\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 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid1770393 \hich\af31506\dbch\af31505\loch\f31506 calculates the double}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 dummy values of the initial 52 cards for all the 20 trump suit/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 -\f31506\insrsid6650094\charrsid13915886 -\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 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 -\b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.\line Status codes: -\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, -\par \hich\af31506\dbch\af31505\loch\f31506 Other status codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 -\hich\af31506\dbch\af31505\loch\f31506 ddTableDeal}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the dealt cards to be analyzed.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDeal \{ -\par \hich\af31506\dbch\af31505\loch\f31506 unsigned int cards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is hand, 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is suit, same coding as \hich\af31506\dbch\af31505\loch\f31506 for deal.remainCards for SolveBoard. */ -\par \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 ddTableResults} -{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \{ /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 int resTable[5][4];\tab /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No T\hich\af31506\dbch\af31505\loch\f31506 rump 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - index is declarer hand, 0=North, 1=East, 2=South, 3=West */ -\par \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par -\par -\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtablePBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\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\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is \hich\af31506\dbch\af31505\loch\f31506 identical to CalcDDtable. -\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 -\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDealPBN \{ -\par \hich\af31506\dbch\af31505\loch\f31506 char cards[80]; -\par \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112235 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid2112235\charrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 CalcAllTables -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 calculates }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the double dummy values }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 -\hich\af37\dbch\af31505\loch\f37 of the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 trump suit/declarer hand combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 -\hich\af37\dbch\af31505\loch\f37 for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 a number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 DD table}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 s in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 . This increases}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 the speed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 -\hich\af37\dbch\af31505\loch\f37 compared to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4602097 \hich\af37\dbch\af31505\loch\f37 calculating}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 se values}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 using a }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 CalcDDtable call }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 for each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 -\hich\af37\dbch\af31505\loch\f37 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 -\par \hich\af37\dbch\af31505\loch\f37 The maximum number of DD tables in a CallAllTables call depends on the number of strains (the number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 5 }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 trump alternatives, any of th\hich\af37\dbch\af31505\loch\f37 -e 4 suits and no trump) to be part of the DD calculations. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14102810 \hich\af37\dbch\af31505\loch\f37 of DD tables that can b\hich\af37\dbch\af31505\loch\f37 e included in a CallAllTable call is 10. -}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 At fewer strains the maximum number of DD tables in a call is higher:}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 4 strains maximum 12 DD tables -\par \hich\af37\dbch\af31505\loch\f37 3 strains maximum 16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 -\par \hich\af37\dbch\af31505\loch\f37 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 strains maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 25}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 -\par \hich\af37\dbch\af31505\loch\f37 1 strain}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 50}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 AllT}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 able}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 -\hich\af37\dbch\af31505\loch\f37 can be called, a st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 ructure of type "ddTable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 s -}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 Res}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 " must be declared.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid5525810 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid16610750 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 returns a status integer, "no fault" means the DLL supplies the double dum}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 -my scores in the "ddTablesRes}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 " type structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441 \hich\af37\dbch\af31505\loch\f37 \hich\f37 - Its contained structure of type \'93\loch\f37 \hich\f37 ddTableResults\'94\loch\f37 is d\hich\af37\dbch\af31505\loch\f37 escribed for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 -\hich\f37 The variable \'93\loch\f37 \hich\f37 noOfBoards\'94\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 show}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 -s the number of solved boards (max 200).}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid940090 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTablesRes \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid940090 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718\charrsid13319718 \hich\af37\dbch\af31505\loch\f37 int noOfBoards;}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid13319718\charrsid940090 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTableResults results[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 ]; -\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441\charrsid6569652 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 Status codes: -\par \hich\af37\dbch\af31505\loch\f37 1=No fault,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8983788 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 -201=Error, all trump suits an}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 d the no trump suit alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 have been marked in the\line - calling parameter trumpFilter to be left out (i.e. they have }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 all }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2181632 \hich\af37\dbch\af31505\loch\f37 -been set to TRUE),}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12087407 \hich\af37\dbch\af31505\loch\f37 -202=Error, too many DD tables in the call. -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 -\par \hich\af37\dbch\af31505\loch\f37 \hich\f37 Structure \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid940090\charrsid6228168 \hich\af37\dbch\af31505\loch\f37 ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 -\loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 con\hich\af37\dbch\af31505\loch\f37 tains }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 up to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 -\hich\af37\dbch\af31505\loch\f37 5}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 0 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 DD table }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 \hich\f37 deals, each in a structure \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 , -\par \hich\af37\dbch\af31505\loch\f37 described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The actual number is set in the \'93\loch\f37 \hich\f37 noOfTables\'94\loch\f37 - parameter.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeals \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid6633554 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746\charrsid6633554 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeal deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 ]; -\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid532764\charrsid12854747 \hich\af37\dbch\af31505\loch\f37 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid532764 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 specifies whether or not par score and par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 wi}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 ll be calculated\line and if so, wh}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 ich sides that are vulnerable:\line -1}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 : }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 -no par calculation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3547548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 0:\tab par calculation, vulnerability None -\par \hich\af37\dbch\af31505\loch\f37 1:\tab par calculation, vulnerability All -\par \hich\af37\dbch\af31505\loch\f37 2:\tab par calculation, \hich\af37\dbch\af31505\loch\f37 vulnerability NS}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid3547548\charrsid3547548 -\par \hich\af37\dbch\af31505\loch\f37 3:\tab par calculation, vulnerability EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The results of the par calculations are given in the structure \'93\loch\f37 \hich\f37 allParResults\'94, -\par \hich\af37\dbch\af31505\loch\f37 which contains the results for all boards. Each board results are given\line \hich\f37 in structure \'93\loch\f37 \hich\f37 parResults\'94\loch\f37 , described fo\hich\af37\dbch\af31505\loch\f37 r the CalcPar function. - -\par -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct allParResults \{ -\par \hich\af37\dbch\af31505\loch\f37 struct parResults presults[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 -\hich\af37\dbch\af31505\loch\f37 ]; -\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\b\f37\cf1\insrsid12854747\charrsid7949161 \hich\af37\dbch\af31505\loch\f37 trumpFilter}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 describes which, if any, of the trump suits or the no trump suit -}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7949161 \line \hich\af37\dbch\af31505\loch\f37 alternatives that will be excluded from the calculations.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 They are defined in the order Spades, Hearts, Diamonds, Clubs and No Trump}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 . E.g. setting trumpFilter to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \{\hich\af37\dbch\af31505\loch\f37 FALSE, FALSE, TRUE, TRUE, TRUE\} - means that values will only be calculated for}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \hich\af37\dbch\af31505\loch\f37 -the trump suits Spades and Hearts. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5712409 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 CalcAllTablesPBN -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 As for CalcAllTab\hich\af37\dbch\af31505\loch\f37 les except that the deals are given in PBN format. The structure\line \hich\f37 \'93\loch\f37 \hich\f37 -ddTableDealPBN\'94\loch\f37 is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 described}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 for the CalcDDtablePBN }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 \hich\af37\dbch\af31505\loch\f37 function.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 -\par -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid2260548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealsPBN \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid2260548 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386\charrsid2260548 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealPBN deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 ]; -\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid12982360 -\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid9907738 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 -\b\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid7616262\charrsid7616262 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 A \'93\loch\f31506 \hich\f31506 chunk\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 - is a collection of boards to be }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 solved by the same thread. -\par \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9907738 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 solves a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \hich\af31506\dbch\af31505\loch\f31506 number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \hich\af31506\dbch\af31505\loch\f31506 -s in parallel for increased performance compared to solve them sequentionally using a SolveBoard call for each board.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 is called with a buffer\hich\af31506\dbch\af31505\loch\f31506 containi} -{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 ng }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 board dat}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 for a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 -\hich\af31506\dbch\af31505\loch\f31506 number of boards, maximum 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -00 boards per call. Each board is defined with the same input data as in SolveBoardPBN. The input data per board can be freely given independent of the settings for the other d}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 -\hich\af31506\dbch\af31505\loch\f31506 eals. SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s -}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 use\hich\af31506\dbch\af31505\loch\f31506 s multi-thread calls to SolveBoardPBN for solving the buffered boards.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 The chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 parameter in the SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 -\hich\af31506\dbch\af31505\loch\f31506 call specifies how many boards that are allocated per thread.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par -\par \hich\af31506\dbch\af31505\loch\f31506 struct boardsPBN \{ -\par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; -\par \hich\af31506\dbch\af31505\loch\f31506 struct dealPBN deals[MAXNOOFBOARDS]; -\par \hich\af31506\dbch\af31505\loch\f31506 int target[MAXNOOFBOARDS]; -\par \hich\af31506\dbch\af31505\loch\f31506 int solutions[MAXNOOFBOARDS]; -\par \hich\af31506\dbch\af31505\loch\f31506 int mode[MAXNOOFBOARDS]; -\par \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par -\par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards \{ -\par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; -\par \hich\af31506\dbch\af31505\loch\f31506 struct futureTricks solvedBoard[MAXNOOFBOARDS]; -\par \}\hich\af31506\dbch\af31505\loch\f31506 ; -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 In the SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call, the cards are coded in PBN text format usi -\hich\af31506\dbch\af31505\loch\f31506 ng the dealPBN structure. The number of boards to be solved must be defined in the boardsPBN structure, the number must not}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12595779 -\hich\af31506\dbch\af31505\loch\f31506 exceed MAXNOOFBOARDS which is 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 00. In the returned information in struct solvedBoards,}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 the number of solved boards is}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 given. The fut -\hich\af31506\dbch\af31505\loch\f31506 ureTricks information is provided for all solved boards with the same returned information per board as with SolveBoard. -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 \hich\af31506\dbch\af31505\loch\f31506 returns 1 if the call succeeds. In case chu}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid3036029 \hich\af31506\dbch\af31505\loch\f31506 n}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 \hich\af31506\dbch\af31505\loch\f31506 kSize is set to less than 1, the error code -201}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid3036029 \hich\af31506\dbch\af31505\loch\f31506 is given}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 otherwise }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 error\hich\af31506\dbch\af31505\loch\f31506 code}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 -\hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 identical to the SolveBoard}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid15821976 -\hich\af31506\dbch\af31505\loch\f31506 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 error codes is given when there is a problem in the input information.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid6650094 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13250408 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid13250408\charrsid13250408 \hich\af37\dbch\af31505\loch\f37 SolveAllBoards -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 -\par \hich\af37\dbch\af31505\loch\f37 SolveAllBoards gives the same results as calling Solve}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 All}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 -\hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 \hich\af37\dbch\af31505\loch\f37 with chunksize=1. Solve -\hich\af37\dbch\af31505\loch\f37 AllBoards is included to obtain DDS backward compatibility. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13250408\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Note}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s on DDS use for simulations} -{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 Setting parameter chunkSize to 1 in the call to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid543320 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 is optimal when th}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 e input boards are dissimilar. If however, a}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 djacent boards in the boards buffer are similar (same trump, very minor difference between ca}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 rds distribution between hands), then the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 transp}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 osition table information can often}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 be reused. }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 But it is then necessary that}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 these boards use }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 the same thread}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 For \hich\af31506\dbch\af31505\loch\f31506 example, when the simulation aims to find out which hand is best as declarer, the boards can be grouped in pairs where }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\cf1\insrsid2446079 \hich\af31506\dbch\af31505\loch\f31506 the two}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 board}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2446079 -\hich\af31506\dbch\af31505\loch\f31506 s in the pair have}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 different declarer }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 -\hich\af31506\dbch\af31505\loch\f31506 hand}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2446079 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 but otherwise are the same. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 \hich\af31506\dbch\af31505\loch\f31506 -In this case, chunkSize should be set to 2 for obtai\hich\af31506\dbch\af31505\loch\f31506 ning transposition table information reuse. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 In simulation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s involving }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different d}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid14169293 \hich\af31506\dbch\af31505\loch\f31506 eclarer hand alternatives and}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different trump }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 suit }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 -\hich\af31506\dbch\af31505\loch\f31506 alternatives, usage of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7167315 \hich\af31506\dbch\af31505\loch\f31506 Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 -\hich\af31506\dbch\af31505\loch\f31506 AllTables }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112392 \hich\af31506\dbch\af31505\loch\f31506 can be}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 - a more }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112392 \hich\af31506\dbch\af31505\loch\f31506 convenient}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\cf1\insrsid2060511 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcPar -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid556337 \hich\af31506\dbch\af31505\loch\f31506 CalcPar c}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -alculates the par score and par contracts of a given deal.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid750573 \hich\af31506\dbch\af31505\loch\f31506 - 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 th\hich\af31506\dbch\af31505\loch\f31506 -ere is no need to make a CalcDDtable call before calling CalcPar. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \line -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13915886 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid7683346 \hich\af31506\dbch\af31505\loch\f31506 Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 can be called, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 -\hich\af31506\dbch\af31505\loch\f31506 a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 structure of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 -\hich\af31506\dbch\af31505\loch\f31506 each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 type " ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 -\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 must be declared. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 CalcPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 - returns a status integer, "no fault" means the DLL supplies the double d\hich\af31506\dbch\af31505\loch\f31506 ummy scores in the "ddTableResults" type structure}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 -\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and the par results in the \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Calling CalcPar with the structure of type \'93\loch\f31506 \hich\f31506 ddTableDeal\'94\loch\f31506 - is done in the same way as for calling CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8527940 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269\charrsid13915886 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Status codes: -\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, -\par \hich\af31506\dbch\af31505\loch\f31506 Other sta\hich\af31506\dbch\af31505\loch\f31506 tus codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\insrsid1261441 \hich\af31506\dbch\af31505\loch\f31506 vulnerable}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f31506\insrsid1190356 \loch\af31506\dbch\af31505\hich\f31506 \'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 is set according to:}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 0 = None -\par \hich\af31506\dbch\af31505\loch\f31506 1 = Both sides -\par \hich\af31506\dbch\af31505\loch\f31506 2 = North / South side vulnerable -\par \hich\af31506\dbch\af31505\loch\f31506 3 = East / West side vulnerable -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 The structure t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12854747 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 ypes \'93\loch\f31506 \hich\f31506 -ddTableDeal\'94\loch\f31506 \hich\f31506 and \'93\loch\f31506 ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 esult\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 s\'94\loch\f31506 - are described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \line \hich\af31506\dbch\af31505\loch\f31506 -\hich\f31506 The \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure type }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 \hich\af31506\dbch\af31505\loch\f31506 includes the par score and the par contracts results returned by }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 the call to CalcPar: -\par -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 struct parResults \{ -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8541195 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 char parScore[2][16];\tab /* index = 0 is from NS view and index =1 is -\hich\af37\dbch\af31505\loch\f37 from EW view. */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 -\par \hich\af37\dbch\af31505\loch\f37 char parContractsString[2][128];}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 -/* index = 0 is NS view and index = 1 is EW view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 \hich\f37 By \'93\loch\f37 \hich\f37 view\'94\loch\f37 is -\par }\pard \ltrpar\ql \fi720\li2160\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2160\itap0\pararsid9314635 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 here meant which side that starts the bidding. }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 -\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1187219 -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid11297517 \hich\af31506\dbch\af31505\loch\f31506 Par score is give}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 n as a text string, e.g NS -460. NS lost 460}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 points.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid6650094 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 All par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 for different suits }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 are listed with comma separating }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 -\hich\af31506\dbch\af31505\loch\f31506 suits.\line Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 -\hich\af31506\dbch\af31505\loch\f31506 3, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 4 and 5 in }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13180120 \hich\af31506\dbch\af31505\loch\f31506 No trumps, are} -{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 given as 345N}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 . -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid3347855 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 Example of par contracts in different suits: -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726\charrsid4679726 \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,NS 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 This is from the NS view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 North}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 -\hich\af37\dbch\af31505\loch\f37 and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 South}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 as declarer make 2 }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 or 3 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 Hearts} -{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 contracts, 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and 2 H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 -\hich\af37\dbch\af31505\loch\f37 earts with an overtrick.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9515749 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749\charrsid9515749 \hich\af37\dbch\af31505\loch\f37 If only North could make 3 Hearts, the text string would h -\hich\af37\dbch\af31505\loch\f37 ave looked: -\par \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,N 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 NS before the colon refer}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13180120 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 the}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid12732549 \hich\af37\dbch\af31505\loch\f37 - assumed side that made the initial bid in the process for determining the par score / contracts}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 Also, DDS calculates the par score / contracts when the assumed side is EW: -\par \hich\af37\dbch\af31505\loch\f37 EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid14370947 \hich\af37\dbch\af31505\loch\f37 :NS 23S,N 23H }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3347855 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 -Nearly always, the par score / 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. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid3347855 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid490522\charrsid8593145 \hich\af37\dbch\af31505\loch\f37 CalcParPBN -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11279197 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The only difference compared to CalcPar is that the structure type -\'93\loch\f37 ddTableDeal\hich\af37\dbch\af31505\loch\f37 \hich\f37 PBN\'94\loch\f37 \hich\f37 is used instead of \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 \hich\f37 . For description of \'93\loch\f37 \hich\f37 ddTableDealPBN\'94\loch\f37 -, see CalcDDtablePBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197\charrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid490522 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522\charrsid13915886 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 -\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 -\f31506\cf1\insrsid6650094\charrsid13915886 -\par \hich\af31506\dbch\af31505\loch\f31506 Rev A, 2006-02-25.\tab \tab First issue. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev B, 2006-03-20\tab \tab Updated issue. -\par -\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev C, 2006-03-28\tab -\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Updated issue. Addition of the SolveBoard parameter \'94\loch\f31506 \hich\f31506 mode\'94. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev D, 2006-04-05\tab Updated issue. Usage of target=0 to list all cards that are legal to play. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev E, 2006-05-29\tab Updated issue. New error code \hich\f31506 \endash \loch\f31506 10 for number of cards > 52. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev F, 2006-08-09\tab Upda\hich\af31506\dbch\af31505\loch\f31506 ted issue. New mode parameter value = 2. New error code \hich\f31506 \endash \loch\f31506 -11 for calling SolveBoard with mode = 2 and forbidden values of other parameters. -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 -\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev F1, 2006-08-14\tab -Clarifications on conditions for returning scores for the different combinations of the values fo\hich\af31506\dbch\af31505\loch\f31506 r target and solutions. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev F2, 2006-08-26\tab New error code \hich\f31506 \endash \loch\f31506 12 for wrongly set valu}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9047914 \hich\af31506\dbch\af31505\loch\f31506 -es of deal.currentTrickSuit and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal.currentTrickRank. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev G, 2007-01-04\tab New DDS release 1.1, otherwise no change compared to isse F2. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev H, 2007-04-23\tab DDS release 1.4, c\hich\af31506\dbch\af31505\loch\f31506 hanges for parameter mode=2. -\par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6309374 \hich\af31506\dbch\af31505\loch\f31506 Rev I, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 2010-04-10\tab -DDS release 2.0, multi-thread support. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev J, 2010-05-29\tab DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev K, 2010-10-27\tab Correction of fault in the desc\hich\af31506\dbch\af31505\loch\f31506 ription: 2nd index in resTable of the structure ddTableResults is declarer hand. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev L, 2011-10-14\tab Added SolveBoardPBN and CalcDDtablePBN. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev M, 2012-07-06\tab Added SolveAllBoards. -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev N, 2012-07-16\tab Max number of threads is 8.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 -\par -\par \hich\af31506\dbch\af31505\loch\f31506 Rev O, 2012-10-21\tab \hich\af31506\dbch\af31505\loch\f31506 Max number of threads is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -configured at initial start-up, but never exceeds 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13316938 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 \hich\af37\dbch\af31505\loch\f37 Rev P, 2013-03-16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 \tab }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 -\hich\af37\dbch\af31505\loch\f37 Added functions CalcPar and CalcParPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9530285 \hich\af37\dbch\af31505\loch\f37 Rev Q, 2014-01-09}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962\charrsid6950962 \tab \hich\af37\dbch\af31505\loch\f37 Added functions Calc}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid6950962 \hich\af37\dbch\af31505\loch\f37 AllTables/CalcAllTablesPBN. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 -\par \hich\af37\dbch\af31505\loch\f37 Rev R, 2014-01-13\tab Updated }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779\charrsid12595779 \hich\af37\dbch\af31505\loch\f37 functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12595779 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377 -\par \hich\af37\dbch\af31505\loch\f37 Rev S}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377\charrsid7089377 \hich\af37\dbch\af31505\loch\f37 , 2014-01-13\tab Updated functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid7089377 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 -\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0\pararsid16724586 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Rev T, 2014-03-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid10245607\charrsid10245607 \tab }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Added function}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607\charrsid10245607 -\hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16724586 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6650094\charrsid16724586 -\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a -9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad -5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 -b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 -0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 -a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f -c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 -0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 -a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 -6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b -4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b -4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210036cc113fa8060000a31b0000160000007468656d652f7468656d652f -7468656d65312e786d6cec594f6f1b4514bf23f11d467b6f6327761a4775aad8b11b48d346b15bd4e37877bc3bcdecce6a669cd437d41e9190100571a012370e -08a8d44a5ccaa709144191fa157833b3bbde89d7246923a8a039b4f6ec6fdefff79b37ebabd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad -79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607f22d771db8b944ad79796a40fcb585ee62949e0d9988b182bf82ac2a540e023901bb3a5e55a6d -7529c634f1508263107b6b3ca63eb9a460abb791cbee31509028a9177c26065a327136186c7050d70839955d26d021666d0fd404fc6848ee2b0f312c153c687b -35f3e72d6d5c5dc2ebd926a616ec2dedeb9bbf6c5fb6213858363a45382a94d6fb8dd695ad42be0130358febf57add5ebd906700d8f7c1536b4b5966a3bf56ef -e4324b20fb715e76b7d6ac355c7c49feca9ccdad4ea7d36c65b658a106643f36e6f06bb5d5c6e6b28337208b6fcee11b9dcd6e77d5c11b90c5afcee1fb575aab -0d176f4011a3c9c11c5a27b4dfcfa417903167db95f03580afd532f80c05d55054975631e6895a546b31bec7451f001ac8b0a20952d3948cb10f45dcc5f14850 -ac15e075824b4fec922fe796b42e247d4153d5f63e4c3134c44cdeabe7dfbf7afe141d3f7876fce0a7e3870f8f1ffc680539bbb671129677bdfcf6b33f1f7f8c -fe78facdcb475f54e36519ffeb0f9ffcf2f3e7d540689f99392fbe7cf2dbb3272fbefaf4f7ef1e55c037051e95e1431a13896e9223b4cf6370cc44c5b59c8cc4 -f9760c234ccb3b369350e2046b2d15f27b2a72d037a79865d971ece81037827704d04715f0fae49e63f0201213452b34ef44b103dce59c75b8a88cc28ed6550a -f3709284d5cac5a48cdbc7f8b04a7717274e7e7b931478332f4bc7f16e441c33f7184e140e494214d2cff8012115dedda5d489eb2ef505977cacd05d8a3a9856 -866448474e35cd366dd318f232adf219f2edc466f70eea7056e5f516397491d0159855183f24cc09e3753c5138ae1239c4312b07fc065651959183a9f0cbb89e -5490e990308e7a0191b26acf2d01fe9692be8381b12ad3becba6b18b148a1e54c9bc81392f23b7f84137c2715a851dd0242a633f900750a218ed715505dfe56e -87e8ef90079c2c4cf71d4a9c749fce06b769e898342b10fd64222a72799d70a77e075336c6c4500d90bac3d5314dfe8eb81905e6b61a2e8eb8812a5f7cfdb8c2 -eeb795b237e1f4aaea99ed1344bd0877929ebb5c04f4ed67e72d3c49f60834c4fc11f58e9cdf91b3f79f27e745fd7cf1943c636120683d8bd841db8cddf1c2a9 -7b4c191ba8292337a419bc259c3d411f16f53e73e124c52d2c8de0a3ee6450e0e04281cd1e24b8fa88aa6810e11486f6baa7858432131d4a9472099745b35c29 -5be361f057f6aad9d49710cb1c12ab5d1ed8e515bd9cdf350a31c6aad05c6873452b5ac05995ad5cc984826fafa3acae8d3ab3b6ba31cd90a2a3ad705987d85c -ca21e4856bb0584413861a04a310447915aefc5a355c763023818ebbcd519e1693858b4c918c7040b21c69bfe773543749ca6b65ce11ed872d067d713c256a25 -6d2d2df60db49d254965758d05eaf2ecbd4996f20a9e6509a49d6c4796949b9325e8a8edb59acb4d0ff9386d7b63b827c3c73885ac4b3d476216c2bb265f095b -f6a736b3e9f259365bb9636e13d4e1d5878dfb9cc30e0fa442aa2d2c235b1ae65156022cd19aacfdcb4d08eb453950c14667b362650d8ae15fb302e2e8a6968c -c7c457e564975674ececd78c4af9441131888223346213b18f21fdba54c19f804a78dd6118417f8177733adae6914bce59d395df88199c5dc72c8d7046b7ba45 -f34eb6704348850de65bc93cf0add276e3dcf95d312d7f41ae94cbf87fe68a3e4fe0edc34aa033e0c39b618191ee94b6c7858a38b0501a51bf2f607030dc01d5 -02ef77e1311415bc9f36ff0b72a8ffb73d676598b6864ba4daa7211214ce23150942f680964cf59d22ac9e9d5d5624cb04998a2a992b536bf6881c1236d41cb8 -aacf760f4550ea864d321a30b893f5e77ecf3a6814ea21a7dc6f0e931567afed817f7af2b1cd0c4eb93c6c069a3cfe8589c578303b55ed7eb33d3f7bcb8ee807 -b331ab917705282b1d05adaced5fd384731eb596b1e63c5e6ee6c64116e73d86c562204ae11d12d2ffc0f94785cf8829637da00ef93e702b821f2fb430281ba8 -ea4b76f0409a20ede2080627bb688b498bb2a1cd46271db5fcb0bee049b7d07b22d8dab2b3e4fb9cc12e8633579dd38b1719ec2cc24eaceddac25043664fb628 -2c8df38b8c498cf995acfc4b161fdd83446fc16f0613a6a42926f89d4a6098a107a60fa0f9ad46b375e32f000000ffff0300504b030414000600080000002100 -0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 -8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 -d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 -1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f -bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 -a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a -0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 -0036cc113fa8060000a31b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 -00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} -{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d -617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 -6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 -656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} -{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 1;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 2;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; -\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; -\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; -\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; -\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; -\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 -4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 -d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000000089 -393e263acf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1053\deflangfe1053\themelang1053\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} +{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} +{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} +{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; +\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp +\fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 +\rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 +\rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink15 \sqformat heading 1;}{ +\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext0 \slink16 \sqformat +heading 2;}{\s3\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1053\loch\f1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 +\sbasedon0 \snext0 \slink17 \sqformat heading 3;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 +\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;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid488565\rsid490522\rsid532764 +\rsid543320\rsid556337\rsid617158\rsid750573\rsid876335\rsid930020\rsid940090\rsid1187219\rsid1190356\rsid1191142\rsid1202844\rsid1258951\rsid1261441\rsid1445386\rsid1706832\rsid1770393\rsid2060511\rsid2112235\rsid2112392\rsid2181632\rsid2260548 +\rsid2427760\rsid2443070\rsid2446079\rsid2641133\rsid2894529\rsid3036029\rsid3347855\rsid3547548\rsid3819803\rsid4460640\rsid4538894\rsid4542728\rsid4602097\rsid4675069\rsid4679726\rsid4981561\rsid5332441\rsid5462095\rsid5525810\rsid5712409\rsid6228168 +\rsid6309374\rsid6309794\rsid6362316\rsid6436444\rsid6499600\rsid6569652\rsid6633554\rsid6650094\rsid6845226\rsid6950962\rsid7041439\rsid7089377\rsid7167315\rsid7421144\rsid7616262\rsid7683346\rsid7807046\rsid7949161\rsid7952569\rsid8000484\rsid8001475 +\rsid8090374\rsid8137115\rsid8527940\rsid8541195\rsid8593145\rsid8799536\rsid8983788\rsid8999377\rsid9002512\rsid9047914\rsid9125746\rsid9175287\rsid9314635\rsid9515749\rsid9530285\rsid9907738\rsid10245607\rsid10426263\rsid10496751\rsid10631094 +\rsid11078728\rsid11279197\rsid11297517\rsid12068517\rsid12087407\rsid12156867\rsid12530193\rsid12595779\rsid12732549\rsid12788235\rsid12854747\rsid12982360\rsid12986669\rsid12992185\rsid13174672\rsid13180120\rsid13250408\rsid13316938\rsid13319718 +\rsid13336457\rsid13714332\rsid13915886\rsid14095979\rsid14102810\rsid14169293\rsid14295269\rsid14370947\rsid14892228\rsid15031452\rsid15620535\rsid15821976\rsid16147558\rsid16405367\rsid16470149\rsid16610750\rsid16655487\rsid16724586}{\mmathPr +\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Bo Haglund}{\creatim\yr2012\mo10\dy21\hr14\min22}{\revtim\yr2014\mo5\dy10\hr22\min31}{\version102}{\edmins831} +{\nofpages10}{\nofwords3136}{\nofchars16621}{\nofcharsws19718}{\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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Bo Haglund, Bob Richardson +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12992185 \hich\af31506\dbch\af31505\loch\f31506 Rev T, 2014-03-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 Latest DLL issue with this description is available at }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +HYPERLINK "http://www.bahnhof.se/wb758135/"}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\lang1053\langfe1053\langnp1053\insrsid4538894\charrsid13915886 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 +0000a5ab00000000004b00000079000000000075000b00006d000000000b0100000000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\ul\cf2\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\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 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Short description of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid10496751 +\hich\af31506\dbch\af31505\loch\f31506 ouble Dummy Problem Solver 2.5}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\ul\cf1\insrsid6650094\charrsid13915886 +\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 +\f31506\cf1\insrsid6650094\charrsid13915886 +\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, +\par \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); +\par +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, +\par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 int solutions, int mode, struct futureTricks *futp, int threadIndex); +\par +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, \line struct ddTableResults * tablep); +\par +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcDDt\hich\af31506\dbch\af31505\loch\f31506 ablePBN(struct ddTableDealPBN\line tableDealPBN, struct ddTableResults * tablep);}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid488565 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid488565 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 extern \'93\loch\f31506 \hich\f31506 C\'94\loch\f31506 +__declspec(dllimport) int __stdcall }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 CalcAllTables(struct ddTableDeals *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \line }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 struct ddTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 \hich\af37\dbch\af31505\loch\f37 Res *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 +\hich\af37\dbch\af31505\loch\f37 struct allParResults}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565\charrsid488565 \hich\af37\dbch\af31505\loch\f37 *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid488565 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7041439 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 \hich\f37 extern \'93\loch\f37 \hich\f37 C\'94\loch\f37 +__declspec(dllimport) int __stdcall CalcAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 +(struct ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439 \hich\af37\dbch\af31505\loch\f37 PBN\line *dealsp,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6362316 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 int mode, int trumpFilter[5], struct ddTablesRes *resp, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8983788 +\par \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid7041439 \hich\af37\dbch\af31505\loch\f37 struct allParResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7041439\charrsid488565 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall SolveAll\hich\af31506\dbch\af31505\loch\f31506 Boards(struct boardsPBN *bop, +\par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards *solvedp); }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12992185 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid12992185 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 \hich\af37\dbch\af31505\loch\f37 extern "C" __declspec(dllimport) int __stdcall SolveAll}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185 \hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 +\hich\af37\dbch\af31505\loch\f37 (struct boardsPBN *bop, +\par \hich\af37\dbch\af31505\loch\f37 struct solvedBoards *}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185 \hich\af37\dbch\af31505\loch\f37 solved, int chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12992185\charrsid12992185 +\hich\af37\dbch\af31505\loch\f37 );}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12992185\charrsid13915886 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid12986669 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); +\par +\par \hich\af31506\dbch\af31505\loch\f31506 extern "C" __declspec(dllimport) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, +\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2894529 \hich\af31506\dbch\af31505\loch\f31506 esults * tablep, int vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid12986669\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 , struct parResults *presp);}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12986669\charrsid13915886 +\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 SolveBoard is threa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 d-safe, so several threads }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 can call SolveBoard in parallel.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 The actual}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 maximum number is configured at initial start-up, this number is maximum 16. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 + +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Before SolveBoard can be called, a structure of type "futureTricks" must be declared. +\par +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 SolveBoard}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + returns a status integer, "no fault" means the DLL supplies the trick data in\hich\af31506\dbch\af31505\loch\f31506 the "futureTricks" type structure.\line Status codes: +\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, +\par \hich\af31506\dbch\af31505\loch\f31506 -1=Unknown fault, +\par \hich\af31506\dbch\af31505\loch\f31506 -2=No of cards = 0, +\par \hich\af31506\dbch\af31505\loch\f31506 -3=target > Number of tricks left, +\par \hich\af31506\dbch\af31505\loch\f31506 -4=Duplicated cards, +\par \hich\af31506\dbch\af31505\loch\f31506 -5=target < -1, +\par \hich\af31506\dbch\af31505\loch\f31506 -7=target >13, +\par \hich\af31506\dbch\af31505\loch\f31506 -8=solutions < 1, +\par \hich\af31506\dbch\af31505\loch\f31506 -9=solutions > 3, +\par \hich\af31506\dbch\af31505\loch\f31506 -10=No of cards > 52 +\par \hich\af31506\dbch\af31505\loch\f31506 -11=Not used +\par \hich\af31506\dbch\af31505\loch\f31506 -12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. +\par \hich\af31506\dbch\af31505\loch\f31506 -13=Card already played in the current trick is also defined as a remaining card to play. +\par \hich\af31506\dbch\af31505\loch\f31506 -14=Wrong number of remaining cards for a hand. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 -15=threadIndex < 0 or >=noOfThreads, noOfThreads is the configured maximum number of threads}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 .\line \hich\af31506\dbch\af31505\loch\f31506 \line \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines all data needed to describe the deal to be analyzed. +\par \hich\af31506\dbch\af31505\loch\f31506 struct deal \{}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int trump; /\hich\af31506\dbch\af31505\loch\f31506 +* 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 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; /* 0-2 for up to 3 cards in \hich\af31506\dbch\af31505\loch\f31506 +the order played */ +\par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickRank[3]; /* 2-14 for up to 3 cards}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6436444 \hich\af31506\dbch\af31505\loch\f31506 . Suits and ranks set to 0 otherwise.}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6436444\charrsid6436444 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 unsigned int remainCards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\super\insrsid6650094\charrsid13915886 +\hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index hand (0-3), 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 , \'85\'85\'85\loch\f31506 . bit 14=rank 14, bit 15=0}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +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 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 is the number of tricks to be won by the side to play, -1 means that the program}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 shall find the }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 maximum number. For equivalent }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 cards only the highest is returned. +\par \line \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 solutions}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\hich\af31506\dbch\af31505\loch\f31506 defines how many card solutions that SolveBoard must return: +\par \hich\af31506\dbch\af31505\loch\f31506 target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target when}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target or higher tricks can be won. Otherwise, score \hich\f31506 \endash \loch\f31506 1 is returned if target cannot be +\hich\af31506\dbch\af31505\loch\f31506 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\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=1: Returns only one of the cards legal to play with score set to 0.}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 target 1-13, solutions=2: Return all\hich\af31506\dbch\af31505\loch\f31506 + 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\f31506 \endash \loch\f31506 +1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won.\line \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 arget \hich\f31506 \endash \loch\f31506 +1, solutions=2: Return all optimum cards with their scores. +\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 target=0, solutions=2: Return all cards legal to play with scores set to 0}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf6\insrsid6650094\charrsid13915886 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \line \hich\af31506\dbch\af31505\loch\f31506 + target irrelevant, solutions=3: Return all cards that can be legally played w}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 \hich\af31506\dbch\af31505\loch\f31506 ith their scores in descendin\hich\af31506\dbch\af31505\loch\f31506 g }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 order. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 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\f31506 \endash \loch\f31506 2 for this card, indicating that there are no alternative c +\hich\af31506\dbch\af31505\loch\f31506 ards. 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\f31506 \rquote \loch\f31506 t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8137115 +\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115 \hich\af37\dbch\af31505\loch\f37 a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8137115\charrsid8137115 \hich\af37\dbch\af31505\loch\f37 +lways search to find the score. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par \hich\af31506\dbch\af31505\loch\f31506 mode=1: Always }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 search to find the score. Even when the hand to play has only one card, with +\hich\af31506\dbch\af31505\loch\f31506 + possible equivalents, to play. For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mod +\hich\af31506\dbch\af31505\loch\f31506 e\hich\af31506\dbch\af31505\loch\f31506 =2 is no longer needed in this case, but can still be done for backwards compatibility.\line + mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL t\hich\af31506\dbch\af31505\loch\f31506 o\hich\af31506\dbch\af31505\loch\f31506 + 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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + 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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \tab 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call: SolveBoard(deal, -1, 1, +\hich\af31506\dbch\af31505\loch\f31506 2, &fut, 0), deal.first=2, i.e. South leads. +\par \hich\af31506\dbch\af31505\loch\f31506 \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 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 futureTricks}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\hich\af31506\dbch\af31505\loch\f31506 \{ /* The DLL provides \hich\af31506\dbch\af31505\loch\f31506 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 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int nodes; /* Number of searched nodes */ +\par \hich\af31506\dbch\af31505\loch\f31506 int cards; /* No of alternative cards */}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int suit[13]; \hich\af31506\dbch\af31505\loch\f31506 /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ +\par \hich\af31506\dbch\af31505\loch\f31506 int rank[13]; /* 2-14 for 2 through Ace *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 / +\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 +int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When there are several \'94\loch\f31506 \hich\f31506 equals\'94\loch\f31506 \hich\f31506 +, the value is the sum of each \'94\loch\f31506 \hich\f31506 equal\'94\loch\f31506 . *}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 /}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 int score[13]; /* -1 indicates th\hich\af31506\dbch\af31505\loch\f31506 at target was not reached, otherwise target or max numbe of tricks */}{\rtlch\fcs1 \af0 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par +\par \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 threadIndex}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the identity of the thread used when calling SolveBoard. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 A configured maximum number of}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\hich\af31506\dbch\af31505\loch\f31506 threads can call SolveBoard in parallel, threadIndex must}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16470149\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 b\hich\af31506\dbch\af31505\loch\f31506 +e an integer in the range 0..max number of threads - 1. This maximum number is configured at DLL initial start-up and cannot exceed 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 SolveBoardPBN +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 In SolveBoardPBN the remaining cards in the deal information are given in PBN text +\par \hich\af31506\dbch\af31505\loch\f31506 format (e.g. \line W:T5.K\hich\af31506\dbch\af31505\loch\f31506 +4.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\af31506\dbch\af31505\loch\f31506 struct dealPBN \{ +\par \hich\af31506\dbch\af31505\loch\f31506 int trump; +\par \hich\af31506\dbch\af31505\loch\f31506 int first; +\par \hich\af31506\dbch\af31505\loch\f31506 int currentTrickSuit[3]; }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 int curre\hich\af31506\dbch\af31505\loch\f31506 ntTrickRank[3]; +\par \hich\af31506\dbch\af31505\loch\f31506 char remainCards[80]; /* First character identifies the hand having the cards given first +\par \hich\af31506\dbch\af31505\loch\f31506 in the string, then the cards of the other hands are given in a +\par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 clock-wise order, see example \hich\af31506\dbch\af31505\loch\f31506 above. Null characters fill out +\par \tab \tab \tab \hich\af31506\dbch\af31505\loch\f31506 the character array at the end. */ +\par \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable +\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 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 +\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 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid1770393 \hich\af31506\dbch\af31505\loch\f31506 calculates the double}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 dummy values of the initial 52 cards for all the 20 trump suit/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 +\f31506\insrsid6650094\charrsid13915886 +\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 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 +\b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure.\line Status codes: +\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, +\par \hich\af31506\dbch\af31505\loch\f31506 Other status codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Structure \'94}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 +\hich\af31506\dbch\af31505\loch\f31506 ddTableDeal}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \loch\af31506\dbch\af31505\hich\f31506 \'94\loch\f31506 defines the dealt cards to be analyzed.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDeal \{ +\par \hich\af31506\dbch\af31505\loch\f31506 unsigned int cards[4][4]; /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is hand, 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is suit, same coding as \hich\af31506\dbch\af31505\loch\f31506 for deal.remainCards for SolveBoard. */ +\par \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 struct }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 ddTableResults} +{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 \{ /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 int resTable[5][4];\tab /* 1}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 st}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No T\hich\af31506\dbch\af31505\loch\f31506 rump 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\super\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 nd}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + index is declarer hand, 0=North, 1=East, 2=South, 3=West */ +\par \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par +\par +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcDDtablePBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\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\lang1033\langfe1053\loch\af1\hich\af1\dbch\af31505\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is \hich\af31506\dbch\af31505\loch\f31506 identical to CalcDDtable. +\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 +\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 struct ddTableDealPBN \{ +\par \hich\af31506\dbch\af31505\loch\f31506 char cards[80]; +\par \}\hich\af31506\dbch\af31505\loch\f31506 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112235 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid2112235\charrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 CalcAllTables +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393 \hich\af37\dbch\af31505\loch\f37 calculates }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the double dummy values }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 +\hich\af37\dbch\af31505\loch\f37 of the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 trump suit/declarer hand combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 +\hich\af37\dbch\af31505\loch\f37 for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 a number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 DD table}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 s in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 . This increases}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 the speed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 +\hich\af37\dbch\af31505\loch\f37 compared to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4602097 \hich\af37\dbch\af31505\loch\f37 calculating}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 the}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 se values}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 using a }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid12068517 \hich\af37\dbch\af31505\loch\f37 CalcDDtable call }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 \hich\af37\dbch\af31505\loch\f37 for each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 +\hich\af37\dbch\af31505\loch\f37 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 +\par \hich\af37\dbch\af31505\loch\f37 The maximum number of DD tables in a CallAllTables call depends on the number of strains (the number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 5 }{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 trump alternatives, any of th\hich\af37\dbch\af31505\loch\f37 +e 4 suits and no trump) to be part of the DD calculations. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14102810 \hich\af37\dbch\af31505\loch\f37 of DD tables that can b\hich\af37\dbch\af31505\loch\f37 e included in a CallAllTable call is 10. +}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 At fewer strains the maximum number of DD tables in a call is higher:}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 4 strains maximum 12 DD tables +\par \hich\af37\dbch\af31505\loch\f37 3 strains maximum 16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 +\par \hich\af37\dbch\af31505\loch\f37 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 strains maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 25}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 +\par \hich\af37\dbch\af31505\loch\f37 1 strain}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 maximum }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 \hich\af37\dbch\af31505\loch\f37 50}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228\charrsid14892228 \hich\af37\dbch\af31505\loch\f37 DD tables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14892228 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 AllT}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 able}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 +\hich\af37\dbch\af31505\loch\f37 can be called, a st}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 ructure of type "ddTable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 s +}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810 \hich\af37\dbch\af31505\loch\f37 Res}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5525810\charrsid5525810 \hich\af37\dbch\af31505\loch\f37 " must be declared.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid5525810 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid16610750 \hich\af37\dbch\af31505\loch\f37 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 returns a status integer, "no fault" means the DLL supplies the double dum}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15031452 \hich\af37\dbch\af31505\loch\f37 +my scores in the "ddTablesRes}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 " type structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441 \hich\af37\dbch\af31505\loch\f37 \hich\f37 + Its contained structure of type \'93\loch\f37 \hich\f37 ddTableResults\'94\loch\f37 is d\hich\af37\dbch\af31505\loch\f37 escribed for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 +\hich\f37 The variable \'93\loch\f37 \hich\f37 noOfBoards\'94\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 show}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 +s the number of solved boards (max 200).}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid940090 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTablesRes \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid940090 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718\charrsid13319718 \hich\af37\dbch\af31505\loch\f37 int noOfBoards;}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid13319718\charrsid940090 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 struct ddTableResults results[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid940090\charrsid940090 \hich\af37\dbch\af31505\loch\f37 ]; +\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5332441\charrsid6569652 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652\charrsid6569652 \hich\af37\dbch\af31505\loch\f37 Status codes: +\par \hich\af37\dbch\af31505\loch\f37 1=No fault,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8983788 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 -201=Error, all trump suits an}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 d the no trump suit alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12156867 \hich\af37\dbch\af31505\loch\f37 have been marked in the\line + calling parameter trumpFilter to be left out (i.e. they have }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 all }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2181632 \hich\af37\dbch\af31505\loch\f37 +been set to TRUE),}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6569652 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12087407 \hich\af37\dbch\af31505\loch\f37 -202=Error, too many DD tables in the call. +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6569652 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 +\par \hich\af37\dbch\af31505\loch\f37 \hich\f37 Structure \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid940090\charrsid6228168 \hich\af37\dbch\af31505\loch\f37 ddTableDeals}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid940090 +\loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 con\hich\af37\dbch\af31505\loch\f37 tains }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 up to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 +\hich\af37\dbch\af31505\loch\f37 5}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 0 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 DD table }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid6228168 \hich\af37\dbch\af31505\loch\f37 \hich\f37 deals, each in a structure \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 , +\par \hich\af37\dbch\af31505\loch\f37 described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The actual number is set in the \'93\loch\f37 \hich\f37 noOfTables\'94\loch\f37 + parameter.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6228168 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeals \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid6633554 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9125746\charrsid6633554 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct ddTableDeal deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 ]; +\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6309794 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid532764\charrsid12854747 \hich\af37\dbch\af31505\loch\f37 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid532764 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 specifies whether or not par score and par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 \hich\af37\dbch\af31505\loch\f37 wi}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 ll be calculated\line and if so, wh}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 ich sides that are vulnerable:\line -1}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid532764 \hich\af37\dbch\af31505\loch\f37 : }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 +no par calculation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3547548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548\charrsid3547548 \hich\af37\dbch\af31505\loch\f37 0:\tab par calculation, vulnerability None +\par \hich\af37\dbch\af31505\loch\f37 1:\tab par calculation, vulnerability All +\par \hich\af37\dbch\af31505\loch\f37 2:\tab par calculation, \hich\af37\dbch\af31505\loch\f37 vulnerability NS}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid3547548\charrsid3547548 +\par \hich\af37\dbch\af31505\loch\f37 3:\tab par calculation, vulnerability EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3547548 \hich\af37\dbch\af31505\loch\f37 only +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The results of the par calculations are given in the structure \'93\loch\f37 \hich\f37 allParResults\'94, +\par \hich\af37\dbch\af31505\loch\f37 which contains the results for all boards. Each board results are given\line \hich\f37 in structure \'93\loch\f37 \hich\f37 parResults\'94\loch\f37 , described fo\hich\af37\dbch\af31505\loch\f37 r the CalcPar function. + +\par +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6633554 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 \hich\af37\dbch\af31505\loch\f37 struct allParResults \{ +\par \hich\af37\dbch\af31505\loch\f37 struct parResults presults[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554\charrsid6633554 +\hich\af37\dbch\af31505\loch\f37 ]; +\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6633554 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \hich\af37\dbch\af31505\loch\f37 \hich\f37 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\b\f37\cf1\insrsid12854747\charrsid7949161 \hich\af37\dbch\af31505\loch\f37 trumpFilter}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 \loch\af37\dbch\af31505\hich\f37 \'94\loch\f37 describes which, if any, of the trump suits or the no trump suit +}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7949161 \line \hich\af37\dbch\af31505\loch\f37 alternatives that will be excluded from the calculations.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 They are defined in the order Spades, Hearts, Diamonds, Clubs and No Trump}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid617158 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 . E.g. setting trumpFilter to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \{\hich\af37\dbch\af31505\loch\f37 FALSE, FALSE, TRUE, TRUE, TRUE\} + means that values will only be calculated for}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 \hich\af37\dbch\af31505\loch\f37 +the trump suits Spades and Hearts. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5712409 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 CalcAllTablesPBN +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12982360 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 As for CalcAllTab\hich\af37\dbch\af31505\loch\f37 les except that the deals are given in PBN format. The structure\line \hich\f37 \'93\loch\f37 \hich\f37 +ddTableDealPBN\'94\loch\f37 is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15620535 \hich\af37\dbch\af31505\loch\f37 described}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 \hich\af37\dbch\af31505\loch\f37 for the CalcDDtablePBN }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 \hich\af37\dbch\af31505\loch\f37 function.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 +\par +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid2260548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealsPBN \{}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid2260548 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386 \hich\af37\dbch\af31505\loch\f37 int noOfTables;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1445386\charrsid2260548 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 struct ddTableDealPBN deals[MAXNOOFBOARDS / }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 \hich\af37\dbch\af31505\loch\f37 4}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid2260548 \hich\af37\dbch\af31505\loch\f37 ]; +\par \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14095979 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2260548\charrsid12982360 +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid9907738 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 +\b\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid7616262\charrsid7616262 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 A \'93\loch\f31506 \hich\f31506 chunk\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 + is a collection of boards to be }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 solved by the same thread. +\par \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9907738 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 \hich\af31506\dbch\af31505\loch\f31506 solves a}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \hich\af31506\dbch\af31505\loch\f31506 number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 \hich\af31506\dbch\af31505\loch\f31506 +s in parallel for increased performance compared to solve them sequentionally using a SolveBoard call for each board.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7616262 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16405367 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 is called with a buffer\hich\af31506\dbch\af31505\loch\f31506 containi} +{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 ng }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 board dat}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid7807046 \hich\af31506\dbch\af31505\loch\f31506 a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2443070 \hich\af31506\dbch\af31505\loch\f31506 for a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7807046 +\hich\af31506\dbch\af31505\loch\f31506 number of boards, maximum 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +00 boards per call. Each board is defined with the same input data as in SolveBoardPBN. The input data per board can be freely given independent of the settings for the other d}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 +\hich\af31506\dbch\af31505\loch\f31506 eals. SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s +}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 use\hich\af31506\dbch\af31505\loch\f31506 s multi-thread calls to SolveBoardPBN for solving the buffered boards.}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 The chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 parameter in the SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid16147558 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16147558 +\hich\af31506\dbch\af31505\loch\f31506 call specifies how many boards that are allocated per thread.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 struct boardsPBN \{ +\par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; +\par \hich\af31506\dbch\af31505\loch\f31506 struct dealPBN deals[MAXNOOFBOARDS]; +\par \hich\af31506\dbch\af31505\loch\f31506 int target[MAXNOOFBOARDS]; +\par \hich\af31506\dbch\af31505\loch\f31506 int solutions[MAXNOOFBOARDS]; +\par \hich\af31506\dbch\af31505\loch\f31506 int mode[MAXNOOFBOARDS]; +\par \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par +\par \hich\af31506\dbch\af31505\loch\f31506 struct solvedBoards \{ +\par \hich\af31506\dbch\af31505\loch\f31506 int noOfBoards; +\par \hich\af31506\dbch\af31505\loch\f31506 struct futureTricks solvedBoard[MAXNOOFBOARDS]; +\par \}\hich\af31506\dbch\af31505\loch\f31506 ; +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 In the SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 call, the cards are coded in PBN text format usi +\hich\af31506\dbch\af31505\loch\f31506 ng the dealPBN structure. The number of boards to be solved must be defined in the boardsPBN structure, the number must not}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid12595779 +\hich\af31506\dbch\af31505\loch\f31506 exceed MAXNOOFBOARDS which is 2}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 00. In the returned information in struct solvedBoards,}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 the number of solved boards is}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 given. The fut +\hich\af31506\dbch\af31505\loch\f31506 ureTricks information is provided for all solved boards with the same returned information per board as with SolveBoard. +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13714332 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 \hich\af31506\dbch\af31505\loch\f31506 returns 1 if the call succeeds. In case chu}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid3036029 \hich\af31506\dbch\af31505\loch\f31506 n}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 \hich\af31506\dbch\af31505\loch\f31506 kSize is set to less than 1, the error code -201}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid3036029 \hich\af31506\dbch\af31505\loch\f31506 is given}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9002512 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 otherwise }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 error\hich\af31506\dbch\af31505\loch\f31506 code}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 +\hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 identical to the SolveBoard}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid15821976 +\hich\af31506\dbch\af31505\loch\f31506 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 error codes is given when there is a problem in the input information.}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid6650094 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13250408 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid13250408\charrsid13250408 \hich\af37\dbch\af31505\loch\f37 SolveAllBoards +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 +\par \hich\af37\dbch\af31505\loch\f37 SolveAllBoards gives the same results as calling Solve}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 All}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 +\hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13250408 \hich\af37\dbch\af31505\loch\f37 + with chunksize=1. SolveAllBoards is included to obtain DD\hich\af37\dbch\af31505\loch\f37 S backward compatibility. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13250408\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Note}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s on DDS use for simulations} +{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 Setting parameter chunkSize to 1 in the call to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 SolveAll}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid543320 \hich\af31506\dbch\af31505\loch\f31506 Chunk}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13336457 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 is optimal when th}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 e input boards are dissimilar. If however, a}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 djacent boards in the boards buffer are similar (same trump, very minor difference between ca}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 rds distribution between hands), then the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 transp}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 osition table information can often}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 be reused. }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 But it is then necessary that}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 these boards use }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 the same thread}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2427760 \hich\af31506\dbch\af31505\loch\f31506 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 For \hich\af31506\dbch\af31505\loch\f31506 example, when the simulation aims to find out which hand is best as declarer, the boards can be grouped in pairs where }{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\cf1\insrsid2446079 \hich\af31506\dbch\af31505\loch\f31506 the two}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 board}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2446079 +\hich\af31506\dbch\af31505\loch\f31506 s in the pair have}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 different declarer }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 +\hich\af31506\dbch\af31505\loch\f31506 hand}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2446079 \hich\af31506\dbch\af31505\loch\f31506 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f31506\cf1\insrsid8000484 \hich\af31506\dbch\af31505\loch\f31506 but otherwise are the same. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4675069 \hich\af31506\dbch\af31505\loch\f31506 +In this case, chunkSize should be set to 2 for obtai\hich\af31506\dbch\af31505\loch\f31506 ning transposition table information reuse. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 In simulation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid10631094 \hich\af31506\dbch\af31505\loch\f31506 s involving }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different d}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid14169293 \hich\af31506\dbch\af31505\loch\f31506 eclarer hand alternatives and}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 different trump }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid16610750 \hich\af31506\dbch\af31505\loch\f31506 suit }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 +\hich\af31506\dbch\af31505\loch\f31506 alternatives, usage of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid7167315 \hich\af31506\dbch\af31505\loch\f31506 Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 +\hich\af31506\dbch\af31505\loch\f31506 AllTables }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112392 \hich\af31506\dbch\af31505\loch\f31506 can be}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 + a more }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid2112392 \hich\af31506\dbch\af31505\loch\f31506 convenient}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid1191142 \hich\af31506\dbch\af31505\loch\f31506 alternative}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\cf1\insrsid2060511 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 CalcPar +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid556337 \hich\af31506\dbch\af31505\loch\f31506 CalcPar c}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +alculates the par score and par contracts of a given deal.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid750573 \hich\af31506\dbch\af31505\loch\f31506 + 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 th\hich\af31506\dbch\af31505\loch\f31506 +ere is no need to make a CalcDDtable call before calling CalcPar. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13915886\charrsid13915886 \line +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13915886 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Before Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid7683346 \hich\af31506\dbch\af31505\loch\f31506 Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 can be called, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 +\hich\af31506\dbch\af31505\loch\f31506 a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 structure of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13174672 +\hich\af31506\dbch\af31505\loch\f31506 each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 type " ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 must be declared. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 \hich\af31506\dbch\af31505\loch\f31506 CalcPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 + returns a status integer, "no fault" means the DLL supplies the double d\hich\af31506\dbch\af31505\loch\f31506 ummy scores in the "ddTableResults" type structure}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12530193 +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 and the par results in the \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Calling CalcPar with the structure of type \'93\loch\f31506 \hich\f31506 ddTableDeal\'94\loch\f31506 + is done in the same way as for calling CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8527940 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid14295269\charrsid13915886 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Status codes: +\par \hich\af31506\dbch\af31505\loch\f31506 1=No fault, +\par \hich\af31506\dbch\af31505\loch\f31506 Other sta\hich\af31506\dbch\af31505\loch\f31506 tus codes are errors, with codes equal to SolveBoard status codes. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Parameter \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f31506\insrsid1261441 \hich\af31506\dbch\af31505\loch\f31506 vulnerable}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f31506\insrsid1190356 \loch\af31506\dbch\af31505\hich\f31506 \'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 is set according to:}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid7952569 \hich\af31506\dbch\af31505\loch\f31506 0 = None +\par \hich\af31506\dbch\af31505\loch\f31506 1 = Both sides +\par \hich\af31506\dbch\af31505\loch\f31506 2 = North / South side vulnerable +\par \hich\af31506\dbch\af31505\loch\f31506 3 = East / West side vulnerable +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1258951 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 The structure t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid12854747 \hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 ypes \'93\loch\f31506 \hich\f31506 +ddTableDeal\'94\loch\f31506 \hich\f31506 and \'93\loch\f31506 ddTableR}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \hich\af31506\dbch\af31505\loch\f31506 esult\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 s\'94\loch\f31506 + are described for the function CalcDDtable.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid5462095 \line \hich\af31506\dbch\af31505\loch\f31506 +\hich\f31506 The \'93\loch\f31506 \hich\f31506 parResults\'94\loch\f31506 structure type }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 \hich\af31506\dbch\af31505\loch\f31506 includes the par score and the par contracts results returned by }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1190356 \hich\af31506\dbch\af31505\loch\f31506 the call to CalcPar: +\par +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 struct parResults \{ +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid8541195 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 char parScore[2][16];\tab /* index = 0 is from NS view and index =1 is +\hich\af37\dbch\af31505\loch\f37 from EW view. */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 +\par \hich\af37\dbch\af31505\loch\f37 char parContractsString[2][128];}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 +/* index = 0 is NS view and index = 1 is EW view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 \hich\f37 By \'93\loch\f37 \hich\f37 view\'94\loch\f37 is +\par }\pard \ltrpar\ql \fi720\li2160\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2160\itap0\pararsid9314635 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid8541195 \hich\af37\dbch\af31505\loch\f37 here meant which side that starts the bidding. }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\insrsid8541195\charrsid1190356 \hich\af37\dbch\af31505\loch\f37 */}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1190356\charrsid1190356 \}\hich\af37\dbch\af31505\loch\f37 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid8799536 +\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid1187219 +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid11297517 \hich\af31506\dbch\af31505\loch\f31506 Par score is give}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 n as a text string, e.g NS -460. NS lost 460}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 points.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13915886\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid6650094 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 All par contracts }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 for different suits }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 are listed with comma separating }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9515749 \hich\af31506\dbch\af31505\loch\f31506 the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 +\hich\af31506\dbch\af31505\loch\f31506 suits.\line Possible different trick levels of par score contracts are enumerated in the contract description, e.g the possible trick levels }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 +\hich\af31506\dbch\af31505\loch\f31506 3, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 \hich\af31506\dbch\af31505\loch\f31506 4 and 5 in }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid13180120 \hich\af31506\dbch\af31505\loch\f31506 No trumps, are} +{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 given as 345N}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid9314635 . +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid3347855 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid930020 \hich\af31506\dbch\af31505\loch\f31506 Example of par contracts in different suits: +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726\charrsid4679726 \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,NS 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 This is from the NS view. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 North}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 +\hich\af37\dbch\af31505\loch\f37 and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid4679726 \hich\af37\dbch\af31505\loch\f37 South}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 as declarer make 2 }{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 or 3 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 Hearts} +{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 contracts, 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 Spades and 2 H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 +\hich\af37\dbch\af31505\loch\f37 earts with an overtrick.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9515749 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749\charrsid9515749 \hich\af37\dbch\af31505\loch\f37 If only North could make 3 Hearts, the text string would h +\hich\af37\dbch\af31505\loch\f37 ave looked: +\par \hich\af37\dbch\af31505\loch\f37 NS:NS 23S,N 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid930020 \hich\af37\dbch\af31505\loch\f37 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 NS before the colon refer}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13180120 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid3347855\charrsid3347855 \hich\af37\dbch\af31505\loch\f37 to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 \hich\af37\dbch\af31505\loch\f37 the}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid12732549 \hich\af37\dbch\af31505\loch\f37 + assumed side that made the initial bid in the process for determining the par score / contracts}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 \hich\af37\dbch\af31505\loch\f37 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9515749 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 Also, DDS calculates the par score / contracts when the assumed side is EW: +\par \hich\af37\dbch\af31505\loch\f37 EW}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid14370947 \hich\af37\dbch\af31505\loch\f37 :NS 23S,N 23H }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3347855 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947 \hich\af37\dbch\af31505\loch\f37 +Nearly always, the par score / 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. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3347855 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14370947\charrsid3347855 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid490522\charrsid8593145 \hich\af37\dbch\af31505\loch\f37 CalcParPBN +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11279197 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 \hich\f37 The only difference compared to CalcPar is that the structure type +\'93\loch\f37 ddTableDeal\hich\af37\dbch\af31505\loch\f37 \hich\f37 PBN\'94\loch\f37 \hich\f37 is used instead of \'93\loch\f37 \hich\f37 ddTableDeal\'94\loch\f37 \hich\f37 . For description of \'93\loch\f37 \hich\f37 ddTableDealPBN\'94\loch\f37 +, see CalcDDtablePBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197\charrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1190356 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11279197 \hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid490522 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid490522\charrsid13915886 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\insrsid6650094\charrsid13915886 +\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 \ltrch\fcs0 \b\f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 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 \ltrch\fcs0 +\f31506\cf1\insrsid6650094\charrsid13915886 +\par \hich\af31506\dbch\af31505\loch\f31506 Rev A, 2006-02-25.\tab \tab First issue. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev B, 2006-03-20\tab \tab Updated issue. +\par +\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev C, 2006-03-28\tab +\hich\af31506\dbch\af31505\loch\f31506 \hich\f31506 Updated issue. Addition of the SolveBoard parameter \'94\loch\f31506 \hich\f31506 mode\'94. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev D, 2006-04-05\tab Updated issue. Usage of target=0 to list all cards that are legal to play. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev E, 2006-05-29\tab Updated issue. New error code \hich\f31506 \endash \loch\f31506 10 for number of cards > 52. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev F, 2006-08-09\tab Upda\hich\af31506\dbch\af31505\loch\f31506 ted issue. New mode parameter value = 2. New error code \hich\f31506 \endash \loch\f31506 +11 for calling SolveBoard with mode = 2 and forbidden values of other parameters. +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 +\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 Rev F1, 2006-08-14\tab +Clarifications on conditions for returning scores for the different combinations of the values fo\hich\af31506\dbch\af31505\loch\f31506 r target and solutions. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev F2, 2006-08-26\tab New error code \hich\f31506 \endash \loch\f31506 12 for wrongly set valu}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid9047914 \hich\af31506\dbch\af31505\loch\f31506 +es of deal.currentTrickSuit and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 deal.currentTrickRank. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev G, 2007-01-04\tab New DDS release 1.1, otherwise no change compared to isse F2. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev H, 2007-04-23\tab DDS release 1.4, c\hich\af31506\dbch\af31505\loch\f31506 hanges for parameter mode=2. +\par +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6309374 \hich\af31506\dbch\af31505\loch\f31506 Rev I, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid6650094\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 2010-04-10\tab +DDS release 2.0, multi-thread support. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev J, 2010-05-29\tab DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev K, 2010-10-27\tab Correction of fault in the desc\hich\af31506\dbch\af31505\loch\f31506 ription: 2nd index in resTable of the structure ddTableResults is declarer hand. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev L, 2011-10-14\tab Added SolveBoardPBN and CalcDDtablePBN. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev M, 2012-07-06\tab Added SolveAllBoards. +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev N, 2012-07-16\tab Max number of threads is 8.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 +\par +\par \hich\af31506\dbch\af31505\loch\f31506 Rev O, 2012-10-21\tab \hich\af31506\dbch\af31505\loch\f31506 Max number of threads is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4542728\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 +configured at initial start-up, but never exceeds 16.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894\charrsid13915886 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid4538894 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f31506\cf1\insrsid13316938 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 \hich\af37\dbch\af31505\loch\f37 Rev P, 2013-03-16}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 \tab }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 +\hich\af37\dbch\af31505\loch\f37 Added functions CalcPar and CalcParPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938\charrsid13316938 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13316938 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9530285 \hich\af37\dbch\af31505\loch\f37 Rev Q, 2014-01-09}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6950962\charrsid6950962 \tab \hich\af37\dbch\af31505\loch\f37 Added functions Calc}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid6950962 \hich\af37\dbch\af31505\loch\f37 AllTables/CalcAllTablesPBN. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779 +\par \hich\af37\dbch\af31505\loch\f37 Rev R, 2014-01-13\tab Updated }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12595779\charrsid12595779 \hich\af37\dbch\af31505\loch\f37 functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid12595779 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377 +\par \hich\af37\dbch\af31505\loch\f37 Rev S}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7089377\charrsid7089377 \hich\af37\dbch\af31505\loch\f37 , 2014-01-13\tab Updated functions CalcAllTables/CalcAllTablesPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid7089377 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 +\par }\pard \ltrpar\ql \fi-2880\li2880\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin2880\itap0\pararsid16724586 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Rev T, 2014-03-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid10245607\charrsid10245607 \tab }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Added function}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607\charrsid10245607 +\hich\af37\dbch\af31505\loch\f37 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 SolveAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10245607 \hich\af37\dbch\af31505\loch\f37 Chunk}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid13336457 \hich\af37\dbch\af31505\loch\f37 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16724586 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6650094\charrsid16724586 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210036cc113fa8060000a31b0000160000007468656d652f7468656d652f +7468656d65312e786d6cec594f6f1b4514bf23f11d467b6f6327761a4775aad8b11b48d346b15bd4e37877bc3bcdecce6a669cd437d41e9190100571a012370e +08a8d44a5ccaa709144191fa157833b3bbde89d7246923a8a039b4f6ec6fdefff79b37ebabd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad +79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607f22d771db8b944ad79796a40fcb585ee62949e0d9988b182bf82ac2a540e023901bb3a5e55a6d +7529c634f1508263107b6b3ca63eb9a460abb791cbee31509028a9177c26065a327136186c7050d70839955d26d021666d0fd404fc6848ee2b0f312c153c687b +35f3e72d6d5c5dc2ebd926a616ec2dedeb9bbf6c5fb6213858363a45382a94d6fb8dd695ad42be0130358febf57add5ebd906700d8f7c1536b4b5966a3bf56ef +e4324b20fb715e76b7d6ac355c7c49feca9ccdad4ea7d36c65b658a106643f36e6f06bb5d5c6e6b28337208b6fcee11b9dcd6e77d5c11b90c5afcee1fb575aab +0d176f4011a3c9c11c5a27b4dfcfa417903167db95f03580afd532f80c05d55054975631e6895a546b31bec7451f001ac8b0a20952d3948cb10f45dcc5f14850 +ac15e075824b4fec922fe796b42e247d4153d5f63e4c3134c44cdeabe7dfbf7afe141d3f7876fce0a7e3870f8f1ffc680539bbb671129677bdfcf6b33f1f7f8c +fe78facdcb475f54e36519ffeb0f9ffcf2f3e7d540689f99392fbe7cf2dbb3272fbefaf4f7ef1e55c037051e95e1431a13896e9223b4cf6370cc44c5b59c8cc4 +f9760c234ccb3b369350e2046b2d15f27b2a72d037a79865d971ece81037827704d04715f0fae49e63f0201213452b34ef44b103dce59c75b8a88cc28ed6550a +f3709284d5cac5a48cdbc7f8b04a7717274e7e7b931478332f4bc7f16e441c33f7184e140e494214d2cff8012115dedda5d489eb2ef505977cacd05d8a3a9856 +866448474e35cd366dd318f232adf219f2edc466f70eea7056e5f516397491d0159855183f24cc09e3753c5138ae1239c4312b07fc065651959183a9f0cbb89e +5490e990308e7a0191b26acf2d01fe9692be8381b12ad3becba6b18b148a1e54c9bc81392f23b7f84137c2715a851dd0242a633f900750a218ed715505dfe56e +87e8ef90079c2c4cf71d4a9c749fce06b769e898342b10fd64222a72799d70a77e075336c6c4500d90bac3d5314dfe8eb81905e6b61a2e8eb8812a5f7cfdb8c2 +eeb795b237e1f4aaea99ed1344bd0877929ebb5c04f4ed67e72d3c49f60834c4fc11f58e9cdf91b3f79f27e745fd7cf1943c636120683d8bd841db8cddf1c2a9 +7b4c191ba8292337a419bc259c3d411f16f53e73e124c52d2c8de0a3ee6450e0e04281cd1e24b8fa88aa6810e11486f6baa7858432131d4a9472099745b35c29 +5be361f057f6aad9d49710cb1c12ab5d1ed8e515bd9cdf350a31c6aad05c6873452b5ac05995ad5cc984826fafa3acae8d3ab3b6ba31cd90a2a3ad705987d85c +ca21e4856bb0584413861a04a310447915aefc5a355c763023818ebbcd519e1693858b4c918c7040b21c69bfe773543749ca6b65ce11ed872d067d713c256a25 +6d2d2df60db49d254965758d05eaf2ecbd4996f20a9e6509a49d6c4796949b9325e8a8edb59acb4d0ff9386d7b63b827c3c73885ac4b3d476216c2bb265f095b +f6a736b3e9f259365bb9636e13d4e1d5878dfb9cc30e0fa442aa2d2c235b1ae65156022cd19aacfdcb4d08eb453950c14667b362650d8ae15fb302e2e8a6968c +c7c457e564975674ececd78c4af9441131888223346213b18f21fdba54c19f804a78dd6118417f8177733adae6914bce59d395df88199c5dc72c8d7046b7ba45 +f34eb6704348850de65bc93cf0add276e3dcf95d312d7f41ae94cbf87fe68a3e4fe0edc34aa033e0c39b618191ee94b6c7858a38b0501a51bf2f607030dc01d5 +02ef77e1311415bc9f36ff0b72a8ffb73d676598b6864ba4daa7211214ce23150942f680964cf59d22ac9e9d5d5624cb04998a2a992b536bf6881c1236d41cb8 +aacf760f4550ea864d321a30b893f5e77ecf3a6814ea21a7dc6f0e931567afed817f7af2b1cd0c4eb93c6c069a3cfe8589c578303b55ed7eb33d3f7bcb8ee807 +b331ab917705282b1d05adaced5fd384731eb596b1e63c5e6ee6c64116e73d86c562204ae11d12d2ffc0f94785cf8829637da00ef93e702b821f2fb430281ba8 +ea4b76f0409a20ede2080627bb688b498bb2a1cd46271db5fcb0bee049b7d07b22d8dab2b3e4fb9cc12e8633579dd38b1719ec2cc24eaceddac25043664fb628 +2c8df38b8c498cf995acfc4b161fdd83446fc16f0613a6a42926f89d4a6098a107a60fa0f9ad46b375e32f000000ffff0300504b030414000600080000002100 +0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 +8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 +d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 +1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f +bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 +a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a +0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 +0036cc113fa8060000a31b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 +00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 1;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 2;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; +\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; +\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; +\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000003065 +b7d78e6ccf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/DLL-dds_252_t.txt b/DLL-dds_252_t.txt new file mode 100644 index 00000000..265c2732 --- /dev/null +++ b/DLL-dds_252_t.txt @@ -0,0 +1,345 @@ +Bo Haglund, Bob Richardson +Rev T, 2014-03-01 +Latest DLL issue with this description is available at http://www.bahnhof.se/wb758135/ + + +Short description of the DLL functions supported in Double Dummy Problem Solver 2.5 + +Callable functions + +extern "C" __declspec(dllimport) int __stdcall SolveBoard(struct deal, int target, + int solutions, int mode, struct futureTricks *futp, int threadIndex); + +extern "C" __declspec(dllimport) int __stdcall SolveBoardPBN(struct dealPBN, int target, + int solutions, int mode, struct futureTricks *futp, int threadIndex); + +extern "C" __declspec(dllimport) int __stdcall CalcDDtable(struct ddTableDeal tableDeal, + struct ddTableResults * tablep); + +extern "C" __declspec(dllimport) int __stdcall CalcDDtablePBN(struct ddTableDealPBN + tableDealPBN, struct ddTableResults * tablep); + +extern “C”__declspec(dllimport) int __stdcall CalcAllTables(struct ddTableDeals *dealsp, + int mode, int trumpFilter[5], struct ddTablesRes *resp, struct allParResults*presp); + +extern “C”__declspec(dllimport) int __stdcall CalcAllTablesPBN(struct ddTableDealsPBN + *dealsp, int mode, int trumpFilter[5], struct ddTablesRes *resp, + struct allParResults *presp); + +extern "C" __declspec(dllimport) int __stdcall SolveAllBoards(struct boardsPBN *bop, + struct solvedBoards *solvedp); + +extern "C" __declspec(dllimport) int __stdcall SolveAllChunks(struct boardsPBN *bop, + struct solvedBoards *solved, int chunkSize); + +extern "C" __declspec(dllimport) int __stdcall CalcPar(struct ddTableDeal tableDeal, int vulnerable, struct ddTableResults * tablep, struct parResults *presp); + +extern "C" __declspec(dllimport) int __stdcall CalcParPBN(struct ddTableDealPBN tableDealPBN, + struct ddTableResults * tablep, int vulnerable, struct parResults *presp); + + +SolveBoard + +SolveBoard is thread-safe, so several threads can call SolveBoard in parallel. The actual maximum number is configured at initial start-up, this number is maximum 16. + +Before SolveBoard can be called, a structure of type "futureTricks" must be declared. + +SolveBoard returns a status integer, "no fault" means the DLL supplies the trick data in the "futureTricks" type structure. +Status codes: + 1=No fault, + -1=Unknown fault, + -2=No of cards = 0, + -3=target > Number of tricks left, + -4=Duplicated cards, + -5=target < -1, + -7=target >13, + -8=solutions < 1, + -9=solutions > 3, +-10=No of cards > 52 +-11=Not used +-12=Suit or rank value out of range for deal.currentTrickSuit or deal.currentTrickRank. +-13=Card already played in the current trick is also defined as a remaining card to play. +-14=Wrong number of remaining cards for a hand. +-15=threadIndex < 0 or >=noOfThreads, noOfThreads is the configured maximum number of threads. + +Structure ”deal” defines all data needed to describe the deal to be analyzed. +struct deal { + int trump; /* I.e. which suit that is trump or if contract is NT, Spades=0, Hearts=1, Diamonds=2, Clubs=3, NT=4 */ + int first; /* 0-3, 0=North, 1=East, 2=South, 3=West , Leading hand for the trick.*/ + int currentTrickSuit[3]; /* 0-2 for up to 3 cards in the order played */ + int currentTrickRank[3]; /* 2-14 for up to 3 cards. Suits and ranks set to 0 otherwise. */ + unsigned int remainCards[4][4]; /* 1st index hand (0-3), 2nd index suit (0-3), values as bitstring of ranks bit 0=0, bit 1=0, bit 2=rank 2, ………. bit 14=rank 14, bit 15=0 for cards remaining after already played cards (cards already played to the current trick are not included in this bitstring). + The decimal value for a card then range between 4 (=rank 2) and 16384 (Ace=rank 14). */ +}; + +Parameter ”target” is the number of tricks to be won by the side to play, -1 means that the program shall find the maximum number. For equivalent cards only the highest is returned. + +Parameter ”solutions” defines how many card solutions that SolveBoard must return: + target=1-13, solutions=1: Returns only one of the cards. Its returned score is the same as target when target or higher tricks can be won. Otherwise, score –1 is returned if target cannot be reached, or score 0 if no tricks can be won. + target=-1, solutions=1: Returns only one of the optimum cards and its score. + target=0, solutions=1: Returns only one of the cards legal to play with score set to 0. + 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 –1 if target cannot be reached, or score 0 for all cards legal to play if no tricks can be won. + target –1, solutions=2: Return all optimum cards with their scores. + target=0, solutions=2: Return all cards legal to play with scores set to 0. + target irrelevant, solutions=3: Return all cards that can be legally played with their scores in descending order. + +Parameter ”mode” defines the DLL mode of operation. + 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 –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’t always search to find the score. + mode=1: Always search to find the score. Even when the hand to play has only one card, with possible equivalents, to play. For both mode=0 and mode=1: If the preceding SolveBoard call had the same trump suit and the same deal, except for deal.first, then the transposition table contents is reused from the preceding SolveBoard call. Setting mode=2 is no longer needed in this case, but can still be done for backwards compatibility. + mode=2: As for mode=1, but the transposition table contents is reused from the preceding SolveBoard call. It is the responsibility of the programmer using the DLL to ensure that reusing the table is safe in the actual situation. Example: Deal is the same, except for deal.first. Trump suit is the same. +1st call: SolveBoard(deal, -1, 1, 1, &fut, 0), deal.first=1, i.e. East leads. + 2nd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=2, i.e. South leads. + 3rd call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=3, i.e. West leads. +4th call: SolveBoard(deal, -1, 1, 2, &fut, 0), deal.first=0, i.e. North leads. + +struct futureTricks { /* 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. */ + int nodes; /* Number of searched nodes */ + int cards; /* No of alternative cards */ + int suit[13]; /* 0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs */ + int rank[13]; /* 2-14 for 2 through Ace */ + int equals[13]; /* Bitstring of ranks for equivalent lower rank cards. The decimal value range between 4 (=2) and 8192 (King=rank 13). When there are several ”equals”, the value is the sum of each ”equal”. */ + int score[13]; /* -1 indicates that target was not reached, otherwise target or max numbe of tricks */ +} ; + +Parameter ”threadIndex” defines the identity of the thread used when calling SolveBoard. +A configured maximum number of threads can call SolveBoard in parallel, threadIndex must be an integer in the range 0..max number of threads - 1. This maximum number is configured at DLL initial start-up and cannot exceed 16. + + +SolveBoardPBN + +In SolveBoardPBN the remaining cards in the deal information are given in PBN text +format (e.g. +W:T5.K4.652.A98542 K6.QJT976.QT7.Q6 432.A.AKJ93.JT73 AQJ987.8532.84.K) instead of using bits 2-14 in an integer array. Otherwise, SolveboardPBN is identical to SolveBoard. + +struct dealPBN { + int trump; + int first; + int currentTrickSuit[3]; + int currentTrickRank[3]; + char remainCards[80]; /* First character identifies the hand having the cards given first + in the string, then the cards of the other hands are given in a + clock-wise order, see example above. Null characters fill out + the character array at the end. */ +}; + + +CalcDDtable + +CalcDDtable calculates the double dummy values of the initial 52 cards for all the 20 trump suit/declarer hand combinations. + +Before CalcDDtable can be called, a structure of type " ddTableResults" must be declared. +CalcDDtable returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure. +Status codes: + 1=No fault, + Other status codes are errors, with codes equal to SolveBoard status codes. + +Structure ”ddTableDeal” defines the dealt cards to be analyzed. +struct ddTableDeal { + unsigned int cards[4][4]; /* 1st index is hand, 2nd index is suit, same coding as for deal.remainCards for SolveBoard. */ +}; + +struct ddTableResults { /* For each combination trump suit / declarer hand, the DLL provides the double dummy score. */ + int resTable[5][4]; /* 1st index is trump (0=Spades, 1=Hearts, 2=Diamonds, 3=Clubs, 4=No Trump 2nd index is declarer hand, 0=North, 1=East, 2=South, 3=West */ +}; + + +CalcDDtablePBN + +In CalcDDtablePBN the remaining cards in the deal information are given in PBN text format, see the description above for SolveBoardPBN. Otherwise, CalcDDtablePBN is identical to CalcDDtable. + +struct ddTableDealPBN { + char cards[80]; +}; + + +CalcAllTables + +CallAllTables calculates the double dummy values of the trump suit/declarer hand combinations for a number of DD tables in parallel. This increases the speed compared to calculating these values using a CalcDDtable call for each DD table. + +The maximum number of DD tables in a CallAllTables call depends on the number of strains (the number of 5 trump alternatives, any of the 4 suits and no trump) to be part of the DD calculations. If all 5 strains are included there are 20 declarer hand / strain combinations. The maximum number of boards that can be calculated in parallel is 200, so the maximum number of DD tables that can be included in a CallAllTable call is 10. At fewer strains the maximum number of DD tables in a call is higher: +4 strains maximum 12 DD tables +3 strains maximum 16 DD tables +2 strains maximum 25 DD tables +1 strain maximum 50 DD tables + +Before CalcAllTables can be called, a structure of type "ddTablesRes" must be declared. +CallAllTables returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTablesRes" type structure. Its contained structure of type “ddTableResults” is described for the function CalcDDtable. The variable “noOfBoards” shows the number of solved boards (max 200). + +struct ddTablesRes { + int noOfBoards; + struct ddTableResults results[MAXNOOFBOARDS / 4]; +}; + +Status codes: + 1=No fault, + -201=Error, all trump suits and the no trump suit alternative have been marked in the + calling parameter trumpFilter to be left out (i.e. they have all been set to TRUE), + -202=Error, too many DD tables in the call. + +Structure “ddTableDeals” contains up to 50 DD table deals, each in a structure “ddTableDeal”, +described for the function CalcDDtable. The actual number is set in the “noOfTables” parameter. + +struct ddTableDeals { + int noOfTables; + struct ddTableDeal deals[MAXNOOFBOARDS / 4]; +}; + +Parameter “mode” specifies whether or not par score and par contracts will be calculated +and if so, which sides that are vulnerable: +-1: no par calculation +0: par calculation, vulnerability None +1: par calculation, vulnerability All +2: par calculation, vulnerability NS only +3: par calculation, vulnerability EW only + +The results of the par calculations are given in the structure “allParResults”, +which contains the results for all boards. Each board results are given +in structure “parResults”, described for the CalcPar function. + +struct allParResults { + struct parResults presults[MAXNOOFBOARDS / 4]; +}; + +Parameter “trumpFilter” describes which, if any, of the trump suits or the no trump suit +alternatives that will be excluded from the calculations. They are defined in the order Spades, Hearts, Diamonds, Clubs and No Trumps. E.g. setting trumpFilter to {FALSE, FALSE, TRUE, TRUE, TRUE} means that values will only be calculated for the trump suits Spades and Hearts. + + +CalcAllTablesPBN + +As for CalcAllTables except that the deals are given in PBN format. The structure +“ddTableDealPBN” is described for the CalcDDtablePBN function. + +struct ddTableDealsPBN { + int noOfTables; + struct ddTableDealPBN deals[MAXNOOFBOARDS / 4]; +}; + + +SolveAllChunks + +A “chunk” is a collection of boards to be solved by the same thread. +SolveAllChunks solves a number of chunks in parallel for increased performance compared to solve them sequentionally using a SolveBoard call for each board. + +SolveAllChunks is called with a buffer containing board data for a number of boards, maximum 200 boards per call. Each board is defined with the same input data as in SolveBoardPBN. The input data per board can be freely given independent of the settings for the other deals. SolveAllChunks uses multi-thread calls to SolveBoardPBN for solving the buffered boards. The chunkSize parameter in the SolveAllChunks call specifies how many boards that are allocated per thread. + +struct boardsPBN { + int noOfBoards; + struct dealPBN deals[MAXNOOFBOARDS]; + int target[MAXNOOFBOARDS]; + int solutions[MAXNOOFBOARDS]; + int mode[MAXNOOFBOARDS]; +}; + +struct solvedBoards { + int noOfBoards; + struct futureTricks solvedBoard[MAXNOOFBOARDS]; +}; + +In the SolveAllChunks call, the cards are coded in PBN text format using the dealPBN structure. The number of boards to be solved must be defined in the boardsPBN structure, the number must not exceed MAXNOOFBOARDS which is 200. In the returned information in struct solvedBoards, the number of solved boards is given. The futureTricks information is provided for all solved boards with the same returned information per board as with SolveBoard. + +SolveAllChunks returns 1 if the call succeeds. In case chunkSize is set to less than 1, the error code -201 is given, otherwise error codes identical to the SolveBoardPBN error codes is given when there is a problem in the input information. + + + +SolveAllBoards + +SolveAllBoards gives the same results as calling SolveAllChunks with chunksize=1. SolveAllBoards is included to obtain DDS backward compatibility. + +Notes on DDS use for simulations + +Setting parameter chunkSize to 1 in the call to SolveAllChunks is optimal when the input boards are dissimilar. If however, adjacent boards in the boards buffer are similar (same trump, very minor difference between cards distribution between hands), then the transposition table information can often be reused. But it is then necessary that these boards use the same thread. For example, when the simulation aims to find out which hand is best as declarer, the boards can be grouped in pairs where the two boards in the pair have different declarer hands but otherwise are the same. In this case, chunkSize should be set to 2 for obtaining transposition table information reuse. +In simulations involving different declarer hand alternatives and different trump suit alternatives, usage of CalcAllTables can be a more convenient alternative. + +CalcPar + +CalcPar calculates the par score and par contracts 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 CalcDDtable call before calling CalcPar. + +Before CalcPar can be called, a structure of each type " ddTableResults" and “parResults” must be declared. +CalcPar returns a status integer, "no fault" means the DLL supplies the double dummy scores in the "ddTableResults" type structure and the par results in the “parResults” structure. +Calling CalcPar with the structure of type “ddTableDeal” is done in the same way as for calling CalcDDtable. + +Status codes: + 1=No fault, + Other status codes are errors, with codes equal to SolveBoard status codes. + +Parameter “vulnerable” is set according to: +0 = None +1 = Both sides +2 = North / South side vulnerable +3 = East / West side vulnerable + +The structure types “ddTableDeal” and “ddTableResults” are described for the function CalcDDtable. +The “parResults” structure type includes the par score and the par contracts results returned by the call to CalcPar: + +struct parResults { + char parScore[2][16]; /* index = 0 is from NS view and index =1 is from 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. */ +}; + +Par score is given as a text string, e.g NS -460. NS lost 460 points. +All par contracts for different suits are listed with comma separating the suits. +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. + +Example of par contracts in different suits: +NS:NS 23S,NS 23H +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. +If only North could make 3 Hearts, the text string would have looked: +NS:NS 23S,N 23H +NS before the colon refers to the assumed side that made the initial bid in the process for determining the par score / contracts. +Also, DDS calculates the par score / contracts when the assumed side is EW: +EW:NS 23S,N 23H +Nearly always, the par score / 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. + + +CalcParPBN + +The only difference compared to CalcPar is that the structure type “ddTableDealPBN” is used instead of “ddTableDeal”. For description of “ddTableDealPBN”, see CalcDDtablePBN. + + + +Revision History + +Rev A, 2006-02-25. First issue. + +Rev B, 2006-03-20 Updated issue. + +Rev C, 2006-03-28 Updated issue. Addition of the SolveBoard parameter ”mode”. + +Rev D, 2006-04-05 Updated issue. Usage of target=0 to list all cards that are legal to play. + +Rev E, 2006-05-29 Updated issue. New error code –10 for number of cards > 52. + +Rev F, 2006-08-09 Updated issue. New mode parameter value = 2. New error code –11 for calling SolveBoard with mode = 2 and forbidden values of other parameters. + +Rev F1, 2006-08-14 Clarifications on conditions for returning scores for the different combinations of the values for target and solutions. + +Rev F2, 2006-08-26 New error code –12 for wrongly set values of deal.currentTrickSuit and deal.currentTrickRank. + +Rev G, 2007-01-04 New DDS release 1.1, otherwise no change compared to isse F2. + +Rev H, 2007-04-23 DDS release 1.4, changes for parameter mode=2. + +Rev I, 2010-04-10 DDS release 2.0, multi-thread support. + +Rev J, 2010-05-29 DDS release 2.1, OpenMP support, reuse of previous DD transposition table results of similar deals. + +Rev K, 2010-10-27 Correction of fault in the description: 2nd index in resTable of the structure ddTableResults is declarer hand. + +Rev L, 2011-10-14 Added SolveBoardPBN and CalcDDtablePBN. + +Rev M, 2012-07-06 Added SolveAllBoards. + +Rev N, 2012-07-16 Max number of threads is 8. + +Rev O, 2012-10-21 Max number of threads is configured at initial start-up, but never exceeds 16. + +Rev P, 2013-03-16 Added functions CalcPar and CalcParPBN. + +Rev Q, 2014-01-09 Added functions CalcAllTables/CalcAllTablesPBN. + +Rev R, 2014-01-13 Updated functions CalcAllTables/CalcAllTablesPBN. + +Rev S, 2014-01-13 Updated functions CalcAllTables/CalcAllTablesPBN. + +Rev T, 2014-03-01 Added function SolveAllChunks. diff --git a/dds.cpp b/dds.cpp index 1a9a3827..19b3df94 100755 --- a/dds.cpp +++ b/dds.cpp @@ -1,7115 +1,7143 @@ - -/* DDS 2.5.1 A bridge double dummy solver. */ -/* Copyright (C) 2006-2014 by Bo Haglund */ -/* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli. */ -/* The code for calculation of par score / contracts is based upon the */ -/* perl code written by Matthew Kidd for ACBLmerge. He has kindly given me */ -/* permission to include a C++ adaptation in DDS. */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -/* See the License for the specific language governing permissions and */ -/* limitations under the License. */ - - -/*#include "stdafx.h"*/ /* Needed by Visual C++ */ - -#include "dll.h" - -struct localVarType localVar[MAXNOOFTHREADS]; - -int * counttable; -int * highestRank; -int lho[4]; -int rho[4]; -int partner[4]; -unsigned short int bitMapRank[16]; -unsigned char cardRank[15]; -unsigned char cardSuit[5]; -unsigned char cardHand[4]; -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 */ - -struct ttStoreType * ttStore; -int lastTTstore; -int ttCollect; -int suppressTTlog; - -int noOfThreads=MAXNOOFTHREADS; /* The number of entries to the transposition tables. There is - one entry per thread. */ -int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */ - -#ifdef _MANAGED -#pragma managed(push, off) -#endif - - -#if defined(_WIN32) -extern "C" BOOL APIENTRY DllMain(HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved) { - int k; - - if (ul_reason_for_call==DLL_PROCESS_ATTACH) { - InitStart(0, 0); - } - else if (ul_reason_for_call==DLL_PROCESS_DETACH) { - for (k=0; k=noOfThreads)) { /* Fault corrected after suggestion by Dirk Willecke. */ - DumpInput(-15, dl, target, solutions, mode); - return -15; - } - - for (k=0; k<=13; k++) { - localVar[thrId].forbiddenMoves[k].rank=0; - localVar[thrId].forbiddenMoves[k].suit=0; - } - - if (target<-1) { - DumpInput(-5, dl, target, solutions, mode); - return -5; - } - if (target>13) { - DumpInput(-7, dl, target, solutions, mode); - return -7; - } - if (solutions<1) { - DumpInput(-8, dl, target, solutions, mode); - return -8; - } - if (solutions>3) { - DumpInput(-9, dl, target, solutions, mode); - return -9; - } - - for (k=0; k<=3; k++) - noOfCardsPerHand[handId(dl.first, k)]=0; - - - for (k=0; k<=2; k++) { - if (dl.currentTrickRank[k]!=0) { - noOfCardsPerHand[handId(dl.first, k)]=1; - aggrRemain=0; - for (h=0; h<=3; h++) - aggrRemain|=(dl.remainCards[h][dl.currentTrickSuit[k]]>>2); - if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]])!=0) { - DumpInput(-13, dl, target, solutions, mode); - return -13; - } - } - } - - if (target==-1) - localVar[thrId].tricksTarget=99; - else - localVar[thrId].tricksTarget=target; - - localVar[thrId].newDeal=FALSE; localVar[thrId].newTrump=FALSE; - localVar[thrId].diffDeal=0; localVar[thrId].aggDeal=0; - cardCount=0; - for (i=0; i<=3; i++) { - for (j=0; j<=3; j++) { - cardCount+=counttable[dl.remainCards[i][j]>>2]; - localVar[thrId].diffDeal+=((dl.remainCards[i][j]>>2)^ - (localVar[thrId].game.suit[i][j])); - localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2); - if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) { - localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2; - localVar[thrId].newDeal=TRUE; - } - } - } - - if (localVar[thrId].newDeal) { - if (localVar[thrId].diffDeal==0) - localVar[thrId].similarDeal=TRUE; - else if ((localVar[thrId].aggDeal/localVar[thrId].diffDeal) - > SIMILARDEALLIMIT) - localVar[thrId].similarDeal=TRUE; - else - localVar[thrId].similarDeal=FALSE; - } - else - localVar[thrId].similarDeal=FALSE; - - if (dl.trump!=localVar[thrId].trump) - localVar[thrId].newTrump=TRUE; - - for (i=0; i<=3; i++) - for (j=0; j<=3; j++) - noOfCardsPerHand[i]+=counttable[localVar[thrId].game.suit[i][j]]; - - for (i=1; i<=3; i++) { - if (noOfCardsPerHand[i]!=noOfCardsPerHand[0]) { - DumpInput(-14, dl, target, solutions, mode); - return -14; - } - } - - if (dl.currentTrickRank[2]) { - if ((dl.currentTrickRank[2]<2)||(dl.currentTrickRank[2]>14) - ||(dl.currentTrickSuit[2]<0)||(dl.currentTrickSuit[2]>3)) { - DumpInput(-12, dl, target, solutions, mode); - return -12; - } - localVar[thrId].handToPlay=handId(dl.first, 3); - handRelFirst=3; - noStartMoves=3; - if (cardCount<=4) { - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { - latestTrickSuit[localVar[thrId].handToPlay]=k; - latestTrickRank[localVar[thrId].handToPlay]= - InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); - break; - } - } - latestTrickSuit[handId(dl.first, 2)]=dl.currentTrickSuit[2]; - latestTrickRank[handId(dl.first, 2)]=dl.currentTrickRank[2]; - latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; - latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; - latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; - latestTrickRank[dl.first]=dl.currentTrickRank[0]; - } - } - else if (dl.currentTrickRank[1]) { - if ((dl.currentTrickRank[1]<2)||(dl.currentTrickRank[1]>14) - ||(dl.currentTrickSuit[1]<0)||(dl.currentTrickSuit[1]>3)) { - DumpInput(-12, dl, target, solutions, mode); - return -12; - } - localVar[thrId].handToPlay=handId(dl.first, 2); - handRelFirst=2; - noStartMoves=2; - if (cardCount<=4) { - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { - latestTrickSuit[localVar[thrId].handToPlay]=k; - latestTrickRank[localVar[thrId].handToPlay]= - InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { - latestTrickSuit[handId(dl.first, 3)]=k; - latestTrickRank[handId(dl.first, 3)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); - break; - } - } - latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; - latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; - latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; - latestTrickRank[dl.first]=dl.currentTrickRank[0]; - } - } - else if (dl.currentTrickRank[0]) { - if ((dl.currentTrickRank[0]<2)||(dl.currentTrickRank[0]>14) - ||(dl.currentTrickSuit[0]<0)||(dl.currentTrickSuit[0]>3)) { - DumpInput(-12, dl, target, solutions, mode); - return -12; - } - localVar[thrId].handToPlay=handId(dl.first,1); - handRelFirst=1; - noStartMoves=1; - if (cardCount<=4) { - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { - latestTrickSuit[localVar[thrId].handToPlay]=k; - latestTrickRank[localVar[thrId].handToPlay]= - InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { - latestTrickSuit[handId(dl.first, 3)]=k; - latestTrickRank[handId(dl.first, 3)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { - latestTrickSuit[handId(dl.first, 2)]=k; - latestTrickRank[handId(dl.first, 2)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); - break; - } - } - latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; - latestTrickRank[dl.first]=dl.currentTrickRank[0]; - } - } - else { - localVar[thrId].handToPlay=dl.first; - handRelFirst=0; - noStartMoves=0; - if (cardCount<=4) { - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { - latestTrickSuit[localVar[thrId].handToPlay]=k; - latestTrickRank[localVar[thrId].handToPlay]= - InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { - latestTrickSuit[handId(dl.first, 3)]=k; - latestTrickRank[handId(dl.first, 3)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { - latestTrickSuit[handId(dl.first, 2)]=k; - latestTrickRank[handId(dl.first, 2)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); - break; - } - } - for (k=0; k<=3; k++) { - if (localVar[thrId].game.suit[handId(dl.first, 1)][k]!=0) { - latestTrickSuit[handId(dl.first, 1)]=k; - latestTrickRank[handId(dl.first, 1)]= - InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 1)][k]); - break; - } - } - } - } - - localVar[thrId].trump=dl.trump; - localVar[thrId].game.first=dl.first; - first=dl.first; - localVar[thrId].game.noOfCards=cardCount; - if (dl.currentTrickRank[0]!=0) { - localVar[thrId].game.leadHand=dl.first; - localVar[thrId].game.leadSuit=dl.currentTrickSuit[0]; - localVar[thrId].game.leadRank=dl.currentTrickRank[0]; - } - else { - localVar[thrId].game.leadHand=0; - localVar[thrId].game.leadSuit=0; - localVar[thrId].game.leadRank=0; - } - - for (k=0; k<=2; k++) { - localVar[thrId].initialMoves[k].suit=255; - localVar[thrId].initialMoves[k].rank=255; - } - - for (k=0; k>2)+2; - else - totalTricks=((cardCount-4)>>2)+1; - checkRes=CheckDeal(&localVar[thrId].cd, thrId); - if (localVar[thrId].game.noOfCards<=0) { - DumpInput(-2, dl, target, solutions, mode); - return -2; - } - if (localVar[thrId].game.noOfCards>52) { - DumpInput(-10, dl, target, solutions, mode); - return -10; - } - if (totalTricksmaxRank)) { - maxRank=latestTrickRank[k]; - maxSuit=dl.trump; - maxHand=k; - } - } - } - /* Highest card in leading suit */ - if (maxRank==0) { - for (k=0; k<=3; k++) { - if (k==dl.first) { - maxSuit=latestTrickSuit[dl.first]; - maxHand=dl.first; - maxRank=latestTrickRank[dl.first]; - break; - } - } - for (k=0; k<=3; k++) { - if ((k!=dl.first)&&(latestTrickSuit[k]==maxSuit)&& - (latestTrickRank[k]>maxRank)) { - maxHand=k; - maxRank=latestTrickRank[k]; - } - } - } - futp->nodes=0; - #ifdef BENCH - futp->totalNodes=0; - #endif - futp->cards=1; - futp->suit[0]=latestTrickSuit[localVar[thrId].handToPlay]; - futp->rank[0]=latestTrickRank[localVar[thrId].handToPlay]; - futp->equals[0]=0; - if ((target==0)&&(solutions<3)) - futp->score[0]=0; - else if ((localVar[thrId].handToPlay==maxHand)|| - (partner[localVar[thrId].handToPlay]==maxHand)) - futp->score[0]=1; - else - futp->score[0]=0; - - /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ - return 1; - } - - if ((mode!=2)&& - (((localVar[thrId].newDeal)&&(!localVar[thrId].similarDeal)) - || localVar[thrId].newTrump || - (localVar[thrId].winSetSize > SIMILARMAXWINNODES))) { - - Wipe(thrId); - localVar[thrId].winSetSizeLimit=WINIT; - localVar[thrId].nodeSetSizeLimit=NINIT; - localVar[thrId].lenSetSizeLimit=LINIT; - localVar[thrId].allocmem=(WINIT+1)*sizeof(struct winCardType); - localVar[thrId].allocmem+=(NINIT+1)*sizeof(struct nodeCardsType); - localVar[thrId].allocmem+=(LINIT+1)*sizeof(struct posSearchType); - localVar[thrId].winCards=localVar[thrId].pw[0]; - localVar[thrId].nodeCards=localVar[thrId].pn[0]; - localVar[thrId].posSearch=localVar[thrId].pl[0]; - localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].lcount=0; - InitGame(0, FALSE, first, handRelFirst, thrId); - } - else { - InitGame(0, TRUE, first, handRelFirst, thrId); - /*localVar[thrId].fp2=fopen("dyn.txt", "a"); - fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", - wcount, ncount, lcount); - fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", - winSetSize, nodeSetSize, lenSetSize); - fclose(localVar[thrId].fp2);*/ - } - - #ifdef STAT - localVar[thrId].nodes=0; - #endif - localVar[thrId].trickNodes=0; - localVar[thrId].iniDepth=cardCount-4; - hiwinSetSize=0; - hinodeSetSize=0; - - if (mode==0) { - MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, - &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); - if (localVar[thrId].movePly[localVar[thrId].iniDepth].last==0) { - futp->nodes=0; - #ifdef BENCH - futp->totalNodes=0; - #endif - futp->cards=1; - futp->suit[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].suit; - futp->rank[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].rank; - futp->equals[0]= - localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].sequence<<2; - futp->score[0]=-2; - - /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ - return 1; - } - } - if ((target==0)&&(solutions<3)) { - MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, - &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); - futp->nodes=0; - #ifdef BENCH - futp->totalNodes=0; - #endif - for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) { - futp->suit[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit; - futp->rank[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank; - futp->equals[k]= - localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].sequence<<2; - futp->score[k]=0; - } - if (solutions==1) - futp->cards=1; - else - futp->cards=localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; - - /*_CrtDumpMemoryLeaks(); */ /* MEMORY LEAK? */ - return 1; - } - - if ((target!=-1)&&(solutions!=3)) { - localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, - localVar[thrId].tricksTarget, localVar[thrId].iniDepth, thrId); - - temp=localVar[thrId].movePly[localVar[thrId].iniDepth]; - last=localVar[thrId].movePly[localVar[thrId].iniDepth].last; - noMoves=last+1; - hiwinSetSize=localVar[thrId].winSetSize; - hinodeSetSize=localVar[thrId].nodeSetSize; - hilenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].nodeSetSize>MaxnodeSetSize) - MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>MaxwinSetSize) - MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>MaxlenSetSize) - MaxlenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].val==1) - localVar[thrId].payOff=localVar[thrId].tricksTarget; - else - localVar[thrId].payOff=0; - futp->cards=1; - ind=2; - - if (localVar[thrId].payOff<=0) { - futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; - futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; - futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; - if (localVar[thrId].tricksTarget>1) - futp->score[0]=-1; - else - futp->score[0]=0; - } - else { - futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; - futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; - futp->score[0]=localVar[thrId].payOff; - } - } - else { - g=localVar[thrId].estTricks[localVar[thrId].handToPlay]; - upperbound=13; - lowerbound=0; - do { - if (g==lowerbound) - tricks=g+1; - else - tricks=g; - assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&& - (localVar[thrId].lookAheadPos.handRelFirst<=3)); - localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, - localVar[thrId].iniDepth, thrId); - - if (localVar[thrId].val==TRUE) - mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; - hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); - hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); - hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); - if (localVar[thrId].nodeSetSize>MaxnodeSetSize) - MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>MaxwinSetSize) - MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>MaxlenSetSize) - MaxlenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].val==FALSE) { - upperbound=tricks-1; - g=upperbound; - } - else { - lowerbound=tricks; - g=lowerbound; - } - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, TRUE, thrId); - } - while (lowerboundcards=1; - if (localVar[thrId].payOff<=0) { - futp->score[0]=0; - futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; - futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; - futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; - } - else { - futp->score[0]=localVar[thrId].payOff; - futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; - futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; - } - localVar[thrId].tricksTarget=localVar[thrId].payOff; - } - - if ((solutions==2)&&(localVar[thrId].payOff>0)) { - forb=1; - ind=forb; - while ((localVar[thrId].payOff==localVar[thrId].tricksTarget)&&(ind<(temp.last+1))) { - localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; - localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - forb++; ind++; - /* All moves before bestMove in the move list shall be - moved to the forbidden moves list, since none of them reached - the target */ - /*mcurr=localVar[thrId].movePly[localVar[thrId].iniDepth].current;*/ - for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) - if ((localVar[thrId].bestMove[localVar[thrId].iniDepth].suit== - localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit) - &&(localVar[thrId].bestMove[localVar[thrId].iniDepth].rank== - localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank)) - break; - for (i=0; iMaxnodeSetSize) - MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>MaxwinSetSize) - MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>MaxlenSetSize) - MaxlenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].val==TRUE) { - localVar[thrId].payOff=localVar[thrId].tricksTarget; - futp->cards=ind; - futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; - futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; - futp->score[ind-1]=localVar[thrId].payOff; - } - else - localVar[thrId].payOff=0; - } - } - else if ((solutions==2)&&(localVar[thrId].payOff==0)&& - ((target==-1)||(localVar[thrId].tricksTarget==1))) { - futp->cards=noMoves; - /* Find the cards that were in the initial move list - but have not been listed in the current result */ - n=0; - for (i=0; isuit[0])&& - (temp.move[i].rank==futp->rank[0])) { - found=TRUE; - } - if (!found) { - futp->suit[1+n]=temp.move[i].suit; - futp->rank[1+n]=temp.move[i].rank; - futp->equals[1+n]=(temp.move[i].sequence)<<2; - futp->score[1+n]=0; - n++; - } - } - } - - if ((solutions==3)&&(localVar[thrId].payOff>0)) { - forb=1; - ind=forb; - for (i=0; i=0)&& - (localVar[thrId].lookAheadPos.handRelFirst<=3)); - localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, - localVar[thrId].iniDepth, thrId); - - if (localVar[thrId].val==TRUE) - mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; - hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); - hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); - hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); - if (localVar[thrId].nodeSetSize>MaxnodeSetSize) - MaxnodeSetSize=localVar[thrId].nodeSetSize; - if (localVar[thrId].winSetSize>MaxwinSetSize) - MaxwinSetSize=localVar[thrId].winSetSize; - if (localVar[thrId].lenSetSize>MaxlenSetSize) - MaxlenSetSize=localVar[thrId].lenSetSize; - if (localVar[thrId].val==FALSE) { - upperbound=tricks-1; - g=upperbound; - } - else { - lowerbound=tricks; - g=lowerbound; - } - - InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, TRUE, thrId); - } - while (lowerboundcards=temp.last+1; - for (j=0; j<=last; j++) { - futp->suit[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].suit; - futp->rank[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].rank; - futp->equals[ind-1+j]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].sequence)<<2; - futp->score[ind-1+j]=localVar[thrId].payOff; - } - break; - } - else { - localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv; - - futp->cards=ind; - futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; - futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; - futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; - futp->score[ind-1]=localVar[thrId].payOff; - } - } - } - else if ((solutions==3)&&(localVar[thrId].payOff==0)) { - futp->cards=noMoves; - /* Find the cards that were in the initial move list - but have not been listed in the current result */ - n=0; - for (i=0; isuit[0])&& - (temp.move[i].rank==futp->rank[0])) { - found=TRUE; - } - if (!found) { - futp->suit[1+n]=temp.move[i].suit; - futp->rank[1+n]=temp.move[i].rank; - futp->equals[1+n]=(temp.move[i].sequence)<<2; - futp->score[1+n]=0; - n++; - } - } - } - - for (k=0; k<=13; k++) { - localVar[thrId].forbiddenMoves[k].suit=0; - localVar[thrId].forbiddenMoves[k].rank=0; - } - - futp->nodes=localVar[thrId].trickNodes; - #ifdef BENCH - futp->totalNodes=localVar[thrId].nodes; - #endif - /*if ((wcount>0)||(ncount>0)||(lcount>0)) { - localVar[thrId].fp2=fopen("dyn.txt", "a"); - fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", - wcount, ncount, lcount); - fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", - winSetSize, nodeSetSize, lenSetSize); - fprintf(localVar[thrId].fp2, "\n"); - fclose(localVar[thrId].fp2); - }*/ - - /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ - return 1; -} - - -int _initialized=0; - -void InitStart(int gb_ram, int ncores) { - int k, r, i, j, m; - unsigned short int res; - unsigned long long pcmem; /* kbytes */ - - if (_initialized) - return; - _initialized = 1; - - ttCollect=FALSE; - suppressTTlog=FALSE; - lastTTstore=0; - ttStore = (struct ttStoreType *)calloc(SEARCHSIZE, sizeof(struct ttStoreType)); - if (ttStore==NULL) - exit(1); - - if (gb_ram==0) { /* Autoconfig */ - - #ifdef _WIN32 - - SYSTEM_INFO temp; - - MEMORYSTATUSEX statex; - statex.dwLength = sizeof (statex); - - GlobalMemoryStatusEx (&statex); /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus - was suggested by Lorne Anderson. */ - - pcmem=(unsigned long long)statex.ullTotalPhys/1024; - - if (pcmem < 1500000) - noOfThreads=Min(MAXNOOFTHREADS, 2); - else if (pcmem < 2500000) - noOfThreads=Min(MAXNOOFTHREADS, 4); - else - noOfThreads=MAXNOOFTHREADS; - - GetSystemInfo(&temp); - noOfCores=Min(noOfThreads, (int)temp.dwNumberOfProcessors); - - #endif - #ifdef __linux__ /* The code for linux was suggested by Antony Lee. */ - ncores = sysconf(_SC_NPROCESSORS_ONLN); - FILE* fifo = popen("free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r"); - fscanf(fifo, "%lld", &pcmem); - fclose(fifo); - #endif - - } - else { - if (gb_ram < 2) - noOfThreads=Min(MAXNOOFTHREADS, 2); - else if (gb_ram < 3) - noOfThreads=Min(MAXNOOFTHREADS, 4); - else - noOfThreads=Min(MAXNOOFTHREADS, 8); - - noOfCores=Min(noOfThreads, ncores); - - pcmem=(unsigned long long)(1000000 * gb_ram); - } - - /*printf("noOfThreads: %d noOfCores: %d\n", noOfThreads, noOfCores);*/ - - for (k=0; k=2; r--) { - if ((k & bitMapRank[r])!=0) { - highestRank[k]=r; - break; - } - } - } - - /* The use of the counttable to give the number of bits set to - one in an integer follows an implementation by Thomas Andrews. */ - - counttable = (int *)calloc(8192, sizeof(int)); - if (counttable==NULL) - exit(1); - - for (i=0; i<8192; i++) { - counttable[i]=0; - for (j=0; j<13; j++) { - if (i & (1<=2; r--) { - if ((i & bitMapRank[r])!=0) { - if (k <= j) { - res|=bitMapRank[r]; - k++; - } - else - break; - } - } - for (m=0; m=(topBitRank+topBitRank)) { - /* Next top bit */ - topBitRank <<=1; - } - - localVar[thrId].rel[ind]=localVar[thrId].rel[ind ^ topBitRank]; - - for (s=0; s<4; s++) { - ord=0; - for (r=14; r>=2; r--) { - if ((ind & bitMapRank[r])!=0) { - ord++; - localVar[thrId].rel[ind].relRank[r][s]=ord; - for (h=0; h<4; h++) { - if ((localVar[thrId].game.suit[h][s] & bitMapRank[r])!=0) { - localVar[thrId].rel[ind].absRank[ord][s].hand=h; - localVar[thrId].rel[ind].absRank[ord][s].rank=r; - break; - } - } - } - } - for (k=ord+1; k<=13; k++) { - localVar[thrId].rel[ind].absRank[k][s].hand=-1; - localVar[thrId].rel[ind].absRank[k][s].rank=0; - } - for (h=0; h<4; h++) { - if (localVar[thrId].game.suit[h][s] & topBitRank) { - localVar[thrId].rel[ind].aggrRanks[s]= - (localVar[thrId].rel[ind].aggrRanks[s]>>2)|(h<<24); - localVar[thrId].rel[ind].winMask[s]= - (localVar[thrId].rel[ind].winMask[s]>>2)|(3<<24); - break; - } - } - } - } - } - - localVar[thrId].iniPosition.first[localVar[thrId].game.noOfCards-4]=first; - localVar[thrId].iniPosition.handRelFirst=handRelFirst; - localVar[thrId].lookAheadPos=localVar[thrId].iniPosition; - - localVar[thrId].estTricks[1]=6; - localVar[thrId].estTricks[3]=6; - localVar[thrId].estTricks[0]=7; - localVar[thrId].estTricks[2]=7; - - #ifdef STAT - fprintf(localVar[thrId].fp2, "Estimated tricks for hand to play:\n"); - fprintf(localVar[thrId].fp2, "hand=%d est tricks=%d\n", - localVar[thrId].handToPlay, localVar[thrId].estTricks[localVar[thrId].handToPlay]); - #endif - - InitSearch(&localVar[thrId].lookAheadPos, localVar[thrId].game.noOfCards-4, - localVar[thrId].initialMoves, first, moveTreeFlag, thrId); - return; -} - - -void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[], - int first, int mtd, int thrId) { - - int s, d, h, handRelFirst, maxAgg, maxHand=0; - int k, noOfStartMoves; /* Number of start moves in the 1st trick */ - int hand[3], suit[3], rank[3]; - struct moveType move; - unsigned short int startMovesBitMap[4][4]; /* Indices are hand and suit */ - unsigned short int aggHand[4][4]; - - for (h=0; h<=3; h++) - for (s=0; s<=3; s++) - startMovesBitMap[h][s]=0; - - handRelFirst=posPoint->handRelFirst; - noOfStartMoves=handRelFirst; - - for (k=0; k<=2; k++) { - hand[k]=handId(first, k); - suit[k]=startMoves[k].suit; - rank[k]=startMoves[k].rank; - if (kfirst[depth]=first; - posPoint->handRelFirst=k; - assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); - posPoint->tricksMAX=0; - - if (k>0) { - posPoint->move[depth+k]=startMoves[k-1]; - move=startMoves[k-1]; - } - - posPoint->high[depth+k]=first; - - while (k>0) { - localVar[thrId].movePly[depth+k].current=0; - localVar[thrId].movePly[depth+k].last=0; - localVar[thrId].movePly[depth+k].move[0].suit=startMoves[k-1].suit; - localVar[thrId].movePly[depth+k].move[0].rank=startMoves[k-1].rank; - if (kmove[depth+k].suit=startMoves[k-1].suit; - posPoint->move[depth+k].rank=startMoves[k-1].rank; - posPoint->high[depth+k]=handId(first, noOfStartMoves-k); - move=posPoint->move[depth+k]; - } - else { - posPoint->move[depth+k]=posPoint->move[depth+k+1]; - posPoint->high[depth+k]=posPoint->high[depth+k+1]; - } - } - k--; - } - - for (s=0; s<=3; s++) - posPoint->removedRanks[s]=0; - - for (s=0; s<=3; s++) /* Suit */ - for (h=0; h<=3; h++) /* Hand */ - posPoint->removedRanks[s]|= - posPoint->rankInSuit[h][s]; - for (s=0; s<=3; s++) - posPoint->removedRanks[s]=~(posPoint->removedRanks[s]); - - for (s=0; s<=3; s++) /* Suit */ - for (h=0; h<=3; h++) /* Hand */ - posPoint->removedRanks[s]&= - (~startMovesBitMap[h][s]); - - for (s=0; s<=3; s++) - localVar[thrId].iniRemovedRanks[s]=posPoint->removedRanks[s]; - - /*for (d=0; d<=49; d++) { - for (s=0; s<=3; s++) - posPoint->winRanks[d][s]=0; - }*/ - - /* Initialize winning and second best ranks */ - for (s=0; s<=3; s++) { - maxAgg=0; - for (h=0; h<=3; h++) { - aggHand[h][s]=startMovesBitMap[h][s] | localVar[thrId].game.suit[h][s]; - if (aggHand[h][s]>maxAgg) { - maxAgg=aggHand[h][s]; - maxHand=h; - } - } - if (maxAgg!=0) { - posPoint->winner[s].hand=maxHand; - k=highestRank[aggHand[maxHand][s]]; - posPoint->winner[s].rank=k; - - maxAgg=0; - for (h=0; h<=3; h++) { - aggHand[h][s]&=(~bitMapRank[k]); - if (aggHand[h][s]>maxAgg) { - maxAgg=aggHand[h][s]; - maxHand=h; - } - } - if (maxAgg>0) { - posPoint->secondBest[s].hand=maxHand; - posPoint->secondBest[s].rank=highestRank[aggHand[maxHand][s]]; - } - else { - posPoint->secondBest[s].hand=-1; - posPoint->secondBest[s].rank=0; - } - } - else { - posPoint->winner[s].hand=-1; - posPoint->winner[s].rank=0; - posPoint->secondBest[s].hand=-1; - posPoint->secondBest[s].rank=0; - } - } - - - for (s=0; s<=3; s++) - for (h=0; h<=3; h++) - posPoint->length[h][s]= - (unsigned char)counttable[posPoint->rankInSuit[h][s]]; - - #ifdef STAT - for (d=0; d<=49; d++) { - score1Counts[d]=0; - score0Counts[d]=0; - c1[d]=0; c2[d]=0; c3[d]=0; c4[d]=0; c5[d]=0; c6[d]=0; c7[d]=0; - c8[d]=0; - localVar[thrId].no[d]=0; - } - #endif - - if (!mtd) { - localVar[thrId].lenSetSize=0; - for (k=0; k<=13; k++) { - for (h=0; h<=3; h++) { - localVar[thrId].rootnp[k][h]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; - localVar[thrId].lenSetSize++; - } - } - localVar[thrId].nodeSetSize=0; - localVar[thrId].winSetSize=0; - } - - #ifdef TTDEBUG - if (!suppressTTlog) - lastTTstore=0; - #endif - - return; -} - -#ifdef STAT -int score1Counts[50], score0Counts[50]; -int sumScore1Counts, sumScore0Counts, dd, suit, rank, order; -int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50]; -int sumc1, sumc2, sumc3, sumc4, sumc5, sumc6, sumc7, sumc8, sumc9; -#endif - -int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { - /* posPoint points to the current look-ahead position, - target is number of tricks to take for the player, - depth is the remaining search length, must be positive, - the value of the subtree is returned. */ - - int moveExists, value, scoreFlag, found; - int hh, ss, rr, qtricks, res, k; - unsigned short int makeWinRank[4]; - struct nodeCardsType * cardsP; - struct evalType evalData; - struct winCardType * np; - struct posSearchType * pp; - struct nodeCardsType * tempP; - struct movePlyType *mply=&localVar[thrId].movePly[depth]; - unsigned short int aggr[4]; - long long suitLengths; - - struct evalType Evaluate(struct pos * posPoint, int trump, int thrId); - /*void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth, int trump, struct movePlyType *mply, int thrId);*/ - void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); - - /*cardsP=NULL;*/ - assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); - int trump=localVar[thrId].trump; - int hand=handId(posPoint->first[depth], posPoint->handRelFirst); -#ifdef STAT - localVar[thrId].nodes++; -#endif - if (posPoint->handRelFirst==0) { - /*localVar[thrId].trickNodes++;*/ - if (posPoint->tricksMAX>=target) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - - #ifdef STAT - c1[depth]++; - - score1Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], - c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - - return TRUE; - } - if (((posPoint->tricksMAX+(depth>>2)+1)winRanks[depth][ss]=0; - - #ifdef STAT - c2[depth]++; - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], - c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - - return FALSE; - } - - if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { - qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); - if (res) { - if (qtricks==0) - return FALSE; - else - return TRUE; - #ifdef STAT - c3[depth]++; - score1Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], - c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - } - if (!LaterTricksMIN(posPoint,hand,depth,target,trump,thrId)) - return FALSE; - } - else { - qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); - if (res) { - if (qtricks==0) - return TRUE; - else - return FALSE; - #ifdef STAT - c4[depth]++; - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], - c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - } - if (LaterTricksMAX(posPoint,hand,depth,target,trump,thrId)) - return TRUE; - } - } - - else if (posPoint->handRelFirst==1) { - ss=posPoint->move[depth+1].suit; - unsigned short ranks=posPoint->rankInSuit[hand][ss] | - posPoint->rankInSuit[partner[hand]][ss]; - found=FALSE; rr=0; qtricks=0; - - if ((trump!=4) && (ss!=trump) && - (((posPoint->rankInSuit[hand][ss]==0) - && (posPoint->rankInSuit[hand][trump]!=0))|| - ((posPoint->rankInSuit[partner[hand]][ss]==0) - && (posPoint->rankInSuit[partner[hand]][trump]!=0)))) { - /* Own side can ruff */ - if ((posPoint->rankInSuit[lho[hand]][ss]!=0)|| - (posPoint->rankInSuit[lho[hand]][trump]==0)) { - found=TRUE; - qtricks=1; - } - } - - else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[lho[hand]][ss])) { - /* Own side has highest card in suit */ - if ((trump==4) || ((ss==trump)|| - (posPoint->rankInSuit[lho[hand]][trump]==0) - || (posPoint->rankInSuit[lho[hand]][ss]!=0))) { - rr=highestRank[ranks]; - if (rr!=0) { - found=TRUE; - qtricks=1; - } - else - found=FALSE; - } - } - - if ((found)&&(depth!=localVar[thrId].iniDepth)) { - for (k=0; k<=3; k++) - posPoint->winRanks[depth][k]=0; - if (rr!=0) - posPoint->winRanks[depth][ss]=bitMapRank[rr]; - - if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { - if (posPoint->tricksMAX+qtricks>=target) { - return TRUE; - } - else if (trump==4) { - if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) - hh=hand; /* Hand to lead next trick */ - else - hh=partner[hand]; - - if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& - (posPoint->secondBest[ss].hand==hh)) { - qtricks++; - posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; - if (posPoint->tricksMAX+qtricks>=target) - return TRUE; - } - - for (k=0; k<=3; k++) { - if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ - if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) - &&(posPoint->length[partner[hh]][k]==0)) { - qtricks+=counttable[posPoint->rankInSuit[hh][k]]; - if (posPoint->tricksMAX+qtricks>=target) - return TRUE; - } - else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { - qtricks++; - posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; - if (posPoint->tricksMAX+qtricks>=target) - return TRUE; - } - } - } - } - } - else { - /* MIN node */ - if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { - return FALSE; - } - else if (trump==4) { - if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) - hh=hand; /* Hand to lead next trick */ - else - hh=partner[hand]; - - if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& - (posPoint->secondBest[ss].hand==hh)) { - qtricks++; - posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; - if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) - return FALSE; - } - - for (k=0; k<=3; k++) { - if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ - if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) - &&(posPoint->length[partner[hh]][k]==0)) { - qtricks+=counttable[posPoint->rankInSuit[hh][k]]; - if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) - return FALSE; - } - else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { - qtricks++; - posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; - if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) - return FALSE; - } - } - } - } - } - } - } - - if ((posPoint->handRelFirst==0)&& - (depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) { - aggr[ss]=0; - for (hh=0; hh<=3; hh++) - aggr[ss]|=posPoint->rankInSuit[hh][ss]; - posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; - } - suitLengths=0; - for (ss=0; ss<=2; ss++) - for (hh=0; hh<=3; hh++) { - suitLengths<<=4; - suitLengths|=posPoint->length[hh][ss]; - } - - pp=SearchLenAndInsert(localVar[thrId].rootnp[depth>>2][hand], - suitLengths, FALSE, &res, thrId); - /* 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, depth>>2, &scoreFlag, thrId); - - if (cardsP!=NULL) { - if (scoreFlag==1) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]= - localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; - - if (cardsP->bestMoveRank!=0) { - localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; - localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; - } - #ifdef STAT - c5[depth]++; - if (scoreFlag==1) - score1Counts[depth]++; - else - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - #ifdef TTDEBUG - if (!suppressTTlog) { - if (lastTTstorewinRanks[depth][ss]= - localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; - - if (cardsP->bestMoveRank!=0) { - localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; - localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; - } - #ifdef STAT - c6[depth]++; - if (scoreFlag==1) - score1Counts[depth]++; - else - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], - c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - - #ifdef TTDEBUG - if (!suppressTTlog) { - if (lastTTstore=target) - value=TRUE; - else - value=FALSE; - for (ss=0; ss<=3; ss++) { - posPoint->winRanks[depth][ss]=evalData.winRanks[ss]; - - #ifdef STAT - c7[depth]++; - if (value==1) - score1Counts[depth]++; - else - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - fprintf(localVar[thrId].fp2, "score statistics:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], - c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], - c6[dd], c7[dd], c8[dd]); - } - } - #endif - } - return value; - } - else { - /*mply=&localVar[thrId].movePly[depth];*/ - moveExists=MoveGen(posPoint, depth, trump, mply, thrId); - -/*#if 0*/ - if ((posPoint->handRelFirst==3)&&(depth>=/*29*//*33*/37) - &&(depth!=localVar[thrId].iniDepth)) { - mply->current=0; - int mexists=TRUE; - int ready=FALSE; - while (mexists) { - Make(posPoint, makeWinRank, depth, trump, mply, thrId); - depth--; - - for (ss=0; ss<=3; ss++) { - aggr[ss]=0; - for (hh=0; hh<=3; hh++) - aggr[ss]|=posPoint->rankInSuit[hh][ss]; - posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; - } - int hfirst=posPoint->first[depth]; - suitLengths=0; - for (ss=0; ss<=2; ss++) - for (hh=0; hh<=3; hh++) { - suitLengths<<=4; - suitLengths|=posPoint->length[hh][ss]; - } - - pp=SearchLenAndInsert(localVar[thrId].rootnp[depth>>2][hfirst], - suitLengths, FALSE, &res, thrId); - /* 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, depth>>2, &scoreFlag, thrId); - - if (tempP!=NULL) { - if ((localVar[thrId].nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth+1][ss]= - localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; - if (tempP->bestMoveRank!=0) { - localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; - localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; - } - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; - Undo(posPoint, depth+1, mply/*&localVar[thrId].movePly[depth+1]*/,thrId); - return TRUE; - } - else if ((localVar[thrId].nodeTypeStore[hand]==MINNODE)&&(scoreFlag==0)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth+1][ss]= - localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; - if (tempP->bestMoveRank!=0) { - localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; - localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; - } - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; - Undo(posPoint, depth+1, mply/*&localVar[thrId].movePly[depth+1]*/, thrId); - return FALSE; - } - else { - mply->move[mply->current].weight+=100; - /*localVar[thrId].movePly[depth+1].move[localVar[thrId].movePly[depth+1].current].weight+=100;*/ - ready=TRUE; - } - } - } - depth++; - Undo(posPoint, depth, mply, thrId); - if (ready) - break; - - if (mply->current <= (mply->last-1)) { - mply->current++; - mexists=TRUE; - } - else - mexists=FALSE; - } - if (ready) - MergeSort(mply->last+1, mply->move); - } -/*#endif*/ - - - mply->current=0; - if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { - value=FALSE; - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - - while (moveExists) { - Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ - if (posPoint->handRelFirst==0) - localVar[thrId].trickNodes++; - assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); - value=ABsearch(posPoint, target, depth-1, thrId); - - Undo(posPoint, depth, mply, thrId); /* Retract current move */ - if (value==TRUE) { - /* A cut-off? */ - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | - makeWinRank[ss]; - localVar[thrId].bestMove[depth]=mply->move[mply->current]; - 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, mply, thrId); - } - } - else { /* A minnode */ - value=TRUE; - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - - while (moveExists) { - Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ - if (posPoint->handRelFirst==0) - localVar[thrId].trickNodes++; - value=ABsearch(posPoint, target, depth-1, thrId); - - Undo(posPoint, depth, mply, thrId); /* Retract current move */ - if (value==FALSE) { - /* A cut-off? */ - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | - makeWinRank[ss]; - localVar[thrId].bestMove[depth]=mply->move[mply->current]; - 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, mply, thrId); - } - } - } - ABexit: - if (depth>=4) { - if(posPoint->handRelFirst==0) { - if (value) - k=target; - else - k=target-1; - if (depth!=localVar[thrId].iniDepth) - BuildSOP(posPoint, suitLengths, depth>>2, hand, target, depth, - value, k, thrId); - if (localVar[thrId].clearTTflag) { - /* Wipe out the TT dynamically allocated structures - except for the initially allocated structures. - Set the TT limits to the initial values. - Reset TT array indices to zero. - Reset memory chunk indices to zero. - Set allocated memory to the initial value. */ - /*localVar[thrId].fp2=fopen("dyn.txt", "a"); - fprintf(localVar[thrId].fp2, "Clear TT:\n"); - fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", - wcount, ncount, lcount); - fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", - winSetSize, nodeSetSize, lenSetSize); - fprintf(localVar[thrId].fp2, "\n"); - fclose(localVar[thrId].fp2);*/ - - Wipe(thrId); - localVar[thrId].winSetSizeLimit=WINIT; - localVar[thrId].nodeSetSizeLimit=NINIT; - localVar[thrId].lenSetSizeLimit=LINIT; - localVar[thrId].lcount=0; - localVar[thrId].allocmem=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); - localVar[thrId].lenSetSize=0; - localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; - for (k=0; k<=13; k++) { - for (hh=0; hh<=3; hh++) { - localVar[thrId].rootnp[k][hh]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; - localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; - localVar[thrId].lenSetSize++; - } - } - localVar[thrId].nodeSetSize=0; - localVar[thrId].winSetSize=0; - localVar[thrId].wcount=0; localVar[thrId].ncount=0; - localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); - localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; - localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); - localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; - localVar[thrId].clearTTflag=FALSE; - localVar[thrId].windex=-1; - } - } - } - - #ifdef STAT - c8[depth]++; - if (value==1) - score1Counts[depth]++; - else - score0Counts[depth]++; - if (depth==localVar[thrId].iniDepth) { - if (localVar[thrId].fp2==NULL) - exit(0); - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "top level cards:\n"); - for (hh=0; hh<=3; hh++) { - fprintf(localVar[thrId].fp2, "hand=%c\n", cardHand[hh]); - for (ss=0; ss<=3; ss++) { - fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); - for (rr=14; rr>=2; rr--) - if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) - fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); - fprintf(localVar[thrId].fp2, "\n"); - } - fprintf(localVar[thrId].fp2, "\n"); - } - fprintf(localVar[thrId].fp2, "top level winning cards:\n"); - for (ss=0; ss<=3; ss++) { - fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); - for (rr=14; rr>=2; rr--) - if (posPoint->winRanks[depth][ss] & bitMapRank[rr]) - fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); - fprintf(localVar[thrId].fp2, "\n"); - } - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "\n"); - - fprintf(localVar[thrId].fp2, "score statistics:\n"); - sumScore0Counts=0; - sumScore1Counts=0; - sumc1=0; sumc2=0; sumc3=0; sumc4=0; - sumc5=0; sumc6=0; sumc7=0; sumc8=0; sumc9=0; - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { - fprintf(localVar[thrId].fp2, "depth=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, - score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); - fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], - c7[dd], c8[dd]); - sumScore0Counts=sumScore0Counts+score0Counts[dd]; - sumScore1Counts=sumScore1Counts+score1Counts[dd]; - sumc1=sumc1+c1[dd]; - sumc2=sumc2+c2[dd]; - sumc3=sumc3+c3[dd]; - sumc4=sumc4+c4[dd]; - sumc5=sumc5+c5[dd]; - sumc6=sumc6+c6[dd]; - sumc7=sumc7+c7[dd]; - sumc8=sumc8+c8[dd]; - sumc9=sumc9+c9[dd]; - } - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "score sum statistics:\n"); - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "sumScore0Counts=%d sumScore1Counts=%d\n", - sumScore0Counts, sumScore1Counts); - fprintf(localVar[thrId].fp2, "nodeSetSize=%d winSetSize=%d\n", localVar[thrId].nodeSetSize, - localVar[thrId].winSetSize); - fprintf(localVar[thrId].fp2, "sumc1=%d sumc2=%d sumc3=%d sumc4=%d\n", - sumc1, sumc2, sumc3, sumc4); - fprintf(localVar[thrId].fp2, "sumc5=%d sumc6=%d sumc7=%d sumc8=%d sumc9=%d\n", - sumc5, sumc6, sumc7, sumc8, sumc9); - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "No of searched nodes per depth:\n"); - for (dd=localVar[thrId].iniDepth; dd>=0; dd--) - fprintf(localVar[thrId].fp2, "depth=%d nodes=%d\n", dd, localVar[thrId].no[dd]); - fprintf(localVar[thrId].fp2, "\n"); - fprintf(localVar[thrId].fp2, "Total nodes=%d\n", localVar[thrId].nodes); - } - #endif - - return value; -} - - -void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth, int trump, struct movePlyType *mply, int thrId) { - int t, u, w; - int mcurr, q; - - assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); - for (int suit=0; suit<=3; suit++) - trickCards[suit]=0; - - 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]; - } - } - 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]; - } - - /* Is the trick won by rank? */ - int s=posPoint->move[depth].suit; - int count=0; - if (mply->move[r].suit==s) - count++; - for (int e=1; e<=3; e++) { - mcurr=localVar[thrId].movePly[depth+e].current; - if (localVar[thrId].movePly[depth+e].move[mcurr].suit==s) { - count++; - /*if (++count>1) - break;*/ - } - } - - - if (localVar[thrId].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=localVar[thrId].movePly[depth+d].current; - w=localVar[thrId].movePly[depth+d].move[r].rank; - u=localVar[thrId].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=localVar[thrId].rel[aggr].absRank[1][u].rank; - posPoint->winner[u].hand=localVar[thrId].rel[aggr].absRank[1][u].hand; - posPoint->secondBest[u].rank=localVar[thrId].rel[aggr].absRank[2][u].rank; - posPoint->secondBest[u].hand=localVar[thrId].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]|=localVar[thrId].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]=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 { - 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]; - } - } - 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]; - } - - t=handId(firstHand, posPoint->handRelFirst); - posPoint->handRelFirst++; /* Current hand is stepped */ - 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]--; - -#ifdef STAT - localVar[thrId].no[depth]++; -#endif - - return; -} - - - -void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId) { - int r, t, u, w; - - assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); - - switch (posPoint->handRelFirst) { - case 3: case 2: case 1: - posPoint->handRelFirst--; - break; - case 0: - posPoint->handRelFirst=3; - } - - int firstHand=posPoint->first[depth]; - - if (posPoint->handRelFirst==0) { /* 1st hand which won the previous - trick */ - t=firstHand; - r=mply->current; - u=mply->move[r].suit; - w=mply->move[r].rank; - } - else if (posPoint->handRelFirst==3) { /* Last hand */ - for (int d=3; d>=0; d--) { - /* Delete the moves from removed ranks */ - r=localVar[thrId].movePly[depth+d].current; - w=localVar[thrId].movePly[depth+d].move[r].rank; - u=localVar[thrId].movePly[depth+d].move[r].suit; - - posPoint->removedRanks[u]&= (~bitMapRank[w]); - - if (w>posPoint->winner[u].rank) { - /*posPoint->secondBest[u].rank=posPoint->winner[u].rank; - posPoint->secondBest[u].hand=posPoint->winner[u].hand;*/ - posPoint->secondBest[u]=posPoint->winner[u]; - posPoint->winner[u].rank=w; - posPoint->winner[u].hand=handId(firstHand, 3-d); - - } - else if (w>posPoint->secondBest[u].rank) { - posPoint->secondBest[u].rank=w; - posPoint->secondBest[u].hand=handId(firstHand, 3-d); - } - } - t=handId(firstHand, 3); - - - if (localVar[thrId].nodeTypeStore[posPoint->first[depth-1]]==MAXNODE) - /* First hand of next trick is winner of the current trick */ - posPoint->tricksMAX--; - } - else { - t=handId(firstHand, posPoint->handRelFirst); - r=mply->current; - u=mply->move[r].suit; - w=mply->move[r].rank; - } - - posPoint->rankInSuit[t][u]|=bitMapRank[w]; - - posPoint->length[t][u]++; - - return; -} - - - -struct evalType Evaluate(struct pos * posPoint, int trump, int thrId) { - int s, h, hmax=0, count=0, k=0; - unsigned short rmax=0; - struct evalType eval; - - int firstHand=posPoint->first[0]; - assert((firstHand >= 0)&&(firstHand <= 3)); - - for (s=0; s<=3; s++) - eval.winRanks[s]=0; - - /* Who wins the last trick? */ - if (trump!=4) { /* Highest trump card wins */ - for (h=0; h<=3; h++) { - if (posPoint->rankInSuit[h][trump]!=0) - count++; - if (posPoint->rankInSuit[h][trump]>rmax) { - hmax=h; - rmax=posPoint->rankInSuit[h][trump]; - } - } - - if (rmax>0) { /* Trumpcard wins */ - if (count>=2) - eval.winRanks[trump]=rmax; - - if (localVar[thrId].nodeTypeStore[hmax]==MAXNODE) - goto maxexit; - else - goto minexit; - } - } - - /* Who has the highest card in the suit played by 1st hand? */ - - k=0; - while (k<=3) { /* Find the card the 1st hand played */ - if (posPoint->rankInSuit[firstHand][k]!=0) /* Is this the card? */ - break; - k++; - } - - assert(k < 4); - - for (h=0; h<=3; h++) { - if (posPoint->rankInSuit[h][k]!=0) - count++; - if (posPoint->rankInSuit[h][k]>rmax) { - hmax=h; - rmax=posPoint->rankInSuit[h][k]; - } - } - - if (count>=2) - eval.winRanks[k]=rmax; - - if (localVar[thrId].nodeTypeStore[hmax]==MAXNODE) - goto maxexit; - else - goto minexit; - - maxexit: - eval.tricks=posPoint->tricksMAX+1; - return eval; - - minexit: - eval.tricks=posPoint->tricksMAX; - return eval; -} - - -int QuickTricks(struct pos * posPoint, int hand, - int depth, int target, int trump, int *result, int thrId) { - int suit, sum, commRank=0, commSuit=-1, s; - int opps, res; - int countLho, countRho, countPart, countOwn, lhoTrumpRanks, rhoTrumpRanks; - int cutoff, ss, rr, lowestQtricks=0; - - int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner, - int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res); - - int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, - int countPart, int suit, int qtricks, int trump, int *res); - - int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, - int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); - - int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int countOwn, - int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); - - *result=TRUE; - int qtricks=0; - for (s=0; s<=3; s++) - posPoint->winRanks[depth][s]=0; - - if ((depth<=0)||(depth==localVar[thrId].iniDepth)) { - *result=FALSE; - return qtricks; - } - - if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) - cutoff=target-posPoint->tricksMAX; - else - cutoff=posPoint->tricksMAX-target+(depth>>2)+2; - - int commPartner=FALSE; - for (s=0; s<=3; s++) { - if ((trump!=4)&&(trump!=s)) { - if (posPoint->winner[s].hand==partner[hand]) { - /* Partner has winning card */ - if (posPoint->rankInSuit[hand][s]!=0) { - /* Own hand has card in suit */ - if (((posPoint->rankInSuit[lho[hand]][s]!=0) || - /* LHO not void */ - (posPoint->rankInSuit[lho[hand]][trump]==0)) - /* LHO has no trump */ - && ((posPoint->rankInSuit[rho[hand]][s]!=0) || - /* RHO not void */ - (posPoint->rankInSuit[rho[hand]][trump]==0))) { - /* RHO has no trump */ - commPartner=TRUE; - commSuit=s; - commRank=posPoint->winner[s].rank; - break; - } - } - } - else if (posPoint->secondBest[s].hand==partner[hand]) { - if ((posPoint->winner[s].hand==hand)&& - (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { - if (((posPoint->rankInSuit[lho[hand]][s]!=0) || - (posPoint->rankInSuit[lho[hand]][trump]==0)) - && ((posPoint->rankInSuit[rho[hand]][s]!=0) || - (posPoint->rankInSuit[rho[hand]][trump]==0))) { - commPartner=TRUE; - commSuit=s; - commRank=posPoint->secondBest[s].rank; - break; - } - } - } - } - else if (trump==4) { - if (posPoint->winner[s].hand==partner[hand]) { - /* Partner has winning card */ - if (posPoint->rankInSuit[hand][s]!=0) { - /* Own hand has card in suit */ - commPartner=TRUE; - commSuit=s; - commRank=posPoint->winner[s].rank; - break; - } - } - else if (posPoint->secondBest[s].hand==partner[hand]) { - if ((posPoint->winner[s].hand==hand)&& - (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { - commPartner=TRUE; - commSuit=s; - commRank=posPoint->secondBest[s].rank; - break; - } - } - } - } - - if ((trump!=4) && (!commPartner) && - (posPoint->rankInSuit[hand][trump]!=0) && - (posPoint->winner[trump].hand==partner[hand])) { - commPartner=TRUE; - commSuit=trump; - commRank=posPoint->winner[trump].rank; - } - - - if (trump!=4) { - suit=trump; - lhoTrumpRanks=posPoint->length[lho[hand]][trump]; - rhoTrumpRanks=posPoint->length[rho[hand]][trump]; - } - else - suit=0; - - do { - countOwn=posPoint->length[hand][suit]; - countLho=posPoint->length[lho[hand]][suit]; - countRho=posPoint->length[rho[hand]][suit]; - countPart=posPoint->length[partner[hand]][suit]; - opps=countLho | countRho; - - if (!opps && (countPart==0)) { - if (countOwn==0) { - /* Continue with next suit. */ - if ((trump!=4)&&(trump!=suit)) { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - } - else { - if ((trump!=4) && (trump==suit)) { - if (trump==0) - suit=1; - else - suit=0; - } - else - suit++; - } - continue; - } - - /* Long tricks when only leading hand have cards in the suit. */ - if ((trump!=4) && (trump!=suit)) { - if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { - qtricks+=countOwn; - if (qtricks>=cutoff) - return qtricks; - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - } - else { - qtricks+=countOwn; - if (qtricks>=cutoff) - return qtricks; - - if ((trump!=4) && (suit==trump)) { - if (trump==0) - suit=1; - else - suit=0; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - } - continue; - } - } - else { - if (!opps && (trump!=4) && (suit==trump)) { - /* The partner but not the opponents have cards in the trump suit. */ - sum=Max(countOwn, countPart); - for (s=0; s<=3; s++) { - if ((sum>0)&&(s!=trump)&&(countOwn>=countPart)&&(posPoint->length[hand][s]>0)&& - (posPoint->length[partner[hand]][s]==0)) { - sum++; - break; - } - } - /* If the additional trick by ruffing causes a cutoff. (qtricks not incremented.) */ - if (sum>=cutoff) - return sum; - } - else if (!opps) { - /* The partner but not the opponents have cards in the suit. */ - sum=Min(countOwn,countPart); - if (trump==4) { - if (sum>=cutoff) - return sum; - } - else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - if (sum>=cutoff) - return sum; - } - } - - if (commPartner) { - if (!opps && (countOwn==0)) { - if ((trump!=4) && (trump!=suit)) { - if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { - qtricks+=countPart; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - if (qtricks>=cutoff) - return qtricks; - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - } - else { - qtricks+=countPart; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - if (qtricks>=cutoff) - return qtricks; - if ((trump!=4) && (suit==trump)) { - if (trump==0) - suit=1; - else - suit=0; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - } - continue; - } - } - else { - if (!opps && (trump!=4) && (suit==trump)) { - sum=Max(countOwn, countPart); - for (s=0; s<=3; s++) { - if ((sum>0)&&(s!=trump)&&(countOwn<=countPart)&&(posPoint->length[partner[hand]][s]>0)&& - (posPoint->length[hand][s]==0)) { - sum++; - break; - } - } - if (sum>=cutoff) { - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - return sum; - } - } - else if (!opps) { - sum=Min(countOwn,countPart); - if (trump==4) { - if (sum>=cutoff) - return sum; - } - else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - if (sum>=cutoff) - return sum; - } - } - } - } - } - - if (posPoint->winner[suit].rank==0) { - if ((trump!=4) && (suit==trump)) { - if (trump==0) - suit=1; - else - suit=0; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - } - continue; - } - - if (posPoint->winner[suit].hand==hand) { - if ((trump!=4)&&(trump!=suit)) { - qtricks=QtricksLeadHandTrump(hand, posPoint, cutoff, depth, - countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, - countPart, suit, qtricks, trump, &res); - if (res==1) - return qtricks; - else if (res==2) { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - } - else { - qtricks=QtricksLeadHandNT(hand, posPoint, cutoff, depth, - countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks, - commPartner, commSuit, countOwn, - countPart, suit, qtricks, trump, &res); - if (res==1) - return qtricks; - else if (res==2) { - if ((trump!=4) && (trump==suit)) { - if (trump==0) - suit=1; - else - suit=0; - } - else - suit++; - continue; - } - } - } - - /* It was not possible to take a quick trick by own winning card in - the suit */ - else { - /* Partner winning card? */ - if ((posPoint->winner[suit].hand==partner[hand])&&(1/*countPart>0*/)) { - /* Winner found at partner*/ - if (commPartner) { - /* There is communication with the partner */ - if ((trump!=4)&&(trump!=suit)) { - qtricks=QuickTricksPartnerHandTrump(hand, posPoint, cutoff, depth, - countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, - countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); - if (res==1) - return qtricks; - else if (res==2) { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - } - else { - qtricks=QuickTricksPartnerHandNT(hand, posPoint, cutoff, depth, - countLho, countRho, countOwn, - countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); - if (res==1) - return qtricks; - else if (res==2) { - if ((trump!=4) && (trump==suit)) { - if (trump==0) - suit=1; - else - suit=0; - } - else - suit++; - continue; - } - } - } - } - } - if ((trump!=4) &&(suit!=trump)&& - (countOwn>0)&&(lowestQtricks==0)&& - ((qtricks==0)||((posPoint->winner[suit].hand!=hand)&& - (posPoint->winner[suit].hand!=partner[hand])&& - (posPoint->winner[trump].hand!=hand)&& - (posPoint->winner[trump].hand!=partner[hand])))) { - if ((countPart==0)&&(posPoint->length[partner[hand]][trump]>0)) { - if (((countRho>0)||(posPoint->length[rho[hand]][trump]==0))&& - ((countLho>0)||(posPoint->length[lho[hand]][trump]==0))) { - lowestQtricks=1; - if (1>=cutoff) - return 1; - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - else if ((countRho==0)&&(countLho==0)) { - if ((posPoint->rankInSuit[lho[hand]][trump] | - posPoint->rankInSuit[rho[hand]][trump]) < - posPoint->rankInSuit[partner[hand]][trump]) { - lowestQtricks=1; - - rr=highestRank[posPoint->rankInSuit[partner[hand]][trump]]; - if (rr!=0) { - posPoint->winRanks[depth][trump]|=bitMapRank[rr]; - if (1>=cutoff) - return 1; - } - } - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - else if (countLho==0) { - if (posPoint->rankInSuit[lho[hand]][trump] < - posPoint->rankInSuit[partner[hand]][trump]) { - lowestQtricks=1; - for (rr=14; rr>=2; rr--) { - if ((posPoint->rankInSuit[partner[hand]][trump] & - bitMapRank[rr])!=0) { - posPoint->winRanks[depth][trump]|=bitMapRank[rr]; - break; - } - } - if (1>=cutoff) - return 1; - } - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - else if (countRho==0) { - if (posPoint->rankInSuit[rho[hand]][trump] < - posPoint->rankInSuit[partner[hand]][trump]) { - lowestQtricks=1; - for (rr=14; rr>=2; rr--) { - if ((posPoint->rankInSuit[partner[hand]][trump] & - bitMapRank[rr])!=0) { - posPoint->winRanks[depth][trump]|=bitMapRank[rr]; - break; - } - } - if (1>=cutoff) - return 1; - } - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - continue; - } - } - } - if (qtricks>=cutoff) - return qtricks; - if ((trump!=4) && (suit==trump)) { - if (trump==0) - suit=1; - else - suit=0; - } - else { - suit++; - if ((trump!=4) && (suit==trump)) - suit++; - } - } - while (suit<=3); - - if (qtricks==0) { - if ((trump==4)||(posPoint->winner[trump].hand==-1)) { - for (ss=0; ss<=3; ss++) { - if (posPoint->winner[ss].hand==-1) - continue; - if (posPoint->length[hand][ss]>0) { - posPoint->winRanks[depth][ss]= - bitMapRank[posPoint->winner[ss].rank]; - } - } - if (localVar[thrId].nodeTypeStore[hand]!=MAXNODE) - cutoff=target-posPoint->tricksMAX; - else - cutoff=posPoint->tricksMAX-target+(depth>>2)+2; - - if (1>=cutoff) - return 0; - } - } - - *result=FALSE; - return qtricks; -} - - -int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, - int countPart, int suit, int qtricks, int trump, int *res) { - /* res=0 Continue with same suit. - res=1 Cutoff. - res=2 Continue with next suit. */ - - - *res=1; - int qt=qtricks; - if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { - posPoint->winRanks[depth][suit]|= - bitMapRank[posPoint->winner[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - - if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)&& - (lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - qt+=countOwn-1; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - - if (posPoint->secondBest[suit].hand==hand) { - if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - posPoint->winRanks[depth][suit]|= - bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { - qt+=countOwn-2; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - /*else { - aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][suit]; - if (rel[aggr].absRank[3][suit].hand==hand) { - qt++; - posPoint->winRanks[depth][suit]|= - bitMapRank[rel[aggr].absRank[3][suit].rank]; - if (qt>=cutoff) - return qt; - if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { - qt+=countOwn-3; - if (qt>=cutoff) - return qt; - } - *res=2; - return qt; - } - }*/ - } - } - else if ((posPoint->secondBest[suit].hand==partner[hand]) - &&(countOwn>1)&&(countPart>1)) { - /* Second best at partner and suit length of own - hand and partner > 1 */ - if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - posPoint->winRanks[depth][suit]|= - bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { - qt+=Max(countOwn-2, countPart-2); - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - } - *res=0; - return qt; -} - -int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, - int commPartner, int commSuit, int countOwn, - int countPart, int suit, int qtricks, int trump, int *res) { - /* res=0 Continue with same suit. - res=1 Cutoff. - res=2 Continue with next suit. */ - - - *res=1; - int qt=qtricks; - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { - /*if (trump==suit) {*/ - (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); - (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); - } - - if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)) { - qt+=countOwn-1; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - - if (posPoint->secondBest[suit].hand==hand) { - posPoint->winRanks[depth][suit]|= - bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { - (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); - (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); - } - if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { - qt+=countOwn-2; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - /*else { - aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][suit]; - if (rel[aggr].absRank[3][suit].hand==hand) { - qt++; - posPoint->winRanks[depth][suit]|= - bitMapRank[rel[aggr].absRank[3][suit].rank]; - if (qt>=cutoff) - return qt; - if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { - qt+=countOwn-3; - if (qt>=cutoff) - return qt; - } - *res=2; - return qt; - } - }*/ - } - else if ((posPoint->secondBest[suit].hand==partner[hand]) - &&(countOwn>1)&&(countPart>1)) { - /* Second best at partner and suit length of own - hand and partner > 1 */ - posPoint->winRanks[depth][suit]|= - bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { - (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); - (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); - } - if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { - qt+=Max(countOwn-2,countPart-2); - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - /*else if (countPart>2) { - aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][suit]; - if (rel[aggr].absRank[3][suit].hand==hand) { - qt++; - posPoint->winRanks[depth][suit]|= - bitMapRank[rel[aggr].absRank[3][suit].rank]; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - }*/ - } - - *res=0; - return qt; -} - - -int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, - int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { - /* res=0 Continue with same suit. - res=1 Cutoff. - res=2 Continue with next suit. */ - - - *res=1; - int qt=qtricks; - if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - qt++; /* A trick can be taken */ - if (qt>=cutoff) - return qt; - if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)&&(lhoTrumpRanks==0)&& - (rhoTrumpRanks==0)) { - qt+=countPart-1; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - - if (posPoint->secondBest[suit].hand==partner[hand]) { - /* Second best found in partners hand */ - if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - /* Opponents have no trump */ - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { - qt+=countPart-2; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - } - else if ((posPoint->secondBest[suit].hand==hand)&&(countPart>1)&&(countOwn>1)) { - /* Second best found in own hand and suit lengths of own hand and partner > 1*/ - if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - /* Opponents have no trump */ - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { - qt+=Max(countPart-2,countOwn-2); - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - } - else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])&& - ((countLho>=2)||(lhoTrumpRanks==0))&&((countRho>=2)||(rhoTrumpRanks==0))) { - unsigned short ranks=0; - for (int k=0; k<=3; k++) - ranks|=posPoint->rankInSuit[k][suit]; - if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { - posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { - qt+=countPart-2; - if (qt>=cutoff) - return qt; - } - } - } - *res=0; - return qt; -} - - -int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, - int countLho, int countRho, int countOwn, - int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { - - *res=1; - int qt=qtricks; - - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; - posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)) { - qt+=countPart-1; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - - if ((posPoint->secondBest[suit].hand==partner[hand])&&(1/*countPart>0*/)) { - /* Second best found in partners hand */ - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { - qt+=countPart-2; - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - else if ((posPoint->secondBest[suit].hand==hand) - &&(countPart>1)&&(countOwn>1)) { - /* Second best found in own hand and own and - partner's suit length > 1 */ - posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { - qt+=Max(countPart-2,countOwn-2); - if (qt>=cutoff) - return qt; - *res=2; - return qt; - } - } - else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])) { - unsigned short ranks=0; - for (int k=0; k<=3; k++) - ranks|=posPoint->rankInSuit[k][suit]; - if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { - posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; - qt++; - if (qt>=cutoff) - return qt; - if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)) { - qtricks+=countPart-2; - if (qt>=cutoff) - return qt; - } - } - } - *res=0; - return qt; -} - - -int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, - int trump, int thrId) { - int hh, ss, k, h, sum=0; - /*unsigned short aggr;*/ - - if ((trump==4)||(posPoint->winner[trump].rank==0)) { - for (ss=0; ss<=3; ss++) { - hh=posPoint->winner[ss].hand; - if (hh!=-1) { - if (localVar[thrId].nodeTypeStore[hh]==MAXNODE) - sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); - } - } - if ((posPoint->tricksMAX+sum0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { - if ((posPoint->tricksMAX+(depth>>2)winner[ss].hand==-1) - posPoint->winRanks[depth][ss]=0; - else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MINNODE) { - if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& - (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& - (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) - posPoint->winRanks[depth][ss]=0; - else - posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; - } - else - posPoint->winRanks[depth][ss]=0; - } - return FALSE; - } - } - } - else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && - (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MINNODE)) { - if ((posPoint->length[hand][trump]==0)&& - (posPoint->length[partner[hand]][trump]==0)) { - if (((posPoint->tricksMAX+(depth>>2)+1- - Max(posPoint->length[lho[hand]][trump], - posPoint->length[rho[hand]][trump]))0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - return FALSE; - } - } - else if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->winner[trump].rank]; - return FALSE; - } - else { - hh=posPoint->secondBest[trump].hand; - if (hh!=-1) { - if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&(posPoint->secondBest[trump].rank!=0)) { - if (((posPoint->length[hh][trump]>1) || - (posPoint->length[partner[hh]][trump]>1))&& - ((posPoint->tricksMAX+(depth>>2)-1)0) - &&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->secondBest[trump].rank] ; - return FALSE; - } - } - } - } - } - else if (trump!=4) { - hh=posPoint->secondBest[trump].hand; - if (hh!=-1) { - if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&& - (posPoint->length[hh][trump]>1)) { - if (posPoint->winner[trump].hand==rho[hh]) { - if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->secondBest[trump].rank]; - return FALSE; - } - } - else { - unsigned short aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][trump]; - h=localVar[thrId].rel[aggr].absRank[3][trump].hand; - if (h!=-1) { - if ((localVar[thrId].nodeTypeStore[h]==MINNODE)&& - ((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; - return FALSE; - } - } - } - } - } - } - return TRUE; -} - - -int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, - int trump, int thrId) { - int hh, ss, k, h, sum=0; - /*unsigned short aggr;*/ - - if ((trump==4)||(posPoint->winner[trump].rank==0)) { - for (ss=0; ss<=3; ss++) { - hh=posPoint->winner[ss].hand; - if (hh!=-1) { - if (localVar[thrId].nodeTypeStore[hh]==MINNODE) - sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); - } - } - if ((posPoint->tricksMAX+(depth>>2)+1-sum>=target)&& - (sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { - if ((posPoint->tricksMAX+1>=target)) { - for (ss=0; ss<=3; ss++) { - if (posPoint->winner[ss].hand==-1) - posPoint->winRanks[depth][ss]=0; - else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MAXNODE) { - if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& - (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& - (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) - posPoint->winRanks[depth][ss]=0; - else - posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; - } - else - posPoint->winRanks[depth][ss]=0; - } - return TRUE; - } - } - } - else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && - (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MAXNODE)) { - if ((posPoint->length[hand][trump]==0)&& - (posPoint->length[partner[hand]][trump]==0)) { - if (((posPoint->tricksMAX+Max(posPoint->length[lho[hand]][trump], - posPoint->length[rho[hand]][trump]))>=target) - &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - return TRUE; - } - } - else if (((posPoint->tricksMAX+1)>=target) - &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->winner[trump].rank]; - return TRUE; - } - else { - hh=posPoint->secondBest[trump].hand; - if (hh!=-1) { - if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&(posPoint->secondBest[trump].rank!=0)) { - if (((posPoint->length[hh][trump]>1) || - (posPoint->length[partner[hh]][trump]>1))&& - ((posPoint->tricksMAX+2)>=target)&&(depth>0) - &&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->secondBest[trump].rank]; - return TRUE; - } - } - } - } - } - - else if (trump!=4) { - hh=posPoint->secondBest[trump].hand; - if (hh!=-1) { - if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&& - (posPoint->length[hh][trump]>1)) { - if (posPoint->winner[trump].hand==rho[hh]) { - if (((posPoint->tricksMAX+1)>=target)&&(depth>0) - &&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[posPoint->secondBest[trump].rank] ; - return TRUE; - } - } - else { - unsigned short aggr=0; - for (k=0; k<=3; k++) - aggr|=posPoint->rankInSuit[k][trump]; - h=localVar[thrId].rel[aggr].absRank[3][trump].hand; - if (h!=-1) { - if ((localVar[thrId].nodeTypeStore[h]==MAXNODE)&& - ((posPoint->tricksMAX+1)>=target)&&(depth>0) - &&(depth!=localVar[thrId].iniDepth)) { - for (ss=0; ss<=3; ss++) - posPoint->winRanks[depth][ss]=0; - posPoint->winRanks[depth][trump]= - bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; - return TRUE; - } - } - } - } - } - } - return FALSE; -} - - -int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId) { - int k, state=MOVESVALID; - - int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int trump, int thrId); - int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int thrId); - - for (k=0; k<4; k++) - localVar[thrId].lowestWin[depth][k]=0; - - int m=0; - int r=posPoint->handRelFirst; - int first=posPoint->first[depth]; - int q=handId(first, r); - - if (r!=0) { - int s=localVar[thrId].movePly[depth+r].current; /* Current move of first hand */ - int t=localVar[thrId].movePly[depth+r].move[s].suit; /* Suit played by first hand */ - unsigned short ris=posPoint->rankInSuit[q][t]; - - if (ris!=0) { - /* Not first hand and not void in suit */ - k=14; - while (k>=2) { - if ((ris & bitMapRank[k])&&(state==MOVESVALID)) { - /* Only first move in sequence is generated */ - mply->move[m].suit=t; - mply->move[m].rank=k; - mply->move[m].sequence=0; - m++; - state=MOVESLOCKED; - } - else if (state==MOVESLOCKED) { - if (ris & bitMapRank[k]) - /* If the card is in own hand */ - mply->move[m-1].sequence|=bitMapRank[k]; - else if ((posPoint->removedRanks[t] & 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++) - mply->move[k].weight=WeightAllocTrump(posPoint, - &(mply->move[k]), depth, ris, trump, thrId); - } - else { - for (k=0; k<=m-1; k++) - mply->move[k].weight=WeightAllocNT(posPoint, - &(mply->move[k]), depth, ris, thrId); - } - } - - mply->last=m-1; - if (m!=1) - MergeSort(m, mply->move); - if (depth!=localVar[thrId].iniDepth) - return m; - else { - m=AdjustMoveList(thrId); - return m; - } - } - } - - /* First hand or void in suit */ - for (int suit=0; suit<=3; suit++) { - k=14; state=MOVESVALID; - while (k>=2) { - if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&& - (state==MOVESVALID)) { - /* Only first move in sequence is generated */ - mply->move[m].suit=suit; - mply->move[m].rank=k; - mply->move[m].sequence=0; - m++; - state=MOVESLOCKED; - } - else if (state==MOVESLOCKED) { - if (posPoint->rankInSuit[q][suit] & bitMapRank[k]) - /* If the card is in own hand */ - mply->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--; - } - } - - if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { - for (k=0; k<=m-1; k++) - mply->move[k].weight=WeightAllocTrump(posPoint, - &(mply->move[k]), depth, 0/*ris*/, trump, thrId); - } - else { - for (k=0; k<=m-1; k++) - mply->move[k].weight=WeightAllocNT(posPoint, - &(mply->move[k]), depth, 0/*ris*/, thrId); - } - - mply->last=m-1; - if (m!=1) - MergeSort(m, mply->move); - - if (depth!=localVar[thrId].iniDepth) - return m; - else { - m=AdjustMoveList(thrId); - return m; - } -} - - -int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int thrId) { - 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; - for (int m=0; m<=3; m++) - aggr|=posPoint->rankInSuit[m][suit]; - int rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; - - switch (posPoint->handRelFirst) { - case 0: - /*thirdBestHand=localVar[thrId].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 (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. */ - - suitWeightDelta=-((countLH+countRH)<<5)/19; - - if (posPoint->length[partner[q]][suit]==0) - suitWeightDelta+=-9; - - 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; - } - - 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; - } - - /* 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 (((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; - - /* Encourage playing cards that previously caused search cutoff - or was stored as the best move in a transposition table entry match. */ - - if ((localVar[thrId].bestMove[depth].suit==suit)&& - (localVar[thrId].bestMove[depth].rank==mp->rank)) - weight+=126; - else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& - (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=24; - } - else { - /* Discourage suit if RHO has winning or second best card. - Exception: RHO has singleton. */ - - if ((posPoint->winner[suit].hand==rho[q])|| - (posPoint->secondBest[suit].hand==rho[q])) { - if (suitCountRH!=1) - suitWeightDelta+=-10; - } - - - /* 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; - } - - /* 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. */ - - thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand; - - 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; - - /* 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+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+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. */ - - if ((localVar[thrId].bestMove[depth].suit==suit)&& - (localVar[thrId].bestMove[depth].rank==mp->rank)) - weight+=47; - else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& - (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=19; - } - - break; - - case 1: - leadSuit=posPoint->move[depth+1].suit; - if (leadSuit==suit) { - if (bitMapRank[mp->rank]> - (bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[partner[first]][suit])) - winMove=TRUE; - else if (posPoint->rankInSuit[rho[first]][suit]> - (bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[partner[first]][suit])) - winMove=TRUE; - } - else { - /* Side with highest rank in leadSuit wins */ - - if (posPoint->rankInSuit[rho[first]][leadSuit] > - (posPoint->rankInSuit[partner[first]][leadSuit] | - bitMapRank[posPoint->move[depth+1].rank])) - winMove=TRUE; - } - - if (winMove) { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/); - if (posPoint->secondBest[suit].hand==q) { - /* Discourage suit discard if 2nd highest card becomes singleton. */ - - if (suitCount==2) - suitAdd+=-2; - } - /* Discourage suit discard of highest card. */ - - else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd+=-3; - - /*Encourage discard of low cards in long suits. */ - weight=-4-(mp->rank)+suitAdd; - } - else { - weight=81/*80*/+rRank; - } - } - else { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/33; - - /* Discourage suit discard if 2nd highest card becomes singleton. */ - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd+=-6; - - /* Discourage suit discard of highest card. */ - else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd+=-8; - - /*Encourage discard of low cards in long suits. */ - weight=2-(mp->rank)+suitAdd; - } - else { - - /* If lowest rank for either partner to leading hand - or rho is higher than played card for lho, - lho should play as low card as possible */ - - kk=posPoint->rankInSuit[partner[first]][leadSuit]; - ll=posPoint->rankInSuit[rho[first]][leadSuit]; - k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of - bit map ranks for partner and RHO. */ - - if ((k > bitMapRank[mp->rank])||(l > bitMapRank[mp->rank])) - weight=-3+rRank; - else if (mp->rank > posPoint->move[depth+1].rank) { - if (mp->sequence) { - weight=/*0*/10+rRank; - } - else { - weight=13-(mp->rank); - /*weight=-5+rRank;*/ - } - } - else { - weight=-11/*15*/+rRank; - } - } - } - - break; - - case 2: - - leadSuit=posPoint->move[depth+2].suit; - if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) { - if (bitMapRank[mp->rank] > - posPoint->rankInSuit[rho[first]][suit]) - winMove=TRUE; - } - else if (posPoint->high[depth+1]==first) { - if (posPoint->rankInSuit[rho[first]][leadSuit] - < bitMapRank[posPoint->move[depth+2].rank]) - winMove=TRUE; - - } - - if (winMove) { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(17/*27*//*30*//*35*/); - - /* Discourage suit discard if 2nd highest card becomes singleton. */ - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(6/*2*//*5*/); - weight=-(mp->rank)+suitAdd; - } - else { - weight=60+rRank; - } - } - else { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(24/*26*//*29*//*35*/); - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(4/*5*/); - /* Discourage suit discard of highest card. */ - else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd-=(4/*5*/); - - weight=-(mp->rank)+suitAdd; - - } - else { - - k=posPoint->rankInSuit[rho[first]][suit]; - if ((k & (-k)) > bitMapRank[mp->rank]) - weight=-(mp->rank); - else if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) { - if ((mp->rank==posPoint->secondBest[leadSuit].rank)&& - (mp->sequence)) - weight=25; - else if (mp->sequence) - weight=20-(mp->rank); - else - weight=10-(mp->rank); - } - else - weight=-10-(mp->rank); - } - } - - break; - - case 3: - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(27/*35*/); - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(6/*5*/); - else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) - suitAdd-=(8/*9*//*8*//*5*/); - - weight=30-(mp->rank)+suitAdd; - } - else if ((posPoint->high[depth+1])==(lho[first])) { - /* If the current winning move is given by the partner */ - weight=30-(mp->rank); - } - else if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) - /* If present move is superior to current winning move and the - current winning move is not given by the partner */ - weight=30-(mp->rank); - else { - /* If present move is not superior to current winning move and the - current winning move is not given by the partner */ - weight=14-(mp->rank); - } - } - return weight; -} - - - -int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, - unsigned short notVoidInSuit, int trump, int thrId) { - 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; - int countLH, countRH; - - 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=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; - - switch (posPoint->handRelFirst) { - case 0: - /*thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;*/ - suitCount=posPoint->length[q][suit]; - suitCountLH=posPoint->length[lho[q]][suit]; - suitCountRH=posPoint->length[rho[q]][suit]; - - /* Discourage suit if LHO or RHO can ruff. */ - - if ((suit!=trump) && - (((posPoint->rankInSuit[lho[q]][suit]==0) && - (posPoint->rankInSuit[lho[q]][trump]!=0)) || - ((posPoint->rankInSuit[rho[q]][suit]==0) && - (posPoint->rankInSuit[rho[q]][trump]!=0)))) - suitBonus=-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+=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+=-12/*13*//*11*/; - } - - /* 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) - suitBonus+=27/*25*//*30*/; - } - - /* Encourage play of suit where partner wins and - returns the suit for a ruff. */ - if ((suit!=trump)&&(suitCount==1)&& - (posPoint->length[q][trump]>0)&& - (posPoint->length[partner[q]][suit]>1)&& - (posPoint->winner[suit].hand==partner[q])) - suitBonus+=19/*26*//*23*/; - - if (suitCountLH!=0) - countLH=(suitCountLH<<2); - else - countLH=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. */ - - suitWeightDelta=suitBonus- - ((countLH+countRH)<<5)/13; - - if (posPoint->winner[suit].rank==mp->rank) { - if ((suit!=trump)) { - if ((posPoint->length[partner[first]][suit]!=0)|| - (posPoint->length[partner[first]][trump]==0)) { - if (((posPoint->length[lho[first]][suit]!=0)|| - (posPoint->length[lho[first]][trump]==0))&& - ((posPoint->length[rho[first]][suit]!=0)|| - (posPoint->length[rho[first]][trump]==0))) - winMove=TRUE; - } - else if (((posPoint->length[lho[first]][suit]!=0)|| - (posPoint->rankInSuit[partner[first]][trump]> - posPoint->rankInSuit[lho[first]][trump]))&& - ((posPoint->length[rho[first]][suit]!=0)|| - (posPoint->rankInSuit[partner[first]][trump]> - posPoint->rankInSuit[rho[first]][trump]))) - winMove=TRUE; - } - else - winMove=TRUE; - } - else if (posPoint->rankInSuit[partner[first]][suit] > - (posPoint->rankInSuit[lho[first]][suit] | - posPoint->rankInSuit[rho[first]][suit])) { - if (suit!=trump) { - if (((posPoint->length[lho[first]][suit]!=0)|| - (posPoint->length[lho[first]][trump]==0))&& - ((posPoint->length[rho[first]][suit]!=0)|| - (posPoint->length[rho[first]][trump]==0))) - winMove=TRUE; - } - else - winMove=TRUE; - } - else if (suit!=trump) { - if ((posPoint->length[partner[first]][suit]==0)&& - (posPoint->length[partner[first]][trump]!=0)) { - if ((posPoint->length[lho[first]][suit]==0)&& - (posPoint->length[lho[first]][trump]!=0)&& - (posPoint->length[rho[first]][suit]==0)&& - (posPoint->length[rho[first]][trump]!=0)) { - if (posPoint->rankInSuit[partner[first]][trump]> - (posPoint->rankInSuit[lho[first]][trump] | - posPoint->rankInSuit[rho[first]][trump])) - winMove=TRUE; - } - else if ((posPoint->length[lho[first]][suit]==0)&& - (posPoint->length[lho[first]][trump]!=0)) { - if (posPoint->rankInSuit[partner[first]][trump] - > posPoint->rankInSuit[lho[first]][trump]) - winMove=TRUE; - } - else if ((posPoint->length[rho[first]][suit]==0)&& - (posPoint->length[rho[first]][trump]!=0)) { - if (posPoint->rankInSuit[partner[first]][trump] - > posPoint->rankInSuit[rho[first]][trump]) - winMove=TRUE; - } - else - winMove=TRUE; - } - } - - if (winMove) { - - /* Encourage ruffing LHO or RHO singleton, highest card. */ - - if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) - ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) - weight=suitWeightDelta+35/*37*//*39*/+rRank; - - /* Lead hand has the highest card. */ - - else if (posPoint->winner[suit].hand==first) { - - /* Also, partner has second highest card. */ - - if (posPoint->secondBest[suit].hand==partner[first]) - 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-3+rRank; - } - else if (posPoint->winner[suit].hand==partner[first]) { - /* If partner has highest card */ - if (posPoint->secondBest[suit].hand==first) - weight=suitWeightDelta+42/*35*//*46*//*50*/+rRank; - else - 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+40/*41*/; - else if (mp->sequence) - weight=suitWeightDelta+22/*17*/+rRank; - else - weight=suitWeightDelta+11+rRank; - - /* Encourage playing cards that previously caused search cutoff - or was stored as the best move in a transposition table entry match. */ - - if ((localVar[thrId].bestMove[depth].suit==suit)&& - (localVar[thrId].bestMove[depth].rank==mp->rank)) - weight+=55/*53*/; - else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& - (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=18/*14*/; - } - else { - - /* 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. */ - - thirdBestHand=localVar[thrId].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+=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/*-2*/; - else if (posPoint->winner[suit].hand==first) { - if (posPoint->secondBest[suit].hand==partner[first]) - - /* Opponents win by ruffing */ - - weight=suitWeightDelta+33+rRank; - else if (posPoint->winner[suit].rank==mp->rank) - - /* Opponents win by ruffing */ - - weight=suitWeightDelta+38/*36*/; - else - weight=suitWeightDelta-14/*17*/+rRank; - } - else if (posPoint->winner[suit].hand==partner[first]) { - - /* Opponents win by ruffing */ - - 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+35/*31*/; - else - 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 ((localVar[thrId].bestMove[depth].suit==suit)&& - (localVar[thrId].bestMove[depth].rank==mp->rank)) - weight+=18/*17*/; - /*else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& - (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) - weight+=4;*/ - } - - break; - - case 1: - leadSuit=posPoint->move[depth+1].suit; - if (leadSuit==suit) { - if (bitMapRank[mp->rank]> - (bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[partner[first]][suit])) { - if (suit!=trump) { - if ((posPoint->length[partner[first]][suit]!=0)|| - (posPoint->length[partner[first]][trump]==0)) - winMove=TRUE; - else if ((posPoint->length[rho[first]][suit]==0) - &&(posPoint->length[rho[first]][trump]!=0) - &&(posPoint->rankInSuit[rho[first]][trump]> - posPoint->rankInSuit[partner[first]][trump])) - winMove=TRUE; - } - else - winMove=TRUE; - } - else if (posPoint->rankInSuit[rho[first]][suit]> - (bitMapRank[posPoint->move[depth+1].rank] | - posPoint->rankInSuit[partner[first]][suit])) { - if (suit!=trump) { - if ((posPoint->length[partner[first]][suit]!=0)|| - (posPoint->length[partner[first]][trump]==0)) - winMove=TRUE; - } - else - winMove=TRUE; - } - else if (bitMapRank[posPoint->move[depth+1].rank] > - (posPoint->rankInSuit[rho[first]][suit] | - posPoint->rankInSuit[partner[first]][suit] | - bitMapRank[mp->rank])) { - if (suit!=trump) { - if ((posPoint->length[rho[first]][suit]==0)&& - (posPoint->length[rho[first]][trump]!=0)) { - if ((posPoint->length[partner[first]][suit]!=0)|| - (posPoint->length[partner[first]][trump]==0)) - winMove=TRUE; - else if (posPoint->rankInSuit[rho[first]][trump] - > posPoint->rankInSuit[partner[first]][trump]) - winMove=TRUE; - } - } - } - else { /* winnerHand is partner to first */ - if (suit!=trump) { - if ((posPoint->length[rho[first]][suit]==0)&& - (posPoint->length[rho[first]][trump]!=0)) - winMove=TRUE; - } - } - } - else { - - /* Leading suit differs from suit played by LHO */ - - if (suit==trump) { - if (posPoint->length[partner[first]][leadSuit]!=0) - winMove=TRUE; - else if (bitMapRank[mp->rank]> - posPoint->rankInSuit[partner[first]][trump]) - winMove=TRUE; - else if ((posPoint->length[rho[first]][leadSuit]==0) - &&(posPoint->length[rho[first]][trump]!=0)&& - (posPoint->rankInSuit[rho[first]][trump] > - posPoint->rankInSuit[partner[first]][trump])) - winMove=TRUE; - } - else if (leadSuit!=trump) { - - /* Neither suit nor leadSuit is trump */ - - if (posPoint->length[partner[first]][leadSuit]!=0) { - if (posPoint->rankInSuit[rho[first]][leadSuit] > - (posPoint->rankInSuit[partner[first]][leadSuit] | - bitMapRank[posPoint->move[depth+1].rank])) - winMove=TRUE; - else if ((posPoint->length[rho[first]][leadSuit]==0) - &&(posPoint->length[rho[first]][trump]!=0)) - winMove=TRUE; - } - - /* Partner to leading hand is void in leading suit */ - - else if ((posPoint->length[rho[first]][leadSuit]==0) - &&(posPoint->rankInSuit[rho[first]][trump]> - posPoint->rankInSuit[partner[first]][trump])) - winMove=TRUE; - else if ((posPoint->length[partner[first]][trump]==0) - &&(posPoint->rankInSuit[rho[first]][leadSuit] > - bitMapRank[posPoint->move[depth+1].rank])) - winMove=TRUE; - } - else { - /* Either no trumps or leadSuit is trump, side with - highest rank in leadSuit wins */ - if (posPoint->rankInSuit[rho[first]][leadSuit] > - (posPoint->rankInSuit[partner[first]][leadSuit] | - bitMapRank[posPoint->move[depth+1].rank])) - winMove=TRUE; - } - } - - - kk=posPoint->rankInSuit[partner[first]][leadSuit]; - ll=posPoint->rankInSuit[rho[first]][leadSuit]; - k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of - bit map ranks for partner and RHO. */ - - if (winMove) { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - 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 (suit==trump) - 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+rRank; - - /* If lowest card for partner to leading hand - is higher than lho played card, playing as low as - possible will give the cheapest win */ - - else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& - (posPoint->rankInSuit[first][leadSuit] > ll)) - weight=41+rRank; - - /* If rho has a card in the leading suit that - is higher than the trick leading card but lower - than the highest rank of the leading hand, then - lho playing the lowest card will be the cheapest - win */ - - else if (mp->rank > posPoint->move[depth+1].rank) { - if (bitMapRank[mp->rank] < ll) - weight=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=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-(mp->rank); - else - weight=49-(mp->rank); - } - } - else if (posPoint->length[rho[first]][leadSuit]>0) { - /*if (mp->sequence)*/ - weight=47-(mp->rank); /* Playing a card in a sequence may promote a winner */ - /* Insensistive */ - /*else - weight=47-(mp->rank);*/ - } - else - weight=40-(mp->rank); - } - else { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/36; - - /* Discourage suit discard if 2nd highest card becomes singleton. */ - - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd+=-4; - - if (suit==trump) { - weight=15-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick - costly for the opponents */ - } - else - weight=-2-(mp->rank)+suitAdd; - } - else if ((k > bitMapRank[mp->rank])|| - (l > bitMapRank[mp->rank])) - weight=-9+rRank; - - /* If lowest rank for either partner to leading hand - or rho is higher than played card for lho, - lho should play as low card as possible */ - - else if (mp->rank > posPoint->move[depth+1].rank) { - if (mp->sequence) - weight=22-(mp->rank); - else - weight=10-(mp->rank); - } - else - weight=-16+rRank; - } - break; - - case 2: - - leadSuit=posPoint->move[depth+2].suit; - if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) { - if (suit==leadSuit) { - if (leadSuit!=trump) { - if (((posPoint->length[rho[first]][suit]!=0)|| - (posPoint->length[rho[first]][trump]==0))&& - (bitMapRank[mp->rank] > - posPoint->rankInSuit[rho[first]][suit])) - winMove=TRUE; - } - else if (bitMapRank[mp->rank] > - posPoint->rankInSuit[rho[first]][suit]) - winMove=TRUE; - } - else { /* Suit is trump */ - if (posPoint->length[rho[first]][leadSuit]==0) { - if (bitMapRank[mp->rank] > - posPoint->rankInSuit[rho[first]][trump]) - winMove=TRUE; - } - else - winMove=TRUE; - } - } - else if (posPoint->high[depth+1]==first) { - if (posPoint->length[rho[first]][leadSuit]!=0) { - if (posPoint->rankInSuit[rho[first]][leadSuit] - < bitMapRank[posPoint->move[depth+2].rank]) - winMove=TRUE; - } - else if (leadSuit==trump) - winMove=TRUE; - else if ((leadSuit!=trump) && - (posPoint->length[rho[first]][trump]==0)) - winMove=TRUE; - } - - if (winMove) { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(50/*36*/); - - /* Discourage suit discard if 2nd highest card becomes singleton. */ - - /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(3);*/ - - if (posPoint->high[depth+1]==first) { - if (suit==trump) - weight=48-(mp->rank)+suitAdd; /* Ruffs partner's winner */ - else - weight=61-(mp->rank)+suitAdd; - } - else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) - - /* Own hand on top by ruffing */ - - weight=72-(mp->rank)+suitAdd; - } - else - weight=58-(mp->rank); - } - else { - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/40; - - /* Discourage suit discard if 2nd highest card becomes singleton. */ - - /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(4);*/ - - if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) - - /* Own hand on top by ruffing */ - - weight=40-(mp->rank)+suitAdd; - else if (suit==trump) - - /* Discard a trump but still losing */ - - weight=-32+rRank+suitAdd; - else - weight=-2-(mp->rank)+suitAdd; - } - else { - k=posPoint->rankInSuit[rho[first]][suit]; - if ((k & (-k)) > bitMapRank[mp->rank]) - - /* If least bit map rank of RHO to lead hand is higher than bit map rank - of current card move. */ - - weight=-3-(mp->rank); - - else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) { - - /* If current card move is highest so far. */ - - if (mp->rank==posPoint->secondBest[leadSuit].rank) - weight=29; - else if (mp->sequence) - weight=26/*20*/-(mp->rank); - else - weight=18-(mp->rank); - } - else - weight=-12-(mp->rank); - } - } - - break; - - case 3: - if (!notVoidInSuit) { - suitCount=posPoint->length[q][suit]; - suitAdd=(suitCount<<6)/(24/*36*/); - if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) - suitAdd-=(2); - - if ((posPoint->high[depth+1])==lho[first]) { - - /* If the current winning move is given by the partner */ - - if (suit==trump) - - /* Ruffing partners winner? */ - - weight=2/*17*/-(mp->rank)+suitAdd; - else - weight=25-(mp->rank)+suitAdd; - } - else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) - - /* Own hand ruffs */ - - weight=33/*27*/+rRank+suitAdd; - else if (suit==trump) - weight=-13+rRank; - else - weight=14-(mp->rank)+suitAdd; - } - else if ((posPoint->high[depth+1])==(lho[first])) { - - /* If the current winning move is given by the partner */ - - if (suit==trump) - - /* Ruffs partners winner */ - - weight=11+rRank; - else - weight=17+rRank; - } - else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) - - /* If present move is superior to current winning move and the - current winning move is not given by the partner */ - - weight=22+rRank; - else { - - /* If present move is not superior to current winning move and the - current winning move is not given by the partner */ - - if (suit==trump) - - /* Ruffs but still loses */ - - weight=-13+rRank; - else - weight=1+rRank; - } - } - return weight; -} - - -/* Shell-1 */ -/* K&R page 62: */ -/*void shellSort(int n, int depth) { - int gap, i, j; - struct moveType temp; - - if (n==2) { - if (movePly[depth].move[0].weight>1; gap>0; gap>>=1) - for (i=gap; i=0 && movePly[depth].move[j].weight< - movePly[depth].move[j+gap].weight; j-=gap) { - temp=movePly[depth].move[j]; - movePly[depth].move[j]=movePly[depth].move[j+gap]; - movePly[depth].move[j+gap]=temp; - } -} */ - -/* Shell-2 */ -/*void shellSort(int n, int depth) -{ - int i, j, increment; - struct moveType temp; - - if (n==2) { - if (movePly[depth].move[0].weight 0) - { - for (i=0; i < n; i++) - { - j = i; - temp = movePly[depth].move[i]; - while ((j >= increment) && (movePly[depth].move[j-increment].weight < temp.weight)) - { - movePly[depth].move[j] = movePly[depth].move[j - increment]; - j = j - increment; - } - movePly[depth].move[j] = temp; - } - if ((increment>>1) != 0) - increment>>=1; - else if (increment == 1) - increment = 0; - else - increment = 1; - } -} */ - - -/* Insert-1 */ -/*void InsertSort(int n, int depth, struct movePlyType *mply, int thrId) { - int i, j; - struct moveType a, temp; - - if (n==2) { - if (mply->move[0].weightmove[1].weight) { - temp=mply->move[0]; - mply->move[0]=mply->move[1]; - mply->move[1]=temp; - return; - } - else - return; - } - - a=mply->move[0]; - for (i=1; i<=n-1; i++) - if (mply->move[i].weight>a.weight) { - temp=a; - a=mply->move[i]; - mply->move[i]=temp; - } - mply->move[0]=a; - for (i=2; i<=n-1; i++) { - j=i; - a=mply->move[i]; - while (a.weight>mply->move[j-1].weight) { - mply->move[j]=mply->move[j-1]; - j--; - } - mply->move[j]=a; - } -} */ - - -/* Insert-2 */ -/*void InsertSort(int n, int depth) { - int i, j; - struct moveType a; - - if (n==2) { - if (movePly[depth].move[0].weight=0)&&(movePly[depth].move[i].weight a[j - 1].weight ; --j) - a[j] = a[j - 1]; - a[j] = tmp; - } - } - - return; -} - - - -int AdjustMoveList(int thrId) { - int k, r, n, rank, suit; - - for (k=1; k<=13; k++) { - suit=localVar[thrId].forbiddenMoves[k].suit; - rank=localVar[thrId].forbiddenMoves[k].rank; - for (r=0; r<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; r++) { - if ((suit==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].suit)&& - (rank!=0)&&(rank==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].rank)) { - /* For the forbidden move r: */ - for (n=r; n<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; n++) - localVar[thrId].movePly[localVar[thrId].iniDepth].move[n]= - localVar[thrId].movePly[localVar[thrId].iniDepth].move[n+1]; - localVar[thrId].movePly[localVar[thrId].iniDepth].last--; - } - } - } - return localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; -} - - -int InvBitMapRank(unsigned short bitMap) { - - switch (bitMap) { - case 0x1000: return 14; - case 0x0800: return 13; - case 0x0400: return 12; - case 0x0200: return 11; - case 0x0100: return 10; - case 0x0080: return 9; - case 0x0040: return 8; - case 0x0020: return 7; - case 0x0010: return 6; - case 0x0008: return 5; - case 0x0004: return 4; - case 0x0002: return 3; - case 0x0001: return 2; - default: return 0; - } -} - -int InvWinMask(int mask) { - - switch (mask) { - case 0x01000000: return 1; - case 0x00400000: return 2; - case 0x00100000: return 3; - case 0x00040000: return 4; - case 0x00010000: return 5; - case 0x00004000: return 6; - case 0x00001000: return 7; - case 0x00000400: return 8; - case 0x00000100: return 9; - case 0x00000040: return 10; - case 0x00000010: return 11; - case 0x00000004: return 12; - case 0x00000001: return 13; - default: return 0; - } -} - - -inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump) { -/* Return TRUE if move 1 wins over move 2, with the assumption that -move 2 is the presently winning card of the trick */ - - if (mvp1->suit==mvp2->suit) { - if ((mvp1->rank)>(mvp2->rank)) - return TRUE; - else - return FALSE; - } - else if ((mvp1->suit)==trump) - return TRUE; - else - return FALSE; -} - - -inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2) { -/* Return TRUE if move 1 wins over move 2, with the assumption that -move 2 is the presently winning card of the trick */ - - if (mvp1->suit==mvp2->suit) { - if ((mvp1->rank)>(mvp2->rank)) - return TRUE; - else - return FALSE; - } - else - return FALSE; -} - - -struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType - * nodep, int target, int tricks, int * result, int *value, int thrId) { - /* Check SOP if it matches the - current position. If match, pointer to the SOP node is returned and - result is set to TRUE, otherwise pointer to SOP node is returned - and result set to FALSE. */ - - /* 07-04-22 */ - if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { - if (nodep->lbound==-1) { /* This bound values for - this leading hand has not yet been determined */ - *result=FALSE; - return nodep; - } - else if ((posPoint->tricksMAX + nodep->lbound)>=target) { - *value=TRUE; - *result=TRUE; - return nodep; - } - else if ((posPoint->tricksMAX + nodep->ubound)ubound==-1) { /* This bound values for - this leading hand has not yet been determined */ - *result=FALSE; - return nodep; - } - else if ((posPoint->tricksMAX + (tricks + 1 - nodep->ubound))>=target) { - *value=TRUE; - *result=TRUE; - return nodep; - } - else if ((posPoint->tricksMAX + (tricks + 1 - nodep->lbound))lbound > nodep->lbound) || - (nodep->lbound==-1)) - nodep->lbound=posPoint->lbound; - if ((posPoint->ubound < nodep->ubound) || - (nodep->ubound==-1)) - nodep->ubound=posPoint->ubound; - - nodep->bestMoveSuit=posPoint->bestMoveSuit; - nodep->bestMoveRank=posPoint->bestMoveRank; - - return nodep; -} - - -struct nodeCardsType * FindSOP(struct pos * posPoint, - struct winCardType * nodeP, int firstHand, - int target, int tricks, int * valp, int thrId) { - struct nodeCardsType * sopP; - struct winCardType * np; - int res; - - np=nodeP; - int s=0; - while ((np!=NULL)&&(s<4)) { - if ((np->winMask & posPoint->orderSet[s])== - np->orderSet) { - /* Winning rank set fits position */ - if (s==3) { - sopP=CheckSOP(posPoint, np->first, target, tricks, &res, valp, thrId); - if (res) { - return sopP; - } - else { - if (np->next!=NULL) { - np=np->next; - } - else { - np=np->prevWin; - s--; - if (np==NULL) - return NULL; - while (np->next==NULL) { - np=np->prevWin; - s--; - if (np==NULL) /* Previous node is header node? */ - return NULL; - } - np=np->next; - } - } - } - else if (s<4) { - np=np->nextWin; - s++; - } - } - else { - if (np->next!=NULL) { - np=np->next; - } - else { - np=np->prevWin; - s--; - if (np==NULL) - return NULL; - while (np->next==NULL) { - np=np->prevWin; - s--; - if (np==NULL) /* Previous node is header node? */ - return NULL; - } - np=np->next; - } - } - } - return NULL; -} - - -struct nodeCardsType * BuildPath(struct pos * posPoint, - struct posSearchType *nodep, int * result, int thrId) { - /* If result is TRUE, a new SOP has been created and BuildPath returns a - pointer to it. If result is FALSE, an existing SOP is used and BuildPath - returns a pointer to the SOP */ - - int found; - struct winCardType * np, * p2, /* * sp2,*/ * nprev, * fnp, *pnp; - struct winCardType temp; - struct nodeCardsType * sopP=0, * p/*, * sp*/; - - np=nodep->posSearchPoint; - nprev=NULL; - int suit=0; - - /* If winning node has a card that equals the next winning card deduced - from the position, then there already exists a (partial) path */ - - if (np==NULL) { /* There is no winning list created yet */ - /* Create winning nodes */ - p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; - AddWinSet(thrId); - p2->next=NULL; - p2->nextWin=NULL; - p2->prevWin=NULL; - nodep->posSearchPoint=p2; - p2->winMask=posPoint->winMask[suit]; - p2->orderSet=posPoint->winOrderSet[suit]; - p2->first=NULL; - np=p2; /* Latest winning node */ - suit++; - while (suit<4) { - p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; - AddWinSet(thrId); - np->nextWin=p2; - p2->prevWin=np; - p2->next=NULL; - p2->nextWin=NULL; - p2->winMask=posPoint->winMask[suit]; - p2->orderSet=posPoint->winOrderSet[suit]; - p2->first=NULL; - np=p2; /* Latest winning node */ - suit++; - } - p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; - AddNodeSet(thrId); - np->first=p; - *result=TRUE; - return p; - } - else { /* Winning list exists */ - while (1) { /* Find all winning nodes that correspond to current - position */ - found=FALSE; - while (1) { /* Find node amongst alternatives */ - if ((np->winMask==posPoint->winMask[suit])&& - (np->orderSet==posPoint->winOrderSet[suit])) { - /* Part of path found */ - found=TRUE; - nprev=np; - break; - } - if (np->next!=NULL) - np=np->next; - else - break; - } - if (found) { - suit++; - if (suit>3) { - sopP=UpdateSOP(posPoint, np->first); - - if (np->prevWin!=NULL) { - pnp=np->prevWin; - fnp=pnp->nextWin; - } - else - fnp=nodep->posSearchPoint; - - temp.orderSet=np->orderSet; - temp.winMask=np->winMask; - temp.first=np->first; - temp.nextWin=np->nextWin; - np->orderSet=fnp->orderSet; - np->winMask=fnp->winMask; - np->first=fnp->first; - np->nextWin=fnp->nextWin; - fnp->orderSet=temp.orderSet; - fnp->winMask=temp.winMask; - fnp->first=temp.first; - fnp->nextWin=temp.nextWin; - - *result=FALSE; - return sopP; - } - else { - np=np->nextWin; /* Find next winning node */ - continue; - } - } - else - break; /* Node was not found */ - } /* End outer while */ - - /* Create additional node, coupled to existing node(s) */ - p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; - AddWinSet(thrId); - p2->prevWin=nprev; - if (nprev!=NULL) { - p2->next=nprev->nextWin; - nprev->nextWin=p2; - } - else { - p2->next=nodep->posSearchPoint; - nodep->posSearchPoint=p2; - } - p2->nextWin=NULL; - p2->winMask=posPoint->winMask[suit]; - p2->orderSet=posPoint->winOrderSet[suit]; - p2->first=NULL; - np=p2; /* Latest winning node */ - suit++; - - /* Rest of path must be created */ - while (suit<4) { - p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; - AddWinSet(thrId); - np->nextWin=p2; - p2->prevWin=np; - p2->next=NULL; - p2->winMask=posPoint->winMask[suit]; - p2->orderSet=posPoint->winOrderSet[suit]; - p2->first=NULL; - p2->nextWin=NULL; - np=p2; /* Latest winning node */ - suit++; - } - - /* All winning nodes in SOP have been traversed and new nodes created */ - p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; - AddNodeSet(thrId); - np->first=p; - *result=TRUE; - return p; - } -} - - -struct posSearchType * SearchLenAndInsert(struct posSearchType - * rootp, long long key, int insertNode, int *result, int thrId) { -/* Search for node which matches with the suit length combination - given by parameter key. If no such node is found, NULL is - returned if parameter insertNode is FALSE, otherwise a new - node is inserted with suitLengths set to key, the pointer to - this node is returned. - The algorithm used is defined in Knuth "The art of computer - programming", vol.3 "Sorting and searching", 6.2.2 Algorithm T, - page 424. */ - - struct posSearchType *np, *p, *sp; - - if (insertNode) - sp=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; - - np=rootp; - while (1) { - if (key==np->suitLengths) { - *result=TRUE; - return np; - } - else if (key < np->suitLengths) { - if (np->left!=NULL) - np=np->left; - else if (insertNode) { - p=sp; - AddLenSet(thrId); - np->left=p; - p->posSearchPoint=NULL; - p->suitLengths=key; - p->left=NULL; p->right=NULL; - *result=TRUE; - return p; - } - else { - *result=FALSE; - return NULL; - } - } - else { /* key > suitLengths */ - if (np->right!=NULL) - np=np->right; - else if (insertNode) { - p=sp; - AddLenSet(thrId); - np->right=p; - p->posSearchPoint=NULL; - p->suitLengths=key; - p->left=NULL; p->right=NULL; - *result=TRUE; - return p; - } - else { - *result=FALSE; - return NULL; - } - } - } -} - - - -void BuildSOP(struct pos * posPoint, long long suitLengths, int tricks, int firstHand, int target, - int depth, int scoreFlag, int score, int thrId) { - int hh, res, wm; - unsigned short int w; - unsigned short int temp[4][4]; - unsigned short int aggr[4]; - struct nodeCardsType * cardsP; - struct posSearchType * np; - -#ifdef TTDEBUG - int k, mcurrent, rr; - mcurrent=localVar[thrId].movePly[depth].current; -#endif - - for (int ss=0; ss<=3; ss++) { - w=posPoint->winRanks[depth][ss]; - if (w==0) { - posPoint->winMask[ss]=0; - posPoint->winOrderSet[ss]=0; - posPoint->leastWin[ss]=0; - for (hh=0; hh<=3; hh++) - temp[hh][ss]=0; - } - else { - w=w & (-w); /* Only lowest win */ - for (hh=0; hh<=3; hh++) - temp[hh][ss]=posPoint->rankInSuit[hh][ss] & (-w); - - aggr[ss]=0; - for (hh=0; hh<=3; hh++) - aggr[ss]|=temp[hh][ss]; - posPoint->winMask[ss]=localVar[thrId].rel[aggr[ss]].winMask[ss]; - posPoint->winOrderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; - wm=posPoint->winMask[ss]; - wm=wm & (-wm); - posPoint->leastWin[ss]=InvWinMask(wm); - } - } - - /* 07-04-22 */ - if (scoreFlag) { - if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { - posPoint->ubound=tricks+1; - posPoint->lbound=target-posPoint->tricksMAX; - } - else { - posPoint->ubound=tricks+1-target+posPoint->tricksMAX; - posPoint->lbound=0; - } - } - else { - if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { - posPoint->ubound=target-posPoint->tricksMAX-1; - posPoint->lbound=0; - } - else { - posPoint->ubound=tricks+1; - posPoint->lbound=tricks+1-target+posPoint->tricksMAX+1; - } - } - - /*long long suitLengths=0; - for (int s=0; s<=2; s++) - for (hh=0; hh<=3; hh++) { - suitLengths<<=4; - suitLengths|=posPoint->length[hh][s]; - }*/ - - np=SearchLenAndInsert(localVar[thrId].rootnp[tricks][firstHand], - suitLengths, TRUE, &res, thrId); - - cardsP=BuildPath(posPoint, np, &res, thrId); - if (res) { - cardsP->ubound=posPoint->ubound; - cardsP->lbound=posPoint->lbound; - if (((localVar[thrId].nodeTypeStore[firstHand]==MAXNODE)&&(scoreFlag))|| - ((localVar[thrId].nodeTypeStore[firstHand]==MINNODE)&&(!scoreFlag))) { - cardsP->bestMoveSuit=localVar[thrId].bestMove[depth].suit; - cardsP->bestMoveRank=localVar[thrId].bestMove[depth].rank; - } - else { - cardsP->bestMoveSuit=0; - cardsP->bestMoveRank=0; - } - posPoint->bestMoveSuit=localVar[thrId].bestMove[depth].suit; - posPoint->bestMoveRank=localVar[thrId].bestMove[depth].rank; - for (int k=0; k<=3; k++) - cardsP->leastWin[k]=posPoint->leastWin[k]; - } - - #ifdef STAT - c9[depth]++; - #endif - - #ifdef TTDEBUG - if ((res) && (ttCollect) && (!suppressTTlog)) { - fprintf(localVar[thrId].fp7, "cardsP=%d\n", (int)cardsP); - fprintf(localVar[thrId].fp7, "nodeSetSize=%d\n", localVar[thrId].nodeSetSize); - fprintf(localVar[thrId].fp7, "ubound=%d\n", cardsP->ubound); - fprintf(localVar[thrId].fp7, "lbound=%d\n", cardsP->lbound); - fprintf(localVar[thrId].fp7, "target=%d\n", target); - fprintf(localVar[thrId].fp7, "first=%c nextFirst=%c\n", - cardHand[posPoint->first[depth]], cardHand[posPoint->first[depth-1]]); - fprintf(localVar[thrId].fp7, "bestMove: suit=%c rank=%c\n", cardSuit[localVar[thrId].bestMove[depth].suit], - cardRank[localVar[thrId].bestMove[depth].rank]); - fprintf(localVar[thrId].fp7, "\n"); - fprintf(localVar[thrId].fp7, "Last trick:\n"); - fprintf(localVar[thrId].fp7, "1st hand=%c\n", cardHand[posPoint->first[depth+3]]); - for (k=3; k>=0; k--) { - mcurrent=localVar[thrId].movePly[depth+k+1].current; - fprintf(localVar[thrId].fp7, "suit=%c rank=%c\n", - cardSuit[localVar[thrId].movePly[depth+k+1].move[mcurrent].suit], - cardRank[localVar[thrId].movePly[depth+k+1].move[mcurrent].rank]); - } - fprintf(localVar[thrId].fp7, "\n"); - for (hh=0; hh<=3; hh++) { - fprintf(localVar[thrId].fp7, "hand=%c\n", cardHand[hh]); - for (ss=0; ss<=3; ss++) { - fprintf(localVar[thrId].fp7, "suit=%c", cardSuit[ss]); - for (rr=14; rr>=2; rr--) - if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) - fprintf(localVar[thrId].fp7, " %c", cardRank[rr]); - fprintf(localVar[thrId].fp7, "\n"); - } - fprintf(localVar[thrId].fp7, "\n"); - } - fprintf(localVar[thrId].fp7, "\n"); - } - #endif -} - - -int CheckDeal(struct moveType * cardp, int thrId) { - int h, s, k, found; - unsigned short int temp[4][4]; - - for (h=0; h<=3; h++) - for (s=0; s<=3; s++) - temp[h][s]=localVar[thrId].game.suit[h][s]; - - /* Check that all ranks appear only once within the same suit. */ - for (s=0; s<=3; s++) - for (k=2; k<=14; k++) { - found=FALSE; - for (h=0; h<=3; h++) { - if ((temp[h][s] & bitMapRank[k])!=0) { - if (found) { - cardp->suit=s; - cardp->rank=k; - return 1; - } - else - found=TRUE; - } - } - } - - return 0; -} - - -int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId) { - /* Returns TRUE if at least one move remains to be - searched, otherwise FALSE is returned. */ - - unsigned short int lw; - int suit; - struct moveType currMove=mply->move[mply->current]; - - if (localVar[thrId].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] >= - localVar[thrId].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] >= - localVar[thrId].lowestWin[depth][suit])) - return TRUE; - } - return FALSE; - } - } - else { - while (mply->current<=(mply->last-1)) { - mply->current++; - if (bitMapRank[mply->move[mply->current].rank] >= - localVar[thrId].lowestWin[depth][mply->move[mply->current].suit]) - return TRUE; - } - return FALSE; - } -} - - -int DumpInput(int errCode, struct deal dl, int target, - int solutions, int mode) { - - FILE *fp; - int i, j, k; - unsigned short ranks[4][4]; - - fp=fopen("dump.txt", "w"); - if (fp==NULL) - return -1; - fprintf(fp, "Error code=%d\n", errCode); - fprintf(fp, "\n"); - fprintf(fp, "Deal data:\n"); - if (dl.trump!=4) - fprintf(fp, "trump=%c\n", cardSuit[dl.trump]); - else - fprintf(fp, "trump=N\n"); - fprintf(fp, "first=%c\n", cardHand[dl.first]); - for (k=0; k<=2; k++) - if (dl.currentTrickRank[k]!=0) - fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n", - k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]); - for (i=0; i<=3; i++) - for (j=0; j<=3; j++) { - fprintf(fp, "index1=%d index2=%d remainCards=%d\n", - i, j, dl.remainCards[i][j]); - ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2; - } - fprintf(fp, "\n"); - fprintf(fp, "target=%d\n", target); - fprintf(fp, "solutions=%d\n", solutions); - fprintf(fp, "mode=%d\n", mode); - fprintf(fp, "\n"); - PrintDeal(fp, ranks); - fclose(fp); - return 0; -} - -void PrintDeal(FILE *fp, unsigned short ranks[][4]) { - int i, count, ec[4], trickCount=0, s, r; - for (i=0; i<=3; i++) { - count=counttable[ranks[3][i]]; - if (count>5) - ec[i]=TRUE; - else - ec[i]=FALSE; - trickCount=trickCount+count; - } - fprintf(fp, "\n"); - for (s=0; s<=3; s++) { - fprintf(fp, "\t%c ", cardSuit[s]); - if (!ranks[0][s]) - fprintf(fp, "--"); - else { - for (r=14; r>=2; r--) - if ((ranks[0][s] & bitMapRank[r])!=0) - fprintf(fp, "%c", cardRank[r]); - } - fprintf(fp, "\n"); - } - for (s=0; s<=3; s++) { - fprintf(fp, "%c ", cardSuit[s]); - if (!ranks[3][s]) - fprintf(fp, "--"); - else { - for (r=14; r>=2; r--) - if ((ranks[3][s] & bitMapRank[r])!=0) - fprintf(fp, "%c", cardRank[r]); - } - if (ec[s]) - fprintf(fp, "\t\%c ", cardSuit[s]); - else - fprintf(fp, "\t\t\%c ", cardSuit[s]); - if (!ranks[1][s]) - fprintf(fp, "--"); - else { - for (r=14; r>=2; r--) - if ((ranks[1][s] & bitMapRank[r])!=0) - fprintf(fp, "%c", cardRank[r]); - } - fprintf(fp, "\n"); - } - for (s=0; s<=3; s++) { - fprintf(fp, "\t%c ", cardSuit[s]); - if (!ranks[2][s]) - fprintf(fp, "--"); - else { - for (r=14; r>=2; r--) - if ((ranks[2][s] & bitMapRank[r])!=0) - fprintf(fp, "%c", cardRank[r]); - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); - return; -} - - - -void Wipe(int thrId) { - int k; - - for (k=1; k<=localVar[thrId].wcount; k++) { - if (localVar[thrId].pw[k]) - free(localVar[thrId].pw[k]); - localVar[thrId].pw[k]=NULL; - } - for (k=1; k<=localVar[thrId].ncount; k++) { - if (localVar[thrId].pn[k]) - free(localVar[thrId].pn[k]); - localVar[thrId].pn[k]=NULL; - } - for (k=1; k<=localVar[thrId].lcount; k++) { - if (localVar[thrId].pl[k]) - free(localVar[thrId].pl[k]); - localVar[thrId].pl[k]=NULL; - } - - localVar[thrId].allocmem=localVar[thrId].summem; - - return; -} - - -void AddWinSet(int thrId) { - if (localVar[thrId].clearTTflag) { - localVar[thrId].windex++; - localVar[thrId].winSetSize=localVar[thrId].windex; - /*localVar[thrId].fp2=fopen("dyn.txt", "a"); - fprintf(localVar[thrId].fp2, "windex=%d\n", windex); - fclose(localVar[thrId].fp2);*/ - localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; - } - else if (localVar[thrId].winSetSize>=localVar[thrId].winSetSizeLimit) { - /* The memory chunk for the winCards structure will be exceeded. */ - if ((localVar[thrId].allocmem+localVar[thrId].wmem)>localVar[thrId].maxmem) { - /* Already allocated memory plus needed allocation overshot maxmem */ - localVar[thrId].windex++; - localVar[thrId].winSetSize=localVar[thrId].windex; - /*localVar[thrId].fp2=fopen("dyn.txt", "a"); - fprintf(localVar[thrId].fp2, "windex=%d\n", windex); - fclose(localVar[thrId].fp2);*/ - localVar[thrId].clearTTflag=TRUE; - localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; - } - else { - localVar[thrId].wcount++; localVar[thrId].winSetSizeLimit=WSIZE; - localVar[thrId].pw[localVar[thrId].wcount] = - (struct winCardType *)calloc(localVar[thrId].winSetSizeLimit+1, sizeof(struct winCardType)); - if (localVar[thrId].pw[localVar[thrId].wcount]==NULL) { - localVar[thrId].clearTTflag=TRUE; - localVar[thrId].windex++; - localVar[thrId].winSetSize=localVar[thrId].windex; - localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; - } - else { - localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); - localVar[thrId].winSetSize=0; - localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; - } - } - } - else - localVar[thrId].winSetSize++; - return; -} - -void AddNodeSet(int thrId) { - if (localVar[thrId].nodeSetSize>=localVar[thrId].nodeSetSizeLimit) { - /* The memory chunk for the nodeCards structure will be exceeded. */ - if ((localVar[thrId].allocmem+localVar[thrId].nmem)>localVar[thrId].maxmem) { - /* Already allocated memory plus needed allocation overshot maxmem */ - localVar[thrId].clearTTflag=TRUE; - } - else { - localVar[thrId].ncount++; localVar[thrId].nodeSetSizeLimit=NSIZE; - localVar[thrId].pn[localVar[thrId].ncount] = (struct nodeCardsType *)calloc(localVar[thrId].nodeSetSizeLimit+1, sizeof(struct nodeCardsType)); - if (localVar[thrId].pn[localVar[thrId].ncount]==NULL) { - localVar[thrId].clearTTflag=TRUE; - } - else { - localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); - localVar[thrId].nodeSetSize=0; - localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; - } - } - } - else - localVar[thrId].nodeSetSize++; - return; -} - -void AddLenSet(int thrId) { - if (localVar[thrId].lenSetSize>=localVar[thrId].lenSetSizeLimit) { - /* The memory chunk for the posSearchType structure will be exceeded. */ - if ((localVar[thrId].allocmem+localVar[thrId].lmem)>localVar[thrId].maxmem) { - /* Already allocated memory plus needed allocation overshot maxmem */ - localVar[thrId].clearTTflag=TRUE; - } - else { - localVar[thrId].lcount++; localVar[thrId].lenSetSizeLimit=LSIZE; - localVar[thrId].pl[localVar[thrId].lcount] = (struct posSearchType *)calloc(localVar[thrId].lenSetSizeLimit+1, sizeof(struct posSearchType)); - if (localVar[thrId].pl[localVar[thrId].lcount]==NULL) { - localVar[thrId].clearTTflag=TRUE; - } - else { - localVar[thrId].allocmem+=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); - localVar[thrId].lenSetSize=0; - localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; - } - } - } - else - localVar[thrId].lenSetSize++; - return; -} - - - -#ifdef TTDEBUG - -void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, - int target, int depth, int thrId) { - int tricksLeft, hh, ss, rr; -/* Stores current position information and TT position value in table - ttStore with current entry lastTTStore. Also stores corresponding - information in log rectt.txt. */ - tricksLeft=0; - for (hh=0; hh<=3; hh++) - for (ss=0; ss<=3; ss++) - tricksLeft+=posPoint->length[hh][ss]; - tricksLeft=tricksLeft/4; - ttStore[lastTTstore].tricksLeft=tricksLeft; - ttStore[lastTTstore].cardsP=cardsP; - ttStore[lastTTstore].first=posPoint->first[depth]; - if ((localVar[thrId].handToPlay==posPoint->first[depth])|| - (localVar[thrId].handToPlay==partner[posPoint->first[depth]])) { - ttStore[lastTTstore].target=target-posPoint->tricksMAX; - ttStore[lastTTstore].ubound=cardsP->ubound; - ttStore[lastTTstore].lbound=cardsP->lbound; - } - else { - ttStore[lastTTstore].target=tricksLeft- - target+posPoint->tricksMAX+1; - } - for (hh=0; hh<=3; hh++) - for (ss=0; ss<=3; ss++) - ttStore[lastTTstore].suit[hh][ss]= - posPoint->rankInSuit[hh][ss]; - localVar[thrId].fp11=fopen("rectt.txt", "a"); - if (lastTTstoretricksMAX); - fprintf(localVar[thrId].fp11, "leftTricks=%d\n", - ttStore[lastTTstore].tricksLeft); - fprintf(localVar[thrId].fp11, "cardsP=%d\n", - ttStore[lastTTstore].cardsP); - fprintf(localVar[thrId].fp11, "ubound=%d\n", - ttStore[lastTTstore].ubound); - fprintf(localVar[thrId].fp11, "lbound=%d\n", - ttStore[lastTTstore].lbound); - fprintf(localVar[thrId].fp11, "first=%c\n", - cardHand[ttStore[lastTTstore].first]); - fprintf(localVar[thrId].fp11, "target=%d\n", - ttStore[lastTTstore].target); - fprintf(localVar[thrId].fp11, "\n"); - for (hh=0; hh<=3; hh++) { - fprintf(localVar[thrId].fp11, "hand=%c\n", cardHand[hh]); - for (ss=0; ss<=3; ss++) { - fprintf(localVar[thrId].fp11, "suit=%c", cardSuit[ss]); - for (rr=14; rr>=2; rr--) - if (ttStore[lastTTstore].suit[hh][ss] - & bitMapRank[rr]) - fprintf(localVar[thrId].fp11, " %c", cardRank[rr]); - fprintf(localVar[thrId].fp11, "\n"); - } - fprintf(localVar[thrId].fp11, "\n"); - } - } - fclose(localVar[thrId].fp11); - lastTTstore++; -} -#endif - -#if defined(_WIN32) -HANDLE solveAllEvents[MAXNOOFTHREADS]; -struct paramType param; -LONG volatile threadIndex; -LONG volatile current; - -long chunk = 4; - -DWORD CALLBACK SolveChunkDDtable (void *) { - struct futureTricks fut[MAXNOOFBOARDS]; - int thid; - long j; - - thid=InterlockedIncrement(&threadIndex); - - while ((j=InterlockedExchangeAdd(¤t, chunk))deals[j+k], param.bop->target[j+k], - param.bop->solutions[j+k], param.bop->mode[j+k], - &fut[j+k], thid); - if (res==1) { - param.solvedp->solvedBoard[j+k]=fut[j+k]; - param.error=0; - } - else { - param.error=res; - } - } - } - - if (SetEvent(solveAllEvents[thid])==0) { - /*int errCode=GetLastError();*/ - return 0; - } - - return 1; - -} - -int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { - int k/*, errCode*/; - DWORD res; - DWORD solveAllWaitResult; - - current=0; - - threadIndex=-1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -101; - - for (k=0; knoOfBoards; - - for (k=0; ksolvedBoard[k].cards=0; - - for (k=0; knoOfBoards=0; - for (k=0; ksolvedBoard[k].cards!=0) - solvedp->noOfBoards++; - } - - if (param.error==0) - return 1; - else - return param.error; -} - -int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize) { - int k/*, errCode*/; - DWORD res; - DWORD solveAllWaitResult; - - current = 0; - threadIndex = -1; - chunk = chunkSize; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -101; - - for (k = 0; knoOfBoards; - - for (k = 0; ksolvedBoard[k].cards = 0; - - for (k = 0; knoOfBoards = 0; - for (k = 0; ksolvedBoard[k].cards != 0) - solvedp->noOfBoards++; - } - - if (param.error == 0) - return 1; - else - return param.error; -} - - -DWORD CALLBACK SolveChunk (void *) { - struct futureTricks fut[MAXNOOFBOARDS]; - int thid; - long j; - - thid=InterlockedIncrement(&threadIndex); - - while ((j=(InterlockedIncrement(¤t)-1))deals[j], param.bop->target[j], - param.bop->solutions[j], param.bop->mode[j], &fut[j], thid); - if (res==1) { - param.solvedp->solvedBoard[j]=fut[j]; - param.error=0; - } - else { - param.error=res; - } - } - - if (SetEvent(solveAllEvents[thid])==0) { - /*int errCode=GetLastError();*/ - return 0; - } - - return 1; - -} - - - -int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { - int k/*, errCode*/; - DWORD res; - DWORD solveAllWaitResult; - - current=0; - - threadIndex=-1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -201; - - for (k=0; knoOfBoards; - - for (k=0; ksolvedBoard[k].cards=0; - - for (k=0; knoOfBoards=0; - for (k=0; ksolvedBoard[k].cards!=0) - solvedp->noOfBoards++; - } - - if (param.error==0) - return 1; - else - return param.error; -} - - -#else -int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { - int k, i, res, chunk, fail; - struct futureTricks fut[MAXNOOFBOARDS]; - - chunk=4; fail=1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -101; - - for (i=0; isolvedBoard[i].cards=0; - -#ifdef _OPENMP - omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ -#endif - - #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) - { - - #pragma omp for schedule(dynamic, chunk) - - for (k=0; knoOfBoards; k++) { - res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], - bop->mode[k], &fut[k], -#ifdef _OPENMP - omp_get_thread_num() -#else - 0 -#endif - ); - if (res==1) { - solvedp->solvedBoard[k]=fut[k]; - } - else - fail=res; - } - } - - if (fail!=1) - return fail; - - solvedp->noOfBoards=0; - for (i=0; isolvedBoard[i].cards!=0) - solvedp->noOfBoards++; - } - - return 1; -} - - -int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize) { - int k, i, res, chunk, fail; - struct futureTricks fut[MAXNOOFBOARDS]; - - chunk=chunkSize; fail=1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -101; - - for (i=0; isolvedBoard[i].cards=0; - -#ifdef _OPENMP - omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ -#endif - - #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) - { - - #pragma omp for schedule(dynamic, chunk) - - for (k=0; knoOfBoards; k++) { - res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], - bop->mode[k], &fut[k], -#ifdef _OPENMP - omp_get_thread_num() -#else - 0 -#endif - ); - if (res==1) { - solvedp->solvedBoard[k]=fut[k]; - } - else - fail=res; - } - } - - if (fail!=1) - return fail; - - solvedp->noOfBoards=0; - for (i=0; isolvedBoard[i].cards!=0) - solvedp->noOfBoards++; - } - - return 1; -} - - - -int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { - int k, i, res, chunk, fail; - struct futureTricks fut[MAXNOOFBOARDS]; - - chunk=1; fail=1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return -101; - - for (i=0; isolvedBoard[i].cards=0; - -#ifdef _OPENMP - omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ -#endif - - #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) - { - - #pragma omp for schedule(dynamic, chunk) - - for (k=0; knoOfBoards; k++) { - res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], - bop->mode[k], &fut[k], -#ifdef _OPENMP - omp_get_thread_num() -#else - 0 -#endif - ); - if (res==1) { - solvedp->solvedBoard[k]=fut[k]; - } - else - fail=res; - } - } - - if (fail!=1) - return fail; - - solvedp->noOfBoards=0; - for (i=0; isolvedBoard[i].cards!=0) - solvedp->noOfBoards++; - } - - return 1; -} -#endif - - -int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep) { - - int h, s, k, ind, tr, first, res; - struct deal dl; - struct boards bo; - struct solvedBoards solved; - - for (h=0; h<=3; h++) - for (s=0; s<=3; s++) - dl.remainCards[h][s]=tableDeal.cards[h][s]; - - for (k=0; k<=2; k++) { - dl.currentTrickRank[k]=0; - dl.currentTrickSuit[k]=0; - } - - ind=0; bo.noOfBoards=20; - - for (tr=4; tr>=0; tr--) - for (first=0; first<=3; first++) { - dl.first=first; - dl.trump=tr; - bo.deals[ind]=dl; - bo.target[ind]=-1; - bo.solutions[ind]=1; - bo.mode[ind]=1; - ind++; - } - - res=SolveAllBoards4(&bo, &solved); - if (res==1) { - for (ind=0; ind<20; ind++) { - tablep->resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= - 13-solved.solvedBoard[ind].score[0]; - } - return 1; - } - - return res; -} - -#ifdef PBN_PLUS -int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, int trumpFilter[5], - struct ddTablesRes *resp, - struct allParResults *presp) { - /* mode = 0: par calculation, vulnerability None - mode = 1: par calculation, vulnerability All - mode = 2: par calculation, vulnerability NS - mode = 3: par calculation, vulnerability EW - mode = -1: no par calculation */ - - int h, s, k, m, ind, tr, first, res, rs, lastIndex=0, - lastBoardIndex[MAXNOOFBOARDS>>2], okey=FALSE, count=0; - struct boards bo; - struct solvedBoards solved; - - int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable); - - for (k=0; k<5; k++) { - if (!trumpFilter[k]) { - okey=TRUE; - count++; - } - } - - if (!okey) - return -201; - - switch (count) { - case 1: if (dealsp->noOfTables > 50) return 202; break; - case 2: if (dealsp->noOfTables > 25) return 202; break; - case 3: if (dealsp->noOfTables > 16) return 202; break; - case 4: if (dealsp->noOfTables > 12) return 202; break; - case 5: if (dealsp->noOfTables > 10) return 202; break; - } - - ind=0; - resp->noOfBoards=0; - - for (m=0; mnoOfTables; m++) { - for (tr=4; tr>=0; tr--) { - if (!trumpFilter[tr]) { - for (first=0; first<=3; first++) { - for (h=0; h<=3; h++) - for (s=0; s<=3; s++) - bo.deals[ind].remainCards[h][s]=dealsp->deals[m].cards[h][s]; - bo.deals[ind].first=first; - bo.deals[ind].trump=tr; - for (k=0; k<=2; k++) { - bo.deals[ind].currentTrickRank[k]=0; - bo.deals[ind].currentTrickSuit[k]=0; - } - - bo.target[ind]=-1; - bo.solutions[ind]=1; - bo.mode[ind]=1; - lastIndex=ind; - lastBoardIndex[m]=ind; - ind++; - } - } - } - } - - bo.noOfBoards=lastIndex+1; - - res=SolveAllBoards4(&bo, &solved); - if (res==1) { - resp->noOfBoards+=solved.noOfBoards; - for (ind=0; ind<=lastIndex; ind++) { - for (k=0; k<=lastIndex; k++) { - if (ind<=lastBoardIndex[k]) { - resp->results[k].resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= - 13-solved.solvedBoard[ind].score[0]; - break; - } - } - } - - if ((mode > -1) && (mode < 4)) { - /* Calculate par */ - for (k=0; knoOfTables; k++) { - rs=Par(&(resp->results[k]), &(presp->presults[k]), mode); - /* vulnerable 0: None 1: Both 2: NS 3: EW */ - if (rs!=1) - return rs; - } - } - return 1; - } - return res; -} - -int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, int trumpFilter[5], - struct ddTablesRes *resp, struct allParResults *presp) { - int res, k; - struct ddTableDeals dls; - - int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); - - for (k=0; knoOfTables; k++) - if (ConvertFromPBN(dealsp->deals[k].cards, dls.deals[k].cards)!=1) - return -99; - - dls.noOfTables=dealsp->noOfTables; - - res=CalcAllTables(&dls, mode, trumpFilter, resp, presp); - - return res; -} -#endif - - -int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]) { - int bp=0, first, card, hand, handRelFirst, suitInHand, h, s; - int IsCard(char cardChar); - - for (h=0; h<=3; h++) - for (s=0; s<=3; s++) - remainCards[h][s]=0; - - while (((dealBuff[bp]!='W')&&(dealBuff[bp]!='N')&& - (dealBuff[bp]!='E')&&(dealBuff[bp]!='S')&& - (dealBuff[bp]!='w')&&(dealBuff[bp]!='n')&& - (dealBuff[bp]!='e')&&(dealBuff[bp]!='s'))&&(bp<3)) - bp++; - - if (bp>=3) - return 0; - - if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n')) - first=0; - else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e')) - first=1; - else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s')) - first=2; - else - first=3; - - bp++; - bp++; - - handRelFirst=0; suitInHand=0; - - while ((bp<80)&&(dealBuff[bp]!='\0')) { - card=IsCard(dealBuff[bp]); - if (card) { - switch (first) { - case 0: - hand=handRelFirst; - break; - case 1: - if (handRelFirst==0) - hand=1; - else if (handRelFirst==3) - hand=0; - else - hand=handRelFirst+1; - break; - case 2: - if (handRelFirst==0) - hand=2; - else if (handRelFirst==1) - hand=3; - else - hand=handRelFirst-2; - break; - default: - if (handRelFirst==0) - hand=3; - else - hand=handRelFirst-1; - } - - remainCards[hand][suitInHand]|=(bitMapRank[card]<<2); - - } - else if (dealBuff[bp]=='.') - suitInHand++; - else if (dealBuff[bp]==' ') { - handRelFirst++; - suitInHand=0; - } - bp++; - } - return 1; -} - - -int IsCard(char cardChar) { - switch (cardChar) { - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - case 'T': - return 10; - case 'J': - return 11; - case 'Q': - return 12; - case 'K': - return 13; - case 'A': - return 14; - case 't': - return 10; - case 'j': - return 11; - case 'q': - return 12; - case 'k': - return 13; - case 'a': - return 14; - default: - return 0; - } - } - -#ifdef PBN -int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, - int solutions, int mode, struct futureTricks *futp, int thrId) { - - int res, k; - struct deal dl; - int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); - - if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1) - return -99; - - for (k=0; k<=2; k++) { - dl.currentTrickRank[k]=dlpbn.currentTrickRank[k]; - dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k]; - } - dl.first=dlpbn.first; - dl.trump=dlpbn.trump; - - res=SolveBoard(dl, target, solutions, mode, futp, thrId); - - return res; -} - -int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) { - struct ddTableDeal tableDeal; - int res; - - if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) - return -99; - - res=CalcDDtable(tableDeal, tablep); - - return res; -} -#endif - -#ifdef PBN_PLUS -int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp) { - struct boards bo; - int k, i, res; - - bo.noOfBoards=bop->noOfBoards; - for (k=0; knoOfBoards; k++) { - bo.mode[k]=bop->mode[k]; - bo.solutions[k]=bop->solutions[k]; - bo.target[k]=bop->target[k]; - bo.deals[k].first=bop->deals[k].first; - bo.deals[k].trump=bop->deals[k].trump; - for (i=0; i<=2; i++) { - bo.deals[k].currentTrickSuit[i]=bop->deals[k].currentTrickSuit[i]; - bo.deals[k].currentTrickRank[i]=bop->deals[k].currentTrickRank[i]; - } - if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards)!=1) - return -99; - } - - res=SolveAllBoards1(&bo, solvedp); - - return res; -} - -int STDCALL SolveAllChunks(struct boardsPBN *bop, struct solvedBoards *solvedp, int chunkSize) { - struct boards bo; - int k, i, res; - - if (chunkSize < 1) - return -201; - - bo.noOfBoards = bop->noOfBoards; - for (k = 0; knoOfBoards; k++) { - bo.mode[k] = bop->mode[k]; - bo.solutions[k] = bop->solutions[k]; - bo.target[k] = bop->target[k]; - bo.deals[k].first = bop->deals[k].first; - bo.deals[k].trump = bop->deals[k].trump; - for (i = 0; i <= 2; i++) { - bo.deals[k].currentTrickSuit[i] = bop->deals[k].currentTrickSuit[i]; - bo.deals[k].currentTrickRank[i] = bop->deals[k].currentTrickRank[i]; - } - if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards) != 1) - return -99; - } - - res = SolveAllBoardsN(&bo, solvedp, chunkSize); - return res; -} -#endif - -#ifdef PBN_PLUS -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; -} - - - - + +/* DDS 2.5.2 A bridge double dummy solver. */ +/* Copyright (C) 2006-2014 by Bo Haglund */ +/* Cleanups and porting to Linux and MacOSX (C) 2006 by Alex Martelli. */ +/* The code for calculation of par score / contracts is based upon the */ +/* perl code written by Matthew Kidd for ACBLmerge. He has kindly given me */ +/* permission to include a C++ adaptation in DDS. */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ + + +/*#include "stdafx.h"*/ /* Needed by Visual C++ */ + +#include "dll.h" + +struct localVarType localVar[MAXNOOFTHREADS]; + +int * counttable; +int * highestRank; +int lho[4]; +int rho[4]; +int partner[4]; +unsigned short int bitMapRank[16]; +unsigned char cardRank[15]; +unsigned char cardSuit[5]; +unsigned char cardHand[4]; +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 */ + +struct ttStoreType * ttStore; +int lastTTstore; +int ttCollect; +int suppressTTlog; + +int noOfThreads=MAXNOOFTHREADS; /* The number of entries to the transposition tables. There is + one entry per thread. */ +int noOfCores; /* The number of processor cores, however cannot be higher than noOfThreads. */ + +#ifdef _MANAGED +#pragma managed(push, off) +#endif + + +#if defined(_WIN32) +extern "C" BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved) { + int k; + + if (ul_reason_for_call==DLL_PROCESS_ATTACH) { + InitStart(0, 0); + } + else if (ul_reason_for_call==DLL_PROCESS_DETACH) { + for (k=0; k=noOfThreads)) { /* Fault corrected after suggestion by Dirk Willecke. */ + DumpInput(-15, dl, target, solutions, mode); + return -15; + } + + for (k=0; k<=13; k++) { + localVar[thrId].forbiddenMoves[k].rank=0; + localVar[thrId].forbiddenMoves[k].suit=0; + } + + if (target<-1) { + DumpInput(-5, dl, target, solutions, mode); + return -5; + } + if (target>13) { + DumpInput(-7, dl, target, solutions, mode); + return -7; + } + if (solutions<1) { + DumpInput(-8, dl, target, solutions, mode); + return -8; + } + if (solutions>3) { + DumpInput(-9, dl, target, solutions, mode); + return -9; + } + + for (k=0; k<=3; k++) + noOfCardsPerHand[handId(dl.first, k)]=0; + + + for (k=0; k<=2; k++) { + if (dl.currentTrickRank[k]!=0) { + noOfCardsPerHand[handId(dl.first, k)]=1; + aggrRemain=0; + for (h=0; h<=3; h++) + aggrRemain|=(dl.remainCards[h][dl.currentTrickSuit[k]]>>2); + if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]])!=0) { + DumpInput(-13, dl, target, solutions, mode); + return -13; + } + } + } + + if (target==-1) + localVar[thrId].tricksTarget=99; + else + localVar[thrId].tricksTarget=target; + + localVar[thrId].newDeal=FALSE; localVar[thrId].newTrump=FALSE; + localVar[thrId].diffDeal=0; localVar[thrId].aggDeal=0; + cardCount=0; + for (i=0; i<=3; i++) { + for (j=0; j<=3; j++) { + cardCount+=counttable[dl.remainCards[i][j]>>2]; + localVar[thrId].diffDeal+=((dl.remainCards[i][j]>>2)^ + (localVar[thrId].game.suit[i][j])); + localVar[thrId].aggDeal+=(dl.remainCards[i][j]>>2); + if (localVar[thrId].game.suit[i][j]!=dl.remainCards[i][j]>>2) { + localVar[thrId].game.suit[i][j]=dl.remainCards[i][j]>>2; + localVar[thrId].newDeal=TRUE; + } + } + } + + if (localVar[thrId].newDeal) { + if (localVar[thrId].diffDeal==0) + localVar[thrId].similarDeal=TRUE; + else if ((localVar[thrId].aggDeal/localVar[thrId].diffDeal) + > SIMILARDEALLIMIT) + localVar[thrId].similarDeal=TRUE; + else + localVar[thrId].similarDeal=FALSE; + } + else + localVar[thrId].similarDeal=FALSE; + + if (dl.trump!=localVar[thrId].trump) + localVar[thrId].newTrump=TRUE; + + for (i=0; i<=3; i++) + for (j=0; j<=3; j++) + noOfCardsPerHand[i]+=counttable[localVar[thrId].game.suit[i][j]]; + + for (i=1; i<=3; i++) { + if (noOfCardsPerHand[i]!=noOfCardsPerHand[0]) { + DumpInput(-14, dl, target, solutions, mode); + return -14; + } + } + + if (dl.currentTrickRank[2]) { + if ((dl.currentTrickRank[2]<2)||(dl.currentTrickRank[2]>14) + ||(dl.currentTrickSuit[2]<0)||(dl.currentTrickSuit[2]>3)) { + DumpInput(-12, dl, target, solutions, mode); + return -12; + } + localVar[thrId].handToPlay=handId(dl.first, 3); + handRelFirst=3; + noStartMoves=3; + if (cardCount<=4) { + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { + latestTrickSuit[localVar[thrId].handToPlay]=k; + latestTrickRank[localVar[thrId].handToPlay]= + InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); + break; + } + } + latestTrickSuit[handId(dl.first, 2)]=dl.currentTrickSuit[2]; + latestTrickRank[handId(dl.first, 2)]=dl.currentTrickRank[2]; + latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; + latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; + latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; + latestTrickRank[dl.first]=dl.currentTrickRank[0]; + } + } + else if (dl.currentTrickRank[1]) { + if ((dl.currentTrickRank[1]<2)||(dl.currentTrickRank[1]>14) + ||(dl.currentTrickSuit[1]<0)||(dl.currentTrickSuit[1]>3)) { + DumpInput(-12, dl, target, solutions, mode); + return -12; + } + localVar[thrId].handToPlay=handId(dl.first, 2); + handRelFirst=2; + noStartMoves=2; + if (cardCount<=4) { + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { + latestTrickSuit[localVar[thrId].handToPlay]=k; + latestTrickRank[localVar[thrId].handToPlay]= + InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { + latestTrickSuit[handId(dl.first, 3)]=k; + latestTrickRank[handId(dl.first, 3)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); + break; + } + } + latestTrickSuit[handId(dl.first, 1)]=dl.currentTrickSuit[1]; + latestTrickRank[handId(dl.first, 1)]=dl.currentTrickRank[1]; + latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; + latestTrickRank[dl.first]=dl.currentTrickRank[0]; + } + } + else if (dl.currentTrickRank[0]) { + if ((dl.currentTrickRank[0]<2)||(dl.currentTrickRank[0]>14) + ||(dl.currentTrickSuit[0]<0)||(dl.currentTrickSuit[0]>3)) { + DumpInput(-12, dl, target, solutions, mode); + return -12; + } + localVar[thrId].handToPlay=handId(dl.first,1); + handRelFirst=1; + noStartMoves=1; + if (cardCount<=4) { + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { + latestTrickSuit[localVar[thrId].handToPlay]=k; + latestTrickRank[localVar[thrId].handToPlay]= + InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { + latestTrickSuit[handId(dl.first, 3)]=k; + latestTrickRank[handId(dl.first, 3)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { + latestTrickSuit[handId(dl.first, 2)]=k; + latestTrickRank[handId(dl.first, 2)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); + break; + } + } + latestTrickSuit[dl.first]=dl.currentTrickSuit[0]; + latestTrickRank[dl.first]=dl.currentTrickRank[0]; + } + } + else { + localVar[thrId].handToPlay=dl.first; + handRelFirst=0; + noStartMoves=0; + if (cardCount<=4) { + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[localVar[thrId].handToPlay][k]!=0) { + latestTrickSuit[localVar[thrId].handToPlay]=k; + latestTrickRank[localVar[thrId].handToPlay]= + InvBitMapRank(localVar[thrId].game.suit[localVar[thrId].handToPlay][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 3)][k]!=0) { + latestTrickSuit[handId(dl.first, 3)]=k; + latestTrickRank[handId(dl.first, 3)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 3)][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 2)][k]!=0) { + latestTrickSuit[handId(dl.first, 2)]=k; + latestTrickRank[handId(dl.first, 2)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 2)][k]); + break; + } + } + for (k=0; k<=3; k++) { + if (localVar[thrId].game.suit[handId(dl.first, 1)][k]!=0) { + latestTrickSuit[handId(dl.first, 1)]=k; + latestTrickRank[handId(dl.first, 1)]= + InvBitMapRank(localVar[thrId].game.suit[handId(dl.first, 1)][k]); + break; + } + } + } + } + + localVar[thrId].trump=dl.trump; + localVar[thrId].game.first=dl.first; + first=dl.first; + localVar[thrId].game.noOfCards=cardCount; + if (dl.currentTrickRank[0]!=0) { + localVar[thrId].game.leadHand=dl.first; + localVar[thrId].game.leadSuit=dl.currentTrickSuit[0]; + localVar[thrId].game.leadRank=dl.currentTrickRank[0]; + } + else { + localVar[thrId].game.leadHand=0; + localVar[thrId].game.leadSuit=0; + localVar[thrId].game.leadRank=0; + } + + for (k=0; k<=2; k++) { + localVar[thrId].initialMoves[k].suit=255; + localVar[thrId].initialMoves[k].rank=255; + } + + for (k=0; k>2)+2; + else + totalTricks=((cardCount-4)>>2)+1; + checkRes=CheckDeal(&localVar[thrId].cd, thrId); + if (localVar[thrId].game.noOfCards<=0) { + DumpInput(-2, dl, target, solutions, mode); + return -2; + } + if (localVar[thrId].game.noOfCards>52) { + DumpInput(-10, dl, target, solutions, mode); + return -10; + } + if (totalTricksmaxRank)) { + maxRank=latestTrickRank[k]; + maxSuit=dl.trump; + maxHand=k; + } + } + } + /* Highest card in leading suit */ + if (maxRank==0) { + for (k=0; k<=3; k++) { + if (k==dl.first) { + maxSuit=latestTrickSuit[dl.first]; + maxHand=dl.first; + maxRank=latestTrickRank[dl.first]; + break; + } + } + for (k=0; k<=3; k++) { + if ((k!=dl.first)&&(latestTrickSuit[k]==maxSuit)&& + (latestTrickRank[k]>maxRank)) { + maxHand=k; + maxRank=latestTrickRank[k]; + } + } + } + futp->nodes=0; + #ifdef BENCH + futp->totalNodes=0; + #endif + futp->cards=1; + futp->suit[0]=latestTrickSuit[localVar[thrId].handToPlay]; + futp->rank[0]=latestTrickRank[localVar[thrId].handToPlay]; + futp->equals[0]=0; + if ((target==0)&&(solutions<3)) + futp->score[0]=0; + else if ((localVar[thrId].handToPlay==maxHand)|| + (partner[localVar[thrId].handToPlay]==maxHand)) + futp->score[0]=1; + else + futp->score[0]=0; + + /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ + return 1; + } + + if ((mode!=2)&& + (((localVar[thrId].newDeal)&&(!localVar[thrId].similarDeal)) + || localVar[thrId].newTrump || + (localVar[thrId].winSetSize > SIMILARMAXWINNODES))) { + + Wipe(thrId); + localVar[thrId].winSetSizeLimit=WINIT; + localVar[thrId].nodeSetSizeLimit=NINIT; + localVar[thrId].lenSetSizeLimit=LINIT; + localVar[thrId].allocmem=(WINIT+1)*sizeof(struct winCardType); + localVar[thrId].allocmem+=(NINIT+1)*sizeof(struct nodeCardsType); + localVar[thrId].allocmem+=(LINIT+1)*sizeof(struct posSearchType); + localVar[thrId].winCards=localVar[thrId].pw[0]; + localVar[thrId].nodeCards=localVar[thrId].pn[0]; + localVar[thrId].posSearch=localVar[thrId].pl[0]; + localVar[thrId].wcount=0; localVar[thrId].ncount=0; localVar[thrId].lcount=0; + InitGame(0, FALSE, first, handRelFirst, thrId); + } + else { + InitGame(0, TRUE, first, handRelFirst, thrId); + /*localVar[thrId].fp2=fopen("dyn.txt", "a"); + fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", + wcount, ncount, lcount); + fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", + winSetSize, nodeSetSize, lenSetSize); + fclose(localVar[thrId].fp2);*/ + } + + #ifdef STAT + localVar[thrId].nodes=0; + #endif + localVar[thrId].trickNodes=0; + localVar[thrId].iniDepth=cardCount-4; + hiwinSetSize=0; + hinodeSetSize=0; + + if (mode==0) { + MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, + &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); + if (localVar[thrId].movePly[localVar[thrId].iniDepth].last==0) { + futp->nodes=0; + #ifdef BENCH + futp->totalNodes=0; + #endif + futp->cards=1; + futp->suit[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].suit; + futp->rank[0]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].rank; + futp->equals[0]= + localVar[thrId].movePly[localVar[thrId].iniDepth].move[0].sequence<<2; + futp->score[0]=-2; + + /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ + return 1; + } + } + if ((target==0)&&(solutions<3)) { + MoveGen(&localVar[thrId].lookAheadPos, localVar[thrId].iniDepth, localVar[thrId].trump, + &localVar[thrId].movePly[localVar[thrId].iniDepth], thrId); + futp->nodes=0; + #ifdef BENCH + futp->totalNodes=0; + #endif + for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) { + futp->suit[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit; + futp->rank[k]=localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank; + futp->equals[k]= + localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].sequence<<2; + futp->score[k]=0; + } + if (solutions==1) + futp->cards=1; + else + futp->cards=localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; + + /*_CrtDumpMemoryLeaks(); */ /* MEMORY LEAK? */ + return 1; + } + + if ((target!=-1)&&(solutions!=3)) { + localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, + localVar[thrId].tricksTarget, localVar[thrId].iniDepth, thrId); + + temp=localVar[thrId].movePly[localVar[thrId].iniDepth]; + last=localVar[thrId].movePly[localVar[thrId].iniDepth].last; + noMoves=last+1; + hiwinSetSize=localVar[thrId].winSetSize; + hinodeSetSize=localVar[thrId].nodeSetSize; + hilenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].val==1) + localVar[thrId].payOff=localVar[thrId].tricksTarget; + else + localVar[thrId].payOff=0; + futp->cards=1; + ind=2; + + if (localVar[thrId].payOff<=0) { + futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; + futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; + futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; + if (localVar[thrId].tricksTarget>1) + futp->score[0]=-1; + else + futp->score[0]=0; + } + else { + futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; + futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; + futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + futp->score[0]=localVar[thrId].payOff; + } + } + else { + g=localVar[thrId].estTricks[localVar[thrId].handToPlay]; + upperbound=13; + lowerbound=0; + do { + if (g==lowerbound) + tricks=g+1; + else + tricks=g; + assert((localVar[thrId].lookAheadPos.handRelFirst>=0)&& + (localVar[thrId].lookAheadPos.handRelFirst<=3)); + localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, + localVar[thrId].iniDepth, thrId); + + if (localVar[thrId].val==TRUE) + mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; + hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); + hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); + hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].val==FALSE) { + upperbound=tricks-1; + g=upperbound; + } + else { + lowerbound=tricks; + g=lowerbound; + } + InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, + localVar[thrId].initialMoves, first, TRUE, thrId); + } + while (lowerboundcards=1; + if (localVar[thrId].payOff<=0) { + futp->score[0]=0; + futp->suit[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].suit; + futp->rank[0]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].rank; + futp->equals[0]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[0].sequence)<<2; + } + else { + futp->score[0]=localVar[thrId].payOff; + futp->suit[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; + futp->rank[0]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; + futp->equals[0]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + } + localVar[thrId].tricksTarget=localVar[thrId].payOff; + } + + if ((solutions==2)&&(localVar[thrId].payOff>0)) { + forb=1; + ind=forb; + while ((localVar[thrId].payOff==localVar[thrId].tricksTarget)&&(ind<(temp.last+1))) { + localVar[thrId].forbiddenMoves[forb].suit=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; + localVar[thrId].forbiddenMoves[forb].rank=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; + forb++; ind++; + /* All moves before bestMove in the move list shall be + moved to the forbidden moves list, since none of them reached + the target */ + /*mcurr=localVar[thrId].movePly[localVar[thrId].iniDepth].current;*/ + for (k=0; k<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; k++) + if ((localVar[thrId].bestMove[localVar[thrId].iniDepth].suit== + localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].suit) + &&(localVar[thrId].bestMove[localVar[thrId].iniDepth].rank== + localVar[thrId].movePly[localVar[thrId].iniDepth].move[k].rank)) + break; + for (i=0; iMaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].val==TRUE) { + localVar[thrId].payOff=localVar[thrId].tricksTarget; + futp->cards=ind; + futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; + futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; + futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + futp->score[ind-1]=localVar[thrId].payOff; + } + else + localVar[thrId].payOff=0; + } + } + else if ((solutions==2)&&(localVar[thrId].payOff==0)&& + ((target==-1)||(localVar[thrId].tricksTarget==1))) { + futp->cards=noMoves; + /* Find the cards that were in the initial move list + but have not been listed in the current result */ + n=0; + for (i=0; isuit[0])&& + (temp.move[i].rank==futp->rank[0])) { + found=TRUE; + } + if (!found) { + futp->suit[1+n]=temp.move[i].suit; + futp->rank[1+n]=temp.move[i].rank; + futp->equals[1+n]=(temp.move[i].sequence)<<2; + futp->score[1+n]=0; + n++; + } + } + } + + if ((solutions==3)&&(localVar[thrId].payOff>0)) { + forb=1; + ind=forb; + for (i=0; i=0)&& + (localVar[thrId].lookAheadPos.handRelFirst<=3)); + localVar[thrId].val=ABsearch(&localVar[thrId].lookAheadPos, tricks, + localVar[thrId].iniDepth, thrId); + + if (localVar[thrId].val==TRUE) + mv=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]; + hiwinSetSize=Max(hiwinSetSize, localVar[thrId].winSetSize); + hinodeSetSize=Max(hinodeSetSize, localVar[thrId].nodeSetSize); + hilenSetSize=Max(hilenSetSize, localVar[thrId].lenSetSize); + if (localVar[thrId].nodeSetSize>MaxnodeSetSize) + MaxnodeSetSize=localVar[thrId].nodeSetSize; + if (localVar[thrId].winSetSize>MaxwinSetSize) + MaxwinSetSize=localVar[thrId].winSetSize; + if (localVar[thrId].lenSetSize>MaxlenSetSize) + MaxlenSetSize=localVar[thrId].lenSetSize; + if (localVar[thrId].val==FALSE) { + upperbound=tricks-1; + g=upperbound; + } + else { + lowerbound=tricks; + g=lowerbound; + } + + InitSearch(&localVar[thrId].iniPosition, localVar[thrId].game.noOfCards-4, + localVar[thrId].initialMoves, first, TRUE, thrId); + } + while (lowerboundcards=temp.last+1; + for (j=0; j<=last; j++) { + futp->suit[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].suit; + futp->rank[ind-1+j]=localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].rank; + futp->equals[ind-1+j]=(localVar[thrId].movePly[localVar[thrId].game.noOfCards-4].move[j].sequence)<<2; + futp->score[ind-1+j]=localVar[thrId].payOff; + } + break; + } + else { + localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4]=mv; + + futp->cards=ind; + futp->suit[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].suit; + futp->rank[ind-1]=localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].rank; + futp->equals[ind-1]=(localVar[thrId].bestMove[localVar[thrId].game.noOfCards-4].sequence)<<2; + futp->score[ind-1]=localVar[thrId].payOff; + } + } + } + else if ((solutions==3)&&(localVar[thrId].payOff==0)) { + futp->cards=noMoves; + /* Find the cards that were in the initial move list + but have not been listed in the current result */ + n=0; + for (i=0; isuit[0])&& + (temp.move[i].rank==futp->rank[0])) { + found=TRUE; + } + if (!found) { + futp->suit[1+n]=temp.move[i].suit; + futp->rank[1+n]=temp.move[i].rank; + futp->equals[1+n]=(temp.move[i].sequence)<<2; + futp->score[1+n]=0; + n++; + } + } + } + + for (k=0; k<=13; k++) { + localVar[thrId].forbiddenMoves[k].suit=0; + localVar[thrId].forbiddenMoves[k].rank=0; + } + + futp->nodes=localVar[thrId].trickNodes; + #ifdef BENCH + futp->totalNodes=localVar[thrId].nodes; + #endif + /*if ((wcount>0)||(ncount>0)||(lcount>0)) { + localVar[thrId].fp2=fopen("dyn.txt", "a"); + fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", + wcount, ncount, lcount); + fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", + winSetSize, nodeSetSize, lenSetSize); + fprintf(localVar[thrId].fp2, "\n"); + fclose(localVar[thrId].fp2); + }*/ + + /*_CrtDumpMemoryLeaks();*/ /* MEMORY LEAK? */ + return 1; +} + + +int _initialized=0; + +void InitStart(int gb_ram, int ncores) { + int k, r, i, j, m; + unsigned short int res; + unsigned long long pcmem; /* kbytes */ + + if (_initialized) + return; + _initialized = 1; + + ttCollect=FALSE; + suppressTTlog=FALSE; + lastTTstore=0; + ttStore = (struct ttStoreType *)calloc(SEARCHSIZE, sizeof(struct ttStoreType)); + if (ttStore==NULL) + exit(1); + + if (gb_ram==0) { /* Autoconfig */ + + #ifdef _WIN32 + + SYSTEM_INFO temp; + + MEMORYSTATUSEX statex; + statex.dwLength = sizeof (statex); + + GlobalMemoryStatusEx (&statex); /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus + was suggested by Lorne Anderson. */ + + pcmem=(unsigned long long)statex.ullTotalPhys/1024; + + if (pcmem < 1500000) + noOfThreads=Min(MAXNOOFTHREADS, 2); + else if (pcmem < 2500000) + noOfThreads=Min(MAXNOOFTHREADS, 4); + else + noOfThreads=MAXNOOFTHREADS; + + GetSystemInfo(&temp); + noOfCores=Min(noOfThreads, (int)temp.dwNumberOfProcessors); + + #endif + #ifdef __linux__ /* The code for linux was suggested by Antony Lee. */ + ncores = sysconf(_SC_NPROCESSORS_ONLN); + FILE* fifo = popen("free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r"); + fscanf(fifo, "%lld", &pcmem); + fclose(fifo); + #endif + + } + else { + if (gb_ram < 2) + noOfThreads=Min(MAXNOOFTHREADS, 2); + else if (gb_ram < 3) + noOfThreads=Min(MAXNOOFTHREADS, 4); + else + noOfThreads=Min(MAXNOOFTHREADS, 8); + + noOfCores=Min(noOfThreads, ncores); + + pcmem=(unsigned long long)(1000000 * gb_ram); + } + + /*printf("noOfThreads: %d noOfCores: %d\n", noOfThreads, noOfCores);*/ + + for (k=0; k=2; r--) { + if ((k & bitMapRank[r])!=0) { + highestRank[k]=r; + break; + } + } + } + + /* The use of the counttable to give the number of bits set to + one in an integer follows an implementation by Thomas Andrews. */ + + counttable = (int *)calloc(8192, sizeof(int)); + if (counttable==NULL) + exit(1); + + for (i=0; i<8192; i++) { + counttable[i]=0; + for (j=0; j<13; j++) { + if (i & (1<=2; r--) { + if ((i & bitMapRank[r])!=0) { + if (k <= j) { + res|=bitMapRank[r]; + k++; + } + else + break; + } + } + for (m=0; m=(topBitRank+topBitRank)) { + /* Next top bit */ + topBitRank <<=1; + } + + localVar[thrId].rel[ind]=localVar[thrId].rel[ind ^ topBitRank]; + + for (s=0; s<4; s++) { + ord=0; + for (r=14; r>=2; r--) { + if ((ind & bitMapRank[r])!=0) { + ord++; + localVar[thrId].rel[ind].relRank[r][s]=ord; + for (h=0; h<4; h++) { + if ((localVar[thrId].game.suit[h][s] & bitMapRank[r])!=0) { + localVar[thrId].rel[ind].absRank[ord][s].hand=h; + localVar[thrId].rel[ind].absRank[ord][s].rank=r; + break; + } + } + } + } + for (k=ord+1; k<=13; k++) { + localVar[thrId].rel[ind].absRank[k][s].hand=-1; + localVar[thrId].rel[ind].absRank[k][s].rank=0; + } + for (h=0; h<4; h++) { + if (localVar[thrId].game.suit[h][s] & topBitRank) { + localVar[thrId].rel[ind].aggrRanks[s]= + (localVar[thrId].rel[ind].aggrRanks[s]>>2)|(h<<24); + localVar[thrId].rel[ind].winMask[s]= + (localVar[thrId].rel[ind].winMask[s]>>2)|(3<<24); + break; + } + } + } + } + } + + localVar[thrId].iniPosition.first[localVar[thrId].game.noOfCards-4]=first; + localVar[thrId].iniPosition.handRelFirst=handRelFirst; + localVar[thrId].lookAheadPos=localVar[thrId].iniPosition; + + localVar[thrId].estTricks[1]=6; + localVar[thrId].estTricks[3]=6; + localVar[thrId].estTricks[0]=7; + localVar[thrId].estTricks[2]=7; + + #ifdef STAT + fprintf(localVar[thrId].fp2, "Estimated tricks for hand to play:\n"); + fprintf(localVar[thrId].fp2, "hand=%d est tricks=%d\n", + localVar[thrId].handToPlay, localVar[thrId].estTricks[localVar[thrId].handToPlay]); + #endif + + InitSearch(&localVar[thrId].lookAheadPos, localVar[thrId].game.noOfCards-4, + localVar[thrId].initialMoves, first, moveTreeFlag, thrId); + return; +} + + +void InitSearch(struct pos * posPoint, int depth, struct moveType startMoves[], + int first, int mtd, int thrId) { + + int s, d, h, handRelFirst, maxAgg, maxHand=0; + int k, noOfStartMoves; /* Number of start moves in the 1st trick */ + int hand[3], suit[3], rank[3]; + struct moveType move; + unsigned short int startMovesBitMap[4][4]; /* Indices are hand and suit */ + unsigned short int aggHand[4][4]; + + for (h=0; h<=3; h++) + for (s=0; s<=3; s++) + startMovesBitMap[h][s]=0; + + handRelFirst=posPoint->handRelFirst; + noOfStartMoves=handRelFirst; + + for (k=0; k<=2; k++) { + hand[k]=handId(first, k); + suit[k]=startMoves[k].suit; + rank[k]=startMoves[k].rank; + if (kfirst[depth]=first; + posPoint->handRelFirst=k; + assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); + posPoint->tricksMAX=0; + + if (k>0) { + posPoint->move[depth+k]=startMoves[k-1]; + move=startMoves[k-1]; + } + + posPoint->high[depth+k]=first; + + while (k>0) { + localVar[thrId].movePly[depth+k].current=0; + localVar[thrId].movePly[depth+k].last=0; + localVar[thrId].movePly[depth+k].move[0].suit=startMoves[k-1].suit; + localVar[thrId].movePly[depth+k].move[0].rank=startMoves[k-1].rank; + if (kmove[depth+k].suit=startMoves[k-1].suit; + posPoint->move[depth+k].rank=startMoves[k-1].rank; + posPoint->high[depth+k]=handId(first, noOfStartMoves-k); + move=posPoint->move[depth+k]; + } + else { + posPoint->move[depth+k]=posPoint->move[depth+k+1]; + posPoint->high[depth+k]=posPoint->high[depth+k+1]; + } + } + k--; + } + + for (s=0; s<=3; s++) + posPoint->removedRanks[s]=0; + + for (s=0; s<=3; s++) /* Suit */ + for (h=0; h<=3; h++) /* Hand */ + posPoint->removedRanks[s]|= + posPoint->rankInSuit[h][s]; + for (s=0; s<=3; s++) + posPoint->removedRanks[s]=~(posPoint->removedRanks[s]); + + for (s=0; s<=3; s++) /* Suit */ + for (h=0; h<=3; h++) /* Hand */ + posPoint->removedRanks[s]&= + (~startMovesBitMap[h][s]); + + for (s=0; s<=3; s++) + localVar[thrId].iniRemovedRanks[s]=posPoint->removedRanks[s]; + + /*for (d=0; d<=49; d++) { + for (s=0; s<=3; s++) + posPoint->winRanks[d][s]=0; + }*/ + + /* Initialize winning and second best ranks */ + for (s=0; s<=3; s++) { + maxAgg=0; + for (h=0; h<=3; h++) { + aggHand[h][s]=startMovesBitMap[h][s] | localVar[thrId].game.suit[h][s]; + if (aggHand[h][s]>maxAgg) { + maxAgg=aggHand[h][s]; + maxHand=h; + } + } + if (maxAgg!=0) { + posPoint->winner[s].hand=maxHand; + k=highestRank[aggHand[maxHand][s]]; + posPoint->winner[s].rank=k; + + maxAgg=0; + for (h=0; h<=3; h++) { + aggHand[h][s]&=(~bitMapRank[k]); + if (aggHand[h][s]>maxAgg) { + maxAgg=aggHand[h][s]; + maxHand=h; + } + } + if (maxAgg>0) { + posPoint->secondBest[s].hand=maxHand; + posPoint->secondBest[s].rank=highestRank[aggHand[maxHand][s]]; + } + else { + posPoint->secondBest[s].hand=-1; + posPoint->secondBest[s].rank=0; + } + } + else { + posPoint->winner[s].hand=-1; + posPoint->winner[s].rank=0; + posPoint->secondBest[s].hand=-1; + posPoint->secondBest[s].rank=0; + } + } + + + for (s=0; s<=3; s++) + for (h=0; h<=3; h++) + posPoint->length[h][s]= + (unsigned char)counttable[posPoint->rankInSuit[h][s]]; + + #ifdef STAT + for (d=0; d<=49; d++) { + score1Counts[d]=0; + score0Counts[d]=0; + c1[d]=0; c2[d]=0; c3[d]=0; c4[d]=0; c5[d]=0; c6[d]=0; c7[d]=0; + c8[d]=0; + localVar[thrId].no[d]=0; + } + #endif + + if (!mtd) { + localVar[thrId].lenSetSize=0; + for (k=0; k<=13; k++) { + for (h=0; h<=3; h++) { + localVar[thrId].rootnp[k][h]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; + localVar[thrId].lenSetSize++; + } + } + localVar[thrId].nodeSetSize=0; + localVar[thrId].winSetSize=0; + } + + #ifdef TTDEBUG + if (!suppressTTlog) + lastTTstore=0; + #endif + + return; +} + +#ifdef STAT +int score1Counts[50], score0Counts[50]; +int sumScore1Counts, sumScore0Counts, dd, suit, rank, order; +int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], c8[50], c9[50]; +int sumc1, sumc2, sumc3, sumc4, sumc5, sumc6, sumc7, sumc8, sumc9; +#endif + +int ABsearch(struct pos * posPoint, int target, int depth, int thrId) { + /* posPoint points to the current look-ahead position, + target is number of tricks to take for the player, + depth is the remaining search length, must be positive, + the value of the subtree is returned. */ + + int moveExists, value, scoreFlag, found; + int hh, ss, rr, qtricks, res, k; + unsigned short int makeWinRank[4]; + struct nodeCardsType * cardsP; + struct evalType evalData; + struct winCardType * np; + struct posSearchType * pp; + struct nodeCardsType * tempP; + struct movePlyType *mply=&localVar[thrId].movePly[depth]; + unsigned short int aggr[4]; + long long suitLengths; + + struct evalType Evaluate(struct pos * posPoint, int trump, int thrId); + /*void Make(struct pos * posPoint, unsigned short int trickCards[4], + int depth, int trump, struct movePlyType *mply, int thrId);*/ + void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); + + /*cardsP=NULL;*/ + assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); + int trump=localVar[thrId].trump; + int hand=handId(posPoint->first[depth], posPoint->handRelFirst); +#ifdef STAT + localVar[thrId].nodes++; +#endif + if (posPoint->handRelFirst==0) { + /*localVar[thrId].trickNodes++;*/ + if (posPoint->tricksMAX>=target) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + + #ifdef STAT + c1[depth]++; + + score1Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], + c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + + return TRUE; + } + if (((posPoint->tricksMAX+(depth>>2)+1)winRanks[depth][ss]=0; + + #ifdef STAT + c2[depth]++; + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], + c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + + return FALSE; + } + + if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { + qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); + if (res) { + if (qtricks==0) + return FALSE; + else + return TRUE; + #ifdef STAT + c3[depth]++; + score1Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], + c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + } + if (!LaterTricksMIN(posPoint,hand,depth,target,trump,thrId)) + return FALSE; + } + else { + qtricks=QuickTricks(posPoint, hand, depth, target, trump, &res, thrId); + if (res) { + if (qtricks==0) + return TRUE; + else + return FALSE; + #ifdef STAT + c4[depth]++; + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], + c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + } + if (LaterTricksMAX(posPoint,hand,depth,target,trump,thrId)) + return TRUE; + } + } + + else if (posPoint->handRelFirst==1) { + ss=posPoint->move[depth+1].suit; + unsigned short ranks=posPoint->rankInSuit[hand][ss] | + posPoint->rankInSuit[partner[hand]][ss]; + found=FALSE; rr=0; qtricks=0; + + if ((trump!=4) && (ss!=trump) && + (((posPoint->rankInSuit[hand][ss]==0) + && (posPoint->rankInSuit[hand][trump]!=0))|| + ((posPoint->rankInSuit[partner[hand]][ss]==0) + && (posPoint->rankInSuit[partner[hand]][trump]!=0)))) { + /* Own side can ruff */ + if ((posPoint->rankInSuit[lho[hand]][ss]!=0)|| + (posPoint->rankInSuit[lho[hand]][trump]==0)) { + found=TRUE; + qtricks=1; + } + } + + else if ( ranks >(bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[lho[hand]][ss])) { + /* Own side has highest card in suit */ + if ((trump==4) || ((ss==trump)|| + (posPoint->rankInSuit[lho[hand]][trump]==0) + || (posPoint->rankInSuit[lho[hand]][ss]!=0))) { + rr=highestRank[ranks]; + if (rr!=0) { + found=TRUE; + qtricks=1; + } + else + found=FALSE; + } + } + + if ((found)&&(depth!=localVar[thrId].iniDepth)) { + for (k=0; k<=3; k++) + posPoint->winRanks[depth][k]=0; + if (rr!=0) + posPoint->winRanks[depth][ss]=bitMapRank[rr]; + + if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { + if (posPoint->tricksMAX+qtricks>=target) { + return TRUE; + } + else if (trump==4) { + if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) + hh=hand; /* Hand to lead next trick */ + else + hh=partner[hand]; + + if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& + (posPoint->secondBest[ss].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; + if (posPoint->tricksMAX+qtricks>=target) + return TRUE; + } + + for (k=0; k<=3; k++) { + if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ + if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) + &&(posPoint->length[partner[hh]][k]==0)) { + qtricks+=counttable[posPoint->rankInSuit[hh][k]]; + if (posPoint->tricksMAX+qtricks>=target) + return TRUE; + } + else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; + if (posPoint->tricksMAX+qtricks>=target) + return TRUE; + } + } + } + } + } + else { + /* MIN node */ + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) { + return FALSE; + } + else if (trump==4) { + if (posPoint->rankInSuit[hand][ss] > posPoint->rankInSuit[partner[hand]][ss]) + hh=hand; /* Hand to lead next trick */ + else + hh=partner[hand]; + + if ((posPoint->winner[ss].hand==hh)&&(posPoint->secondBest[ss].rank!=0)&& + (posPoint->secondBest[ss].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][ss]|=bitMapRank[posPoint->secondBest[ss].rank]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) + return FALSE; + } + + for (k=0; k<=3; k++) { + if ((k!=ss)&&(posPoint->length[hh][k]!=0)) { /* Not lead suit, not void in suit */ + if ((posPoint->length[lho[hh]][k]==0)&&(posPoint->length[rho[hh]][k]==0) + &&(posPoint->length[partner[hh]][k]==0)) { + qtricks+=counttable[posPoint->rankInSuit[hh][k]]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) + return FALSE; + } + else if ((posPoint->winner[k].rank!=0)&&(posPoint->winner[k].hand==hh)) { + qtricks++; + posPoint->winRanks[depth][k]|=bitMapRank[posPoint->winner[k].rank]; + if ((posPoint->tricksMAX+((depth)>>2)+3-qtricks)<=target) + return FALSE; + } + } + } + } + } + } + } + + if ((posPoint->handRelFirst==0)&& + (depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) { + aggr[ss]=0; + for (hh=0; hh<=3; hh++) + aggr[ss]|=posPoint->rankInSuit[hh][ss]; + posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; + } + suitLengths=0; + for (ss=0; ss<=2; ss++) + for (hh=0; hh<=3; hh++) { + suitLengths<<=4; + suitLengths|=posPoint->length[hh][ss]; + } + + pp=SearchLenAndInsert(localVar[thrId].rootnp[depth>>2][hand], + suitLengths, FALSE, &res, thrId); + /* 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, depth>>2, &scoreFlag, thrId); + + if (cardsP!=NULL) { + if (scoreFlag==1) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]= + localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; + + if (cardsP->bestMoveRank!=0) { + localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; + localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; + } + #ifdef STAT + c5[depth]++; + if (scoreFlag==1) + score1Counts[depth]++; + else + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd],c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + #ifdef TTDEBUG + if (!suppressTTlog) { + if (lastTTstorewinRanks[depth][ss]= + localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)cardsP->leastWin[ss]]; + + if (cardsP->bestMoveRank!=0) { + localVar[thrId].bestMoveTT[depth].suit=cardsP->bestMoveSuit; + localVar[thrId].bestMoveTT[depth].rank=cardsP->bestMoveRank; + } + #ifdef STAT + c6[depth]++; + if (scoreFlag==1) + score1Counts[depth]++; + else + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], + c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + + #ifdef TTDEBUG + if (!suppressTTlog) { + if (lastTTstore=target) + value=TRUE; + else + value=FALSE; + for (ss=0; ss<=3; ss++) { + posPoint->winRanks[depth][ss]=evalData.winRanks[ss]; + + #ifdef STAT + c7[depth]++; + if (value==1) + score1Counts[depth]++; + else + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + fprintf(localVar[thrId].fp2, "score statistics:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "d=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], + c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], + c6[dd], c7[dd], c8[dd]); + } + } + #endif + } + return value; + } + else { + /*mply=&localVar[thrId].movePly[depth];*/ + moveExists=MoveGen(posPoint, depth, trump, mply, thrId); + +/*#if 0*/ + if ((posPoint->handRelFirst==3)&&(depth>=/*29*//*33*/37) + &&(depth!=localVar[thrId].iniDepth)) { + mply->current=0; + int mexists=TRUE; + int ready=FALSE; + while (mexists) { + Make(posPoint, makeWinRank, depth, trump, mply, thrId); + depth--; + + for (ss=0; ss<=3; ss++) { + aggr[ss]=0; + for (hh=0; hh<=3; hh++) + aggr[ss]|=posPoint->rankInSuit[hh][ss]; + posPoint->orderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; + } + int hfirst=posPoint->first[depth]; + suitLengths=0; + for (ss=0; ss<=2; ss++) + for (hh=0; hh<=3; hh++) { + suitLengths<<=4; + suitLengths|=posPoint->length[hh][ss]; + } + + pp=SearchLenAndInsert(localVar[thrId].rootnp[depth>>2][hfirst], + suitLengths, FALSE, &res, thrId); + /* 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, depth>>2, &scoreFlag, thrId); + + if (tempP!=NULL) { + if ((localVar[thrId].nodeTypeStore[hand]==MAXNODE)&&(scoreFlag==1)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth+1][ss]= + localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; + if (tempP->bestMoveRank!=0) { + localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; + localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; + } + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; + Undo(posPoint, depth+1, mply/*&localVar[thrId].movePly[depth+1]*/,thrId); + return TRUE; + } + else if ((localVar[thrId].nodeTypeStore[hand]==MINNODE)&&(scoreFlag==0)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth+1][ss]= + localVar[thrId].adaptWins[aggr[ss]].winRanks[(int)tempP->leastWin[ss]]; + if (tempP->bestMoveRank!=0) { + localVar[thrId].bestMoveTT[depth+1].suit=tempP->bestMoveSuit; + localVar[thrId].bestMoveTT[depth+1].rank=tempP->bestMoveRank; + } + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth+1][ss]|=makeWinRank[ss]; + Undo(posPoint, depth+1, mply/*&localVar[thrId].movePly[depth+1]*/, thrId); + return FALSE; + } + else { + mply->move[mply->current].weight+=100; + /*localVar[thrId].movePly[depth+1].move[localVar[thrId].movePly[depth+1].current].weight+=100;*/ + ready=TRUE; + } + } + } + depth++; + Undo(posPoint, depth, mply, thrId); + if (ready) + break; + + if (mply->current <= (mply->last-1)) { + mply->current++; + mexists=TRUE; + } + else + mexists=FALSE; + } + if (ready) + MergeSort(mply->last+1, mply->move); + } +/*#endif*/ + + + mply->current=0; + if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) { + value=FALSE; + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + + while (moveExists) { + Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ + if (posPoint->handRelFirst==0) + localVar[thrId].trickNodes++; + assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); + value=ABsearch(posPoint, target, depth-1, thrId); + + Undo(posPoint, depth, mply, thrId); /* Retract current move */ + if (value==TRUE) { + /* A cut-off? */ + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | + makeWinRank[ss]; + localVar[thrId].bestMove[depth]=mply->move[mply->current]; + 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, mply, thrId); + } + } + else { /* A minnode */ + value=TRUE; + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + + while (moveExists) { + Make(posPoint, makeWinRank, depth, trump, mply, thrId); /* Make current move */ + if (posPoint->handRelFirst==0) + localVar[thrId].trickNodes++; + value=ABsearch(posPoint, target, depth-1, thrId); + + Undo(posPoint, depth, mply, thrId); /* Retract current move */ + if (value==FALSE) { + /* A cut-off? */ + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=posPoint->winRanks[depth-1][ss] | + makeWinRank[ss]; + localVar[thrId].bestMove[depth]=mply->move[mply->current]; + 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, mply, thrId); + } + } + } + ABexit: + if (depth>=4) { + if(posPoint->handRelFirst==0) { + if (value) + k=target; + else + k=target-1; + if (depth!=localVar[thrId].iniDepth) + BuildSOP(posPoint, suitLengths, depth>>2, hand, target, depth, + value, k, thrId); + if (localVar[thrId].clearTTflag) { + /* Wipe out the TT dynamically allocated structures + except for the initially allocated structures. + Set the TT limits to the initial values. + Reset TT array indices to zero. + Reset memory chunk indices to zero. + Set allocated memory to the initial value. */ + /*localVar[thrId].fp2=fopen("dyn.txt", "a"); + fprintf(localVar[thrId].fp2, "Clear TT:\n"); + fprintf(localVar[thrId].fp2, "wcount=%d, ncount=%d, lcount=%d\n", + wcount, ncount, lcount); + fprintf(localVar[thrId].fp2, "winSetSize=%d, nodeSetSize=%d, lenSetSize=%d\n", + winSetSize, nodeSetSize, lenSetSize); + fprintf(localVar[thrId].fp2, "\n"); + fclose(localVar[thrId].fp2);*/ + + Wipe(thrId); + localVar[thrId].winSetSizeLimit=WINIT; + localVar[thrId].nodeSetSizeLimit=NINIT; + localVar[thrId].lenSetSizeLimit=LINIT; + localVar[thrId].lcount=0; + localVar[thrId].allocmem=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); + localVar[thrId].lenSetSize=0; + localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; + for (k=0; k<=13; k++) { + for (hh=0; hh<=3; hh++) { + localVar[thrId].rootnp[k][hh]=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].suitLengths=0; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].posSearchPoint=NULL; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].left=NULL; + localVar[thrId].posSearch[localVar[thrId].lenSetSize].right=NULL; + localVar[thrId].lenSetSize++; + } + } + localVar[thrId].nodeSetSize=0; + localVar[thrId].winSetSize=0; + localVar[thrId].wcount=0; localVar[thrId].ncount=0; + localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); + localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; + localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); + localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; + localVar[thrId].clearTTflag=FALSE; + localVar[thrId].windex=-1; + } + } + } + + #ifdef STAT + c8[depth]++; + if (value==1) + score1Counts[depth]++; + else + score0Counts[depth]++; + if (depth==localVar[thrId].iniDepth) { + if (localVar[thrId].fp2==NULL) + exit(0); + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "top level cards:\n"); + for (hh=0; hh<=3; hh++) { + fprintf(localVar[thrId].fp2, "hand=%c\n", cardHand[hh]); + for (ss=0; ss<=3; ss++) { + fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); + for (rr=14; rr>=2; rr--) + if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) + fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); + fprintf(localVar[thrId].fp2, "\n"); + } + fprintf(localVar[thrId].fp2, "\n"); + } + fprintf(localVar[thrId].fp2, "top level winning cards:\n"); + for (ss=0; ss<=3; ss++) { + fprintf(localVar[thrId].fp2, "suit=%c", cardSuit[ss]); + for (rr=14; rr>=2; rr--) + if (posPoint->winRanks[depth][ss] & bitMapRank[rr]) + fprintf(localVar[thrId].fp2, " %c", cardRank[rr]); + fprintf(localVar[thrId].fp2, "\n"); + } + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "\n"); + + fprintf(localVar[thrId].fp2, "score statistics:\n"); + sumScore0Counts=0; + sumScore1Counts=0; + sumc1=0; sumc2=0; sumc3=0; sumc4=0; + sumc5=0; sumc6=0; sumc7=0; sumc8=0; sumc9=0; + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) { + fprintf(localVar[thrId].fp2, "depth=%d s1=%d s0=%d c1=%d c2=%d c3=%d c4=%d", dd, + score1Counts[dd], score0Counts[dd], c1[dd], c2[dd], c3[dd], c4[dd]); + fprintf(localVar[thrId].fp2, " c5=%d c6=%d c7=%d c8=%d\n", c5[dd], c6[dd], + c7[dd], c8[dd]); + sumScore0Counts=sumScore0Counts+score0Counts[dd]; + sumScore1Counts=sumScore1Counts+score1Counts[dd]; + sumc1=sumc1+c1[dd]; + sumc2=sumc2+c2[dd]; + sumc3=sumc3+c3[dd]; + sumc4=sumc4+c4[dd]; + sumc5=sumc5+c5[dd]; + sumc6=sumc6+c6[dd]; + sumc7=sumc7+c7[dd]; + sumc8=sumc8+c8[dd]; + sumc9=sumc9+c9[dd]; + } + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "score sum statistics:\n"); + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "sumScore0Counts=%d sumScore1Counts=%d\n", + sumScore0Counts, sumScore1Counts); + fprintf(localVar[thrId].fp2, "nodeSetSize=%d winSetSize=%d\n", localVar[thrId].nodeSetSize, + localVar[thrId].winSetSize); + fprintf(localVar[thrId].fp2, "sumc1=%d sumc2=%d sumc3=%d sumc4=%d\n", + sumc1, sumc2, sumc3, sumc4); + fprintf(localVar[thrId].fp2, "sumc5=%d sumc6=%d sumc7=%d sumc8=%d sumc9=%d\n", + sumc5, sumc6, sumc7, sumc8, sumc9); + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "No of searched nodes per depth:\n"); + for (dd=localVar[thrId].iniDepth; dd>=0; dd--) + fprintf(localVar[thrId].fp2, "depth=%d nodes=%d\n", dd, localVar[thrId].no[dd]); + fprintf(localVar[thrId].fp2, "\n"); + fprintf(localVar[thrId].fp2, "Total nodes=%d\n", localVar[thrId].nodes); + } + #endif + + return value; +} + + +void Make(struct pos * posPoint, unsigned short int trickCards[4], + int depth, int trump, struct movePlyType *mply, int thrId) { + int t, u, w; + int mcurr, q; + + assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); + for (int suit=0; suit<=3; suit++) + trickCards[suit]=0; + + 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]; + } + } + 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]; + } + + /* Is the trick won by rank? */ + int s=posPoint->move[depth].suit; + int count=0; + if (mply->move[r].suit==s) + count++; + for (int e=1; e<=3; e++) { + mcurr=localVar[thrId].movePly[depth+e].current; + if (localVar[thrId].movePly[depth+e].move[mcurr].suit==s) { + count++; + /*if (++count>1) + break;*/ + } + } + + + if (localVar[thrId].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=localVar[thrId].movePly[depth+d].current; + w=localVar[thrId].movePly[depth+d].move[r].rank; + u=localVar[thrId].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=localVar[thrId].rel[aggr].absRank[1][u].rank; + posPoint->winner[u].hand=localVar[thrId].rel[aggr].absRank[1][u].hand; + posPoint->secondBest[u].rank=localVar[thrId].rel[aggr].absRank[2][u].rank; + posPoint->secondBest[u].hand=localVar[thrId].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]|=localVar[thrId].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]=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 { + 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]; + } + } + 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]; + } + + t=handId(firstHand, posPoint->handRelFirst); + posPoint->handRelFirst++; /* Current hand is stepped */ + 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]--; + +#ifdef STAT + localVar[thrId].no[depth]++; +#endif + + return; +} + + + +void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId) { + int r, t, u, w; + + assert((posPoint->handRelFirst>=0)&&(posPoint->handRelFirst<=3)); + + switch (posPoint->handRelFirst) { + case 3: case 2: case 1: + posPoint->handRelFirst--; + break; + case 0: + posPoint->handRelFirst=3; + } + + int firstHand=posPoint->first[depth]; + + if (posPoint->handRelFirst==0) { /* 1st hand which won the previous + trick */ + t=firstHand; + r=mply->current; + u=mply->move[r].suit; + w=mply->move[r].rank; + } + else if (posPoint->handRelFirst==3) { /* Last hand */ + for (int d=3; d>=0; d--) { + /* Delete the moves from removed ranks */ + r=localVar[thrId].movePly[depth+d].current; + w=localVar[thrId].movePly[depth+d].move[r].rank; + u=localVar[thrId].movePly[depth+d].move[r].suit; + + posPoint->removedRanks[u]&= (~bitMapRank[w]); + + if (w>posPoint->winner[u].rank) { + /*posPoint->secondBest[u].rank=posPoint->winner[u].rank; + posPoint->secondBest[u].hand=posPoint->winner[u].hand;*/ + posPoint->secondBest[u]=posPoint->winner[u]; + posPoint->winner[u].rank=w; + posPoint->winner[u].hand=handId(firstHand, 3-d); + + } + else if (w>posPoint->secondBest[u].rank) { + posPoint->secondBest[u].rank=w; + posPoint->secondBest[u].hand=handId(firstHand, 3-d); + } + } + t=handId(firstHand, 3); + + + if (localVar[thrId].nodeTypeStore[posPoint->first[depth-1]]==MAXNODE) + /* First hand of next trick is winner of the current trick */ + posPoint->tricksMAX--; + } + else { + t=handId(firstHand, posPoint->handRelFirst); + r=mply->current; + u=mply->move[r].suit; + w=mply->move[r].rank; + } + + posPoint->rankInSuit[t][u]|=bitMapRank[w]; + + posPoint->length[t][u]++; + + return; +} + + + +struct evalType Evaluate(struct pos * posPoint, int trump, int thrId) { + int s, h, hmax=0, count=0, k=0; + unsigned short rmax=0; + struct evalType eval; + + int firstHand=posPoint->first[0]; + assert((firstHand >= 0)&&(firstHand <= 3)); + + for (s=0; s<=3; s++) + eval.winRanks[s]=0; + + /* Who wins the last trick? */ + if (trump!=4) { /* Highest trump card wins */ + for (h=0; h<=3; h++) { + if (posPoint->rankInSuit[h][trump]!=0) + count++; + if (posPoint->rankInSuit[h][trump]>rmax) { + hmax=h; + rmax=posPoint->rankInSuit[h][trump]; + } + } + + if (rmax>0) { /* Trumpcard wins */ + if (count>=2) + eval.winRanks[trump]=rmax; + + if (localVar[thrId].nodeTypeStore[hmax]==MAXNODE) + goto maxexit; + else + goto minexit; + } + } + + /* Who has the highest card in the suit played by 1st hand? */ + + k=0; + while (k<=3) { /* Find the card the 1st hand played */ + if (posPoint->rankInSuit[firstHand][k]!=0) /* Is this the card? */ + break; + k++; + } + + assert(k < 4); + + for (h=0; h<=3; h++) { + if (posPoint->rankInSuit[h][k]!=0) + count++; + if (posPoint->rankInSuit[h][k]>rmax) { + hmax=h; + rmax=posPoint->rankInSuit[h][k]; + } + } + + if (count>=2) + eval.winRanks[k]=rmax; + + if (localVar[thrId].nodeTypeStore[hmax]==MAXNODE) + goto maxexit; + else + goto minexit; + + maxexit: + eval.tricks=posPoint->tricksMAX+1; + return eval; + + minexit: + eval.tricks=posPoint->tricksMAX; + return eval; +} + + +int QuickTricks(struct pos * posPoint, int hand, + int depth, int target, int trump, int *result, int thrId) { + int suit, sum, commRank=0, commSuit=-1, s; + int opps, res; + int countLho, countRho, countPart, countOwn, lhoTrumpRanks, rhoTrumpRanks; + int cutoff, ss, rr, lowestQtricks=0; + + int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, int commPartner, + int commSuit, int countOwn, int countPart, int suit, int qtricks, int trump, int *res); + + int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, + int countPart, int suit, int qtricks, int trump, int *res); + + int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, + int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); + + int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int countOwn, + int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId); + + *result=TRUE; + int qtricks=0; + for (s=0; s<=3; s++) + posPoint->winRanks[depth][s]=0; + + if ((depth<=0)||(depth==localVar[thrId].iniDepth)) { + *result=FALSE; + return qtricks; + } + + if (localVar[thrId].nodeTypeStore[hand]==MAXNODE) + cutoff=target-posPoint->tricksMAX; + else + cutoff=posPoint->tricksMAX-target+(depth>>2)+2; + + int commPartner=FALSE; + for (s=0; s<=3; s++) { + if ((trump!=4)&&(trump!=s)) { + if (posPoint->winner[s].hand==partner[hand]) { + /* Partner has winning card */ + if (posPoint->rankInSuit[hand][s]!=0) { + /* Own hand has card in suit */ + if (((posPoint->rankInSuit[lho[hand]][s]!=0) || + /* LHO not void */ + (posPoint->rankInSuit[lho[hand]][trump]==0)) + /* LHO has no trump */ + && ((posPoint->rankInSuit[rho[hand]][s]!=0) || + /* RHO not void */ + (posPoint->rankInSuit[rho[hand]][trump]==0))) { + /* RHO has no trump */ + commPartner=TRUE; + commSuit=s; + commRank=posPoint->winner[s].rank; + break; + } + } + } + else if (posPoint->secondBest[s].hand==partner[hand]) { + if ((posPoint->winner[s].hand==hand)&& + (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { + if (((posPoint->rankInSuit[lho[hand]][s]!=0) || + (posPoint->rankInSuit[lho[hand]][trump]==0)) + && ((posPoint->rankInSuit[rho[hand]][s]!=0) || + (posPoint->rankInSuit[rho[hand]][trump]==0))) { + commPartner=TRUE; + commSuit=s; + commRank=posPoint->secondBest[s].rank; + break; + } + } + } + } + else if (trump==4) { + if (posPoint->winner[s].hand==partner[hand]) { + /* Partner has winning card */ + if (posPoint->rankInSuit[hand][s]!=0) { + /* Own hand has card in suit */ + commPartner=TRUE; + commSuit=s; + commRank=posPoint->winner[s].rank; + break; + } + } + else if (posPoint->secondBest[s].hand==partner[hand]) { + if ((posPoint->winner[s].hand==hand)&& + (posPoint->length[hand][s]>=2)&&(posPoint->length[partner[hand]][s]>=2)) { + commPartner=TRUE; + commSuit=s; + commRank=posPoint->secondBest[s].rank; + break; + } + } + } + } + + if ((trump!=4) && (!commPartner) && + (posPoint->rankInSuit[hand][trump]!=0) && + (posPoint->winner[trump].hand==partner[hand])) { + commPartner=TRUE; + commSuit=trump; + commRank=posPoint->winner[trump].rank; + } + + + if (trump!=4) { + suit=trump; + lhoTrumpRanks=posPoint->length[lho[hand]][trump]; + rhoTrumpRanks=posPoint->length[rho[hand]][trump]; + } + else + suit=0; + + do { + countOwn=posPoint->length[hand][suit]; + countLho=posPoint->length[lho[hand]][suit]; + countRho=posPoint->length[rho[hand]][suit]; + countPart=posPoint->length[partner[hand]][suit]; + opps=countLho | countRho; + + if (!opps && (countPart==0)) { + if (countOwn==0) { + /* Continue with next suit. */ + if ((trump!=4)&&(trump!=suit)) { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + } + else { + if ((trump!=4) && (trump==suit)) { + if (trump==0) + suit=1; + else + suit=0; + } + else + suit++; + } + continue; + } + + /* Long tricks when only leading hand have cards in the suit. */ + if ((trump!=4) && (trump!=suit)) { + if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { + qtricks+=countOwn; + if (qtricks>=cutoff) + return qtricks; + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + } + else { + qtricks+=countOwn; + if (qtricks>=cutoff) + return qtricks; + + if ((trump!=4) && (suit==trump)) { + if (trump==0) + suit=1; + else + suit=0; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + } + continue; + } + } + else { + if (!opps && (trump!=4) && (suit==trump)) { + /* The partner but not the opponents have cards in the trump suit. */ + sum=Max(countOwn, countPart); + for (s=0; s<=3; s++) { + if ((sum>0)&&(s!=trump)&&(countOwn>=countPart)&&(posPoint->length[hand][s]>0)&& + (posPoint->length[partner[hand]][s]==0)) { + sum++; + break; + } + } + /* If the additional trick by ruffing causes a cutoff. (qtricks not incremented.) */ + if (sum>=cutoff) + return sum; + } + else if (!opps) { + /* The partner but not the opponents have cards in the suit. */ + sum=Min(countOwn,countPart); + if (trump==4) { + if (sum>=cutoff) + return sum; + } + else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + if (sum>=cutoff) + return sum; + } + } + + if (commPartner) { + if (!opps && (countOwn==0)) { + if ((trump!=4) && (trump!=suit)) { + if ((lhoTrumpRanks==0) && (rhoTrumpRanks==0)) { + qtricks+=countPart; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + if (qtricks>=cutoff) + return qtricks; + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + } + else { + qtricks+=countPart; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + if (qtricks>=cutoff) + return qtricks; + if ((trump!=4) && (suit==trump)) { + if (trump==0) + suit=1; + else + suit=0; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + } + continue; + } + } + else { + if (!opps && (trump!=4) && (suit==trump)) { + sum=Max(countOwn, countPart); + for (s=0; s<=3; s++) { + if ((sum>0)&&(s!=trump)&&(countOwn<=countPart)&&(posPoint->length[partner[hand]][s]>0)&& + (posPoint->length[hand][s]==0)) { + sum++; + break; + } + } + if (sum>=cutoff) { + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + return sum; + } + } + else if (!opps) { + sum=Min(countOwn,countPart); + if (trump==4) { + if (sum>=cutoff) + return sum; + } + else if ((suit!=trump)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + if (sum>=cutoff) + return sum; + } + } + } + } + } + + if (posPoint->winner[suit].rank==0) { + if ((trump!=4) && (suit==trump)) { + if (trump==0) + suit=1; + else + suit=0; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + } + continue; + } + + if (posPoint->winner[suit].hand==hand) { + if ((trump!=4)&&(trump!=suit)) { + qtricks=QtricksLeadHandTrump(hand, posPoint, cutoff, depth, + countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, + countPart, suit, qtricks, trump, &res); + if (res==1) + return qtricks; + else if (res==2) { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + } + else { + qtricks=QtricksLeadHandNT(hand, posPoint, cutoff, depth, + countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks, + commPartner, commSuit, countOwn, + countPart, suit, qtricks, trump, &res); + if (res==1) + return qtricks; + else if (res==2) { + if ((trump!=4) && (trump==suit)) { + if (trump==0) + suit=1; + else + suit=0; + } + else + suit++; + continue; + } + } + } + + /* It was not possible to take a quick trick by own winning card in + the suit */ + else { + /* Partner winning card? */ + if ((posPoint->winner[suit].hand==partner[hand])&&(1/*countPart>0*/)) { + /* Winner found at partner*/ + if (commPartner) { + /* There is communication with the partner */ + if ((trump!=4)&&(trump!=suit)) { + qtricks=QuickTricksPartnerHandTrump(hand, posPoint, cutoff, depth, + countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, + countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); + if (res==1) + return qtricks; + else if (res==2) { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + } + else { + qtricks=QuickTricksPartnerHandNT(hand, posPoint, cutoff, depth, + countLho, countRho, countOwn, + countPart, suit, qtricks, commSuit, commRank, trump, &res, thrId); + if (res==1) + return qtricks; + else if (res==2) { + if ((trump!=4) && (trump==suit)) { + if (trump==0) + suit=1; + else + suit=0; + } + else + suit++; + continue; + } + } + } + } + } + if ((trump!=4) &&(suit!=trump)&& + (countOwn>0)&&(lowestQtricks==0)&& + ((qtricks==0)||((posPoint->winner[suit].hand!=hand)&& + (posPoint->winner[suit].hand!=partner[hand])&& + (posPoint->winner[trump].hand!=hand)&& + (posPoint->winner[trump].hand!=partner[hand])))) { + if ((countPart==0)&&(posPoint->length[partner[hand]][trump]>0)) { + if (((countRho>0)||(posPoint->length[rho[hand]][trump]==0))&& + ((countLho>0)||(posPoint->length[lho[hand]][trump]==0))) { + lowestQtricks=1; + if (1>=cutoff) + return 1; + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + else if ((countRho==0)&&(countLho==0)) { + if ((posPoint->rankInSuit[lho[hand]][trump] | + posPoint->rankInSuit[rho[hand]][trump]) < + posPoint->rankInSuit[partner[hand]][trump]) { + lowestQtricks=1; + + rr=highestRank[posPoint->rankInSuit[partner[hand]][trump]]; + if (rr!=0) { + posPoint->winRanks[depth][trump]|=bitMapRank[rr]; + if (1>=cutoff) + return 1; + } + } + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + else if (countLho==0) { + if (posPoint->rankInSuit[lho[hand]][trump] < + posPoint->rankInSuit[partner[hand]][trump]) { + lowestQtricks=1; + for (rr=14; rr>=2; rr--) { + if ((posPoint->rankInSuit[partner[hand]][trump] & + bitMapRank[rr])!=0) { + posPoint->winRanks[depth][trump]|=bitMapRank[rr]; + break; + } + } + if (1>=cutoff) + return 1; + } + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + else if (countRho==0) { + if (posPoint->rankInSuit[rho[hand]][trump] < + posPoint->rankInSuit[partner[hand]][trump]) { + lowestQtricks=1; + for (rr=14; rr>=2; rr--) { + if ((posPoint->rankInSuit[partner[hand]][trump] & + bitMapRank[rr])!=0) { + posPoint->winRanks[depth][trump]|=bitMapRank[rr]; + break; + } + } + if (1>=cutoff) + return 1; + } + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + continue; + } + } + } + if (qtricks>=cutoff) + return qtricks; + if ((trump!=4) && (suit==trump)) { + if (trump==0) + suit=1; + else + suit=0; + } + else { + suit++; + if ((trump!=4) && (suit==trump)) + suit++; + } + } + while (suit<=3); + + if (qtricks==0) { + if ((trump==4)||(posPoint->winner[trump].hand==-1)) { + for (ss=0; ss<=3; ss++) { + if (posPoint->winner[ss].hand==-1) + continue; + if (posPoint->length[hand][ss]>0) { + posPoint->winRanks[depth][ss]= + bitMapRank[posPoint->winner[ss].rank]; + } + } + if (localVar[thrId].nodeTypeStore[hand]!=MAXNODE) + cutoff=target-posPoint->tricksMAX; + else + cutoff=posPoint->tricksMAX-target+(depth>>2)+2; + + if (1>=cutoff) + return 0; + } + } + + *result=FALSE; + return qtricks; +} + + +int QtricksLeadHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, + int countPart, int suit, int qtricks, int trump, int *res) { + /* res=0 Continue with same suit. + res=1 Cutoff. + res=2 Continue with next suit. */ + + + *res=1; + int qt=qtricks; + if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { + posPoint->winRanks[depth][suit]|= + bitMapRank[posPoint->winner[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + + if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)&& + (lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + qt+=countOwn-1; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + + if (posPoint->secondBest[suit].hand==hand) { + if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + posPoint->winRanks[depth][suit]|= + bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { + qt+=countOwn-2; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + /*else { + aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][suit]; + if (rel[aggr].absRank[3][suit].hand==hand) { + qt++; + posPoint->winRanks[depth][suit]|= + bitMapRank[rel[aggr].absRank[3][suit].rank]; + if (qt>=cutoff) + return qt; + if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { + qt+=countOwn-3; + if (qt>=cutoff) + return qt; + } + *res=2; + return qt; + } + }*/ + } + } + else if ((posPoint->secondBest[suit].hand==partner[hand]) + &&(countOwn>1)&&(countPart>1)) { + /* Second best at partner and suit length of own + hand and partner > 1 */ + if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + posPoint->winRanks[depth][suit]|= + bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { + qt+=Max(countOwn-2, countPart-2); + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + } + *res=0; + return qt; +} + +int QtricksLeadHandNT(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int *lhoTrumpRanks, int *rhoTrumpRanks, + int commPartner, int commSuit, int countOwn, + int countPart, int suit, int qtricks, int trump, int *res) { + /* res=0 Continue with same suit. + res=1 Cutoff. + res=2 Continue with next suit. */ + + + *res=1; + int qt=qtricks; + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { + /*if (trump==suit) {*/ + (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); + (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); + } + + if ((countLho<=1)&&(countRho<=1)&&(countPart<=1)) { + qt+=countOwn-1; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + + if (posPoint->secondBest[suit].hand==hand) { + posPoint->winRanks[depth][suit]|= + bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { + (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); + (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); + } + if ((countLho<=2)&&(countRho<=2)&&(countPart<=2)) { + qt+=countOwn-2; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + /*else { + aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][suit]; + if (rel[aggr].absRank[3][suit].hand==hand) { + qt++; + posPoint->winRanks[depth][suit]|= + bitMapRank[rel[aggr].absRank[3][suit].rank]; + if (qt>=cutoff) + return qt; + if ((countLho<=3)&&(countRho<=3)&&(countPart<=3)) { + qt+=countOwn-3; + if (qt>=cutoff) + return qt; + } + *res=2; + return qt; + } + }*/ + } + else if ((posPoint->secondBest[suit].hand==partner[hand]) + &&(countOwn>1)&&(countPart>1)) { + /* Second best at partner and suit length of own + hand and partner > 1 */ + posPoint->winRanks[depth][suit]|= + bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((trump==suit) && ((!commPartner) || (suit!=commSuit))) { + (*lhoTrumpRanks)=Max(0, (*lhoTrumpRanks)-1); + (*rhoTrumpRanks)=Max(0, (*rhoTrumpRanks)-1); + } + if ((countLho<=2)&&(countRho<=2)&&((countPart<=2)||(countOwn<=2))) { + qt+=Max(countOwn-2,countPart-2); + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + /*else if (countPart>2) { + aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][suit]; + if (rel[aggr].absRank[3][suit].hand==hand) { + qt++; + posPoint->winRanks[depth][suit]|= + bitMapRank[rel[aggr].absRank[3][suit].rank]; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + }*/ + } + + *res=0; + return qt; +} + + +int QuickTricksPartnerHandTrump(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int lhoTrumpRanks, int rhoTrumpRanks, int countOwn, + int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { + /* res=0 Continue with same suit. + res=1 Cutoff. + res=2 Continue with next suit. */ + + + *res=1; + int qt=qtricks; + if (((countLho!=0) || (lhoTrumpRanks==0)) && ((countRho!=0) || (rhoTrumpRanks==0))) { + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + qt++; /* A trick can be taken */ + if (qt>=cutoff) + return qt; + if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)&&(lhoTrumpRanks==0)&& + (rhoTrumpRanks==0)) { + qt+=countPart-1; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + + if (posPoint->secondBest[suit].hand==partner[hand]) { + /* Second best found in partners hand */ + if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + /* Opponents have no trump */ + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { + qt+=countPart-2; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + } + else if ((posPoint->secondBest[suit].hand==hand)&&(countPart>1)&&(countOwn>1)) { + /* Second best found in own hand and suit lengths of own hand and partner > 1*/ + if ((lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + /* Opponents have no trump */ + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { + qt+=Max(countPart-2,countOwn-2); + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + } + else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])&& + ((countLho>=2)||(lhoTrumpRanks==0))&&((countRho>=2)||(rhoTrumpRanks==0))) { + unsigned short ranks=0; + for (int k=0; k<=3; k++) + ranks|=posPoint->rankInSuit[k][suit]; + if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { + posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)&&(lhoTrumpRanks==0)&&(rhoTrumpRanks==0)) { + qt+=countPart-2; + if (qt>=cutoff) + return qt; + } + } + } + *res=0; + return qt; +} + + +int QuickTricksPartnerHandNT(int hand, struct pos *posPoint, int cutoff, int depth, + int countLho, int countRho, int countOwn, + int countPart, int suit, int qtricks, int commSuit, int commRank, int trump, int *res, int thrId) { + + *res=1; + int qt=qtricks; + + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->winner[suit].rank]; + posPoint->winRanks[depth][commSuit]|=bitMapRank[commRank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=1)&&(countRho<=1)&&(countOwn<=1)) { + qt+=countPart-1; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + + if ((posPoint->secondBest[suit].hand==partner[hand])&&(1/*countPart>0*/)) { + /* Second best found in partners hand */ + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&(countOwn<=2)) { + qt+=countPart-2; + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + else if ((posPoint->secondBest[suit].hand==hand) + &&(countPart>1)&&(countOwn>1)) { + /* Second best found in own hand and own and + partner's suit length > 1 */ + posPoint->winRanks[depth][suit]|=bitMapRank[posPoint->secondBest[suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countLho<=2)&&(countRho<=2)&&((countOwn<=2)||(countPart<=2))) { + qt+=Max(countPart-2,countOwn-2); + if (qt>=cutoff) + return qt; + *res=2; + return qt; + } + } + else if ((suit==commSuit)&&(posPoint->secondBest[suit].hand==lho[hand])) { + unsigned short ranks=0; + for (int k=0; k<=3; k++) + ranks|=posPoint->rankInSuit[k][suit]; + if (localVar[thrId].rel[ranks].absRank[3][suit].hand==partner[hand]) { + posPoint->winRanks[depth][suit]|=bitMapRank[localVar[thrId].rel[ranks].absRank[3][suit].rank]; + qt++; + if (qt>=cutoff) + return qt; + if ((countOwn<=2)&&(countLho<=2)&&(countRho<=2)) { + qtricks+=countPart-2; + if (qt>=cutoff) + return qt; + } + } + } + *res=0; + return qt; +} + + +int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, + int trump, int thrId) { + int hh, ss, k, h, sum=0; + /*unsigned short aggr;*/ + + if ((trump==4)||(posPoint->winner[trump].rank==0)) { + for (ss=0; ss<=3; ss++) { + hh=posPoint->winner[ss].hand; + if (hh!=-1) { + if (localVar[thrId].nodeTypeStore[hh]==MAXNODE) + sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); + } + } + if ((posPoint->tricksMAX+sum0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { + if ((posPoint->tricksMAX+(depth>>2)winner[ss].hand==-1) + posPoint->winRanks[depth][ss]=0; + else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MINNODE) { + if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& + (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& + (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) + posPoint->winRanks[depth][ss]=0; + else + posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; + } + else + posPoint->winRanks[depth][ss]=0; + } + return FALSE; + } + } + } + else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && + (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MINNODE)) { + if ((posPoint->length[hand][trump]==0)&& + (posPoint->length[partner[hand]][trump]==0)) { + if (((posPoint->tricksMAX+(depth>>2)+1- + Max(posPoint->length[lho[hand]][trump], + posPoint->length[rho[hand]][trump]))0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + return FALSE; + } + } + else if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->winner[trump].rank]; + return FALSE; + } + else { + hh=posPoint->secondBest[trump].hand; + if (hh!=-1) { + if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&&(posPoint->secondBest[trump].rank!=0)) { + if (((posPoint->length[hh][trump]>1) || + (posPoint->length[partner[hh]][trump]>1))&& + ((posPoint->tricksMAX+(depth>>2)-1)0) + &&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->secondBest[trump].rank] ; + return FALSE; + } + } + } + } + } + else if (trump!=4) { + hh=posPoint->secondBest[trump].hand; + if (hh!=-1) { + if ((localVar[thrId].nodeTypeStore[hh]==MINNODE)&& + (posPoint->length[hh][trump]>1)) { + if (posPoint->winner[trump].hand==rho[hh]) { + if (((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->secondBest[trump].rank]; + return FALSE; + } + } + else { + unsigned short aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][trump]; + h=localVar[thrId].rel[aggr].absRank[3][trump].hand; + if (h!=-1) { + if ((localVar[thrId].nodeTypeStore[h]==MINNODE)&& + ((posPoint->tricksMAX+(depth>>2))0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; + return FALSE; + } + } + } + } + } + } + return TRUE; +} + + +int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, + int trump, int thrId) { + int hh, ss, k, h, sum=0; + /*unsigned short aggr;*/ + + if ((trump==4)||(posPoint->winner[trump].rank==0)) { + for (ss=0; ss<=3; ss++) { + hh=posPoint->winner[ss].hand; + if (hh!=-1) { + if (localVar[thrId].nodeTypeStore[hh]==MINNODE) + sum+=Max(posPoint->length[hh][ss], posPoint->length[partner[hh]][ss]); + } + } + if ((posPoint->tricksMAX+(depth>>2)+1-sum>=target)&& + (sum>0)&&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { + if ((posPoint->tricksMAX+1>=target)) { + for (ss=0; ss<=3; ss++) { + if (posPoint->winner[ss].hand==-1) + posPoint->winRanks[depth][ss]=0; + else if (localVar[thrId].nodeTypeStore[posPoint->winner[ss].hand]==MAXNODE) { + if ((posPoint->rankInSuit[partner[posPoint->winner[ss].hand]][ss]==0)&& + (posPoint->rankInSuit[lho[posPoint->winner[ss].hand]][ss]==0)&& + (posPoint->rankInSuit[rho[posPoint->winner[ss].hand]][ss]==0)) + posPoint->winRanks[depth][ss]=0; + else + posPoint->winRanks[depth][ss]=bitMapRank[posPoint->winner[ss].rank]; + } + else + posPoint->winRanks[depth][ss]=0; + } + return TRUE; + } + } + } + else if ((trump!=4) && (posPoint->winner[trump].rank!=0) && + (localVar[thrId].nodeTypeStore[posPoint->winner[trump].hand]==MAXNODE)) { + if ((posPoint->length[hand][trump]==0)&& + (posPoint->length[partner[hand]][trump]==0)) { + if (((posPoint->tricksMAX+Max(posPoint->length[lho[hand]][trump], + posPoint->length[rho[hand]][trump]))>=target) + &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + return TRUE; + } + } + else if (((posPoint->tricksMAX+1)>=target) + &&(depth>0)&&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->winner[trump].rank]; + return TRUE; + } + else { + hh=posPoint->secondBest[trump].hand; + if (hh!=-1) { + if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&&(posPoint->secondBest[trump].rank!=0)) { + if (((posPoint->length[hh][trump]>1) || + (posPoint->length[partner[hh]][trump]>1))&& + ((posPoint->tricksMAX+2)>=target)&&(depth>0) + &&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->secondBest[trump].rank]; + return TRUE; + } + } + } + } + } + + else if (trump!=4) { + hh=posPoint->secondBest[trump].hand; + if (hh!=-1) { + if ((localVar[thrId].nodeTypeStore[hh]==MAXNODE)&& + (posPoint->length[hh][trump]>1)) { + if (posPoint->winner[trump].hand==rho[hh]) { + if (((posPoint->tricksMAX+1)>=target)&&(depth>0) + &&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[posPoint->secondBest[trump].rank] ; + return TRUE; + } + } + else { + unsigned short aggr=0; + for (k=0; k<=3; k++) + aggr|=posPoint->rankInSuit[k][trump]; + h=localVar[thrId].rel[aggr].absRank[3][trump].hand; + if (h!=-1) { + if ((localVar[thrId].nodeTypeStore[h]==MAXNODE)&& + ((posPoint->tricksMAX+1)>=target)&&(depth>0) + &&(depth!=localVar[thrId].iniDepth)) { + for (ss=0; ss<=3; ss++) + posPoint->winRanks[depth][ss]=0; + posPoint->winRanks[depth][trump]= + bitMapRank[localVar[thrId].rel[aggr].absRank[3][trump].rank]; + return TRUE; + } + } + } + } + } + } + return FALSE; +} + + +int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId) { + int k, state=MOVESVALID; + + int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int trump, int thrId); + int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int thrId); + + for (k=0; k<4; k++) + localVar[thrId].lowestWin[depth][k]=0; + + int m=0; + int r=posPoint->handRelFirst; + int first=posPoint->first[depth]; + int q=handId(first, r); + + if (r!=0) { + int s=localVar[thrId].movePly[depth+r].current; /* Current move of first hand */ + int t=localVar[thrId].movePly[depth+r].move[s].suit; /* Suit played by first hand */ + unsigned short ris=posPoint->rankInSuit[q][t]; + + if (ris!=0) { + /* Not first hand and not void in suit */ + k=14; + while (k>=2) { + if ((ris & bitMapRank[k])&&(state==MOVESVALID)) { + /* Only first move in sequence is generated */ + mply->move[m].suit=t; + mply->move[m].rank=k; + mply->move[m].sequence=0; + m++; + state=MOVESLOCKED; + } + else if (state==MOVESLOCKED) { + if (ris & bitMapRank[k]) + /* If the card is in own hand */ + mply->move[m-1].sequence|=bitMapRank[k]; + else if ((posPoint->removedRanks[t] & 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++) + mply->move[k].weight=WeightAllocTrump(posPoint, + &(mply->move[k]), depth, ris, trump, thrId); + } + else { + for (k=0; k<=m-1; k++) + mply->move[k].weight=WeightAllocNT(posPoint, + &(mply->move[k]), depth, ris, thrId); + } + } + + mply->last=m-1; + if (m!=1) + MergeSort(m, mply->move); + if (depth!=localVar[thrId].iniDepth) + return m; + else { + m=AdjustMoveList(thrId); + return m; + } + } + } + + /* First hand or void in suit */ + for (int suit=0; suit<=3; suit++) { + k=14; state=MOVESVALID; + while (k>=2) { + if ((posPoint->rankInSuit[q][suit] & bitMapRank[k])&& + (state==MOVESVALID)) { + /* Only first move in sequence is generated */ + mply->move[m].suit=suit; + mply->move[m].rank=k; + mply->move[m].sequence=0; + m++; + state=MOVESLOCKED; + } + else if (state==MOVESLOCKED) { + if (posPoint->rankInSuit[q][suit] & bitMapRank[k]) + /* If the card is in own hand */ + mply->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--; + } + } + + if ((trump!=4)&&(posPoint->winner[trump].rank!=0)) { + for (k=0; k<=m-1; k++) + mply->move[k].weight=WeightAllocTrump(posPoint, + &(mply->move[k]), depth, 0/*ris*/, trump, thrId); + } + else { + for (k=0; k<=m-1; k++) + mply->move[k].weight=WeightAllocNT(posPoint, + &(mply->move[k]), depth, 0/*ris*/, thrId); + } + + mply->last=m-1; + if (m!=1) + MergeSort(m, mply->move); + + if (depth!=localVar[thrId].iniDepth) + return m; + else { + m=AdjustMoveList(thrId); + return m; + } +} + + +int WeightAllocNT(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int thrId) { + 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; + for (int m=0; m<=3; m++) + aggr|=posPoint->rankInSuit[m][suit]; + int rRank=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; + + switch (posPoint->handRelFirst) { + case 0: + /*thirdBestHand=localVar[thrId].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 (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. */ + + suitWeightDelta=-((countLH+countRH)<<5)/19; + + if (posPoint->length[partner[q]][suit]==0) + suitWeightDelta+=-9; + + 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; + } + + 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; + } + + /* 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 (((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; + + /* Encourage playing cards that previously caused search cutoff + or was stored as the best move in a transposition table entry match. */ + + if ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=126; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=24; + } + else { + /* Discourage suit if RHO has winning or second best card. + Exception: RHO has singleton. */ + + if ((posPoint->winner[suit].hand==rho[q])|| + (posPoint->secondBest[suit].hand==rho[q])) { + if (suitCountRH!=1) + suitWeightDelta+=-10; + } + + + /* 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; + } + + /* 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. */ + + thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand; + + 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; + + /* 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+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+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. */ + + if ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=47; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=19; + } + + break; + + case 1: + leadSuit=posPoint->move[depth+1].suit; + if (leadSuit==suit) { + if (bitMapRank[mp->rank]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) + winMove=TRUE; + else if (posPoint->rankInSuit[rho[first]][suit]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) + winMove=TRUE; + } + else { + /* Side with highest rank in leadSuit wins */ + + if (posPoint->rankInSuit[rho[first]][leadSuit] > + (posPoint->rankInSuit[partner[first]][leadSuit] | + bitMapRank[posPoint->move[depth+1].rank])) + winMove=TRUE; + } + + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(23/*20*//*21*//*24*//*30*//*35*/); + if (posPoint->secondBest[suit].hand==q) { + /* Discourage suit discard if 2nd highest card becomes singleton. */ + + if (suitCount==2) + suitAdd+=-2; + } + /* Discourage suit discard of highest card. */ + + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd+=-3; + + /*Encourage discard of low cards in long suits. */ + weight=-4-(mp->rank)+suitAdd; + } + else { + weight=81/*80*/+rRank; + } + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/33; + + /* Discourage suit discard if 2nd highest card becomes singleton. */ + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd+=-6; + + /* Discourage suit discard of highest card. */ + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd+=-8; + + /*Encourage discard of low cards in long suits. */ + weight=2-(mp->rank)+suitAdd; + } + else { + + /* If lowest rank for either partner to leading hand + or rho is higher than played card for lho, + lho should play as low card as possible */ + + kk=posPoint->rankInSuit[partner[first]][leadSuit]; + ll=posPoint->rankInSuit[rho[first]][leadSuit]; + k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of + bit map ranks for partner and RHO. */ + + if ((k > bitMapRank[mp->rank])||(l > bitMapRank[mp->rank])) + weight=-3+rRank; + else if (mp->rank > posPoint->move[depth+1].rank) { + if (mp->sequence) { + weight=/*0*/10+rRank; + } + else { + weight=13-(mp->rank); + /*weight=-5+rRank;*/ + } + } + else { + weight=-11/*15*/+rRank; + } + } + } + + break; + + case 2: + + leadSuit=posPoint->move[depth+2].suit; + if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) { + if (bitMapRank[mp->rank] > + posPoint->rankInSuit[rho[first]][suit]) + winMove=TRUE; + } + else if (posPoint->high[depth+1]==first) { + if (posPoint->rankInSuit[rho[first]][leadSuit] + < bitMapRank[posPoint->move[depth+2].rank]) + winMove=TRUE; + + } + + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(17/*27*//*30*//*35*/); + + /* Discourage suit discard if 2nd highest card becomes singleton. */ + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(6/*2*//*5*/); + weight=-(mp->rank)+suitAdd; + } + else { + weight=60+rRank; + } + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(24/*26*//*29*//*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(4/*5*/); + /* Discourage suit discard of highest card. */ + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(4/*5*/); + + weight=-(mp->rank)+suitAdd; + + } + else { + + k=posPoint->rankInSuit[rho[first]][suit]; + if ((k & (-k)) > bitMapRank[mp->rank]) + weight=-(mp->rank); + else if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) { + if ((mp->rank==posPoint->secondBest[leadSuit].rank)&& + (mp->sequence)) + weight=25; + else if (mp->sequence) + weight=20-(mp->rank); + else + weight=10-(mp->rank); + } + else + weight=-10-(mp->rank); + } + } + + break; + + case 3: + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(27/*35*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(6/*5*/); + else if ((suitCount==1)&&(posPoint->winner[suit].hand==q)) + suitAdd-=(8/*9*//*8*//*5*/); + + weight=30-(mp->rank)+suitAdd; + } + else if ((posPoint->high[depth+1])==(lho[first])) { + /* If the current winning move is given by the partner */ + weight=30-(mp->rank); + } + else if (WinningMoveNT(mp, &(posPoint->move[depth+1]))) + /* If present move is superior to current winning move and the + current winning move is not given by the partner */ + weight=30-(mp->rank); + else { + /* If present move is not superior to current winning move and the + current winning move is not given by the partner */ + weight=14-(mp->rank); + } + } + return weight; +} + + + +int WeightAllocTrump(struct pos * posPoint, struct moveType * mp, int depth, + unsigned short notVoidInSuit, int trump, int thrId) { + 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; + int countLH, countRH; + + 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=localVar[thrId].rel[aggr].relRank[mp->rank][suit]; + + switch (posPoint->handRelFirst) { + case 0: + /*thirdBestHand=localVar[thrId].rel[aggr].absRank[3][suit].hand;*/ + suitCount=posPoint->length[q][suit]; + suitCountLH=posPoint->length[lho[q]][suit]; + suitCountRH=posPoint->length[rho[q]][suit]; + + /* Discourage suit if LHO or RHO can ruff. */ + + if ((suit!=trump) && + (((posPoint->rankInSuit[lho[q]][suit]==0) && + (posPoint->rankInSuit[lho[q]][trump]!=0)) || + ((posPoint->rankInSuit[rho[q]][suit]==0) && + (posPoint->rankInSuit[rho[q]][trump]!=0)))) + suitBonus=-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+=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+=-12/*13*//*11*/; + } + + /* 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) + suitBonus+=27/*25*//*30*/; + } + + /* Encourage play of suit where partner wins and + returns the suit for a ruff. */ + if ((suit!=trump)&&(suitCount==1)&& + (posPoint->length[q][trump]>0)&& + (posPoint->length[partner[q]][suit]>1)&& + (posPoint->winner[suit].hand==partner[q])) + suitBonus+=19/*26*//*23*/; + + if (suitCountLH!=0) + countLH=(suitCountLH<<2); + else + countLH=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. */ + + suitWeightDelta=suitBonus- + ((countLH+countRH)<<5)/13; + + if (posPoint->winner[suit].rank==mp->rank) { + if ((suit!=trump)) { + if ((posPoint->length[partner[first]][suit]!=0)|| + (posPoint->length[partner[first]][trump]==0)) { + if (((posPoint->length[lho[first]][suit]!=0)|| + (posPoint->length[lho[first]][trump]==0))&& + ((posPoint->length[rho[first]][suit]!=0)|| + (posPoint->length[rho[first]][trump]==0))) + winMove=TRUE; + } + else if (((posPoint->length[lho[first]][suit]!=0)|| + (posPoint->rankInSuit[partner[first]][trump]> + posPoint->rankInSuit[lho[first]][trump]))&& + ((posPoint->length[rho[first]][suit]!=0)|| + (posPoint->rankInSuit[partner[first]][trump]> + posPoint->rankInSuit[rho[first]][trump]))) + winMove=TRUE; + } + else + winMove=TRUE; + } + else if (posPoint->rankInSuit[partner[first]][suit] > + (posPoint->rankInSuit[lho[first]][suit] | + posPoint->rankInSuit[rho[first]][suit])) { + if (suit!=trump) { + if (((posPoint->length[lho[first]][suit]!=0)|| + (posPoint->length[lho[first]][trump]==0))&& + ((posPoint->length[rho[first]][suit]!=0)|| + (posPoint->length[rho[first]][trump]==0))) + winMove=TRUE; + } + else + winMove=TRUE; + } + else if (suit!=trump) { + if ((posPoint->length[partner[first]][suit]==0)&& + (posPoint->length[partner[first]][trump]!=0)) { + if ((posPoint->length[lho[first]][suit]==0)&& + (posPoint->length[lho[first]][trump]!=0)&& + (posPoint->length[rho[first]][suit]==0)&& + (posPoint->length[rho[first]][trump]!=0)) { + if (posPoint->rankInSuit[partner[first]][trump]> + (posPoint->rankInSuit[lho[first]][trump] | + posPoint->rankInSuit[rho[first]][trump])) + winMove=TRUE; + } + else if ((posPoint->length[lho[first]][suit]==0)&& + (posPoint->length[lho[first]][trump]!=0)) { + if (posPoint->rankInSuit[partner[first]][trump] + > posPoint->rankInSuit[lho[first]][trump]) + winMove=TRUE; + } + else if ((posPoint->length[rho[first]][suit]==0)&& + (posPoint->length[rho[first]][trump]!=0)) { + if (posPoint->rankInSuit[partner[first]][trump] + > posPoint->rankInSuit[rho[first]][trump]) + winMove=TRUE; + } + else + winMove=TRUE; + } + } + + if (winMove) { + + /* Encourage ruffing LHO or RHO singleton, highest card. */ + + if (((suitCountLH==1)&&(posPoint->winner[suit].hand==lho[first])) + ||((suitCountRH==1)&&(posPoint->winner[suit].hand==rho[first]))) + weight=suitWeightDelta+35/*37*//*39*/+rRank; + + /* Lead hand has the highest card. */ + + else if (posPoint->winner[suit].hand==first) { + + /* Also, partner has second highest card. */ + + if (posPoint->secondBest[suit].hand==partner[first]) + 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-3+rRank; + } + else if (posPoint->winner[suit].hand==partner[first]) { + /* If partner has highest card */ + if (posPoint->secondBest[suit].hand==first) + weight=suitWeightDelta+42/*35*//*46*//*50*/+rRank; + else + 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+40/*41*/; + else if (mp->sequence) + weight=suitWeightDelta+22/*17*/+rRank; + else + weight=suitWeightDelta+11+rRank; + + /* Encourage playing cards that previously caused search cutoff + or was stored as the best move in a transposition table entry match. */ + + if ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=55/*53*/; + else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=18/*14*/; + } + else { + + /* 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. */ + + thirdBestHand=localVar[thrId].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+=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/*-2*/; + else if (posPoint->winner[suit].hand==first) { + if (posPoint->secondBest[suit].hand==partner[first]) + + /* Opponents win by ruffing */ + + weight=suitWeightDelta+33+rRank; + else if (posPoint->winner[suit].rank==mp->rank) + + /* Opponents win by ruffing */ + + weight=suitWeightDelta+38/*36*/; + else + weight=suitWeightDelta-14/*17*/+rRank; + } + else if (posPoint->winner[suit].hand==partner[first]) { + + /* Opponents win by ruffing */ + + 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+35/*31*/; + else + 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 ((localVar[thrId].bestMove[depth].suit==suit)&& + (localVar[thrId].bestMove[depth].rank==mp->rank)) + weight+=18/*17*/; + /*else if ((localVar[thrId].bestMoveTT[depth].suit==suit)&& + (localVar[thrId].bestMoveTT[depth].rank==mp->rank)) + weight+=4;*/ + } + + break; + + case 1: + leadSuit=posPoint->move[depth+1].suit; + if (leadSuit==suit) { + if (bitMapRank[mp->rank]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) { + if (suit!=trump) { + if ((posPoint->length[partner[first]][suit]!=0)|| + (posPoint->length[partner[first]][trump]==0)) + winMove=TRUE; + else if ((posPoint->length[rho[first]][suit]==0) + &&(posPoint->length[rho[first]][trump]!=0) + &&(posPoint->rankInSuit[rho[first]][trump]> + posPoint->rankInSuit[partner[first]][trump])) + winMove=TRUE; + } + else + winMove=TRUE; + } + else if (posPoint->rankInSuit[rho[first]][suit]> + (bitMapRank[posPoint->move[depth+1].rank] | + posPoint->rankInSuit[partner[first]][suit])) { + if (suit!=trump) { + if ((posPoint->length[partner[first]][suit]!=0)|| + (posPoint->length[partner[first]][trump]==0)) + winMove=TRUE; + } + else + winMove=TRUE; + } + else if (bitMapRank[posPoint->move[depth+1].rank] > + (posPoint->rankInSuit[rho[first]][suit] | + posPoint->rankInSuit[partner[first]][suit] | + bitMapRank[mp->rank])) { + if (suit!=trump) { + if ((posPoint->length[rho[first]][suit]==0)&& + (posPoint->length[rho[first]][trump]!=0)) { + if ((posPoint->length[partner[first]][suit]!=0)|| + (posPoint->length[partner[first]][trump]==0)) + winMove=TRUE; + else if (posPoint->rankInSuit[rho[first]][trump] + > posPoint->rankInSuit[partner[first]][trump]) + winMove=TRUE; + } + } + } + else { /* winnerHand is partner to first */ + if (suit!=trump) { + if ((posPoint->length[rho[first]][suit]==0)&& + (posPoint->length[rho[first]][trump]!=0)) + winMove=TRUE; + } + } + } + else { + + /* Leading suit differs from suit played by LHO */ + + if (suit==trump) { + if (posPoint->length[partner[first]][leadSuit]!=0) + winMove=TRUE; + else if (bitMapRank[mp->rank]> + posPoint->rankInSuit[partner[first]][trump]) + winMove=TRUE; + else if ((posPoint->length[rho[first]][leadSuit]==0) + &&(posPoint->length[rho[first]][trump]!=0)&& + (posPoint->rankInSuit[rho[first]][trump] > + posPoint->rankInSuit[partner[first]][trump])) + winMove=TRUE; + } + else if (leadSuit!=trump) { + + /* Neither suit nor leadSuit is trump */ + + if (posPoint->length[partner[first]][leadSuit]!=0) { + if (posPoint->rankInSuit[rho[first]][leadSuit] > + (posPoint->rankInSuit[partner[first]][leadSuit] | + bitMapRank[posPoint->move[depth+1].rank])) + winMove=TRUE; + else if ((posPoint->length[rho[first]][leadSuit]==0) + &&(posPoint->length[rho[first]][trump]!=0)) + winMove=TRUE; + } + + /* Partner to leading hand is void in leading suit */ + + else if ((posPoint->length[rho[first]][leadSuit]==0) + &&(posPoint->rankInSuit[rho[first]][trump]> + posPoint->rankInSuit[partner[first]][trump])) + winMove=TRUE; + else if ((posPoint->length[partner[first]][trump]==0) + &&(posPoint->rankInSuit[rho[first]][leadSuit] > + bitMapRank[posPoint->move[depth+1].rank])) + winMove=TRUE; + } + else { + /* Either no trumps or leadSuit is trump, side with + highest rank in leadSuit wins */ + if (posPoint->rankInSuit[rho[first]][leadSuit] > + (posPoint->rankInSuit[partner[first]][leadSuit] | + bitMapRank[posPoint->move[depth+1].rank])) + winMove=TRUE; + } + } + + + kk=posPoint->rankInSuit[partner[first]][leadSuit]; + ll=posPoint->rankInSuit[rho[first]][leadSuit]; + k=kk & (-kk); l=ll & (-ll); /* Only least significant 1 bit of + bit map ranks for partner and RHO. */ + + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + 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 (suit==trump) + 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+rRank; + + /* If lowest card for partner to leading hand + is higher than lho played card, playing as low as + possible will give the cheapest win */ + + else if ((ll > bitMapRank[posPoint->move[depth+1].rank])&& + (posPoint->rankInSuit[first][leadSuit] > ll)) + weight=41+rRank; + + /* If rho has a card in the leading suit that + is higher than the trick leading card but lower + than the highest rank of the leading hand, then + lho playing the lowest card will be the cheapest + win */ + + else if (mp->rank > posPoint->move[depth+1].rank) { + if (bitMapRank[mp->rank] < ll) + weight=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=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-(mp->rank); + else + weight=49-(mp->rank); + } + } + else if (posPoint->length[rho[first]][leadSuit]>0) { + /*if (mp->sequence)*/ + weight=47-(mp->rank); /* Playing a card in a sequence may promote a winner */ + /* Insensistive */ + /*else + weight=47-(mp->rank);*/ + } + else + weight=40-(mp->rank); + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/36; + + /* Discourage suit discard if 2nd highest card becomes singleton. */ + + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd+=-4; + + if (suit==trump) { + weight=15-(mp->rank)+suitAdd; /* Ruffing is preferred, makes the trick + costly for the opponents */ + } + else + weight=-2-(mp->rank)+suitAdd; + } + else if ((k > bitMapRank[mp->rank])|| + (l > bitMapRank[mp->rank])) + weight=-9+rRank; + + /* If lowest rank for either partner to leading hand + or rho is higher than played card for lho, + lho should play as low card as possible */ + + else if (mp->rank > posPoint->move[depth+1].rank) { + if (mp->sequence) + weight=22-(mp->rank); + else + weight=10-(mp->rank); + } + else + weight=-16+rRank; + } + break; + + case 2: + + leadSuit=posPoint->move[depth+2].suit; + if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) { + if (suit==leadSuit) { + if (leadSuit!=trump) { + if (((posPoint->length[rho[first]][suit]!=0)|| + (posPoint->length[rho[first]][trump]==0))&& + (bitMapRank[mp->rank] > + posPoint->rankInSuit[rho[first]][suit])) + winMove=TRUE; + } + else if (bitMapRank[mp->rank] > + posPoint->rankInSuit[rho[first]][suit]) + winMove=TRUE; + } + else { /* Suit is trump */ + if (posPoint->length[rho[first]][leadSuit]==0) { + if (bitMapRank[mp->rank] > + posPoint->rankInSuit[rho[first]][trump]) + winMove=TRUE; + } + else + winMove=TRUE; + } + } + else if (posPoint->high[depth+1]==first) { + if (posPoint->length[rho[first]][leadSuit]!=0) { + if (posPoint->rankInSuit[rho[first]][leadSuit] + < bitMapRank[posPoint->move[depth+2].rank]) + winMove=TRUE; + } + else if (leadSuit==trump) + winMove=TRUE; + else if ((leadSuit!=trump) && + (posPoint->length[rho[first]][trump]==0)) + winMove=TRUE; + } + + if (winMove) { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(50/*36*/); + + /* Discourage suit discard if 2nd highest card becomes singleton. */ + + /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(3);*/ + + if (posPoint->high[depth+1]==first) { + if (suit==trump) + weight=48-(mp->rank)+suitAdd; /* Ruffs partner's winner */ + else + weight=61-(mp->rank)+suitAdd; + } + else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) + + /* Own hand on top by ruffing */ + + weight=72-(mp->rank)+suitAdd; + } + else + weight=58-(mp->rank); + } + else { + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/40; + + /* Discourage suit discard if 2nd highest card becomes singleton. */ + + /*if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(4);*/ + + if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) + + /* Own hand on top by ruffing */ + + weight=40-(mp->rank)+suitAdd; + else if (suit==trump) + + /* Discard a trump but still losing */ + + weight=-32+rRank+suitAdd; + else + weight=-2-(mp->rank)+suitAdd; + } + else { + k=posPoint->rankInSuit[rho[first]][suit]; + if ((k & (-k)) > bitMapRank[mp->rank]) + + /* If least bit map rank of RHO to lead hand is higher than bit map rank + of current card move. */ + + weight=-3-(mp->rank); + + else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) { + + /* If current card move is highest so far. */ + + if (mp->rank==posPoint->secondBest[leadSuit].rank) + weight=29; + else if (mp->sequence) + weight=26/*20*/-(mp->rank); + else + weight=18-(mp->rank); + } + else + weight=-12-(mp->rank); + } + } + + break; + + case 3: + if (!notVoidInSuit) { + suitCount=posPoint->length[q][suit]; + suitAdd=(suitCount<<6)/(24/*36*/); + if ((suitCount==2)&&(posPoint->secondBest[suit].hand==q)) + suitAdd-=(2); + + if ((posPoint->high[depth+1])==lho[first]) { + + /* If the current winning move is given by the partner */ + + if (suit==trump) + + /* Ruffing partners winner? */ + + weight=2/*17*/-(mp->rank)+suitAdd; + else + weight=25-(mp->rank)+suitAdd; + } + else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) + + /* Own hand ruffs */ + + weight=33/*27*/+rRank+suitAdd; + else if (suit==trump) + weight=-13+rRank; + else + weight=14-(mp->rank)+suitAdd; + } + else if ((posPoint->high[depth+1])==(lho[first])) { + + /* If the current winning move is given by the partner */ + + if (suit==trump) + + /* Ruffs partners winner */ + + weight=11+rRank; + else + weight=17+rRank; + } + else if (WinningMove(mp, &(posPoint->move[depth+1]),trump)) + + /* If present move is superior to current winning move and the + current winning move is not given by the partner */ + + weight=22+rRank; + else { + + /* If present move is not superior to current winning move and the + current winning move is not given by the partner */ + + if (suit==trump) + + /* Ruffs but still loses */ + + weight=-13+rRank; + else + weight=1+rRank; + } + } + return weight; +} + + +/* Shell-1 */ +/* K&R page 62: */ +/*void shellSort(int n, int depth) { + int gap, i, j; + struct moveType temp; + + if (n==2) { + if (movePly[depth].move[0].weight>1; gap>0; gap>>=1) + for (i=gap; i=0 && movePly[depth].move[j].weight< + movePly[depth].move[j+gap].weight; j-=gap) { + temp=movePly[depth].move[j]; + movePly[depth].move[j]=movePly[depth].move[j+gap]; + movePly[depth].move[j+gap]=temp; + } +} */ + +/* Shell-2 */ +/*void shellSort(int n, int depth) +{ + int i, j, increment; + struct moveType temp; + + if (n==2) { + if (movePly[depth].move[0].weight 0) + { + for (i=0; i < n; i++) + { + j = i; + temp = movePly[depth].move[i]; + while ((j >= increment) && (movePly[depth].move[j-increment].weight < temp.weight)) + { + movePly[depth].move[j] = movePly[depth].move[j - increment]; + j = j - increment; + } + movePly[depth].move[j] = temp; + } + if ((increment>>1) != 0) + increment>>=1; + else if (increment == 1) + increment = 0; + else + increment = 1; + } +} */ + + +/* Insert-1 */ +/*void InsertSort(int n, int depth, struct movePlyType *mply, int thrId) { + int i, j; + struct moveType a, temp; + + if (n==2) { + if (mply->move[0].weightmove[1].weight) { + temp=mply->move[0]; + mply->move[0]=mply->move[1]; + mply->move[1]=temp; + return; + } + else + return; + } + + a=mply->move[0]; + for (i=1; i<=n-1; i++) + if (mply->move[i].weight>a.weight) { + temp=a; + a=mply->move[i]; + mply->move[i]=temp; + } + mply->move[0]=a; + for (i=2; i<=n-1; i++) { + j=i; + a=mply->move[i]; + while (a.weight>mply->move[j-1].weight) { + mply->move[j]=mply->move[j-1]; + j--; + } + mply->move[j]=a; + } +} */ + + +/* Insert-2 */ +/*void InsertSort(int n, int depth) { + int i, j; + struct moveType a; + + if (n==2) { + if (movePly[depth].move[0].weight=0)&&(movePly[depth].move[i].weight a[j - 1].weight ; --j) + a[j] = a[j - 1]; + a[j] = tmp; + } + } + + return; +} + + + +int AdjustMoveList(int thrId) { + int k, r, n, rank, suit; + + for (k=1; k<=13; k++) { + suit=localVar[thrId].forbiddenMoves[k].suit; + rank=localVar[thrId].forbiddenMoves[k].rank; + for (r=0; r<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; r++) { + if ((suit==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].suit)&& + (rank!=0)&&(rank==localVar[thrId].movePly[localVar[thrId].iniDepth].move[r].rank)) { + /* For the forbidden move r: */ + for (n=r; n<=localVar[thrId].movePly[localVar[thrId].iniDepth].last; n++) + localVar[thrId].movePly[localVar[thrId].iniDepth].move[n]= + localVar[thrId].movePly[localVar[thrId].iniDepth].move[n+1]; + localVar[thrId].movePly[localVar[thrId].iniDepth].last--; + } + } + } + return localVar[thrId].movePly[localVar[thrId].iniDepth].last+1; +} + + +int InvBitMapRank(unsigned short bitMap) { + + switch (bitMap) { + case 0x1000: return 14; + case 0x0800: return 13; + case 0x0400: return 12; + case 0x0200: return 11; + case 0x0100: return 10; + case 0x0080: return 9; + case 0x0040: return 8; + case 0x0020: return 7; + case 0x0010: return 6; + case 0x0008: return 5; + case 0x0004: return 4; + case 0x0002: return 3; + case 0x0001: return 2; + default: return 0; + } +} + +int InvWinMask(int mask) { + + switch (mask) { + case 0x01000000: return 1; + case 0x00400000: return 2; + case 0x00100000: return 3; + case 0x00040000: return 4; + case 0x00010000: return 5; + case 0x00004000: return 6; + case 0x00001000: return 7; + case 0x00000400: return 8; + case 0x00000100: return 9; + case 0x00000040: return 10; + case 0x00000010: return 11; + case 0x00000004: return 12; + case 0x00000001: return 13; + default: return 0; + } +} + + +inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump) { +/* Return TRUE if move 1 wins over move 2, with the assumption that +move 2 is the presently winning card of the trick */ + + if (mvp1->suit==mvp2->suit) { + if ((mvp1->rank)>(mvp2->rank)) + return TRUE; + else + return FALSE; + } + else if ((mvp1->suit)==trump) + return TRUE; + else + return FALSE; +} + + +inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2) { +/* Return TRUE if move 1 wins over move 2, with the assumption that +move 2 is the presently winning card of the trick */ + + if (mvp1->suit==mvp2->suit) { + if ((mvp1->rank)>(mvp2->rank)) + return TRUE; + else + return FALSE; + } + else + return FALSE; +} + + +struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType + * nodep, int target, int tricks, int * result, int *value, int thrId) { + /* Check SOP if it matches the + current position. If match, pointer to the SOP node is returned and + result is set to TRUE, otherwise pointer to SOP node is returned + and result set to FALSE. */ + + /* 07-04-22 */ + if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { + if (nodep->lbound==-1) { /* This bound values for + this leading hand has not yet been determined */ + *result=FALSE; + return nodep; + } + else if ((posPoint->tricksMAX + nodep->lbound)>=target) { + *value=TRUE; + *result=TRUE; + return nodep; + } + else if ((posPoint->tricksMAX + nodep->ubound)ubound==-1) { /* This bound values for + this leading hand has not yet been determined */ + *result=FALSE; + return nodep; + } + else if ((posPoint->tricksMAX + (tricks + 1 - nodep->ubound))>=target) { + *value=TRUE; + *result=TRUE; + return nodep; + } + else if ((posPoint->tricksMAX + (tricks + 1 - nodep->lbound))lbound > nodep->lbound) || + (nodep->lbound==-1)) + nodep->lbound=posPoint->lbound; + if ((posPoint->ubound < nodep->ubound) || + (nodep->ubound==-1)) + nodep->ubound=posPoint->ubound; + + nodep->bestMoveSuit=posPoint->bestMoveSuit; + nodep->bestMoveRank=posPoint->bestMoveRank; + + return nodep; +} + + +struct nodeCardsType * FindSOP(struct pos * posPoint, + struct winCardType * nodeP, int firstHand, + int target, int tricks, int * valp, int thrId) { + struct nodeCardsType * sopP; + struct winCardType * np; + int res; + + np=nodeP; + int s=0; + while ((np!=NULL)&&(s<4)) { + if ((np->winMask & posPoint->orderSet[s])== + np->orderSet) { + /* Winning rank set fits position */ + if (s==3) { + sopP=CheckSOP(posPoint, np->first, target, tricks, &res, valp, thrId); + if (res) { + return sopP; + } + else { + if (np->next!=NULL) { + np=np->next; + } + else { + np=np->prevWin; + s--; + if (np==NULL) + return NULL; + while (np->next==NULL) { + np=np->prevWin; + s--; + if (np==NULL) /* Previous node is header node? */ + return NULL; + } + np=np->next; + } + } + } + else if (s<4) { + np=np->nextWin; + s++; + } + } + else { + if (np->next!=NULL) { + np=np->next; + } + else { + np=np->prevWin; + s--; + if (np==NULL) + return NULL; + while (np->next==NULL) { + np=np->prevWin; + s--; + if (np==NULL) /* Previous node is header node? */ + return NULL; + } + np=np->next; + } + } + } + return NULL; +} + + +struct nodeCardsType * BuildPath(struct pos * posPoint, + struct posSearchType *nodep, int * result, int thrId) { + /* If result is TRUE, a new SOP has been created and BuildPath returns a + pointer to it. If result is FALSE, an existing SOP is used and BuildPath + returns a pointer to the SOP */ + + int found; + struct winCardType * np, * p2, /* * sp2,*/ * nprev, * fnp, *pnp; + struct winCardType temp; + struct nodeCardsType * sopP=0, * p/*, * sp*/; + + np=nodep->posSearchPoint; + nprev=NULL; + int suit=0; + + /* If winning node has a card that equals the next winning card deduced + from the position, then there already exists a (partial) path */ + + if (np==NULL) { /* There is no winning list created yet */ + /* Create winning nodes */ + p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; + AddWinSet(thrId); + p2->next=NULL; + p2->nextWin=NULL; + p2->prevWin=NULL; + nodep->posSearchPoint=p2; + p2->winMask=posPoint->winMask[suit]; + p2->orderSet=posPoint->winOrderSet[suit]; + p2->first=NULL; + np=p2; /* Latest winning node */ + suit++; + while (suit<4) { + p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; + AddWinSet(thrId); + np->nextWin=p2; + p2->prevWin=np; + p2->next=NULL; + p2->nextWin=NULL; + p2->winMask=posPoint->winMask[suit]; + p2->orderSet=posPoint->winOrderSet[suit]; + p2->first=NULL; + np=p2; /* Latest winning node */ + suit++; + } + p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; + AddNodeSet(thrId); + np->first=p; + *result=TRUE; + return p; + } + else { /* Winning list exists */ + while (1) { /* Find all winning nodes that correspond to current + position */ + found=FALSE; + while (1) { /* Find node amongst alternatives */ + if ((np->winMask==posPoint->winMask[suit])&& + (np->orderSet==posPoint->winOrderSet[suit])) { + /* Part of path found */ + found=TRUE; + nprev=np; + break; + } + if (np->next!=NULL) + np=np->next; + else + break; + } + if (found) { + suit++; + if (suit>3) { + sopP=UpdateSOP(posPoint, np->first); + + if (np->prevWin!=NULL) { + pnp=np->prevWin; + fnp=pnp->nextWin; + } + else + fnp=nodep->posSearchPoint; + + temp.orderSet=np->orderSet; + temp.winMask=np->winMask; + temp.first=np->first; + temp.nextWin=np->nextWin; + np->orderSet=fnp->orderSet; + np->winMask=fnp->winMask; + np->first=fnp->first; + np->nextWin=fnp->nextWin; + fnp->orderSet=temp.orderSet; + fnp->winMask=temp.winMask; + fnp->first=temp.first; + fnp->nextWin=temp.nextWin; + + *result=FALSE; + return sopP; + } + else { + np=np->nextWin; /* Find next winning node */ + continue; + } + } + else + break; /* Node was not found */ + } /* End outer while */ + + /* Create additional node, coupled to existing node(s) */ + p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; + AddWinSet(thrId); + p2->prevWin=nprev; + if (nprev!=NULL) { + p2->next=nprev->nextWin; + nprev->nextWin=p2; + } + else { + p2->next=nodep->posSearchPoint; + nodep->posSearchPoint=p2; + } + p2->nextWin=NULL; + p2->winMask=posPoint->winMask[suit]; + p2->orderSet=posPoint->winOrderSet[suit]; + p2->first=NULL; + np=p2; /* Latest winning node */ + suit++; + + /* Rest of path must be created */ + while (suit<4) { + p2=&localVar[thrId].winCards[localVar[thrId].winSetSize]; + AddWinSet(thrId); + np->nextWin=p2; + p2->prevWin=np; + p2->next=NULL; + p2->winMask=posPoint->winMask[suit]; + p2->orderSet=posPoint->winOrderSet[suit]; + p2->first=NULL; + p2->nextWin=NULL; + np=p2; /* Latest winning node */ + suit++; + } + + /* All winning nodes in SOP have been traversed and new nodes created */ + p=&localVar[thrId].nodeCards[localVar[thrId].nodeSetSize]; + AddNodeSet(thrId); + np->first=p; + *result=TRUE; + return p; + } +} + + +struct posSearchType * SearchLenAndInsert(struct posSearchType + * rootp, long long key, int insertNode, int *result, int thrId) { +/* Search for node which matches with the suit length combination + given by parameter key. If no such node is found, NULL is + returned if parameter insertNode is FALSE, otherwise a new + node is inserted with suitLengths set to key, the pointer to + this node is returned. + The algorithm used is defined in Knuth "The art of computer + programming", vol.3 "Sorting and searching", 6.2.2 Algorithm T, + page 424. */ + + struct posSearchType *np, *p, *sp; + + if (insertNode) + sp=&localVar[thrId].posSearch[localVar[thrId].lenSetSize]; + + np=rootp; + while (1) { + if (key==np->suitLengths) { + *result=TRUE; + return np; + } + else if (key < np->suitLengths) { + if (np->left!=NULL) + np=np->left; + else if (insertNode) { + p=sp; + AddLenSet(thrId); + np->left=p; + p->posSearchPoint=NULL; + p->suitLengths=key; + p->left=NULL; p->right=NULL; + *result=TRUE; + return p; + } + else { + *result=FALSE; + return NULL; + } + } + else { /* key > suitLengths */ + if (np->right!=NULL) + np=np->right; + else if (insertNode) { + p=sp; + AddLenSet(thrId); + np->right=p; + p->posSearchPoint=NULL; + p->suitLengths=key; + p->left=NULL; p->right=NULL; + *result=TRUE; + return p; + } + else { + *result=FALSE; + return NULL; + } + } + } +} + + + +void BuildSOP(struct pos * posPoint, long long suitLengths, int tricks, int firstHand, int target, + int depth, int scoreFlag, int score, int thrId) { + int hh, res, wm; + unsigned short int w; + unsigned short int temp[4][4]; + unsigned short int aggr[4]; + struct nodeCardsType * cardsP; + struct posSearchType * np; + +#ifdef TTDEBUG + int k, mcurrent, rr; + mcurrent=localVar[thrId].movePly[depth].current; +#endif + + for (int ss=0; ss<=3; ss++) { + w=posPoint->winRanks[depth][ss]; + if (w==0) { + posPoint->winMask[ss]=0; + posPoint->winOrderSet[ss]=0; + posPoint->leastWin[ss]=0; + for (hh=0; hh<=3; hh++) + temp[hh][ss]=0; + } + else { + w=w & (-w); /* Only lowest win */ + for (hh=0; hh<=3; hh++) + temp[hh][ss]=posPoint->rankInSuit[hh][ss] & (-w); + + aggr[ss]=0; + for (hh=0; hh<=3; hh++) + aggr[ss]|=temp[hh][ss]; + posPoint->winMask[ss]=localVar[thrId].rel[aggr[ss]].winMask[ss]; + posPoint->winOrderSet[ss]=localVar[thrId].rel[aggr[ss]].aggrRanks[ss]; + wm=posPoint->winMask[ss]; + wm=wm & (-wm); + posPoint->leastWin[ss]=InvWinMask(wm); + } + } + + /* 07-04-22 */ + if (scoreFlag) { + if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { + posPoint->ubound=tricks+1; + posPoint->lbound=target-posPoint->tricksMAX; + } + else { + posPoint->ubound=tricks+1-target+posPoint->tricksMAX; + posPoint->lbound=0; + } + } + else { + if (localVar[thrId].nodeTypeStore[0]==MAXNODE) { + posPoint->ubound=target-posPoint->tricksMAX-1; + posPoint->lbound=0; + } + else { + posPoint->ubound=tricks+1; + posPoint->lbound=tricks+1-target+posPoint->tricksMAX+1; + } + } + + /*long long suitLengths=0; + for (int s=0; s<=2; s++) + for (hh=0; hh<=3; hh++) { + suitLengths<<=4; + suitLengths|=posPoint->length[hh][s]; + }*/ + + np=SearchLenAndInsert(localVar[thrId].rootnp[tricks][firstHand], + suitLengths, TRUE, &res, thrId); + + cardsP=BuildPath(posPoint, np, &res, thrId); + if (res) { + cardsP->ubound=posPoint->ubound; + cardsP->lbound=posPoint->lbound; + if (((localVar[thrId].nodeTypeStore[firstHand]==MAXNODE)&&(scoreFlag))|| + ((localVar[thrId].nodeTypeStore[firstHand]==MINNODE)&&(!scoreFlag))) { + cardsP->bestMoveSuit=localVar[thrId].bestMove[depth].suit; + cardsP->bestMoveRank=localVar[thrId].bestMove[depth].rank; + } + else { + cardsP->bestMoveSuit=0; + cardsP->bestMoveRank=0; + } + posPoint->bestMoveSuit=localVar[thrId].bestMove[depth].suit; + posPoint->bestMoveRank=localVar[thrId].bestMove[depth].rank; + for (int k=0; k<=3; k++) + cardsP->leastWin[k]=posPoint->leastWin[k]; + } + + #ifdef STAT + c9[depth]++; + #endif + + #ifdef TTDEBUG + if ((res) && (ttCollect) && (!suppressTTlog)) { + fprintf(localVar[thrId].fp7, "cardsP=%d\n", (int)cardsP); + fprintf(localVar[thrId].fp7, "nodeSetSize=%d\n", localVar[thrId].nodeSetSize); + fprintf(localVar[thrId].fp7, "ubound=%d\n", cardsP->ubound); + fprintf(localVar[thrId].fp7, "lbound=%d\n", cardsP->lbound); + fprintf(localVar[thrId].fp7, "target=%d\n", target); + fprintf(localVar[thrId].fp7, "first=%c nextFirst=%c\n", + cardHand[posPoint->first[depth]], cardHand[posPoint->first[depth-1]]); + fprintf(localVar[thrId].fp7, "bestMove: suit=%c rank=%c\n", cardSuit[localVar[thrId].bestMove[depth].suit], + cardRank[localVar[thrId].bestMove[depth].rank]); + fprintf(localVar[thrId].fp7, "\n"); + fprintf(localVar[thrId].fp7, "Last trick:\n"); + fprintf(localVar[thrId].fp7, "1st hand=%c\n", cardHand[posPoint->first[depth+3]]); + for (k=3; k>=0; k--) { + mcurrent=localVar[thrId].movePly[depth+k+1].current; + fprintf(localVar[thrId].fp7, "suit=%c rank=%c\n", + cardSuit[localVar[thrId].movePly[depth+k+1].move[mcurrent].suit], + cardRank[localVar[thrId].movePly[depth+k+1].move[mcurrent].rank]); + } + fprintf(localVar[thrId].fp7, "\n"); + for (hh=0; hh<=3; hh++) { + fprintf(localVar[thrId].fp7, "hand=%c\n", cardHand[hh]); + for (ss=0; ss<=3; ss++) { + fprintf(localVar[thrId].fp7, "suit=%c", cardSuit[ss]); + for (rr=14; rr>=2; rr--) + if (posPoint->rankInSuit[hh][ss] & bitMapRank[rr]) + fprintf(localVar[thrId].fp7, " %c", cardRank[rr]); + fprintf(localVar[thrId].fp7, "\n"); + } + fprintf(localVar[thrId].fp7, "\n"); + } + fprintf(localVar[thrId].fp7, "\n"); + } + #endif +} + + +int CheckDeal(struct moveType * cardp, int thrId) { + int h, s, k, found; + unsigned short int temp[4][4]; + + for (h=0; h<=3; h++) + for (s=0; s<=3; s++) + temp[h][s]=localVar[thrId].game.suit[h][s]; + + /* Check that all ranks appear only once within the same suit. */ + for (s=0; s<=3; s++) + for (k=2; k<=14; k++) { + found=FALSE; + for (h=0; h<=3; h++) { + if ((temp[h][s] & bitMapRank[k])!=0) { + if (found) { + cardp->suit=s; + cardp->rank=k; + return 1; + } + else + found=TRUE; + } + } + } + + return 0; +} + + +int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId) { + /* Returns TRUE if at least one move remains to be + searched, otherwise FALSE is returned. */ + + unsigned short int lw; + int suit; + struct moveType currMove=mply->move[mply->current]; + + if (localVar[thrId].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] >= + localVar[thrId].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] >= + localVar[thrId].lowestWin[depth][suit])) + return TRUE; + } + return FALSE; + } + } + else { + while (mply->current<=(mply->last-1)) { + mply->current++; + if (bitMapRank[mply->move[mply->current].rank] >= + localVar[thrId].lowestWin[depth][mply->move[mply->current].suit]) + return TRUE; + } + return FALSE; + } +} + + +int DumpInput(int errCode, struct deal dl, int target, + int solutions, int mode) { + + FILE *fp; + int i, j, k; + unsigned short ranks[4][4]; + + fp=fopen("dump.txt", "w"); + if (fp==NULL) + return -1; + fprintf(fp, "Error code=%d\n", errCode); + fprintf(fp, "\n"); + fprintf(fp, "Deal data:\n"); + if (dl.trump!=4) + fprintf(fp, "trump=%c\n", cardSuit[dl.trump]); + else + fprintf(fp, "trump=N\n"); + fprintf(fp, "first=%c\n", cardHand[dl.first]); + for (k=0; k<=2; k++) + if (dl.currentTrickRank[k]!=0) + fprintf(fp, "index=%d currentTrickSuit=%c currentTrickRank=%c\n", + k, cardSuit[dl.currentTrickSuit[k]], cardRank[dl.currentTrickRank[k]]); + for (i=0; i<=3; i++) + for (j=0; j<=3; j++) { + fprintf(fp, "index1=%d index2=%d remainCards=%d\n", + i, j, dl.remainCards[i][j]); + ranks[i][j]=dl.remainCards[i][/*3-*/j]>>2; + } + fprintf(fp, "\n"); + fprintf(fp, "target=%d\n", target); + fprintf(fp, "solutions=%d\n", solutions); + fprintf(fp, "mode=%d\n", mode); + fprintf(fp, "\n"); + PrintDeal(fp, ranks); + fclose(fp); + return 0; +} + +void PrintDeal(FILE *fp, unsigned short ranks[][4]) { + int i, count, ec[4], trickCount=0, s, r; + for (i=0; i<=3; i++) { + count=counttable[ranks[3][i]]; + if (count>5) + ec[i]=TRUE; + else + ec[i]=FALSE; + trickCount=trickCount+count; + } + fprintf(fp, "\n"); + for (s=0; s<=3; s++) { + fprintf(fp, "\t%c ", cardSuit[s]); + if (!ranks[0][s]) + fprintf(fp, "--"); + else { + for (r=14; r>=2; r--) + if ((ranks[0][s] & bitMapRank[r])!=0) + fprintf(fp, "%c", cardRank[r]); + } + fprintf(fp, "\n"); + } + for (s=0; s<=3; s++) { + fprintf(fp, "%c ", cardSuit[s]); + if (!ranks[3][s]) + fprintf(fp, "--"); + else { + for (r=14; r>=2; r--) + if ((ranks[3][s] & bitMapRank[r])!=0) + fprintf(fp, "%c", cardRank[r]); + } + if (ec[s]) + fprintf(fp, "\t\%c ", cardSuit[s]); + else + fprintf(fp, "\t\t\%c ", cardSuit[s]); + if (!ranks[1][s]) + fprintf(fp, "--"); + else { + for (r=14; r>=2; r--) + if ((ranks[1][s] & bitMapRank[r])!=0) + fprintf(fp, "%c", cardRank[r]); + } + fprintf(fp, "\n"); + } + for (s=0; s<=3; s++) { + fprintf(fp, "\t%c ", cardSuit[s]); + if (!ranks[2][s]) + fprintf(fp, "--"); + else { + for (r=14; r>=2; r--) + if ((ranks[2][s] & bitMapRank[r])!=0) + fprintf(fp, "%c", cardRank[r]); + } + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + return; +} + + + +void Wipe(int thrId) { + int k; + + for (k=1; k<=localVar[thrId].wcount; k++) { + if (localVar[thrId].pw[k]) + free(localVar[thrId].pw[k]); + localVar[thrId].pw[k]=NULL; + } + for (k=1; k<=localVar[thrId].ncount; k++) { + if (localVar[thrId].pn[k]) + free(localVar[thrId].pn[k]); + localVar[thrId].pn[k]=NULL; + } + for (k=1; k<=localVar[thrId].lcount; k++) { + if (localVar[thrId].pl[k]) + free(localVar[thrId].pl[k]); + localVar[thrId].pl[k]=NULL; + } + + localVar[thrId].allocmem=localVar[thrId].summem; + + return; +} + + +void AddWinSet(int thrId) { + if (localVar[thrId].clearTTflag) { + localVar[thrId].windex++; + localVar[thrId].winSetSize=localVar[thrId].windex; + /*localVar[thrId].fp2=fopen("dyn.txt", "a"); + fprintf(localVar[thrId].fp2, "windex=%d\n", windex); + fclose(localVar[thrId].fp2);*/ + localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; + } + else if (localVar[thrId].winSetSize>=localVar[thrId].winSetSizeLimit) { + /* The memory chunk for the winCards structure will be exceeded. */ + if ((localVar[thrId].allocmem+localVar[thrId].wmem)>localVar[thrId].maxmem) { + /* Already allocated memory plus needed allocation overshot maxmem */ + localVar[thrId].windex++; + localVar[thrId].winSetSize=localVar[thrId].windex; + /*localVar[thrId].fp2=fopen("dyn.txt", "a"); + fprintf(localVar[thrId].fp2, "windex=%d\n", windex); + fclose(localVar[thrId].fp2);*/ + localVar[thrId].clearTTflag=TRUE; + localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; + } + else { + localVar[thrId].wcount++; localVar[thrId].winSetSizeLimit=WSIZE; + localVar[thrId].pw[localVar[thrId].wcount] = + (struct winCardType *)calloc(localVar[thrId].winSetSizeLimit+1, sizeof(struct winCardType)); + if (localVar[thrId].pw[localVar[thrId].wcount]==NULL) { + localVar[thrId].clearTTflag=TRUE; + localVar[thrId].windex++; + localVar[thrId].winSetSize=localVar[thrId].windex; + localVar[thrId].winCards=&localVar[thrId].temp_win[localVar[thrId].windex]; + } + else { + localVar[thrId].allocmem+=(localVar[thrId].winSetSizeLimit+1)*sizeof(struct winCardType); + localVar[thrId].winSetSize=0; + localVar[thrId].winCards=localVar[thrId].pw[localVar[thrId].wcount]; + } + } + } + else + localVar[thrId].winSetSize++; + return; +} + +void AddNodeSet(int thrId) { + if (localVar[thrId].nodeSetSize>=localVar[thrId].nodeSetSizeLimit) { + /* The memory chunk for the nodeCards structure will be exceeded. */ + if ((localVar[thrId].allocmem+localVar[thrId].nmem)>localVar[thrId].maxmem) { + /* Already allocated memory plus needed allocation overshot maxmem */ + localVar[thrId].clearTTflag=TRUE; + } + else { + localVar[thrId].ncount++; localVar[thrId].nodeSetSizeLimit=NSIZE; + localVar[thrId].pn[localVar[thrId].ncount] = (struct nodeCardsType *)calloc(localVar[thrId].nodeSetSizeLimit+1, sizeof(struct nodeCardsType)); + if (localVar[thrId].pn[localVar[thrId].ncount]==NULL) { + localVar[thrId].clearTTflag=TRUE; + } + else { + localVar[thrId].allocmem+=(localVar[thrId].nodeSetSizeLimit+1)*sizeof(struct nodeCardsType); + localVar[thrId].nodeSetSize=0; + localVar[thrId].nodeCards=localVar[thrId].pn[localVar[thrId].ncount]; + } + } + } + else + localVar[thrId].nodeSetSize++; + return; +} + +void AddLenSet(int thrId) { + if (localVar[thrId].lenSetSize>=localVar[thrId].lenSetSizeLimit) { + /* The memory chunk for the posSearchType structure will be exceeded. */ + if ((localVar[thrId].allocmem+localVar[thrId].lmem)>localVar[thrId].maxmem) { + /* Already allocated memory plus needed allocation overshot maxmem */ + localVar[thrId].clearTTflag=TRUE; + } + else { + localVar[thrId].lcount++; localVar[thrId].lenSetSizeLimit=LSIZE; + localVar[thrId].pl[localVar[thrId].lcount] = (struct posSearchType *)calloc(localVar[thrId].lenSetSizeLimit+1, sizeof(struct posSearchType)); + if (localVar[thrId].pl[localVar[thrId].lcount]==NULL) { + localVar[thrId].clearTTflag=TRUE; + } + else { + localVar[thrId].allocmem+=(localVar[thrId].lenSetSizeLimit+1)*sizeof(struct posSearchType); + localVar[thrId].lenSetSize=0; + localVar[thrId].posSearch=localVar[thrId].pl[localVar[thrId].lcount]; + } + } + } + else + localVar[thrId].lenSetSize++; + return; +} + + + +#ifdef TTDEBUG + +void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, + int target, int depth, int thrId) { + int tricksLeft, hh, ss, rr; +/* Stores current position information and TT position value in table + ttStore with current entry lastTTStore. Also stores corresponding + information in log rectt.txt. */ + tricksLeft=0; + for (hh=0; hh<=3; hh++) + for (ss=0; ss<=3; ss++) + tricksLeft+=posPoint->length[hh][ss]; + tricksLeft=tricksLeft/4; + ttStore[lastTTstore].tricksLeft=tricksLeft; + ttStore[lastTTstore].cardsP=cardsP; + ttStore[lastTTstore].first=posPoint->first[depth]; + if ((localVar[thrId].handToPlay==posPoint->first[depth])|| + (localVar[thrId].handToPlay==partner[posPoint->first[depth]])) { + ttStore[lastTTstore].target=target-posPoint->tricksMAX; + ttStore[lastTTstore].ubound=cardsP->ubound; + ttStore[lastTTstore].lbound=cardsP->lbound; + } + else { + ttStore[lastTTstore].target=tricksLeft- + target+posPoint->tricksMAX+1; + } + for (hh=0; hh<=3; hh++) + for (ss=0; ss<=3; ss++) + ttStore[lastTTstore].suit[hh][ss]= + posPoint->rankInSuit[hh][ss]; + localVar[thrId].fp11=fopen("rectt.txt", "a"); + if (lastTTstoretricksMAX); + fprintf(localVar[thrId].fp11, "leftTricks=%d\n", + ttStore[lastTTstore].tricksLeft); + fprintf(localVar[thrId].fp11, "cardsP=%d\n", + ttStore[lastTTstore].cardsP); + fprintf(localVar[thrId].fp11, "ubound=%d\n", + ttStore[lastTTstore].ubound); + fprintf(localVar[thrId].fp11, "lbound=%d\n", + ttStore[lastTTstore].lbound); + fprintf(localVar[thrId].fp11, "first=%c\n", + cardHand[ttStore[lastTTstore].first]); + fprintf(localVar[thrId].fp11, "target=%d\n", + ttStore[lastTTstore].target); + fprintf(localVar[thrId].fp11, "\n"); + for (hh=0; hh<=3; hh++) { + fprintf(localVar[thrId].fp11, "hand=%c\n", cardHand[hh]); + for (ss=0; ss<=3; ss++) { + fprintf(localVar[thrId].fp11, "suit=%c", cardSuit[ss]); + for (rr=14; rr>=2; rr--) + if (ttStore[lastTTstore].suit[hh][ss] + & bitMapRank[rr]) + fprintf(localVar[thrId].fp11, " %c", cardRank[rr]); + fprintf(localVar[thrId].fp11, "\n"); + } + fprintf(localVar[thrId].fp11, "\n"); + } + } + fclose(localVar[thrId].fp11); + lastTTstore++; +} +#endif + +#if defined(_WIN32) +HANDLE solveAllEvents[MAXNOOFTHREADS]; +struct paramType param; +LONG volatile threadIndex; +LONG volatile current; + +long chunk = 4; + +DWORD CALLBACK SolveChunkDDtable (void *) { + struct futureTricks fut[MAXNOOFBOARDS]; + int thid; + long j; + + thid=InterlockedIncrement(&threadIndex); + + while ((j=InterlockedExchangeAdd(¤t, chunk))deals[j+k], param.bop->target[j+k], + param.bop->solutions[j+k], param.bop->mode[j+k], + &fut[j+k], thid); + if (res==1) { + param.solvedp->solvedBoard[j+k]=fut[j+k]; + param.error=0; + } + else { + param.error=res; + } + } + } + + if (SetEvent(solveAllEvents[thid])==0) { + /*int errCode=GetLastError();*/ + return 0; + } + + return 1; + +} + +int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { + int k/*, errCode*/; + DWORD res; + DWORD solveAllWaitResult; + + current=0; + + threadIndex=-1; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -101; + + for (k=0; knoOfBoards; + + for (k=0; ksolvedBoard[k].cards=0; + + for (k=0; knoOfBoards=0; + for (k=0; ksolvedBoard[k].cards!=0) + solvedp->noOfBoards++; + } + + if (param.error==0) + return 1; + else + return param.error; +} + +int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize) { + int k/*, errCode*/; + DWORD res; + DWORD solveAllWaitResult; + + current = 0; + threadIndex = -1; + chunk = chunkSize; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -101; + + for (k = 0; knoOfBoards; + + for (k = 0; ksolvedBoard[k].cards = 0; + + for (k = 0; knoOfBoards = 0; + for (k = 0; ksolvedBoard[k].cards != 0) + solvedp->noOfBoards++; + } + + if (param.error == 0) + return 1; + else + return param.error; +} + + +DWORD CALLBACK SolveChunk (void *) { + struct futureTricks fut[MAXNOOFBOARDS]; + int thid; + long j; + + thid=InterlockedIncrement(&threadIndex); + + while ((j=(InterlockedIncrement(¤t)-1))deals[j], param.bop->target[j], + param.bop->solutions[j], param.bop->mode[j], &fut[j], thid); + if (res==1) { + param.solvedp->solvedBoard[j]=fut[j]; + param.error=0; + } + else { + param.error=res; + } + } + + if (SetEvent(solveAllEvents[thid])==0) { + /*int errCode=GetLastError();*/ + return 0; + } + + return 1; + +} + + + +int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { + int k/*, errCode*/; + DWORD res; + DWORD solveAllWaitResult; + + current=0; + + threadIndex=-1; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -201; + + for (k=0; knoOfBoards; + + for (k=0; ksolvedBoard[k].cards=0; + + for (k=0; knoOfBoards=0; + for (k=0; ksolvedBoard[k].cards!=0) + solvedp->noOfBoards++; + } + + if (param.error==0) + return 1; + else + return param.error; +} + + +#else +int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp) { + int k, i, res, chunk, fail; + struct futureTricks fut[MAXNOOFBOARDS]; + + chunk=4; fail=1; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -101; + + for (i=0; isolvedBoard[i].cards=0; + +#ifdef _OPENMP + omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ +#endif + + #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) + { + + #pragma omp for schedule(dynamic, chunk) + + for (k=0; knoOfBoards; k++) { + res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], + bop->mode[k], &fut[k], +#ifdef _OPENMP + omp_get_thread_num() +#else + 0 +#endif + ); + if (res==1) { + solvedp->solvedBoard[k]=fut[k]; + } + else + fail=res; + } + } + + if (fail!=1) + return fail; + + solvedp->noOfBoards=0; + for (i=0; isolvedBoard[i].cards!=0) + solvedp->noOfBoards++; + } + + return 1; +} + + +int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize) { + int k, i, res, chunk, fail; + struct futureTricks fut[MAXNOOFBOARDS]; + + chunk=chunkSize; fail=1; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -101; + + for (i=0; isolvedBoard[i].cards=0; + +#ifdef _OPENMP + omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ +#endif + + #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) + { + + #pragma omp for schedule(dynamic, chunk) + + for (k=0; knoOfBoards; k++) { + res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], + bop->mode[k], &fut[k], +#ifdef _OPENMP + omp_get_thread_num() +#else + 0 +#endif + ); + if (res==1) { + solvedp->solvedBoard[k]=fut[k]; + } + else + fail=res; + } + } + + if (fail!=1) + return fail; + + solvedp->noOfBoards=0; + for (i=0; isolvedBoard[i].cards!=0) + solvedp->noOfBoards++; + } + + return 1; +} + + + +int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp) { + int k, i, res, chunk, fail; + struct futureTricks fut[MAXNOOFBOARDS]; + + chunk=1; fail=1; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return -101; + + for (i=0; isolvedBoard[i].cards=0; + +#ifdef _OPENMP + omp_set_num_threads(noOfCores); /* Added after suggestion by Dirk Willecke. */ +#endif + + #pragma omp parallel shared(bop, solvedp, chunk, fail) private(k) + { + + #pragma omp for schedule(dynamic, chunk) + + for (k=0; knoOfBoards; k++) { + res=SolveBoard(bop->deals[k], bop->target[k], bop->solutions[k], + bop->mode[k], &fut[k], +#ifdef _OPENMP + omp_get_thread_num() +#else + 0 +#endif + ); + if (res==1) { + solvedp->solvedBoard[k]=fut[k]; + } + else + fail=res; + } + } + + if (fail!=1) + return fail; + + solvedp->noOfBoards=0; + for (i=0; isolvedBoard[i].cards!=0) + solvedp->noOfBoards++; + } + + return 1; +} +#endif + + +int STDCALL CalcDDtable(struct ddTableDeal tableDeal, struct ddTableResults * tablep) { + + int h, s, k, ind, tr, first, res; + struct deal dl; + struct boards bo; + struct solvedBoards solved; + + for (h=0; h<=3; h++) + for (s=0; s<=3; s++) + dl.remainCards[h][s]=tableDeal.cards[h][s]; + + for (k=0; k<=2; k++) { + dl.currentTrickRank[k]=0; + dl.currentTrickSuit[k]=0; + } + + ind=0; bo.noOfBoards=20; + + for (tr=4; tr>=0; tr--) + for (first=0; first<=3; first++) { + dl.first=first; + dl.trump=tr; + bo.deals[ind]=dl; + bo.target[ind]=-1; + bo.solutions[ind]=1; + bo.mode[ind]=1; + ind++; + } + + res=SolveAllBoards4(&bo, &solved); + if (res==1) { + for (ind=0; ind<20; ind++) { + tablep->resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= + 13-solved.solvedBoard[ind].score[0]; + } + return 1; + } + + return res; +} + +#ifdef PBN_PLUS +int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, int trumpFilter[5], + struct ddTablesRes *resp, + struct allParResults *presp) { + /* mode = 0: par calculation, vulnerability None + mode = 1: par calculation, vulnerability All + mode = 2: par calculation, vulnerability NS + mode = 3: par calculation, vulnerability EW + mode = -1: no par calculation */ + + int h, s, k, m, ind, tr, first, res, rs, lastIndex=0, + lastBoardIndex[MAXNOOFBOARDS>>2], okey=FALSE, count=0; + struct boards bo; + struct solvedBoards solved; + + int Par(struct ddTableResults * tablep, struct parResults *presp, int vulnerable); + + for (k=0; k<5; k++) { + if (!trumpFilter[k]) { + okey=TRUE; + count++; + } + } + + if (!okey) + return -201; + + switch (count) { + case 1: if (dealsp->noOfTables > 50) return 202; break; + case 2: if (dealsp->noOfTables > 25) return 202; break; + case 3: if (dealsp->noOfTables > 16) return 202; break; + case 4: if (dealsp->noOfTables > 12) return 202; break; + case 5: if (dealsp->noOfTables > 10) return 202; break; + } + + ind=0; + resp->noOfBoards=0; + + for (m=0; mnoOfTables; m++) { + for (tr=4; tr>=0; tr--) { + if (!trumpFilter[tr]) { + for (first=0; first<=3; first++) { + for (h=0; h<=3; h++) + for (s=0; s<=3; s++) + bo.deals[ind].remainCards[h][s]=dealsp->deals[m].cards[h][s]; + bo.deals[ind].first=first; + bo.deals[ind].trump=tr; + for (k=0; k<=2; k++) { + bo.deals[ind].currentTrickRank[k]=0; + bo.deals[ind].currentTrickSuit[k]=0; + } + + bo.target[ind]=-1; + bo.solutions[ind]=1; + bo.mode[ind]=1; + lastIndex=ind; + lastBoardIndex[m]=ind; + ind++; + } + } + } + } + + bo.noOfBoards=lastIndex+1; + + res=SolveAllBoards4(&bo, &solved); + if (res==1) { + resp->noOfBoards+=solved.noOfBoards; + for (ind=0; ind<=lastIndex; ind++) { + for (k=0; k<=lastIndex; k++) { + if (ind<=lastBoardIndex[k]) { + resp->results[k].resTable[bo.deals[ind].trump][rho[bo.deals[ind].first]]= + 13-solved.solvedBoard[ind].score[0]; + break; + } + } + } + + if ((mode > -1) && (mode < 4)) { + /* Calculate par */ + for (k=0; knoOfTables; k++) { + rs=Par(&(resp->results[k]), &(presp->presults[k]), mode); + /* vulnerable 0: None 1: Both 2: NS 3: EW */ + if (rs!=1) + return rs; + } + } + return 1; + } + return res; +} + +int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, int trumpFilter[5], + struct ddTablesRes *resp, struct allParResults *presp) { + int res, k; + struct ddTableDeals dls; + + int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); + + for (k=0; knoOfTables; k++) + if (ConvertFromPBN(dealsp->deals[k].cards, dls.deals[k].cards)!=1) + return -99; + + dls.noOfTables=dealsp->noOfTables; + + res=CalcAllTables(&dls, mode, trumpFilter, resp, presp); + + return res; +} +#endif + + +int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]) { + int bp=0, first, card, hand, handRelFirst, suitInHand, h, s; + int IsCard(char cardChar); + + for (h=0; h<=3; h++) + for (s=0; s<=3; s++) + remainCards[h][s]=0; + + while (((dealBuff[bp]!='W')&&(dealBuff[bp]!='N')&& + (dealBuff[bp]!='E')&&(dealBuff[bp]!='S')&& + (dealBuff[bp]!='w')&&(dealBuff[bp]!='n')&& + (dealBuff[bp]!='e')&&(dealBuff[bp]!='s'))&&(bp<3)) + bp++; + + if (bp>=3) + return 0; + + if ((dealBuff[bp]=='N')||(dealBuff[bp]=='n')) + first=0; + else if ((dealBuff[bp]=='E')||(dealBuff[bp]=='e')) + first=1; + else if ((dealBuff[bp]=='S')||(dealBuff[bp]=='s')) + first=2; + else + first=3; + + bp++; + bp++; + + handRelFirst=0; suitInHand=0; + + while ((bp<80)&&(dealBuff[bp]!='\0')) { + card=IsCard(dealBuff[bp]); + if (card) { + switch (first) { + case 0: + hand=handRelFirst; + break; + case 1: + if (handRelFirst==0) + hand=1; + else if (handRelFirst==3) + hand=0; + else + hand=handRelFirst+1; + break; + case 2: + if (handRelFirst==0) + hand=2; + else if (handRelFirst==1) + hand=3; + else + hand=handRelFirst-2; + break; + default: + if (handRelFirst==0) + hand=3; + else + hand=handRelFirst-1; + } + + remainCards[hand][suitInHand]|=(bitMapRank[card]<<2); + + } + else if (dealBuff[bp]=='.') + suitInHand++; + else if (dealBuff[bp]==' ') { + handRelFirst++; + suitInHand=0; + } + bp++; + } + return 1; +} + + +int IsCard(char cardChar) { + switch (cardChar) { + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'T': + return 10; + case 'J': + return 11; + case 'Q': + return 12; + case 'K': + return 13; + case 'A': + return 14; + case 't': + return 10; + case 'j': + return 11; + case 'q': + return 12; + case 'k': + return 13; + case 'a': + return 14; + default: + return 0; + } + } + +#ifdef PBN +int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, + int solutions, int mode, struct futureTricks *futp, int thrId) { + + int res, k; + struct deal dl; + int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); + + if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards)!=1) + return -99; + + for (k=0; k<=2; k++) { + dl.currentTrickRank[k]=dlpbn.currentTrickRank[k]; + dl.currentTrickSuit[k]=dlpbn.currentTrickSuit[k]; + } + dl.first=dlpbn.first; + dl.trump=dlpbn.trump; + + res=SolveBoard(dl, target, solutions, mode, futp, thrId); + + return res; +} + +int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, struct ddTableResults * tablep) { + struct ddTableDeal tableDeal; + int res; + + if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards)!=1) + return -99; + + res=CalcDDtable(tableDeal, tablep); + + return res; +} +#endif + +#ifdef PBN_PLUS +int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp) { + struct boards bo; + int k, i, res; + + bo.noOfBoards=bop->noOfBoards; + for (k=0; knoOfBoards; k++) { + bo.mode[k]=bop->mode[k]; + bo.solutions[k]=bop->solutions[k]; + bo.target[k]=bop->target[k]; + bo.deals[k].first=bop->deals[k].first; + bo.deals[k].trump=bop->deals[k].trump; + for (i=0; i<=2; i++) { + bo.deals[k].currentTrickSuit[i]=bop->deals[k].currentTrickSuit[i]; + bo.deals[k].currentTrickRank[i]=bop->deals[k].currentTrickRank[i]; + } + if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards)!=1) + return -99; + } + + res=SolveAllBoards1(&bo, solvedp); + + return res; +} + +int STDCALL SolveAllChunks(struct boardsPBN *bop, struct solvedBoards *solvedp, int chunkSize) { + struct boards bo; + int k, i, res; + + if (chunkSize < 1) + return -201; + + bo.noOfBoards = bop->noOfBoards; + for (k = 0; knoOfBoards; k++) { + bo.mode[k] = bop->mode[k]; + bo.solutions[k] = bop->solutions[k]; + bo.target[k] = bop->target[k]; + bo.deals[k].first = bop->deals[k].first; + bo.deals[k].trump = bop->deals[k].trump; + for (i = 0; i <= 2; i++) { + bo.deals[k].currentTrickSuit[i] = bop->deals[k].currentTrickSuit[i]; + bo.deals[k].currentTrickRank[i] = bop->deals[k].currentTrickRank[i]; + } + if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards) != 1) + return -99; + } + + res = SolveAllBoardsN(&bo, solvedp, chunkSize); + return res; +} +#endif + +#ifdef PBN_PLUS +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); + int VulnerDefSide(int side, int vulnerable); + + /* 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 = abs(par_score[i]); + /* 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, + VulnerDefSide(par_score[0]>0, vulnerable)); + else + sc1 = -rawscore(-1, par_tricks[i] - max_lower - tu_max + 1, + VulnerDefSide(par_score[0]>0, vulnerable)); + /* 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 = abs(par_score[i]); + /* Score for making the tentative lower par contract. */ + while (max_lower > 0) { + if (denom_max < j) + sc1 = -rawscore(-1, 9 - max_lower - tu_max, + VulnerDefSide(par_score[0]>0, vulnerable)); + else + sc1 = -rawscore(-1, 9 - max_lower - tu_max + 1, + VulnerDefSide(par_score[0]>0, vulnerable)); + /* 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 = abs(par_score[i]); + /* Score for making the tentative lower par contract. */ + while (max_lower > 0) { + if (denom_max < j) + sc1 = -rawscore(-1, 8 - max_lower - tu_max, + VulnerDefSide(par_score[0]>0, vulnerable)); + else + sc1 = -rawscore(-1, 8 - max_lower - tu_max + 1, + VulnerDefSide(par_score[0]>0, vulnerable)); + /* 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; +} + + +int VulnerDefSide(int side, int vulnerable) { + if (vulnerable == 0) + return 0; + else if (vulnerable == 1) + return 1; + else if (side) { + /* N/S makes par contract. */ + if (vulnerable == 2) + return 0; + else + return 1; + } + else { + if (vulnerable == 3) + return 0; + else + return 1; + } +} + + + + diff --git a/dll.h b/dll.h index 47d03f90..e5bfcbab 100755 --- a/dll.h +++ b/dll.h @@ -1,550 +1,550 @@ -/* portability-macros header prefix */ - -/* Windows requires a __declspec(dllexport) tag, etc */ -#if defined(_WIN32) -# define DLLEXPORT __declspec(dllexport) -# define STDCALL __stdcall -#else -# define DLLEXPORT -# define STDCALL -# define INT8 char -#endif - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C -#endif - -#if defined(_WIN32) && defined(__MINGW32__) -#define WINVER 0x500 -# include -# include -#endif - -#if defined(_WIN32) && !defined(__MINGW32__) -# include -# include -#endif - -#ifdef __linux__ -# include -#endif - - -#if defined(_MSC_VER) -# include -#else -# include -#endif - -/* end of portability-macros section */ - -#define DDS_VERSION 20501 /* Version 2.5.1. Allowing for 2 digit minor versions */ - -#define PBN - -#define PBN_PLUS - -/*#define BENCH*/ - -#include -/*#define _CRTDBG_MAP_ALLOC */ /* MEMORY LEAK? */ -#include -/*#include */ /* MEMORY LEAK? */ -#include -#include -#include -#include - -#ifdef __linux__ -typedef long long __int64; -#endif - -/*#define STAT*/ /* Define STAT to generate a statistics log, stat.txt */ -/*#define TTDEBUG*/ /* Define TTDEBUG to generate transposition table debug information. - Only for a single thread! */ - -#ifdef TTDEBUG -#define SEARCHSIZE 20000 -#else -#define SEARCHSIZE 1 -#endif - -#if defined(INFINITY) -# undef INFINITY -#endif -#define INFINITY 32000 - -#define MAXNOOFTHREADS 16 - -#define MAXNODE 1 -#define MINNODE 0 - -#define TRUE 1 -#define FALSE 0 - -#define MOVESVALID 1 -#define MOVESLOCKED 2 - -#define NSIZE 100000 -#define WSIZE 100000 -#define LSIZE 20000 -#define NINIT 250000 -#define WINIT 700000 -#define LINIT 50000 - -#define SIMILARDEALLIMIT 5 -#define SIMILARMAXWINNODES 700000 - -#define MAXNOOFBOARDS 200/*100*/ - -#define Max(x, y) (((x) >= (y)) ? (x) : (y)) -#define Min(x, y) (((x) <= (y)) ? (x) : (y)) - -/* "hand" is leading hand, "relative" is hand relative leading -hand. -The handId macro implementation follows a solution -by Thomas Andrews. -All hand identities are given as -0=NORTH, 1=EAST, 2=SOUTH, 3=WEST. */ - -#define handId(hand, relative) (hand + relative) & 3 -#define CMP_SWAP(i, j) if (a[i].weight < a[j].weight) \ - { struct moveType tmp = a[i]; a[i] = a[j]; a[j] = tmp; } - - -struct gameInfo { /* All info of a particular deal */ - int declarer; - int leadHand; - int leadSuit; - int leadRank; - int first; - int noOfCards; - unsigned short int suit[4][4]; - /* 1st index is hand id, 2nd index is suit id */ -}; - - -struct moveType { - int suit; - int rank; - unsigned short int sequence; /* Whether or not this move is - the first in a sequence */ - short int weight; /* Weight used at sorting */ -}; - -struct movePlyType { - struct moveType move[14]; - int current; - int last; -}; - -struct highCardType { - int rank; - int hand; -}; - -struct futureTricks { - int nodes; - #ifdef BENCH - int totalNodes; - #endif - int cards; - int suit[13]; - int rank[13]; - int equals[13]; - int score[13]; -}; - -struct deal { - int trump; - int first; - int currentTrickSuit[3]; - int currentTrickRank[3]; - unsigned int remainCards[4][4]; -}; - - -struct dealPBN { - int trump; - int first; - int currentTrickSuit[3]; - int currentTrickRank[3]; - char remainCards[80]; -}; - - -struct pos { - unsigned short int rankInSuit[4][4]; /* 1st index is hand, 2nd index is - suit id */ - int orderSet[4]; - int winOrderSet[4]; - int winMask[4]; - int leastWin[4]; - unsigned short int removedRanks[4]; /* Ranks removed from board, - index is suit */ - unsigned short int winRanks[50][4]; /* Cards that win by rank, - indices are depth and suit */ - unsigned char length[4][4]; - int ubound; - int lbound; - int bestMoveSuit; - int bestMoveRank; - int first[50]; /* Hand that leads the trick for each ply*/ - int high[50]; /* Hand that is presently winning the trick */ - struct moveType move[50]; /* Presently winning move */ - int handRelFirst; /* The current hand, relative first hand */ - int tricksMAX; /* Aggregated tricks won by MAX */ - struct highCardType winner[4]; /* Winning rank of the trick, - index is suit id. */ - struct highCardType secondBest[4]; /* Second best rank, index is suit id. */ -}; - -struct posSearchType { - struct winCardType * posSearchPoint; - long long suitLengths; - struct posSearchType * left; - struct posSearchType * right; -}; - - -struct nodeCardsType { - char ubound; /* ubound and - lbound for the N-S side */ - char lbound; - char bestMoveSuit; - char bestMoveRank; - char leastWin[4]; -}; - -struct winCardType { - int orderSet; - int winMask; - struct nodeCardsType * first; - struct winCardType * prevWin; - struct winCardType * nextWin; - struct winCardType * next; -}; - - -struct evalType { - int tricks; - unsigned short int winRanks[4]; -}; - -struct absRankType { - char rank; - char hand; -}; - -struct relRanksType { - int aggrRanks[4]; - int winMask[4]; - char relRank[15][4]; - struct absRankType absRank[15][4]; -}; - -struct adaptWinRanksType { - unsigned short int winRanks[14]; -}; - - -struct ttStoreType { - struct nodeCardsType * cardsP; - char tricksLeft; - char target; - char ubound; - char lbound; - unsigned char first; - unsigned short int suit[4][4]; -}; - -struct card { - int suit; - int rank; -}; - -struct boards { - int noOfBoards; - struct deal deals[MAXNOOFBOARDS]; - int target[MAXNOOFBOARDS]; - int solutions[MAXNOOFBOARDS]; - int mode[MAXNOOFBOARDS]; -}; - -struct boardsPBN { - int noOfBoards; - struct dealPBN deals[MAXNOOFBOARDS]; - int target[MAXNOOFBOARDS]; - int solutions[MAXNOOFBOARDS]; - int mode[MAXNOOFBOARDS]; -}; - -struct solvedBoards { - int noOfBoards; - struct futureTricks solvedBoard[MAXNOOFBOARDS]; -}; - -struct paramType { - int noOfBoards; - struct boards *bop; - struct solvedBoards *solvedp; - int error; -}; - -struct ddTableDeal { - unsigned int cards[4][4]; -}; - -struct ddTableDeals { - int noOfTables; - struct ddTableDeal deals[MAXNOOFBOARDS>>2]; -}; - -struct ddTableDealPBN { - char cards[80]; -}; - -struct ddTableDealsPBN { - int noOfTables; - struct ddTableDealPBN deals[MAXNOOFBOARDS>>2]; -}; - -struct ddTableResults { - int resTable[5][4]; -}; - -struct ddTablesRes { - int noOfBoards; - struct ddTableResults results[MAXNOOFBOARDS>>2]; -}; - - -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 allParResults { - struct parResults presults[MAXNOOFBOARDS / 20]; -}; - -struct par_suits_type { - int suit; - int tricks; - int score; -}; - - -struct localVarType { - int nodeTypeStore[4]; - int trump; - unsigned short int lowestWin[50][4]; - #ifdef STAT - int nodes; - #endif - int trickNodes; - int no[50]; - int iniDepth; - int handToPlay; - int payOff; - int val; - struct pos iniPosition; - struct pos lookAheadPos; /* Is initialized for starting - alpha-beta search */ - struct moveType forbiddenMoves[14]; - struct moveType initialMoves[4]; - struct moveType cd; - struct movePlyType movePly[50]; - int tricksTarget; - struct gameInfo game; - int newDeal; - int newTrump; - int similarDeal; - unsigned short int diffDeal; - unsigned short int aggDeal; - int estTricks[4]; - FILE *fp2; - FILE *fp7; - FILE *fp11; - /*FILE *fdp */ - struct moveType bestMove[50]; - struct moveType bestMoveTT[50]; - struct winCardType temp_win[5]; - int nodeSetSizeLimit; - int winSetSizeLimit; - int lenSetSizeLimit; - unsigned long long maxmem; /* bytes */ - unsigned long long allocmem; - unsigned long long summem; - int wmem; - int nmem; - int lmem; - int maxIndex; - int wcount; - int ncount; - int lcount; - int clearTTflag; - int windex; - /*int ttCollect; - int suppressTTlog;*/ - struct relRanksType * rel; - struct adaptWinRanksType * adaptWins; - struct posSearchType *rootnp[14][4]; - struct winCardType **pw; - struct nodeCardsType **pn; - struct posSearchType **pl; - struct nodeCardsType * nodeCards; - struct winCardType * winCards; - struct posSearchType * posSearch; - /*struct ttStoreType * ttStore; - int lastTTstore;*/ - unsigned short int iniRemovedRanks[4]; - - int nodeSetSize; /* Index with range 0 to nodeSetSizeLimit */ - int winSetSize; /* Index with range 0 to winSetSizeLimit */ - int lenSetSize; /* Index with range 0 to lenSetSizeLimit */ -}; - -extern int noOfThreads; -extern int noOfCores; -extern struct localVarType localVar[MAXNOOFTHREADS]; -extern int * highestRank; -extern int * counttable; -extern struct adaptWinRanksType * adaptWins; -extern unsigned short int bitMapRank[16]; -extern unsigned short int relRankInSuit[4][4]; -extern int sum; -extern int score1Counts[50], score0Counts[50]; -extern int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], - c8[50], c9[50]; -extern int nodeTypeStore[4]; /* Look-up table for determining if - node is MAXNODE or MINNODE */ -extern int lho[4], rho[4], partner[4]; -extern int nodes; /* Number of nodes searched */ -extern int no[50]; /* Number of nodes searched on each - depth level */ -extern int payOff; -extern int iniDepth; -extern int treeDepth; -extern int tricksTarget; /* No of tricks for MAX in order to - meet the game goal, e.g. to make the - contract */ -extern int tricksTargetOpp; /* Target no of tricks for MAX - opponent */ -extern int targetNS; -extern int targetEW; -extern int handToPlay; -extern int searchTraceFlag; -extern int countMax; -extern int depthCount; -extern int highHand; -extern int nodeSetSizeLimit; -extern int winSetSizeLimit; -extern int lenSetSizeLimit; -extern int estTricks[4]; -extern int recInd; -extern int suppressTTlog; -extern unsigned char suitChar[4]; -extern unsigned char rankChar[15]; -extern unsigned char handChar[4]; -extern unsigned char cardRank[15], cardSuit[5], cardHand[4]; -extern int totalNodes; -extern struct futureTricks fut, ft; -extern struct futureTricks *futp; -extern char stri[128]; - -extern FILE *fp, /**fp2, *fp7, *fp11,*/ *fpx; - /* Pointers to logs */ - -extern struct ttStoreType * ttStore; -extern int lastTTstore; -extern int ttCollect; -extern int suppressTTlog; - -EXTERN_C DLLEXPORT int STDCALL SolveBoard(struct deal dl, - int target, int solutions, int mode, struct futureTricks *futp, int threadIndex); -EXTERN_C DLLEXPORT int STDCALL CalcDDtable(struct ddTableDeal tableDeal, - struct ddTableResults * tablep); - -#ifdef PBN -EXTERN_C DLLEXPORT int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, - int solutions, int mode, struct futureTricks *futp, int thrId); -EXTERN_C DLLEXPORT int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, - struct ddTableResults * tablep); -#endif - -#ifdef PBN_PLUS -EXTERN_C DLLEXPORT int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp); -EXTERN_C DLLEXPORT int STDCALL SolveAllChunks(struct boardsPBN *bop, struct solvedBoards *solvedp, int chunkSize); -EXTERN_C DLLEXPORT int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, - int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); -EXTERN_C DLLEXPORT int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, - int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); -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); -#endif - -#ifdef __linux -EXTERN_C void InitStart(int gb_ram, int ncores); /* For usage with ctypes in Linux. */ -#endif - -void InitStart(int gb_ram, int ncores); -void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId); -void InitSearch(struct pos * posPoint, int depth, - struct moveType startMoves[], int first, int mtd, int thrId); -int ABsearch(struct pos * posPoint, int target, int depth, int thrId); -void Make(struct pos * posPoint, unsigned short int trickCards[4], - int depth, int trump, struct movePlyType *mply, int thrId); -int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId); -void MergeSort(int n, struct moveType *a); -inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump); -inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2); -int AdjustMoveList(int thrId); -int QuickTricks(struct pos * posPoint, int hand, - int depth, int target, int trump, int *result, int thrId); -int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); -int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); -struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType - * nodep, int target, int tricks, int * result, int *value, int thrId); -struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType - * nodep); -struct nodeCardsType * FindSOP(struct pos * posPoint, - struct winCardType * nodeP, int firstHand, - int target, int tricks, int * valp, int thrId); -struct nodeCardsType * BuildPath(struct pos * posPoint, - struct posSearchType *nodep, int * result, int thrId); -void BuildSOP(struct pos * posPoint, long long suitLengths, int tricks, int firstHand, int target, - int depth, int scoreFlag, int score, int thrId); -struct posSearchType * SearchLenAndInsert(struct posSearchType - * rootp, long long key, int insertNode, int *result, int thrId); -void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); -int CheckDeal(struct moveType * cardp, int thrId); -int InvBitMapRank(unsigned short bitMap); -int InvWinMask(int mask); -void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, int target, - int depth, int thrId); -int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId); -int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode); -void Wipe(int thrId); -void AddNodeSet(int thrId); -void AddLenSet(int thrId); -void AddWinSet(int thrId); - -void PrintDeal(FILE *fp, unsigned short ranks[4][4]); - -int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp); -int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize); -int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp); - -int IsCard(char cardChar); -void UpdateDealInfo(int card); -int IsVal(char cardChar); - - +/* portability-macros header prefix */ + +/* Windows requires a __declspec(dllexport) tag, etc */ +#if defined(_WIN32) +# define DLLEXPORT __declspec(dllexport) +# define STDCALL __stdcall +#else +# define DLLEXPORT +# define STDCALL +# define INT8 char +#endif + +#ifdef __cplusplus +# define EXTERN_C extern "C" +#else +# define EXTERN_C +#endif + +#if defined(_WIN32) && defined(__MINGW32__) +#define WINVER 0x500 +# include +# include +#endif + +#if defined(_WIN32) && !defined(__MINGW32__) +# include +# include +#endif + +#ifdef __linux__ +# include +#endif + + +#if defined(_MSC_VER) +# include +#else +# include +#endif + +/* end of portability-macros section */ + +#define DDS_VERSION 20502 /* Version 2.5.2. Allowing for 2 digit minor versions */ + +#define PBN + +#define PBN_PLUS + +/*#define BENCH*/ + +#include +/*#define _CRTDBG_MAP_ALLOC */ /* MEMORY LEAK? */ +#include +/*#include */ /* MEMORY LEAK? */ +#include +#include +#include +#include + +#ifdef __linux__ +typedef long long __int64; +#endif + +/*#define STAT*/ /* Define STAT to generate a statistics log, stat.txt */ +/*#define TTDEBUG*/ /* Define TTDEBUG to generate transposition table debug information. + Only for a single thread! */ + +#ifdef TTDEBUG +#define SEARCHSIZE 20000 +#else +#define SEARCHSIZE 1 +#endif + +#if defined(INFINITY) +# undef INFINITY +#endif +#define INFINITY 32000 + +#define MAXNOOFTHREADS 16 + +#define MAXNODE 1 +#define MINNODE 0 + +#define TRUE 1 +#define FALSE 0 + +#define MOVESVALID 1 +#define MOVESLOCKED 2 + +#define NSIZE 100000 +#define WSIZE 100000 +#define LSIZE 20000 +#define NINIT 250000 +#define WINIT 700000 +#define LINIT 50000 + +#define SIMILARDEALLIMIT 5 +#define SIMILARMAXWINNODES 700000 + +#define MAXNOOFBOARDS 200/*100*/ + +#define Max(x, y) (((x) >= (y)) ? (x) : (y)) +#define Min(x, y) (((x) <= (y)) ? (x) : (y)) + +/* "hand" is leading hand, "relative" is hand relative leading +hand. +The handId macro implementation follows a solution +by Thomas Andrews. +All hand identities are given as +0=NORTH, 1=EAST, 2=SOUTH, 3=WEST. */ + +#define handId(hand, relative) (hand + relative) & 3 +#define CMP_SWAP(i, j) if (a[i].weight < a[j].weight) \ + { struct moveType tmp = a[i]; a[i] = a[j]; a[j] = tmp; } + + +struct gameInfo { /* All info of a particular deal */ + int declarer; + int leadHand; + int leadSuit; + int leadRank; + int first; + int noOfCards; + unsigned short int suit[4][4]; + /* 1st index is hand id, 2nd index is suit id */ +}; + + +struct moveType { + int suit; + int rank; + unsigned short int sequence; /* Whether or not this move is + the first in a sequence */ + short int weight; /* Weight used at sorting */ +}; + +struct movePlyType { + struct moveType move[14]; + int current; + int last; +}; + +struct highCardType { + int rank; + int hand; +}; + +struct futureTricks { + int nodes; + #ifdef BENCH + int totalNodes; + #endif + int cards; + int suit[13]; + int rank[13]; + int equals[13]; + int score[13]; +}; + +struct deal { + int trump; + int first; + int currentTrickSuit[3]; + int currentTrickRank[3]; + unsigned int remainCards[4][4]; +}; + + +struct dealPBN { + int trump; + int first; + int currentTrickSuit[3]; + int currentTrickRank[3]; + char remainCards[80]; +}; + + +struct pos { + unsigned short int rankInSuit[4][4]; /* 1st index is hand, 2nd index is + suit id */ + int orderSet[4]; + int winOrderSet[4]; + int winMask[4]; + int leastWin[4]; + unsigned short int removedRanks[4]; /* Ranks removed from board, + index is suit */ + unsigned short int winRanks[50][4]; /* Cards that win by rank, + indices are depth and suit */ + unsigned char length[4][4]; + int ubound; + int lbound; + int bestMoveSuit; + int bestMoveRank; + int first[50]; /* Hand that leads the trick for each ply*/ + int high[50]; /* Hand that is presently winning the trick */ + struct moveType move[50]; /* Presently winning move */ + int handRelFirst; /* The current hand, relative first hand */ + int tricksMAX; /* Aggregated tricks won by MAX */ + struct highCardType winner[4]; /* Winning rank of the trick, + index is suit id. */ + struct highCardType secondBest[4]; /* Second best rank, index is suit id. */ +}; + +struct posSearchType { + struct winCardType * posSearchPoint; + long long suitLengths; + struct posSearchType * left; + struct posSearchType * right; +}; + + +struct nodeCardsType { + char ubound; /* ubound and + lbound for the N-S side */ + char lbound; + char bestMoveSuit; + char bestMoveRank; + char leastWin[4]; +}; + +struct winCardType { + int orderSet; + int winMask; + struct nodeCardsType * first; + struct winCardType * prevWin; + struct winCardType * nextWin; + struct winCardType * next; +}; + + +struct evalType { + int tricks; + unsigned short int winRanks[4]; +}; + +struct absRankType { + char rank; + char hand; +}; + +struct relRanksType { + int aggrRanks[4]; + int winMask[4]; + char relRank[15][4]; + struct absRankType absRank[15][4]; +}; + +struct adaptWinRanksType { + unsigned short int winRanks[14]; +}; + + +struct ttStoreType { + struct nodeCardsType * cardsP; + char tricksLeft; + char target; + char ubound; + char lbound; + unsigned char first; + unsigned short int suit[4][4]; +}; + +struct card { + int suit; + int rank; +}; + +struct boards { + int noOfBoards; + struct deal deals[MAXNOOFBOARDS]; + int target[MAXNOOFBOARDS]; + int solutions[MAXNOOFBOARDS]; + int mode[MAXNOOFBOARDS]; +}; + +struct boardsPBN { + int noOfBoards; + struct dealPBN deals[MAXNOOFBOARDS]; + int target[MAXNOOFBOARDS]; + int solutions[MAXNOOFBOARDS]; + int mode[MAXNOOFBOARDS]; +}; + +struct solvedBoards { + int noOfBoards; + struct futureTricks solvedBoard[MAXNOOFBOARDS]; +}; + +struct paramType { + int noOfBoards; + struct boards *bop; + struct solvedBoards *solvedp; + int error; +}; + +struct ddTableDeal { + unsigned int cards[4][4]; +}; + +struct ddTableDeals { + int noOfTables; + struct ddTableDeal deals[MAXNOOFBOARDS>>2]; +}; + +struct ddTableDealPBN { + char cards[80]; +}; + +struct ddTableDealsPBN { + int noOfTables; + struct ddTableDealPBN deals[MAXNOOFBOARDS>>2]; +}; + +struct ddTableResults { + int resTable[5][4]; +}; + +struct ddTablesRes { + int noOfBoards; + struct ddTableResults results[MAXNOOFBOARDS>>2]; +}; + + +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 allParResults { + struct parResults presults[MAXNOOFBOARDS / 20]; +}; + +struct par_suits_type { + int suit; + int tricks; + int score; +}; + + +struct localVarType { + int nodeTypeStore[4]; + int trump; + unsigned short int lowestWin[50][4]; + #ifdef STAT + int nodes; + #endif + int trickNodes; + int no[50]; + int iniDepth; + int handToPlay; + int payOff; + int val; + struct pos iniPosition; + struct pos lookAheadPos; /* Is initialized for starting + alpha-beta search */ + struct moveType forbiddenMoves[14]; + struct moveType initialMoves[4]; + struct moveType cd; + struct movePlyType movePly[50]; + int tricksTarget; + struct gameInfo game; + int newDeal; + int newTrump; + int similarDeal; + unsigned short int diffDeal; + unsigned short int aggDeal; + int estTricks[4]; + FILE *fp2; + FILE *fp7; + FILE *fp11; + /*FILE *fdp */ + struct moveType bestMove[50]; + struct moveType bestMoveTT[50]; + struct winCardType temp_win[5]; + int nodeSetSizeLimit; + int winSetSizeLimit; + int lenSetSizeLimit; + unsigned long long maxmem; /* bytes */ + unsigned long long allocmem; + unsigned long long summem; + int wmem; + int nmem; + int lmem; + int maxIndex; + int wcount; + int ncount; + int lcount; + int clearTTflag; + int windex; + /*int ttCollect; + int suppressTTlog;*/ + struct relRanksType * rel; + struct adaptWinRanksType * adaptWins; + struct posSearchType *rootnp[14][4]; + struct winCardType **pw; + struct nodeCardsType **pn; + struct posSearchType **pl; + struct nodeCardsType * nodeCards; + struct winCardType * winCards; + struct posSearchType * posSearch; + /*struct ttStoreType * ttStore; + int lastTTstore;*/ + unsigned short int iniRemovedRanks[4]; + + int nodeSetSize; /* Index with range 0 to nodeSetSizeLimit */ + int winSetSize; /* Index with range 0 to winSetSizeLimit */ + int lenSetSize; /* Index with range 0 to lenSetSizeLimit */ +}; + +extern int noOfThreads; +extern int noOfCores; +extern struct localVarType localVar[MAXNOOFTHREADS]; +extern int * highestRank; +extern int * counttable; +extern struct adaptWinRanksType * adaptWins; +extern unsigned short int bitMapRank[16]; +extern unsigned short int relRankInSuit[4][4]; +extern int sum; +extern int score1Counts[50], score0Counts[50]; +extern int c1[50], c2[50], c3[50], c4[50], c5[50], c6[50], c7[50], + c8[50], c9[50]; +extern int nodeTypeStore[4]; /* Look-up table for determining if + node is MAXNODE or MINNODE */ +extern int lho[4], rho[4], partner[4]; +extern int nodes; /* Number of nodes searched */ +extern int no[50]; /* Number of nodes searched on each + depth level */ +extern int payOff; +extern int iniDepth; +extern int treeDepth; +extern int tricksTarget; /* No of tricks for MAX in order to + meet the game goal, e.g. to make the + contract */ +extern int tricksTargetOpp; /* Target no of tricks for MAX + opponent */ +extern int targetNS; +extern int targetEW; +extern int handToPlay; +extern int searchTraceFlag; +extern int countMax; +extern int depthCount; +extern int highHand; +extern int nodeSetSizeLimit; +extern int winSetSizeLimit; +extern int lenSetSizeLimit; +extern int estTricks[4]; +extern int recInd; +extern int suppressTTlog; +extern unsigned char suitChar[4]; +extern unsigned char rankChar[15]; +extern unsigned char handChar[4]; +extern unsigned char cardRank[15], cardSuit[5], cardHand[4]; +extern int totalNodes; +extern struct futureTricks fut, ft; +extern struct futureTricks *futp; +extern char stri[128]; + +extern FILE *fp, /**fp2, *fp7, *fp11,*/ *fpx; + /* Pointers to logs */ + +extern struct ttStoreType * ttStore; +extern int lastTTstore; +extern int ttCollect; +extern int suppressTTlog; + +EXTERN_C DLLEXPORT int STDCALL SolveBoard(struct deal dl, + int target, int solutions, int mode, struct futureTricks *futp, int threadIndex); +EXTERN_C DLLEXPORT int STDCALL CalcDDtable(struct ddTableDeal tableDeal, + struct ddTableResults * tablep); + +#ifdef PBN +EXTERN_C DLLEXPORT int STDCALL SolveBoardPBN(struct dealPBN dlpbn, int target, + int solutions, int mode, struct futureTricks *futp, int thrId); +EXTERN_C DLLEXPORT int STDCALL CalcDDtablePBN(struct ddTableDealPBN tableDealPBN, + struct ddTableResults * tablep); +#endif + +#ifdef PBN_PLUS +EXTERN_C DLLEXPORT int STDCALL SolveAllBoards(struct boardsPBN *bop, struct solvedBoards *solvedp); +EXTERN_C DLLEXPORT int STDCALL SolveAllChunks(struct boardsPBN *bop, struct solvedBoards *solvedp, int chunkSize); +EXTERN_C DLLEXPORT int STDCALL CalcAllTables(struct ddTableDeals *dealsp, int mode, + int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); +EXTERN_C DLLEXPORT int STDCALL CalcAllTablesPBN(struct ddTableDealsPBN *dealsp, int mode, + int trumpFilter[5], struct ddTablesRes *resp, struct allParResults *presp); +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); +#endif + +#ifdef __linux +EXTERN_C void InitStart(int gb_ram, int ncores); /* For usage with ctypes in Linux. */ +#endif + +void InitStart(int gb_ram, int ncores); +void InitGame(int gameNo, int moveTreeFlag, int first, int handRelFirst, int thrId); +void InitSearch(struct pos * posPoint, int depth, + struct moveType startMoves[], int first, int mtd, int thrId); +int ABsearch(struct pos * posPoint, int target, int depth, int thrId); +void Make(struct pos * posPoint, unsigned short int trickCards[4], + int depth, int trump, struct movePlyType *mply, int thrId); +int MoveGen(struct pos * posPoint, int depth, int trump, struct movePlyType *mply, int thrId); +void MergeSort(int n, struct moveType *a); +inline int WinningMove(struct moveType * mvp1, struct moveType * mvp2, int trump); +inline int WinningMoveNT(struct moveType * mvp1, struct moveType * mvp2); +int AdjustMoveList(int thrId); +int QuickTricks(struct pos * posPoint, int hand, + int depth, int target, int trump, int *result, int thrId); +int LaterTricksMIN(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); +int LaterTricksMAX(struct pos *posPoint, int hand, int depth, int target, int trump, int thrId); +struct nodeCardsType * CheckSOP(struct pos * posPoint, struct nodeCardsType + * nodep, int target, int tricks, int * result, int *value, int thrId); +struct nodeCardsType * UpdateSOP(struct pos * posPoint, struct nodeCardsType + * nodep); +struct nodeCardsType * FindSOP(struct pos * posPoint, + struct winCardType * nodeP, int firstHand, + int target, int tricks, int * valp, int thrId); +struct nodeCardsType * BuildPath(struct pos * posPoint, + struct posSearchType *nodep, int * result, int thrId); +void BuildSOP(struct pos * posPoint, long long suitLengths, int tricks, int firstHand, int target, + int depth, int scoreFlag, int score, int thrId); +struct posSearchType * SearchLenAndInsert(struct posSearchType + * rootp, long long key, int insertNode, int *result, int thrId); +void Undo(struct pos * posPoint, int depth, struct movePlyType *mply, int thrId); +int CheckDeal(struct moveType * cardp, int thrId); +int InvBitMapRank(unsigned short bitMap); +int InvWinMask(int mask); +void ReceiveTTstore(struct pos *posPoint, struct nodeCardsType * cardsP, int target, + int depth, int thrId); +int NextMove(struct pos *posPoint, int depth, struct movePlyType *mply, int thrId); +int DumpInput(int errCode, struct deal dl, int target, int solutions, int mode); +void Wipe(int thrId); +void AddNodeSet(int thrId); +void AddLenSet(int thrId); +void AddWinSet(int thrId); + +void PrintDeal(FILE *fp, unsigned short ranks[4][4]); + +int SolveAllBoards4(struct boards *bop, struct solvedBoards *solvedp); +int SolveAllBoardsN(struct boards *bop, struct solvedBoards *solvedp, int chunkSize); +int SolveAllBoards1(struct boards *bop, struct solvedBoards *solvedp); + +int IsCard(char cardChar); +void UpdateDealInfo(int card); +int IsVal(char cardChar); + + diff --git a/readme.txt b/readme.txt index 0157e2c0..8d088946 100755 --- a/readme.txt +++ b/readme.txt @@ -1,64 +1,64 @@ -DDS 2.4, Bo Haglund 2014-03-01 - -For Win32, DDS compiles with Visual C++ 2010 and 2012 Express editions -and the TDM-GCC/Mingw port of gcc. - -When using Visual C++, the statement -#include "stdafx.h" at the beginning of dds.cpp must be uncommented. - - -Linking with an application using DDS -------------------------------------- -The InitStart() function of DDS should be called from inside the -application. Then SolveBoard in DDS can be called multiple times -without the overhead of InitStart() at each call. -For this purpose, the application code must have an include -statement for the dll.h file in DDS. - - -Maximum number of threads -------------------------- -The maximum number of simultaneous threads depends on the PC physical memory size: -1 GB or less, max 2 threads. -2 GB, max 4 threads. -3 or 4 GB, max 16 threads. - -For e.g. Windows, allocating memory for the maximum number of simultaneous threads can -be done by reading out the physical memory size from Windows. This is done in the DDS.DLL. -Another alternative is to provide the physical memory size as a parameter (gb_ram) in the -InitStart call. This alternative needs to be used when the operating system does not support -memory autoconfiguration. - - -Setting the number of simultaneous threads when calling CalcDDtable. --------------------------------------------------------------------- -For Windows, this can be done either by reading out the number of processor cores -and using this for setting the number of threads, or by supplying the number of -threads (ncores) in InitStart. This latter alternative needs to be used when the operating -system does not support reading out of the number of processors. - - -Options at DDS compilation --------------------------- -Compiling options: - -The SolveBoard and CalcDDtable are included in all DDS compilation options. -The "PBN" and the "PBN_PLUS" definitions are included in the header fill dll.h. -Defining "PBN" means that the functions SolveBoardPBN and CalcDDtablePBN are supported. -Defining "PBN_PLUS" as well means that also the functions SolveAllBoards, -SolveAllChunks, ParCalc and ParCalcPBN are supported. - -The possible configurations thus are: - -1) None of the definitions "PBN" and "PBN_plus": - only the basic functions SolveBoard and CalcDDtable are supported. -2) "PBN": Also support for SolveBoardPBN and CalcDDtablePBN. -3) "PBN" and "PBN_PLUS": As for "PBN" and also supporting SolveAllBoards, - SolveAllChunks, SolveAllTables, SolveAllTablesPBN, ParCalc and ParCalcPBN. - -Staying with the previous configuration might be needed when 2.5.1 is to replace an -older 2.x.y version, and the application using DDS cannot handle a changed interface. - - - - +DDS 2.4, Bo Haglund 2014-03-01 + +For Win32, DDS compiles with Visual C++ 2010 and 2012 Express editions +and the TDM-GCC/Mingw port of gcc. + +When using Visual C++, the statement +#include "stdafx.h" at the beginning of dds.cpp must be uncommented. + + +Linking with an application using DDS +------------------------------------- +The InitStart() function of DDS should be called from inside the +application. Then SolveBoard in DDS can be called multiple times +without the overhead of InitStart() at each call. +For this purpose, the application code must have an include +statement for the dll.h file in DDS. + + +Maximum number of threads +------------------------- +The maximum number of simultaneous threads depends on the PC physical memory size: +1 GB or less, max 2 threads. +2 GB, max 4 threads. +3 or 4 GB, max 16 threads. + +For e.g. Windows, allocating memory for the maximum number of simultaneous threads can +be done by reading out the physical memory size from Windows. This is done in the DDS.DLL. +Another alternative is to provide the physical memory size as a parameter (gb_ram) in the +InitStart call. This alternative needs to be used when the operating system does not support +memory autoconfiguration. + + +Setting the number of simultaneous threads when calling CalcDDtable. +-------------------------------------------------------------------- +For Windows, this can be done either by reading out the number of processor cores +and using this for setting the number of threads, or by supplying the number of +threads (ncores) in InitStart. This latter alternative needs to be used when the operating +system does not support reading out of the number of processors. + + +Options at DDS compilation +-------------------------- +Compiling options: + +The SolveBoard and CalcDDtable are included in all DDS compilation options. +The "PBN" and the "PBN_PLUS" definitions are included in the header fill dll.h. +Defining "PBN" means that the functions SolveBoardPBN and CalcDDtablePBN are supported. +Defining "PBN_PLUS" as well means that also the functions SolveAllBoards, +SolveAllChunks, ParCalc and ParCalcPBN are supported. + +The possible configurations thus are: + +1) None of the definitions "PBN" and "PBN_plus": + only the basic functions SolveBoard and CalcDDtable are supported. +2) "PBN": Also support for SolveBoardPBN and CalcDDtablePBN. +3) "PBN" and "PBN_PLUS": As for "PBN" and also supporting SolveAllBoards, + SolveAllChunks, SolveAllTables, SolveAllTablesPBN, ParCalc and ParCalcPBN. + +Staying with the previous configuration might be needed when 2.5.1 is to replace an +older 2.x.y version, and the application using DDS cannot handle a changed interface. + + + + diff --git a/release_notes.txt b/release_notes.txt index 97331869..7b0d7869 100755 --- a/release_notes.txt +++ b/release_notes.txt @@ -450,4 +450,10 @@ Release Notes DDS 2.5.1 The Windows DDS DLL always uses the Windows API for implementing the multithread functions (i.e. OpenMP is not used for Windows). +Release Notes DDS 2.5.2 +----------------------- +A fault in the par calculation has been fixed. The fault could cause +presentation of wrongly extra par contracts in cases were the sides had different +vulnerability. +