diff --git a/.gitignore b/.gitignore index 9461933f..3265db34 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,7 @@ test/itest *.exe *.swp *.bak + +*.exp +*.lib +*.res diff --git a/ChangeLog b/ChangeLog index bc54f55f..933f94ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +Release Notes DDS 2.9.0 beta +---------------------------- +Included code for a number of multi-threading systems: +- Windows API (was already there) +- OpenMP (was already there) +- GCD (new, intended for Mac, not really tested) +- Boost (new, works on many systems, but you may have to install it) +- STL (new, should work on most systems with a modern compiler) +- TBB (new, not so broadly available, but portable in principle) +- STLIMPL (new, experimental) +- PPLIMPL (new, experimental) + +Tested combinations include: +- Visual C++ with Windows API, OpenMP, Boost, STL +- Cygwin g++ with Windows API, OpenMP, Boost, STL +- mingw g++ with OpenMP, Boost, STL +- Linux g++ with OpenMP, Boost, STL +- MacOS clang with GCD, Boost, STL (static and shared library) +- MacOS GNU g++ with OpenMP, Boost, STL + +The number of threads is now unlimited in principle, although the +DLL will not let you go beyond the number of processor cores. + +Enabled the transposition-table code for both the large and the small +versions in the same DLL. Therefore there is only a single DLL +distributed now for both. The SMALL_MEMORY compile switch is gone. + +Enabled the DLL to pick the best combination of large and small +transposition tables for a given resource set-up consisting of +available memory and number of threads. Yes, the DLL can choose to +run 4 large and 2 small threads, for example. + +Expanded the DDSInfo systemString (which now needs 1024 chars as +stated in the new dll.h). + +MAXNOOFTABLES was increased from 32 to 40. + +Fixed a reliance that char == signed char (not the case on Android, +which caused a bug). + +Dealt with the reported issues on the GitHub issues list. + +Lots of clean-up of internal code. The code also looks more like C++. + + Release Notes DDS 2.8.4 ----------------------- Added a lower-memory DLL version with a compile flag. This is about diff --git a/INSTALL b/INSTALL index 1331b621..a61b4253 100644 --- a/INSTALL +++ b/INSTALL @@ -7,7 +7,7 @@ know what you're doing and you'll figure it out :-). The first step is to compile the library. -If you have trouble, read the Makefile. They all have the compiler +If you have trouble, read the Makefiles. They all have the compiler warning levels set rather high, and they are set to fail even on warnings. You can turn this off. The Visual C++ version also requires a couple of tools that you may not have, but this too is @@ -24,14 +24,14 @@ Generally speaking: the Makefile, then modify the Makefile. Once you've tested the source, you'll need the library file, the -dll.h include from the include directory, and possibly other files +dll.h include file from the include directory, and possibly other files such as dll.lib, depending on the exact system. You don't need include/portab.h, although you're welcome to use it. The library files needed are: Microsoft Visual C++: dds.dll, dds.lib mingw and cygwin: dds.dll, dds.def -Mac and linux: libdds.a +Mac and linux: libdds.a or libdds.so depending on compilation General instructions @@ -41,88 +41,139 @@ General instructions 2. Copy the right Makefile_... from the Makefiles sub-directory to the src directory and call it Makefile, see below. (Or use make -f) +So for example "cp Makefiles/Makefile_Visual Makefile". +See "System-specific data" below. -3. If your compiler does not have the name assumed in the Makefile -(see below), modify the Makefile. +3. Check the configuration section and make any changes you need. +- Section (1) has to do with paths for certain multi-threading systems + which you may or may not want/have. If you set a certain compiler + flag, it is your own responsibility that you have the corresponding + threading system available -- otherwise the code will not compile. +- Section (2) sets the threading systems with which you want to compile + the DLL. Note that you can have as many as you like (see below). +- Section (3) has to do with certain debugging flags etc. which you + normally shouldn't set. -4. If you don't have the "windres" and "cvtres" programs, -then you can also manage without. These are just used for -getting version information into the DLL. Delete the corresponding -lines. +3. Check the "Often OK" section, in particular the name of the +compiler you want to use. -5. If you want OpenMP rather than Windows multi-threading for -some reason, find the right place in the Makefile and uncomment -one line and comment the other. +4. If you're on Windows and you don't have the "windres" and +"cvtres" programs, then you can also manage without. These are +just used for getting version information into the DLL. Delete +the corresponding lines. -6. make clean (not necessary if you're starting clean). +6. "make clean" (not necessary if you're starting clean). -7. make depend (ditto). +7. There is a "make depend" target, but DO NOT USE IT. The Makefile +is set up to read the dependencies from Makefiles/depends_*.txt. -8. make (produces dds.dll on Windows, libdds.a on Linux and Mac). +8. "make" (produces dds.dll on Windows, libdds.a or libdds.so on +Linux and Mac). -9. make install (if you want to run tests; this is only a -local install to ../lib, not a system-wide one). +9. "make install" (if you want to run tests; this is only a +local install to ../test and ../examples, not a system-wide one). System-specific data ==================== -Microsoft Visual C++ (Unix-like, so Cygwin and mingw) +Microsoft Visual C++ -------------------- Makefile: Makefile_Visual Compiler: cl +If you don't have a Cygwin-like set-up with access to commands +such as "cp", see the last lines of that Makefile. -Microsoft Visual C++ (Windows-like, so no "mV", different "make") --------------------- -Makefile: Makefile_Visual_Windows -Compiler: cl - -Mingw ------ +Windows Mingw +------------- Makefile: Makefile_mingw -Compiler: i686-w64-mingw32-g++ - -32-bit and 64-bit variants for the tdc compiler are available. +Compiler: g++ -Cygwin ------- +Windows Cygwin +-------------- Makefile: Makefile_cygwin Compiler: g++ Linux (static library .a) -===== -Makefile: Makefile_linux +----- +Makefile: Makefile_linux_static Compiler: g++ -Linux (dynamic library .ld) -===== +Linux (dynamic library .so) +----- Makefile: Makefile_linux_shared Compiler: g++ -Apple -===== -Makefile: Makefile_Mac_clang (for clang compiler, single-threaded) +MacOS clang (static library .a) +----- +Makefile: Makefile_Mac_clang_static Compiler: g++ -Supports both OpenMP and GDD multi-threading. -Makefile: Makefile_Mac_gcc (for GNU g++ compiler, multi-threaded) -Makefile: Makefile_Mac_shared (for GNU g++ compiler, multi-threaded) + +MacOS clang (shared library .a) +----- +Makefile: Makefile_Mac_clang_static +Compiler: g++ + + +MacOS GNU g++ (static library .a) +----- +Makefile: Makefile_Mac_clang_static +Compiler: gcc-4.9 + + +MacOS GNU g++ (shared library .a) +----- +Makefile: Makefile_Mac_clang_static +Compiler: gcc-4.9 + + +Multi-threading +=============== + +As of v2.9.0 this works differently. It is possible to have +multiple threading systems in the same library. There is a new +DLL function called SetThreading() to select the one you want, +in case there is more than one. If the DLL is compiled only +single-threaded, that is what you'll get. If there are multiple +options, the DLL will default to the multi-threaded one with the +lowest number (among those compiled in, of course). The numbers +can be found in ../include/dll.h. + +It is NOT recommended to use STLIMPL and PPLIMPL as they are today. +You cannot control the number of threads that they will want, nor +the memory that they will consume. But maybe some day... + +The others are very equivalent in terms of speed, but you might as +well use STL if you have it, as this is probably the most portable. + +If you don't have a C++17 compiler, you will not get STLIMPL or +PPLIMPL. + +The *IMPL versions let the system handle threads autonomously +(up to the number of threads set by the user), whereas the others +are handled by DDS internally. The *IMPL version are similar in +speed, except if there is some near-duplication in the input hands +(say, instances of the same distribution played in the same +denomination from different side). The non-IMPL version handle +this more efficiently. Testing ======= The step "make install" above should have put the library file -in ../lib. +in ../test. test ---- +In the test directory you can compile the dtest program. This program tests five main modes of DDS: * solve, the solution of a hand for a given declarer and strain. @@ -135,9 +186,11 @@ The program can use a number of pre-defined input files in the ../hands directory. To compile the program, you follow the same steps as for the library, -except that you don't do a "make install". +except that you don't do a "make install". So you copy the right +Makefile from Makefiles (e.g. "cp Makefiles/Makefile_Visual Makefile"), +then type "make". -You now have a program called "dtest" or "dtest.exe". Let us +You should now have a program called "dtest" or "dtest.exe". Let us assume dtest.exe. Let us also assume that your system is set up in such a way that your path does not include the current working directory. @@ -147,19 +200,15 @@ You can invoke the program as ./dtest.exe which should just give a brief usage message. If that works, then -you can invoke the program like this: - -./dtest.exe file.txt mode [number of threads] - -file.txt has to be the name of a file EITHER in the current -directory OR in ../hands. The program checks first in the current -directory. A good starting example is list100.txt. +you can invoke the program like this, for example: -mode has to be one of solve, calc, play, parand dealerpar. +./dtest.exe -f ../hands/list100.txt -s solve -n 4 -m 1000 The number of threads is optional. If it is not supplied, DDS figures one out itself. If it is supplied, then it is passed to -SetMaxThreads(). +SetMaxThreads(). You can also use SetResources() instead of +SetMaxThreads() to set the memory consumption as well. If you use +SetResources(), there is no need to use SetMaxThreads(). Generally speaking, the test program first shows some information about how it was compiled. Then it shows some ongoing timing @@ -179,7 +228,7 @@ minimally to support a multi-threaded DLL. However, it doesn't use the full capabilities of DDS, as it was written at a time when functions such as CalcAllTables and SolveAllBoards were not yet available. Therefore it is rather slow, but it does have a nice -hand generator built in. +hand generator built in. It has not been updated since v2.8.4. examples diff --git a/README.md b/README.md index 0afa25f8..aec6bdce 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ DDS offers a wide range of functions, including par-score calculations. Please refer to the [home page](http://privat.bahnhof.se/wb758135) for details. -The current version is DDS 2.8.4 released in March 2016 and licensed under the Apache 2.0 license in the LICENSE FILE. +The current version is DDS 2.9.0 beta, released in May 2018 and licensed under the Apache 2.0 license in the LICENSE FILE. Release notes are in the ChangeLog file. -(c) Bo Haglund 2006-2014, (c) Bo Haglund / Soren Hein 2014-2016. +(c) Bo Haglund 2006-2014, (c) Bo Haglund / Soren Hein 2014-2018. Credits @@ -27,7 +27,7 @@ Foppe Hemminga maintains DDS on ArchLinux. He also contributed a version of the Pierre Cossard contributed the code for multi-threading on the Mac using GDS. -Soren Hein made a number of contributions before becoming a co-author starting in v2.8 in 2014. +Soren Hein made a number of contributions before becoming a co-author starting with v2.8 in 2014. Overview @@ -52,7 +52,7 @@ Supported systems ================= The DLLs work out of the box on Windows systems. There is a single-threaded version for old Windows versions, and there is a multi-threaded version that works on all modern Windows systems. This is the one you should use if in doubt. -The Windows versions use the Windows multi-threading. The code compiles on windows (see INSTALL) with at least: +The distributed Windows DLL uses Windows multi-threading. The code compiles on windows (see INSTALL) with at least: * Visual C++ 2010 Express editions or later. * The TDM-GCC/Mingw port of g++. @@ -73,20 +73,22 @@ The `without-multilib` is important because you won't get OpenMP otherwise, and Thanks for Pierre Cossard's contribution, the Mac port now also supports GCD multi-threading with LLVM. +There's an example .Net wrapper on https://github.com/anorsich/dds.net (not supported by us). + Usage ===== -DDS tries to figure out the available number of cores and the available memory. Based on this, DDS calculates a reasonable number of threads to use. The user can override this by calling the `SetMaxThreads()` function. In principle SetMaxThreads can be called multiple times, but there is overhead associated with this, so only call it at the beginning of your program unless you really want to change the number of threads dynamically. +DDS tries to figure out the available number of cores and the available memory. Based on this, DDS calculates a reasonable number of threads to use. The user can override this by calling the `SetMaxThreads()` or the `SetResources()` function. In principle these functions can be called multiple times, but there is overhead associated with this, so only call it at the beginning of your program unless you really want to change the number of threads dynamically. DDS on Windows calls SetMaxThreads itself when it is attached to a process, so you don't have to. On Unix-like systems we use an equivalent mechanism, but we have had a report that this does not always happen in the right order of things, so you may want to call SetMaxThreads explicitly. Docs ==== -The DDS library interface is very well documented. You find the docs, including a Markdown version which you can read online, in the /doc folder. +The DDS library interface is documented. You find the docs, including a Markdown version which you can read online, in the /doc folder. The Markdown version has not been updated since v2.8.4. Bugs ==== -Version 2.8.4 has no known bugs. +Version 2.9.0 beta has no known bugs. Please report bugs to bo.haglund@bahnhof.se and soren.hein@gmail.com. diff --git a/doc/DLL-dds_x.htm b/doc/DLL-dds_x.htm index 99488dd7..fb3bc21f 100644 --- a/doc/DLL-dds_x.htm +++ b/doc/DLL-dds_x.htm @@ -7448,7 +7448,7 @@

 

CallAllTables calculates the +style='font-family:"Calibri",sans-serif;color:black'>CalcAllTables calculates the double dummy values of the denomination/declarer hand combinations in “*dealsp”The maximum number of DD -tables in a CallAllTables call depends on the number of strains required, see +tables in a CalcAllTables call depends on the number of strains required, see the following table:

color:black'> 

CallAllTables calcul= +style=3D'font-family:"Calibri",sans-serif;color:black'>CalcAllTables calcul= ates the double dummy values of the denomination/declarer hand combinations in  

The maximum number o= f DD -tables in a CallAllTables call depends on the number of strains required, s= +tables in a CalcAllTables call depends on the number of strains required, s= ee the following table:

diff --git a/doc/DLL-dds_x.rtf b/doc/DLL-dds_x.rtf index 90aeee7b..eb3bbbd7 100644 --- a/doc/DLL-dds_x.rtf +++ b/doc/DLL-dds_x.rtf @@ -1,30 +1,31 @@ {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff1\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang1031\deflangfe1031\themelang1053\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;} {\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri{\*\falt Calibri};}{\f39\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} -{\f115\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\f40\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\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{\*\falt Calibri};} -{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f310\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f311\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} -{\f313\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f314\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f315\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f316\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} -{\f317\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f318\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f320\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f321\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} -{\f323\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f324\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f325\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f326\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} -{\f327\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f328\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f330\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f331\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} -{\f333\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f334\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f335\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f336\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} -{\f337\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f338\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f650\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f651\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} -{\f653\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f654\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f657\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f658\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} -{\f680\fbidi \fswiss\fcharset238\fprq2 Calibri CE{\*\falt Calibri};}{\f681\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr{\*\falt Calibri};}{\f683\fbidi \fswiss\fcharset161\fprq2 Calibri Greek{\*\falt Calibri};} -{\f684\fbidi \fswiss\fcharset162\fprq2 Calibri Tur{\*\falt Calibri};}{\f687\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Calibri};}{\f688\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Calibri};} -{\f700\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f701\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\f703\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f704\fbidi \froman\fcharset162\fprq2 Cambria Tur;} -{\f707\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f708\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\f1460\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f1461\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;} -{\f1463\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f1464\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}{\f1465\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f1466\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);} -{\f1467\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f1468\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f1469\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\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;} +{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f268\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f269\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\f271\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f272\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f273\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f274\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\f275\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f276\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f278\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f279\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} +{\f281\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f282\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f283\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f284\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} +{\f285\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f286\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f288\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f289\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;} +{\f291\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f292\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f293\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f294\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);} +{\f295\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f296\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f608\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f609\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} +{\f611\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f612\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f615\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f616\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} +{\f638\fbidi \fswiss\fcharset238\fprq2 Calibri CE{\*\falt Calibri};}{\f639\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr{\*\falt Calibri};}{\f641\fbidi \fswiss\fcharset161\fprq2 Calibri Greek{\*\falt Calibri};} +{\f642\fbidi \fswiss\fcharset162\fprq2 Calibri Tur{\*\falt Calibri};}{\f643\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew){\*\falt Calibri};}{\f644\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic){\*\falt Calibri};} +{\f645\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Calibri};}{\f646\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Calibri};}{\f658\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\f659\fbidi \froman\fcharset204\fprq2 Cambria Cyr;} +{\f661\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\f662\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\f665\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\f666\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);} +{\f668\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;}{\f669\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f671\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f672\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;} +{\f673\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f674\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f675\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f676\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);} +{\f677\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);}{\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;} @@ -35,25 +36,26 @@ {\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{\*\falt Calibri};} {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr{\*\falt Calibri};}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek{\*\falt Calibri};}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur{\*\falt Calibri};} -{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Calibri};}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Calibri};}{\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; -\chyperlink\ctint255\cshade255\red0\green0\blue255;\cfollowedhyperlink\ctint255\cshade255\red128\green0\blue128;\red0\green112\blue192;}{\*\defchp \f37 }{\*\defpap \ql \li0\ri0\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 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 \snext0 \sqformat \spriority0 \styrsid12400949 Normal;}{ -\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\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 \f1\fs24\lang1033\langfe1053\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 \f1\fs24\lang1033\langfe1053\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\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew){\*\falt Calibri};}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic){\*\falt Calibri};}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Calibri};} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Calibri};}{\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;\chyperlink\ctint255\cshade255\red0\green0\blue255;\cfollowedhyperlink\ctint255\cshade255\red128\green0\blue128;\red0\green112\blue192;} +{\*\defchp \f37 }{\*\defpap \ql \li0\ri0\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 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 \snext0 \sqformat \spriority0 \styrsid12400949 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\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 +\f1\fs24\lang1033\langfe1053\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 +\f1\fs24\lang1033\langfe1053\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\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs20\alang1025 \ltrch\fcs0 \f37\fs20\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\f39\fs32\lang1033\langfe0\kerning32\langnp1033\langfenp0 \sbasedon10 \slink1 \slocked \spriority9 \'dcberschrift 1 Zchn;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\i\f39\fs28\lang1033\langfe0\langnp1033\langfenp0 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 \'dcberschrift 2 Zchn;}{\*\cs17 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \b\f39\fs26\lang1033\langfe0\langnp1033\langfenp0 \sbasedon10 \slink3 \slocked \ssemihidden \spriority9 \'dcberschrift 3 Zchn;}{\*\ts18\tsrowd\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \f37\fs20\lang1031\langfe1031\cgrid\langnp1031\langfenp1031 \sbasedon11 \snext18 \spriority59 \styrsid1789909 Table Grid;}{ -\s19\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af115\afs16\alang1025 \ltrch\fcs0 \f115\fs16\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext19 \slink20 \ssemihidden \sunhideused \styrsid5376200 -Balloon Text;}{\*\cs20 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f115\fs16\lang1033\langfe1053\langnp1033\langfenp1053 \sbasedon10 \slink19 \slocked \ssemihidden \styrsid5376200 Sprechblasentext Zchn;}{\s21\ql \li0\ri0\nowidctlpar +\s19\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af40\afs16\alang1025 \ltrch\fcs0 \f40\fs16\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext19 \slink20 \ssemihidden \sunhideused \styrsid5376200 Balloon Text;} +{\*\cs20 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f40\fs16\lang1033\langfe1053\langnp1033\langfenp1053 \sbasedon10 \slink19 \slocked \ssemihidden \styrsid5376200 Sprechblasentext Zchn;}{\s21\ql \li0\ri0\nowidctlpar \tqc\tx4536\tqr\tx9072\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 \sbasedon0 \snext21 \slink22 \sunhideused \styrsid14119459 header;}{\*\cs22 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\langnp1033\langfenp1053 \sbasedon10 \slink21 \slocked \styrsid14119459 Kopfzeile Zchn;}{\s23\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1031\langfe1033\cgrid\langnp1031\langfenp1033 \snext23 \sqformat \spriority1 \styrsid2849436 No Spacing;}{\s24\ql \li0\ri0\nowidctlpar\tqc\tx4536\tqr\tx9072\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 @@ -85,209 +87,331 @@ Balloon Text;}{\*\cs20 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \f115\fs16\lang103 {\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4170\lin4170 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617 \'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4890\lin4890 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5610\lin5610 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6330\lin6330 }{\listname -;}\listid161943208}{\list\listtemplateid1379147632\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\leveltemplateid-926013378\'01\u-3913 ?;}{\levelnumbers;} -\loch\af3\hich\af3\dbch\af0\fbias0 \fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 -\fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel -\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 -\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 -\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 -\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621 -\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid356662528}{\list\listtemplateid-1508340354\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0 -{\leveltext\leveltemplateid728809608\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af0\fbias0 \fi-360\li570\lin570 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1290\lin1290 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621 -\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2010\lin2010 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;} -\f3\fbias0 \fi-360\li2730\lin2730 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3450\lin3450 } -{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4170\lin4170 }{\listlevel\levelnfc23\levelnfcn23 -\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4890\lin4890 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 -\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5610\lin5610 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 -\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6330\lin6330 }{\listname ;}\listid871384482}{\list\listtemplateid59153134\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 -\levelstartat3\levelspace0\levelindent0{\leveltext\leveltemplateid-320719486\'01\u-3986 ?;}{\levelnumbers;}\loch\af10\hich\af10\dbch\af0\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 -\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 -{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617 -\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 -\fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel -\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 -\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 -\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid880896998}{\list\listtemplateid1722038506\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0 -\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0 -\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009433\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1 -\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009435\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative -\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 -\levelindent0{\leveltext\leveltemplateid69009433\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 -{\leveltext\leveltemplateid69009435\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid69009423\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid69009433\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid69009435\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid894395624}{\list\listtemplateid-681416416\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0 -\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative -\levelspace0\levelindent0{\leveltext\leveltemplateid69009433\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0 -\levelindent0{\leveltext\leveltemplateid69009435\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 -{\leveltext\leveltemplateid69009423\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +;}\listid161943208}{\list\listtemplateid-1463488010\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 +\fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1080\lin1080 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360 +\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;} +\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid229731547}{\list\listtemplateid1379147632\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\leveltemplateid-926013378 +\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af0\fbias0 \fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 +\fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid356662528}{\list\listtemplateid-1451302670\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0 +{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23 +\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid830560009}{\list\listtemplateid-1508340354\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid728809608\'01\u-3913 ?;}{\levelnumbers;}\loch\af3\hich\af3\dbch\af0\fbias0 \fi-360\li570\lin570 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1290\lin1290 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2010\lin2010 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2730\lin2730 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3450\lin3450 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 +\fi-360\li4170\lin4170 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4890\lin4890 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5610\lin5610 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6330\lin6330 }{\listname ;}\listid871384482}{\list\listtemplateid59153134\listhybrid{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\leveltemplateid-320719486\'01\u-3986 ?;}{\levelnumbers;}\loch\af10\hich\af10\dbch\af0\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid880896998} +{\list\listtemplateid180496522\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li360\lin360 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 } +{\listname ;}\listid885608239}{\list\listtemplateid1722038506\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 +\af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009433\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 +\ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009435\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009433\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009435\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009423\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009433\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid69009435\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 +\fi-180\li6480\lin6480 }{\listname ;}\listid894395624}{\list\listtemplateid-1142497534\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative +\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0 +{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid1203058793}{\list\listtemplateid-681416416\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\leveltemplateid69009423\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid69009433\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid69009435\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid69009423\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext \leveltemplateid69009433\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext \leveltemplateid69009435\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext \leveltemplateid69009423\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext \leveltemplateid69009433\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext -\leveltemplateid69009435\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid1355108172}}{\*\listoverridetable{\listoverride\listid880896998\listoverridecount0\ls1}{\listoverride\listid111049838 -\listoverridecount0\ls2}{\listoverride\listid356662528\listoverridecount0\ls3}{\listoverride\listid894395624\listoverridecount0\ls4}{\listoverride\listid1355108172\listoverridecount0\ls5}{\listoverride\listid161943208\listoverridecount0\ls6} -{\listoverride\listid60494166\listoverridecount0\ls7}{\listoverride\listid871384482\listoverridecount0\ls8}}{\*\revtbl {Unknown;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid7744\rsid70445\rsid75593\rsid81923\rsid133834\rsid163452\rsid201282\rsid269493 -\rsid270015\rsid337766\rsid340960\rsid348894\rsid394021\rsid409864\rsid415956\rsid425889\rsid488565\rsid490522\rsid532764\rsid543320\rsid556337\rsid591688\rsid617158\rsid619035\rsid678750\rsid726458\rsid750270\rsid750573\rsid856123\rsid875686\rsid876335 -\rsid930020\rsid940090\rsid943124\rsid1056208\rsid1187219\rsid1190356\rsid1191142\rsid1202844\rsid1212155\rsid1258951\rsid1261441\rsid1313463\rsid1336469\rsid1385888\rsid1386919\rsid1445386\rsid1449865\rsid1469964\rsid1520891\rsid1538933\rsid1579764 -\rsid1595222\rsid1596512\rsid1706832\rsid1708722\rsid1716250\rsid1716707\rsid1721597\rsid1770393\rsid1775603\rsid1783690\rsid1789515\rsid1789909\rsid1800033\rsid1839042\rsid1846101\rsid1852854\rsid1900643\rsid1910210\rsid1918919\rsid1921007\rsid2057006 -\rsid2060511\rsid2101911\rsid2112235\rsid2112392\rsid2123303\rsid2165691\rsid2181632\rsid2229366\rsid2238558\rsid2244172\rsid2260548\rsid2365273\rsid2369496\rsid2427760\rsid2443070\rsid2446079\rsid2447429\rsid2449260\rsid2493172\rsid2494613\rsid2505631 -\rsid2566533\rsid2568164\rsid2635362\rsid2637590\rsid2641133\rsid2647507\rsid2769001\rsid2833141\rsid2838088\rsid2849436\rsid2884635\rsid2894529\rsid2952804\rsid3023369\rsid3034397\rsid3034548\rsid3036029\rsid3095740\rsid3167271\rsid3220430\rsid3228943 -\rsid3231049\rsid3240706\rsid3243212\rsid3301731\rsid3303530\rsid3308555\rsid3342996\rsid3347855\rsid3352595\rsid3547548\rsid3552042\rsid3567911\rsid3752772\rsid3819803\rsid3893966\rsid3937665\rsid3954019\rsid4000336\rsid4002451\rsid4071901\rsid4076363 -\rsid4091367\rsid4155951\rsid4264099\rsid4268479\rsid4272774\rsid4288894\rsid4330566\rsid4350787\rsid4405244\rsid4460289\rsid4460640\rsid4475334\rsid4533879\rsid4538894\rsid4542728\rsid4545218\rsid4602097\rsid4616356\rsid4658062\rsid4675069\rsid4679222 -\rsid4679726\rsid4683401\rsid4738929\rsid4744549\rsid4877901\rsid4981561\rsid5054625\rsid5070438\rsid5113162\rsid5186751\rsid5191231\rsid5248313\rsid5254237\rsid5318615\rsid5320216\rsid5332441\rsid5376200\rsid5388872\rsid5462095\rsid5506187\rsid5519688 -\rsid5525810\rsid5526679\rsid5532374\rsid5594575\rsid5638529\rsid5650157\rsid5653460\rsid5712409\rsid5712463\rsid5767474\rsid5779433\rsid5843075\rsid5862788\rsid5927621\rsid5928646\rsid5974982\rsid5979431\rsid6045873\rsid6047888\rsid6048783\rsid6054214 -\rsid6058144\rsid6099241\rsid6115982\rsid6164997\rsid6170015\rsid6179193\rsid6228168\rsid6246771\rsid6247188\rsid6302457\rsid6309374\rsid6309794\rsid6313661\rsid6317456\rsid6362316\rsid6377474\rsid6384684\rsid6436444\rsid6499600\rsid6516102\rsid6557897 -\rsid6557970\rsid6569652\rsid6570883\rsid6573516\rsid6578564\rsid6580905\rsid6629265\rsid6633554\rsid6641819\rsid6643870\rsid6650094\rsid6699576\rsid6701983\rsid6771888\rsid6845226\rsid6894851\rsid6895698\rsid6901705\rsid6910245\rsid6950962\rsid6957422 -\rsid6968528\rsid7041439\rsid7089377\rsid7167315\rsid7277737\rsid7285964\rsid7302518\rsid7305895\rsid7415269\rsid7421144\rsid7483127\rsid7542885\rsid7545453\rsid7616262\rsid7678768\rsid7683346\rsid7686926\rsid7697883\rsid7759131\rsid7763137\rsid7804526 -\rsid7807046\rsid7880574\rsid7931676\rsid7949161\rsid7952569\rsid7959800\rsid7998566\rsid8000484\rsid8001475\rsid8090374\rsid8129941\rsid8137115\rsid8154048\rsid8194765\rsid8261617\rsid8281290\rsid8290285\rsid8323199\rsid8395240\rsid8408337\rsid8522857 -\rsid8527940\rsid8538722\rsid8541195\rsid8549130\rsid8588264\rsid8592696\rsid8593145\rsid8610523\rsid8616569\rsid8655475\rsid8682482\rsid8799536\rsid8923128\rsid8939615\rsid8983788\rsid8984001\rsid8999377\rsid9000425\rsid9002512\rsid9047914\rsid9069276 -\rsid9125746\rsid9175287\rsid9176944\rsid9249735\rsid9306501\rsid9314635\rsid9315241\rsid9331762\rsid9389132\rsid9401184\rsid9450855\rsid9515364\rsid9515749\rsid9530285\rsid9534906\rsid9572146\rsid9586997\rsid9588289\rsid9589735\rsid9713208\rsid9716036 -\rsid9716705\rsid9731125\rsid9834330\rsid9838060\rsid9845272\rsid9851850\rsid9856546\rsid9898065\rsid9907738\rsid9911854\rsid9974881\rsid10056466\rsid10108539\rsid10122796\rsid10173450\rsid10174318\rsid10176355\rsid10239463\rsid10245607\rsid10290420 -\rsid10308289\rsid10310988\rsid10313626\rsid10376323\rsid10383915\rsid10423813\rsid10426263\rsid10452726\rsid10486826\rsid10487319\rsid10490777\rsid10496751\rsid10567623\rsid10576044\rsid10616963\rsid10631094\rsid10646944\rsid10698169\rsid10774562 -\rsid10813614\rsid10831092\rsid10838587\rsid10843677\rsid10967321\rsid11030455\rsid11078728\rsid11089766\rsid11099036\rsid11107656\rsid11149793\rsid11173409\rsid11276707\rsid11277669\rsid11279197\rsid11280091\rsid11294126\rsid11297517\rsid11344057 -\rsid11351616\rsid11367514\rsid11540483\rsid11562205\rsid11762622\rsid11801900\rsid11805493\rsid11868543\rsid11882119\rsid11930665\rsid11946565\rsid11952575\rsid11956256\rsid11958279\rsid12008966\rsid12014436\rsid12065713\rsid12068517\rsid12069216 -\rsid12071252\rsid12087407\rsid12128238\rsid12156867\rsid12210879\rsid12400949\rsid12408664\rsid12460046\rsid12520971\rsid12530193\rsid12595610\rsid12595779\rsid12615130\rsid12649012\rsid12657542\rsid12658578\rsid12658900\rsid12659025\rsid12720965 -\rsid12732549\rsid12739696\rsid12788235\rsid12797083\rsid12854747\rsid12874235\rsid12914880\rsid12915233\rsid12941889\rsid12982360\rsid12983768\rsid12986669\rsid12992185\rsid12998134\rsid13053124\rsid13071121\rsid13072585\rsid13174672\rsid13180120 -\rsid13200681\rsid13244366\rsid13250408\rsid13267252\rsid13316938\rsid13319718\rsid13321745\rsid13331862\rsid13336457\rsid13444065\rsid13452191\rsid13457490\rsid13530431\rsid13593709\rsid13641876\rsid13697230\rsid13701456\rsid13703926\rsid13714332 -\rsid13771084\rsid13780248\rsid13840817\rsid13857996\rsid13902528\rsid13902769\rsid13915886\rsid14090435\rsid14092583\rsid14095979\rsid14098709\rsid14102810\rsid14119459\rsid14169293\rsid14171083\rsid14292727\rsid14295269\rsid14307787\rsid14370947 -\rsid14429502\rsid14435334\rsid14436934\rsid14444034\rsid14498845\rsid14574742\rsid14634080\rsid14636249\rsid14814422\rsid14892228\rsid15031452\rsid15079468\rsid15084961\rsid15088206\rsid15150655\rsid15283250\rsid15291332\rsid15299259\rsid15413752 -\rsid15420320\rsid15490742\rsid15613967\rsid15620535\rsid15664614\rsid15668792\rsid15679176\rsid15744623\rsid15747980\rsid15755105\rsid15757396\rsid15800872\rsid15821976\rsid15824246\rsid15932640\rsid15937974\rsid15939092\rsid15941930\rsid15999168 -\rsid16002722\rsid16012515\rsid16021753\rsid16057925\rsid16132195\rsid16147558\rsid16151628\rsid16189992\rsid16206388\rsid16217378\rsid16276961\rsid16323149\rsid16348565\rsid16386593\rsid16401568\rsid16405367\rsid16456729\rsid16467273\rsid16470149 -\rsid16530750\rsid16534708\rsid16585076\rsid16599140\rsid16609230\rsid16610750\rsid16655487\rsid16662276\rsid16676162\rsid16715055\rsid16720464\rsid16724586\rsid16731528}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0 -\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Soren Hein}{\operator Soren Hein}{\creatim\yr2014\mo11\dy18\hr12\min16}{\revtim\yr2016\mo3\dy20\hr10\min12}{\printim\yr2016\mo1\dy1\hr23\min11}{\version22}{\edmins0}{\nofpages22}{\nofwords6014} -{\nofchars37891}{\*\company HP}{\nofcharsws43818}{\vern57439}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1417\gutter0\ltrsect +\leveltemplateid69009435\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid1355108172}{\list\listtemplateid-1975356656\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li360\lin360 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360 +\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1080\lin1080 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext +\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3960\lin3960 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567617\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567619\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5400\lin5400 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace360\levelindent0{\leveltext\leveltemplateid67567621\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6120\lin6120 }{\listname ;}\listid1369648479}}{\*\listoverridetable{\listoverride\listid880896998 +\listoverridecount0\ls1}{\listoverride\listid111049838\listoverridecount0\ls2}{\listoverride\listid356662528\listoverridecount0\ls3}{\listoverride\listid894395624\listoverridecount0\ls4}{\listoverride\listid1355108172\listoverridecount0\ls5} +{\listoverride\listid161943208\listoverridecount0\ls6}{\listoverride\listid60494166\listoverridecount0\ls7}{\listoverride\listid871384482\listoverridecount0\ls8}{\listoverride\listid1203058793\listoverridecount0\ls9}{\listoverride\listid1369648479 +\listoverridecount0\ls10}{\listoverride\listid885608239\listoverridecount0\ls11}{\listoverride\listid830560009\listoverridecount0\ls12}{\listoverride\listid229731547\listoverridecount0\ls13}}{\*\revtbl {Unknown;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}} +{\*\rsidtbl \rsid7744\rsid70445\rsid75593\rsid81923\rsid133834\rsid163452\rsid201282\rsid269493\rsid270015\rsid337766\rsid340960\rsid348894\rsid394021\rsid409864\rsid415956\rsid425889\rsid488565\rsid490522\rsid532764\rsid543320\rsid556337\rsid591688 +\rsid617158\rsid619035\rsid678750\rsid726458\rsid750270\rsid750573\rsid856123\rsid875686\rsid876335\rsid930020\rsid940090\rsid943124\rsid1056208\rsid1187219\rsid1190356\rsid1191142\rsid1202844\rsid1212155\rsid1258951\rsid1261441\rsid1313463\rsid1336469 +\rsid1385888\rsid1386919\rsid1389500\rsid1445386\rsid1449865\rsid1469964\rsid1520891\rsid1538933\rsid1579764\rsid1595222\rsid1596512\rsid1706832\rsid1708722\rsid1716250\rsid1716707\rsid1721597\rsid1770393\rsid1775603\rsid1783690\rsid1789515\rsid1789909 +\rsid1800033\rsid1839042\rsid1846101\rsid1852854\rsid1900643\rsid1910210\rsid1918919\rsid1921007\rsid2057006\rsid2060511\rsid2101911\rsid2112235\rsid2112392\rsid2123303\rsid2165691\rsid2181632\rsid2229366\rsid2238558\rsid2244172\rsid2260548\rsid2365273 +\rsid2369496\rsid2427760\rsid2443070\rsid2446079\rsid2447429\rsid2449260\rsid2493172\rsid2494613\rsid2504324\rsid2505631\rsid2566533\rsid2568164\rsid2623319\rsid2635362\rsid2637590\rsid2641133\rsid2647507\rsid2769001\rsid2833141\rsid2838088\rsid2849436 +\rsid2884635\rsid2894529\rsid2952804\rsid3023369\rsid3034397\rsid3034548\rsid3036029\rsid3095740\rsid3167271\rsid3220430\rsid3228943\rsid3231049\rsid3240706\rsid3243212\rsid3301731\rsid3303530\rsid3308555\rsid3342996\rsid3347855\rsid3352595\rsid3547548 +\rsid3552042\rsid3567911\rsid3752772\rsid3819803\rsid3893966\rsid3937665\rsid3954019\rsid4000336\rsid4002451\rsid4071901\rsid4076363\rsid4091367\rsid4155951\rsid4264099\rsid4268479\rsid4272774\rsid4288894\rsid4330566\rsid4350787\rsid4405244\rsid4460289 +\rsid4460640\rsid4475334\rsid4533879\rsid4538894\rsid4542728\rsid4545218\rsid4602097\rsid4616356\rsid4658062\rsid4675069\rsid4679222\rsid4679726\rsid4683401\rsid4738929\rsid4744549\rsid4877901\rsid4981561\rsid5054625\rsid5070438\rsid5113162\rsid5186751 +\rsid5191231\rsid5248313\rsid5254237\rsid5318615\rsid5320216\rsid5332441\rsid5376200\rsid5388872\rsid5399796\rsid5462095\rsid5506187\rsid5519688\rsid5525810\rsid5526679\rsid5532374\rsid5594575\rsid5638529\rsid5650157\rsid5653460\rsid5712409\rsid5712463 +\rsid5767474\rsid5779433\rsid5843075\rsid5862788\rsid5902855\rsid5927621\rsid5928646\rsid5974982\rsid5979431\rsid6045873\rsid6047888\rsid6048783\rsid6054214\rsid6058144\rsid6099241\rsid6115982\rsid6164997\rsid6170015\rsid6179193\rsid6228168\rsid6246771 +\rsid6247188\rsid6302457\rsid6309374\rsid6309794\rsid6313661\rsid6317456\rsid6318629\rsid6362316\rsid6377474\rsid6378612\rsid6384684\rsid6436444\rsid6499600\rsid6516102\rsid6557897\rsid6557970\rsid6569652\rsid6570883\rsid6573516\rsid6578564\rsid6580905 +\rsid6629265\rsid6633554\rsid6641819\rsid6643870\rsid6650094\rsid6699576\rsid6701983\rsid6771888\rsid6839745\rsid6845226\rsid6894851\rsid6895698\rsid6901705\rsid6910245\rsid6950962\rsid6957422\rsid6968528\rsid6975890\rsid7019779\rsid7041439\rsid7089377 +\rsid7167315\rsid7277737\rsid7285964\rsid7302518\rsid7305895\rsid7350065\rsid7415269\rsid7421144\rsid7472903\rsid7483127\rsid7542885\rsid7545453\rsid7560207\rsid7616262\rsid7678768\rsid7683346\rsid7686926\rsid7697883\rsid7759131\rsid7763137\rsid7804526 +\rsid7807046\rsid7880574\rsid7880615\rsid7931676\rsid7949161\rsid7952569\rsid7959800\rsid7998566\rsid8000484\rsid8001475\rsid8090374\rsid8129941\rsid8137115\rsid8154048\rsid8194765\rsid8261617\rsid8281290\rsid8290285\rsid8323199\rsid8395240\rsid8408337 +\rsid8522857\rsid8527940\rsid8538722\rsid8541195\rsid8549130\rsid8588264\rsid8592696\rsid8593145\rsid8610523\rsid8616569\rsid8655475\rsid8682482\rsid8799536\rsid8923128\rsid8939615\rsid8983788\rsid8984001\rsid8997327\rsid8999377\rsid9000425\rsid9002512 +\rsid9047914\rsid9069276\rsid9125746\rsid9175287\rsid9176944\rsid9249735\rsid9306501\rsid9314635\rsid9315241\rsid9331762\rsid9389132\rsid9401184\rsid9450855\rsid9515364\rsid9515749\rsid9530285\rsid9534906\rsid9572146\rsid9586997\rsid9588289\rsid9589735 +\rsid9713208\rsid9716036\rsid9716705\rsid9731125\rsid9834330\rsid9838060\rsid9845272\rsid9851850\rsid9856546\rsid9898065\rsid9907738\rsid9911854\rsid9974881\rsid9977698\rsid10056466\rsid10108539\rsid10122796\rsid10173450\rsid10174318\rsid10176355 +\rsid10239463\rsid10245607\rsid10290420\rsid10308289\rsid10310988\rsid10313626\rsid10376323\rsid10383915\rsid10423813\rsid10426263\rsid10452726\rsid10486826\rsid10487319\rsid10490777\rsid10496751\rsid10567623\rsid10576044\rsid10616963\rsid10631094 +\rsid10646944\rsid10698169\rsid10774562\rsid10813614\rsid10831092\rsid10838587\rsid10843677\rsid10967321\rsid11030455\rsid11078728\rsid11089766\rsid11099036\rsid11107656\rsid11149793\rsid11173409\rsid11276707\rsid11277669\rsid11279197\rsid11280091 +\rsid11294126\rsid11297517\rsid11301755\rsid11344057\rsid11351616\rsid11367514\rsid11540483\rsid11562205\rsid11762622\rsid11801900\rsid11805493\rsid11868543\rsid11882119\rsid11930665\rsid11946565\rsid11952575\rsid11956256\rsid11958279\rsid12008966 +\rsid12014436\rsid12065713\rsid12068517\rsid12069172\rsid12069216\rsid12071252\rsid12087407\rsid12128238\rsid12156867\rsid12198414\rsid12203684\rsid12210879\rsid12400949\rsid12408664\rsid12460046\rsid12520971\rsid12530193\rsid12595610\rsid12595779 +\rsid12615130\rsid12649012\rsid12657542\rsid12658578\rsid12658900\rsid12659025\rsid12720965\rsid12732549\rsid12739696\rsid12788235\rsid12797083\rsid12854747\rsid12874235\rsid12914880\rsid12915233\rsid12941889\rsid12982360\rsid12983768\rsid12986669 +\rsid12992185\rsid12998134\rsid13042502\rsid13053124\rsid13071121\rsid13072585\rsid13174672\rsid13180120\rsid13200681\rsid13244366\rsid13250408\rsid13267252\rsid13316938\rsid13319718\rsid13321745\rsid13331862\rsid13336457\rsid13444065\rsid13452191 +\rsid13457490\rsid13530431\rsid13593709\rsid13641876\rsid13697230\rsid13701456\rsid13703926\rsid13714332\rsid13771084\rsid13780248\rsid13840817\rsid13843369\rsid13857996\rsid13902528\rsid13902769\rsid13915886\rsid14090435\rsid14092583\rsid14095979 +\rsid14098709\rsid14102810\rsid14119459\rsid14169293\rsid14171083\rsid14292727\rsid14295269\rsid14307787\rsid14310469\rsid14368275\rsid14370947\rsid14429502\rsid14435334\rsid14436934\rsid14444034\rsid14498845\rsid14574742\rsid14579995\rsid14634080 +\rsid14636249\rsid14814422\rsid14892228\rsid15031452\rsid15079468\rsid15084961\rsid15088206\rsid15150655\rsid15283250\rsid15291332\rsid15299259\rsid15413752\rsid15420320\rsid15490742\rsid15613967\rsid15620535\rsid15664614\rsid15668792\rsid15679176 +\rsid15744623\rsid15747980\rsid15755105\rsid15757396\rsid15800872\rsid15821976\rsid15824246\rsid15932640\rsid15937974\rsid15939092\rsid15941930\rsid15999168\rsid16002722\rsid16012515\rsid16021753\rsid16057925\rsid16132195\rsid16147558\rsid16151628 +\rsid16189992\rsid16206388\rsid16217378\rsid16264811\rsid16276961\rsid16323149\rsid16348565\rsid16386593\rsid16401568\rsid16405367\rsid16456729\rsid16467273\rsid16470149\rsid16530750\rsid16534708\rsid16585076\rsid16599140\rsid16609230\rsid16610750 +\rsid16655487\rsid16662276\rsid16676162\rsid16713324\rsid16715055\rsid16720464\rsid16724586\rsid16731528}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info +{\author Soren Hein}{\operator Soren Hein}{\creatim\yr2014\mo11\dy18\hr12\min16}{\revtim\yr2018\mo4\dy1\hr15\min2}{\printim\yr2016\mo1\dy1\hr23\min11}{\version35}{\edmins0}{\nofpages22}{\nofwords6173}{\nofchars38892}{\*\company HP}{\nofcharsws44976} +{\vern57445}}{\*\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\donotembedlingdata0\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120 \dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\splytwnine\ftnlytwnine\htmautsp\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct\asianbrkrule\rsidroot4538894 \newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450} \nofeaturethrottle1\ilfomacatclnup0{\*\ftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14119459 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 { -\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3167271 \chftnsep +\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12069172 \chftnsep \par }}{\*\ftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14119459 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\insrsid3167271 \chftnsepc +\insrsid12069172 \chftnsepc \par }}{\*\aftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14119459 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\insrsid3167271 \chftnsep +\insrsid12069172 \chftnsep \par }}{\*\aftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14119459 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\insrsid3167271 \chftnsepc +\insrsid12069172 \chftnsepc \par }}\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\footerr \ltrpar \pard\plain \ltrpar\s24\qc \li0\ri0\nowidctlpar\tqc\tx4536\tqr\tx9072\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 -\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7483127\charrsid14119459 PAGE \\* MERGEFORMAT}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\lang1024\langfe1024\noproof\langnp1031\insrsid11030455\charrsid11030455 18}}}\sectd \ltrsect\linex0\endnhere\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7483127\charrsid14119459 -\par }\pard \ltrpar\s24\ql \li0\ri0\nowidctlpar\tqc\tx4536\tqr\tx9072\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7483127 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6318629\charrsid14119459 PAGE \\* MERGEFORMAT}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\lang1024\langfe1024\noproof\langnp1031\insrsid5902855\charrsid5902855 22}}}\sectd \ltrsect\linex0\endnhere\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6318629\charrsid14119459 +\par }\pard \ltrpar\s24\ql \li0\ri0\nowidctlpar\tqc\tx4536\tqr\tx9072\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6318629 \par }}{\*\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 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\lang1031\langfe1053\langnp1031\insrsid6650094\charrsid16456729 Bo Haglund, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\lang1031\langfe1053\langnp1031\insrsid2123303\charrsid16456729 Soren Hein, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\lang1031\langfe1053\langnp1031\insrsid6650094\charrsid16456729 Bob Richardson -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11030455 Rev Z}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid16720464 , 2016-01-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6650094\charrsid14119459 -\par Latest DLL issue with this description is available at }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid15824246 HYPERLINK "http://www.bahnhof.se/wb758135/" }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\cf19\insrsid2101911\charrsid15824246 {\*\datafield +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11301755 Rev AA, 2018-04-01}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6650094\charrsid14119459 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11301755 GitHub releases are}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9977698 available}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid11301755 at }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af37 \ltrch\fcs0 +\f31506\ul\cf19\insrsid11301755\charrsid16264811 HYPERLINK "https://github.com/dds-bridge/dds/releases" }{\rtlch\fcs1 \af37 \ltrch\fcs0 \f31506\ul\cf19\insrsid16264811\charrsid16264811 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6e000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f006400640073002d006200720069006400670065002f006400640073002f00720065006c006500610073006500 +73000000795881f43b1d7f48af2c825dc485276300000000a5ab000300}}}{\fldrslt {\rtlch\fcs1 \af37 \ltrch\fcs0 \f31506\ul\cf19\insrsid11301755\charrsid16264811 https://github.com/dds-bridge/dds/releases}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid6650094\charrsid16264811 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9977698 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9977698\charrsid14119459 Latest DLL issue with this description is available at }{\field\fldedit{\*\fldinst {\rtlch\fcs1 +\af1 \ltrch\fcs0 \cf19\insrsid9977698\charrsid15824246 HYPERLINK "http://www.bahnhof.se/wb758135/" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid9977698\charrsid15824246 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b5800000068007400740070003a002f002f007700770077002e006200610068006e0068006f0066002e00730065002f00770062003700350038003100330035002f000000795881f43b1d7f48af2c825dc48527630000 -0000a5ab000000000011000000ff008c00507a490000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid6650094\charrsid15824246 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\insrsid6650094\charrsid14119459 -\par -\par +0000a5ab000000000011000000ff008c00507a4900003201008b87}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid9977698\charrsid15824246 http://www.bahnhof.se/wb758135/}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 +\cf19\insrsid9977698\charrsid11301755 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid6650094\charrsid16264811 \par }\pard\plain \ltrpar\s2\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 -\b\f37\ul\cf1\insrsid1595222 D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid6650094\charrsid14119459 escription of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid5318615 ouble Dummy Problem Solver}{ -\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid270015 2.8}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid11030455 .4}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid6650094\charrsid14119459 -\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid10576044\charrsid14119459 -\par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 -\b\f37\cf1\insrsid6650094\charrsid14119459 Callable functions -\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1789909\charrsid14119459 -The callable functions are all preceded with }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \f2\fs22\cf1\insrsid1789909\charrsid1789909 extern "C" __declspec(dllimport) int __stdcall}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1789909 . }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid10576044 The prototypes are available in dll.h}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 in the \'93include\'94 directory}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10576044 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid14119459 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 -\par -\par }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid14119459\charrsid14119459 REF Return \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b020000000800000007000000520065007400750072006e00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 Return codes}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid14119459 are given at the end.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10576044 +\b\f37\ul\cf1\insrsid1595222 D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid6650094\charrsid14119459 escription of the DLL functions supported in D}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid5318615 ouble Dummy Solver}{\rtlch\fcs1 +\ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid11301755 2.9.0}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\ul\cf1\insrsid6650094\charrsid14119459 +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10576044 +\par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid14310469 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 +\ltrch\fcs0 \b\f37\cf1\insrsid14368275\charrsid14119459 Callable functions}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid14368275\charrsid14310469 +\par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13042502 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275\charrsid14119459 The callable functions are all preceded with }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \f2\fs22\cf1\insrsid14368275\charrsid1789909 extern "C" __declspec(dllimport) int __stdcall}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275 . The prototypes are available in dll.h in the \'93include\'94 directory. }{\field\flddirty{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid14368275\charrsid14119459 REF Return \\h \\* MERGEFORMAT }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid14368275\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000007000000520065007400750072006e000000000300550078}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 +\f37\ul\cf19\insrsid14368275\charrsid16386593 Return codes}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 are given at the end.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14368275 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 +\par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid14310469 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 +\ltrch\fcs0 \b\f37\cf1\insrsid9977698\charrsid9977698 Historical note}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid9977698\charrsid14310469 +\par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9977698 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 I +n addition to the core functions, further layers of interface functions and functionality +have been added to DDS over time. Therefore it is not always consistent whether a pointer or an entire structure is passed to or from DDS. So please read the documentation carefully. \par -\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1789909 Not all functions are present in all versions of the DLL.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid8154048 For historical reasons, the function names are not entirely consistent with respect to the input form -at. Functions accepting binary deals will end on Bin, and those accepting PBN deals will end on PBN in the future. At some point existing function names may be changed as well, so use the new names!}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6650094 +\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14368275 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 For the same reason, the function names are not entirely consistent wi +th respect to the input format. In the future}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 functions accepting \'93binary\'94 deals will end on Bin, and those accepting PBN }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 text }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 deals will end on PBN. At some point existing function names may be changed as well}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 .}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid9977698\charrsid14119459 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10576044 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid9977698\charrsid9977698 Types of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid14368275 functions}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid9977698\charrsid9977698 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 +\par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3871\clshdrawnil \cellx4671 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4260\clshdrawnil \cellx8931\pard\plain \ltrpar +\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid9977698\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\b\f37\cf1\insrsid6318629\charrsid14579995 Mode\cell }\pard \ltrpar\qc \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6318629\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6318629\charrsid14579995 Single\cell Multiple\cell +}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid6318629 \trowd \irow0\irowband0\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3871\clshdrawnil \cellx4671 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4260\clshdrawnil \cellx8931\row \ltrrow}\trowd \irow1\irowband1\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 +\trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1985\clshdrawnil \cellx2785 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1886\clshdrawnil \cellx4671\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2084\clshdrawnil \cellx6755\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2176\clshdrawnil \cellx8931\pard\plain \ltrpar +\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7350065\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 \cell }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid7350065\charrsid7350065 Bin\cell PBN\cell Bin\cell PBN\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 +\ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 \trowd \irow1\irowband1\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 +\trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1985\clshdrawnil \cellx2785\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1886\clshdrawnil \cellx4671\clvertalt\clbrdrt +\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2084\clshdrawnil \cellx6755\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 +\cltxlrtb\clftsWidth3\clwWidth2176\clshdrawnil \cellx8931\row \ltrrow}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7350065\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 Solve\cell SolveBoard +\par \cell SolveBoardPBN\cell SolveAllChunksBin +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \strike\f37\cf1\insrsid7350065\charrsid7350065 \cell }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 SolveAllBoards +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \strike\f37\cf1\insrsid7350065\charrsid7350065 SolveAllChunks SolveAllChunksPBN\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 +\ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 \trowd \irow2\irowband2\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 +\trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1985\clshdrawnil \cellx2785\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1886\clshdrawnil \cellx4671\clvertalt\clbrdrt +\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2084\clshdrawnil \cellx6755\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 +\cltxlrtb\clftsWidth3\clwWidth2176\clshdrawnil \cellx8931\row \ltrrow}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7350065\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 Calc\cell CalcDDtable +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12203684 CalcPar\cell }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 CalcDDtablePBN +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12203684 CalcParPBN\cell }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 CalcAllTables\cell CalcAllTablesPBN\cell }\pard\plain \ltrpar +\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 +\trowd \irow3\irowband3\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1985\clshdrawnil \cellx2785 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1886\clshdrawnil \cellx4671\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2084\clshdrawnil \cellx6755\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2176\clshdrawnil \cellx8931\row \ltrrow +}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7350065\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid7350065 Play\cell AnalysePlayBin\cell AnalysePlayPBN\cell AnalyseAllPlaysBin\cell AnalyseAllPlaysPBN\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 +\af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 \trowd \irow4\irowband4\lastrow \ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl +\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6318629\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth908\clshdrawnil \cellx800\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1985\clshdrawnil \cellx2785 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1886\clshdrawnil \cellx4671\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2084\clshdrawnil \cellx6755\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2176\clshdrawnil \cellx8931\row }\pard \ltrpar +\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid9977698 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7350065 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 There are currently four main families of solvers, and each solver function contains exactly one of these words: +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14579995 +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid9977698 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}\pard\plain \ltrpar +\s28\ql \fi-360\li360\ri0\nowidctlpar\wrapdefault\faauto\ls9\rin0\lin360\itap0\pararsid9977698\contextualspace \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid9977698 Solve: Solve hands for a given leader, strain etc.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14579995 , whether from the opening lead or later.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 +(Do not use the function names that are struck through.)}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid9977698 \loch\af10\dbch\af0\hich\f10 \'a7\tab}Calc: }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14579995 Calculate tables }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 for all }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7880615 5 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7880615 {\field{\*\fldinst SYMBOL 215 \\f "Symbol" \\s 12}{\fldrslt\f3\fs24}}}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7880615 4 = 20 combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 leaders }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7880615 and strains in one go}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14579995 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid9977698 \loch\af10\dbch\af0\hich\f10 \'a7\tab}Play}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14579995 +: Find the optimal results after each card that was actually played on a given hand.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698 +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid9977698 \loch\af10\dbch\af0\hich\f10 \'a7\tab}Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14579995 +: Calculate the par result. This can also be integrated within a Calc function.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9977698\charrsid9977698 +\par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid13042502 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 The Bin functions are for deals that are specified in \'93binary\'94 format, while the PBN functions are for deals that are specified as PBN-like text strings. The \'93Single\'94 + functions are for solving a single instance, while the \'93Multiple\'94 functions are for solving several instances in one call. If you have multiple hands to solve +, you will almost surely be better off using a Multiple function and letting DDS figure out the multi-threading for you}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 \endash see below.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8395240 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid8395240\charrsid1800033 The Basic Functions -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8395240 -\par The basic functions SolveBoard and SolveBoardPBN }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8395240 solve a single hand }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12941889 -and are thread-safe}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 , }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12941889 making it possible }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 to use }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid6641819 them for solving}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12941889 several hands in parallel. The other callable functions use the SolveBoard functions either directly or indirectly. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 +\par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid16269820\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth5245\clshdrawnil \cellx8789\pard\plain \ltrpar +\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13042502\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\b\f37\cf1\insrsid13042502\charrsid13042502 Par family\cell }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13331862\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid13042502\charrsid13042502 Uses\cell }\pard \ltrpar +\qc \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13042502\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid13042502\charrsid13042502 Output format}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 \cell }\pard\plain \ltrpar +\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 +\trowd \irow0\irowband0\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid16269820\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth5245\clshdrawnil \cellx8789\row \ltrrow}\trowd \irow1\irowband1\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 +\trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid13042502\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx5387\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1559\clshdrawnil \cellx6946\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx8789\pard\plain \ltrpar +\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13331862\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 \cell \cell } +{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid13042502\charrsid13042502 Text-1\cell Text-2\cell Bin\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 +\ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 \trowd \irow1\irowband1\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 +\trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid13042502\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx5387\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1559\clshdrawnil \cellx6946\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx8789\row \ltrrow +}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13042502\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid13042502 Par\cell Vul, but not dealer\cell Par\cell SidesPar\cell SidesParBin\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 \trowd \irow2\irowband2\ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr +\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid13042502\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx5387\clvertalt\clbrdrt +\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1559\clshdrawnil \cellx6946\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 +\cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx8789\row \ltrrow}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid13042502\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 Dealer\cell Vul and dealer\cell (not available)\cell DealerPar\cell DealerParBin\cell }\pard\plain \ltrpar +\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13042502 +\trowd \irow3\irowband3\lastrow \ltrrow\ts18\trqc\trgaph70\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid13042502\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb +\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1384\clshdrawnil \cellx1276\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2268\clshdrawnil \cellx3544 +\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx5387\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr +\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1559\clshdrawnil \cellx6946\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1843\clshdrawnil \cellx8789\row }\pard \ltrpar +\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 +\par The Par functions are divided differently, as they operate on a finished Calc table (or in the case of CalcPar and CalcParPBN, the par results are generated directly from a Calc function as well). }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 P +ar calculations are so fast that they are never multi-threaded.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 +\par The \'93Par\'94 family, which does not contain the word \'93Dealer\'94, makes use of the vulnerability but not of the dealer in a given deal. This can lead to rare differences depending on who opens the bidding; for example both sides might make 1NT. +The \'93Dealer\'94 family makes use of both the vulnerability and the dealer to arrive at a single overall par score. +\par +\par The Text-1 and Text-2 output formats are described later. The \'93Bin\'94 output format can be used to generate your own output text strings if you don\rquote t like ours. The two }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 help functions +ConvertTo}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 \-Sides\-}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 Te}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 xtFormat and ConvertToDealer}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275 TextFormat }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 do this for the Text-2 and Bin formats, respectively, and you can look at the code at the end of Par.cpp if you are so inclined.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275 \par -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid7545453\charrsid1800033 The Multi-}{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid12520971 T}{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid7545453\charrsid1800033 hread}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\i\f37\cf1\insrsid12941889\charrsid1800033 Double Dummy Solver Functions -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 -\par The double dummy trick values for all }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 5 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 {\field{\*\fldinst SYMBOL 215 \\f "Symbol" \\s 12}{\fldrslt\f3\fs24}}}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12520971 4 = }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 20 possible combinations of a hand\rquote s trump strain and declarer han}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5506187 d alternatives are solved by a}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4738929 single }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 call to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5506187 one of }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 the function}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5506187 s CalcDDtable and CalcDDtablePBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid856123 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid856123 T}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 hreads are allocated per strain in order to save computations.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid856123 -\par To obtain better utilization of available threads, the double dummy}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 (DD)}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid856123 tables can be grouped using one of the func}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid5388872 tions CalcAllTables and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid856123 CalcAllTablesPBN. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11277669 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 Solving hands can be done much }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 more }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 quick}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12520971 ly}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 using one of the multi-thread alternatives }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6910245 for}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid6910245 calling }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 SolveBoard. Then a number of hands are grouped for a sing}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12008966 le call to one of the functions}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5927621 SolveAllBoards, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5388872 SolveAllChunksBin and }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid4155951 SolveAllChunksPBN.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12008966 T}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1708722 he hands }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12008966 are then solved }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1708722 in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12008966 using the available threads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1708722 . -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1900643 -\par The number of threads is automatically configured by DDS}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5927621 on Windows}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1900643 - taking into account the number of processor cores and available memory. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1900643 The number of threads can be influenced }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid16456729 by calling}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1900643 SetMaxThreads.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5927621 - This function should probably always be called on Linux/Mac, with a zero argument for auto-configuration.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1900643 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4076363 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 Calling}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4076363 FreeMemory causes DDS to give up its dynamically allocated memory. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1800033 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid1800033\charrsid7959800 The PAR Calculation Functions -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1800033 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11958279 The PAR calculation functions }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6957422 find the optimal contract(s) assuming open cards and optimal bidding from both sides.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid5650157 In very rare cases it matters which side }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4002451 or hand that starts the bidding, i.e. which side or hand that }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10423813 -is first to bid its optimal contract.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1800033 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 -\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid10308289 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5650157 Two }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2833141 alternatives are given}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid10308289 : -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 -\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f37\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid10308289 \hich\af37\dbch\af0\loch\f37 1.\tab}}\pard \ltrpar -\qj \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls5\rin0\lin720\itap0\pararsid11099036 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10308289 The PAR scores / contracts are calculated separately for each side. In almost all cases the results w}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3752772 ill be identical for both sides, but in rare cases}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9834330 the result is dependent on which side that \'93starts the bidding\'94, }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid9834330\charrsid9834330 i.e. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9834330 that first finds the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9834330\charrsid9834330 bid that is most b}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid7305895 eneficial for the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9834330 own side. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid409864\charrsid7305895 One example is when both sides can make 1 NT.}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid10308289\charrsid7305895 -\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f37\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid10308289\charrsid9834330 \hich\af37\dbch\af0\loch\f37 2.\tab}}\pard \ltrpar -\qj \fi-360\li720\ri0\nowidctlpar\wrapdefault\faauto\ls5\rin0\lin720\itap0\pararsid2057006 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10308289\charrsid9834330 The dealer hand is}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10383915 assumed to \'93 -start the bidding\'94.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15755105\charrsid9834330 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10308289\charrsid9834330 -\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7804526 The presentation of the par sco}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 re and contracts are given in }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7804526 alternative formats.}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4155951 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6054214 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 The functions Par, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3352595 SidesPar and DealerPar }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1386919 do the par calculation}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid12520971 ;}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1386919 their call}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 must be preceded by a function }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1386919 call }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 calculating the double dummy table value}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11952575 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid12941889 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 The functions SidesParBin and DealerParBin provide binary output of the par results}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 - making it easy to tailor-ma}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 k}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 e the output text format. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 Two}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid3301731 such functions}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16456729 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731\charrsid3301731 -ConvertToSidesTextFormat}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558 and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558\charrsid2238558 ConvertToDealerTextFormat}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558 , are included}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2568164 as examples}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3301731 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3352595 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558 It is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid3352595\charrsid3352595 possible as an option to perform par calculation in CalcAllTables and CalcAllTablesPBN. }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid3352595 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 -\par The par calculation is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1386919 executed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9974881 using}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid7305895 a single thread. But }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 the calculation is very fast and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4533879 i}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7305895 t}{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4533879 s }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7305895 duration is negligible}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 compared to the }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid7763137 double}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 dummy calculation}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4533879 duration}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6573516 . -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7959800 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid13902528 Double Dummy Value}{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid7959800\charrsid7959800 Analyser Functions -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7959800 -\par The functions AnalysePlayBin, AnalysePlayPBN, AnalyseAllPlaysBin and AnalyseAll}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13902528 PlaysPBN take}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7959800 the played cards in a game }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid10313626 or games }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7959800 and calculate and present their double dummy values. -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12941889 -\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8154048\charrsid14119459 -\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 \page }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1789909\charrsid14119459 +\par There are also some functions to do with DDS itself: +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}\pard\plain \ltrpar +\s28\qj \fi-360\li360\ri0\nowidctlpar\wrapdefault\faauto\ls10\rin0\lin360\itap0\pararsid14368275\contextualspace \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275 GetDDSInfo can provide information about the DLL and how it is compiled and configured. +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}ErrorMessage can turn an error code into an error string. +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}SetThreading controls the type of threading that is used internally. If you\rquote +re using a ready-made DLL, you probably don\rquote t need to call this. +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}SetMaxThreads sets the maximum number of threads to be used internally. +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}SetResources sets both the maximum memory and the maximum number of threads.}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 This of SetMaxThreads }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 should probably always be called on Linux/Mac, with a zero argument for auto-configuration}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid8997327 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14368275 +\par {\listtext\pard\plain\ltrpar \s28 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\cf1\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14368275 \loch\af10\dbch\af0\hich\f10 \'a7\tab}FreeMemory relinquishes all dynamically allocated memory.}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid14368275\charrsid14368275 +\par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14368275 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid8997327\charrsid8997327 Multi-threading}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid12941889\charrsid14310469 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 DDS is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14310469 quite optimized for performance}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid14310469 including}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 multi-threading. For example, DDS takes advantage of similarity between hands (such as the same cards and strain but a different de +clarer) and solves such hands as groups. DDS sets up threads and tries to load the threads as equally as possible, looking into the individual hands as well. Unless you have an unusual set-up, you\rquote re probably not going to beat DDS\rquote +s multi-threading by trying to do it manually instead. +\par +\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid14310469 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid8997327 DDS has two types of threads available internally, \'93large\'94 ones which are +a bit faster and use more memory, and \'93small\'94 ones which are the opposite. DDS automatically chooses the right mixture of thread types based on the available memory and number of threads.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid8154048\charrsid14119459 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12520971 \page }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1789909\charrsid14119459 \par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt @@ -300,38 +424,38 @@ ConvertToSidesTextFormat}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2238558 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14119459\charrsid14119459 - REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt -{\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar -\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 + REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f0061007200640000000006290000dc}} +}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid14119459 \cell +}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5767474\charrsid14119459 REF deal \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16530750 dl,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c000000001400ca0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16530750 dl,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 \par int target, \par int solutions, \par int mode, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12659025\charrsid14119459 REF futureTricks \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000143b00120c}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *futp, \par int threadIndex\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid13267252 Binary }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 -\f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 -The most basic function, solves a single hand from the beginning or from later play\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 +\f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 The most basi +c function, solves a single hand from the beginning or from later play\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow1\irowband1\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid13331862\charrsid13331862 REF SolveBoardPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid13331862 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000053006f006c007600650042006f00610072006400500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveBoardPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid13331862 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6968528\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000077}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid4616356 dlPBN}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16530750 ,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid8154048\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000053006f006c007600650042006f00610072006400500042004e000000003000654100}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveBoardPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid13331862 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789909 {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6968528\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000077480065ba00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid4616356 dlPBN}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16530750 ,}{\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 \par int target, \par int solutions, \par int mode, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12659025\charrsid14119459 REF futureTricks \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b0073000000bf}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b0073000000bf6300005b7f}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *futp, \par int threadIndex}{\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f37\fs18\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid13267252 PBN}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -342,17 +466,17 @@ dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \l \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid11107656\charrsid11107656 - REF CalcDDtable \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid11107656 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000430061006c006300440044007400610062006c006500000020}} -}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtable}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell -}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5974982 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid6901705 struct}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\insrsid8154048\charrsid6901705 } -{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c00000022}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid6901705 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid16456729\charrsid6901705 - + REF CalcDDtable \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid11107656 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000430061006c006300440044007400610062006c00650000002030800000ad}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtable}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5974982 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid8154048\charrsid6901705 struct}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\insrsid8154048\charrsid6901705 }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{ +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c000000226f00040000}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid8154048\charrsid6901705 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid16456729\charrsid6901705 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 tableDeal, \line struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT } -{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000072}}}{\fldrslt {\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid16456729 +{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000720007320000}}}{\fldrslt { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 * tablep\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid13267252 Binary }{ \rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell Solves an initial hand for all possible declarers and denominations (}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid16012515 up to }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 20 combinations)\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 @@ -362,16 +486,16 @@ dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid11107656\charrsid11107656 REF CalcDDtablePBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid11107656 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000430061006c006300440044007400610062006c006500500042004e00000067}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtablePBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000065}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 \line }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6968528\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000430061006c006300440044007400610062006c006500500042004e000000676900314000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtablePBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e0000006500003100a8}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 \line }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6968528\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 tableDealPBN, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5974982 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000030}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000303600745f14}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 * tablep\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 PBN }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14307787\charrsid14119459 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar @@ -384,21 +508,21 @@ dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid11107656\charrsid11107656 REF CalcAllTables \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid11107656 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e000000430061006c00630041006c006c005400610062006c006500730000002e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcAllTables}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableDeals \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d000000640064005400610062006c0065004400650061006c007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeals}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e000000430061006c00630041006c006c005400610062006c006500730000002e030072dc00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcAllTables}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableDeals \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d000000640064005400610062006c0065004400650061006c0073000000001200611a69}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeals}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 dealsp, \par int mode, \par int trumpFilter[5], \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTablesRes \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000013eb006c0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *resp, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6701983 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6701983\charrsid14119459 REF allParResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c0074007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c0074007300000013a2126e0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 presp\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 Binary \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 Solves a number of hands in parallel. Multi-threaded.\cell }\pard \ltrpar @@ -409,22 +533,22 @@ dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid11107656\charrsid11107656 REF CalcAllTablesPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid11107656 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b020000000800000011000000430061006c00630041006c006c005400610062006c0065007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcAllTablesPBN}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af2\afs18 +08d0c9ea79f9bace118c8200aa004ba90b020000000800000011000000430061006c00630041006c006c005400610062006c0065007300500042004e000000000000000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcAllTablesPBN} +}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid11107656 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableDealsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000010000000640064005400610062006c0065004400650061006c007300500042004e00000014}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000010000000640064005400610062006c0065004400650061006c007300500042004e000000140012000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *dealsp, \par int mode, \par int trumpFilter[5], }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid70445\charrsid14119459 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTablesRes \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c006500730052006500730000000000402d0094}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *resp, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6701983 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6701983\charrsid14119459 REF allParResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c00740073000000c5}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c00740073000000c5691a06486e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 presp\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 PBN }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14307787\charrsid14119459 @@ -438,35 +562,35 @@ dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5320216\charrsid5320216 REF SolveAllBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5320216 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f00000053006f006c007600650041006c006c0042006f006100720064007300000022}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllBoards}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000091}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f00000053006f006c007600650041006c006c0042006f00610072006400730000002200cc55a469}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllBoards}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000091001a326700}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *bop, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14429502 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14429502\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000016}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f0061007200640073000000160000204700}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7880574 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574 * }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid7880574 solvedp\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 PBN }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14307787\charrsid14119459 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 { -\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8682482 Consider using this instead of the next 3 \'93Chunk\'94 functions\'94!}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar -\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow7\irowband7\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 -\trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8682482 Consider }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid2623319 using this instead of the next 2}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8682482 \'93Chunk\'94 + functions\'94!}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8154048\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\insrsid3937665\charrsid14119459 \trowd \irow7\irowband7\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5320216\charrsid5320216 REF SolveAllChunksBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5320216 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllChunksBin}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *bop, +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300420069006e000000000000484900}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 +SolveAllChunksBin}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8154048 { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f0061007200640073000000006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *bop, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14429502 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14429502\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f0061007200640073000000000000005700}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8154048\charrsid14119459 int chunkSize\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -479,13 +603,13 @@ Solves a number of hands in parallel. Multi-threaded.}{\rtlch\fcs1 \af1\afs22 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5320216\charrsid5320216 REF SolveAllChunks \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5320216 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f00000053006f006c007600650041006c006c004300680075006e006b007300000000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllChunks}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid16151628 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid16151628\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16151628\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f00000053006f006c007600650041006c006c004300680075006e006b0073000000000000005700}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllChunks}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid16151628 {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid16151628\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16151628\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000001d000800}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16151628\charrsid14119459 *bop, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16151628\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000b06d000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16151628\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16151628\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16151628\charrsid14119459 solvedp, }{ \rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 @@ -499,14 +623,14 @@ Solves a number of hands in parallel. Multi-threaded.}{\rtlch\fcs1 \af1\afs22 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5320216\charrsid5320216 REF SolveAllChunksPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5320216 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SolveAllChunksPBN}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300500042004e00000000001a250000}}}{\fldrslt {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 +SolveAllChunksPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8154048\charrsid5320216 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e000000000000be0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *bop, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14429502 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14429502\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f0061007200640073000000000000a82000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 solvedp, }{ \rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 @@ -520,16 +644,16 @@ Solves a number of hands in parallel. Multi-threaded.}{\rtlch\fcs1 \af1\afs22 \l \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12520971 \page \par \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12658900\charrsid12658900 REF Par \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid12658900 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000004000000500061007200000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 Par}}} +\f2\fs18\ul\cf19\insrsid16386593\charrsid12658900 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000040000005000610072000000000008366118}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 Par}}} \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid12658900 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000005400c22016}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 tablep, }{ \rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6701983\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c007400730000000003003e8089}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *presp, \par int vulnerable\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 No format }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14307787\charrsid14119459 @@ -543,11 +667,11 @@ Solves a number of hands in parallel. Multi-threaded.}{\rtlch\fcs1 \af1\afs22 \l \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3567911 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3567911 DealerPar}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3567911\charrsid12658900 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3567911\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000d7003d8000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 tablep, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "parResultsDealer" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c0065007200000000d00000000000ff002e213120f50000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c0065007200000000d00000000000ff002e213120f50000726faa0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid13701456\charrsid16456729 parResultsDealer}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid13701456 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3567911\charrsid14119459 presp, @@ -562,11 +686,12 @@ Solves a number of hands in parallel. Multi-threaded.}{\rtlch\fcs1 \af1\afs22 \l \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3567911 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430\charrsid3220430 DealerParBin }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3220430 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 struct } {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000011006c00000aff0021080020a70000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 -ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000011006c00000aff0021080020a700001e6f6f0800}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 * tablep, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000780000000000ff00e2007420850000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000780000000000ff00e20074208500001236040000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 * presp, @@ -582,7 +707,7 @@ ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3567911 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430\charrsid3220430 ConvertToDealerTextFormat}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3220430 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 -{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d006100730074006500720000000068008c0000006d008e002020530000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d006100730074006500720000000068008c0000006d008e00202053000076e0000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 pres, @@ -596,11 +721,11 @@ Text}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid3220430\charrsid14 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid348894 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid15939092 SidesPar}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid348894\charrsid8538722 \cell }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid348894\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000002e00fb0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894\charrsid14119459 tablep, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "parResultsDealer" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c00650072000000000000000000000000de003c00960000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c00650072000000000000000000000000de003c0096000000e8371700}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3954019\charrsid16456729 parResultsDealer}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894\charrsid14119459 presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid348894 , @@ -614,11 +739,11 @@ Par results are given for sides with the DealerPar output format.}{\rtlch\fcs1 \ \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid348894 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430\charrsid3220430 SidesParBin}{ \rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3220430 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 struct } {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000000000000000000002e3137001000f2}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 -ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \line }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid3220430\charrsid3220430 * tablep, +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000000000000000000002e3137001000f200c83c0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid16456729 \line }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 * tablep, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid16456729 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid16456729 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d00610073007400650072000000000004000000000000b5006923a700f1}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d00610073007400650072000000000004000000000000b5006923a700f10000eb2f00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid3220430\charrsid16456729 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16456729 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid3220430 sidesRes[2], @@ -634,13 +759,14 @@ ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid348894 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430\charrsid3220430 ConvertToSidesTextFormat}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid3220430 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid16057925 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid8682482 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid8682482 -{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000000f0000e5002c008e0d3a006a00f1}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +{\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000000f0000e5002c008e0d3a006a00f10073413100}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid16057925\charrsid8682482 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 pres, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid8682482 HYPERLINK \\l "parTextResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid8682482 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000700061007200540065007800740052006500730075006c007400730000000000000000f7000000d2003e00f700f1}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid16057925\charrsid8682482 -parTextResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000700061007200540065007800740052006500730075006c007400730000000000000000f7000000d2003e00f700f1002b356800}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid16057925\charrsid8682482 parTextResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16057925\charrsid16057925 resp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid3220430\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid348894 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8290285 Text}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid3220430\charrsid13053124 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1520891 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1520891\charrsid1520891 @@ -651,22 +777,22 @@ Example of text output from }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\i \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid8538722 - REF CalcPar \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid8538722 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000008000000430061006c006300500061007200000013}}}{\fldrslt {\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcPar}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid8538722 \cell }\pard \ltrpar + REF CalcPar \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid8538722 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000008000000430061006c006300500061007200000013370061fa00}}}{\fldrslt { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcPar}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid8538722 \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid6557970 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c00000013}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c000000130000826100}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid6557970 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482\charrsid6557970 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 tableDeal, \par int vulnerable, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5974982\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15757396 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000f808612000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15757396 \par * }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 tablep, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6701983 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6701983\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000000eb00558000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 presp\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14307787 Binary}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 @@ -677,21 +803,21 @@ Solves for both the DD result table and the par contracts}{\rtlch\fcs1 \af1\afs2 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid8538722 - REF CalcParPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid8538722 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000430061006c006300500061007200500042004e00000000}}}{\fldrslt { -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcParPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid8538722 \cell }\pard \ltrpar -\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 + REF CalcParPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid8538722 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000430061006c006300500061007200500042004e000000004a00656c69}} +}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 CalcParPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid8538722 \cell +}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid70445\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000000ba006e6e00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid70445\charrsid14119459 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 tableDealPBN, \par struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid8682482 HYPERLINK \\l "ddTableResults" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid8682482 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000000000307b0f00200004350000680000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid6578564\charrsid8682482 -ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15757396 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000000000307b0f002000043500006800000000492200}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid6578564\charrsid8682482 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15757396 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 * tablep, \par int vulnerable, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6701983 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6701983\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c00740073000000000000de0a00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 presp\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 PBN \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid2769001 As CalcPar, but with PBN input format.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid3034548 }{\rtlch\fcs1 \af1\afs22 @@ -703,18 +829,18 @@ ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12520971 \page \par \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid2849436 REF TracePlayBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid2849436 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d0000005400720061006300650050006c0061007900420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid2849436 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d0000005400720061006300650050006c0061007900420069006e000000000000426409}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalysePlayBin}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid2849436 \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6968528\charrsid14119459 REF deal \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 dl, +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c000000005001005800}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 dl, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF playTraceBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTraceBin}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e000000000010250000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTraceBin}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6580905\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid14119459\charrsid14119459 play}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 ,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid14119459\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14119459\charrsid14119459 REF solvedPlay \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c00610079000000000111000006}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid14119459\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid14119459\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid14119459\charrsid14119459 solvedp,}{ \rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 @@ -728,18 +854,18 @@ ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid2849436 - REF TracePlayPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid2849436 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d0000005400720061006300650050006c0061007900500042004e00000000}} -}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalysePlayPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid2849436 \cell -}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid6968528\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000020}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 dlPBN, + REF TracePlayPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid2849436 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d0000005400720061006300650050006c0061007900500042004e000000000012051a00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalysePlayPBN}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid2849436 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6968528\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e000000200000ff9a00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 dlPBN, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF playTracePBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracePBN}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e000000005314af0079}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracePBN}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 playPBN, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid14119459\charrsid14119459 REF solvedPlay \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000ec00001ec8}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 solvedp, \par int thrId\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 PBN }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -754,16 +880,16 @@ ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid5979431 REF TraceAllPlaysBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5979431 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000110000005400720061006300650041006c006c0050006c00610079007300420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalyseAllPlaysBin}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000110000005400720061006300650041006c006c0050006c00610079007300420069006e000000004200001e75}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalyseAllPlaysBin +}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f0061007200640073000000a0}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *bop, +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f0061007200640073000000a06900000057}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *bop, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF playTracesBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesBin}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *plp, +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300420069006e000000000000010200}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesBin}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *plp, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF solvedPlays \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c00610079007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c006100790073000000000000ec0500}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 solvedp, \par int chunkSize\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 Binary }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -777,17 +903,17 @@ boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \lt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid5979431 REF TraceAllPlaysPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid5979431 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000110000005400720061006300650041006c006c0050006c00610079007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalyseAllPlaysPBN}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000110000005400720061006300650041006c006c0050006c00610079007300500042004e00000000e900001aca}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 AnalyseAllPlaysPBN +}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12657542\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid70445\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e000000000000000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *bopPBN, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF playTracesPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300500042004e0000000000d8000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 plpPBN, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6580905\charrsid14119459 REF solvedPlays \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c00610079007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c0061007900730000000000a2009100}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 *}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8682482 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12657542\charrsid14119459 solvedp, \par int chunkSize\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12657542\charrsid14119459 PBN }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -800,38 +926,59 @@ boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \lt \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 +\cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field\flddirty{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5902855 HYPERLINK \\ +l "SetThreading" }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5902855 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000053006500740054006800720065006100640069006e0067000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1389500\charrsid5902855 SetThreading}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1389500 \cell }\pard \ltrpar +\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1389500 int code\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 { +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1389500\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6771888 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1389500 +Can be used to select the multi-threading system that is used internally. You probably don\rquote t need this. The codes are in dll.h\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 +\af1 \ltrch\fcs0 \insrsid1389500\charrsid14119459 \trowd \irow4\irowband4\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 +\clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt +\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 REF SetMaxThreads \\h }{ -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005300650074004d0061007800540068007200650061006400730000008f}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005300650074004d0061007800540068007200650061006400730000008f00bd000000}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 SetMaxThreads}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1056208\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1056208 int }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1056208\charrsid1056208 userThreads}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1056208\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1056208\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6771888 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6771888 Used at initial start and can also be called with a request for allocating memory for a specified number of threads. }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6643870 Is apparently mandatory on Linux and Mac (optional on Windows)}{ \rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1056208\charrsid3034548 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1056208\charrsid14119459 -\trowd \irow4\irowband4\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trowd \irow5\irowband5\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 +\clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt +\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 +\cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field\flddirty{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1389500 HYPERLINK \\ +l "SetResources" }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1389500 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d0000005300650074005200650073006f00750072006300650073000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2623319\charrsid1389500 SetResources}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2623319 \cell }\pard \ltrpar +\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2623319 int maxMemoryMB,\line int maxThreads\cell }\pard \ltrpar +\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid2623319\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6771888 +{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid2623319 Like SetMaxThreads, but also sets the maximum memory to use. One of these two functions is enough.\cell }\pard \ltrpar +\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid2623319\charrsid14119459 \trowd \irow6\irowband6\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 +\trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 REF FreeMemory \\h }{ -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000046007200650065004d0065006d006f00720079000000de}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000046007200650065004d0065006d006f00720079000000de36e60000bf}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 FreeMemory}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1056208\charrsid5979431 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1056208 void}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1056208\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1056208\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8682482 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6771888 Frees }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid8682482 all}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6771888 allocated dynamical memory.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid1056208\charrsid3034548 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 { -\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1056208\charrsid14119459 \trowd \irow5\irowband5\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv +\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1056208\charrsid14119459 \trowd \irow7\irowband7\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv \brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr \brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2288\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 - REF GetDDSInfo \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000047006500740044004400530049006e0066006f00000011}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid7483127 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 GetDDSInfo}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 + REF GetDDSInfo \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000047006500740044004400530049006e0066006f0000001100120000ff}}{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7483127 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 GetDDSInfo}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7483127\charrsid9069276 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12657542 {\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1921007\charrsid1921007 - REF DDSInfo \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid1921007 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000044004400530049006e0066006f000000c2}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid1921007 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 DDSInfo}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 + REF DDSInfo \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid1921007 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000044004400530049006e0066006f000000c20000730000}}{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid1921007 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 DDSInfo}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7483127 * info\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid7483127\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8682482 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid7483127 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 { -\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7483127\charrsid14119459 \trowd \irow6\irowband6\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv +\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7483127\charrsid14119459 \trowd \irow8\irowband8\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv \brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1353\clshdrawnil \cellx7226\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr @@ -840,7 +987,7 @@ Used at initial start and can also be called with a request for allocating memor \par char line[80]\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14307787 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid9069276\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8682482 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid9069276 Turns a return code into an error message string\cell }\pard \ltrpar -\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid9069276\charrsid14119459 \trowd \irow7\irowband7\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl +\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid9069276\charrsid14119459 \trowd \irow9\irowband9\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl \brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11099036\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2918\clshdrawnil \cellx2810\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3063\clshdrawnil \cellx5873\clvertalt @@ -958,7 +1105,7 @@ Holding\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1668\clshdrawnil \cellx1560\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3260\clshdrawnil \cellx4820\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4618\clshdrawnil \cellx9438\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid10576044\charrsid14119459 {\*\bkmkstart deal}deal{\*\bkmkend deal}\cell int trump;\cell }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid10239463\charrsid14119459 REF suit \\h \\ -* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000047}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000047022c000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10239463\charrsid14119459 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10576044\charrsid14119459 \trowd \irow1\irowband1\ltrrow \ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -967,8 +1114,8 @@ Holding\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4618\clshdrawnil \cellx9438\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid10576044\charrsid14119459 \cell int first;\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10239463\charrsid14119459 The hand leading to the trick. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF hand \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000008}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid10239463\charrsid14119459 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e0064000000080095000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10239463\charrsid14119459 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 \par \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10576044\charrsid14119459 \trowd \irow2\irowband2\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14119459\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 @@ -976,7 +1123,7 @@ Holding\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4618\clshdrawnil \cellx9438\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid10576044\charrsid14119459 \cell int currentTrickSuit[3];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12659025 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 Up to 3 cards may already have been played to the trick. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{ -\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000007258000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid163452 }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid163452\charrsid163452 Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10576044\charrsid14119459 \trowd \irow3\irowband3\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 @@ -993,16 +1140,16 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4618\clshdrawnil \cellx9438\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid10576044\charrsid14119459 \cell unsigned int remainCards[4][4];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12659025 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5254237 1st}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 index is }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid15757396\charrsid14119459 REF hand \\h \\ -* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000022}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e0064000000226700000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5254237 , 2nd}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 index is }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid15757396\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 -\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000020}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid15757396\charrsid14119459 . }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12983768 remainCards use}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 -\f37\fs22\cf1\insrsid5254237 s }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid12983768 HYPERLINK \\l "holding" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid12983768 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000068006f006c00640069006e006700000016003e23000200a40030340f002f0090}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \cs26\f37\fs22\ul\cf19\insrsid5254237\charrsid12983768 Holding}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12983768 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5254237 .}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10576044\charrsid14119459 -\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10576044\charrsid14119459 \trowd \irow5\irowband5\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt -\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000201e00000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 +Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid15757396\charrsid14119459 . }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12983768 remainCards use}{\rtlch\fcs1 \af1\afs22 +\ltrch\fcs0 \f37\fs22\cf1\insrsid5254237 s }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid12983768 HYPERLINK \\l "holding" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid12983768 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000068006f006c00640069006e006700000016003e23000200a40030340f002f00901c00000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \cs26\f37\fs22\ul\cf19\insrsid5254237\charrsid12983768 Holding}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12983768 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5254237 .}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +\f37\fs22\cf1\insrsid10576044\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10576044\charrsid14119459 +\trowd \irow5\irowband5\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14119459\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1668\clshdrawnil \cellx1560\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3260\clshdrawnil \cellx4820\clvertalt \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4618\clshdrawnil \cellx9438\row }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 @@ -1019,16 +1166,16 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 {\*\bkmkstart dealPBN}dealPBN{\*\bkmkend dealPBN}\cell int trump;\cell }{\field{\*\fldinst { \rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000020}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000200264000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow1\irowband1\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1951\clshdrawnil \cellx1843\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2977\clshdrawnil \cellx4820 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 \cell int first;\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 The hand leading to the trick. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF hand \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 -\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid9713208 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 \cell }\pard \ltrpar +\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e0064000000000064000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 +Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid9713208 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow2\irowband2\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1036,7 +1183,7 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 \cell int currentTrickSuit[3];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 Up to 3 cards may already have been played to the trick. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{ -\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000ff64000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding.\cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow3\irowband3\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1053,8 +1200,8 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 \cell char remainCards[80];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 Remaining cards. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF PBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 -\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000004000000500042004e00000020}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 PBN}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 { +\f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000004000000500042004e000000206400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 PBN} +}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 { \rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow5\irowband5\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv \brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl \brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1951\clshdrawnil \cellx1843\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 @@ -1068,11 +1215,11 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid10967321 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid10967321\charrsid14119459 {\*\bkmkstart ddTableDeal}ddTableDeal{\*\bkmkend ddTableDeal}\cell unsigned int cards[4][4]; \cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10967321 Encodes a deal. First index is hand. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid10967321\charrsid14119459 REF hand \\h \\* MERGEFORMAT }{ -\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000017}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000017616d000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10967321 encoding. Second index is suit. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid10967321\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000020}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid10967321\charrsid14119459 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10967321\charrsid10967321 \cell }\pard \ltrpar +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000206f6d000069}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10967321\charrsid14119459 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid10967321\charrsid10967321 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \b\f37\fs22\cf1\insrsid10967321\charrsid14119459 \trowd \irow1\irowband1\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt \brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid1852854\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1088,7 +1235,7 @@ Set to 0 if no card has been played.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12210879 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 {\*\bkmkstart ddTableDealPBN}ddTableDealPBN}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 {\*\bkmkend ddTableDealPBN} }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 \cell char cards[80];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12210879\charrsid14119459 Encodes a deal}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12658578\charrsid14119459 . }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12658578\charrsid14119459 REF PBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000004000000500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000004000000500042004e000000000055000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 PBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12658578\charrsid14119459 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12210879\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \b\f37\fs22\cf1\insrsid12210879\charrsid14119459 \trowd \irow1\irowband1\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1113,7 +1260,7 @@ Encodes a deal}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12658578 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid70445\charrsid14119459 \cell }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\lang1031\langfe1053\langnp1031\insrsid70445\charrsid7697883 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c00000000}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\ +\f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c000000009d02330096}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\ * MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\lang1031\langfe1053\langnp1031\insrsid70445\charrsid7697883 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12210879 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\lang1031\langfe1053\langnp1031\insrsid12210879\charrsid7697883 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 @@ -1140,7 +1287,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12210879 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 \cell }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 s}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 truct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid12210879\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 -\ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000020}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e0000002000000000be}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 deals[}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 X}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 ];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12210879 X = }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid12210879 MAXNOOFTABLES * DDS_STRAINS}{ @@ -1164,8 +1311,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid6968528\charrsid14119459 REF deal \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c00000030}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 -\ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c0000003000000000d4}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par [}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow2\irowband2\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1175,7 +1322,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int target}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000540000004b}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow3\irowband3\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1184,7 +1331,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int solutions}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f006100720064000000006f0000001c}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow4\irowband4\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1193,7 +1340,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int mode}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f006100720064000000003c00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow5\irowband5\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1214,8 +1361,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid6968528\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { -\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid12210879 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e000000000000000002}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj +{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 [}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow2\irowband2\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1225,7 +1372,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int target}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f0061007200640000000006000080ff}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow3\irowband3\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1234,7 +1381,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int solutions}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f0061007200640000000000000000ff}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow4\irowband4\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1243,7 +1390,7 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 \cell int mode}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6968528\charrsid14119459 [MAXNOOFBOARDS];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 See }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid6968528\charrsid14119459 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f0061007200640000000000000000ff}}}{\fldrslt {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6968528\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6968528\charrsid14119459 \trowd \irow5\irowband5\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1273,8 +1420,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12720965\charrsid14119459 \cell int suit[13];\cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12659025 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 Suit of the each returned card. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12720965\charrsid14119459 \cell }\pard \ltrpar +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000000000005f00}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 encoding}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12720965\charrsid14119459 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12720965\charrsid14119459 \trowd \irow9\irowband9\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb @@ -1290,17 +1437,20 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 \cell int equals[13];\cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid15283250 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 Lower-ranked equals}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid15283250 . } {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid15283250\charrsid12983768 HYPERLINK \\l "holding" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid15283250\charrsid12983768 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000068006f006c00640069006e006700000016003e2300020018000000006198189d}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \cs26\f37\fs22\ul\cf19\insrsid15283250\charrsid12983768 Holding}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid15283250 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid15757396 \cell }\pard \ltrpar +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000800000068006f006c00640069006e006700000016003e2300020018000000006198189dff00000001}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \cs26\f37\fs22\ul\cf19\insrsid15283250\charrsid12983768 Holding}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid15283250 encoding.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid12659025\charrsid15757396 \cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow11\irowband11\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1951\clshdrawnil \cellx1843\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2977\clshdrawnil \cellx4820 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6968528 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12659025\charrsid14119459 \cell int score[13];\cell }\pard \ltrpar -\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12659025 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 -1: target not reached. -\par Otherwise: Target of maximum number of tricks.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12659025\charrsid14119459 -\trowd \irow12\irowband12\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12659025 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 -1: target not reached.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025 + +\par }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid7472903 -2 (if mode == 0): O}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12198414 nly one card to be played; s}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5399796 +ee SolveBoard() description.}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid7472903\charrsid14119459 +\par }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12659025\charrsid14119459 Otherwise: Target of maximum number of tricks.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 +\ltrch\fcs0 \insrsid12659025\charrsid14119459 \trowd \irow12\irowband12\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12210879\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1951\clshdrawnil \cellx1843\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2977\clshdrawnil \cellx4820 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4678\clshdrawnil \cellx9498\row }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 @@ -1323,8 +1473,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4694\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14429502 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid14429502\charrsid14119459 REF futureTricks \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 -\f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000000000ff00}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 +\ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12065713\charrsid11099036 solvedBoard}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12065713\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 [MAXNOOFBOARDS];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -1349,9 +1499,9 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5974982 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid5974982\charrsid14119459 int resTable[5][4];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5974982\charrsid14119459 Encodes the solution of a deal for combinations of denomination and declarer. First index is denomination. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid5974982\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid5974982\charrsid14119459 encoding. Second index is declarer. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid5974982\charrsid14119459 REF hand \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000ff000030ff}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5974982\charrsid14119459 encoding. Second index is declarer. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid5974982\charrsid14119459 REF hand \\h \\* MERGEFORMAT }{ +\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000000c000006500}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5974982\charrsid14119459 encoding. Each entry is a number of tricks.\cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow1\irowband1\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl \brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1376,8 +1526,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth4694\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12210879 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 \cell struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid12210879\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000040dc697700}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 results[}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879 X}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid14119459 ];\cell }{ \rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12210879 X = }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12210879\charrsid12210879 MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12210879\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \b\f37\fs22\cf1\insrsid12210879\charrsid14119459 @@ -1405,8 +1555,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 {\*\bkmkstart parResults}parResults{\*\bkmkend parResults}\cell char parScore[2][16];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid14429502 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 First index is NS/EW. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid14429502\charrsid14119459 REF side \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300690064006500000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Side}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073006900640065000000000300003000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Side}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow1\irowband1\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2235\clshdrawnil \cellx2127\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3543\clshdrawnil \cellx5670 @@ -1415,8 +1565,8 @@ MAXNOOFTABLES * DDS_STRAINS}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\in \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid14429502\charrsid14119459 [2][128];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 First index is NS/EW. }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid14429502\charrsid14119459 REF side \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300690064006500000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Side}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073006900640065000000000000e60aff}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Side}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid14429502\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow2\irowband2\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2235\clshdrawnil \cellx2127\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3543\clshdrawnil \cellx5670 @@ -1498,8 +1648,9 @@ There are up to 20 declarer/strain combinations per DD table}{\rtlch\fcs1 \af1\a \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3844\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid4330566 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12400949\charrsid14119459 \cell }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12400949 struct } {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid11276707 HYPERLINK \\l "contractType" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid11276707 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000063006f006e00740072006100630074005400790070006500000000001171430000d500944500258e0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \cs26\f2\fs20\ul\cf19\insrsid12400949\charrsid11276707 -contractType}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf19\insrsid12400949\charrsid11276707 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf19\insrsid11276707 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000063006f006e00740072006100630074005400790070006500000000001171430000d500944500258e00000000027100}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\cs26\f2\fs20\ul\cf19\insrsid12400949\charrsid11276707 contractType}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf19\insrsid12400949\charrsid11276707 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\f2\fs20\cf19\insrsid11276707 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12400949 contracts}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid12400949\charrsid14119459 [10];\cell }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid12400949\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid12400949\charrsid14119459 \trowd \irow3\irowband3\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt \brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1653,8 +1804,8 @@ contractType}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3844\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid750270\charrsid14119459 \cell int suit[52];\cell }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid750270\charrsid14119459 REF suit \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 -\ltrch\fcs0 \f37\fs22\cf1\insrsid750270\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000500000073007500690074000000002a00005e00}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid750270\charrsid14119459 encoding.\cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow2\irowband2\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid11276707\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb \brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth1809\clshdrawnil \cellx1701\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3969\clshdrawnil \cellx5670 @@ -1662,7 +1813,7 @@ contractType}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid750270\charrsid14119459 \cell int rank[52];\cell }\pard \ltrpar \ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid750270 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid750270\charrsid14119459 Encoding 2 .. 14 (}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \i\f37\fs22\cf1\insrsid750270\charrsid14119459 not}{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid750270\charrsid14119459 }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid750270\charrsid14119459 REF card \\h \\ -* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006300610072006400000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 +* MERGEFORMAT }{\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006300610072006400000000bc00005900}}}{\fldrslt {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\ul\cf19\insrsid16386593\charrsid16386593 Card}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid750270\charrsid14119459 encoding).\cell }\pard \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow3\irowband3\lastrow \ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl \brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 @@ -1714,7 +1865,7 @@ String of cards with no space in between, also not between tricks. Each card co \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3844\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 { \rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6580905 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid6580905\charrsid14119459 REF playTraceBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 -\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e00000000b200009469}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 playTraceBin}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid11276707 \par plays[MAXNOOFBOARDS}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 ];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 @@ -1739,7 +1890,7 @@ String of cards with no space in between, also not between tricks. Each card co \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3844\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 { \rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6580905 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 Struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid6580905\charrsid14119459 REF playTracePBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 -\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e00000000b100000300}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 playTracePBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid11276707 \par }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 p}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid11276707 lays[MAXNOOFBOARDS}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 ]; @@ -1787,7 +1938,7 @@ String of cards with no space in between, also not between tricks. Each card co \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3844\clshdrawnil \cellx9514\row \ltrrow}\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 { \rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6580905 {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid6580905\charrsid14119459 REF solvedPlay \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 -\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 +\f2\fs20\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c00610079000000001800ff0000}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid11276707 \par solved[MAXNOOFBOARDS}{\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\cf1\insrsid6580905\charrsid14119459 ];\cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3342996 {\rtlch\fcs1 \af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid6580905\charrsid14119459 \cell }\pard \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow2\irowband2\lastrow \ltrrow @@ -1806,14 +1957,14 @@ String of cards with no space in between, also not between tricks. Each card co \b\f37\cf1\insrsid6099241\charrsid14119459 {\*\bkmkend SolveBoard} \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid8154048 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid5767474 REF deal \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid5767474 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}} -\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid8154048 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241 dl,}{\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid8154048 +\f2\fs18\ul\cf19\insrsid16386593\charrsid5767474 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c000000000d00ff1e00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 +deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid8154048 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241 dl,}{\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid8154048 \par int target, \par int solutions, \par int mode, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid12659025 REF futureTricks \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid12659025 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b0073000000006900ff1e4c}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid8154048 *futp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid8154048 \par int threadIndex}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241\charrsid14119459 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 \cell }\pard\plain \ltrpar @@ -1821,15 +1972,15 @@ String of cards with no space in between, also not between tricks. Each card co \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 {\*\bkmkstart SolveBoardPBN}SolveBoardPBN}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid14119459 {\*\bkmkend SolveBoardPBN} \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16731528 d}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid15150655 l} -{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16731528 ,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid6099241\charrsid14119459 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e000000000000ffe300}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16731528 d}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid15150655 l}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16731528 ,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par int target, \par int solutions, \par int mode, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF futureTricks \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b0073000000006400ffcf07}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *futp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel2\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 int threadIndex}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid14119459 @@ -1854,30 +2005,30 @@ t do that, and they also hide the implementation details such as transposition t \par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid13331862 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14119459\charrsid14119459 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6650094\charrsid14119459 SolveBoard is threa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4542728\charrsid14119459 d-safe, so several threads }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid6650094\charrsid14119459 can call SolveBoard in parallel.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4538894\charrsid14119459 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9716036 -Thus the user of DDS can create threads and call SolveBoard in parallel over them. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4538894\charrsid14119459 The }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14119459\charrsid14119459 +\f37\cf1\insrsid6650094\charrsid14119459 can call SolveBoard in parallel.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4538894\charrsid14119459 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9716036 Thus the user of DD +S can create threads and call SolveBoard in parallel over them. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4538894\charrsid14119459 The }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14119459\charrsid14119459 maximum number of threads is fixed in the DLL at co}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 mpile time and is currently 16. So }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid16530750\charrsid16530750 \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid13331862\charrsid16530750 threadIndex}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid16530750\charrsid16530750 \'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 must be between 0 and 15 inclusive}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9000425 ; see also the function SetMaxThreads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10108539 Together with the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 Play}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10108539 Analyse}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 functions, t}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 his is the only function that exposes the thread number to the user.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9716036 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13331862 -\par There is a \'93transposition table\'94 memory associated with each thread. Each node in the table is effectiv -ely a position after certain cards have been played and other certain cards remain. The table is not deleted automatically after each call to SolveBoard, so it can be reused from call to call. However, it only really makes sense to reuse the table when -the hand is very similar in the two calls. The function will still run if this is not the case, but it won\rquote t be as efficient.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 The reu}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16323149 -se of the transposition table can be}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 controlled by the \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid13857996\charrsid13857996 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid13857996 \'94 parameter}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11540483 , but normally this is not needed and should not be done}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid16530750 +\par There is a \'93transposition table\'94 memory associated with each thread. Each node in the table is effectively a position after certain cards have been played a +nd other certain cards remain. The table is not deleted automatically after each call to SolveBoard, so it can be reused from call to call. However, it only really makes sense to reuse the table when the hand is very similar in the two calls. The funct +ion will still run if this is not the case, but it won\rquote t be as efficient.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 The reu}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16323149 se of the transposition table can be}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 controlled by the \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid13857996\charrsid13857996 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 \'94 parameter}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid11540483 , but normally this is not needed and should not be done}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 \par \par The three parameters \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid16530750\charrsid16530750 target}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 \'94, \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid16530750\charrsid16530750 solutions}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 \'94 and \'93}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid16530750\charrsid16530750 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid16530750 \'94 together control the function. General}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 ly speaking, the target is the number of tricks to be won (at least) by the side to play; solutions cont -rols how many solutions should be returned; and mode }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 controls the search behavior.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16467273 See next page for definitions.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid16530750 +\f37\cf1\insrsid16530750 \'94 together control the function. General}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13857996 +ly speaking, the target is the number of tricks to be won (at least) by the side to play; solutions controls how many solutions should be returned; and mode }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 controls the search behavior.}{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16467273 See next page for definitions.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 \par For equivalent cards, only the highest is returned, and lower equivalent cards are encoded in the }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid11294126\charrsid11294126 REF futureTricks \\h }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid11294126 \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid11294126 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000}} -}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 structure (see \'93equals\'94). +\f37\ul\cf19\insrsid11294126 \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid11294126 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000066007500740075007200650054007200690063006b007300000000bd00ff0028}}}{\fldrslt {\rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20\ul\cf19\insrsid16386593\charrsid16386593 futureTricks}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 structure (see \'93equals\'94). \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11294126 \page }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16530750 @@ -2032,26 +2183,27 @@ is the responsibility of the programmer using the DLL to ensure that reusing the \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid6557970 {\*\bkmkstart CalcDDtable}CalcDDtable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241\charrsid6557970 {\*\bkmkend CalcDDtable} \par }\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid6901705 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c00000037}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\ +\f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c0000003700000ae300}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\ * MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid6901705 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 tableDeal, \line }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000016}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000160000002e55}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 * tablep}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 {\*\bkmkstart CalcDDtablePBN}CalcDDtablePBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6099241\charrsid14119459 {\*\bkmkend CalcDDtablePBN} \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000016}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000016080000181e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 tableDealPBN, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000016}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 * tablep}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f37\cf1\insrsid6099241\charrsid6099241 \cell }\pard\plain \ltrpar -\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6099241 -\trowd \irow0\irowband0\lastrow \ltrrow\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6099241\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt -\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil -\cellx9438\row }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid11107656 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000164a000e5628}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 * tablep}{\rtlch\fcs1 \af0 \ltrch\fcs0 \f37\cf1\insrsid6099241\charrsid6099241 \cell +}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\insrsid6099241 \trowd \irow0\irowband0\lastrow \ltrrow +\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6099241\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb +\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx9438\row }\pard\plain \ltrpar +\s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid11107656 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid6099241 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11107656 CalcDDtablePBN is just like CalcDDtable, except for the input format. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11107656 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid11107656 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6099241 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11107656 CalcDDtable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11107656\charrsid14119459 solves a single deal }{ @@ -2066,35 +2218,36 @@ which must be declared before calling }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\in \par \ltrrow}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 {\*\bkmkstart CalcAllTables}CalcAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid14119459 {\*\bkmkend CalcAllTables} \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTableDeals \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d000000640064005400610062006c0065004400650061006c00730000000e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeals}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *dealsp,}{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d000000640064005400610062006c0065004400650061006c00730000000e0200115f48}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeals}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *dealsp,}{ +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par int mode, \par int trumpFilter[5], \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTablesRes \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000073}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000073ff0001ac00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *resp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF allParResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c0074007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c00740073000000130000007b00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid1846101 \par }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel2\rin0\lin0\pararsid5594575\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1846101 \cell }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 { \rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 {\*\bkmkstart CalcAllTablesPBN}CalcAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241 PBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid14119459 {\*\bkmkend CalcAllTablesPBN} \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTableDealsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000010000000640064005400610062006c0065004400650061006c007300500042004e00000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *dealsp, }{ -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000010000000640064005400610062006c0065004400650061006c007300500042004e00000013ff00b49700}}}{\fldrslt {\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 + *dealsp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par int mode, \par int trumpFilter[5], \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF ddTablesRes \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065007300520065007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c00650073005200650073000000130600354b00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTablesRes}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *resp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8323199\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6099241\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6099241\charrsid14119459 REF allParResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c0074007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000061006c006c0050006100720052006500730075006c00740073000000130000f30000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 allParResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6099241\charrsid14119459 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid1846101\charrsid5594575 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6099241 \trowd \irow0\irowband0\lastrow \ltrrow \ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6099241\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb @@ -2102,42 +2255,44 @@ which must be declared before calling }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\in \s3\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid11107656 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11107656 CalcAllTablesPBN is just like CalcAllTables, except for the input format. \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11107656 -\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11107656 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 CallAllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid1770393 calculates }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 the double dummy values }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 of the }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid9713208 denomination}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 /declarer hand combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 in }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 -\b\f2\fs22\cf1\insrsid11762622\charrsid11762622 \'93*dealsp\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 -a number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 s in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 . This increases}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 the speed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 compared to }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid4602097 calculating}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 the}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 se values}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 using a -}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 CalcDDtable call }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 for each }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\cf1\insrsid1770393\charrsid1770393 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 The results are returned in }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid11762622\charrsid11762622 \'93*resp\'94}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid11762622 which must be defined before CalcAllTables is called.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 +\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11107656 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16713324 Calc}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 AllTables}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393\charrsid1770393 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 calculates }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 the double dummy values }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393 of the }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9713208 denomination}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 /declarer hand combinations }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 +in }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid11762622\charrsid11762622 \'93*dealsp\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 for }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393\charrsid1770393 a number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13319718 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 s in parallel}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid12068517 . This increases}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10631094 the speed}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 + compared to }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid4602097 calculating}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 the}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 se values}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid1770393\charrsid1770393 using a }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12068517 CalcDDtable call }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 for each }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\cf1\insrsid13319718 DD table}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393\charrsid1770393 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 The results are returned in }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 +\b\f2\fs22\cf1\insrsid11762622\charrsid11762622 \'93*resp\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 which must be defined before CalcAllTables is called.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid1770393 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6099241 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 The }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid6099241\charrsid6099241 \'93mode\'94}{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 parameter contains the vulnerability (}{\field{\*\fldinst {\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ul\cf19\insrsid6099241\charrsid6099241 REF vulnerable \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid6099241 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000760075006c006e0065007200610062006c006500000000}}}{\fldrslt {\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 -Vulnerable}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 encoding}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5927621 ; not to be confused with the SolveBoard }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 -\b\f2\fs22\cf1\insrsid5927621\charrsid5927621 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 ) for use in the par calculation. It is set to -1 if no par calculation is to be performed. +\f37\ul\cf19\insrsid16386593\charrsid6099241 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000760075006c006e0065007200610062006c006500000000eb00001e34}}}{\fldrslt {\rtlch\fcs1 \af2 \ltrch\fcs0 +\f37\ul\cf19\insrsid16386593\charrsid16386593 Vulnerable}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 encoding}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid5927621 +; not to be confused with the SolveBoard }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid5927621\charrsid5927621 mode}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 +) for use in the par calculation. It is set to -1 if no par calculation is to be performed. \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11762622 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6099241 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9713208 There are 5 possible denominations or strains (the four trump suits and no trump). }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 The parameter }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid11762622\charrsid11762622 \'93trumpFilter\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 describes which, if any, of the }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 5 possibilities}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 that will be }{\rtlch\fcs1 \af1 \ltrch\fcs0 \i\f37\cf1\insrsid11762622\charrsid6099241 excluded}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 from the calculations. They are defined}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 in }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid6099241\charrsid6099241 REF suit \\h \\* MERGEFORMAT }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid6099241 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 encoding order, so}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 setting trumpFilter to \{ -FALSE, FALSE, TRUE, TRUE, TRUE\} means that values will only be calculated for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 the trump suits spades and h}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 earts.}{\rtlch\fcs1 \af1 \ltrch\fcs0 +\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid6099241 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000007300750069007400000000cd000012ed}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\ul\cf19\insrsid16386593\charrsid16386593 Suit}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 encoding order, so}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 setting trumpFilter to \{FAL +SE, FALSE, TRUE, TRUE, TRUE\} means that values will only be calculated for }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 the trump suits spades and h}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11762622 earts.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13244366 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13244366\charrsid9401184 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9713208 -\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6099241 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 The maximum number of DD tables in a CallAllTables call depends on the number of }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid6099241 strains required}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2101911 , see the following table:}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 +\par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid6099241 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 The maxim}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16713324 um number of DD tables in a Calc}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\cf1\insrsid9175287 AllTables call depends on the number of }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 strains required}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2101911 , see the following table:}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid9175287 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid6099241 \par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts18\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14090435\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2235\clshdrawnil \cellx2127\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3543\clshdrawnil \cellx5670 \pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\b\f37\cf1\insrsid6099241\charrsid6099241 Number of strains\cell }\pard \ltrpar\qc \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid6099241 -Maximum number of DD tables\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 { -\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6099241 \trowd \irow0\irowband0\ltrrow\ts18\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 +\b\f37\cf1\insrsid6099241\charrsid6099241 Number of strains\cell }\pard \ltrpar\qc \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6099241\charrsid6099241 M +aximum number of DD tables\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 +\af1 \ltrch\fcs0 \insrsid6099241 \trowd \irow0\irowband0\ltrrow\ts18\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14090435\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2235\clshdrawnil \cellx2127\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth3543\clshdrawnil \cellx5670\row \ltrrow }\pard\plain \ltrpar\qc \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid6099241\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 @@ -2178,35 +2333,35 @@ Maximum number of DD tables\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intb \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574 SolveAllBoards}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid7880574\charrsid5320216 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7880574\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid7880574\charrsid14119459 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f006100720064007300000000f300001ef6}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 \par struct}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574 }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f00610072006400730000000038120012f5}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574 \par * solvedp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid7880574 \cell }\pard\plain \ltrpar\s3\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel2\rin0\lin0\pararsid5320216\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid5320216 {\*\bkmkstart SolveAllChunksBin}SolveAllChunksBin}{ \rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid7880574\charrsid5320216 {\*\bkmkend SolveAllChunksBin} \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5320216\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 -boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid7880574\charrsid14119459 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f0061007200640073000000001316001e0b}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5320216\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000771a00bc8f}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 int chunkSize}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid1846101 \cell }\pard\plain \ltrpar \s3\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel2\rin0\lin0\pararsid5320216\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid5320216 {\*\bkmkstart SolveAllChunksPBN}SolveAllChunksPBN}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid7880574\charrsid5320216 {\*\bkmkend SolveAllChunksPBN} \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5320216\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e00000000000000db00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5320216\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid7880574\charrsid14119459 REF solvedBoards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000073006f006c0076006500640042006f006100720064007300000000c42100fce2}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedBoards}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7880574\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574\charrsid14119459 int chunkSize}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7880574 \par @@ -2236,9 +2391,9 @@ rd 5, and so on. This continued until all boards had}{\rtlch\fcs1 \af1 \ltrch\f \f37\cf1\insrsid15668792 be waiting for the las}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 t thread to finish}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 . \par \par The transposition table in a given thread (see }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid15668792\charrsid15668792 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid15668792 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000013}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 ) is generally not reused between board -2, 4 and 5 in thread 2. This only happens if SolveBoard itself determines that the boards are suspiciously similar. +\f37\ul\cf19\insrsid16386593\charrsid15668792 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f006100720064000000137a2700a53c}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 +\f37\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 +) is generally not reused between board 2, 4 and 5 in thread 2. This only happens if SolveBoard itself determines that the boards are suspiciously similar. \par \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 If the chunk size wa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 s 2, then initially thread 0 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 got}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 boards 0 and 1, thread 1 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 got}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 boards 2 and 3, thread 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 got}{ @@ -2252,9 +2407,8 @@ sition table in a given thread wa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid \ltrch\fcs0 \f37\cf1\insrsid15668792 that boards are gr}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 ouped in chunks of 2 or 10, it wa}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid15668792 s possible to force the DD solver to use this knowledge. }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7880574 However, this is rather limiting on the user, as the alignment must remain perfect throughout the batch. \par -\par SolveAllBoards now detec -ts repetitions automatically within a batch, whether or not the hands are evenly arranged and whether or not the duplicates are next to each other. This is more flexible and transparent to the user, and the overhead is negligible. Therefore, use SolveAl -lBoards! +\par SolveAllBoards now detects repetitions automatically within a batch, whether or not the hands are evenly arranged and whether or not the duplicates are next to each other. This is more flexible and transparent to the user, + and the overhead is negligible. Therefore, use SolveAllBoards! \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 \page \par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid12658900\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt \clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil @@ -2262,10 +2416,10 @@ lBoards! \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid12658900 {\*\bkmkstart Par}Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid12658900 {\*\bkmkend Par} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12658900\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12658900\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000074}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000074452b0092ac}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12658900\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000030}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c00740073000000300b2c0060ad}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *presp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12658900\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 int vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 @@ -2273,13 +2427,14 @@ lBoards! \rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid12658900\charrsid12658900 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12658900\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid12658900\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000013762d00906b}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 + \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5843075 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsDealer" }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c0065007200000000000065005600ff0568002a1800f388} -}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid5843075\charrsid7880574 parResultsDealer}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5843075 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *presp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid12658900\charrsid14119459 +\ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c0065007200000000000065005600ff0568002a1800f388008b002400}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid5843075\charrsid7880574 parResultsDealer}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5843075 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid12658900\charrsid14119459 *presp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 \par int dealer, \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12658900\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid12658900\charrsid14119459 int vulnerable}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256 @@ -2291,11 +2446,11 @@ lBoards! \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid11956256 Sides}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid11956256\charrsid12658900 Par}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid11956256 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12128238\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid11956256\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000006e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid11956256\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000006e6232006b40}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid11956256\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256\charrsid14119459 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsDealer" }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c006500720000000000000000a400ffff79000020008558}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004400650061006c006500720000000000000000a400ffff790000200085581266002e00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\lang1033\langfe1031\langfenp1031\insrsid5843075\charrsid7880574 parResultsDealer}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5843075 *sidesRes[2],}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid11956256\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256\charrsid14119459 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid12128238\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid11956256\charrsid14119459 int vulnerable}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 @@ -2310,22 +2465,23 @@ lBoards! \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450 Bin}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid10173450 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789515\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid10173450\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000078}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000007886a3000013}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16132195\charrsid16132195 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsMaster" }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d00610073007400650072000000000016000fd000bc091a00005400fa20}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d00610073007400650072000000000016000fd000bc091a00005400fa20000100d400}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid16132195\charrsid7880574 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16132195\charrsid16132195 * presp,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789515\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 int vulnerable}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10173450\charrsid12658900 \cell }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450 SidesParBin}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid10173450\charrsid12658900 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789515\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid10173450\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000072}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000726452008200}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 *tablep, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 + \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16132195\charrsid16132195 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsMaster" }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000001e000ff200ffde0100443000f964}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000001e000ff200ffde0100443000f964129a006700}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid16132195\charrsid7880574 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16132195\charrsid16132195 * presp,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450\charrsid14119459 \par int dealer, @@ -2339,21 +2495,21 @@ lBoards! \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid15800872\charrsid15800872 ConvertToDealerTextFormat}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid10173450 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789515\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid16132195\charrsid15800872 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000c323000f5e0000c101003772005c00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000c323000f5e0000c101003772005c00009ad62000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid16132195\charrsid7880574 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid16132195\charrsid15800872 *pres,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid10173450\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid10173450 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1789515\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15800872 char *resp}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10173450\charrsid12658900 \cell }{ \rtlch\fcs1 \af2 \ltrch\fcs0 \b\f31506\cf1\insrsid15800872\charrsid15800872 ConvertToSidesTextFormat}{\rtlch\fcs1 \af2 \ltrch\fcs0 \b\f31506\cf1\insrsid15800872 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15800872\charrsid15800872 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsMaster" }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d006100730074006500720000000037290044140004966020453100ec00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d006100730074006500720000000037290044140004966020453100ec00009a000100}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid15800872\charrsid7880574 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid15800872\charrsid15800872 *pres,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15800872 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15800872\charrsid15800872 struct }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid4877901\charrsid7880574 HYPERLINK \\l "parTextResults" }{ \rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\lang1033\langfe1031\langfenp1031\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000700061007200540065007800740052006500730075006c0074007300000001492a0000fd00001c00006b6d00fe00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \cs26\f2\fs18\ul\cf19\insrsid15800872\charrsid7880574 -parTextResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid15800872\charrsid15800872 *resp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid15800872\charrsid15800872 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000700061007200540065007800740052006500730075006c0074007300000001492a0000fd00001c00006b6d00fe00000e002a00}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\cs26\f2\fs18\ul\cf19\insrsid15800872\charrsid7880574 parTextResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid15800872\charrsid15800872 *resp}{\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid15800872\charrsid15800872 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid10173450\charrsid11956256 \trowd \irow3\irowband3\lastrow \ltrrow \ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid1789515\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb \brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx9438\row }\pard \ltrpar @@ -2362,10 +2518,10 @@ parTextResults}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\a \f37\cf1\insrsid13072585 Par, DealerPar, SidesPar, DealerParBin and SidesParBin }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 calculate the par score and par contracts of a given double-dummy solution matrix }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid12658900\charrsid12658900 \'93*tablep\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 which would often be the solution of a call to }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid12658900\charrsid12658900 REF CalcDDtable \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid12658900 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000430061006c006300440044007400610062006c006500000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtable}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10290420 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid10290420 -Since the input is a table, there is no PBN and non-PBN version}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13840817 of these}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid10290420 function}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13840817 s}{\rtlch\fcs1 -\af1 \ltrch\fcs0 \f37\insrsid10290420 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12854747 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000430061006c006300440044007400610062006c006500000000c200005700}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 CalcDDtable}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 .}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10290420 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid10290420 Since the input is a table, there is no PBN and non-PBN v +ersion}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13840817 of these}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid10290420 function}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid13840817 s}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid10290420 .}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \f37\cf1\insrsid12854747 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 \par Before the functions can be called, a structure of the type }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid12658900\charrsid12658900 \'93parResults\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2165691 ,}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2505631 }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid2505631\charrsid2505631 \'93parResultsDealer\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2505631 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2165691 or }{ @@ -2374,17 +2530,17 @@ Since the input is a table, there is no PBN and non-PBN version}{\rtlch\fcs1 \af \par \par The }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid12658900\charrsid12658900 \'93vulnerable\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 parameter is given using }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid12658900\charrsid12658900 REF vulnerable \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid12658900 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000760075006c006e0065007200610062006c006500000000}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 Vulnerable}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 encoding. +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b000000760075006c006e0065007200610062006c00650000000094000032a7}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 Vulnerable}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid12658900 encoding. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14574742 -\par The Par() function uses knowledge of the vulnerability, but not of the dealer. It attempts to return results for both declaring sides. These results can be different in - some rare cases, for instance when both sides can make 1NT due to the opening lead. +\par The Par() function uses knowledge of the vulnerability, but not of the dealer. It attempts to return results for both declaring sides. These results can be different in some rare cases, for instance when both sides can make 1NT due + to the opening lead. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2505631 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2838088 The DealerPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14574742 () function also uses knowledge of the }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid14574742\charrsid14574742 \'93 dealer\'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14574742 using }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid14574742\charrsid14574742 REF hand \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid14574742 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e006400000058}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 Hand}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14574742 encoding. The argument is that in all practical cases, the dealer is known when the vulnerability is known. Therefore all results returned will be for the same side. - +\f37\ul\cf19\insrsid16386593\charrsid14574742 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b020000000800000005000000680061006e0064000000580019000353}}}{\fldrslt {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 Hand}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid14574742 encoding. The argument is that in all practical cases, the dealer is known when the vulnerability is known. Therefore all re +sults returned will be for the same side. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9716036 \par The SidesPar() function is similar to the Par() function, the only difference is }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid13840817 that }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9716036 the par results are given in the same format as for DealerPar(). @@ -2408,8 +2564,8 @@ the par results are given in the same format as for DealerPar(). \f37\insrsid14574742\charrsid14574742 pades and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 h}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid14574742 earts contracts, 2 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 spades and 2 h }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid14574742 earts with an overtrick.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid14574742 This is from the NS view}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 , shown by \'93NS:\'94 meaning that NS made the first bid}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid14574742 . }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 -Note that this information is actually not enough, as it may be that N and S can make a given contract and that either E or W can bid this same contract (for instance 1NT) before N but not before S. So -in the rare cases where the NS and EW sides are not the same, the results will take some manual inspection. +Note that this information is actually not enough, as it may be that N and S can make a given contract and that either E or W can bid this same c +ontract (for instance 1NT) before N but not before S. So in the rare cases where the NS and EW sides are not the same, the results will take some manual inspection. \par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1 \ltrch\fcs0 \f3\lang1033\langfe1053\langnp1033\langfenp1053\insrsid14574742 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \ltrpar \ql \fi-360\li360\ri0\nowidctlpar\wrapdefault\faauto\ls3\rin0\lin360\itap0\pararsid14574742 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 \'93}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid9515749 NS:NS 23S,N 23H}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742\charrsid14574742 \'94}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid14574742 : Only North makes 3 hearts. @@ -2424,16 +2580,15 @@ separate text string: \qj \fi-360\li360\ri0\nowidctlpar\wrapdefault\faauto\ls3\rin0\lin360\itap0\pararsid2369496 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid2369496 \'934S*-EW-1\'94 means that E and W can both sacrifice in four spades doubled, going down one trick. \par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1 \ltrch\fcs0 \f3\lang1033\langfe1053\langnp1033\langfenp1053\insrsid2369496 \loch\af3\dbch\af0\hich\f3 \'b7\tab}\'933N-EW\'94 means that E and W can both make exactly 3NT. \par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1 \ltrch\fcs0 \f3\lang1033\langfe1053\langnp1033\langfenp1053\insrsid2369496 \loch\af3\dbch\af0\hich\f3 \'b7\tab}\'934N-W+1\'94 - means that only West can make 4NT +1. In the last example, 5NT just making can also be considered a par contract, but North-South don\rquote -t have a profitable sacrifice against 4NT, so the par contract is shown in this way. If North-South did indeed have a profitable sacrifice, perhaps 5C*_NS-2, then par contract would have been shown as \'935N-W\'94. Par() would show \'934N-W+1\'94 as -\'93W 45N\'94. + means that only West can make 4NT +1. In the last example, 5NT just making can also be considered a par contract, but North-South don\rquote t have a profitable sacrifice against 4NT, so the par contract is shown in this way. If North-Sou +th did indeed have a profitable sacrifice, perhaps 5C*_NS-2, then par contract would have been shown as \'935N-W\'94. Par() would show \'934N-W+1\'94 as \'93W 45N\'94. \par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af1 \ltrch\fcs0 \f3\lang1033\langfe1053\langnp1033\langfenp1053\insrsid2369496 \loch\af3\dbch\af0\hich\f3 \'b7\tab}SidesPar() give the par contract text strings as described above for each side. \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid3547548 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2369496 \par }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11099036 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid269493 DealerParBin and SidesParBin are similar to DealerPar }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9000425 and}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid269493 SidesPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9000425 , respectively}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid269493 , except that both functions give the output results in binary using the }{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid269493\charrsid13703926 \'93}{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid4877901\charrsid7880574 HYPERLINK \\l "parResultsMaster" }{\rtlch\fcs1 \af1 \ltrch\fcs0 \cf19\insrsid2101911\charrsid7880574 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000bb3100000000000001000000c1fd68}}}{\fldrslt {\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000001100000070006100720052006500730075006c00740073004d0061007300740065007200000000bb3100000000000001000000c1fd680000006f00}}}{\fldrslt {\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \cs26\b\f2\fs22\ul\cf19\insrsid269493\charrsid7880574 parResultsMaster}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid269493\charrsid13703926 \'94}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid269493 }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f31506\cf1\insrsid269493\charrsid269493 structure}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid269493 .}{\rtlch\fcs1 \af2\afs22 \ltrch\fcs0 \b\f2\fs22\cf1\insrsid9000425 }{ \rtlch\fcs1 \af2 \ltrch\fcs0 \f31506\cf1\insrsid5186751 This simplifies the writing of a conversion program to }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f31506\cf1\insrsid14092583 get }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f31506\cf1\insrsid5186751 @@ -2461,30 +2616,30 @@ s in parResultsMaster are used when calling }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid7931676\charrsid6557970 {\*\bkmkstart CalcPar}CalcPar}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid7931676\charrsid6557970 {\*\bkmkend CalcPar} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8538722\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid6901705 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705\charrsid6901705 REF ddTableDeal \\h }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid6901705 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c00000058}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c000000640064005400610062006c0065004400650061006c000000580000007300}}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid6901705 \\* MERGEFORMAT }}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDeal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722\charrsid6901705 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722 dl}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 \par int vulnerable, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000022}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722 * t}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 p, +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c00740073000000220000002398}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722 * t}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 p, \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid4071901\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000074}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c007400730000007400000000be}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid4071901 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6058144\charrsid4071901 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid7931676\charrsid7931676 {\*\bkmkstart CalcParPBN}CalcParPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid7931676 {\*\bkmkend CalcParPBN} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid8538722\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid14119459 REF ddTableDealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e00000063}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722 dl}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 -\f2\fs18\cf1\insrsid8538722\charrsid14119459 , +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c0065004400650061006c00500042004e000000630000000004}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableDealPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722\charrsid14119459 }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722 dl}{\rtlch\fcs1 \af2\afs18 +\ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 , \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid14119459 REF ddTableResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722 * t}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 p, +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000f000000640064005400610062006c00650052006500730075006c007400730000000000000000bc}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 ddTableResults}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722 * t}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid8538722\charrsid14119459 p, \par int vulnerable, \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid8538722\charrsid14119459 REF parResults \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c0074007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000070006100720052006500730075006c007400730000000000005d009e}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 parResults}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722\charrsid14119459 *presp}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid8538722 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6058144 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid4071901\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid6058144\charrsid7931676 \cell }\pard \ltrpar @@ -2515,26 +2670,26 @@ s in parResultsMaster are used when calling }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid2849436 PlayBin}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2849436 {\*\bkmkend TracePlayBin} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid2849436\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF deal \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 -\ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 dl, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000050000006400650061006c000000000000000037}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 deal}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 +\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 dl, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF playTraceBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTraceBin}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500420069006e000000000000c40015}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTraceBin}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 play,}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF solvedPlay \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000000b4000df}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par int thrId}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2849436\charrsid2849436 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid3347855\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid2449260 {\*\bkmkstart TracePlayPBN}Analyse}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid2849436 PlayPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2849436\charrsid2849436 {\*\bkmkend TracePlayPBN} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid2849436\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF dealPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000014}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { -\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 dlPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b0200000008000000080000006400650061006c00500042004e00000014006f000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 dealPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj +{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 dlPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF playTracePBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracePBN}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000d00000070006c006100790054007200610063006500500042004e000000004b170000ad}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracePBN}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 playPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid2849436\charrsid14119459 REF solvedPlay \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c0061007900000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000073006f006c0076006500640050006c00610079000000009448ff0092}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlay}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid2849436\charrsid14119459 \par int thrId}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\cf1\insrsid2849436\charrsid2849436 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid2849436 \trowd \irow0\irowband0\lastrow \ltrrow @@ -2547,8 +2702,9 @@ s in parResultsMaster are used when calling }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ \par }\pard\plain \ltrpar\s3\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid2849436 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436\charrsid2849436 The }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 function returns a list of double-dummy values after each specific played card in a hand. Since the function uses }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid2849436\charrsid2849436 REF SolveBoard \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid2849436 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f00610072006400000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { -\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 , the same comments apply concerning the thread number \'93thrId\'94 and the transposition tables.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436\charrsid2849436 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000b00000053006f006c007600650042006f0061007200640000000094b4004264}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 SolveBoard}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 , the same comments apply concerning the thread number \'93thrId\'94 and the transposition tables.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436\charrsid2849436 + \par }\pard\plain \ltrpar\s23\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2849436 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1031\langfe1033\cgrid\langnp1031\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1033\langnp1033\insrsid2849436 \par }\pard\plain \ltrpar\s3\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid2849436 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 @@ -2558,9 +2714,8 @@ s in parResultsMaster are used when calling }{\rtlch\fcs1 \af2 \ltrch\fcs0 \f37\ \par \par 9 10 10 10 10 9 9 \par -\par The number of tricks are always seen from declarer\rquote -s viewpoint (he is the one to the right of the opening leader). There is one more result in the trace than there are cards played, because there is a DD value before any card is played, and one DD value after each card played.}{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\cf1\insrsid2849436 +\par The number of tricks are always seen from declarer\rquote s viewpoint (he is the one to the right of the opening leader). + There is one more result in the trace than there are cards played, because there is a DD value before any card is played, and one DD value after each card played.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid2849436 \par }\pard \ltrpar\s3\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0\pararsid16720464 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16720464\charrsid16720464 \par As of v2.8.3, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16720464 the functions can be invoked not just from the beginning of a 13-trick hand, but from any position. Cards in dl.currentTrickSuit and dl.currentTrickRank are respected.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16720464\charrsid16720464 @@ -2572,26 +2727,27 @@ s viewpoint (he is the one to the right of the opening leader). There is one mo \b\f37\insrsid2849436 {\*\bkmkend TraceAllPlaysBin} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5979431\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF boards \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f006100720064007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 -\af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000700000062006f00610072006400730000000095c8004277}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boards}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { +\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *bop, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF playTracesBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesBin}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *plp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300420069006e0000000000fb010000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesBin}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *plp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF solvedPlays \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c006100790073000000cb}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c006100790073000000cb0003000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 \par int chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid5979431\charrsid2849436 \cell }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid1190356\yts18 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid2449260 {\*\bkmkstart TraceAllPlaysPBN}Analyse}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid2849436\charrsid2849436 AllPlaysPBN}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid2849436\charrsid2849436 {\*\bkmkend TraceAllPlaysPBN} \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid5979431\yts18 {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF boardsPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e000000af}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj -{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *bopPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000a00000062006f006100720064007300500042004e000000af0066480000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 boardsPBN}}}\sectd \ltrsect +\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *bopPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF playTracesPBN \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300500042004e000000f0}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesPBN}}}\sectd \ltrsect -\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *plpPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e00000070006c0061007900540072006100630065007300500042004e000000f00066000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 playTracesPBN}}} +\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *plpPBN, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 + \par struct }{\field{\*\fldinst {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid5979431\charrsid14119459 REF solvedPlays \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid14119459 {\*\datafield -08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c00610079007300000000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect +08d0c9ea79f9bace118c8200aa004ba90b02000000080000000c00000073006f006c0076006500640050006c006100790073000000000069020000}}}{\fldrslt {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\ul\cf19\insrsid16386593\charrsid16386593 solvedPlays}}}\sectd \ltrsect \linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid5979431\charrsid14119459 *solvedp, }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid5979431\charrsid14119459 \par int chunkSize}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid2849436 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid2849436 \trowd \irow0\irowband0\lastrow \ltrrow @@ -2607,52 +2763,73 @@ s viewpoint (he is the one to the right of the opening leader). There is one mo \f37\cf1\insrsid10376323 AllPlays* functions invoke SolveBoard several times in parallel in multiple threads, rather than sequentially in a single thread. This increases execution speed. Up to 20 boards are permitted per call. \par \par Concerning chunkSize, exactly the same remarks apply as with }{\field{\*\fldinst {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\ul\cf19\insrsid10376323\charrsid10376323 REF SolveAllChunksBin \\h \\* MERGEFORMAT }{\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\ul\cf19\insrsid16386593\charrsid10376323 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300420069006e00000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 +\f37\ul\cf19\insrsid16386593\charrsid10376323 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000001200000053006f006c007600650041006c006c004300680075006e006b007300420069006e000000000006000000}}}{\fldrslt {\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\ul\cf19\insrsid16386593\charrsid16386593 SolveAllChunksBin}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid10376323 . \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7759131 \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid9000425 \page }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid7759131 -\par \ltrrow}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid75593\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\b\f37\lang1033\langfe1031\langfenp1031\insrsid7759131 {\*\bkmkstart SetMaxThreads}SetMaxThreads}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7759131\charrsid14119459 {\*\bkmkend SetMaxThreads} }{\rtlch\fcs1 -\af1 \ltrch\fcs0 \b\f37\insrsid7759131\charrsid15413752 -\par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7759131\charrsid14119459 int }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7759131 userThreads}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7759131\charrsid11946565 \cell }{ -\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid7759131 {\*\bkmkstart FreeMemory}FreeMemory}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid7759131\charrsid2849436 {\*\bkmkend FreeMemory} -\par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7759131 void}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 -\af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7759131 \trowd \irow0\irowband0\lastrow \ltrrow -\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid75593\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb -\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx9438\row }\pard \ltrpar -\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid10376323 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131 -\par }\pard\plain \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid7759131 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\b\f37\insrsid7759131\charrsid3240706 SetMaxThreads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131 r}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131\charrsid7759131 eturns }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid9000425 the }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \f37\insrsid7759131\charrsid7759131 actual number of threads.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131 -\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid11099036 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\insrsid9000425\charrsid11099036 -\par }\pard\plain \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid11099036 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\insrsid7759131\charrsid7759131 DDS has a preferred memory size per thread, currently about 95 MB, and a maximum memory size per thread, currently about 160 MB. It will also not use more than 70% of the available memory. It will not create more thr -eads than there are processor cores, as this will only require more memory and will not improve performance. Within these constraints, DDS auto-configures the number of threads. -\par -\par DDS first detects the number of cores and the available memory. If this doesn't work for some reason, it defaults to 1 thread which is allowed to use the maximum memory size per thread. -\par -\par DDS then checks whether a number of threads equal to the number of cores will fit within the available memory when each thread may use the maxim -um memory per thread. If there is not enough memory for this, DDS scales back its ambition. If there is enough memory for the preferred memory size, then DDS still creates a number of threads equal to the number of cores. If there is not even enough me -mory for this, DDS scales back the number of threads to fit within the memory. -\par -\par }\pard \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid15088206 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131\charrsid7759131 -The user can suggest to DDS a number of threads by calling SetMaxThreads. DDS will never create more threads than requested, but it may create fewer if there is not enough memo -ry, calculated as above. Calling SetMaxThreads is optional, not mandatory. DDS will always select a suitab}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206 le number of threads on its own. +\par \ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6378612\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0 +\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth3469\clshdrawnil \cellx3361\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl +\cltxlrtb\clftsWidth3\clwWidth2798\clshdrawnil \cellx6159\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth3355\clshdrawnil \cellx9514\pard\plain \ltrpar +\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid75593\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\b\f37\lang1033\langfe1031\langfenp1031\insrsid6378612 {\*\bkmkstart SetMaxThreads}SetMaxThreads}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid6378612\charrsid14119459 {\*\bkmkend SetMaxThreads} }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \b\f37\insrsid6378612\charrsid15413752 +\par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6378612\charrsid14119459 int }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6378612 userThreads}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid6378612\charrsid11946565 \cell }{ +\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid6378612 {\*\bkmkstart SetResources}SetResources{\*\bkmkend SetResources} +\par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1389500 int maxMemoryMB,\line int userThreads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid1389500 \cell {\*\bkmkstart SetThreading}SetThreading}{\rtlch\fcs1 \af1 +\ltrch\fcs0 \b\f37\insrsid6378612\charrsid2849436 {\*\bkmkend SetThreading} +\par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid1389500 int code}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid6378612 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 +\af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid6378612 \trowd \irow0\irowband0\lastrow \ltrrow +\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid6378612\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl +\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth3469\clshdrawnil \cellx3361\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth2798\clshdrawnil \cellx6159\clvertalt\clbrdrt +\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth3355\clshdrawnil \cellx9514\row }\pard \ltrpar\qj \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid10376323 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid7759131 +\par }\pard\plain \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\b\f37\insrsid7759131\charrsid3240706 SetMaxThreads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 and }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid1389500\charrsid1389500 SetResources}{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f37\insrsid1389500 set the system resources for DDS. SetThreading can set the threading system that is used internally in DDS; you probably do not need this. The codes are in DLL.h. +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1389500 +\par }\pard\plain \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid1389500\charrsid1389500 DDS }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 has two thread sizes internally, \'93large\'94 (about 95-160 MB) and \'93small\'94 (about 20-30 MB). The large ones are about 12-14% faster at the moment. D +DS chooses the best mixture given the resources constraints. More specifically, the memory usage will be limited as follows. +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1389500 +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid1389500 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}\pard\plain \ltrpar +\s1\qj \fi-360\li360\ri0\keepn\nowidctlpar\wrapdefault\faauto\ls12\outlinelevel0\rin0\lin360\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid1389500 maxMemoryMB plus a percentage}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500\charrsid1389500 (this }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 works out statistically). +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid1389500\charrsid1389500 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500\charrsid1389500 +70% of the free memory. +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid1389500\charrsid1389500 \loch\af10\dbch\af0\hich\f10 \'a7\tab}No more than 1800 MB if we\rquote re on a 32-bit system. +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\insrsid1389500\charrsid1389500 +\par }\pard\plain \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid1389500 The number of threads will }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207 currently }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 be limited as follows. +\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1389500 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid1389500 +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid1389500\charrsid7560207 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}\pard\plain \ltrpar +\s1\qj \fi-360\li360\ri0\keepn\nowidctlpar\wrapdefault\faauto\ls12\outlinelevel0\rin0\lin360\itap0\pararsid7560207 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid1389500\charrsid7560207 If compiled single-threaded, or single-threading is selected: 1. +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid7560207\charrsid7560207 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207\charrsid7560207 +If one of the experimental \'93IMP\'94 codes is used (don\rquote t use!), 1.5 times the number of processor cores.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500\charrsid7560207 +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid7560207\charrsid7560207 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207\charrsid7560207 +Otherwise the lower of userThreads and 1.5 times the number of processor cores.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207 +\par {\listtext\pard\plain\ltrpar \s1 \rtlch\fcs1 \af1 \ltrch\fcs0 \f10\lang1033\langfe1053\langnp1033\langfenp1053\insrsid7560207\charrsid7560207 \loch\af10\dbch\af0\hich\f10 \'a7\tab}}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207\charrsid7560207 +But fewer threads if there is not enough memory.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7560207\charrsid7560207 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid15088206 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid15088206 \par }\pard\plain \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid15088206 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\f37\insrsid15088206\charrsid15088206 It may be possible, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206 -especially on non-Windows systems, to call SetMaxThreads() actively, even though the user does not want to influence the default values. In this case, use a 0 argument.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206\charrsid15088206 +\f37\insrsid15088206\charrsid15088206 It }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7560207 is}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206\charrsid15088206 possible, }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206 +especially on non-Windows systems, to call SetMaxThreads() actively, even though the user does not want to influence the default values. In this case, use a 0 }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 as }{\rtlch\fcs1 \af1 \ltrch\fcs0 +\f37\insrsid15088206 argument.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid15088206\charrsid15088206 \par }\pard \ltrpar\s1\qj \li0\ri0\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0\pararsid11099036 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131\charrsid7759131 -\par SetMaxThreads can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3240706 +\par SetMaxThreads}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid1389500 /SetResources}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7759131\charrsid7759131 + can be called multiple times even within the same session. So it is theoretically possible to change the number of threads dynamically.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid3240706 \par +\par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid1389500\charrsid3240706 FreeMemory}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\cf1\insrsid1389500 \par }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\cf1\insrsid3240706\charrsid3240706 It is possible to ask DDS to give up its dynamically allocated memory by calling }{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \b\f37\cf1\insrsid3240706\charrsid3240706 FreeMemory}{\rtlch\fcs1 -\ab\af1 \ltrch\fcs0 \f37\cf1\insrsid3240706\charrsid3240706 . This could be useful for instance if there is a long pause where DDS is not used within a sess -ion. DDS will free its memory when the DLL detaches from the user program, so there is no need for the user to call this function before detaching.}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\cf1\insrsid7483127 +\ab\af1 \ltrch\fcs0 \f37\cf1\insrsid3240706\charrsid3240706 . This could be useful for instance if there is a long pause where DDS is not used within a session. DDS will free its memory when the DLL detaches from t +he user program, so there is no need for the user to call this function before detaching.}{\rtlch\fcs1 \ab\af1 \ltrch\fcs0 \f37\cf1\insrsid7483127 \par -\par \ltrrow}\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7483127\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 -\b\f37\lang1033\langfe1031\langfenp1031\insrsid7483127 {\*\bkmkstart GetDDSInfo}GetDDSInfo}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7483127\charrsid14119459 {\*\bkmkend GetDDSInfo} }{\rtlch\fcs1 \af1 -\ltrch\fcs0 \b\f37\insrsid7483127\charrsid15413752 +\par \ltrrow}\trowd \irow0\irowband0\lastrow \ltrrow\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid7483127\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0 +\tblindtype3 \clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl \cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx4665\clvertalt\clbrdrt\brdrtbl \clbrdrl\brdrtbl \clbrdrb\brdrtbl \clbrdrr\brdrtbl +\cltxlrtb\clftsWidth3\clwWidth4773\clshdrawnil \cellx9438\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\intbl\wrapdefault\faauto\rin0\lin0\pararsid7483127\yts18 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 +\f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\lang1033\langfe1031\langfenp1031\insrsid7483127 {\*\bkmkstart GetDDSInfo}GetDDSInfo}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 +\f2\fs18\cf1\lang1033\langfe1031\langfenp1031\insrsid7483127\charrsid14119459 {\*\bkmkend GetDDSInfo} }{\rtlch\fcs1 \af1 \ltrch\fcs0 \b\f37\insrsid7483127\charrsid15413752 \par }{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7483127 DDSInfo * info}{\rtlch\fcs1 \af2\afs18 \ltrch\fcs0 \f2\fs18\cf1\insrsid7483127\charrsid11946565 \cell }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\insrsid7483127 \cell }\pard\plain \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid7483127 \trowd \irow0\irowband0\lastrow \ltrrow\ts18\trgaph108\trleft-108\trftsWidth1\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid7483127\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 @@ -2856,8 +3033,8 @@ A played card is not held by the right player.}{\rtlch\fcs1 \ab\af1\afs22 \ltrch \clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth5185\clshdrawnil \cellx9438\row \ltrrow}\pard\plain \ltrpar \s1\qc \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel0\rin0\lin0\pararsid14119459 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid3937665 -103\cell }\pard \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel0\rin0\lin0\pararsid14119459 {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid3937665 RETURN_THREAD_WAIT\cell -}\pard \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel0\rin0\lin0\pararsid5862788 {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5862788 Returned from multi-threading -functions when something went wrong while waiting for all threads to complete.}{\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5862788\charrsid5862788 \cell }\pard\plain \ltrpar +}\pard \ltrpar\s1\ql \li0\ri0\keepn\nowidctlpar\intbl\wrapdefault\faauto\outlinelevel0\rin0\lin0\pararsid5862788 {\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5862788 Returned from multi-threading functions +when something went wrong while waiting for all threads to complete.}{\rtlch\fcs1 \ab\af1\afs22 \ltrch\fcs0 \f37\fs22\cf1\insrsid5862788\charrsid5862788 \cell }\pard\plain \ltrpar \ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af1\afs24\alang1025 \ltrch\fcs0 \f1\fs24\lang1033\langfe1053\cgrid\langnp1033\langfenp1053 {\rtlch\fcs1 \af1 \ltrch\fcs0 \insrsid3937665\charrsid14119459 \trowd \irow23\irowband23\ltrrow\ts11\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid5054625\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 @@ -2953,7 +3130,9 @@ Extended maximum number of tables when calling CalcAllTables}{\rtlch\fcs1 \af1 \ \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16720464 \par Rev Y, 2016-01-01\tab Update to v2.8.3. \par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 -\par Rez Z, 2016-03-20\tab Update to v2.8.4.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455\charrsid16724586 +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16264811 Rev}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid11030455 Z, 2016-03-20\tab Update to v2.8.4. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16264811 +\par Rev AA, 2018-04-01\tab Update to v.2.9.0.}{\rtlch\fcs1 \af1 \ltrch\fcs0 \f37\cf1\insrsid16264811\charrsid16724586 \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 @@ -3072,18 +3251,18 @@ fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e500000000000000000000000010ba -4ba28882d1010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff02000000000000000000000000000000000000000000000000934ba28882d101 -10ba4ba28882d101000000000000000000000000310033004b004e00c00041004a004a0044004500ce004300c600d800cd0041004800c800c6003000df0041003d003d000000000000000000000000000000000032000101ffffffffffffffff03000000000000000000000000000000000000000000000000934ba28882 -d10110ba4ba28882d1010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000 +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e5000000000000000000000000e0bf +fcaab9c9d3010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff020000000000000000000000000000000000000000000000e0bffcaab9c9d301 +e0bffcaab9c9d301000000000000000000000000d100c700460045004c00cc004900c200c1004500ce0046003400cb0041004a00cc00470056004600570051003d003d000000000000000000000000000000000032000101ffffffffffffffff030000000000000000000000000000000000000000000000e0bffcaab9c9 +d301e0bffcaab9c9d3010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000 00000000000000000000000000000000fc00000000000000010000000200000003000000feffffff0500000006000000070000000800000009000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c623a536f75726365732053656c65637465645374796c653d225c415041536978746845646974696f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d22362220786d6c6e733a 623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e74 -2f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b38303844 -443236442d343930322d344230432d383239422d3842343031453839394146437d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c +2f323030362f6269626c696f677261706879223e3c2f623a536f75726365733e000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b32453434 +373143362d323243322d344238342d383537412d4230303942303635343535397d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c 64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000 0000000000000000000000000000000000000000000000000000000000000400000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000 diff --git a/doc/dll-description.html b/doc/dll-description.html index 25b64059..7fb9ac01 100644 --- a/doc/dll-description.html +++ b/doc/dll-description.html @@ -878,10 +878,10 @@

Functions

CalcAllTablesPBN is just like CalcAllTables, except for the input format.

-

CallAllTables calculates the double dummy values of the denomination/declarer hand combinations in “*dealsp” 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 results are returned in “*resp” which must be defined before CalcAllTables is called.

+

CalcAllTables calculates the double dummy values of the denomination/declarer hand combinations in “*dealsp” 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 results are returned in “*resp” which must be defined before CalcAllTables is called.

The “mode” parameter contains the vulnerability (Vulnerable encoding; not to be confused with the SolveBoard mode) for use in the par calculation. It is set to -1 if no par calculation is to be performed.

There are 5 possible denominations or strains (the four trump suits and no trump). The parameter “trumpFilter” describes which, if any, of the 5 possibilities that will be excluded from the calculations. They are defined in Suit encoding order, so setting trumpFilter to {FALSE, FALSE, TRUE, TRUE, TRUE} means that values will only be calculated for the trump suits spades and hearts.

-

The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table:

+

The maximum number of DD tables in a CalcAllTables call depends on the number of strains required, see the following table:

diff --git a/doc/dll-description.md b/doc/dll-description.md index 1e5d01ad..9d532745 100644 --- a/doc/dll-description.md +++ b/doc/dll-description.md @@ -908,13 +908,13 @@ CalcDDtable solves a single deal “ tableDeal ” and returns the doubl CalcAllTablesPBN is just like CalcAllTables, except for the input format. -CallAllTables calculates the double dummy values of the denomination/declarer hand combinations in “\*dealsp” 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 results are returned in “\*resp” which must be defined before CalcAllTables is called. +CalcAllTables calculates the double dummy values of the denomination/declarer hand combinations in “\*dealsp” 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 results are returned in “\*resp” which must be defined before CalcAllTables is called. The “mode” parameter contains the vulnerability (Vulnerable encoding; not to be confused with the SolveBoard mode) for use in the par calculation. It is set to -1 if no par calculation is to be performed. There are 5 possible denominations or strains (the four trump suits and no trump). The parameter “trumpFilter” describes which, if any, of the 5 possibilities that will be excluded from the calculations. They are defined in Suit encoding order, so setting trumpFilter to {FALSE, FALSE, TRUE, TRUE, TRUE} means that values will only be calculated for the trump suits spades and hearts. -The maximum number of DD tables in a CallAllTables call depends on the number of strains required, see the following table: +The maximum number of DD tables in a CalcAllTables call depends on the number of strains required, see the following table:
diff --git a/examples/hands.cpp b/examples/hands.cpp index 05dfe054..db05409b 100644 --- a/examples/hands.cpp +++ b/examples/hands.cpp @@ -85,11 +85,11 @@ char PBN[3][80] = { // third index is hand. unsigned int holdings[3][4][4] = { - { + { // North East South West { RQ|RJ|R6, R8|R7|R3, RK|R5, RA|RT|R9|R4|R2 } , // spades { RK|R6|R5|R2, RJ|R9|R7, RT|R8|R3, RA|RQ|R4 } , // hearts { RJ|R8|R5, RA|RT|R7|R6|R4, RK|RQ|R9, R3|R2 } , // diamonds - { RT|R9|R8, RQ|R4, RA|R7|R6|R5|R2, RK|RJ|R3 }}, // clubs, + { RT|R9|R8, RQ|R4, RA|R7|R6|R5|R2, RK|RJ|R3 }}, // clubs { { RA|RK|R9|R6, RQ|RJ|RT|R5|R4|R3|R2, 0, R8|R7}, { RK|RQ|R8, RT, RJ|R9|R7|R5|R4|R3, RA|R6|R2 }, diff --git a/hands/README b/hands/README index 15329d40..61e18c9f 100644 --- a/hands/README +++ b/hands/README @@ -26,6 +26,7 @@ list1000.txt list300.txt list100.txt list10.txt +list2.txt list1.txt ------------- These are just excerpts from the larger masterDD.txt file. @@ -42,3 +43,8 @@ thomas2.txt These are artificially constructed hands that take a very long time to solve. +sol100000.txt +sol10.txt +------------- +These are hands with CalcTable solutions. I think they came from +an original DDS test program. diff --git a/hands/list1000.txt b/hands/list1000.txt index bc074b5f..a8c36a98 100644 --- a/hands/list1000.txt +++ b/hands/list1000.txt @@ -5360,7 +5360,7 @@ TABLE 6 7 6 7 11 2 11 2 5 7 5 7 10 2 10 2 6 6 6 6 PAR "NS 450" "EW -450" "NS:NS 45H" "EW:NS 45H" PAR2 "450" "4H-NS+1" PLAY 51 "DQDADTDJSKSAD8S5DKH2D5D2C2C9CKC4SQS2C5S3HJHAH3H6D9H5H8D4S6S4STH4HKH9H7D3HTHQS7D6S9S8SJC6D7C8CTC7C3CACJ" -TRACE 48 11 11 11 11 11 11 11 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 6 6 6 7 7 7 7 7 7 7 7 +TRACE 49 11 11 11 11 11 11 11 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 6 6 6 7 7 7 7 7 7 7 7 7 PBN 3 0 0 3 "W:AJT2.A.KT9763.43 .KT5432.J8.A8652 9653.Q986.Q5.JT9 KQ874.J7.A42.KQ7" FUT 9 2 2 2 2 1 3 0 0 0 3 7 10 13 14 4 2 11 14 0 64 512 0 0 8 0 1024 0 7 7 7 7 7 7 6 6 5 TABLE 6 7 6 7 11 2 11 2 5 7 5 7 10 2 10 2 6 6 6 6 diff --git a/hands/list2.txt b/hands/list2.txt new file mode 100644 index 00000000..55ed58da --- /dev/null +++ b/hands/list2.txt @@ -0,0 +1,15 @@ +NUMBER 2 +PBN 0 0 0 0 "N:QJ6.K652.J85.T98 873.J97.AT764.Q4 K5.T83.KQ9.A7652 AT942.AQ4.32.KJ3" +FUT 9 2 2 2 3 0 0 1 1 1 5 8 11 10 6 12 2 6 13 0 0 0 768 0 2048 0 32 0 5 5 5 5 5 5 4 4 4 +TABLE 5 8 5 8 6 6 6 6 5 7 5 7 7 5 7 5 6 6 6 6 +PAR "NS -110" "EW 110" "NS:EW 2S" "EW:EW 2S" +PAR2 "-110" "2S-EW" +PLAY 45 "CTC4CACJH8H4HKH9D5DAD9D2S7S5S2SQD8D4DQD3H3HAH6H7C3C8CQC2S3SKSAS6HQH5HJHTCKC9D6C5S4SJS8C6DJ" +TRACE 46 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +PBN 1 2 4 1 "E:QJT5432.T.6.QJ82 .J97543.K7532.94 87.A62.QJT4.AT75 AK96.KQ8.A98.K63" +FUT 7 3 3 3 1 2 0 0 2 8 12 10 6 12 5 0 0 2048 0 0 3072 28 4 4 4 3 3 3 2 +TABLE 4 9 4 9 10 2 10 2 8 3 8 3 6 7 6 7 9 3 9 3 +PAR "NS 100" "EW -100" "NS:EW 4Sx" "EW:EW 4Sx" +PAR2 "100" "4S*-EW-1" +PLAY 52 "SQD2S8SAHKHTH3H2HQS2H4H6H8D6HJHAS7SKS4C4D8C2DKD4H9C5S6S3H7C7C3S5H5CTD9STD3DQDAC8S9SJC9DTCQD5CAC6DJCKCJD7" +TRACE 49 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 diff --git a/hands/masterDD.txt b/hands/masterDD.txt index ace89d9d..d7ac3479 100644 --- a/hands/masterDD.txt +++ b/hands/masterDD.txt @@ -5360,7 +5360,7 @@ TABLE 6 7 6 7 11 2 11 2 5 7 5 7 10 2 10 2 6 6 6 6 PAR "NS 450" "EW -450" "NS:NS 45H" "EW:NS 45H" PAR2 "450" "4H-NS+1" PLAY 51 "DQDADTDJSKSAD8S5DKH2D5D2C2C9CKC4SQS2C5S3HJHAH3H6D9H5H8D4S6S4STH4HKH9H7D3HTHQS7D6S9S8SJC6D7C8CTC7C3CACJ" -TRACE 48 11 11 11 11 11 11 11 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 6 6 6 7 7 7 7 7 7 7 7 +TRACE 49 11 11 11 11 11 11 11 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 6 6 6 7 7 7 7 7 7 7 7 7 PBN 3 0 0 3 "W:AJT2.A.KT9763.43 .KT5432.J8.A8652 9653.Q986.Q5.JT9 KQ874.J7.A42.KQ7" FUT 9 2 2 2 2 1 3 0 0 0 3 7 10 13 14 4 2 11 14 0 64 512 0 0 8 0 1024 0 7 7 7 7 7 7 6 6 5 TABLE 6 7 6 7 11 2 11 2 5 7 5 7 10 2 10 2 6 6 6 6 @@ -8146,7 +8146,7 @@ TABLE 9 4 9 4 8 5 8 5 9 4 9 4 7 6 7 6 9 4 9 4 PAR "NS 600" "EW -600" "NS:NS 3N" "EW:NS 3N" PAR2 "600" "3N-NS" PLAY 49 "HQH3H5H4HJH6H8H2HAHKHTH9H7C2C8C5CTC3C4CASAS3S4S5SQS7S6S2S8S9SJC7SKCKC9STDKD7D2D3D6D9DAD5D4DQD8DJC6" -TRACE 46 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +TRACE 49 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 PBN 1 2 4 3 "E:52.T85.J97.KQ874 AQ8.942.AT42.A95 T973.AQJ7.Q53.T6 KJ64.K63.K86.J32" FUT 11 3 3 1 0 0 2 2 0 1 1 2 6 10 14 3 10 3 5 7 7 12 12 0 0 0 0 512 0 0 0 0 2048 0 4 4 4 4 4 4 4 4 4 4 3 TABLE 9 4 9 4 8 5 8 5 9 4 9 4 7 6 7 6 9 4 9 4 @@ -8538,7 +8538,7 @@ TABLE 9 4 9 4 9 4 9 4 7 6 7 6 5 8 5 8 6 5 7 5 PAR "NS 140" "EW -140" "NS:NS 3S,NS 3H" "EW:NS 3S,NS 3H" PAR2 "140" "3S-NS" "3H-NS" PLAY 50 "DTDAD5D7S9S2S5STD4DKD9C4S7C3SAS4H2H9HQHADQS6D8D2C6C2CAC9HTH3H4SQSKS3CTS8DJD3H7SJHKC5H6H8HJC7C8CJH5CK" -TRACE 47 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 2 0 0 3 "S:AJ865.KJ542.7.64 KQT4.9.JT84.K752 973.QT6.AK632.A8 2.A873.Q95.QJT93" FUT 11 3 3 3 3 1 2 2 2 0 0 0 2 5 7 13 9 4 8 11 13 4 10 0 0 0 0 0 0 0 1024 4096 0 0 4 4 4 4 4 4 4 4 4 3 3 TABLE 9 4 9 4 9 4 9 4 7 6 7 6 5 8 5 8 6 5 7 5 @@ -9266,7 +9266,7 @@ TABLE 5 7 5 7 2 11 2 11 5 8 5 8 6 7 6 7 4 8 4 8 PAR "NS -650" "EW 650" "NS:EW 45H" "EW:EW 45H" PAR2 "-650" "4H-EW+1" PLAY 49 "DTD3DKD2H5HKH9H6S4S3SKS6S8STSJS2CTCKC4C5DAD4H3D5HQHTH4HAC3C2C9CAHJS9S5D7H8C6D6S7H7CQD9SQH2D8SAC7C8" -TRACE 46 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +TRACE 49 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 PBN 2 3 4 2 "S:KQ87.T6.743.J974 T6.J875432.K.A85 J94.AK.J852.QT63 A532.Q9.AQT96.K2" FUT 10 0 3 3 3 3 0 1 1 2 2 13 4 7 9 11 8 6 10 7 4 4096 0 0 0 0 128 0 0 0 8 5 5 5 5 5 5 4 4 4 4 TABLE 5 7 5 7 2 11 2 11 5 8 5 8 6 7 6 7 4 8 4 8 @@ -9896,7 +9896,7 @@ TABLE 4 9 4 9 6 7 6 6 4 8 4 8 6 6 6 6 4 9 4 9 PAR "NS -400" "EW 400" "NS:EW 3N" "EW:EW 3N" PAR2 "-400" "3N-EW" PLAY 50 "HAH5HQH2HKH6H4H3H7HTHJH8C3CAC4C6S3S2SAS5SJS6S8S4D2D3DQD5SKS7C7C2SQSTD6C5S9H9C8C9D8DTDAD4DKDJCTCJD7D9" -TRACE 47 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 0 0 4 2 "N:65.QJ4.J943.9532 KQ983.832.Q8.AQT T742.AK97.T5.KJ4 AJ.T65.AK762.876" FUT 12 1 1 1 2 2 0 0 0 0 3 3 3 7 9 14 5 10 2 4 7 10 4 11 13 0 0 8192 0 0 0 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 3 3 3 TABLE 4 9 4 9 6 7 6 6 4 8 4 8 6 6 6 6 4 9 4 9 @@ -22181,7 +22181,7 @@ TABLE 7 6 7 6 4 9 4 9 9 4 9 4 3 9 3 9 4 8 4 8 PAR "NS -140" "EW 140" "NS:EW 3H" "EW:EW 3H" PAR2 "-140" "3H-EW" PLAY 49 "H2H4HAH6H3S4H8H7D3DQDAD4S7S2SJSQHKH9H5S8SAS3HTS5SKS6D5D7STS9D6C3D2C7DJDKHQD8C6D9HJDTC8C4C2C5CACJCT" -TRACE 46 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +TRACE 49 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 PBN 3 0 4 0 "W:KQ2.864.K3.AJ972 AT86.A97532.62.T 43.KQJT.QJT9.K86 J975..A8754.Q543" FUT 12 0 0 0 2 2 1 3 0 1 1 1 1 6 8 10 2 6 14 10 14 3 5 7 9 0 0 0 0 0 0 0 0 4 0 0 0 5 5 5 4 4 4 4 3 3 3 3 3 TABLE 6 5 6 5 6 6 6 6 6 7 6 7 4 9 4 8 4 8 4 8 @@ -22524,7 +22524,7 @@ TABLE 4 9 4 9 7 6 7 6 6 7 6 7 8 4 8 4 4 8 4 7 PAR "NS -140" "EW 140" "NS:EW 23S" "EW:EW 23S" PAR2 "-140" "2S-EW+1" PLAY 49 "D8D9DJDAH4H6HJHKDKD3C3D4D2S9C2D5H5HTHAH7S8SQSKS4C6C9CKCAD6SJC4D7S5S2STS7C7C5C8CQH9H3H2HQCTS6DTCJH8" -TRACE 46 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 0 2 4 3 "N:642.T986.8.Q9432 T83.AJ3.T9754.K7 Q7.K72.KQJ62.AJ5 AKJ95.Q54.A3.T86" FUT 11 0 1 1 2 2 0 3 0 3 3 0 14 5 12 14 3 5 6 9 8 10 11 8192 16 0 0 0 0 0 0 0 0 0 9 9 9 8 8 7 7 7 7 7 7 TABLE 4 9 4 9 7 6 7 6 6 7 6 7 8 4 8 4 4 8 4 7 @@ -25989,7 +25989,7 @@ TABLE 10 2 11 2 7 6 7 6 9 4 9 3 6 7 6 7 7 4 7 4 PAR "NS 450" "EW -450" "NS:S 45S" "EW:S 45S" PAR2 "450" "4S-S+1" PLAY 49 "H8HTHQS5S6S2SQSJHKHAS7H5S8S3SASTH2H6S9C3SKS4C2D4D2DAD9D6C6CAC5C4DQC9D3D7HJH7D5C8DKCTD8DTH3H9C7CKCJ" -TRACE 46 11 11 11 11 11 11 11 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 +TRACE 49 11 11 11 11 11 11 11 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 PBN 0 3 1 2 "N:KQJ94..J4.AQJ974 7.QJT85.Q7632.K3 652.43.KT98.T862 AT83.AK9762.A5.5" FUT 9 0 0 3 3 3 3 1 2 2 2 6 2 6 8 10 4 10 13 0 32 0 0 0 0 8 768 0 1 1 1 1 1 1 1 0 0 TABLE 8 5 8 5 1 12 1 11 4 8 4 9 9 3 9 3 4 8 4 9 @@ -30630,7 +30630,7 @@ TABLE 10 3 10 3 11 2 11 2 12 1 12 1 11 2 11 2 12 1 12 1 PAR "NS 1440" "EW -1440" "NS:NS 6N" "EW:NS 6N" PAR2 "1440" "6N-NS" PLAY 49 "D9D2D6DKS3S5SAS2HJHTHAH2SKS6C2C6CAC4C3C7CTC9C5CJH5H3H4HQD5DTDQD4D3D8DADJD7H6H8S7C8CKS4S8H7S9SJHKCQ" -TRACE 46 12 12 12 12 12 12 12 12 12 12 12 12 12 11 11 11 12 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 +TRACE 49 12 12 12 12 12 12 12 12 12 12 12 12 12 11 11 11 12 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 PBN 1 0 1 3 "E:AQ73.Q4.JT4.8763 K54.K7652.K5.KT9 T9862.A8.Q93.J42 J.JT93.A8762.AQ5" FUT 11 0 0 0 3 3 3 2 1 2 2 1 2 6 10 2 4 11 3 14 9 12 8 0 0 768 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 TABLE 8 5 8 5 11 2 11 2 10 3 10 3 9 4 9 4 8 3 8 3 @@ -32625,7 +32625,7 @@ TABLE 6 6 6 6 5 7 5 7 4 8 4 8 6 7 6 7 6 7 5 7 PAR "NS -90" "EW 90" "NS:EW 1N,EW 12D" "EW:EW 1N,EW 12D" PAR2 "-90" "1D-EW+1" "1N-EW" PLAY 51 "H2HAH4H3CQC6C5CAC3CKC9S2H5H7HKD9SAS3STS6C4C8H8S8SKSQH6S4DAD6D3DKD2D7DTS9HQC7H9HTD5CJC2D8DQD4S5S7HJDJSJ" -TRACE 48 8 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 8 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 0 2 0 2 "N:AJ65.T94.Q842.Q8 KQ973.53.AK73.T2 42.AJ87.T95.AKJ3 T8.KQ62.J6.97654" FUT 10 3 0 0 3 2 1 3 1 1 2 14 2 4 3 10 8 11 11 14 5 8192 0 0 0 512 128 0 0 0 0 6 6 6 6 6 6 6 6 5 5 TABLE 6 7 6 7 7 6 7 6 7 6 6 6 6 6 6 6 7 5 6 6 @@ -32849,7 +32849,7 @@ TABLE 9 4 9 4 5 8 5 8 7 6 7 6 6 7 6 7 6 6 6 6 PAR "NS 140" "EW -140" "NS:NS 23S" "EW:NS 23S" PAR2 "140" "2S-NS+1" PLAY 49 "SKS6S7S2CAC3CTC4C5C6HTC2SJSASQS9HAH4H3H7HKH8H9HQS5D2HJS3CKS4D3C7CJS8H2C8H5D6D7STD4D8DJDQD5DTDADKCQ" -TRACE 46 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 +TRACE 49 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 PBN 2 3 0 3 "S:JT8743.QT7.Q95.T A52.AK652.T43.42 KQ.84.A862.AQ875 96.J93.KJ7.KJ963" FUT 10 3 1 3 2 2 0 1 1 0 0 2 14 4 4 10 14 2 6 2 5 0 8192 0 8 0 0 0 32 0 0 4 4 4 4 4 4 4 4 4 4 TABLE 9 4 9 4 5 8 5 8 7 6 7 6 6 7 6 7 6 6 6 6 @@ -34543,7 +34543,7 @@ TABLE 9 4 9 4 8 4 8 4 7 6 7 6 7 6 7 6 8 4 8 4 PAR "NS 140" "EW -140" "NS:NS 123S" "EW:NS 123S" PAR2 "140" "1S-NS+2" PLAY 49 "C5C3CAC8C6CJCKC4CTD6S5CQSAS2S3S6SKS4S7S9DAD8D9D2H2H5HKH3STD7D3S8SJD4D5C2SQH6C7C9H4HJHAH8HTHQH9DTDQ" -TRACE 46 8 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 8 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 1 3 4 3 "E:965.J63.KT742.A6 AK.AT72.A53.QJ87 842.Q85.Q8.KT952 QJT73.K94.J96.43" FUT 12 2 2 3 3 3 0 0 0 1 3 1 1 8 12 2 5 10 2 4 8 12 13 5 8 0 0 0 0 512 0 0 0 0 0 0 0 5 5 4 4 4 4 4 4 4 3 3 3 TABLE 9 4 9 4 8 4 8 4 7 6 7 6 7 6 7 6 8 4 8 4 @@ -35649,7 +35649,7 @@ TABLE 5 7 5 8 0 12 0 12 3 9 2 9 5 8 5 8 3 9 3 10 PAR "NS -1430" "EW 1430" "NS:EW 6H" "EW:EW 6H" PAR2 "-1430" "6H-EW" PLAY 49 "SQS3S6SKC2C5H7C7SAS2D6S4D2D8H2D5C3C6H8C9D3D4H4DJCKCAHJCTHKH3H5HTS5S7HASTHQSJD7H9CQC8S9DTC4CJDQD9DA" -TRACE 46 12 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +TRACE 49 12 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 PBN 1 1 4 2 "E:J9.K654.Q84.QJ96 Q3.A83.A632.KT82 AK74.J97.JT.A753 T8652.QT2.K975.4" FUT 12 0 2 2 2 0 3 1 3 3 1 1 3 12 3 6 14 3 2 14 8 10 3 8 13 0 4 0 0 0 0 0 0 0 0 0 0 7 6 6 6 6 6 6 6 6 6 6 5 TABLE 7 6 7 6 6 7 6 7 8 5 8 5 6 7 6 7 6 6 6 6 @@ -40682,7 +40682,7 @@ TABLE 9 4 9 4 11 2 11 2 7 5 8 5 8 4 9 4 10 2 11 2 PAR "NS 660" "EW -660" "NS:S 345N" "EW:S 345N" PAR2 "660" "3N-S+2" PLAY 49 "D7D9DTDAHAH7H5D2H3HJHKD6DJDQDKD5D3C2H6D4H9S3H4HQCTCAC3C4CKC7C5C9C6C8H8S2HTH2CJD8S6S5SAS4S7SKS8S9CQ" -TRACE 46 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 10 11 11 11 10 11 11 11 11 11 11 11 11 11 11 11 10 10 10 10 10 10 10 10 10 10 10 10 10 +TRACE 49 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 10 11 11 11 10 11 11 11 11 11 11 11 11 11 11 11 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 PBN 2 2 1 3 "S:AT7.K965.J9.AKJ6 K43..QT8642.Q873 J86.AT843.AK3.54 Q952.QJ72.75.T92" FUT 11 2 2 2 2 2 2 0 0 3 3 3 2 4 6 8 10 12 4 13 3 8 12 0 0 0 0 0 0 8 0 0 128 0 2 2 2 2 2 2 2 2 2 2 2 TABLE 9 4 9 4 11 2 11 2 7 5 8 5 8 4 9 4 10 2 11 2 @@ -46184,7 +46184,7 @@ TABLE 9 4 9 3 5 7 5 7 8 4 8 4 10 2 10 2 8 5 8 4 PAR "NS 140" "EW -140" "NS:NS 123S" "EW:NS 123S" PAR2 "140" "1S-NS+2" PLAY 51 "D6D7DQDKSKS7S2S3SJS5S4S8H2H6S6H3SAH4C4STCJCQCAC5CTC7C3C2C8D3C6CKD4D5DTD2HQD8H5HKDJDAD9H7HASQH8H9C9HTHJ" -TRACE 48 9 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 9 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 2 1 1 2 "S:AJ82.T.AT3.T9653 953.Q752.Q8.KJ87 KT6.A98.KJ654.Q2 Q74.KJ643.972.A4" FUT 11 2 2 0 2 0 3 3 3 1 0 0 3 10 2 14 8 3 6 10 10 11 14 0 0 0 0 0 0 32 512 0 0 0 6 6 6 6 6 6 6 6 6 5 5 TABLE 10 3 10 3 6 7 6 7 11 2 11 2 9 4 9 4 10 3 10 3 @@ -54094,7 +54094,7 @@ TABLE 5 7 5 7 9 4 9 4 3 10 3 10 9 4 9 4 5 8 5 8 PAR "NS -100" "EW 100" "NS:NS 4Hx" "EW:NS 4Hx" PAR2 "-100" "4H*-NS-1" PLAY 49 "DAD8DTD4DKDQD6H2H6H3HJHAC8C3CAC2C6C7C4CQH7H4HQD7H9D2HTH5S3S6SJS5CJD5CTC5C9D9CKD3S4S2SAS7S8S9SQSKDJ" -TRACE 46 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 1 2 0 0 "E:K872.KQ62.AJ8.T6 QT43.A874.QT763. AJ96.5.K2.KJ9432 5.JT93.954.AQ875" FUT 9 1 1 3 2 2 3 0 3 3 3 11 14 5 9 8 5 5 12 0 1536 0 16 0 128 0 0 0 4 4 4 4 4 4 4 3 3 TABLE 4 9 4 9 7 6 7 6 6 7 6 7 4 9 4 9 5 8 5 7 @@ -55256,7 +55256,7 @@ TABLE 6 7 6 7 4 9 4 9 7 6 7 6 5 8 5 8 6 7 6 7 PAR "NS -140" "EW 140" "NS:EW 123H" "EW:EW 123H" PAR2 "-140" "1H-EW+2" PLAY 49 "DKD6D2DAHJHQHKHADQDTD9D7D3H5DJD8HTH7H3H2C3C7C9CQS3S2S9SJS4S6SKS5SASTS8S7CKC8C2C4C5CTCAD4H8D5H4H9CJ" -TRACE 46 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 0 0 0 0 "N:K95.Q3.Q74.AJT65 7.J976.AT632.K43 Q4.T842.KJ95.872 AJT8632.AK5.8.Q9" FUT 11 2 2 2 3 3 3 0 1 0 0 1 4 7 12 14 6 11 5 3 9 13 12 0 0 0 0 32 1024 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 TABLE 2 11 2 11 5 8 5 8 5 7 5 7 5 6 5 6 3 8 5 8 @@ -63201,7 +63201,7 @@ TABLE 11 2 11 2 12 0 13 0 8 5 8 5 12 1 12 1 11 2 11 2 PAR "NS 1510" "EW -1510" "NS:S 7H" "EW:S 7H" PAR2 "1510" "7H-S" PLAY 49 "DAD6D2HTHKH8H3H2HQD7H4H5HJD3H6H7CJC6CQC4HAH9S2C8DKD4S6D5DQD9S7D8S4S5SAS3SKSTDTS9CASJC2C5CKDJC3C7S8" -TRACE 46 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +TRACE 49 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 PBN 2 3 1 3 "S:AK8762.KQJT..AKJ QJT3.8.AJ8753.86 4.A643.KQT6.QT32 95.9752.942.9754" FUT 10 0 3 3 0 1 2 2 2 2 2 3 6 8 12 8 14 3 5 8 11 0 0 0 3072 0 0 0 0 128 0 0 0 0 0 0 0 0 0 0 0 TABLE 11 2 11 2 12 0 13 0 8 5 8 5 12 1 12 1 11 2 11 2 @@ -155510,7 +155510,7 @@ TABLE 6 7 6 7 7 6 7 6 5 8 5 8 6 7 6 7 5 8 5 8 PAR "NS -120" "EW 120" "NS:EW 12N" "EW:EW 12N" PAR2 "-120" "1N-EW+1" PLAY 49 "S2S5STSKDADJD2D3D6H3D4DTC6CJCQCKD7DQDKH4S6SJSAD5S7H2S8SQCTC3C4C7C9C2C5H7H5HAH9H8D8HJD9H6S9S3C8CAHQ" -TRACE 46 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 1 2 4 2 "E:K986.Q87.AK96.J7 QJ432.6543.J.QT9 A75.AT.8742.K832 T.KJ92.QT53.A654" FUT 6 1 3 0 0 2 3 6 12 12 4 11 10 56 0 2048 12 0 512 5 5 5 5 5 4 TABLE 6 7 6 7 7 6 7 6 5 8 5 8 6 7 6 7 5 8 5 8 @@ -232657,7 +232657,7 @@ TABLE 7 6 7 6 8 5 8 5 7 6 7 6 8 5 8 5 7 6 7 6 PAR "NS 110" "EW -110" "NS:NS 12H" "EW:NS 12H" PAR2 "110" "1H-NS+1" PLAY 49 "S5SKS3S6CKC4C2C6C7C5CJCQDQD2D5DKCAC8S2D6CTC9D3D8C3H2H3DTS9STD4SJHQHKHAH8SAD9S7S4H7H9HJH4SQS8D7DADJ" -TRACE 46 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 +TRACE 49 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 PBN 0 2 1 2 "N:543.T9.9632.AJ86 A2.QJ752.QT84.74 QJ87.A8.J7.KQT52 KT96.K643.AK5.93" FUT 10 3 3 3 3 1 2 2 1 0 0 2 5 10 13 14 7 11 8 8 12 0 0 0 4096 0 0 0 0 128 2048 3 3 3 3 3 3 3 3 2 2 TABLE 5 7 5 7 3 10 3 10 3 9 3 9 7 5 7 5 6 7 6 7 @@ -254700,7 +254700,7 @@ TABLE 6 7 6 7 6 6 6 6 3 10 3 10 4 8 4 9 5 7 6 7 PAR "NS -130" "EW 130" "NS:EW 1234D" "EW:EW 1234D" PAR2 "-130" "1D-EW+3" PLAY 49 "H5HAH8H4D3D6D7DJC3C2CTCADKD5D8D2DAH3DTDQD4H7C4HTD9S6S3S2C8CQC5C6CKC9C7H2HKS4H9HJH6CJS7HQS8STSKSAS9" -TRACE 46 7 7 7 7 7 7 7 7 7 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +TRACE 49 7 7 7 7 7 7 7 7 7 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 PBN 0 2 1 1 "N:T62.KQ972.Q.QT85 Q73.A4.KJ963.AK9 KJ98.T863.AT.J62 A54.J5.87542.743" FUT 12 2 2 2 2 2 0 0 3 0 1 3 1 3 6 9 11 13 3 7 14 12 14 9 4 0 0 0 0 0 0 0 8192 0 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 TABLE 8 5 8 5 9 4 9 4 5 8 5 8 7 6 7 6 5 8 5 8 @@ -268175,7 +268175,7 @@ TABLE 6 7 6 7 6 7 6 7 5 7 5 7 3 10 3 10 4 8 4 8 PAR "NS -130" "EW 130" "NS:EW 1234C" "EW:EW 1234C" PAR2 "-130" "1C-EW+3" PLAY 49 "C5C7CKC2CAC3C4CTC8CJCQS2C9D4D5H2C6S3D2H4SKSAS7S8DQDAD3D7S5SQS4S6DKD6D8D9DJH6H5H8DTH3S9STHAHJH9HTH7" -TRACE 46 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +TRACE 49 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 PBN 2 1 0 1 "S:Q8.A742.KJT3.J32 KJ4.J63.76.Q9654 A9632.Q95.Q84.T7 T75.KT8.A952.AK8" FUT 12 3 2 3 0 2 0 2 2 1 1 1 0 14 14 8 5 2 7 5 9 8 10 13 10 8192 0 0 0 0 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 6 6 6 6 TABLE 6 7 6 7 6 7 6 7 5 7 5 7 3 10 3 10 4 8 4 8 @@ -268945,7 +268945,7 @@ TABLE 8 5 8 5 7 6 7 6 2 11 2 10 1 12 1 12 1 9 1 9 PAR "NS -920" "EW 920" "NS:EW 6C" "EW:EW 6C" PAR2 "-920" "6C-EW" PLAY 49 "S4S3SKSAD3D6DQDASTSJSQD2H7H4HKHAHQH2D5H3C2S2CAC6CKC4C8H5CQC5CJS6CTC7H9H6C9S5H8HTC3HJS8D4D8D7DKDJDT" -TRACE 46 9 9 9 9 9 8 8 8 8 8 8 8 8 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 +TRACE 49 9 9 9 9 9 8 8 8 8 8 8 8 8 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 PBN 1 2 4 2 "E:AJ8.AQ98.KT3.J82 Q9642.T7652.J64. 3.4.Q9852.AKQT93 KT75.KJ3.A7.7654" FUT 11 0 0 0 0 0 1 1 2 1 2 2 2 4 6 9 12 2 7 4 10 6 11 0 0 0 0 0 0 96 0 0 0 0 4 4 4 2 2 1 1 1 1 1 1 TABLE 8 5 8 5 7 6 7 6 2 11 2 10 1 12 1 12 1 9 1 9 @@ -272774,7 +272774,7 @@ TABLE 7 6 7 6 7 5 7 5 6 5 6 5 10 3 10 3 7 6 7 6 PAR "NS 130" "EW -130" "NS:NS 1234C" "EW:NS 1234C" PAR2 "130" "1C-NS+3" PLAY 49 "HTHAH5H4CACJC6C4CTCKC8CQD7D2D3DAC2S8C7H3D4D6DJD5SQS9S4SADTDQH6D8C3H9C5S6SKS2SJH7C9S7S3H2HKH8D9S5HJ" -TRACE 46 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +TRACE 49 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 PBN 2 0 2 1 "S:A3.K43.QJ753.AQ8 842.Q765.AK6.972 JT975.J982..KT43 KQ6.AT.T9842.J65" FUT 9 1 1 2 2 2 0 0 3 3 14 10 2 4 10 13 6 6 11 0 0 0 0 768 4096 0 32 0 6 6 6 6 6 5 5 5 5 TABLE 10 3 10 3 8 4 8 4 7 6 7 5 9 3 9 4 7 6 7 6 @@ -283855,7 +283855,7 @@ TABLE 3 10 3 10 9 4 9 4 1 11 1 11 2 11 2 11 4 6 4 6 PAR "NS -420" "EW 420" "NS:EW 4S" "EW:EW 4S" PAR2 "-420" "4S-EW" PLAY 51 "H5H3HAH7H6S3HKH8S4S2SAS6SKS8S7S5C2C4CKC9C7C6CJS9HQSTHJD2SQD7D3SJC3C8CTH2CAH4D5CQC5H9D6D8DQD4DAD9DTDKDJ" -TRACE 48 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 +TRACE 49 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 PBN 1 3 4 2 "E:J62.AQ.AQT72.A32 KQ98.J962.5.J765 T74.KT87.J983.Q9 A53.543.K64.KT84" FUT 9 0 0 3 1 3 1 1 1 2 9 13 7 2 11 6 9 11 5 256 4096 96 0 0 0 0 0 0 5 5 5 5 5 5 5 4 4 TABLE 7 6 6 6 6 7 6 7 4 9 4 9 8 5 8 5 5 8 4 8 @@ -283869,7 +283869,7 @@ TABLE 7 6 6 6 6 7 6 7 4 9 4 9 8 5 8 5 5 8 4 8 PAR "NS -110" "EW 110" "NS:EW 3D" "EW:EW 3D" PAR2 "-110" "3D-EW" PLAY 51 "H6H7H5HQDAD5D3D4D2C7D8D6D9DKD7C5S5S6SQS4C6CQCKCADQS8DJH4DTH2S7S3HAH9H8H3C2CJC9C4SKSTSAS2CTC3S9HTC8SJHJ" -TRACE 48 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 +TRACE 49 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 PBN 2 1 1 2 "S:K76.T54.J6.JT852 9.AQ963.AQT432.9 AQJ853.2.K8.AK73 T42.KJ87.975.Q64" FUT 10 0 0 3 3 3 3 2 2 1 1 7 13 2 5 8 11 6 11 5 10 64 0 0 0 0 1024 0 0 16 0 3 3 3 3 3 3 3 3 3 3 TABLE 10 3 10 3 3 10 3 10 3 10 3 10 10 3 10 3 7 5 7 5 @@ -334283,7 +334283,7 @@ TABLE 3 8 3 9 3 9 3 10 6 5 6 7 6 4 6 7 3 8 3 10 PAR "NS -430" "EW 430" "NS:W 34N" "EW:W 34N" PAR2 "-430" "3N-W+1" PLAY 49 "DKD3C7D2DAD5C4D4DQD6C2DTD7DJH7H9H2HTHKH5H6H8HJHQD8C5C8H3SQS4S2S7HAC6C9CTS6S5SKSACAH4C3CQSJS9S3STS8" -TRACE 46 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 1 2 4 0 "E:Q983.KJ8.87.JT85 AK72.97632.JT.Q3 J54.QT5.AK952.A6 T6.A4.Q643.K9742" FUT 12 1 3 0 0 3 3 3 3 2 2 1 2 14 13 6 10 2 4 7 9 6 4 4 12 0 0 0 0 0 0 0 0 0 8 0 0 6 6 5 5 5 5 5 5 5 5 5 4 TABLE 5 8 5 8 6 7 6 7 6 7 6 7 7 6 7 6 5 7 5 7 @@ -341808,7 +341808,7 @@ TABLE 7 6 7 6 7 6 7 6 8 5 8 4 8 5 8 5 6 7 6 7 PAR "NS 90" "EW -90" "NS:NS 2D,NS 2C" "EW:NS 2D,NS 2C" PAR2 "90" "2D-NS" "2C-NS" PLAY 49 "S8SAS6H3S2S7C2STH4H7HQH2S3SJC3SKCAC4C7C6CKCJC8C9D4D3DKDTS4SQC5H5H8HAHJHTH6D2CTHKD9D5DAD7H9S5DQD8D6" -TRACE 46 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 2 2 1 0 "S:Q9862.52.J7.8763 J543.AKQ74.QT6.J AT.J6.K84.AQT952 K7.T983.A9532.K4" FUT 12 3 0 0 1 1 3 3 3 3 2 2 2 14 14 10 6 11 2 5 10 12 4 8 13 0 0 0 0 0 0 0 512 0 0 0 0 3 3 3 3 3 2 2 2 2 1 1 1 TABLE 6 7 6 7 3 10 3 10 3 10 3 10 8 5 8 5 3 8 3 8 @@ -378901,7 +378901,7 @@ TABLE 8 5 8 5 3 9 3 9 2 10 2 10 1 11 1 11 3 10 3 10 PAR "NS -500" "EW 500" "NS:NS 5Sx" "EW:NS 5Sx" PAR2 "-500" "5S*-NS-3" PLAY 49 "CKC2C6C8S4S3S6S9H4H8HKHAS2STSASQCAC4C7S5SKC3C5H3SJD5D3D7S8C9D4CQH5H7HJH6CTDTS7CJHQD2D6H9DQDAD8DKD9" -TRACE 46 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 9 9 PBN 1 1 3 1 "E:KQ982.J9.Q875.JT AT74..KJT962.A42 J65.KT7643.A4.63 3.AQ852.3.KQ9875" FUT 9 0 0 0 2 2 2 3 1 1 13 2 9 5 8 12 11 9 11 4096 0 256 0 128 0 1024 0 0 2 2 2 1 1 1 1 1 1 TABLE 7 5 7 5 8 5 8 5 9 3 9 3 11 1 11 1 9 4 9 4 @@ -452051,7 +452051,7 @@ TABLE 6 6 6 6 7 5 7 5 9 4 9 4 8 5 8 4 8 5 8 5 PAR "NS 120" "EW -120" "NS:NS 12N" "EW:NS 12N" PAR2 "120" "1N-NS+1" PLAY 49 "H4H9H5H7HAH3H6HJC5CQC4C7DKD2H2DADJD3D4H8D8DQD5HTS6D7S2S8SKSAC2S4S7C3STSQS3D6DTS5SJS9CTC8CJCACKHQC6" -TRACE 46 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 +TRACE 49 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 PBN 1 3 0 2 "E:J8652.A54.KJ73.K KT.962.T98542.43 Q943.KJ83.Q6.876 A7.QT7.A.AQJT952" FUT 9 3 2 2 2 1 1 1 0 0 4 2 5 10 2 6 9 10 13 8 0 16 768 0 0 0 0 0 5 5 5 5 5 5 5 4 4 TABLE 4 8 4 8 6 6 6 6 8 5 8 5 10 2 10 3 10 3 10 3 @@ -487884,7 +487884,7 @@ TABLE 11 2 11 2 9 3 9 3 13 0 13 0 7 5 7 5 11 2 11 2 PAR "NS 2140" "EW -2140" "NS:NS 7D" "EW:NS 7D" PAR2 "2140" "7D-NS" PLAY 49 "CTCACKS6H2H5H9HQC8C5CJD3S8S3SAS7H6H8HAH3H4HKDTH7D4D7DAD2DKD5D9C6DQD6C2C7DJD8C3C9HJS5C4HTS2S9STSQCQ" -TRACE 46 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +TRACE 49 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 10 10 PBN 0 2 3 0 "N:J862.AJ94.AKQJ3. 9543.KQ3.8652.T8 AKT.62.T94.A5432 Q7.T875.7.KQJ976" FUT 10 0 2 0 0 2 0 1 1 1 1 2 14 6 8 3 11 14 4 9 11 0 14336 0 0 0 0 0 0 0 0 8 8 8 8 8 7 7 7 7 6 TABLE 11 2 11 2 9 3 9 3 13 0 13 0 7 5 7 5 11 2 11 2 @@ -488024,7 +488024,7 @@ TABLE 10 2 10 2 11 2 11 2 12 1 12 1 8 5 8 5 9 3 9 3 PAR "NS 1370" "EW -1370" "NS:NS 6D" "EW:NS 6D" PAR2 "1370" "6D-NS" PLAY 49 "S5STS8S7D3D2DQD9H2H6HQHACKCQC2C3C4H5C9C6C5CACJH8SJS3SKS2SAS4SQS6DJD7D6D5D4D8DKH7DAC8DTS9H4H3HKH9HT" -TRACE 46 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 +TRACE 49 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 PBN 2 2 2 3 "S:AK7.KT852.QJT4.Q 9542.96.987.T952 QJT.Q4.AK63.A763 863.AJ73.52.KJ84" FUT 9 3 3 3 1 1 0 0 0 2 2 5 10 6 9 2 5 9 9 0 0 512 0 0 0 16 0 384 1 1 1 1 1 1 1 1 1 TABLE 10 2 10 2 11 2 11 2 12 1 12 1 8 5 8 5 9 3 9 3 @@ -497159,7 +497159,7 @@ TABLE 7 6 7 6 6 7 6 7 9 4 9 4 7 6 7 5 8 5 8 5 PAR "NS 120" "EW -120" "NS:NS 2N" "EW:NS 2N" PAR2 "120" "2N-NS" PLAY 51 "SJS3S8SQC3C2CQC6D5D4DKD2CTCAC5C4SAD6H2S6C8CKC7H3DAD9D3DTDQDJD8S2D7H6S5S4C9CJH5S9H7H9HAH4HTHKHQS7H8HJSK" -TRACE 48 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 1 0 4 1 "E:AJT942.AT.T2.A82 3.K84.AQ765.KQ95 8.QJ762.J94.J764 KQ765.953.K83.T3" FUT 11 1 3 2 3 2 3 1 0 0 0 0 14 14 2 2 10 8 10 14 2 4 11 0 0 0 0 0 0 0 0 0 0 1536 5 5 5 5 5 5 5 4 4 4 4 TABLE 7 6 7 6 6 7 6 7 9 4 9 4 7 6 7 5 8 5 8 5 @@ -499133,7 +499133,7 @@ TABLE 10 3 10 3 10 2 10 2 6 7 6 7 11 2 11 2 10 2 10 2 PAR "NS 430" "EW -430" "NS:NS 34N" "EW:NS 34N" PAR2 "430" "3N-NS+1" PLAY 51 "H8HTHJHASQS6S9STC6C8CKC4C2C7CACTSKSAC3CJH3HKH6H2SJS2D5D2S3S5C5D3H5H4H7D4HQD8D9H9S4S8CQD6DTD7C9DJS7DADK" -TRACE 48 11 11 11 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +TRACE 49 11 11 11 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 11 11 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 PBN 2 0 3 1 "S:9.T52.KT95.KQ532 T.J943.Q7632.J74 KQJ743.AKQ7..A96 A8652.86.AJ84.T8" FUT 12 0 1 1 3 0 3 0 2 2 2 2 0 14 6 8 10 2 8 6 14 4 8 11 8 0 0 0 0 0 0 32 0 0 0 0 0 2 2 2 2 1 1 1 1 1 1 1 0 TABLE 10 3 10 3 10 2 10 2 6 7 6 7 11 2 11 2 10 2 10 2 @@ -499175,7 +499175,7 @@ TABLE 3 10 3 10 8 5 8 5 4 9 4 9 5 8 5 8 4 8 4 9 PAR "NS -420" "EW 420" "NS:EW 4S" "EW:EW 4S" PAR2 "-420" "4S-EW" PLAY 50 "H5H2HAH3D3D4DQDKS3S2SAS7HJH6C2H4HQHKS6H9D5D2DAH7CKC4C6CJC3C7CAS4DJS5C8D6C5CTS8STDTSJH8D7SKHTS9SQC9CQ" -TRACE 47 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +TRACE 49 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 PBN 1 0 0 0 "E:9863.2.K8765.A62 QT42.A94.JT932.J AKJ5.QJ3.A4.K953 7.KT8765.Q.QT874" FUT 9 1 1 1 3 3 3 3 2 0 8 10 13 4 8 10 12 12 7 224 0 0 0 128 0 0 0 0 3 3 3 3 3 3 3 3 3 TABLE 3 10 3 10 8 5 8 5 4 9 4 9 5 8 5 8 4 8 4 9 @@ -503144,7 +503144,7 @@ TABLE 10 3 10 3 8 4 8 5 10 3 10 3 5 8 5 8 6 7 6 7 PAR "NS 500" "EW -500" "NS:EW 4Nx,EW 5Cx" "EW:EW 4Nx,EW 5Cx" PAR2 "500" "5C*-EW-3" "4N*-EW-3" PLAY 49 "CJC9C7CAH4H7HKH2D2DTDAD6C5C3S3C2D3D5DKD8C8C4S7CQS8SAS2S6HTS4H9H6D4DQD7H3CTH8CKS9D9HADJS5STSJH5HJSK" -TRACE 46 10 10 10 10 10 9 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 +TRACE 49 10 10 10 10 10 9 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 PBN 3 2 0 1 "W:AQT5.T32.T5.KQ72 KJ942.4.AK94.A85 6.A975.Q86.JT643 873.KQJ86.J732.9" FUT 11 3 3 3 1 0 1 1 1 2 2 2 4 6 11 14 6 5 7 9 6 8 12 8 0 1024 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3 3 3 3 3 TABLE 10 3 10 3 8 4 8 5 10 3 10 3 5 8 5 8 6 7 6 7 @@ -509920,7 +509920,7 @@ TABLE 3 10 3 10 4 9 4 9 7 6 7 6 7 6 7 6 6 7 6 6 PAR "NS -420" "EW 420" "NS:EW 4S" "EW:EW 4S" PAR2 "-420" "4S-EW" PLAY 49 "SQS2S4SADQDKDAD3DJD9S3D5D2D7H2DTCAC4C2C5C3C6H6C8D4D8HJHQS6S5STS9SKS8C7S7CQC9CKH9HTHAH3H7D6H5H8HKSJ" -TRACE 46 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +TRACE 49 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 PBN 1 2 1 2 "E:A983.J532.Q.AT93 Q6.Q87.KT5.KJ764 J752.KT96.AJ42.2 KT4.A4.98763.Q85" FUT 11 3 2 3 2 3 1 3 2 1 0 0 4 5 7 10 11 8 13 13 12 6 12 0 0 64 0 0 128 0 0 0 0 0 4 4 4 4 4 4 4 4 4 4 4 TABLE 3 10 3 10 4 9 4 9 7 6 7 6 7 6 7 6 6 7 6 6 diff --git a/include/dll.h b/include/dll.h index f94da845..c946e4a3 100644 --- a/include/dll.h +++ b/include/dll.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2015 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -26,8 +26,8 @@ #define EXTERN_C #endif -/* Version 2.8.4. Allowing for 2 digit minor versions */ -#define DDS_VERSION 20804 +/* Version 2.9.0. Allowing for 2 digit minor versions */ +#define DDS_VERSION 20900 #define DDS_HANDS 4 @@ -37,7 +37,7 @@ #define MAXNOOFBOARDS 200 -#define MAXNOOFTABLES 32 +#define MAXNOOFTABLES 40 // Error codes. See interface document for more detail. @@ -141,6 +141,10 @@ #define RETURN_THREAD_WAIT -103 #define TEXT_THREAD_WAIT "Something failed waiting for thread to end" +// Tried to set a multi-threading system that is not present in DLL. +#define RETURN_THREAD_MISSING -104 +#define TEXT_THREAD_MISSING "Multi-threading system not present" + // CalcAllTables*() #define RETURN_NO_SUIT -201 #define TEXT_NO_SUIT "Denomination filter vector has no entries" @@ -344,6 +348,9 @@ struct DDSInfo // Currently 0 = unknown, 1 = Windows, 2 = Cygwin, 3 = Linux, 4 = Apple int system; + // We know 32 and 64-bit systems. + int numBits; + // Currently 0 = unknown, 1 = Microsoft Visual C++, 2 = mingw, // 3 = GNU g++, 4 = clang int compiler; @@ -351,13 +358,29 @@ struct DDSInfo // Currently 0 = none, 1 = DllMain, 2 = Unix-style int constructor; - // Currently 0 = none, 1 = Windows, 2 = OpenMP, 3 = GCD + int numCores; + + // Currently + // 0 = none, + // 1 = Windows (native), + // 2 = OpenMP, + // 3 = GCD, + // 4 = Boost, + // 5 = STL, + // 6 = TBB, + // 7 = STLIMPL (for_each), experimental only + // 8 = PPLIMPL (for_each), experimental only int threading; // The actual number of threads configured int noOfThreads; - char systemString[512]; + // This will break if there are > 128 threads... + // The string is of the form LLLSSS meaning 3 large TT memories + // and 3 small ones. + char threadSizes[128]; + + char systemString[1024]; }; @@ -365,6 +388,13 @@ struct DDSInfo EXTERN_C DLLEXPORT void STDCALL SetMaxThreads( int userThreads); +EXTERN_C DLLEXPORT int STDCALL SetThreading( + int code); + +EXTERN_C DLLEXPORT void STDCALL SetResources( + int maxMemoryMB, + int maxThreads); + EXTERN_C DLLEXPORT void STDCALL FreeMemory(); EXTERN_C DLLEXPORT int STDCALL SolveBoard( diff --git a/include/portab.h b/include/portab.h index 72cd62ad..6507839d 100644 --- a/include/portab.h +++ b/include/portab.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2015 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -66,11 +66,4 @@ #define UNUSED(x) ((void)(true ? 0 : ((x), void(), 0))) #endif - -#if __cplusplus <= 199711L - #ifndef nullptr - #define nullptr NULL - #endif -#endif - #endif diff --git a/src/ABsearch.cpp b/src/ABsearch.cpp index ca00adb8..f2c7c190 100644 --- a/src/ABsearch.cpp +++ b/src/ABsearch.cpp @@ -2,282 +2,68 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ +#include +#include +#include -#include "dds.h" #include "TransTable.h" #include "Moves.h" -#include "threadmem.h" #include "QuickTricks.h" #include "LaterTricks.h" #include "ABsearch.h" - - -#define DDS_POS_LINES 5 -#define DDS_HAND_LINES 12 -#define DDS_NODE_LINES 4 -#define DDS_FULL_LINE 80 -#define DDS_HAND_OFFSET 16 -#define DDS_HAND_OFFSET2 12 -#define DDS_DIAG_WIDTH 34 +#include "ABstats.h" +#include "TimerList.h" +#include "dump.h" +#include "debug.h" void Make3Simple( pos * posPoint, - unsigned short int trickCards[DDS_SUITS], - int depth, - moveType * mply, - localVarType * thrp); + unsigned short trickCards[DDS_SUITS], + const int depth, + moveType const * mply, + ThreadData * thrp); void Undo0( pos * posPoint, - int depth, - moveType * mply, - localVarType * thrp); + const int depth, + const moveType& mply, + ThreadData const * thrp); void Undo0Simple( pos * posPoint, - int depth, - moveType * mply); + const int depth, + const moveType& mply); void Undo1( pos * posPoint, - int depth, - moveType * mply); + const int depth, + const moveType& mply); void Undo2( pos * posPoint, - int depth, - moveType * mply); + const int depth, + const moveType& mply); void Undo3( pos * posPoint, - int depth, - moveType * mply); - -void RankToDiagrams( - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - nodeCardsType * np, - char text[DDS_HAND_LINES][DDS_FULL_LINE]); - -void WinnersToText( - unsigned short int winRanks[DDS_SUITS], - char text[DDS_SUITS][DDS_FULL_LINE]); - -void NodeToText( - nodeCardsType * np, - char text[DDS_NODE_LINES][DDS_FULL_LINE]); - -void FullNodeToText( - nodeCardsType * np, - char text[DDS_NODE_LINES][DDS_FULL_LINE]); - -void PosToText( - pos * posPoint, - int target, - int depth, - char text[DDS_POS_LINES][DDS_FULL_LINE]); - -void DumpRetrieved( - FILE * fp, - pos * posPoint, - nodeCardsType * np, - int target, - int depth); - -void DumpStored( - FILE * fp, - pos * posPoint, - Moves * moves, - nodeCardsType * np, - int target, - int depth); + const int depth, + const moveType& mply); const int handDelta[DDS_SUITS] = { 256, 16, 1, 0 }; -// The top-level debugging should possibly go in SolveBoard.cpp -// at some point, but it's so similar to the code here that I -// leave it in this file for now. - -void InitFileTopLevel(int thrId) -{ -#ifdef DDS_TOP_LEVEL - localVarType * thrp = &localVar[thrId]; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s", - DDS_TOP_LEVEL_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - thrp->fpTopLevel = fopen(fname, "w"); - if (! thrp->fpTopLevel) - thrp->fpTopLevel = stdout; -#else - UNUSED(thrId); -#endif -} - - -void InitFileABstats(int thrId) -{ -#ifdef DDS_AB_STATS - localVarType * thrp = &localVar[thrId]; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s", - DDS_AB_STATS_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - thrp->ABStats.SetFile(fname); - - thrp->ABStats.SetName(AB_TARGET_REACHED, "Target decided"); - thrp->ABStats.SetName(AB_DEPTH_ZERO , "depth == 0"); - thrp->ABStats.SetName(AB_QUICKTRICKS , "QuickTricks"); - thrp->ABStats.SetName(AB_LATERTRICKS , "LaterTricks"); - thrp->ABStats.SetName(AB_MAIN_LOOKUP , "Main lookup"); - thrp->ABStats.SetName(AB_SIDE_LOOKUP , "Other lookup"); - thrp->ABStats.SetName(AB_MOVE_LOOP , "Move trial"); -#else - UNUSED(thrId); -#endif -} - - -void InitFileABhits(int thrId) -{ -#ifdef DDS_AB_HITS - localVarType * thrp = &localVar[thrId]; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s", - DDS_AB_HITS_RETRIEVED_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - thrp->fpRetrieved = fopen(fname, "w"); - if (! thrp->fpRetrieved) - thrp->fpRetrieved = stdout; - - sprintf(fname, "%s%d%s", - DDS_AB_HITS_STORED_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - thrp->fpStored = fopen(fname, "w"); - if (! thrp->fpStored) - thrp->fpStored = stdout; -#else - UNUSED(thrId); -#endif -} - - -void InitFileTTstats(int thrId) -{ -#ifdef DDS_TT_STATS - localVarType * thrp = &localVar[thrId]; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s", - DDS_TT_STATS_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - thrp->transTable.SetFile(fname); -#else - UNUSED(thrId); -#endif -} - - -void InitFileTimer(int thrId) -{ -#ifdef DDS_TIMING - Timer * timerp = &localVar[thrId].timer; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s\0", - DDS_TIMING_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - timerp->SetFile(fname); - - timerp->SetNames(); -#else - UNUSED(thrId); -#endif -} - - -void InitFileMoves(int thrId) -{ -#ifdef DDS_MOVES - Moves * movesp = &localVar[thrId].moves; - - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%d%s\0", - DDS_MOVES_PREFIX, - thrId, - DDS_DEBUG_SUFFIX); - - movesp->SetFile(fname); -#else - UNUSED(thrId); -#endif -} - - -void InitFileScheduler() -{ -#ifdef DDS_SCHEDULER - char fname[DDS_FNAME_LEN]; - sprintf(fname, "%s%s\0", - DDS_SCHEDULER_PREFIX, - DDS_DEBUG_SUFFIX); - - scheduler.SetFile(fname); -#endif -} - - -void CloseFileTopLevel(int thrId) -{ -#ifdef DDS_TOP_LEVEL - localVarType * thrp = &localVar[thrId]; - if (thrp->fpTopLevel != stdout && thrp->fpTopLevel != nullptr) - fclose(thrp->fpTopLevel); -#else - UNUSED(thrId); -#endif -} - - -void CloseFileABhits(int thrId) -{ -#ifdef DDS_AB_HITS - localVarType * thrp = &localVar[thrId]; - if (thrp->fpStored != stdout && thrp->fpStored != nullptr) - fclose(thrp->fpStored); -#else - UNUSED(thrId); -#endif -} - - bool ABsearch( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) { /* posPoint points to the current look-ahead position, target is number of tricks to take for the player, @@ -294,46 +80,45 @@ bool ABsearch( thrp->nodes++; #endif - TIMER_START(TIMER_MOVEGEN + depth); + TIMER_START(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) thrp->lowestWin[depth][ss] = 0; thrp->moves.MoveGen0( tricks, - posPoint, - &thrp->bestMove[depth], - &thrp->bestMoveTT[depth], + * posPoint, + thrp->bestMove[depth], + thrp->bestMoveTT[depth], thrp->rel); thrp->moves.Purge(tricks, 0, thrp->forbiddenMoves); - TIMER_END(TIMER_MOVEGEN + depth); + TIMER_END(TIMER_NO_MOVEGEN, depth); - moveType * mply; for (int ss = 0; ss < DDS_SUITS; ss++) posPoint->winRanks[depth][ss] = 0; while (1) { - TIMER_START(TIMER_MAKE + depth); - mply = thrp->moves.MakeNext(tricks, 0, - posPoint->winRanks[depth]); + TIMER_START(TIMER_NO_MAKE, depth); + moveType const * mply = thrp->moves.MakeNext(tricks, 0, + posPoint->winRanks[depth]); #ifdef DDS_AB_STATS thrp->ABStats.IncrNode(depth); #endif - TIMER_END(TIMER_MAKE + depth); + TIMER_END(TIMER_NO_MAKE, depth); if (mply == NULL) break; Make0(posPoint, depth, mply); - TIMER_START(TIMER_AB + depth - 1); + TIMER_START(TIMER_NO_AB, depth - 1); value = ABsearch1(posPoint, target, depth - 1, thrp); - TIMER_END(TIMER_AB + depth - 1); + TIMER_END(TIMER_NO_AB, depth - 1); - TIMER_START(TIMER_UNDO + depth); - Undo1(posPoint, depth, mply); - TIMER_END(TIMER_UNDO + depth); + TIMER_START(TIMER_NO_UNDO, depth); + Undo1(posPoint, depth, * mply); + TIMER_END(TIMER_NO_UNDO, depth); if (value == success) /* A cut-off? */ { @@ -351,15 +136,15 @@ bool ABsearch( posPoint->winRanks[depth][ss] |= posPoint->winRanks[depth - 1][ss]; - TIMER_START(TIMER_NEXTMOVE + depth); - TIMER_END(TIMER_NEXTMOVE + depth); + TIMER_START(TIMER_NO_NEXTMOVE, depth); + TIMER_END(TIMER_NO_NEXTMOVE, depth); } ABexit: AB_COUNT(AB_MOVE_LOOP, value, depth); #ifdef DDS_AB_STATS - thrp->ABStats.PrintStats(); + thrp->ABStats.PrintStats(thrp->fileABstats.GetStream()); #endif return value; @@ -368,9 +153,9 @@ bool ABsearch( bool ABsearch0( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) { /* posPoint points to the current look-ahead position, target is number of tricks to take for the player, @@ -399,17 +184,18 @@ bool ABsearch0( limit = tricks - (target - posPoint->tricksMAX - 1); bool lowerFlag; - TIMER_START(TIMER_LOOKUP + depth); - nodeCardsType * cardsP = - thrp->transTable.Lookup( + TIMER_START(TIMER_NO_LOOKUP, depth); + nodeCardsType const * cardsP = + thrp->transTable->Lookup( tricks, hand, posPoint->aggr, posPoint->handDist, - limit, &lowerFlag); - TIMER_END(TIMER_LOOKUP + depth); + limit, lowerFlag); + TIMER_END(TIMER_NO_LOOKUP, depth); if (cardsP) { #ifdef DDS_AB_HITS - DumpRetrieved(thrp->fpRetrieved, posPoint, cardsP, target, depth); + DumpRetrieved(thrp->fileRetrieved.GetStream(), + * posPoint, cardsP, target, depth); #endif for (int ss = 0; ss < DDS_SUITS; ss++) @@ -443,9 +229,9 @@ bool ABsearch0( } else if (depth == 0) /* Maximum depth? */ { - TIMER_START(TIMER_EVALUATE + depth); + TIMER_START(TIMER_NO_EVALUATE, depth); evalType evalData = Evaluate(posPoint, trump, thrp); - TIMER_END(TIMER_EVALUATE + depth); + TIMER_END(TIMER_NO_EVALUATE, depth); bool value = (evalData.tricks >= target ? true : false); @@ -457,10 +243,10 @@ bool ABsearch0( } bool res; - TIMER_START(TIMER_QT + depth); - int qtricks = QuickTricks(posPoint, hand, depth, target, - trump, &res, thrp); - TIMER_END(TIMER_QT + depth); + TIMER_START(TIMER_NO_QT, depth); + int qtricks = QuickTricks(* posPoint, hand, depth, target, + trump, res, * thrp); + TIMER_END(TIMER_NO_QT, depth); if (thrp->nodeTypeStore[hand] == MAXNODE) { @@ -470,9 +256,9 @@ bool ABsearch0( return (qtricks == 0 ? false : true); } - TIMER_START(TIMER_LT + depth); - res = LaterTricksMIN(posPoint, hand, depth, target, trump, thrp); - TIMER_END(TIMER_LT + depth); + TIMER_START(TIMER_NO_LT, depth); + res = LaterTricksMIN(* posPoint, hand, depth, target, trump, * thrp); + TIMER_END(TIMER_NO_LT, depth); if (! res) { @@ -489,9 +275,9 @@ bool ABsearch0( return (qtricks == 0 ? true : false); } - TIMER_START(TIMER_LT + depth); - res = LaterTricksMAX(posPoint, hand, depth, target, trump, thrp); - TIMER_END(TIMER_LT + depth); + TIMER_START(TIMER_NO_LT, depth); + res = LaterTricksMAX(* posPoint, hand, depth, target, trump, * thrp); + TIMER_END(TIMER_NO_LT, depth); if (res) { @@ -500,22 +286,6 @@ bool ABsearch0( } } - /* - if (depth == 4) - { - char text[DDS_HAND_LINES][DDS_FULL_LINE]; - - RankToText(posPoint->rankInSuit, text); - for (int i = 0; i < DDS_HAND_LINES; i++) - printf("%s\n", text[i]); - printf("\nTrump %c, leader %c, target %d tricks\n", - cardSuit[trump], - cardHand[hand], - - posPoint->tricksMAX + target); - printf("----------------------------------\n\n"); - } - */ - if (depth < 20) { /* Find node that fits the suit lengths */ @@ -526,17 +296,18 @@ bool ABsearch0( limit = tricks - (target - posPoint->tricksMAX - 1); bool lowerFlag; - TIMER_START(TIMER_LOOKUP + depth); - nodeCardsType * cardsP = - thrp->transTable.Lookup( + TIMER_START(TIMER_NO_LOOKUP, depth); + nodeCardsType const * cardsP = + thrp->transTable->Lookup( tricks, hand, posPoint->aggr, posPoint->handDist, - limit, &lowerFlag); - TIMER_END(TIMER_LOOKUP + depth); + limit, lowerFlag); + TIMER_END(TIMER_NO_LOOKUP, depth); if (cardsP) { #ifdef DDS_AB_HITS - DumpRetrieved(thrp->fpRetrieved, posPoint, cardsP, target, depth); + DumpRetrieved(thrp->fileRetrieved.GetStream(), + * posPoint, * cardsP, target, depth); #endif for (int ss = 0; ss < DDS_SUITS; ss++) @@ -561,45 +332,44 @@ bool ABsearch0( bool success = (thrp->nodeTypeStore[hand] == MAXNODE ? true : false); bool value = ! success; - TIMER_START(TIMER_MOVEGEN + depth); + TIMER_START(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) thrp->lowestWin[depth][ss] = 0; thrp->moves.MoveGen0( tricks, - posPoint, - &thrp->bestMove[depth], - &thrp->bestMoveTT[depth], + * posPoint, + thrp->bestMove[depth], + thrp->bestMoveTT[depth], thrp->rel); - TIMER_END(TIMER_MOVEGEN + depth); + TIMER_END(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) posPoint->winRanks[depth][ss] = 0; - moveType * mply; while (1) { - TIMER_START(TIMER_MAKE + depth); - mply = thrp->moves.MakeNext(tricks, 0, - posPoint->winRanks[depth]); + TIMER_START(TIMER_NO_MAKE, depth); + moveType const * mply = thrp->moves.MakeNext(tricks, 0, + posPoint->winRanks[depth]); #ifdef DDS_AB_STATS thrp->ABStats.IncrNode(depth); #endif - TIMER_END(TIMER_MAKE + depth); + TIMER_END(TIMER_NO_MAKE, depth); if (mply == NULL) break; Make0(posPoint, depth, mply); - TIMER_START(TIMER_AB + depth - 1); + TIMER_START(TIMER_NO_AB, depth - 1); value = ABsearch1(posPoint, target, depth - 1, thrp); - TIMER_END(TIMER_AB + depth - 1); + TIMER_END(TIMER_NO_AB, depth - 1); - TIMER_START(TIMER_UNDO + depth); - Undo1(posPoint, depth, mply); - TIMER_END(TIMER_UNDO + depth); + TIMER_START(TIMER_NO_UNDO, depth); + Undo1(posPoint, depth, * mply); + TIMER_END(TIMER_NO_UNDO, depth); if (value == success) /* A cut-off? */ { @@ -617,8 +387,8 @@ bool ABsearch0( posPoint->winRanks[depth][ss] |= posPoint->winRanks[depth - 1][ss]; - TIMER_START(TIMER_NEXTMOVE + depth); - TIMER_END(TIMER_NEXTMOVE + depth); + TIMER_START(TIMER_NO_NEXTMOVE, depth); + TIMER_END(TIMER_NO_NEXTMOVE, depth); } ABexit: @@ -661,19 +431,19 @@ bool ABsearch0( (thrp->nodeTypeStore[hand] == MINNODE && !value)) ? true : false; - TIMER_START(TIMER_BUILD + depth); - thrp->transTable.Add( + TIMER_START(TIMER_NO_BUILD, depth); + thrp->transTable->Add( tricks, hand, posPoint->aggr, posPoint->winRanks[depth], - &first, + first, flag); - TIMER_END(TIMER_BUILD + depth); + TIMER_END(TIMER_NO_BUILD, depth); #ifdef DDS_AB_HITS - DumpStored(thrp->fpStored, posPoint, &thrp->moves, - &first, target, depth); + DumpStored(thrp->fileStored.GetStream(), + * posPoint, thrp->moves, first, target, depth); #endif AB_COUNT(AB_MOVE_LOOP, value, depth); @@ -683,9 +453,9 @@ bool ABsearch0( bool ABsearch1( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) { int trump = thrp->trump; int hand = handId(posPoint->first[depth], 1); @@ -697,48 +467,51 @@ bool ABsearch1( thrp->nodes++; #endif - TIMER_START(TIMER_QT + depth); - int res = QuickTricksSecondHand(posPoint, hand, depth, target, - trump, thrp); - TIMER_END(TIMER_QT + depth); - if (res) return success; + TIMER_START(TIMER_NO_QT, depth); + int res = QuickTricksSecondHand(* posPoint, hand, depth, target, + trump, * thrp); + TIMER_END(TIMER_NO_QT, depth); + if (res) + { + AB_COUNT(AB_QUICKTRICKS_2ND, true, depth); + return success; + } - TIMER_START(TIMER_MOVEGEN + depth); + TIMER_START(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) thrp->lowestWin[depth][ss] = 0; - thrp->moves.MoveGen123(tricks, 1, posPoint); + thrp->moves.MoveGen123(tricks, 1, * posPoint); if (depth == thrp->iniDepth) thrp->moves.Purge(tricks, 1, thrp->forbiddenMoves); - TIMER_END(TIMER_MOVEGEN + depth); + TIMER_END(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) posPoint->winRanks[depth][ss] = 0; - moveType * mply; while (1) { - TIMER_START(TIMER_MAKE + depth); - mply = thrp->moves.MakeNext(tricks, 1, - posPoint->winRanks[depth]); + TIMER_START(TIMER_NO_MAKE, depth); + moveType const * mply = thrp->moves.MakeNext(tricks, 1, + posPoint->winRanks[depth]); #ifdef DDS_AB_STATS thrp->ABStats.IncrNode(depth); #endif - TIMER_END(TIMER_MAKE + depth); + TIMER_END(TIMER_NO_MAKE, depth); if (mply == NULL) break; Make1(posPoint, depth, mply); - TIMER_START(TIMER_AB + depth - 1); + TIMER_START(TIMER_NO_AB, depth - 1); value = ABsearch2(posPoint, target, depth - 1, thrp); - TIMER_END(TIMER_AB + depth - 1); + TIMER_END(TIMER_NO_AB, depth - 1); - TIMER_START(TIMER_UNDO + depth); - Undo2(posPoint, depth, mply); - TIMER_END(TIMER_UNDO + depth); + TIMER_START(TIMER_NO_UNDO, depth); + Undo2(posPoint, depth, * mply); + TIMER_END(TIMER_NO_UNDO, depth); if (value == success) /* A cut-off? */ { @@ -757,8 +530,8 @@ bool ABsearch1( posPoint->winRanks[depth][ss] |= posPoint->winRanks[depth - 1][ss]; - TIMER_START(TIMER_NEXTMOVE + depth); - TIMER_END(TIMER_NEXTMOVE + depth); + TIMER_START(TIMER_NO_NEXTMOVE, depth); + TIMER_END(TIMER_NO_NEXTMOVE, depth); } ABexit: @@ -769,9 +542,9 @@ bool ABsearch1( bool ABsearch2( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) { int hand = handId(posPoint->first[depth], 2); bool success = (thrp->nodeTypeStore[hand] == MAXNODE ? true : false); @@ -782,25 +555,24 @@ bool ABsearch2( thrp->nodes++; #endif - TIMER_START(TIMER_MOVEGEN + depth); + TIMER_START(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) thrp->lowestWin[depth][ss] = 0; - thrp->moves.MoveGen123(tricks, 2, posPoint); + thrp->moves.MoveGen123(tricks, 2, * posPoint); if (depth == thrp->iniDepth) thrp->moves.Purge(tricks, 2, thrp->forbiddenMoves); - TIMER_END(TIMER_MOVEGEN + depth); + TIMER_END(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) posPoint->winRanks[depth][ss] = 0; - moveType * mply; while (1) { - TIMER_START(TIMER_MAKE + depth); - mply = thrp->moves.MakeNext(tricks, 2, - posPoint->winRanks[depth]); + TIMER_START(TIMER_NO_MAKE, depth); + moveType const * mply = thrp->moves.MakeNext(tricks, 2, + posPoint->winRanks[depth]); if (mply == NULL) break; @@ -810,15 +582,15 @@ bool ABsearch2( #ifdef DDS_AB_STATS thrp->ABStats.IncrNode(depth); #endif - TIMER_END(TIMER_MAKE + depth); + TIMER_END(TIMER_NO_MAKE, depth); - TIMER_START(TIMER_AB + depth - 1); + TIMER_START(TIMER_NO_AB, depth - 1); value = ABsearch3(posPoint, target, depth - 1, thrp); - TIMER_END(TIMER_AB + depth - 1); + TIMER_END(TIMER_NO_AB, depth - 1); - TIMER_START(TIMER_UNDO + depth); - Undo3(posPoint, depth, mply); - TIMER_END(TIMER_UNDO + depth); + TIMER_START(TIMER_NO_UNDO, depth); + Undo3(posPoint, depth, * mply); + TIMER_END(TIMER_NO_UNDO, depth); if (value == success) /* A cut-off? */ @@ -838,8 +610,8 @@ bool ABsearch2( posPoint->winRanks[depth][ss] |= posPoint->winRanks[depth - 1][ss]; - TIMER_START(TIMER_NEXTMOVE + depth); - TIMER_END(TIMER_NEXTMOVE + depth); + TIMER_START(TIMER_NO_NEXTMOVE, depth); + TIMER_END(TIMER_NO_NEXTMOVE, depth); } ABexit: @@ -850,9 +622,9 @@ bool ABsearch2( bool ABsearch3( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) { /* This is a specialized AB function for handRelFirst == 3. */ @@ -866,31 +638,29 @@ bool ABsearch3( thrp->nodes++; #endif - TIMER_START(TIMER_MOVEGEN + depth); + TIMER_START(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) thrp->lowestWin[depth][ss] = 0; int tricks = (depth + 3) >> 2; - thrp->moves.MoveGen123(tricks, 3, posPoint); + thrp->moves.MoveGen123(tricks, 3, * posPoint); if (depth == thrp->iniDepth) thrp->moves.Purge(tricks, 3, thrp->forbiddenMoves); - TIMER_END(TIMER_MOVEGEN + depth); - - moveType * mply; + TIMER_END(TIMER_NO_MOVEGEN, depth); for (int ss = 0; ss < DDS_SUITS; ss++) posPoint->winRanks[depth][ss] = 0; while (1) { - TIMER_START(TIMER_MAKE + depth); - mply = thrp->moves.MakeNext(tricks, 3, - posPoint->winRanks[depth]); + TIMER_START(TIMER_NO_MAKE, depth); + moveType const * mply = thrp->moves.MakeNext(tricks, 3, + posPoint->winRanks[depth]); #ifdef DDS_AB_STATS thrp->ABStats.IncrNode(depth); #endif - TIMER_END(TIMER_MAKE + depth); + TIMER_END(TIMER_NO_MAKE, depth); if (mply == NULL) break; @@ -902,17 +672,17 @@ bool ABsearch3( if (thrp->nodeTypeStore[posPoint->first[depth - 1]] == MAXNODE) posPoint->tricksMAX++; - TIMER_START(TIMER_AB + depth - 1); + TIMER_START(TIMER_NO_AB, depth - 1); value = ABsearch0(posPoint, target, depth - 1, thrp); - TIMER_END(TIMER_AB + depth - 1); + TIMER_END(TIMER_NO_AB, depth - 1); - TIMER_START(TIMER_UNDO + depth); - Undo0(posPoint, depth, mply, thrp); + TIMER_START(TIMER_NO_UNDO, depth); + Undo0(posPoint, depth, * mply, thrp); if (thrp->nodeTypeStore[posPoint->first[depth - 1]] == MAXNODE) posPoint->tricksMAX--; - TIMER_END(TIMER_UNDO + depth); + TIMER_END(TIMER_NO_UNDO, depth); if (value == success) /* A cut-off? */ { @@ -930,8 +700,8 @@ bool ABsearch3( posPoint->winRanks[depth][ss] |= posPoint->winRanks[depth - 1][ss] | makeWinRank[ss]; - TIMER_START(TIMER_NEXTMOVE + depth); - TIMER_END(TIMER_NEXTMOVE + depth); + TIMER_START(TIMER_NO_NEXTMOVE, depth); + TIMER_END(TIMER_NO_NEXTMOVE, depth); } ABexit: @@ -942,8 +712,8 @@ bool ABsearch3( void Make0( pos * posPoint, - int depth, - moveType * mply) + const int depth, + moveType const * mply) { /* First hand is not changed in next move */ int h = posPoint->first[depth]; @@ -962,8 +732,8 @@ void Make0( void Make1( pos * posPoint, - int depth, - moveType * mply) + const int depth, + moveType const * mply) { /* First hand is not changed in next move */ int firstHand = posPoint->first[depth]; @@ -982,8 +752,8 @@ void Make1( void Make2( pos * posPoint, - int depth, - moveType * mply) + const int depth, + moveType const * mply) { /* First hand is not changed in next move */ int firstHand = posPoint->first[depth]; @@ -1002,16 +772,16 @@ void Make2( void Make3( pos * posPoint, - unsigned short int trickCards[DDS_SUITS], - int depth, - moveType * mply, - localVarType * thrp) + unsigned short trickCards[DDS_SUITS], + const int depth, + moveType const * mply, + ThreadData * thrp) { int firstHand = posPoint->first[depth]; - trickDataType * datap = thrp->moves.GetTrickData((depth + 3) >> 2); + const trickDataType& data = thrp->moves.GetTrickData((depth + 3) >> 2); - posPoint->first[depth - 1] = handId(firstHand, datap->relWinner); + posPoint->first[depth - 1] = handId(firstHand, data.relWinner); /* Defines who is first in the next move */ int h = handId(firstHand, 3); @@ -1020,13 +790,13 @@ void Make3( for (int suit = 0; suit < DDS_SUITS; suit++) trickCards[suit] = 0; - int ss = datap->bestSuit; - if (datap->playCount[ss] >= 2) + int ss = data.bestSuit; + if (data.playCount[ss] >= 2) { // Win by rank when some else played that suit, too. - int rr = datap->bestRank; + int rr = data.bestRank; trickCards[ss] = static_cast - (bitMapRank[rr] | datap->bestSequence); + (bitMapRank[rr] | data.bestSequence); } int r = mply->rank; @@ -1042,7 +812,7 @@ void Make3( for (int st = 0; st < 4; st++) { - if (datap->playCount[st]) + if (data.playCount[st]) { int n = wp->number; wp->winner[n].suit = st; @@ -1066,28 +836,28 @@ void Make3( void Make3Simple( pos * posPoint, - unsigned short int trickCards[DDS_SUITS], - int depth, - moveType * mply, - localVarType * thrp) + unsigned short trickCards[DDS_SUITS], + const int depth, + moveType const * mply, + ThreadData * thrp) { - trickDataType * datap = thrp->moves.GetTrickData((depth + 3) >> 2); + const trickDataType& data = thrp->moves.GetTrickData((depth + 3) >> 2); int firstHand = posPoint->first[depth]; // Leader of next trick - posPoint->first[depth - 1] = handId(firstHand, datap->relWinner); + posPoint->first[depth - 1] = handId(firstHand, data.relWinner); for (int suit = 0; suit < DDS_SUITS; suit++) trickCards[suit] = 0; - int s = datap->bestSuit; - if (datap->playCount[s] >= 2) + int s = data.bestSuit; + if (data.playCount[s] >= 2) { // Win by rank when some else played that suit, too. - int r = datap->bestRank; + int r = data.bestRank; trickCards[s] = static_cast - (bitMapRank[r] | datap->bestSequence); + (bitMapRank[r] | data.bestSequence); } int h = handId(firstHand, 3); @@ -1101,13 +871,13 @@ void Make3Simple( void Undo0( pos * posPoint, - int depth, - moveType * mply, - localVarType * thrp) + const int depth, + const moveType& mply, + ThreadData const * thrp) { int h = handId(posPoint->first[depth], 3); - int s = mply->suit; - int r = mply->rank; + int s = mply.suit; + int r = mply.rank; posPoint->rankInSuit[h][s] |= bitMapRank[r]; posPoint->aggr[s] |= bitMapRank[r]; @@ -1115,7 +885,7 @@ void Undo0( posPoint->length[h][s]++; // Changes that we now undo. - WinnersType * wp = &thrp->winners[ (depth + 3) >> 2]; + WinnersType const * wp = &thrp->winners[ (depth + 3) >> 2]; for (int n = 0; n < wp->number; n++) { @@ -1130,12 +900,12 @@ void Undo0( void Undo0Simple( pos * posPoint, - int depth, - moveType * mply) + const int depth, + const moveType& mply) { int h = handId(posPoint->first[depth], 3); - int s = mply->suit; - int r = mply->rank; + int s = mply.suit; + int r = mply.rank; posPoint->aggr[s] |= bitMapRank[r]; posPoint->handDist[h] += handDelta[s]; @@ -1144,12 +914,12 @@ void Undo0Simple( void Undo1( pos * posPoint, - int depth, - moveType * mply) + const int depth, + const moveType& mply) { int h = posPoint->first[depth]; - int s = mply->suit; - int r = mply->rank; + int s = mply.suit; + int r = mply.rank; posPoint->rankInSuit[h][s] |= bitMapRank[r]; posPoint->aggr[s] |= bitMapRank[r]; @@ -1160,12 +930,12 @@ void Undo1( void Undo2( pos * posPoint, - int depth, - moveType * mply) + const int depth, + const moveType& mply) { int h = handId(posPoint->first[depth], 1); - int s = mply->suit; - int r = mply->rank; + int s = mply.suit; + int r = mply.rank; posPoint->rankInSuit[h][s] |= bitMapRank[r]; posPoint->aggr[s] |= bitMapRank[r]; @@ -1176,12 +946,12 @@ void Undo2( void Undo3( pos * posPoint, - int depth, - moveType * mply) + const int depth, + const moveType& mply) { int h = handId(posPoint->first[depth], 2); - int s = mply->suit; - int r = mply->rank; + int s = mply.suit; + int r = mply.rank; posPoint->rankInSuit[h][s] |= bitMapRank[r]; posPoint->aggr[s] |= bitMapRank[r]; @@ -1191,9 +961,9 @@ void Undo3( evalType Evaluate( - pos * posPoint, - int trump, - localVarType * thrp) + pos const * posPoint, + const int trump, + ThreadData const * thrp) { int s, h, hmax = 0, count = 0, k = 0; unsigned short rmax = 0; @@ -1271,364 +1041,3 @@ evalType Evaluate( return eval; } - -void RankToText( - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - char text[DDS_HAND_LINES][DDS_FULL_LINE]) -{ - int c, h, s, r; - - for (int l = 0; l < DDS_HAND_LINES; l++) - { - memset(text[l], ' ', DDS_FULL_LINE); - text[l][DDS_FULL_LINE - 1] = '\0'; - } - - for (h = 0; h < DDS_HANDS; h++) - { - int offset, line; - if (h == 0) - { - offset = DDS_HAND_OFFSET; - line = 0; - } - else if (h == 1) - { - offset = 2 * DDS_HAND_OFFSET; - line = 4; - } - else if (h == 2) - { - offset = DDS_HAND_OFFSET; - line = 8; - } - else - { - offset = 0; - line = 4; - } - - for (s = 0; s < DDS_SUITS; s++) - { - c = offset; - for (r = 14; r >= 2; r--) - { - if (rankInSuit[h][s] & bitMapRank[r]) - text[line + s][c++] = static_cast(cardRank[r]); - } - - if (c == offset) - text[line + s][c++] = '-'; - - if (h != 3) - text[line + s][c] = '\0'; - } - } -} - - -void RankToDiagrams( - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - nodeCardsType * np, - char text[DDS_HAND_LINES][DDS_FULL_LINE]) -{ - int c, h, s, r; - - for (int l = 0; l < DDS_HAND_LINES; l++) - { - memset(text[l], ' ', DDS_FULL_LINE); - text[l][DDS_FULL_LINE - 1] = '\0'; - text[l][DDS_DIAG_WIDTH ] = '|'; - } - - strncpy(text[0], "Sought", 6); - strncpy(&text[0][DDS_DIAG_WIDTH + 5], "Found", 5); - - for (h = 0; h < DDS_HANDS; h++) - { - int offset, line; - if (h == 0) - { - offset = DDS_HAND_OFFSET2; - line = 0; - } - else if (h == 1) - { - offset = 2 * DDS_HAND_OFFSET2; - line = 4; - } - else if (h == 2) - { - offset = DDS_HAND_OFFSET2; - line = 8; - } - else - { - offset = 0; - line = 4; - } - - for (s = 0; s < DDS_SUITS; s++) - { - c = offset; - for (r = 14; r >= 2; r--) - { - if (rankInSuit[h][s] & bitMapRank[r]) - { - text[line + s][c] = static_cast(cardRank[r]); - text[line + s][c + DDS_DIAG_WIDTH + 5] = - (r >= 15 - np->leastWin[s] ? - static_cast(cardRank[r]) : 'x'); - c++; - } - } - - if (c == offset) - { - text[line + s][c] = '-'; - text[line + s][c + DDS_DIAG_WIDTH + 5] = '-'; - c++; - } - - if (h != 3) - text[line + s][c + DDS_DIAG_WIDTH + 5] = '\0'; - } - } -} - - -void WinnersToText( - unsigned short int ourWinRanks[DDS_SUITS], - char text[DDS_SUITS][DDS_FULL_LINE]) -{ - int c, s, r; - - for (int l = 0; l < DDS_SUITS; l++) - memset(text[l], ' ', DDS_FULL_LINE); - - for (s = 0; s < DDS_SUITS; s++) - { - text[s][0] = static_cast(cardSuit[s]); - - c = 2; - for (r = 14; r >= 2; r--) - { - if (ourWinRanks[s] & bitMapRank[r]) - text[s][c++] = static_cast(cardRank[r]); - } - text[s][c] = '\0'; - } -} - - -void NodeToText( - nodeCardsType * np, - char text[DDS_NODE_LINES - 1][DDS_FULL_LINE]) - -{ - sprintf(text[0], "Address\t\t%p\n", static_cast(np)); - - sprintf(text[1], "Bounds\t\t%d to %d tricks\n", - static_cast(np->lbound), - static_cast(np->ubound)); - - sprintf(text[2], "Best move\t%c%c\n", - cardSuit[ static_cast(np->bestMoveSuit) ], - cardRank[ static_cast(np->bestMoveRank) ]); - -} - - -void FullNodeToText( - nodeCardsType * np, - char text[DDS_NODE_LINES][DDS_FULL_LINE]) - -{ - sprintf(text[0], "Address\t\t%p\n", static_cast(np)); - - sprintf(text[1], "Lowest used\t%c%c, %c%c, %c%c, %c%c\n", - cardSuit[0], cardRank[ 15 - static_cast(np->leastWin[0]) ], - cardSuit[1], cardRank[ 15 - static_cast(np->leastWin[1]) ], - cardSuit[2], cardRank[ 15 - static_cast(np->leastWin[2]) ], - cardSuit[3], cardRank[ 15 - static_cast(np->leastWin[3]) ]); - - sprintf(text[2], "Bounds\t\t%d to %d tricks\n", - static_cast(np->lbound), - static_cast(np->ubound)); - - sprintf(text[3], "Best move\t%c%c\n", - cardSuit[ static_cast(np->bestMoveSuit) ], - cardRank[ static_cast(np->bestMoveRank) ]); - -} - - -void PosToText( - pos * posPoint, - int target, - int depth, - char text[DDS_POS_LINES][DDS_FULL_LINE]) -{ - sprintf(text[0], "Target\t\t%d\n" , target); - sprintf(text[1], "Depth\t\t%d\n" , depth); - sprintf(text[2], "tricksMAX\t%d\n" , posPoint->tricksMAX); - sprintf(text[3], "First hand\t%c\n", - cardHand[ posPoint->first[depth] ]); - sprintf(text[4], "Next first\t%c\n", - cardHand[ posPoint->first[depth - 1] ]); -} - - -void DumpRetrieved( - FILE * fp, - pos * posPoint, - nodeCardsType * np, - int target, - int depth) -{ - // Big enough for all uses. - char text[DDS_HAND_LINES][DDS_FULL_LINE]; - - fprintf(fp, "Retrieved entry\n"); - fprintf(fp, "---------------\n"); - - PosToText(posPoint, target, depth, text); - for (int i = 0; i < DDS_POS_LINES; i++) - fprintf(fp, "%s", text[i]); - fprintf(fp, "\n"); - - FullNodeToText(np, text); - for (int i = 0; i < DDS_NODE_LINES; i++) - fprintf(fp, "%s", text[i]); - fprintf(fp, "\n"); - - RankToDiagrams(posPoint->rankInSuit, np, text); - for (int i = 0; i < DDS_HAND_LINES; i++) - fprintf(fp, "%s\n", text[i]); - fprintf(fp, "\n"); -} - - -void DumpStored( - FILE * fp, - pos * posPoint, - Moves * moves, - nodeCardsType * np, - int target, - int depth) -{ - // Big enough for all uses. - char text[DDS_HAND_LINES][DDS_FULL_LINE]; - - fprintf(fp, "Stored entry\n"); - fprintf(fp, "------------\n"); - - PosToText(posPoint, target, depth, text); - for (int i = 0; i < DDS_POS_LINES; i++) - fprintf(fp, "%s", text[i]); - fprintf(fp, "\n"); - - NodeToText(np, text); - for (int i = 0; i < DDS_NODE_LINES - 1; i++) - fprintf(fp, "%s", text[i]); - fprintf(fp, "\n"); - - moves->TrickToText((depth >> 2) + 1, text[0]); - fprintf(fp, "%s", text[0]); - fprintf(fp, "\n"); - - RankToText(posPoint->rankInSuit, text); - for (int i = 0; i < DDS_HAND_LINES; i++) - fprintf(fp, "%s\n", text[i]); - fprintf(fp, "\n"); -} - - -void DumpTopLevel( - localVarType * thrp, - int tricks, - int lower, - int upper, - int printMode) -{ -#ifdef DDS_TOP_LEVEL - char text[DDS_HAND_LINES][DDS_FULL_LINE]; - pos * posPoint = &thrp->lookAheadPos; - FILE * fp = thrp->fpTopLevel; - - if (printMode == 0) - { - // Trying just one target. - sprintf(text[0], "Single target %d, %s\n", - tricks, - "achieved"); - } - else if (printMode == 1) - { - // Looking for best score. - if (thrp->val) - { - sprintf(text[0], - "Loop target %d, bounds %d .. %d, achieved with move %c%c\n", - tricks, - lower, - upper, - cardSuit[ thrp->bestMove[thrp->iniDepth].suit ], - cardRank[ thrp->bestMove[thrp->iniDepth].rank ]); - } - else - { - sprintf(text[0], - "Loop target %d, bounds %d .. %d, failed\n", - tricks, - lower, - upper); - } - } - else if (printMode == 2) - { - // Looking for other moves with best score. - if (thrp->val) - { - sprintf(text[0], - "Loop for cards with score %d, achieved with move %c%c\n", - tricks, - cardSuit[ thrp->bestMove[thrp->iniDepth].suit ], - cardRank[ thrp->bestMove[thrp->iniDepth].rank ]); - } - else - { - sprintf(text[0], - "Loop for cards with score %d, failed\n", - tricks); - } - } - - size_t l = strlen(text[0]) - 1; - - memset(text[1], '-', l); - text[1][l] = '\0'; - fprintf(fp, "%s%s\n\n", text[0], text[1]); - - RankToText(posPoint->rankInSuit, text); - for (int i = 0; i < DDS_HAND_LINES; i++) - fprintf(fp, "%s\n", text[i]); - fprintf(fp, "\n"); - - WinnersToText(posPoint->winRanks[ thrp->iniDepth ], text); - for (int i = 0; i < DDS_SUITS; i++) - fprintf(fp, "%s\n", text[i]); - fprintf(fp, "\n"); - - fprintf(fp, "%d AB nodes, %d trick nodes\n\n", - thrp->nodes, - thrp->trickNodes); -#else - UNUSED(thrp); - UNUSED(tricks); - UNUSED(lower); - UNUSED(upper); - UNUSED(printMode); -#endif -} - diff --git a/src/ABsearch.h b/src/ABsearch.h index a45c1c6a..bf4e3515 100644 --- a/src/ABsearch.h +++ b/src/ABsearch.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,108 +10,65 @@ #ifndef DDS_ABSEARCH_H #define DDS_ABSEARCH_H - -#define DDS_POS_LINES 5 -#define DDS_HAND_LINES 12 -#define DDS_NODE_LINES 4 -#define DDS_FULL_LINE 80 -#define DDS_HAND_OFFSET 16 -#define DDS_HAND_OFFSET2 12 -#define DDS_DIAG_WIDTH 34 +#include "dds.h" +#include "Memory.h" bool ABsearch( - struct pos * posPoint, - int target, - int depth, - struct localVarType * thrp); + pos * posPoint, + const int target, + const int depth, + ThreadData * thrp); bool ABsearch0( - struct pos * posPoint, - int target, - int depth, - struct localVarType * thrp); + pos * posPoint, + const int target, + const int depth, + ThreadData * thrp); bool ABsearch1( - struct pos * posPoint, - int target, - int depth, - struct localVarType * thrp); + pos * posPoint, + const int target, + const int depth, + ThreadData * thrp); bool ABsearch2( - struct pos * posPoint, - int target, - int depth, - struct localVarType * thrp); + pos * posPoint, + const int target, + const int depth, + ThreadData * thrp); bool ABsearch3( - struct pos * posPoint, - int target, - int depth, - struct localVarType * thrp); + pos * posPoint, + const int target, + const int depth, + ThreadData * thrp); void Make0( - struct pos * posPoint, - int depth, - moveType * mply); + pos * posPoint, + const int depth, + moveType const * mply); void Make1( - struct pos * posPoint, - int depth, - moveType * mply); + pos * posPoint, + const int depth, + moveType const * mply); void Make2( - struct pos * posPoint, - int depth, - moveType * mply); + pos * posPoint, + const int depth, + moveType const * mply); void Make3( - struct pos * posPoint, - unsigned short int trickCards[DDS_SUITS], - int depth, - moveType * mply, - localVarType * thrp); - -evalType Evaluate( pos * posPoint, - int trump, - localVarType * thrp); + unsigned short trickCards[DDS_SUITS], + const int depth, + moveType const * mply, + ThreadData * thrp); -void InitFileTopLevel( - int thrId); - -void InitFileABstats( - int thrId); - -void InitFileABhits( - int thrId); - -void InitFileTTstats( - int thrId); - -void InitFileTimer( - int thrId); - -void InitFileMoves( - int thrId); - -void InitFileScheduler(); - -void CloseFileTopLevel( - int thrId); - -void CloseFileABhits( - int thrId); - -void DumpTopLevel( - struct localVarType * thrp, - int tricks, - int lower, - int upper, - int printMode); - -void RankToText( - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - char text[DDS_HAND_LINES][DDS_FULL_LINE]); +evalType Evaluate( + pos const * posPoint, + const int trump, + ThreadData const * thrp); #endif diff --git a/src/ABstats.cpp b/src/ABstats.cpp index 01456bc9..f45ec888 100644 --- a/src/ABstats.cpp +++ b/src/ABstats.cpp @@ -2,335 +2,351 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ /* - This object, ABstats, is a simple object for AB statistics - and return values. + ABstats is a simple object for AB statistics and return values. */ -#include "dds.h" +#include + #include "ABstats.h" ABstats::ABstats() { - strcpy(fname, ""); - fp = stdout; ABstats::Reset(); - ABstats::ResetCum(); + ABstats::SetNames(); } ABstats::~ABstats() { - // Nothing to do - if (fp != stdout && fp != nullptr) - fclose(fp); } void ABstats::Reset() { - for (int p = 0; p < DDS_AB_POS; p++) - { - sprintf(name[p], "Position %4d", p); + for (int depth = 0; depth < DDS_MAXDEPTH; depth++) + ABnodes.list[depth] = 0; - for (int depth = 0; depth < DDS_MAXDEPTH; depth++) - counter[p][depth] = 0; - } + ABnodes.sum = 0; + ABnodes.sumWeighted = 0; for (int side = 0; side < 2; side++) { for (int depth = 0; depth < DDS_MAXDEPTH; depth++) - score[side][depth] = 0; + ABsides[side].list[depth] = 0; + + ABsides[side].sum = 0; + ABsides[side].sumWeighted = 0; } - for (int depth = 0; depth < DDS_MAXDEPTH; depth++) - nodes[depth] = 0; + for (int place = 0; place < AB_SIZE; place++) + { + for (int depth = 0; depth < DDS_MAXDEPTH; depth++) + ABplaces[place].list[depth] = 0; - allnodes = 0; + ABplaces[place].sum = 0; + ABplaces[place].sumWeighted = 0; + } } void ABstats::ResetCum() { - for (int depth = 0; depth < DDS_MAXDEPTH; depth++) - nodesCum[depth] = 0; - - allnodesCum = 0; - - scoreCum[1] = 0; - scoreCum[0] = 0; + ABnodesCum.sumCum = 0; + ABnodesCum.sumCumWeighted = 0; - pscoreCum[1] = 0; - pscoreCum[0] = 0; + for (int side = 0; side < 2; side++) + { + ABsides[side].sumCum = 0; + ABsides[side].sumCumWeighted = 0; + } - for (int p = 0; p < DDS_AB_POS; p++) + for (int place = 0; place < AB_SIZE; place++) { - counterCum[p] = 0; - pcounterCum[p] = 0; + ABplaces[place].sumCum = 0; + ABplaces[place].sumCumWeighted = 0; } } -void ABstats::SetFile(char * ourFname) +void ABstats::SetNames() { - if (strlen(ourFname) > DDS_LINE_LEN) - return; + name[AB_TARGET_REACHED] = "Target decided"; + name[AB_DEPTH_ZERO] = "depth == 0"; + name[AB_QUICKTRICKS] = "QuickTricks"; + name[AB_QUICKTRICKS_2ND] = "QuickTricks 2nd"; + name[AB_LATERTRICKS] = "LaterTricks"; + name[AB_MAIN_LOOKUP] = "Main lookup"; + name[AB_SIDE_LOOKUP] = "Other lookup"; + name[AB_MOVE_LOOP] = "Move trial"; +} + - if (fp != stdout) // Already set +void ABstats::IncrPos( + const ABCountType no, + const bool side, + const int depth) +{ + if (no < 0 || no >= AB_SIZE) return; - strncpy(fname, ourFname, strlen(ourFname)); + ABplaces[no].list[depth]++; + ABplaces[no].sum++; + ABplaces[no].sumWeighted += depth; + ABplaces[no].sumCum++; + ABplaces[no].sumCumWeighted += depth; + + const int iside = (side ? 1 : 0); + + ABsides[iside].list[depth]++; + ABsides[iside].sum++; + ABsides[iside].sumWeighted += depth; + ABsides[iside].sumCum++; + ABsides[iside].sumCumWeighted += depth; - fp = fopen(fname, "w"); - if (! fp) - fp = stdout; } -void ABstats::SetName(int no, char * ourName) +void ABstats::IncrNode(const int depth) { - if (no < 0 || no >= DDS_AB_POS) - return; + ABnodes.list[depth]++; + ABnodes.sum++; + ABnodes.sumWeighted += depth; + + ABnodesCum.list[depth]++; + ABnodesCum.sumCum++; + ABnodesCum.sumCumWeighted += depth; +} + - sprintf(name[no], "%s", ourName); +int ABstats::GetNodes() const +{ + return ABnodes.sum; } -void ABstats::IncrPos(int no, bool side, int depth) +void ABstats::PrintHeaderPosition(ofstream& fout) const { - if (no < 0 || no >= DDS_AB_POS) + fout << "No " << + setw(20) << left << "Return" << + setw(9) << right << "Count" << + setw(6) << "%" << + setw(6) << "d_avg" << + setw(9) << "Cumul" << + setw(6) << "%" << + setw(6) << "d_avg" << "\n"; + + fout << string(65, '-') << "\n"; +} + + +void ABstats::PrintStatsPosition( + ofstream& fout, + const int no, + const string& text, + const ABtracker& abt, + const ABtracker& divisor) const +{ + if (! abt.sumCum) return; - counter[no][depth]++; - if (side) - score[1][depth]++; + fout << setw(2) << (no == -1 ? "" : to_string(no)) << " " << + setw(20) << left << text << + setw(9) << right << abt.sum << + setw(6) << setprecision(1) << fixed << + 100. * abt.sum / static_cast(divisor.sum); + + if (abt.sum) + fout << setw(6) << setprecision(1) << fixed << + abt.sumWeighted / static_cast(abt.sum); else - score[0][depth]++; + fout << setw(6) << ""; + + fout << setw(9) << abt.sumCum << + setw(6) << setprecision(1) << fixed << + 100. * abt.sumCum / static_cast(divisor.sumCum) << + setw(6) << setprecision(1) << fixed << + abt.sumCumWeighted / static_cast(abt.sumCum) << "\n"; } -void ABstats::IncrNode(int depth) +void ABstats::PrintHeaderDepth(ofstream& fout) const { - nodes[depth]++; - allnodes++; + fout << setw(5) << right << "Depth" << + setw(7) << "Nodes" << + setw(7) << "Cumul" << + setw(6) << "Cum%" << + setw(6) << "Cumc%" << + setw(7) << "Branch" << "\n"; + + fout << string(38, '-') << "\n"; } -int ABstats::GetNodes() +void ABstats::PrintStatsDepth( + ofstream& fout, + const int depth, + const int cum) const { - return allnodes; + fout << setw(5) << depth << + setw(7) << ABnodes.list[depth] << + setw(7) << ABnodesCum.list[depth] << + setw(6) << setprecision(1) << fixed << + 100. * ABnodesCum.list[depth] / + static_cast(ABnodesCum.sumCum) << + setw(6) << setprecision(1) << fixed << + 100. * cum / static_cast(ABnodesCum.sumCum); + + // "Branching factor" from end of one trick to end of + // the previous trick. + if ((depth % 4 == 1) && + (depth < DDS_MAXDEPTH - 4) && + (ABnodesCum.list[depth + 4] > 0)) + fout << setw(6) << setprecision(2) << fixed << + ABnodesCum.list[depth] / + static_cast(ABnodesCum.list[depth + 4]); + fout << "\n"; } -void ABstats::PrintStats() +void ABstats::PrintAverageDepth( + ofstream& fout, + const ABtracker& ABsidesSum) const { - int sumScore1 = 0 , sumScore0 = 0; - int psumScore1 = 0 , psumScore0 = 0; - int sum[DDS_AB_POS], psum[DDS_AB_POS]; + fout << "\nTotal" << + setw(7) << right << ABnodes.sum << + setw(7) << ABnodesCum.sumCum << "\n"; - for (int p = 0; p < DDS_AB_POS; p++) - { - sum[p] = 0; - psum[p] = 0; - } + if (! ABnodesCum.sumCum) + return; - for (int d = 0; d < DDS_MAXDEPTH; d++) - { - sumScore1 += score[1][d]; - sumScore0 += score[0][d]; + fout << setw(5) << left << "Avg" << right; - psumScore1 += d * score[1][d]; - psumScore0 += d * score[0][d]; + if (ABnodes.sum) + fout << setw(7) << setprecision(1) << fixed << + ABnodes.sumWeighted / static_cast(ABnodes.sum); + else + fout << setw(7) << ""; + + fout << setw(7) << setprecision(1) << fixed << + ABnodesCum.sumCumWeighted / static_cast(ABnodesCum.sumCum) << + "\n\n"; + + fout << setw(5) << left << "Nodes" << + setw(7) << right << ABnodes.sum << + setw(7) << ABnodesCum.sumCum << "\n"; + + fout << setw(5) << left << "Ends" << + setw(7) << right << ABsidesSum.sum << + setw(7) << ABsidesSum.sumCum << "\n"; + + if (ABsidesSum.sum) + fout << setw(5) << left << "Ratio" << + setw(6) << right << setprecision(0) << fixed << + 100. * ABsidesSum.sum / static_cast(ABnodes.sum) << "%" << + setw(6) << setprecision(0) << fixed << + 100. * ABsidesSum.sumCum / static_cast(ABnodesCum.sumCum) << + "%\n\n"; +} - for (int p = 0; p < DDS_AB_POS; p++) - { - sum[p] += counter[p][d]; - psum[p] += d * counter[p][d]; - } - nodesCum[d] += nodes[d]; - } +void ABstats::PrintHeaderDetail(ofstream& fout) const +{ + fout << " d" << setw(7) << "Side1" << setw(7) << "Side0"; - allnodesCum += allnodes; + for (int p = 0; p < AB_SIZE; p++) + fout << setw(6) << p; - scoreCum[1] += sumScore1; - scoreCum[0] += sumScore0; + fout << "\n" << string(65, '-') << "\n"; +} - pscoreCum[1] += psumScore1; - pscoreCum[0] += psumScore0; - for (int p = 0; p < DDS_AB_POS; p++) - { - counterCum[p] += sum[p]; - pcounterCum[p] += psum[p]; - } +void ABstats::PrintStatsDetail( + ofstream& fout, + const int depth) const +{ + if (ABsides[1].list[depth] == 0 && ABsides[0].list[depth] == 0) + return; - int s = sumScore1 + sumScore0; - int cs = scoreCum[1] + scoreCum[0]; - if (s) - { - fprintf(fp, "%2s %-20s %8s %5s %5s %8s %5s %5s\n", - "No", - "Return", - "Count", - "%", - "d_avg", - "Cumul", - "%", - "d_avg"); - - fprintf(fp, "-----------------------------------"); - fprintf(fp, "------------------------------\n"); - - fprintf(fp, "%2s %-20s %8d %5.1f %5.1f %8d %5.1f %5.1f\n", - "", - "Side1", - sumScore1, - 100. * sumScore1 / static_cast(s), - psumScore1 / static_cast(s), - scoreCum[1], - 100. * scoreCum[1] / static_cast(cs), - pscoreCum[1] / static_cast(cs)); - - fprintf(fp, "%2s %-20s %8d %5.1f %5.1f %8d %5.1f %5.1f\n\n", - "", - "Side0", - sumScore0, - 100. * sumScore0 / static_cast(s), - psumScore0 / static_cast(s), - scoreCum[0], - 100. * scoreCum[0] / static_cast(cs), - pscoreCum[0] / static_cast(cs)); - - for (int p = 0; p < DDS_AB_POS; p++) - { - if (sum[p]) - { - fprintf(fp, "%2d %-20s %8d %5.1f %5.1f %8d %5.1f %5.1f\n", - p, - name[p], - sum[p], - 100. * sum[p] / static_cast(s), - psum[p] / static_cast(sum[p]), - counterCum[p], - 100. * counterCum[p] / static_cast(cs), - pcounterCum[p] / static_cast(counterCum[p])); - } - else if (counterCum[p]) - { - fprintf(fp, "%2d %-20s %8d %5.1f %5s %8d %5.1f %5.1f\n", - p, - name[p], - sum[p], - 100. * sum[p] / static_cast(s), - "", - counterCum[p], - 100. * counterCum[p] / static_cast(cs), - pcounterCum[p] / static_cast(counterCum[p])); - } - } - } + fout << setw(2) << depth << + setw(7) << ABsides[1].list[depth] << + setw(7) << ABsides[0].list[depth]; - fprintf(fp, "\n%5s %6s %6s %5s %5s %6s\n", - "Depth", - "Nodes", - "Cumul", - "Cum%", - "Cumc%", - "Branch"); + for (int p = 0; p < AB_SIZE; p++) + fout << setw(6) << ABplaces[p].list[depth]; + fout << "\n"; +} - fprintf(fp, "------------------------------------------\n"); - int c = 0; - double np = 0., ncp = 0.; - for (int d = DDS_MAXDEPTH - 1; d >= 0; d--) - { - if (nodesCum[d] == 0) - continue; +void ABstats::PrintSumDetail(ofstream& fout) const +{ + fout << string(65, '-') << "\n"; - c += nodesCum[d]; - np += d * nodes[d]; - ncp += d * nodesCum[d]; - - fprintf(fp, "%5d %6d %6d %5.1f %5.1f", - d, - nodes[d], - nodesCum[d], - 100. * nodesCum[d] / static_cast(allnodesCum), - 100. * c / static_cast(allnodesCum)); - - // "Branching factor" from end of one trick to end of - // the previous trick. - if ((d % 4 == 1) && - (d < DDS_MAXDEPTH - 4) && - (nodesCum[d + 4] > 0)) - fprintf(fp, " %5.2f", - nodesCum[d] / static_cast(nodesCum[d + 4])); - fprintf(fp, "\n"); - } + fout << setw(2) << "S" << + setw(7) << ABsides[1].sum << + setw(7) << ABsides[0].sum; - fprintf(fp, "\n%-5s %6d %6d\n", - "Total", allnodes, allnodesCum); + for (int p = 0; p < AB_SIZE; p++) + fout << setw(6) << ABplaces[p].sum; + fout << "\n\n"; +} - if (allnodes) - { - fprintf(fp, "%-5s %6.1f %6.1f\n", - "d_avg", - np / static_cast(allnodes), - ncp / static_cast(allnodesCum)); - } - else if (allnodesCum) + +void ABstats::PrintStats(ofstream& fout) +{ + ABtracker ABsidesSum; + ABsidesSum.sum = ABsides[1].sum + ABsides[0].sum; + ABsidesSum.sumCum = ABsides[1].sumCum + ABsides[0].sumCum; + + if (ABsidesSum.sum) { - fprintf(fp, "\n%-5s %6s %6.1f\n", - "Avg", - "-", - ncp / static_cast(allnodesCum)); - } + // First table: By side and position. - fprintf(fp, "%-5s %6d\n\n\n", "Diff", - allnodes - sumScore1 - sumScore0); + ABstats::PrintHeaderPosition(fout); -#ifdef DDS_AB_DETAILS - fprintf(fp, "%2s %6s %6s", - "d", - "Side1", - "Side0"); + ABstats::PrintStatsPosition(fout, -1, "Side1", ABsides[1], ABsidesSum); + ABstats::PrintStatsPosition(fout, -1, "Side0", ABsides[0], ABsidesSum); + fout << "\n"; + + for (int p = 0; p < AB_SIZE; p++) + ABstats::PrintStatsPosition(fout, p, name[p], ABplaces[p], ABsidesSum); + fout << "\n"; + } + + ABstats::PrintHeaderDepth(fout); - for (int p = 0; p < DDS_AB_POS; p++) - fprintf(fp, " %5d", p); - fprintf(fp, "\n------------------------------"); - fprintf(fp, "-----------------------------\n"); + // Second table: By depth. + int c = 0; for (int d = DDS_MAXDEPTH - 1; d >= 0; d--) { - if (score[1][d] == 0 && score[0][d] == 0) + if (ABnodesCum.list[d] == 0) continue; - fprintf(fp, "%2d %6d %6d", - d, score[1][d], score[0][d]); - - for (int p = 0; p < DDS_AB_POS; p++) - fprintf(fp, " %5d", counter[p][d]); - fprintf(fp, "\n"); + c += ABnodesCum.list[d]; + ABstats::PrintStatsDepth(fout, d, c); } - fprintf(fp, "--------------------------------"); - fprintf(fp, "---------------------------\n"); + ABstats::PrintAverageDepth(fout, ABsidesSum); - fprintf(fp, "%2s %6d %6d", - "S", sumScore1, sumScore0); - for (int p = 0; p < DDS_AB_POS; p++) - fprintf(fp, " %5d", sum[p]); - fprintf(fp, "\n\n"); -#endif +#ifdef DDS_AB_DETAILS + // Third table: All the detail. + + ABstats::PrintHeaderDetail(fout); + for (int d = DDS_MAXDEPTH - 1; d >= 0; d--) + ABstats::PrintStatsDetail(fout, d); + + ABstats::PrintSumDetail(fout); +#endif } + diff --git a/src/ABstats.h b/src/ABstats.h index 5395eb69..3312d410 100644 --- a/src/ABstats.h +++ b/src/ABstats.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,9 +10,14 @@ #ifndef DDS_ABSTATS_H #define DDS_ABSTATS_H -#include -#include -#include +#include +#include +#include + +#include "debug.h" + +using namespace std; + /* AB_COUNT is a macro that avoids the tedious #ifdef's at @@ -26,51 +31,97 @@ #endif -#define AB_TARGET_REACHED 0 -#define AB_DEPTH_ZERO 1 -#define AB_QUICKTRICKS 2 -#define AB_LATERTRICKS 3 -#define AB_MAIN_LOOKUP 4 -#define AB_SIDE_LOOKUP 5 -#define AB_MOVE_LOOP 6 - - +enum ABCountType +{ + AB_TARGET_REACHED = 0, + AB_DEPTH_ZERO = 1, + AB_QUICKTRICKS = 2, + AB_QUICKTRICKS_2ND = 3, + AB_LATERTRICKS = 4, + AB_MAIN_LOOKUP = 5, + AB_SIDE_LOOKUP = 6, + AB_MOVE_LOOP = 7, + AB_SIZE = 8 +}; #define DDS_MAXDEPTH 49 -#define DDS_LINE_LEN 20 -#define DDS_AB_POS 7 +struct ABtracker +{ + int list[DDS_MAXDEPTH]; + int sum; + int sumWeighted; + int sumCum; + int sumCumWeighted; +}; + class ABstats { private: - FILE * fp; - char fname[DDS_LINE_LEN]; - char name[DDS_AB_POS][40]; - int counter[DDS_AB_POS][DDS_MAXDEPTH]; - int counterCum[DDS_AB_POS]; - int pcounterCum[DDS_AB_POS]; - int score[2][DDS_MAXDEPTH]; - int scoreCum[2]; - int pscoreCum[2]; - int nodes[DDS_MAXDEPTH]; - int nodesCum[DDS_MAXDEPTH]; - int allnodes, - allnodesCum; - int iniDepth; + + string name[AB_SIZE]; + + // A node arises when a new move is generated. + // Not every move leads to an AB termination. + ABtracker ABnodes; + ABtracker ABnodesCum; + + // AB terminations are tracked by side and position. + ABtracker ABsides[2]; + ABtracker ABplaces[AB_SIZE]; + + void SetNames(); + + void PrintHeaderPosition(ofstream& fout) const; + + void PrintStatsPosition( + ofstream& fout, + const int no, + const string& text, + const ABtracker& abt, + const ABtracker& divisor) const; + + void PrintHeaderDepth(ofstream& fout) const; + + void PrintStatsDepth( + ofstream& fout, + const int depth, + const int cum) const; + + void PrintAverageDepth( + ofstream& fout, + const ABtracker& ABsidesSum) const; + + void PrintHeaderDetail(ofstream& fout) const; + + void PrintStatsDetail( + ofstream& fout, + const int depth) const; + + void PrintSumDetail(ofstream& fout) const; public: + ABstats(); + ~ABstats(); + void Reset(); + void ResetCum(); - void SetFile(char * fname); - void SetName(int no, char * name); - void IncrPos(int no, bool side, int depth); - void IncrNode(int depth); - int GetNodes(); - void PrintStats(); + + void IncrPos( + const ABCountType no, + const bool side, + const int depth); + + void IncrNode(const int depth); + + int GetNodes() const; + + void PrintStats(ofstream& fout); }; #endif diff --git a/src/COMMENT b/src/COMMENT index 83ae80d6..7e21dab9 100644 --- a/src/COMMENT +++ b/src/COMMENT @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ diff --git a/src/CalcTables.cpp b/src/CalcTables.cpp index a2fc181d..4763c934 100644 --- a/src/CalcTables.cpp +++ b/src/CalcTables.cpp @@ -2,19 +2,167 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include - -#include "dds.h" +#include "CalcTables.h" +#include "SolverIF.h" #include "SolveBoard.h" +#include "System.h" +#include "Memory.h" +#include "Scheduler.h" #include "PBN.h" +paramType cparam; + +extern System sysdep; +extern Memory memory; +extern Scheduler scheduler; + +int CalcAllBoardsN( + boards * bop, + solvedBoards * solvedp); + + +void CalcSingleCommon( + const int thrId, + const int bno) +{ + // Solves a single deal and strain for all four declarers. + + futureTricks fut; + cparam.bop->deals[bno].first = 0; + + START_THREAD_TIMER(thrId); + int res = SolveBoard( + cparam.bop->deals[bno], + cparam.bop->target[bno], + cparam.bop->solutions[bno], + cparam.bop->mode[bno], + &fut, + thrId); + + // SH: I'm making a terrible use of the fut structure here. + + if (res == 1) + cparam.solvedp->solvedBoard[bno].score[0] = fut.score[0]; + else + cparam.error = res; + + ThreadData * thrp = memory.GetPtr(static_cast(thrId)); + for (int k = 1; k < DDS_HANDS; k++) + { + int hint = (k == 2 ? fut.score[0] : 13 - fut.score[0]); + + cparam.bop->deals[bno].first = k; // Next declarer + + res = SolveSameBoard(thrp, cparam.bop->deals[bno], &fut, hint); + + if (res == 1) + cparam.solvedp->solvedBoard[bno].score[k] = fut.score[0]; + else + cparam.error = res; + } + END_THREAD_TIMER(thrId); +} + + +void CopyCalcSingle(const vector& crossrefs) +{ + for (unsigned i = 0; i < crossrefs.size(); i++) + { + if (crossrefs[i] == -1) + continue; + + START_THREAD_TIMER(thrId); + for (int k = 0; k < DDS_HANDS; k++) + cparam.solvedp->solvedBoard[i].score[k] = + cparam.solvedp->solvedBoard[ crossrefs[i] ].score[k]; + END_THREAD_TIMER(thrId); + } +} + + +void CalcChunkCommon( + const int thrId) +{ + // Solves each deal and strain for all four declarers. + vector fut; + fut.resize(static_cast(cparam.noOfBoards)); + + int index; + schedType st; + + while (1) + { + st = scheduler.GetNumber(thrId); + index = st.number; + if (index == -1) + break; + + if (st.repeatOf != -1) + { + START_THREAD_TIMER(thrId); + for (int k = 0; k < DDS_HANDS; k++) + { + cparam.bop->deals[index].first = k; + + cparam.solvedp->solvedBoard[index].score[k] = + cparam.solvedp->solvedBoard[ st.repeatOf ].score[k]; + } + END_THREAD_TIMER(thrId); + continue; + } + + CalcSingleCommon(thrId, index); + } +} + + +int CalcAllBoardsN( + boards * bop, + solvedBoards * solvedp) +{ + cparam.error = 0; + + if (bop->noOfBoards > MAXNOOFBOARDS) + return RETURN_TOO_MANY_BOARDS; + + cparam.bop = bop; + cparam.solvedp = solvedp; + cparam.noOfBoards = bop->noOfBoards; + + scheduler.RegisterRun(DDS_RUN_CALC, * bop); + sysdep.RegisterRun(DDS_RUN_CALC, * bop); + + for (int k = 0; k < MAXNOOFBOARDS; k++) + solvedp->solvedBoard[k].cards = 0; + + START_BLOCK_TIMER; + int retRun = sysdep.RunThreads(); + END_BLOCK_TIMER; + + if (retRun != RETURN_NO_FAULT) + return retRun; + + solvedp->noOfBoards = cparam.noOfBoards; + +#ifdef DDS_SCHEDULER + scheduler.PrintTiming(); +#endif + + if (cparam.error == 0) + return RETURN_NO_FAULT; + else + return cparam.error; +} + + + int STDCALL CalcDDtable( ddTableDeal tableDeal, ddTableResults * tablep) @@ -34,9 +182,9 @@ int STDCALL CalcDDtable( } int ind = 0; - bo.noOfBoards = 5; + bo.noOfBoards = DDS_STRAINS; - for (int tr = 4; tr >= 0; tr--) + for (int tr = DDS_STRAINS-1; tr >= 0; tr--) { dl.trump = tr; bo.deals[ind] = dl; @@ -46,25 +194,23 @@ int STDCALL CalcDDtable( ind++; } - int res = SolveAllBoardsN(&bo, &solved, 4, 1); - if (res == 1) + int res = CalcAllBoardsN(&bo, &solved); + if (res != 1) + return res; + + for (int index = 0; index < DDS_STRAINS; index++) { - for (int index = 0; index < 5; index++) - { - int strain = bo.deals[index].trump; + int strain = bo.deals[index].trump; - // SH: I'm making a terrible use of the fut structure here. + // SH: I'm making a terrible use of the fut structure here. - for (int first = 0; first < DDS_HANDS; first++) - { - tablep->resTable[strain][ rho[first] ] = - 13 - solved.solvedBoard[index].score[first]; - } + for (int first = 0; first < DDS_HANDS; first++) + { + tablep->resTable[strain][ rho[first] ] = + 13 - solved.solvedBoard[index].score[first]; } - return RETURN_NO_FAULT; } - - return res; + return RETURN_NO_FAULT; } @@ -86,7 +232,7 @@ int STDCALL CalcAllTables( int count = 0; bool okey = false; - for (int k = 0; k < 5; k++) + for (int k = 0; k < DDS_STRAINS; k++) { if (!trumpFilter[k]) { @@ -107,7 +253,7 @@ int STDCALL CalcAllTables( for (int m = 0; m < dealsp->noOfTables; m++) { - for (int tr = 4; tr >= 0; tr--) + for (int tr = DDS_STRAINS-1; tr >= 0; tr--) { if (trumpFilter[tr]) continue; @@ -135,7 +281,7 @@ int STDCALL CalcAllTables( bo.noOfBoards = lastIndex + 1; - int res = SolveAllBoardsN(&bo, &solved, 4, 1); + int res = CalcAllBoardsN(&bo, &solved); if (res != 1) return res; @@ -180,17 +326,14 @@ int STDCALL CalcAllTablesPBN( ddTablesRes * resp, allParResults * presp) { - int res; ddTableDeals dls; - for (int k = 0; k < dealsp->noOfTables; k++) if (ConvertFromPBN(dealsp->deals[k].cards, dls.deals[k].cards) != 1) return RETURN_PBN_FAULT; dls.noOfTables = dealsp->noOfTables; - res = CalcAllTables(&dls, mode, trumpFilter, resp, presp); - + int res = CalcAllTables(&dls, mode, trumpFilter, resp, presp); return res; } @@ -200,14 +343,21 @@ int STDCALL CalcDDtablePBN( ddTableResults * tablep) { ddTableDeal tableDeal; - int res; - if (ConvertFromPBN(tableDealPBN.cards, tableDeal.cards) != 1) return RETURN_PBN_FAULT; - res = CalcDDtable(tableDeal, tablep); - + int res = CalcDDtable(tableDeal, tablep); return res; } +void DetectCalcDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs) +{ + // Could save a little bit of time with a dedicated checker that + // only looks at the cards. + return DetectSolveDuplicates(bds, uniques, crossrefs); +} + diff --git a/src/CalcTables.h b/src/CalcTables.h new file mode 100644 index 00000000..47d11537 --- /dev/null +++ b/src/CalcTables.h @@ -0,0 +1,35 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_CALCTABLES_H +#define DDS_CALCTABLES_H + +#include + +#include "dds.h" + +using namespace std; + + +void CalcSingleCommon( + const int thrID, + const int bno); + +void CopyCalcSingle( + const vector& crossrefs); + +void CalcChunkCommon( + const int thrId); + +void DetectCalcDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs); + +#endif diff --git a/src/DealerPar.cpp b/src/DealerPar.cpp index 0baab5db..46facd7c 100644 --- a/src/DealerPar.cpp +++ b/src/DealerPar.cpp @@ -2,15 +2,21 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ +#include +#include +#include +#include #include "dds.h" +using namespace std; + /* First index: 0 nonvul, 1 vul. Second index: tricks down */ int DOUBLED_SCORES[2][14] = @@ -64,7 +70,7 @@ int FLOOR_CONTRACT[36] = 31, 32, 33, 34, 35 }; -char NUMBER_TO_CONTRACT[36][3] = +const vector NUMBER_TO_CONTRACT = { "0", "1C", "1D", "1H", "1S", "1N", @@ -76,7 +82,7 @@ char NUMBER_TO_CONTRACT[36][3] = "7C", "7D", "7H", "7S", "7N" }; -char NUMBER_TO_PLAYER[4][2] = { "N", "E", "S", "W" }; +const vector NUMBER_TO_PLAYER = { "N", "E", "S", "W" }; /* First index is vul: none, both, NS, EW. Second index is vul (0, 1) for NS and then EW. */ @@ -113,53 +119,51 @@ struct list_type void survey_scores( - ddTableResults * tablep, - int dealer, - int vul_by_side[2], - data_type * data, - int * num_candidates, - list_type list[2][5]); + const ddTableResults& table, + const int dealer, + const int vul_by_side[2], + data_type& data, + int& num_candidates, + list_type list[2][DDS_STRAINS]); void best_sacrifice( - ddTableResults * tablep, - int side, - int no, - int dno, - int dealer, - list_type list[2][5], + const ddTableResults& table, + const int side, + const int no, + const int dno, + const int dealer, + const list_type list[2][5], int sacr[5][5], - int * best_down); + int& best_down); void sacrifices_as_text( - ddTableResults * tablep, - int side, - int dealer, - int best_down, - int no_decl, - int dno, - list_type list[2][5], - int sacr[5][5], + const ddTableResults& table, + const int side, + const int dealer, + const int best_down, + const int no_decl, + const int dno, + const list_type list[2][5], + const int sacr[5][5], char results[10][10], - int * res_no); + int& res_no); void reduce_contract( - int * no, - int down, - int * plus); + int& no, + const int down, + int& plus); -void contract_as_text( - ddTableResults * tablep, - int side, - int no, - int dno, - int down, - char str[10]); +string contract_as_text( + const ddTableResults& table, + const int side, + const int no, + const int dno, + const int down); -void sacrifice_as_text( - int no, - int pno, - int down, - char str[10]); +string sacrifice_as_text( + const int no, + const int pno, + const int down); @@ -172,9 +176,9 @@ int STDCALL DealerPar( /* dealer 0: North 1: East 2: South 3: West */ /* vulnerable 0: None 1: Both 2: NS 3: EW */ - int * vul_by_side = VUL_LOOKUP[vulnerable]; + int const * vul_by_side = VUL_LOOKUP[vulnerable]; data_type data; - list_type list[2][5]; + list_type list[2][DDS_STRAINS]; /* First we find the side entitled to a plus score (primacy) and some statistics for each constructively bid (undoubled) @@ -182,13 +186,13 @@ int STDCALL DealerPar( int num_cand; - survey_scores(tablep, dealer, vul_by_side, &data, &num_cand, list); + survey_scores(* tablep, dealer, vul_by_side, data, num_cand, list); int side = data.primacy; if (side == -1) { presp->number = 1; - sprintf(presp->contracts[0], "%s", "pass"); + strcpy(presp->contracts[0], "pass"); return RETURN_NO_FAULT; } @@ -199,10 +203,11 @@ int STDCALL DealerPar( int down = 0; int sac_found = 0; - int type[5], sac_gap[5]; + int type[DDS_STRAINS], sac_gap[DDS_STRAINS]; int best_down = 0; - int sacr[5][5] = { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} + int sacr[DDS_STRAINS][DDS_STRAINS] = + { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }; for (int n = 0; n < num_cand; n++) @@ -211,7 +216,7 @@ int STDCALL DealerPar( int dno = lists[n].dno; int target = DOWN_TARGET[no][vul_no]; - best_sacrifice(tablep, side, no, dno, dealer, list, sacr, &down); + best_sacrifice(* tablep, side, no, dno, dealer, list, sacr, down); if (down <= target) { @@ -252,10 +257,10 @@ int STDCALL DealerPar( { if (type[n] != 1 || lists[n].score != best_plus) continue; int no = lists[n].no, plus; - reduce_contract(&no, sac_gap[n], &plus); + reduce_contract(no, sac_gap[n], plus); - contract_as_text(tablep, side, no, lists[n].dno, - plus, presp->contracts[res_no]); + strcpy(presp->contracts[res_no], + contract_as_text(* tablep, side, no, lists[n].dno, plus).c_str()); res_no++; } } @@ -269,9 +274,9 @@ int STDCALL DealerPar( for (int n = 0; n < num_cand; n++) { if (type[n] != 0 || lists[n].down != best_down) continue; - sacrifices_as_text(tablep, side, dealer, best_down, + sacrifices_as_text(* tablep, side, dealer, best_down, lists[n].no, lists[n].dno, list, sacr, - presp->contracts, &res_no); + presp->contracts, res_no); } } presp->number = res_no; @@ -280,12 +285,12 @@ int STDCALL DealerPar( void survey_scores( - ddTableResults * tablep, - int dealer, - int vul_by_side[2], - data_type * data, - int * num_candidates, - list_type list[2][5]) + const ddTableResults& table, + const int dealer, + const int vul_by_side[2], + data_type& data, + int& num_candidates, + list_type list[2][DDS_STRAINS]) { /* When this is done, data has added the following entries: @@ -314,15 +319,15 @@ void survey_scores( int dearest_making_no = 0; int dearest_score = 0; - for (int dno = 0; dno <= 4; dno++) + for (int dno = 0; dno < DDS_STRAINS; dno++) { list_type * slist = &list[side][dno]; - int * t = tablep->resTable[ DENOM_ORDER[dno] ]; - int a = t[side]; - int b = t[side + 2]; - int best = (a > b ? a : b); + int const * t = table.resTable[ DENOM_ORDER[dno] ]; + const int a = t[side]; + const int b = t[side + 2]; + const int best = (a > b ? a : b); - int no = 5 * (best - 7) + dno + 1; + const int no = 5 * (best - 7) + dno + 1; slist->no = no; /* May be negative! */ if (best < 7) @@ -331,7 +336,7 @@ void survey_scores( continue; } - int score = SCORES[no][ vul_by_side[side] ]; + const int score = SCORES[no][ vul_by_side[side] ]; slist->score = score; slist->dno = dno; slist->tricks = best; @@ -352,15 +357,15 @@ void survey_scores( highest_making_no = no; } } - data_type * sside = &stats[side]; - sside->highest_making_no = highest_making_no; - sside->dearest_making_no = dearest_making_no; - sside->dearest_score = dearest_score; + data_type& sside = stats[side]; + sside.highest_making_no = highest_making_no; + sside.dearest_making_no = dearest_making_no; + sside.dearest_score = dearest_score; } int primacy = 0; - int s0 = stats[0].highest_making_no; - int s1 = stats[1].highest_making_no; + const int s0 = stats[0].highest_making_no; + const int s1 = stats[1].highest_making_no; if (s0 > s1) { primacy = 0; @@ -371,19 +376,20 @@ void survey_scores( } else if (s0 == 0) { - data->primacy = -1; + data.primacy = -1; return; } else { /* Special case, depends who can bid it first. */ - int dno = (s0 - 1) % 5; - int t_max = list[0][dno].tricks; - int * t = tablep->resTable[ DENOM_ORDER[dno] ]; + const int dno = (s0 - 1) % 5; + const int t_max = list[0][dno].tricks; + int const * t = table.resTable[ DENOM_ORDER[dno] ]; for (int pno = dealer; pno <= dealer + 3; pno++) { - if (t[pno % 4] != t_max) continue; + if (t[pno % 4] != t_max) + continue; primacy = pno % 2; break; } @@ -391,26 +397,27 @@ void survey_scores( data_type * sside = &stats[primacy]; - int dm_no = sside->dearest_making_no; - data->primacy = primacy; - data->highest_making_no = sside->highest_making_no; - data->dearest_making_no = dm_no; - data->dearest_score = sside->dearest_score; + const int dm_no = sside->dearest_making_no; + data.primacy = primacy; + data.highest_making_no = sside->highest_making_no; + data.dearest_making_no = dm_no; + data.dearest_score = sside->dearest_score; - int vul_primacy = vul_by_side[primacy]; - int vul_other = vul_by_side[1 - primacy]; - data->vul_no = VUL_TO_NO[vul_primacy][vul_other]; + const int vul_primacy = vul_by_side[primacy]; + const int vul_other = vul_by_side[1 - primacy]; + data.vul_no = VUL_TO_NO[vul_primacy][vul_other]; /* Sort the scores in descending order of contract number, i.e. first by score and second by contract number in case the score is the same. Primitive bubble sort... */ - int n = 5; + int n = DDS_STRAINS; do { int new_n = 0; for (int i = 1; i < n; i++) { - if (list[primacy][i - 1].no > list[primacy][i].no) continue; + if (list[primacy][i - 1].no > list[primacy][i].no) + continue; list_type temp = list[primacy][i - 1]; list[primacy][i - 1] = list[primacy][i]; @@ -422,53 +429,57 @@ void survey_scores( } while (n > 0); - *num_candidates = 5; - for (n = 0; n <= 4; n++) + num_candidates = DDS_STRAINS; + for (n = 0; n < DDS_STRAINS; n++) { - if (list[primacy][n].no < dm_no) (*num_candidates)--; + if (list[primacy][n].no < dm_no) + num_candidates--; } } void best_sacrifice( - ddTableResults * tablep, - int side, - int no, - int dno, - int dealer, - list_type list[2][5], - int sacr_table[5][5], - int * best_down) + const ddTableResults& table, + const int side, + const int no, + const int dno, + const int dealer, + const list_type list[2][DDS_STRAINS], + int sacr_table[DDS_STRAINS][DDS_STRAINS], + int& best_down) { - int other = 1 - side; - list_type * sacr_list = list[other]; - *best_down = BIGNUM; + const int other = 1 - side; + list_type const * sacr_list = list[other]; + best_down = BIGNUM; for (int eno = 0; eno <= 4; eno++) { - list_type sacr = sacr_list[eno]; + const list_type sacr = sacr_list[eno]; int down = BIGNUM; if (eno == dno) { - int t_max = static_cast((no + 34) / 5); - int * t = tablep->resTable[ DENOM_ORDER[dno] ]; + const int t_max = static_cast((no + 34) / 5); + int const * t = table.resTable[ DENOM_ORDER[dno] ]; int incr_flag = 0; for (int pno = dealer; pno <= dealer + 3; pno++) { - int diff = t_max - t[pno % 4]; - int s = pno % 2; + const int diff = t_max - t[pno % 4]; + const int s = pno % 2; if (s == side) { - if (diff == 0) incr_flag = 1; + if (diff == 0) + incr_flag = 1; } else { - int local = diff + incr_flag; - if (local < down) down = local; + const int local = diff + incr_flag; + if (local < down) + down = local; } } - if (sacr.no + 5 * down > 35) down = BIGNUM; + if (sacr.no + 5 * down > 35) + down = BIGNUM; } else { @@ -476,25 +487,26 @@ void best_sacrifice( if (sacr.no + 5 * down > 35) down = BIGNUM; } sacr_table[dno][eno] = down; - if (down < *best_down) *best_down = down; + if (down < best_down) + best_down = down; } } void sacrifices_as_text( - ddTableResults * tablep, - int side, - int dealer, - int best_down, - int no_decl, - int dno, - list_type list[2][5], - int sacr[5][5], + const ddTableResults& table, + const int side, + const int dealer, + const int best_down, + const int no_decl, + const int dno, + const list_type list[2][DDS_STRAINS], + const int sacr[DDS_STRAINS][DDS_STRAINS], char results[10][10], - int * res_no) + int& res_no) { - int other = 1 - side; - list_type * sacr_list = list[other]; + const int other = 1 - side; + list_type const * sacr_list = list[other]; for (int eno = 0; eno <= 4; eno++) { @@ -503,15 +515,15 @@ void sacrifices_as_text( if (eno != dno) { - int no_sac = sacr_list[eno].no + 5 * best_down; - contract_as_text(tablep, other, no_sac, eno, -best_down, - results[*res_no]); - (*res_no)++; + const int no_sac = sacr_list[eno].no + 5 * best_down; + strcpy(results[res_no], + contract_as_text(table, other, no_sac, eno, -best_down).c_str()); + res_no++; continue; } - int t_max = static_cast((no_decl + 34) / 5); - int * t = tablep->resTable[ DENOM_ORDER[dno] ]; + const int t_max = static_cast((no_decl + 34) / 5); + int const * t = table.resTable[ DENOM_ORDER[dno] ]; int incr_flag = 0; int p_hit = 0; int pno_list[2], sac_list[2]; @@ -534,37 +546,37 @@ void sacrifices_as_text( } } - int ns0 = sac_list[0]; + const int ns0 = sac_list[0]; if (p_hit == 1) { - sacrifice_as_text(ns0, pno_list[0], best_down, - results[*res_no]); - (*res_no)++; + strcpy(results[res_no], + sacrifice_as_text(ns0, pno_list[0], best_down).c_str()); + res_no++; continue; } - int ns1 = sac_list[1]; + const int ns1 = sac_list[1]; if (ns0 == ns1) { /* Both players */ - contract_as_text(tablep, other, ns0, eno, -best_down, - results[*res_no]); - (*res_no)++; + strcpy(results[res_no], + contract_as_text(table, other, ns0, eno, -best_down).c_str()); + res_no++; continue; } - int p = (ns0 < ns1 ? 0 : 1); - sacrifice_as_text(sac_list[p], pno_list[p], best_down, - results[*res_no]); - (*res_no)++; + const int p = (ns0 < ns1 ? 0 : 1); + strcpy(results[res_no], + sacrifice_as_text(sac_list[p], pno_list[p], best_down).c_str()); + res_no++; } } void reduce_contract( - int * no, - int sac_gap, - int * plus) + int& no, + const int sac_gap, + int& plus) { /* Could be that we found 4C just making, but it would be enough to bid 2C +2. But we don't want to bid so low that @@ -573,12 +585,12 @@ void reduce_contract( if (sac_gap >= -1) { /* No scope to reduce. */ - *plus = 0; + plus = 0; return; } /* This is the lowest contract that we could reduce to. */ - int flr = FLOOR_CONTRACT[*no]; + int flr = FLOOR_CONTRACT[no]; /* As such, declarer could reduce the contract by down+1 levels (where down is negative) and still the opponent's sacrifice @@ -586,47 +598,40 @@ void reduce_contract( this can go wrong: 1M+1 and 2M= both pay +90, but 3m*-2 is a bad sacrifice against 2M=, while 2m*-1 would be a good sacrifice against 1M+1. */ - int no_sac_level = *no + 5 * (sac_gap + 1); + int no_sac_level = no + 5 * (sac_gap + 1); int new_no = (no_sac_level > flr ? no_sac_level : flr); - *plus = (*no - new_no) / 5; - *no = new_no; + plus = (no - new_no) / 5; + no = new_no; } -void contract_as_text( - ddTableResults * tablep, - int side, - int no, - int dno, - int delta, - char str[10]) +string contract_as_text( + const ddTableResults& table, + const int side, + const int no, + const int dno, + const int delta) { - int * t = tablep->resTable[ DENOM_ORDER[dno] ]; - int ta = t[side]; - int tb = t[side + 2]; - int t_max = (ta > tb ? ta : tb); - - char d[4] = ""; - if (delta != 0) - sprintf(d, "%+d", delta); - - sprintf(str, "%s%s%s%s%s", - NUMBER_TO_CONTRACT[no], - (delta < 0 ? "*-" : "-"), - (ta == t_max ? NUMBER_TO_PLAYER[side] : ""), - (tb == t_max ? NUMBER_TO_PLAYER[side + 2] : ""), - d); + int const * t = table.resTable[ DENOM_ORDER[dno] ]; + const int ta = t[side]; + const int tb = t[side + 2]; + const int t_max = (ta > tb ? ta : tb); + + return NUMBER_TO_CONTRACT[static_cast(no)] + + (delta < 0 ? "*-" : "-") + + (ta == t_max ? NUMBER_TO_PLAYER[static_cast(side)] : "") + + (tb == t_max ? NUMBER_TO_PLAYER[static_cast(side + 2)] : "") + + (delta > 0 ? "+" : "") + + (delta == 0 ? "" : to_string(delta)); } -void sacrifice_as_text( - int no, - int pno, - int down, - char str[10]) +string sacrifice_as_text( + const int no, + const int pno, + const int down) { - sprintf(str, "%s*-%s-%d", - NUMBER_TO_CONTRACT[no], - NUMBER_TO_PLAYER[pno], - down); + return NUMBER_TO_CONTRACT[static_cast(no)] + "-" + + NUMBER_TO_PLAYER[static_cast(pno)] + "-" + + to_string(down); } diff --git a/src/Exports.def b/src/Exports.def index 1566f0ca..8098e882 100644 --- a/src/Exports.def +++ b/src/Exports.def @@ -2,6 +2,10 @@ LIBRARY dds EXPORTS SetMaxThreads SetMaxThreads@4 = SetMaxThreads + SetThreading + SetThreading@4 = SetThreading + SetResources + SetResources@8 = SetResources FreeMemory FreeMemory@0 = FreeMemory ErrorMessage diff --git a/src/File.cpp b/src/File.cpp new file mode 100644 index 00000000..56f359df --- /dev/null +++ b/src/File.cpp @@ -0,0 +1,63 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +// Keeps track of debug files without opening and closing them +// all the time, and without creating empty files. + + +#include "File.h" + + +File::File() +{ + File::Reset(); +} + + +File::~File() +{ + File::Close(); +} + + +void File::Reset() +{ + fname = ""; + fileOpen = false; +} + + +void File::SetName(const string& fnameIn) +{ + // No error checking! + fname = fnameIn; +} + + +ofstream& File::GetStream() +{ + if (! fileOpen) + { + fout.open(fname); + fileOpen = true; + } + + return fout; +} + + +void File::Close() +{ + if (fileOpen) + { + fout.close(); + fileOpen = false; + } +} + diff --git a/src/File.h b/src/File.h new file mode 100644 index 00000000..38a24290 --- /dev/null +++ b/src/File.h @@ -0,0 +1,44 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_FILE_H +#define DDS_FILE_H + +#include +#include + +using namespace std; + + +class File +{ + private: + + string fname; + + bool fileOpen; + + ofstream fout; + + public: + + File(); + + ~File(); + + void Reset(); + + void SetName(const string& fnameIn); + + ofstream& GetStream(); + + void Close(); +}; + +#endif diff --git a/src/Init.cpp b/src/Init.cpp index a102c2d6..5c2fff0c 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -2,30 +2,34 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include "dds.h" -#include "threadmem.h" +#include +#include + #include "Init.h" -#include "Stats.h" -#include "ABsearch.h" +#include "System.h" #include "Scheduler.h" +#include "ThreadMgr.h" +#include "debug.h" + + +System sysdep; +Memory memory; +Scheduler scheduler; +ThreadMgr threadMgr; + void InitConstants(); void InitDebugFiles(); -double ConstantMemoryUsed(); - void FreeThreadMem(); -localVarType localVar[MAXNOOFTHREADS]; -Scheduler scheduler; -int noOfThreads; int lho[DDS_HANDS] = { 1, 2, 3, 0 }; int rho[DDS_HANDS] = { 3, 0, 1, 2 }; @@ -74,151 +78,115 @@ moveGroupType groupData[8192]; int _initialized = 0; + void STDCALL SetMaxThreads( int userThreads) { - if (! _initialized) - noOfThreads = 0; - - InitTimer(); - InitTimerList(); - - // First figure out how much memory we have available - // and how many cores the system has. - int oldNoOfThreads = noOfThreads; - unsigned long long kilobytesFree = 0; - int ncores = 1; - -#ifdef DDS_THREADS_SINGLE - noOfThreads = 1; -#else -#if defined(_WIN32) || defined(__CYGWIN__) - /* Using GlobalMemoryStatusEx instead of GlobalMemoryStatus - was suggested by Lorne Anderson. */ - MEMORYSTATUSEX statex; - statex.dwLength = sizeof(statex); - GlobalMemoryStatusEx(&statex); - kilobytesFree = static_cast( - statex.ullTotalPhys / 1024); - - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - ncores = static_cast(sysinfo.dwNumberOfProcessors); -#endif - -#ifdef __APPLE__ - // The code for Mac OS X was suggested by Matthew Kidd. - - // This is physical memory, rather than "free" memory as below for Linux. - // Always leave 0.5 GB for the OS and other stuff. It would be better to - // find free memory (how?) but in practice the number of cores rather than - // free memory is almost certainly the limit for Macs which have - // standardized hardware (whereas say a 32 core Linux server is hardly - // unusual). - FILE * fifo = popen("sysctl -n hw.memsize", "r"); - fscanf(fifo, "%lld", &kilobytesFree); - fclose(fifo); - - kilobytesFree /= 1024; - if (kilobytesFree > 500000) - { - kilobytesFree -= 500000; - } - - ncores = sysconf(_SC_NPROCESSORS_ONLN); -#endif - -#ifdef __linux__ - /* The code for linux was suggested by Antony Lee. */ - FILE * fifo = popen( - "free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r"); - int ignore = fscanf(fifo, "%llu", &kilobytesFree); - fclose(fifo); - - ncores = sysconf(_SC_NPROCESSORS_ONLN); -#endif -#endif + SetResources(0, userThreads); +} - // 70%, capped at 2 GB. - int kilobytesUsable = static_cast(0.70 * kilobytesFree); - if (kilobytesUsable > 2000000) - kilobytesUsable = 2000000; - if (userThreads) - noOfThreads = Min(ncores, userThreads); +void STDCALL SetResources( + int maxMemoryMB, + int maxThreadsIn) +{ + // Figure out system resources. + int ncores; + unsigned long long kilobytesFree; + sysdep.GetHardware(ncores, kilobytesFree); + + // Memory usage will be limited to the lower of: + // - maxMemoryMB + 30% (if given; statistically this works out) + // - 70% of free memory + // - 1800 MB if we're on a 32-bit system. + + const int memMaxGivenMB = (maxMemoryMB == 0 ? 1000000 : + static_cast(1.3 * maxMemoryMB)); + const int memMaxFreeMB = static_cast(0.70 * kilobytesFree / 1024); + const int memMax32bMB = (sizeof(void *) == 4 ? 1800 : 1000000); + + int memMaxMB = min(memMaxGivenMB, memMaxFreeMB); + memMaxMB = min(memMaxMB, memMax32bMB); + + // The number of threads will be limited by: + // - If threading set as single-threaded or compiled only + // single-threaded: 1 + // - If threading set as one of the IMPL variants: ncores + // whatever the user says (as we currently don't have control) + // - Otherwise the lower of maxThreads and ncores + + int thrMax; + if (sysdep.IsSingleThreaded()) + thrMax = 1; + else if (sysdep.IsIMPL() || maxThreadsIn <= 0) + thrMax = ncores; else - noOfThreads = ncores; - - int deltaThreads = noOfThreads - oldNoOfThreads; + thrMax = min(maxThreadsIn, ncores); - int mem_def, mem_max; + // For simplicity we won't vary the amount of memory per thread + // in the small and large versions. - if (deltaThreads <= 0) - { - // We already have the memory. - mem_def = THREADMEM_DEF_MB; - mem_max = THREADMEM_MAX_MB; - } - else if (kilobytesUsable == 0 || noOfThreads == 1) - { - // Take our chances with default values. - mem_def = THREADMEM_DEF_MB; - mem_max = THREADMEM_MAX_MB; - } - else if (kilobytesUsable >= 1024 * THREADMEM_MAX_MB * deltaThreads) + int noOfThreads, noOfLargeThreads, noOfSmallThreads; + if (thrMax * THREADMEM_LARGE_MAX_MB <= memMaxMB) { - // Comfortable. - mem_def = THREADMEM_DEF_MB; - mem_max = THREADMEM_MAX_MB; + // We have enough memory for the maximum number of large threads. + noOfThreads = thrMax; + noOfLargeThreads = thrMax; + noOfSmallThreads = 0; } - else if (kilobytesUsable >= 1024 * THREADMEM_DEF_MB * deltaThreads) - { - // Slightly less comfortable, cap the maximum, - // but make the maximum number of threads. - mem_def = THREADMEM_DEF_MB; - mem_max = THREADMEM_DEF_MB; + else if (thrMax * THREADMEM_SMALL_MAX_MB > memMaxMB) + { + // We don't even have enough memory for only small threads. + // We'll limit the number of threads. + noOfThreads = static_cast(memMaxMB / + static_cast(THREADMEM_SMALL_MAX_MB)); + noOfLargeThreads = 0; + noOfSmallThreads = noOfThreads; } else { - // Limit the number of threads to the available memory. - int fittingThreads = static_cast( kilobytesUsable / - ( static_cast(1024. * THREADMEM_DEF_MB) ) ); + // We'll have a mixture with as many large threads as possible. + const double d = static_cast( + THREADMEM_LARGE_MAX_MB - THREADMEM_SMALL_MAX_MB); - noOfThreads = Max(fittingThreads, 1); - mem_def = THREADMEM_DEF_MB; - mem_max = THREADMEM_DEF_MB; + noOfThreads = thrMax; + noOfLargeThreads = static_cast( + (memMaxMB - thrMax * THREADMEM_SMALL_MAX_MB) / d); + noOfSmallThreads = thrMax - noOfLargeThreads; } - for (int k = 0; k < noOfThreads; k++) - { - localVar[k].transTable.SetMemoryDefault(mem_def); - localVar[k].transTable.SetMemoryMaximum(mem_max); - } + sysdep.RegisterParams(noOfThreads, memMaxMB); - if (noOfThreads == oldNoOfThreads) - { - // Must already have TT allocated. - } - else if (noOfThreads > oldNoOfThreads) - { - for (int k = oldNoOfThreads; k < noOfThreads; k++) - localVar[k].transTable.MakeTT(); - } - else - { - for (int k = noOfThreads; k < oldNoOfThreads; k++) - localVar[k].transTable.ReturnAllMemory(); - } + scheduler.RegisterThreads(noOfThreads); + + // Clear the thread memory and fill it up again. + memory.Resize(0, DDS_TT_SMALL, 0, 0); + if (noOfLargeThreads > 0) + memory.Resize(static_cast(noOfLargeThreads), + DDS_TT_LARGE, THREADMEM_LARGE_DEF_MB, THREADMEM_LARGE_MAX_MB); + if (noOfSmallThreads > 0) + memory.Resize(static_cast(noOfThreads), + DDS_TT_SMALL, THREADMEM_SMALL_DEF_MB, THREADMEM_SMALL_MAX_MB); + + threadMgr.Reset(noOfThreads); + + InitDebugFiles(); if (! _initialized) { _initialized = 1; InitConstants(); - InitDebugFiles(); } } +int STDCALL SetThreading( + int code) +{ + return sysdep.PreferThreading(static_cast(code)); +} + + void InitConstants() { // highestRank[aggr] is the highest absolute rank in the @@ -246,8 +214,8 @@ void InitConstants() } } - /* The use of the counttable to give the number of bits set to - one in an integer follows an implementation by Thomas Andrews. */ + // The use of the counttable to give the number of bits set to + // one in an integer follows an implementation by Thomas Andrews. // counttable[aggr] is the number of '1' bits (binary weight) // in aggr. @@ -384,30 +352,35 @@ void InitConstants() void InitDebugFiles() { - for (int k = 0; k < noOfThreads; k++) + for (unsigned thrId = 0; thrId < sysdep.NumThreads(); thrId++) { + ThreadData * thrp = memory.GetPtr(thrId); + UNUSED(thrp); // To avoid compile errors + const string send = to_string(thrId) + DDS_DEBUG_SUFFIX; + #ifdef DDS_TOP_LEVEL - InitFileTopLevel(k); + thrp->fileTopLevel.SetName(DDS_TOP_LEVEL_PREFIX + send); #endif #ifdef DDS_AB_STATS - InitFileABstats(k); + thrp->fileABstats.SetName(DDS_AB_STATS_PREFIX + send); #endif #ifdef DDS_AB_HITS - InitFileABhits(k); + thrp->fileRetrieved.SetName(DDS_AB_HITS_RETRIEVED_PREFIX + send); + thrp->fileStored.SetName(DDS_AB_HITS_STORED_PREFIX + send); #endif #ifdef DDS_TT_STATS - InitFileTTstats(k); + thrp->fileTTstats.SetName(DDS_TT_STATS_PREFIX + send); #endif #ifdef DDS_TIMING - InitFileTimer(k); + thrp->fileTimerList.SetName(DDS_TIMING_PREFIX + send); #endif #ifdef DDS_MOVES - InitFileMoves(k); + thrp->fileMoves.SetName(DDS_MOVES_PREFIX + send); #endif } @@ -419,21 +392,41 @@ void InitDebugFiles() void CloseDebugFiles() { - for (int k = 0; k < noOfThreads; k++) + for (unsigned thrId = 0; thrId < sysdep.NumThreads(); thrId++) { + ThreadData * thrp = memory.GetPtr(thrId); + UNUSED(thrp); // To avoid compiler warning + #ifdef DDS_TOP_LEVEL - CloseFileTopLevel(k); + thrp->fileTopLevel.Close(); +#endif + +#ifdef DDS_AB_STATS + thrp->fileABstats.Close(); #endif #ifdef DDS_AB_HITS - CloseFileABhits(k); + thrp->fileRetrieved.Close(); + thrp->fileStored.Close(); +#endif + +#ifdef DDS_TT_STATS + thrp->fileTTstats.Close(); +#endif + +#ifdef DDS_TIMING + thrp->fileTimerList.Close(); +#endif + +#ifdef DDS_MOVES + thrp->fileMoves.Close(); #endif } } void SetDeal( - localVarType * thrp) + ThreadData * thrp) { /* Initialization of the rel structure is inspired by a solution given by Thomas Andrews */ @@ -468,13 +461,13 @@ void SetDeal( void SetDealTables( - localVarType * thrp) + ThreadData * thrp) { unsigned int topBitRank = 1; unsigned int topBitNo = 2; - /* Initialization of the rel structure is inspired by - a solution given by Thomas Andrews */ + // Initialization of the rel structure is inspired by + // a solution given by Thomas Andrews. // rel[aggr].absRank[absolute rank][suit].hand is the hand // (N = 0, E = 1 etc.) which holds the absolute rank in @@ -511,7 +504,7 @@ void SetDealTables( } } - thrp->transTable.Init(handLookup); + thrp->transTable->Init(handLookup); relRanksType * relp; for (unsigned int aggr = 1; aggr < 8192; aggr++) @@ -546,9 +539,9 @@ void SetDealTables( void InitWinners( - deal * dl, - pos * posPoint, - localVarType * thrp) + const deal& dl, + pos& posPoint, + ThreadData const * thrp) { int hand, suit, rank; unsigned short int startMovesBitMap[DDS_HANDS][DDS_SUITS]; @@ -557,11 +550,11 @@ void InitWinners( for (int s = 0; s < DDS_SUITS; s++) startMovesBitMap[h][s] = 0; - for (int k = 0; k < posPoint->handRelFirst; k++) + for (int k = 0; k < posPoint.handRelFirst; k++) { - hand = handId(dl->first, k); - suit = dl->currentTrickSuit[k]; - rank = dl->currentTrickRank[k]; + hand = handId(dl.first, k); + suit = dl.currentTrickSuit[k]; + rank = dl.currentTrickRank[k]; startMovesBitMap[hand][suit] |= bitMapRank[rank]; } @@ -572,16 +565,16 @@ void InitWinners( for (int h = 0; h < DDS_HANDS; h++) aggr |= startMovesBitMap[h][s] | thrp->suit[h][s]; - posPoint->winner[s].rank = thrp->rel[aggr].absRank[1][s].rank; - posPoint->winner[s].hand = thrp->rel[aggr].absRank[1][s].hand; - posPoint->secondBest[s].rank = thrp->rel[aggr].absRank[2][s].rank; - posPoint->secondBest[s].hand = thrp->rel[aggr].absRank[2][s].hand; + posPoint.winner[s].rank = thrp->rel[aggr].absRank[1][s].rank; + posPoint.winner[s].hand = thrp->rel[aggr].absRank[1][s].hand; + posPoint.secondBest[s].rank = thrp->rel[aggr].absRank[2][s].rank; + posPoint.secondBest[s].hand = thrp->rel[aggr].absRank[2][s].hand; } } void ResetBestMoves( - localVarType * thrp) + ThreadData * thrp) { for (int d = 0; d <= 49; d++) { @@ -589,7 +582,7 @@ void ResetBestMoves( thrp->bestMoveTT[d].rank = 0; } - thrp->memUsed = thrp->transTable.MemoryInUse() + + thrp->memUsed = thrp->transTable->MemoryInUse() + ThreadMemoryUsed(); #ifdef DDS_AB_STATS @@ -600,129 +593,27 @@ void ResetBestMoves( void STDCALL GetDDSInfo(DDSInfo * info) { - char t[80]; - - info->major = DDS_VERSION / 10000; - info->minor = (DDS_VERSION - info->major * 10000) / 100; - info->patch = DDS_VERSION % 100; - - sprintf(info->versionString, "%d.%d.%d", - info->major, info->minor, info->patch); - - info->system = 0; - info->compiler = 0; - info->constructor = 0; - info->threading = 0; - info->noOfThreads = noOfThreads; - - sprintf(info->systemString, "DDS DLL\n-------\n"); - -#if defined(_WIN32) - info->system = 1; - sprintf(t, "%-12s %20s\n", "System", "Windows"); - strcat(info->systemString, t); -#elif defined(__CYGWIN__) - info->system = 2; - sprintf(t, "%-12s %20s\n", "System", "Cygwin"); - strcat(info->systemString, t); -#elif defined(__linux) - info->system = 3; - sprintf(t, "%-12s %20s\n", "System", "Linux"); - strcat(info->systemString, t); -#elif defined(__APPLE__) - info->system = 4; - sprintf(t, "%-12s %20s\n", "System", "Apple"); - strcat(info->systemString, t); -#endif - -#if defined(_MSC_VER) - info->compiler = 1; - sprintf(t, "%-12s %20s\n", "Compiler", "Microsoft Visual C++"); - strcat(info->systemString, t); -#elif defined(__MINGW32__) - info->compiler = 2; - sprintf(t, "%-12s %20s\n", "Compiler", "MinGW"); - strcat(info->systemString, t); -#elif defined(__GNUC__) - info->compiler = 3; - sprintf(t, "%-12s %20s\n", "Compiler", "GNU g++"); - strcat(info->systemString, t); -#elif defined(__clang__) - info->compiler = 4; - sprintf(t, "%-12s %20s\n", "Compiler", "clang"); - strcat(info->systemString, t); -#endif - -#if defined(USES_DLLMAIN) - info->constructor = 1; - sprintf(t, "%-12s %20s\n", "Constructor", "DllMain"); - strcat(info->systemString, t); -#elif defined(USES_CONSTRUCTOR) - info->constructor = 2; - sprintf(t, "%-12s %20s\n", "Constructor", "Unix-style"); - strcat(info->systemString, t); -#endif - -#if defined(DDS_THREADS_SINGLE) - info->threading = 0; - sprintf(t, "%-12s %20s\n", "Threading", "None"); - strcat(info->systemString, t); -#elif defined(_OPENMP) - info->threading = 2; - sprintf(t, "%-12s %20s\n", "Threading", "OpenMP"); - strcat(info->systemString, t); -#elif defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED) - info->threading = 3; - sprintf(t, "%-12s %20s\n", "Threading", "GCD"); - strcat(info->systemString, t); -#else - info->threading = 1; - sprintf(t, "%-12s %20s\n", "Threading", "Windows"); - strcat(info->systemString, t); -#endif - - sprintf(t, "%-12s %20d\n", "Threads", noOfThreads); - strcat(info->systemString, t); + (void) sysdep.str(info); } void FreeThreadMem() { - for (int k = 0; k < noOfThreads; k++) - { - localVar[k].transTable.ResetMemory(FREE_THREAD_MEM); - localVar[k].memUsed = localVar[k].transTable.MemoryInUse() + - ThreadMemoryUsed(); - } + for (unsigned thrId = 0; thrId < sysdep.NumThreads(); thrId++) + memory.ResetThread(thrId); } void STDCALL FreeMemory() { - for (int k = 0; k < noOfThreads; k++) - { - localVar[k].transTable.ReturnAllMemory(); - localVar[k].memUsed = localVar[k].transTable.MemoryInUse() + - ThreadMemoryUsed(); - } -} - - -double ConstantMemoryUsed() -{ - double memUsed = - 8192 * ( sizeof(int) // highestRank - + sizeof(int) // counttable - + 15 * sizeof(char) // relRank - + 14 * sizeof(unsigned short int)) - / static_cast(1024.); - - return memUsed; + for (unsigned thrId = 0; thrId < sysdep.NumThreads(); thrId++) + memory.ReturnThread(thrId); } double ThreadMemoryUsed() { + // TODO: Only needed because SolverIF wants to set it. Avoid? double memUsed = 8192 * sizeof(relRanksType) / static_cast(1024.); @@ -804,6 +695,9 @@ void STDCALL ErrorMessage(int code, char line[80]) case RETURN_THREAD_WAIT: strcpy(line, TEXT_THREAD_WAIT); break; + case RETURN_THREAD_MISSING: + strcpy(line, TEXT_THREAD_MISSING); + break; case RETURN_NO_SUIT: strcpy(line, TEXT_NO_SUIT); break; diff --git a/src/Init.h b/src/Init.h index 2edbae48..ae661b21 100644 --- a/src/Init.h +++ b/src/Init.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,26 +10,23 @@ #ifndef DDS_INIT_H #define DDS_INIT_H +#include "dds.h" +#include "Memory.h" -void SetDeal( - struct localVarType * thrp); -void SetDealTables( - struct localVarType * thrp); +void SetDeal(ThreadData * thrp); + +void SetDealTables(ThreadData * thrp); void InitWinners( - deal * dl, - struct pos * posPoint, - struct localVarType * thrp); + const deal& dl, + pos& posPoint, + ThreadData const * thrp); -void ResetBestMoves( - struct localVarType * thrp); +void ResetBestMoves(ThreadData * thrp); double ThreadMemoryUsed(); void CloseDebugFiles(); -// Used by SH for stand-alone mode. -void DDSidentify(char * s); - #endif diff --git a/src/LaterTricks.cpp b/src/LaterTricks.cpp index 21f7be07..70d58157 100644 --- a/src/LaterTricks.cpp +++ b/src/LaterTricks.cpp @@ -2,103 +2,101 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ +#include -#include "dds.h" -#include "threadmem.h" #include "LaterTricks.h" bool LaterTricksMIN( - pos * posPoint, - int hand, - int depth, - int target, - int trump, - localVarType * thrp) + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd) { - if ((trump == DDS_NOTRUMP) || (posPoint->winner[trump].rank == 0)) + if ((trump == DDS_NOTRUMP) || (tpos.winner[trump].rank == 0)) { int sum = 0; for (int ss = 0; ss < DDS_SUITS; ss++) { - int hh = posPoint->winner[ss].hand; + int hh = tpos.winner[ss].hand; if (hh != -1) { - if (thrp->nodeTypeStore[hh] == MAXNODE) - sum += Max(posPoint->length[hh][ss], - posPoint->length[partner[hh]][ss]); + if (thrd.nodeTypeStore[hh] == MAXNODE) + sum += max(tpos.length[hh][ss], + tpos.length[partner[hh]][ss]); } } - if ((posPoint->tricksMAX + sum < target) && (sum > 0)) + if ((tpos.tricksMAX + sum < target) && (sum > 0)) { - if ((posPoint->tricksMAX + (depth >> 2) >= target)) + if ((tpos.tricksMAX + (depth >> 2) >= target)) return true; for (int ss = 0; ss < DDS_SUITS; ss++) { - int win_hand = posPoint->winner[ss].hand; + int win_hand = tpos.winner[ss].hand; if (win_hand == -1) - posPoint->winRanks[depth][ss] = 0; - else if (thrp->nodeTypeStore[win_hand] == MINNODE) + tpos.winRanks[depth][ss] = 0; + else if (thrd.nodeTypeStore[win_hand] == MINNODE) { - if ((posPoint->rankInSuit[partner[win_hand]][ss] == 0) && - (posPoint->rankInSuit[lho[win_hand]][ss] == 0) && - (posPoint->rankInSuit[rho[win_hand]][ss] == 0)) - posPoint->winRanks[depth][ss] = 0; + if ((tpos.rankInSuit[partner[win_hand]][ss] == 0) && + (tpos.rankInSuit[lho[win_hand]][ss] == 0) && + (tpos.rankInSuit[rho[win_hand]][ss] == 0)) + tpos.winRanks[depth][ss] = 0; else - posPoint->winRanks[depth][ss] = - bitMapRank[posPoint->winner[ss].rank]; + tpos.winRanks[depth][ss] = bitMapRank[tpos.winner[ss].rank]; } else - posPoint->winRanks[depth][ss] = 0; + tpos.winRanks[depth][ss] = 0; } return false; } } - else if (thrp->nodeTypeStore[posPoint->winner[trump].hand] == MINNODE) + else if (thrd.nodeTypeStore[tpos.winner[trump].hand] == MINNODE) { - if ((posPoint->length[hand][trump] == 0) && - (posPoint->length[partner[hand]][trump] == 0)) + if ((tpos.length[hand][trump] == 0) && + (tpos.length[partner[hand]][trump] == 0)) { - if (((posPoint->tricksMAX + (depth >> 2) + 1 - - Max(posPoint->length[lho[hand]][trump], - posPoint->length[rho[hand]][trump])) < target)) + if (((tpos.tricksMAX + (depth >> 2) + 1 - + max(tpos.length[lho[hand]][trump], + tpos.length[rho[hand]][trump])) < target)) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; + tpos.winRanks[depth][ss] = 0; return false; } } - else if ((posPoint->tricksMAX + (depth >> 2)) < target) + else if ((tpos.tricksMAX + (depth >> 2)) < target) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = - bitMapRank[posPoint->winner[trump].rank]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = + bitMapRank[tpos.winner[trump].rank]; return false; } - else if (posPoint->tricksMAX + (depth >> 2) == target) + else if (tpos.tricksMAX + (depth >> 2) == target) { - int hh = posPoint->secondBest[trump].hand; + int hh = tpos.secondBest[trump].hand; if (hh == -1) return true; - int r2 = posPoint->secondBest[trump].rank; - if ((thrp->nodeTypeStore[hh] == MINNODE) && (r2 != 0)) + int r2 = tpos.secondBest[trump].rank; + if ((thrd.nodeTypeStore[hh] == MINNODE) && (r2 != 0)) { - if (posPoint->length[hh][trump] > 1 || - posPoint->length[partner[hh]][trump] > 1) + if (tpos.length[hh][trump] > 1 || + tpos.length[partner[hh]][trump] > 1) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = bitMapRank[r2]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = bitMapRank[r2]; return false; } } @@ -106,39 +104,39 @@ bool LaterTricksMIN( } else // Not NT { - int hh = posPoint->secondBest[trump].hand; + int hh = tpos.secondBest[trump].hand; if (hh == -1) return true; - if ((thrp->nodeTypeStore[hh] != MINNODE) || - (posPoint->length[hh][trump] <= 1)) + if ((thrd.nodeTypeStore[hh] != MINNODE) || + (tpos.length[hh][trump] <= 1)) return true; - if (posPoint->winner[trump].hand == rho[hh]) + if (tpos.winner[trump].hand == rho[hh]) { - if (((posPoint->tricksMAX + (depth >> 2)) < target)) + if (((tpos.tricksMAX + (depth >> 2)) < target)) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = - bitMapRank[posPoint->secondBest[trump].rank]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = + bitMapRank[tpos.secondBest[trump].rank]; return false; } } else { - unsigned short aggr = posPoint->aggr[trump]; - int h = thrp->rel[aggr].absRank[3][trump].hand; + unsigned short aggr = tpos.aggr[trump]; + int h = thrd.rel[aggr].absRank[3][trump].hand; if (h == -1) return true; - if ((thrp->nodeTypeStore[h] == MINNODE) && - ((posPoint->tricksMAX + (depth >> 2)) < target)) + if ((thrd.nodeTypeStore[h] == MINNODE) && + ((tpos.tricksMAX + (depth >> 2)) < target)) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = bitMapRank[ - static_cast(thrp->rel[aggr].absRank[3][trump].rank) ]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = bitMapRank[ + static_cast(thrd.rel[aggr].absRank[3][trump].rank) ]; return false; } } @@ -148,94 +146,94 @@ bool LaterTricksMIN( bool LaterTricksMAX( - pos * posPoint, - int hand, - int depth, - int target, - int trump, - localVarType * thrp) + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd) { - if ((trump == DDS_NOTRUMP) || (posPoint->winner[trump].rank == 0)) + if ((trump == DDS_NOTRUMP) || (tpos.winner[trump].rank == 0)) { int sum = 0; for (int ss = 0; ss < DDS_SUITS; ss++) { - int hh = posPoint->winner[ss].hand; + int hh = tpos.winner[ss].hand; if (hh != -1) { - if (thrp->nodeTypeStore[hh] == MINNODE) - sum += Max(posPoint->length[hh][ss], - posPoint->length[partner[hh]][ss]); + if (thrd.nodeTypeStore[hh] == MINNODE) + sum += max(tpos.length[hh][ss], + tpos.length[partner[hh]][ss]); } } - if ((posPoint->tricksMAX + (depth >> 2) + 1 - sum >= target) && + if ((tpos.tricksMAX + (depth >> 2) + 1 - sum >= target) && (sum > 0)) { - if ((posPoint->tricksMAX + 1 < target)) + if ((tpos.tricksMAX + 1 < target)) return false; for (int ss = 0; ss < DDS_SUITS; ss++) { - int win_hand = posPoint->winner[ss].hand; + int win_hand = tpos.winner[ss].hand; if (win_hand == -1) - posPoint->winRanks[depth][ss] = 0; - else if (thrp->nodeTypeStore[win_hand] == MAXNODE) + tpos.winRanks[depth][ss] = 0; + else if (thrd.nodeTypeStore[win_hand] == MAXNODE) { - if ((posPoint->rankInSuit[partner[win_hand]][ss] == 0) && - (posPoint->rankInSuit[lho[win_hand]][ss] == 0) && - (posPoint->rankInSuit[rho[win_hand]][ss] == 0)) - posPoint->winRanks[depth][ss] = 0; + if ((tpos.rankInSuit[partner[win_hand]][ss] == 0) && + (tpos.rankInSuit[lho[win_hand]][ss] == 0) && + (tpos.rankInSuit[rho[win_hand]][ss] == 0)) + tpos.winRanks[depth][ss] = 0; else - posPoint->winRanks[depth][ss] = - bitMapRank[posPoint->winner[ss].rank]; + tpos.winRanks[depth][ss] = + bitMapRank[tpos.winner[ss].rank]; } else - posPoint->winRanks[depth][ss] = 0; + tpos.winRanks[depth][ss] = 0; } return true; } } - else if (thrp->nodeTypeStore[posPoint->winner[trump].hand] == MAXNODE) + else if (thrd.nodeTypeStore[tpos.winner[trump].hand] == MAXNODE) { - if ((posPoint->length[hand][trump] == 0) && - (posPoint->length[partner[hand]][trump] == 0)) + if ((tpos.length[hand][trump] == 0) && + (tpos.length[partner[hand]][trump] == 0)) { - int maxlen = Max(posPoint->length[lho[hand]][trump], - posPoint->length[rho[hand]][trump]); + int maxlen = max(tpos.length[lho[hand]][trump], + tpos.length[rho[hand]][trump]); - if ((posPoint->tricksMAX + maxlen) >= target) + if ((tpos.tricksMAX + maxlen) >= target) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; + tpos.winRanks[depth][ss] = 0; return true; } } - else if ((posPoint->tricksMAX + 1) >= target) + else if ((tpos.tricksMAX + 1) >= target) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = - bitMapRank[posPoint->winner[trump].rank]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = + bitMapRank[tpos.winner[trump].rank]; return true; } else { - int hh = posPoint->secondBest[trump].hand; + int hh = tpos.secondBest[trump].hand; if (hh == -1) return false; - if ((thrp->nodeTypeStore[hh] == MAXNODE) && - (posPoint->secondBest[trump].rank != 0)) + if ((thrd.nodeTypeStore[hh] == MAXNODE) && + (tpos.secondBest[trump].rank != 0)) { - if (((posPoint->length[hh][trump] > 1) || - (posPoint->length[partner[hh]][trump] > 1)) && - ((posPoint->tricksMAX + 2) >= target)) + if (((tpos.length[hh][trump] > 1) || + (tpos.length[partner[hh]][trump] > 1)) && + ((tpos.tricksMAX + 2) >= target)) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = - bitMapRank[posPoint->secondBest[trump].rank]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = + bitMapRank[tpos.secondBest[trump].rank]; return true; } } @@ -244,39 +242,39 @@ bool LaterTricksMAX( else // trump != DDS_NOTRUMP) { - int hh = posPoint->secondBest[trump].hand; + int hh = tpos.secondBest[trump].hand; if (hh == -1) return false; - if ((thrp->nodeTypeStore[hh] != MAXNODE) || - (posPoint->length[hh][trump] <= 1)) + if ((thrd.nodeTypeStore[hh] != MAXNODE) || + (tpos.length[hh][trump] <= 1)) return false; - if (posPoint->winner[trump].hand == rho[hh]) + if (tpos.winner[trump].hand == rho[hh]) { - if ((posPoint->tricksMAX + 1) >= target) + if ((tpos.tricksMAX + 1) >= target) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = - bitMapRank[posPoint->secondBest[trump].rank] ; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = + bitMapRank[tpos.secondBest[trump].rank] ; return true; } } else { - unsigned short aggr = posPoint->aggr[trump]; - int h = thrp->rel[aggr].absRank[3][trump].hand; + unsigned short aggr = tpos.aggr[trump]; + int h = thrd.rel[aggr].absRank[3][trump].hand; if (h == -1) return false; - if ((thrp->nodeTypeStore[h] == MAXNODE) && - ((posPoint->tricksMAX + 1) >= target)) + if ((thrd.nodeTypeStore[h] == MAXNODE) && + ((tpos.tricksMAX + 1) >= target)) { for (int ss = 0; ss < DDS_SUITS; ss++) - posPoint->winRanks[depth][ss] = 0; - posPoint->winRanks[depth][trump] = bitMapRank[ - static_cast(thrp->rel[aggr].absRank[3][trump].rank) ]; + tpos.winRanks[depth][ss] = 0; + tpos.winRanks[depth][trump] = bitMapRank[ + static_cast(thrd.rel[aggr].absRank[3][trump].rank) ]; return true; } } diff --git a/src/LaterTricks.h b/src/LaterTricks.h index 333ff0d9..04ef8d7b 100644 --- a/src/LaterTricks.h +++ b/src/LaterTricks.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,21 +10,24 @@ #ifndef DDS_LATERTRICKS_H #define DDS_LATERTRICKS_H +#include "dds.h" +#include "Memory.h" + bool LaterTricksMIN( - struct pos * posPoint, - int hand, - int depth, - int target, - int trump, - struct localVarType * thrp); + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd); bool LaterTricksMAX( - struct pos * posPoint, - int hand, - int depth, - int target, - int trump, - struct localVarType * thrp); + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd); #endif diff --git a/src/Makefiles/Makefile_Mac_clang b/src/Makefiles/Makefile_Mac_clang deleted file mode 100644 index 3d3e21a4..00000000 --- a/src/Makefiles/Makefile_Mac_clang +++ /dev/null @@ -1,133 +0,0 @@ -# This the DDS Makefile for Mac OS and the clang compiler. -# No multi-threadingOpenMP works here. - -# If your compiler name is not given here, change it. -CC = g++ - -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -mtune=generic - -LD_FLAGS = \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wcomment \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DLLBASE = dds -STATIC_LIB = lib$(DLLBASE).a - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) - -linux: $(O_FILES) - ar rcs $(STATIC_LIB) $(O_FILES) - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(STATIC_LIB) - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(STATIC_LIB) ../test - cp $(STATIC_LIB) ../examples - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h Timer.h ABstats.h -dds.o: Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -ABsearch.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h QuickTricks.h -ABsearch.o: LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -ABstats.o: ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -CalcTables.o: ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -DealerPar.o: ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Init.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -LaterTricks.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -LaterTricks.o: LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Moves.o: ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h ABstats.h -Par.o: Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -PlayAnalyser.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h SolverIF.h -PlayAnalyser.o: PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h ABstats.h -PBN.o: Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -QuickTricks.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -QuickTricks.o: QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Scheduler.o: Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -SolveBoard.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h SolverIF.h -SolveBoard.o: SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -SolverIF.o: ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Stats.o: ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Timer.o: ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -TransTable.o: ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_Mac_clang_shared b/src/Makefiles/Makefile_Mac_clang_shared new file mode 100644 index 00000000..f3b44543 --- /dev/null +++ b/src/Makefiles/Makefile_Mac_clang_shared @@ -0,0 +1,120 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for MacOS and the clang compiler. +# It creates a dynamically linked (shared) library, libdds.so. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_BOOST) $(THR_GCD) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_INCL = $(CC_BOOST)/include +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_COMPILE = +THREAD_LINK = $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wcomment \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -fPIC -O3 -flto -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) + +DLLBASE = dds +SHARED_LIB = lib$(DLLBASE).so + +LINK_FLAGS = \ + -shared \ + $(THREAD_LINK) \ + -fPIC + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + + +macos: $(O_FILES) + $(CC) -o $(SHARED_LIB) $(O_FILES) $(LINK_FLAGS) + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(SHARED_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(SHARED_LIB) ../test + cp $(SHARED_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_Mac_clang_static b/src/Makefiles/Makefile_Mac_clang_static new file mode 100644 index 00000000..911ed4cc --- /dev/null +++ b/src/Makefiles/Makefile_Mac_clang_static @@ -0,0 +1,115 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for MacOS and the clang compiler. +# It creates a statically linked library, libdds.a. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_BOOST) $(THR_GCD) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_INCL = $(CC_BOOST)/include +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_COMPILE = +THREAD_LINK = $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wcomment \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -O3 -flto -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) + +DLLBASE = dds +STATIC_LIB = lib$(DLLBASE).a + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + + +macos: $(O_FILES) + ar rcs $(STATIC_LIB) $(O_FILES) + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(STATIC_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(STATIC_LIB) ../test + cp $(STATIC_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_Mac_gcc b/src/Makefiles/Makefile_Mac_gcc deleted file mode 100644 index 4a2be4c9..00000000 --- a/src/Makefiles/Makefile_Mac_gcc +++ /dev/null @@ -1,146 +0,0 @@ -# This the DDS Makefile for Mac and the GNU g++ compiler. -# Only OpenMP works here. - -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none - -# If your compiler name is not given here, change it. -CC = gcc-4.9 - -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic - -LD_FLAGS = \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -fno-use-linker-plugin \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wnoexcept \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-null-sentinel \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DLLBASE = dds -STATIC_LIB = lib$(DLLBASE).a - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - -mac: $(O_FILES) - ar rcs $(STATIC_LIB) $(O_FILES) - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(STATIC_LIB) - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(STATIC_LIB) ../test - cp $(STATIC_LIB) ../examples - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h Timer.h ABstats.h -dds.o: Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -ABsearch.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h QuickTricks.h -ABsearch.o: LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -ABstats.o: ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -CalcTables.o: ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -DealerPar.o: ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Init.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -LaterTricks.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -LaterTricks.o: LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Moves.o: ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h ABstats.h -Par.o: Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -PlayAnalyser.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h SolverIF.h -PlayAnalyser.o: PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h ABstats.h -PBN.o: Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -QuickTricks.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -QuickTricks.o: QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Scheduler.o: Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -SolveBoard.o: ABstats.h Moves.h Stats.h Scheduler.h threadmem.h SolverIF.h -SolveBoard.o: SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -SolverIF.o: ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Stats.o: ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -Timer.o: ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h Timer.h -TransTable.o: ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_Mac_gcc_shared b/src/Makefiles/Makefile_Mac_gcc_shared new file mode 100644 index 00000000..5aa3fe51 --- /dev/null +++ b/src/Makefiles/Makefile_Mac_gcc_shared @@ -0,0 +1,125 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for MacOS and the g++ compiler. +# It creates a dynamically linked (shared) library, libdds.so. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_OPENMP) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +THREAD_COMPILE = +THREAD_LINK = -lgomp + +# 2. The small memory option, which causes DDS to consume a lot less +# memory and to run somewhat more slowly. + +SMALL_MEMORY = -DSMALL_MEMORY_OPTION + +# 3. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = gcc-4.9 + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -fno-use-linker-plugin \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wnoexcept \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-null-sentinel \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -fPIC -O3 -flto -mtune=generic -Wno-write-string \ + -fopenmp -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) + +DLLBASE = dds +SHARED_LIB = lib$(DLLBASE).so + +LINK_FLAGS = \ + -shared \ + $(THREAD_LINK) \ + -fPIC + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + + +macos: $(O_FILES) + $(CC) -o $(SHARED_LIB) $(O_FILES) $(LINK_FLAGS) -lstdc++ + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(SHARED_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(SHARED_LIB) ../test + cp $(SHARED_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_Mac_gcc_static b/src/Makefiles/Makefile_Mac_gcc_static new file mode 100644 index 00000000..009f4d88 --- /dev/null +++ b/src/Makefiles/Makefile_Mac_gcc_static @@ -0,0 +1,129 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for MacOS and the GNU g++ compiler. +# It creates a statically linked library, libdds.a. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_INCL = $(CC_BOOST)/include +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_COMPILE = +THREAD_LINK = $(CC_BOOST_LINK) + +# 2. The small memory option, which causes DDS to consume a lot less +# memory and to run somewhat more slowly. + +SMALL_MEMORY = -DSMALL_MEMORY_OPTION + +# 3. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = gcc-4.9 + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -fno-use-linker-plugin \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wnoexcept \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-null-sentinel \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) + +DLLBASE = dds +STATIC_LIB = lib$(DLLBASE).a + +LD_FLAGS = \ + -Wl,--dynamicbase \ + -Wl,--nxcompat \ + -Wl,--no-seh \ + -Wl,--enable-stdcall-fixup + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + + +macos: $(O_FILES) + ar rcs $(STATIC_LIB) $(O_FILES) + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(STATIC_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(STATIC_LIB) ../test + cp $(STATIC_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_Mac_shared b/src/Makefiles/Makefile_Mac_shared deleted file mode 100644 index 1e0617b6..00000000 --- a/src/Makefiles/Makefile_Mac_shared +++ /dev/null @@ -1,150 +0,0 @@ -# This the DDS Makefile for Linux and the GNU g++ compiler. -# Only OpenMP works here. - -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none - -# If your compiler name is not given here, change it. -CC = gcc-4.9 - -# Use this one to get OpenMP multi-threading -CC_FLAGS = -fPIC -g -O3 -flto -fopenmp -mtune=generic -Wno-write-strings - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -fno-use-linker-plugin \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wnoexcept \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-null-sentinel \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DLLBASE = dds -SHARED_LIB = lib$(DLLBASE).so - -# Major version -MAJOR = 2 - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - -mac: $(O_FILES) - $(CC) -dynamiclib -fopenmp \ - -o $(SHARED_LIB) ABsearch.o ABstats.o CalcTables.o \ - DealerPar.o Init.o LaterTricks.o Moves.o PBN.o Par.o \ - PlayAnalyser.o QuickTricks.o SolveBoard.o \ - SolverIF.o Stats.o Timer.o TransTable.o dds.o \ - Scheduler.o -lstdc++ - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(SHARED_LIB) - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(SHARED_LIB) ../test - cp $(SHARED_LIB) ../examples - cp $(SHARED_LIB) /usr/lib - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_Visual b/src/Makefiles/Makefile_Visual index 8ee22fb9..41aced4a 100644 --- a/src/Makefiles/Makefile_Visual +++ b/src/Makefiles/Makefile_Visual @@ -1,42 +1,110 @@ -# This the DDS Makefile for Windows and the Microsoft Visual C++ -# compiler. It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# --------------------- INFORMATION -------------------------------- -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none +# This the DDS Makefile for Windows and the Microsoft Visual C++ +# compiler. It assumes a Unix-like setup for some commands. # The "windres" and "cvtres" tools are used for putting version # information into the DLL in a way that Windows can see. # It is not mandatory, and if you don't have those tools, # You can remove $(VFILE).obj in the target line below. +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: +# +# 1. The location of the Boost libraries (you can leave the +# variables blank if you don't have or want Boost). All that +# matters are CC_BOOST_INCL and CC_BOOST_LINK. +# On my systems (there are two), they are here: + +BOOST32_PATH1 = \User\sheins\boost_1_66_0_x32_new +BOOST32_LIB1 = $(BOOST32_PATH1)\lib32-msvc-14.1 + +BOOST32_PATH2 = \Users\s.hein\Documents\Programs\boost_1_66_0_x32_14_1 +BOOST32_LIB2 = $(BOOST32_PATH2)\lib32-msvc-14.1 + +CC_BOOST_INCL = /I$(BOOST32_PATH1) /I$(BOOST32_PATH2) +CC_BOOST_LINK = /link /LIBPATH:$(BOOST32_LIB1) /LIBPATH:$(BOOST32_LIB2) + +# 2. The threading systems that you want in the DLL/executable. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD doesn't work on Windows. +THR_WINAPI = /DDDS_THREADS_WINAPI +THR_OPENMP = /DDDS_THREADS_OPENMP +THR_GCD = /DDDS_THREADS_GCD +THR_BOOST = /DDDS_THREADS_BOOST +THR_STL = /DDDS_THREADS_STL +THR_TBB = /DDDS_THREADS_TBB +THR_STLIMPL = /DDDS_THREADS_STLIMPL +THR_PPLIMPL = /DDDS_THREADS_PPLIMPL + +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_WINAPI) \ + $(THR_STL) $(THR_STLIMPL) $(THR_PPLIMPL) + +# If you need to add something for a threading system, this is +# the place. + +THREAD_COMPILE = /openmp $(CC_BOOST_INCL) +THREAD_LINK = $(CC_BOOST_LINK) + +# 3. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = /DDDS_DEBUG_ALL +TIMING = /DDDS_TIMING +SCHEDULER = /DDDS_SCHEDULER + +# All that matters from no. 3 and no. 4 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_obj.txt # If your Microsoft compiler is not called cl, change it here. CC = cl -CC_FLAGS = /O2 /Oi /Ot /Oy /GL /EHs -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in Windows libraries in great numbers... + WARN_FLAGS = \ /Wall \ - /wd4127 \ + /wd4365 \ + /wd4464 \ + /wd4514 \ /wd4555 \ + /wd4571 \ + /wd4623 \ + /wd4625 \ + /wd4626 \ /wd4668 \ - /wd4701 \ /wd4710 \ /wd4711 \ + /wd4774 \ /wd4820 \ - /wd4986 \ - /wd4987 \ /wd4996 \ + /wd5026 \ + /wd5027 \ /WX -# Here you can turn on warnings and add /DSMALL_MEMORY_OPTION. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) +# If you don't have /std:c++17, you won't get THR_STLIMPL. + +COMPILE_FLAGS = /O2 /Oi /Ot /Oy /Ox /GL /EHs /std:c++17 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) -LIB_FLAGS = /link /DLL +LINK_FLAGS1 = /O2 /Oi /Ot /Oy /GL /EHs $(WARN_FLAGS) +LINK_FLAGS2 = $(THREAD_LINK) DLLBASE = dds DLL = $(DLLBASE).dll @@ -45,40 +113,16 @@ EXPORTER = Exports.def VFILE = ddsres -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp +include $(INCL_SOURCE) OBJ_FILES = $(subst .cpp,.obj,$(SOURCE_FILES)) $(VFILE).obj -ifeq ($(DDS_THREADS),none) -DDS_THR = /DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - vs: $(OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(OBJ_FILES) $(EXPORTER) $(LIB_FLAGS) /out:$(DLL) + $(CC) $(LINK_FLAGS1) $(OBJ_FILES) $(EXPORTER) \ + $(LINK_FLAGS2) /out:$(DLL) %.obj: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) /c $< + $(CC) $(COMPILE_FLAGS) /c $< $(DLLBASE).res: $(DLLBASE).rc windres $(DLLBASE).rc $(DLLBASE).res @@ -87,7 +131,7 @@ $(VFILE).obj: $(DLLBASE).res cvtres /MACHINE:X86 /OUT:$(VFILE).obj $(DLLBASE).res depend: - makedepend -Y -o.obj -- $(CC_FLAGS) -- $(SOURCE_FILES) + makedepend -Y -o.obj -- $(SOURCE_FILES) clean: rm -f $(OBJ_FILES) $(DLL) $(DLLBASE).{lib,exp,def,obj,res} @@ -98,50 +142,8 @@ install: cp $(DLL) $(DLIB) ../test cp $(DLL) $(DLIB) ../examples -# DO NOT DELETE - -dds.obj: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.obj: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.obj: dds.h debug.h ../include/portab.h TransTable.h -CalcTables.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -CalcTables.obj: Scheduler.h SolveBoard.h PBN.h -DealerPar.obj: dds.h debug.h ../include/portab.h TransTable.h -DealerPar.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.obj: ABsearch.h -LaterTricks.obj: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -LaterTricks.obj: Scheduler.h threadmem.h LaterTricks.h -Moves.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.obj: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.obj: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.obj: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -QuickTricks.obj: Scheduler.h threadmem.h QuickTricks.h -Scheduler.obj: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.obj: dds.h debug.h ../include/portab.h TransTable.h -SolveBoard.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.obj: Scheduler.h threadmem.h SolverIF.h SolveBoard.h PBN.h -SolverIF.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -SolverIF.obj: threadmem.h ABsearch.h SolverIF.h -Stats.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.obj: dds.h debug.h ../include/portab.h TransTable.h -TransTable.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -TransTable.obj: Scheduler.h +# If you don't have a Linux-like setup, use "del" instead of "rm" +# and "copy" instead of "cp". + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_Visual_Windows b/src/Makefiles/Makefile_Visual_Windows deleted file mode 100644 index 10fa8095..00000000 --- a/src/Makefiles/Makefile_Visual_Windows +++ /dev/null @@ -1,154 +0,0 @@ -# This the DDS Makefile for Windows and the Microsoft Visual C++ -# compiler. Unlike the other Makefiles, it does not assume a -# Unix-like setup. -# Contributed by Philippe Capron in Dec. 2014. - -# You can't compile a single-threaded version with this particular -# Makefile. - -# The cvtres" tool is used for putting version -# information into the DLL in a way that Windows can see. -# It is not mandatory, and if you don't have those tools, -# You can remove $(VFILE).obj in the target line below. - - -# If your Microsoft compiler is not called cl, change it here. -CC = cl -CC_FLAGS = /O2 /Oi /Ot /Oy /GL - -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - /Wall \ - /wd4127 \ - /wd4555 \ - /wd4668 \ - /wd4701 \ - /wd4710 \ - /wd4711 \ - /wd4820 \ - /wd4986 \ - /wd4987 \ - /wd4996 \ - /WX - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -LIB_FLAGS = /link /DLL - -DLLBASE = dds -DLL = $(DLLBASE).dll -DLIB = $(DLLBASE).lib -EXPORTER = Exports.def - -VFILE = ddsres - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -OBJ_FILES = \ - dds.obj \ - ABsearch.obj \ - ABstats.obj \ - CalcTables.obj \ - DealerPar.obj \ - Init.obj \ - LaterTricks.obj \ - Moves.obj \ - Par.obj \ - PlayAnalyser.obj \ - PBN.obj \ - QuickTricks.obj \ - Scheduler.obj \ - SolveBoard.obj \ - SolverIF.obj \ - Stats.obj \ - Timer.obj \ - TransTable.obj \ - $(VFILE).obj - -vs: $(OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(OBJ_FILES) $(EXPORTER) $(LIB_FLAGS) /out:$(DLL) - -%.obj: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) /c $< - -$(VFILE).obj: $(DLLBASE).res - cvtres /MACHINE:X86 /OUT:$(VFILE).obj $(DLLBASE).res - -clean: - del $(OBJ_FILES) $(DLL) \ - $(DLLBASE).lib $(DLLBASE).exp $(DLLBASE).def $(DLLBASE).obj $(DLLBASE).res - -install: - copy $(DLL) ..\test - copy $(DLIB) ..\test - copy $(DLL) ..\examples - copy $(DLIB) ..\examples - -# DO NOT DELETE - -dds.obj: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.obj: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.obj: dds.h debug.h ../include/portab.h TransTable.h -CalcTables.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -CalcTables.obj: Scheduler.h SolveBoard.h PBN.h -DealerPar.obj: dds.h debug.h ../include/portab.h TransTable.h -DealerPar.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.obj: ABsearch.h -LaterTricks.obj: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -LaterTricks.obj: Scheduler.h threadmem.h LaterTricks.h -Moves.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.obj: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.obj: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.obj: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -QuickTricks.obj: Scheduler.h threadmem.h QuickTricks.h -Scheduler.obj: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.obj: dds.h debug.h ../include/portab.h TransTable.h -SolveBoard.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.obj: Scheduler.h threadmem.h SolverIF.h SolveBoard.h PBN.h -SolverIF.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -SolverIF.obj: threadmem.h ABsearch.h SolverIF.h -Stats.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.obj: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.obj: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.obj: dds.h debug.h ../include/portab.h TransTable.h -TransTable.obj: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -TransTable.obj: Scheduler.h diff --git a/src/Makefiles/Makefile_cygwin b/src/Makefiles/Makefile_cygwin index e538a76b..6df619a4 100644 --- a/src/Makefiles/Makefile_cygwin +++ b/src/Makefiles/Makefile_cygwin @@ -1,35 +1,69 @@ -# This the DDS Makefile for Cygwin under Windows and the -# GNU g++ compiler. It does assume a Unix-like setup for some -# commands, but if you only want to call "make" with the default -# target, you should be OK. +# --------------------- INFORMATION -------------------------------- -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none +# This the DDS Makefile for Windows and the Cygwin GNU g++ +# compiler. It assumes a Unix-like setup for some commands. # The "windres" and "cvtres" tools are used for putting version # information into the DLL in a way that Windows can see. # It is not mandatory, and if you don't have those tools, # You can remove $(VFILE).obj in the target line below. +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the DLL/executable. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD doesn't work on Windows. +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_GCD = -DDDS_THREADS_GCD +THR_BOOST = -DDDS_THREADS_BOOST +THR_STL = -DDDS_THREADS_STL +THR_TBB = -DDDS_THREADS_TBB +THR_STLIMPL = -DDDS_THREADS_STLIMPL +THR_PPLIMPL = -DDDS_THREADS_PPLIMPL + +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_WINAPI) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_COMPILE = -fopenmp +THREAD_LINK = $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt # If your compiler name is not given here, change it. CC = g++ -# Use this one to get Windows multi-threading -CC_FLAGS = -O3 -flto -mtune=generic -fno-use-linker-plugin -# Use this one to get OpenMP multi-threading -# CC_FLAGS = -O3 -flto -fopenmp -mtune=generic -fno-use-linker-plugin +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -LD_FLAGS = \ - -Wl,--subsystem,windows \ - -Wl,--output-def,$(DLLBASE).def \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -55,53 +89,38 @@ WARN_FLAGS = \ -Wno-unknown-pragmas \ -Wno-long-long -# Here you can turn on warnings and add -DSMALL_MEMORY_OPTION -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic -fno-use-linker-plugin \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) -LIB_FLAGS = -shared +LINK1_FLAGS = -shared -fopenmp +LINK2_FLAGS = \ + -Wl,--subsystem,windows \ + -Wl,--output-def,$(DLLBASE).def \ + -Wl,--dynamicbase \ + -Wl,--nxcompat \ + -Wl,--no-seh \ + -Wl,--enable-stdcall-fixup \ + $(THREAD_LINK) DLLBASE = dds DLL = $(DLLBASE).dll +DLIB = $(DLLBASE).lib EXPORTER = Exports.def VFILE = ddsres WINDRES_FLAG = -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp +include $(INCL_SOURCE) O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) $(VFILE).o -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - cygwin: $(O_FILES) - $(CC) $(LIB_FLAGS) $(CC_FULL_FLAGS) $(O_FILES) $(LD_FLAGS) $(EXPORTER) -o $(DLL) + $(CC) $(LINK1_FLAGS) $(O_FILES) \ + $(LINK2_FLAGS) $(EXPORTER) -o $(DLL) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< + $(CC) $(COMPILE_FLAGS) -c $< $(DLLBASE).res: $(DLLBASE).rc windres $(DLLBASE).rc $(DLLBASE).res @@ -110,7 +129,7 @@ $(VFILE).o: $(DLLBASE).rc windres $(WINDRES_FLAG) $(DLLBASE).rc $(VFILE).o depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) + makedepend -Y -- $(SOURCE_FILES) clean: rm -f $(O_FILES) $(DLL) $(DLLBASE).{lib,def,exp,res} @@ -121,50 +140,8 @@ install: cp $(DLL) $(DLLBASE).def ../test cp $(DLL) $(DLLBASE).def ../examples +# If you don't have a Linux-like setup, use "del" instead of "rm +# and "copy" instead of "cp". + +include $(INCL_DEPENDS) -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_linux b/src/Makefiles/Makefile_linux deleted file mode 100644 index 6cdc1ddb..00000000 --- a/src/Makefiles/Makefile_linux +++ /dev/null @@ -1,147 +0,0 @@ -# This the DDS Makefile for Linux and the GNU g++ compiler. -# Only OpenMP works here. - -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none - -# If your compiler name is not given here, change it. -CC = g++ - -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic - -LD_FLAGS = \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wnoexcept \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-null-sentinel \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DLLBASE = dds -STATIC_LIB = lib$(DLLBASE).a - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - -linux: $(O_FILES) - ar rcs $(STATIC_LIB) $(O_FILES) - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(STATIC_LIB) - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(STATIC_LIB) ../test - cp $(STATIC_LIB) ../examples - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_linux_shared b/src/Makefiles/Makefile_linux_shared index 9e7cd25f..ec4a2c8a 100644 --- a/src/Makefiles/Makefile_linux_shared +++ b/src/Makefiles/Makefile_linux_shared @@ -1,25 +1,61 @@ +# --------------------- INFORMATION -------------------------------- + # This the DDS Makefile for Linux and the GNU g++ compiler. -# Only OpenMP works here. +# It creates a dynamically linked (shared) library, libdds.so. -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none +# --------------------- CONFIGURATION ------------------------------ -# If your compiler name is not given here, change it. -CC = g++ +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_COMPILE = -fopenmp +THREAD_LINK = -fopenmp $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) -# Use this one to get OpenMP multi-threading -CC_FLAGS = -fPIC -g -O3 -flto -fopenmp -mtune=generic -Wno-write-strings +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER -LD_FLAGS = \ - -Wl,-O1 \ - -Wl,--sort-common \ - -Wl,--as-needed \ - -Wl,-z \ - -Wl,relro +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -45,58 +81,37 @@ WARN_FLAGS = \ -Wno-long-long \ -Wno-format -# Here you can turn on warnings. -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) +COMPILE_FLAGS = -fPIC -O3 -flto -fopenmp -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) DLLBASE = dds -SHARED_LIB = lib$(DLLBASE).so - -# Major version -MAJOR = 2 - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp +SHARED_LIB = lib$(DLLBASE).so + +include $(INCL_SOURCE) O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif +LINK_FLAGS = \ + -shared \ + -Wl,-O2 \ + -Wl,--sort-common \ + -Wl,--as-needed \ + -Wl,-z \ + -Wl,relro \ + $(THREAD_LINK) \ + -fPIC linux: $(O_FILES) - $(CC) $(LD_FLAGS) -fopenmp \ - -Wl,-soname,lib$(DLLBASE).so.$(MAJOR) \ - -o $(SHARED_LIB) ABsearch.o ABstats.o CalcTables.o \ - DealerPar.o Init.o LaterTricks.o Moves.o PBN.o Par.o \ - PlayAnalyser.o QuickTricks.o SolveBoard.o \ - SolverIF.o Stats.o Timer.o TransTable.o dds.o \ - Scheduler.o -shared -fPIC + $(CC) \ + -o $(SHARED_LIB) $(O_FILES) $(LINK_FLAGS) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< + $(CC) $(COMPILE_FLAGS) -c $< depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) + makedepend -Y -- $(SOURCE_FILES) clean: rm -f $(O_FILES) $(SHARED_LIB) @@ -104,54 +119,8 @@ clean: install: test -d ../test || mkdir ../test test -d ../examples || mkdir ../examples - cp $(SHARED_LIB) ../test - cp $(SHARED_LIB) ../examples - cp $(SHARED_LIB) /usr/lib - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h + cp $(STATIC_LIB) ../test + cp $(STATIC_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_linux_static b/src/Makefiles/Makefile_linux_static new file mode 100644 index 00000000..82dbc261 --- /dev/null +++ b/src/Makefiles/Makefile_linux_static @@ -0,0 +1,120 @@ +# --------------------- INFORMATION -------------------------------- + +# This the DDS Makefile for Linux and the GNU g++ compiler. +# It creates a statically linked library, libdds.a. + +# --------------------- CONFIGURATION ------------------------------ + +# You can configure the following: + +# 1. The threading systems that you want in the library. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. + +# GCD and WINAPI don't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL + +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_COMPILE = -fopenmp +THREAD_LINK = $(CC_BOOST_LINK) + +# 2. The small memory option, which causes DDS to consume a lot less +# memory and to run somewhat more slowly. + +SMALL_MEMORY = -DSMALL_MEMORY_OPTION + +# 3. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + +WARN_FLAGS = \ + -Wshadow \ + -Wsign-conversion \ + -pedantic -Wall -Wextra \ + -Wcast-align -Wcast-qual \ + -Wctor-dtor-privacy \ + -Wdisabled-optimization \ + -Winit-self \ + -Wlogical-op \ + -Wmissing-declarations \ + -Wmissing-include-dirs \ + -Wnoexcept \ + -Wold-style-cast \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wsign-promo \ + -Wstrict-null-sentinel \ + -Wstrict-overflow=1 \ + -Wswitch-default -Wundef \ + -Werror \ + -Wno-unused \ + -Wno-unknown-pragmas \ + -Wno-long-long \ + -Wno-format + +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic -std=c++11 \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) + +DLLBASE = dds +STATIC_LIB = lib$(DLLBASE).a + +include $(INCL_SOURCE) + +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) + + +linux: $(O_FILES) + gcc-ar rcs $(STATIC_LIB) $(O_FILES) + +%.o: %.cpp + $(CC) $(COMPILE_FLAGS) -c $< + +depend: + makedepend -Y -- $(SOURCE_FILES) + +clean: + rm -f $(O_FILES) $(STATIC_LIB) + +install: + test -d ../test || mkdir ../test + test -d ../examples || mkdir ../examples + cp $(STATIC_LIB) ../test + cp $(STATIC_LIB) ../examples + +include $(INCL_DEPENDS) + diff --git a/src/Makefiles/Makefile_mingw b/src/Makefiles/Makefile_mingw index c81d89c1..0ab02d08 100644 --- a/src/Makefiles/Makefile_mingw +++ b/src/Makefiles/Makefile_mingw @@ -1,37 +1,66 @@ -# This the DDS Makefile for Windows and the MinGW compiler. -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# --------------------- INFORMATION -------------------------------- -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none +# This the DDS Makefile for Windows and the mingw GNU g++ +# compiler. It assumes a Unix-like setup for some commands. # The "windres" and "cvtres" tools are used for putting version # information into the DLL in a way that Windows can see. # It is not mandatory, and if you don't have those tools, # You can remove $(VFILE).obj in the target line below. +# --------------------- CONFIGURATION ------------------------------ -# If your exact compiler name is not given here, change it. -# CC = mingw32-g++ -CC = i686-w64-mingw32-g++ +# You can configure the following: -# Use this one to get Windows multi-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic +# 1. The threading systems that you want in the DLL/executable. +# You will always get single-threading. If you have multiple +# threading systems, the default will be the multi-threading one +# with the lowest number (see System.cpp). All that matters is +# CC_THREADING. -LD_FLAGS = \ - -Wl,--subsystem,windows \ - -Wl,--output-def,$(DLLBASE).def \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup +# GCD doesn't work on Windows. +THR_BOOST = -DDDS_THREADS_BOOST +THR_GCD = -DDDS_THREADS_GCD +THR_OPENMP = -DDDS_THREADS_OPENMP +THR_WINAPI = -DDDS_THREADS_WINAPI +THR_STL = -DDDS_THREADS_STL +THREADING = $(THR_BOOST) $(THR_OPENMP) $(THR_STL) + +# If you need to add something for a threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_COMPILE = -fopenmp +THREAD_LINK = -lgomp $(CC_BOOST_LINK) + +# 2. Debugging options. (There are more granular options in debug.h.) + +DEBUG_ALL = -DDDS_DEBUG_ALL +TIMING = -DDDS_TIMING +SCHEDULER = -DDDS_SCHEDULER + +# All that matters from no. 2 and no. 3 is the following. Here you +# can add $(SMALL_MEMORY) etc. + +DDS_BEHAVIOR = + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_SOURCE = Makefiles/sources.txt +INCL_DEPENDS = Makefiles/depends_obj.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -39,6 +68,7 @@ WARN_FLAGS = \ -Wcast-align -Wcast-qual \ -Wctor-dtor-privacy \ -Wdisabled-optimization \ + -Wformat=2 \ -Winit-self \ -Wlogical-op \ -Wmissing-declarations \ @@ -46,7 +76,6 @@ WARN_FLAGS = \ -Wnoexcept \ -Wold-style-cast \ -Woverloaded-virtual \ - -Wredundant-decls \ -Wsign-promo \ -Wstrict-null-sentinel \ -Wstrict-overflow=1 \ @@ -54,56 +83,36 @@ WARN_FLAGS = \ -Werror \ -Wno-unused \ -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format + -Wno-long-long -# Here you can turn on warnings and add -DSMALL_MEMORY_OPTION -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) +COMPILE_FLAGS = -O3 -DBUILDING_EXAMPLE_DLL -fopenmp \ + $(WARN_FLAGS) \ + $(DDS_BEHAVIOR) $(THREAD_COMPILE) $(THREADING) -LIB_FLAGS = -mdll +LINK1_FLAGS = -shared +LINK2_FLAGS = \ + $(THREAD_LINK) \ + -Wl,--out-implib,libdds.a \ + -Wl,--no-undefined DLLBASE = dds DLL = $(DLLBASE).dll +DLIB = $(DLLBASE).lib EXPORTER = Exports.def VFILE = ddsres -WINDRES_FLAG = -F pe-i386 - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp +WINDRES_FLAG = -F pe-x86-64 -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) $(VFILE).o - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif +include $(INCL_SOURCE) +O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) $(VFILE).o mingw: $(O_FILES) - $(CC) $(LIB_FLAGS) $(CC_FULL_FLAGS) $(O_FILES) $(LD_FLAGS) $(EXPORTER) -o $(DLL) + $(CC) $(LINK1_FLAGS) $(O_FILES) \ + -o $(DLL) $(LINK2_FLAGS) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< + $(CC) $(COMPILE_FLAGS) -c $< $(DLLBASE).res: $(DLLBASE).rc windres $(DLLBASE).rc $(DLLBASE).res @@ -112,7 +121,7 @@ $(VFILE).o: $(DLLBASE).rc windres $(WINDRES_FLAG) $(DLLBASE).rc $(VFILE).o depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) + makedepend -Y -- $(SOURCE_FILES) clean: rm -f $(O_FILES) $(DLL) $(DLLBASE).{lib,def,exp,res} @@ -123,50 +132,8 @@ install: cp $(DLL) $(DLLBASE).def ../test cp $(DLL) $(DLLBASE).def ../examples +# If you don't have a Linux-like setup, use "del" instead of "rm" +# and "copy" instead of "cp". + +include $(INCL_DEPENDS) -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_mingw_tdc32 b/src/Makefiles/Makefile_mingw_tdc32 deleted file mode 100644 index 8623138b..00000000 --- a/src/Makefiles/Makefile_mingw_tdc32 +++ /dev/null @@ -1,167 +0,0 @@ -# This is the DDS Makefile for Windows and the tdm-gcc compiler: -# http://tdm-gcc.tdragon.net/ -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. -# Changes relative to the MinGW Makefile contributed by Sergio Polini. - -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none - -# If your exact compiler name is not given here, change it. -CC = x86_64-w64-mingw32-g++ - -# Use this one to get Windows multi-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic -m32 - -LD_FLAGS = \ - -Wl,--subsystem,windows \ - -Wl,--output-def,$(DLLBASE).def \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wnoexcept \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-null-sentinel \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -LIB_FLAGS = -mdll -m32 - -DLLBASE = dds -DLL = $(DLLBASE).dll -EXPORTER = Exports.def - -VFILE = ddsres -WINDRES_FLAG = -F pe-i386 - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) $(VFILE).o - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - -mingw: $(O_FILES) - $(CC) $(LIB_FLAGS) $(CC_FULL_FLAGS) $(O_FILES) $(LD_FLAGS) $(EXPORTER) -o $(DLL) - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< - -$(DLLBASE).res: $(DLLBASE).rc - windres $(DLLBASE).rc $(DLLBASE).res - -$(VFILE).o: $(DLLBASE).rc - windres $(WINDRES_FLAG) $(DLLBASE).rc $(VFILE).o - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(DLL) $(DLLBASE).{lib,def,exp,res} - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(DLL) $(DLLBASE).def ../test - cp $(DLL) $(DLLBASE).def ../examples - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/Makefile_mingw_tdc64 b/src/Makefiles/Makefile_mingw_tdc64 deleted file mode 100644 index 0dc5510d..00000000 --- a/src/Makefiles/Makefile_mingw_tdc64 +++ /dev/null @@ -1,167 +0,0 @@ -# This is the DDS Makefile for Windows and the tdm-gcc compiler: -# http://tdm-gcc.tdragon.net/ -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. -# Changes relative to the MinGW Makefile contributed by Sergio Polini. - -# If you want to compile a single-threaded version, use -# make DDS_THREADS=none - -# If your exact compiler name is not given here, change it. -CC = x86_64-w64-mingw32-g++ - -# Use this one to get Windows multi-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic - -LD_FLAGS = \ - -Wl,--subsystem,windows \ - -Wl,--output-def,$(DLLBASE).def \ - -Wl,--dynamicbase \ - -Wl,--nxcompat \ - -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup - - -# These flags are not turned on be default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - -Wshadow \ - -Wsign-conversion \ - -pedantic -Wall -Wextra \ - -Wcast-align -Wcast-qual \ - -Wctor-dtor-privacy \ - -Wdisabled-optimization \ - -Winit-self \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-include-dirs \ - -Wnoexcept \ - -Wold-style-cast \ - -Woverloaded-virtual \ - -Wredundant-decls \ - -Wsign-promo \ - -Wstrict-null-sentinel \ - -Wstrict-overflow=1 \ - -Wswitch-default -Wundef \ - -Werror \ - -Wno-unused \ - -Wno-unknown-pragmas \ - -Wno-long-long \ - -Wno-format - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -LIB_FLAGS = -mdll - -DLLBASE = dds -DLL = $(DLLBASE).dll -EXPORTER = Exports.def - -VFILE = ddsres -WINDRES_FLAG = -F pe-x86-64 - -SOURCE_FILES = \ - dds.cpp \ - ABsearch.cpp \ - ABstats.cpp \ - CalcTables.cpp \ - DealerPar.cpp \ - Init.cpp \ - LaterTricks.cpp \ - Moves.cpp \ - Par.cpp \ - PlayAnalyser.cpp \ - PBN.cpp \ - QuickTricks.cpp \ - Scheduler.cpp \ - SolveBoard.cpp \ - SolverIF.cpp \ - Stats.cpp \ - Timer.cpp \ - TransTable.cpp - -O_FILES = $(subst .cpp,.o,$(SOURCE_FILES)) $(VFILE).o - -ifeq ($(DDS_THREADS),none) -DDS_THR = -DDDS_THREADS_SINGLE -else -DDS_THR = -endif - - -mingw: $(O_FILES) - $(CC) $(LIB_FLAGS) $(CC_FULL_FLAGS) $(O_FILES) $(LD_FLAGS) $(EXPORTER) -o $(DLL) - -%.o: %.cpp - $(CC) $(CC_FULL_FLAGS) $(DDS_THR) -c $< - -$(DLLBASE).res: $(DLLBASE).rc - windres $(DLLBASE).rc $(DLLBASE).res - -$(VFILE).o: $(DLLBASE).rc - windres $(WINDRES_FLAG) $(DLLBASE).rc $(VFILE).o - -depend: - makedepend -Y -- $(CC_FLAGS) -- $(SOURCE_FILES) - -clean: - rm -f $(O_FILES) $(DLL) $(DLLBASE).{lib,def,exp,res} - -install: - test -d ../test || mkdir ../test - test -d ../examples || mkdir ../examples - cp $(DLL) $(DLLBASE).def ../test - cp $(DLL) $(DLLBASE).def ../examples - - -# DO NOT DELETE - -dds.o: ../include/dll.h dds.h debug.h ../include/portab.h TransTable.h -dds.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h -ABsearch.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABsearch.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -ABsearch.o: QuickTricks.h LaterTricks.h ABsearch.h -ABstats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -ABstats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -CalcTables.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -CalcTables.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h SolveBoard.h -CalcTables.o: PBN.h -DealerPar.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -DealerPar.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Init.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Init.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h Init.h -Init.o: ABsearch.h -LaterTricks.o: dds.h debug.h ../include/portab.h TransTable.h -LaterTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -LaterTricks.o: threadmem.h LaterTricks.h -Moves.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Moves.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h ABsearch.h -Par.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Par.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -PlayAnalyser.o: dds.h debug.h ../include/portab.h TransTable.h -PlayAnalyser.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -PlayAnalyser.o: Scheduler.h threadmem.h SolverIF.h PBN.h -PBN.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -PBN.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h PBN.h -QuickTricks.o: dds.h debug.h ../include/portab.h TransTable.h -QuickTricks.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h Scheduler.h -QuickTricks.o: threadmem.h QuickTricks.h -Scheduler.o: Scheduler.h dds.h debug.h ../include/portab.h TransTable.h -Scheduler.o: ../include/dll.h Timer.h ABstats.h Moves.h Stats.h -SolveBoard.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolveBoard.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h threadmem.h -SolveBoard.o: SolverIF.h SolveBoard.h PBN.h -SolverIF.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -SolverIF.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h Init.h threadmem.h -SolverIF.o: ABsearch.h SolverIF.h -Stats.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Stats.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -Timer.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -Timer.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h -TransTable.o: dds.h debug.h ../include/portab.h TransTable.h ../include/dll.h -TransTable.o: Timer.h ABstats.h Moves.h Stats.h Scheduler.h diff --git a/src/Makefiles/depends_o.txt b/src/Makefiles/depends_o.txt new file mode 100644 index 00000000..f705666f --- /dev/null +++ b/src/Makefiles/depends_o.txt @@ -0,0 +1,56 @@ +dds.o: ../include/dll.h Init.h dds.h ../include/portab.h Memory.h +dds.o: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +dump.o: dump.h dds.h ../include/portab.h ../include/dll.h Moves.h Memory.h +dump.o: TransTable.h TransTableS.h TransTableL.h File.h debug.h +ABsearch.o: TransTable.h dds.h ../include/portab.h ../include/dll.h Moves.h +ABsearch.o: QuickTricks.h Memory.h TransTableS.h TransTableL.h File.h debug.h +ABsearch.o: LaterTricks.h ABsearch.h ABstats.h TimerList.h TimerGroup.h +ABsearch.o: Timer.h dump.h +ABstats.o: ABstats.h debug.h +CalcTables.o: CalcTables.h dds.h ../include/portab.h ../include/dll.h +CalcTables.o: SolverIF.h Memory.h TransTable.h TransTableS.h TransTableL.h +CalcTables.o: Moves.h File.h debug.h SolveBoard.h System.h Scheduler.h +CalcTables.o: TimeStatList.h TimeStat.h Timer.h PBN.h +DealerPar.o: dds.h ../include/portab.h ../include/dll.h +File.o: File.h +Init.o: Init.h dds.h ../include/portab.h ../include/dll.h Memory.h +Init.o: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +Init.o: System.h Scheduler.h TimeStatList.h TimeStat.h Timer.h +LaterTricks.o: LaterTricks.h dds.h ../include/portab.h ../include/dll.h +LaterTricks.o: Memory.h TransTable.h TransTableS.h TransTableL.h Moves.h +LaterTricks.o: File.h debug.h +Memory.o: Memory.h TransTable.h dds.h ../include/portab.h ../include/dll.h +Memory.o: TransTableS.h TransTableL.h Moves.h File.h debug.h +Moves.o: Moves.h dds.h ../include/portab.h ../include/dll.h debug.h +Par.o: dds.h ../include/portab.h ../include/dll.h PBN.h +PlayAnalyser.o: PlayAnalyser.h dds.h ../include/portab.h ../include/dll.h +PlayAnalyser.o: SolverIF.h Memory.h TransTable.h TransTableS.h TransTableL.h +PlayAnalyser.o: Moves.h File.h debug.h System.h Scheduler.h TimeStatList.h +PlayAnalyser.o: TimeStat.h Timer.h PBN.h +PBN.o: dds.h ../include/portab.h ../include/dll.h PBN.h +QuickTricks.o: QuickTricks.h dds.h ../include/portab.h ../include/dll.h +QuickTricks.o: Memory.h TransTable.h TransTableS.h TransTableL.h Moves.h +QuickTricks.o: File.h debug.h +Scheduler.o: Scheduler.h dds.h ../include/portab.h ../include/dll.h +Scheduler.o: TimeStatList.h TimeStat.h Timer.h +SolveBoard.o: SolverIF.h dds.h ../include/portab.h ../include/dll.h Memory.h +SolveBoard.o: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +SolveBoard.o: SolveBoard.h System.h Scheduler.h TimeStatList.h TimeStat.h +SolveBoard.o: Timer.h PBN.h +SolverIF.o: SolverIF.h dds.h ../include/portab.h ../include/dll.h Memory.h +SolverIF.o: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +SolverIF.o: Init.h ABsearch.h TimerList.h TimerGroup.h Timer.h System.h +SolverIF.o: Scheduler.h TimeStatList.h TimeStat.h dump.h +System.o: SolveBoard.h dds.h ../include/portab.h ../include/dll.h +System.o: CalcTables.h PlayAnalyser.h parallel.h System.h Memory.h +System.o: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +System.o: Scheduler.h TimeStatList.h TimeStat.h Timer.h +Timer.o: Timer.h +TimerGroup.o: TimerGroup.h Timer.h +TimerList.o: TimerList.h TimerGroup.h Timer.h debug.h +TimeStat.o: TimeStat.h +TimeStatList.o: TimeStatList.h TimeStat.h +TransTableS.o: TransTableS.h TransTable.h dds.h ../include/portab.h +TransTableS.o: ../include/dll.h debug.h +TransTableL.o: TransTableL.h ../include/dll.h dds.h ../include/portab.h +TransTableL.o: TransTable.h debug.h diff --git a/src/Makefiles/depends_obj.txt b/src/Makefiles/depends_obj.txt new file mode 100644 index 00000000..67df28f7 --- /dev/null +++ b/src/Makefiles/depends_obj.txt @@ -0,0 +1,56 @@ +dds.obj: ../include/dll.h Init.h dds.h ../include/portab.h Memory.h +dds.obj: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +dump.obj: dump.h dds.h ../include/portab.h ../include/dll.h Moves.h Memory.h +dump.obj: TransTable.h TransTableS.h TransTableL.h File.h debug.h +ABsearch.obj: TransTable.h dds.h ../include/portab.h ../include/dll.h Moves.h +ABsearch.obj: QuickTricks.h Memory.h TransTableS.h TransTableL.h File.h +ABsearch.obj: debug.h LaterTricks.h ABsearch.h ABstats.h TimerList.h +ABsearch.obj: TimerGroup.h Timer.h dump.h +ABstats.obj: ABstats.h debug.h +CalcTables.obj: CalcTables.h dds.h ../include/portab.h ../include/dll.h +CalcTables.obj: SolverIF.h Memory.h TransTable.h TransTableS.h TransTableL.h +CalcTables.obj: Moves.h File.h debug.h SolveBoard.h System.h Scheduler.h +CalcTables.obj: TimeStatList.h TimeStat.h Timer.h PBN.h +DealerPar.obj: dds.h ../include/portab.h ../include/dll.h +File.obj: File.h +Init.obj: Init.h dds.h ../include/portab.h ../include/dll.h Memory.h +Init.obj: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +Init.obj: System.h Scheduler.h TimeStatList.h TimeStat.h Timer.h +LaterTricks.obj: LaterTricks.h dds.h ../include/portab.h ../include/dll.h +LaterTricks.obj: Memory.h TransTable.h TransTableS.h TransTableL.h Moves.h +LaterTricks.obj: File.h debug.h +Memory.obj: Memory.h TransTable.h dds.h ../include/portab.h ../include/dll.h +Memory.obj: TransTableS.h TransTableL.h Moves.h File.h debug.h +Moves.obj: Moves.h dds.h ../include/portab.h ../include/dll.h debug.h +Par.obj: dds.h ../include/portab.h ../include/dll.h PBN.h +PlayAnalyser.obj: PlayAnalyser.h dds.h ../include/portab.h ../include/dll.h +PlayAnalyser.obj: SolverIF.h Memory.h TransTable.h TransTableS.h +PlayAnalyser.obj: TransTableL.h Moves.h File.h debug.h System.h Scheduler.h +PlayAnalyser.obj: TimeStatList.h TimeStat.h Timer.h PBN.h +PBN.obj: dds.h ../include/portab.h ../include/dll.h PBN.h +QuickTricks.obj: QuickTricks.h dds.h ../include/portab.h ../include/dll.h +QuickTricks.obj: Memory.h TransTable.h TransTableS.h TransTableL.h Moves.h +QuickTricks.obj: File.h debug.h +Scheduler.obj: Scheduler.h dds.h ../include/portab.h ../include/dll.h +Scheduler.obj: TimeStatList.h TimeStat.h Timer.h +SolveBoard.obj: SolverIF.h dds.h ../include/portab.h ../include/dll.h +SolveBoard.obj: Memory.h TransTable.h TransTableS.h TransTableL.h Moves.h +SolveBoard.obj: File.h debug.h SolveBoard.h System.h Scheduler.h +SolveBoard.obj: TimeStatList.h TimeStat.h Timer.h PBN.h +SolverIF.obj: SolverIF.h dds.h ../include/portab.h ../include/dll.h Memory.h +SolverIF.obj: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +SolverIF.obj: Init.h ABsearch.h TimerList.h TimerGroup.h Timer.h System.h +SolverIF.obj: Scheduler.h TimeStatList.h TimeStat.h dump.h +System.obj: SolveBoard.h dds.h ../include/portab.h ../include/dll.h +System.obj: CalcTables.h PlayAnalyser.h parallel.h System.h Memory.h +System.obj: TransTable.h TransTableS.h TransTableL.h Moves.h File.h debug.h +System.obj: Scheduler.h TimeStatList.h TimeStat.h Timer.h +Timer.obj: Timer.h +TimerGroup.obj: TimerGroup.h Timer.h +TimerList.obj: TimerList.h TimerGroup.h Timer.h debug.h +TimeStat.obj: TimeStat.h +TimeStatList.obj: TimeStatList.h TimeStat.h +TransTableS.obj: TransTableS.h TransTable.h dds.h ../include/portab.h +TransTableS.obj: ../include/dll.h debug.h +TransTableL.obj: TransTableL.h ../include/dll.h dds.h ../include/portab.h +TransTableL.obj: TransTable.h debug.h diff --git a/src/Makefiles/sources.txt b/src/Makefiles/sources.txt new file mode 100644 index 00000000..566a0584 --- /dev/null +++ b/src/Makefiles/sources.txt @@ -0,0 +1,28 @@ +SOURCE_FILES = \ + dds.cpp \ + dump.cpp \ + ABsearch.cpp \ + ABstats.cpp \ + CalcTables.cpp \ + DealerPar.cpp \ + File.cpp \ + Init.cpp \ + LaterTricks.cpp \ + Memory.cpp \ + Moves.cpp \ + Par.cpp \ + PlayAnalyser.cpp \ + PBN.cpp \ + QuickTricks.cpp \ + Scheduler.cpp \ + SolveBoard.cpp \ + SolverIF.cpp \ + System.cpp \ + ThreadMgr.cpp \ + Timer.cpp \ + TimerGroup.cpp \ + TimerList.cpp \ + TimeStat.cpp \ + TimeStatList.cpp \ + TransTableS.cpp \ + TransTableL.cpp diff --git a/src/Memory.cpp b/src/Memory.cpp new file mode 100644 index 00000000..f333d01f --- /dev/null +++ b/src/Memory.cpp @@ -0,0 +1,130 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include "Memory.h" + + +Memory::Memory() +{ + Memory::Reset(); +} + + +Memory::~Memory() +{ +} + + +void Memory::Reset() +{ + nThreads = 0; +} + + +void Memory::ResetThread(const unsigned thrId) +{ + memory[thrId]->transTable->ResetMemory(TT_RESET_FREE_MEMORY); + memory[thrId]->memUsed = Memory::MemoryInUseMB(thrId); +} + + +void Memory::ReturnThread(const unsigned thrId) +{ + memory[thrId]->transTable->ReturnAllMemory(); + memory[thrId]->memUsed = Memory::MemoryInUseMB(thrId); +} + + +void Memory::Resize( + const unsigned n, + const TTmemory flag, + const int memDefault_MB, + const int memMaximum_MB) +{ + if (nThreads == n) + return; + + if (nThreads > n) + { + // Downsize. + for (unsigned i = n; i < nThreads; i++) + { + memory[i]->transTable->ReturnAllMemory(); + delete memory[i]->transTable; + delete memory[i]; + } + memory.resize(static_cast(n)); + threadSizes.resize(static_cast(n)); + } + else + { + // Upsize. + memory.resize(n); + threadSizes.resize(n); + for (unsigned i = nThreads; i < n; i++) + { + memory[i] = new ThreadData; + if (flag == DDS_TT_SMALL) + { + memory[i]->transTable = new TransTableS; + threadSizes[i] = "S"; + } + else + { + memory[i]->transTable = new TransTableL; + threadSizes[i] = "L"; + } + + memory[i]->transTable->SetMemoryDefault(memDefault_MB); + memory[i]->transTable->SetMemoryMaximum(memMaximum_MB); + + memory[i]->transTable->MakeTT(); + } + } + + nThreads = n; +} + + +int Memory::NumThreads() const +{ + return static_cast(nThreads); +} + + +ThreadData * Memory::GetPtr(const unsigned thrId) +{ + if (thrId >= nThreads) + { + cout << "Memory::GetPtr: " << thrId << " vs. " << nThreads << endl; + exit(1); + } + return memory[thrId]; +} + + +double Memory::MemoryInUseMB(const unsigned thrId) const +{ + return memory[thrId]->transTable->MemoryInUse() + + 8192. * sizeof(relRanksType) / static_cast(1024.); +} + + +void Memory::ReturnAllMemory() +{ + Memory::Resize(0, DDS_TT_SMALL, 0, 0); +} + + +string Memory::ThreadSize(const unsigned thrId) const +{ + return threadSizes[thrId]; +} + diff --git a/src/Memory.h b/src/Memory.h new file mode 100644 index 00000000..3f86fa35 --- /dev/null +++ b/src/Memory.h @@ -0,0 +1,153 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_MEMORY_H +#define DDS_MEMORY_H + +#include + +#include "TransTable.h" +#include "TransTableS.h" +#include "TransTableL.h" + +#include "Moves.h" +#include "File.h" +#include "debug.h" + +#ifdef DDS_AB_STATS + #include "ABstats.h" +#endif + +#ifdef DDS_TIMING + #include "TimerList.h" +#endif + +using namespace std; + + +enum TTmemory +{ + DDS_TT_SMALL = 0, + DDS_TT_LARGE = 1 +}; + +struct WinnerEntryType +{ + int suit; + int winnerRank; + int winnerHand; + int secondRank; + int secondHand; +}; + +struct WinnersType +{ + int number; + WinnerEntryType winner[4]; +}; + + +struct ThreadData +{ + int nodeTypeStore[DDS_HANDS]; + int iniDepth; + bool val; + + unsigned short int suit[DDS_HANDS][DDS_SUITS]; + int trump; + + pos lookAheadPos; // Recursive alpha-beta data + bool analysisFlag; + unsigned short int lowestWin[50][DDS_SUITS]; + WinnersType winners[13]; + moveType forbiddenMoves[14]; + moveType bestMove[50]; + moveType bestMoveTT[50]; + + double memUsed; + int nodes; + int trickNodes; + + // Constant for a given hand. + // 960 KB + relRanksType rel[8192]; + + TransTable * transTable; + + Moves moves; + +#ifdef DDS_TOP_LEVEL + File fileTopLevel; +#endif + +#ifdef DDS_AB_STATS + ABstats ABStats; + File fileABstats; +#endif + +#ifdef DDS_AB_HITS + File fileRetrieved; + File fileStored; +#endif + +#ifdef DDS_TT_STATS + File fileTTstats; +#endif + +#ifdef DDS_TIMING + TimerList timerList; + File fileTimerList; +#endif + +#ifdef DDS_MOVES + File fileMoves; +#endif + +}; + + +class Memory +{ + private: + + vector memory; + unsigned nThreads; + + vector threadSizes; + + public: + + Memory(); + + ~Memory(); + + void Reset(); + + void ResetThread(const unsigned thrId); + + void ReturnThread(const unsigned thrId); + + void Resize( + const unsigned n, + const TTmemory flag, + const int memDefault_MB, + const int memMaximum_MB); + + int NumThreads() const; + + ThreadData * GetPtr(const unsigned thrId); + + double MemoryInUseMB(const unsigned thrId) const; + + void ReturnAllMemory(); + + string ThreadSize(const unsigned thrId) const; +}; + +#endif diff --git a/src/Moves.cpp b/src/Moves.cpp index c82188de..c2e5e629 100644 --- a/src/Moves.cpp +++ b/src/Moves.cpp @@ -2,17 +2,17 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include +#include +#include -#include "dds.h" #include "Moves.h" -#include "ABsearch.h" +#include "debug.h" #ifdef DDS_MOVES #define MG_REGISTER(a, b) lastCall[currTrick][b] = a @@ -21,10 +21,10 @@ #endif -int RegisterList[16] = +const MGtype RegisterList[16] = { MG_NT0, MG_TRUMP0, - -1, -1, + MG_SIZE, MG_SIZE, // Unused MG_NT_NOTVOID1, MG_TRUMP_NOTVOID1, MG_NT_VOID1, MG_TRUMP_VOID1, @@ -39,32 +39,32 @@ int RegisterList[16] = Moves::Moves() { - sprintf(funcName[MG_NT0] , "%s", "NT0"); - sprintf(funcName[MG_TRUMP0] , "%s", "Trump0"); - sprintf(funcName[MG_NT_VOID1] , "%s", "NT_Void1"); - sprintf(funcName[MG_TRUMP_VOID1] , "%s", "Trump_Void1"); - sprintf(funcName[MG_NT_NOTVOID1] , "%s", "NT_Notvoid1"); - sprintf(funcName[MG_TRUMP_NOTVOID1], "%s", "Trump_Notvoid1"); - sprintf(funcName[MG_NT_VOID2] , "%s", "NT_Void2"); - sprintf(funcName[MG_TRUMP_VOID2] , "%s", "Trump_Void2"); - sprintf(funcName[MG_NT_NOTVOID2] , "%s", "NT_Notvoid2"); - sprintf(funcName[MG_TRUMP_NOTVOID2], "%s", "Trump_Notvoid2"); - sprintf(funcName[MG_NT_VOID3] , "%s", "NT_Void3"); - sprintf(funcName[MG_TRUMP_VOID3] , "%s", "Trump_Void3"); - sprintf(funcName[MG_COMB_NOTVOID3] , "%s", "Comb_Notvoid3"); + funcName[MG_NT0] = "NT0"; + funcName[MG_TRUMP0] = "Trump0"; + funcName[MG_NT_VOID1] = "NT_Void1"; + funcName[MG_TRUMP_VOID1] = "Trump_Void1"; + funcName[MG_NT_NOTVOID1] = "NT_Notvoid1"; + funcName[MG_TRUMP_NOTVOID1] = "Trump_Notvoid1"; + funcName[MG_NT_VOID2] = "NT_Void2"; + funcName[MG_TRUMP_VOID2] = "Trump_Void2"; + funcName[MG_NT_NOTVOID2] = "NT_Notvoid2"; + funcName[MG_TRUMP_NOTVOID2] = "Trump_Notvoid2"; + funcName[MG_NT_VOID3] = "NT_Void3"; + funcName[MG_TRUMP_VOID3] = "Trump_Void3"; + funcName[MG_COMB_NOTVOID3] = "Comb_Notvoid3"; for (int t = 0; t < 13; t++) { for (int h = 0; h < DDS_HANDS; h++) { - lastCall[t][h] = -1; + lastCall[t][h] = MG_SIZE; trickTable[t][h].count = 0; trickSuitTable[t][h].count = 0; trickDetailTable [t][h].nfuncs = 0; trickDetailSuitTable[t][h].nfuncs = 0; - for (int i = 0; i < MG_NUM_FUNCTIONS; i++) + for (int i = 0; i < MG_SIZE; i++) { trickDetailTable [t][h].list[i].count = 0; trickDetailSuitTable[t][h].list[i].count = 0; @@ -72,17 +72,14 @@ Moves::Moves() } } - trickFuncTable .nfuncs = 0; + trickFuncTable.nfuncs = 0; trickFuncSuitTable.nfuncs = 0; - for (int i = 0; i < MG_NUM_FUNCTIONS; i++) + for (int i = 0; i < MG_SIZE; i++) { trickFuncTable .list[i].count = 0; trickFuncSuitTable.list[i].count = 0; } - strcpy(fname, ""); - fp = stdout; - WeightList[ 4] = &Moves::WeightAllocNTNotvoid1; WeightList[ 5] = &Moves::WeightAllocTrumpNotvoid1; WeightList[ 6] = &Moves::WeightAllocNTVoid1; @@ -100,37 +97,19 @@ Moves::Moves() } -void Moves::SetFile(char * ourFname) -{ - if (strlen(ourFname) > 80) - return; - - if (fp != stdout) // Already set - return; - - strncpy(fname, ourFname, strlen(ourFname)); - - fp = fopen(fname, "w"); - if (! fp) - fp = stdout; -} - - Moves::~Moves() { - if (fp != stdout && fp != nullptr) - fclose(fp); } void Moves::Init( - int tricks, - int relStartHand, - int initialRanks[], - int initialSuits[], - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - int ourTrump, - int ourLeadHand) + const int tricks, + const int relStartHand, + const int initialRanks[], + const int initialSuits[], + const unsigned short rankInSuit[DDS_HANDS][DDS_SUITS], + const int ourTrump, + const int ourLeadHand) { currTrick = tricks; trump = ourTrump; @@ -167,19 +146,19 @@ void Moves::Init( void Moves::Reinit( - int tricks, - int ourLeadHand) + const int tricks, + const int ourLeadHand) { track[tricks].leadHand = ourLeadHand; } int Moves::MoveGen0( - int tricks, - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]) + const int tricks, + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]) { trackp = &track[tricks]; leadHand = trackp->leadHand; @@ -189,18 +168,18 @@ int Moves::MoveGen0( moveGroupType * mp; int removed, g, rank, seq; - movePlyType * listp = &moveList[tricks][0]; - mply = listp->move; + movePlyType& list = moveList[tricks][0]; + mply = list.move; for (int s = 0; s < DDS_SUITS; s++) trackp->lowestWin[0][s] = 0; numMoves = 0; bool ftest = ((trump != DDS_NOTRUMP) && - (posPoint->winner[trump].rank != 0)); + (tpos.winner[trump].rank != 0)); for (suit = 0; suit < DDS_SUITS; suit++) { - unsigned short ris = posPoint->rankInSuit[leadHand][suit]; + unsigned short ris = tpos.rankInSuit[leadHand][suit]; if (ris == 0) continue; lastNumMoves = numMoves; @@ -225,11 +204,9 @@ int Moves::MoveGen0( } if (ftest) - Moves::WeightAllocTrump0(posPoint, - bestMove, bestMoveTT, thrp_rel); + Moves::WeightAllocTrump0(tpos, bestMove, bestMoveTT, thrp_rel); else - Moves::WeightAllocNT0(posPoint, - bestMove, bestMoveTT, thrp_rel); + Moves::WeightAllocNT0(tpos, bestMove, bestMoveTT, thrp_rel); } #ifdef DDS_MOVES @@ -239,8 +216,8 @@ int Moves::MoveGen0( MG_REGISTER(MG_NT0, 0); #endif - listp->current = 0; - listp->last = numMoves - 1; + list.current = 0; + list.last = numMoves - 1; if (numMoves != 1) Moves::MergeSort(); return numMoves; @@ -248,9 +225,9 @@ int Moves::MoveGen0( int Moves::MoveGen123( - int tricks, - int handRel, - pos * posPoint) + const int tricks, + const int handRel, + const pos& tpos) { trackp = &track[tricks]; leadHand = trackp->leadHand; @@ -261,8 +238,8 @@ int Moves::MoveGen123( moveGroupType * mp; int removed, g, rank, seq; - movePlyType * listp = &moveList[tricks][handRel]; - mply = listp->move; + movePlyType& list = moveList[tricks][handRel]; + mply = list.move; for (int s = 0; s < DDS_SUITS; s++) trackp->lowestWin[handRel][s] = 0; @@ -271,9 +248,9 @@ int Moves::MoveGen123( WeightPtr WeightFnc; int findex; int ftest = ((trump != DDS_NOTRUMP) && - (posPoint->winner[trump].rank != 0) ? 1 : 0); + (tpos.winner[trump].rank != 0) ? 1 : 0); - unsigned short ris = posPoint->rankInSuit[currHand][leadSuit]; + unsigned short ris = tpos.rankInSuit[currHand][leadSuit]; if (ris != 0) { @@ -302,14 +279,12 @@ int Moves::MoveGen123( MG_REGISTER(RegisterList[findex], handRel); #endif - listp->current = 0; - listp->last = numMoves - 1; + list.current = 0; + list.last = numMoves - 1; if (numMoves == 1) return numMoves; - // WeightFnc = WeightList[findex]; - // (this->*WeightFnc)(posPoint); - (this->*WeightList[findex])(posPoint); + (this->*WeightList[findex])(tpos); Moves::MergeSort(); return numMoves; @@ -324,7 +299,7 @@ int Moves::MoveGen123( for (suit = 0; suit < DDS_SUITS; suit++) { - ris = posPoint->rankInSuit[currHand][suit]; + ris = tpos.rankInSuit[currHand][suit]; if (ris == 0) continue; lastNumMoves = numMoves; @@ -348,11 +323,11 @@ int Moves::MoveGen123( g--; } - (this->*WeightFnc)(posPoint); + (this->*WeightFnc)(tpos); } - listp->current = 0; - listp->last = numMoves - 1; + list.current = 0; + list.last = numMoves - 1; if (numMoves != 1) Moves::MergeSort(); return numMoves; @@ -360,15 +335,15 @@ int Moves::MoveGen123( void Moves::WeightAllocTrump0( - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]) + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]) { - unsigned short suitCount = posPoint->length[leadHand][suit]; - unsigned short suitCountLH = posPoint->length[lho[leadHand]][suit]; - unsigned short suitCountRH = posPoint->length[rho[leadHand]][suit]; - unsigned short aggr = posPoint->aggr[suit]; + const unsigned short suitCount = tpos.length[leadHand][suit]; + const unsigned short suitCountLH = tpos.length[lho[leadHand]][suit]; + const unsigned short suitCountRH = tpos.length[rho[leadHand]][suit]; + const unsigned short aggr = tpos.aggr[suit]; // Why? int countLH = (suitCountLH == 0 ? currTrick + 1 : suitCountLH) << 2; @@ -385,22 +360,22 @@ void Moves::WeightAllocTrump0( /* Discourage suit if LHO or RHO can ruff. */ if ((suit != trump) && - (((posPoint->rankInSuit[lho[leadHand]][suit] == 0) && - (posPoint->rankInSuit[lho[leadHand]][trump] != 0)) || - ((posPoint->rankInSuit[rho[leadHand]][suit] == 0) && - (posPoint->rankInSuit[rho[leadHand]][trump] != 0)))) + (((tpos.rankInSuit[lho[leadHand]][suit] == 0) && + (tpos.rankInSuit[lho[leadHand]][trump] != 0)) || + ((tpos.rankInSuit[rho[leadHand]][suit] == 0) && + (tpos.rankInSuit[rho[leadHand]][trump] != 0)))) suitBonus = -12; /* Encourage suit if partner can ruff. */ if ((suit != trump) && - (posPoint->length[partner[leadHand]][suit] == 0) && - (posPoint->length[partner[leadHand]][trump] > 0) && + (tpos.length[partner[leadHand]][suit] == 0) && + (tpos.length[partner[leadHand]][trump] > 0) && (suitCountRH > 0)) suitBonus += 17; /* Discourage suit if RHO has high card. */ - if ((posPoint->winner[suit].hand == rho[leadHand]) || - (posPoint->secondBest[suit].hand == rho[leadHand])) + if ((tpos.winner[suit].hand == rho[leadHand]) || + (tpos.secondBest[suit].hand == rho[leadHand])) { if (suitCountRH != 1) suitBonus += -12; @@ -409,20 +384,20 @@ void Moves::WeightAllocTrump0( /* Try suit if LHO has winning card and partner second best. Exception: partner has singleton. */ - else if ((posPoint->winner[suit].hand == lho[leadHand]) && - (posPoint->secondBest[suit].hand == partner[leadHand])) + else if ((tpos.winner[suit].hand == lho[leadHand]) && + (tpos.secondBest[suit].hand == partner[leadHand])) { /* This case was suggested by Joël Bradmetz. */ - if (posPoint->length[partner[leadHand]][suit] != 1) + if (tpos.length[partner[leadHand]][suit] != 1) suitBonus += 27; } /* Encourage play of suit where partner wins and returns the suit for a ruff. */ if ((suit != trump) && (suitCount == 1) && - (posPoint->length[leadHand][trump] > 0) && - (posPoint->length[partner[leadHand]][suit] > 1) && - (posPoint->winner[suit].hand == partner[leadHand])) + (tpos.length[leadHand][trump] > 0) && + (tpos.length[partner[leadHand]][suit] > 1) && + (tpos.winner[suit].hand == partner[leadHand])) suitBonus += 19; @@ -433,40 +408,40 @@ void Moves::WeightAllocTrump0( int suitWeightDelta = suitBonus + suitWeightD; - if (posPoint->winner[suit].rank == mply[k].rank) + if (tpos.winner[suit].rank == mply[k].rank) { if ((suit != trump)) { - if ((posPoint->length[partner[leadHand]][suit] != 0) || - (posPoint->length[partner[leadHand]][trump] == 0)) + if ((tpos.length[partner[leadHand]][suit] != 0) || + (tpos.length[partner[leadHand]][trump] == 0)) { - if (((posPoint->length[lho[leadHand]][suit] != 0) || - (posPoint->length[lho[leadHand]][trump] == 0)) && - ((posPoint->length[rho[leadHand]][suit] != 0) || - (posPoint->length[rho[leadHand]][trump] == 0))) + if (((tpos.length[lho[leadHand]][suit] != 0) || + (tpos.length[lho[leadHand]][trump] == 0)) && + ((tpos.length[rho[leadHand]][suit] != 0) || + (tpos.length[rho[leadHand]][trump] == 0))) winMove = true; } - else if (((posPoint->length[lho[leadHand]][suit] != 0) || - (posPoint->rankInSuit[partner[leadHand]][trump] > - posPoint->rankInSuit[lho[leadHand]][trump])) && - ((posPoint->length[rho[leadHand]][suit] != 0) || - (posPoint->rankInSuit[partner[leadHand]][trump] > - posPoint->rankInSuit[rho[leadHand]][trump]))) + else if (((tpos.length[lho[leadHand]][suit] != 0) || + (tpos.rankInSuit[partner[leadHand]][trump] > + tpos.rankInSuit[lho[leadHand]][trump])) && + ((tpos.length[rho[leadHand]][suit] != 0) || + (tpos.rankInSuit[partner[leadHand]][trump] > + tpos.rankInSuit[rho[leadHand]][trump]))) winMove = true; } else winMove = true; } - else if (posPoint->rankInSuit[partner[leadHand]][suit] > - (posPoint->rankInSuit[lho[leadHand]][suit] | - posPoint->rankInSuit[rho[leadHand]][suit])) + else if (tpos.rankInSuit[partner[leadHand]][suit] > + (tpos.rankInSuit[lho[leadHand]][suit] | + tpos.rankInSuit[rho[leadHand]][suit])) { if (suit != trump) { - if (((posPoint->length[lho[leadHand]][suit] != 0) || - (posPoint->length[lho[leadHand]][trump] == 0)) && - ((posPoint->length[rho[leadHand]][suit] != 0) || - (posPoint->length[rho[leadHand]][trump] == 0))) + if (((tpos.length[lho[leadHand]][suit] != 0) || + (tpos.length[lho[leadHand]][trump] == 0)) && + ((tpos.length[rho[leadHand]][suit] != 0) || + (tpos.length[rho[leadHand]][trump] == 0))) winMove = true; } else @@ -474,31 +449,31 @@ void Moves::WeightAllocTrump0( } else if (suit != trump) { - if ((posPoint->length[partner[leadHand]][suit] == 0) && - (posPoint->length[partner[leadHand]][trump] != 0)) + if ((tpos.length[partner[leadHand]][suit] == 0) && + (tpos.length[partner[leadHand]][trump] != 0)) { - if ((posPoint->length[lho[leadHand]][suit] == 0) && - (posPoint->length[lho[leadHand]][trump] != 0) && - (posPoint->length[rho[leadHand]][suit] == 0) && - (posPoint->length[rho[leadHand]][trump] != 0)) + if ((tpos.length[lho[leadHand]][suit] == 0) && + (tpos.length[lho[leadHand]][trump] != 0) && + (tpos.length[rho[leadHand]][suit] == 0) && + (tpos.length[rho[leadHand]][trump] != 0)) { - if (posPoint->rankInSuit[partner[leadHand]][trump] > - (posPoint->rankInSuit[lho[leadHand]][trump] | - posPoint->rankInSuit[rho[leadHand]][trump])) + if (tpos.rankInSuit[partner[leadHand]][trump] > + (tpos.rankInSuit[lho[leadHand]][trump] | + tpos.rankInSuit[rho[leadHand]][trump])) winMove = true; } - else if ((posPoint->length[lho[leadHand]][suit] == 0) && - (posPoint->length[lho[leadHand]][trump] != 0)) + else if ((tpos.length[lho[leadHand]][suit] == 0) && + (tpos.length[lho[leadHand]][trump] != 0)) { - if (posPoint->rankInSuit[partner[leadHand]][trump] - > posPoint->rankInSuit[lho[leadHand]][trump]) + if (tpos.rankInSuit[partner[leadHand]][trump] + > tpos.rankInSuit[lho[leadHand]][trump]) winMove = true; } - else if ((posPoint->length[rho[leadHand]][suit] == 0) && - (posPoint->length[rho[leadHand]][trump] != 0)) + else if ((tpos.length[rho[leadHand]][suit] == 0) && + (tpos.length[rho[leadHand]][trump] != 0)) { - if (posPoint->rankInSuit[partner[leadHand]][trump] - > posPoint->rankInSuit[rho[leadHand]][trump]) + if (tpos.rankInSuit[partner[leadHand]][trump] + > tpos.rankInSuit[rho[leadHand]][trump]) winMove = true; } else @@ -510,28 +485,28 @@ void Moves::WeightAllocTrump0( { /* Encourage ruffing LHO or RHO singleton, highest card. */ if (((suitCountLH == 1) && - (posPoint->winner[suit].hand == lho[leadHand])) + (tpos.winner[suit].hand == lho[leadHand])) || ((suitCountRH == 1) && - (posPoint->winner[suit].hand == rho[leadHand]))) + (tpos.winner[suit].hand == rho[leadHand]))) mply[k].weight = suitWeightDelta + 35 + rRank; /* Lead hand has the highest card. */ - else if (posPoint->winner[suit].hand == leadHand) + else if (tpos.winner[suit].hand == leadHand) { /* Also, partner has second highest card. */ - if (posPoint->secondBest[suit].hand == partner[leadHand]) + if (tpos.secondBest[suit].hand == partner[leadHand]) mply[k].weight = suitWeightDelta + 48 + rRank; - else if (posPoint->winner[suit].rank == mply[k].rank) + else if (tpos.winner[suit].rank == mply[k].rank) /* If the current card to play is the highest card. */ mply[k].weight = suitWeightDelta + 31; else mply[k].weight = suitWeightDelta - 3 + rRank; } - else if (posPoint->winner[suit].hand == partner[leadHand]) + else if (tpos.winner[suit].hand == partner[leadHand]) { /* If partner has highest card */ - if (posPoint->secondBest[suit].hand == leadHand) + if (tpos.secondBest[suit].hand == leadHand) mply[k].weight = suitWeightDelta + 42 + rRank; else mply[k].weight = suitWeightDelta + 28 + rRank; @@ -539,7 +514,7 @@ void Moves::WeightAllocTrump0( /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mply[k].sequence) && - (mply[k].rank == posPoint->secondBest[suit].rank)) + (mply[k].rank == tpos.secondBest[suit].rank)) mply[k].weight = suitWeightDelta + 40; else if (mply[k].sequence) mply[k].weight = suitWeightDelta + 22 + rRank; @@ -550,11 +525,11 @@ void Moves::WeightAllocTrump0( or was stored as the best move in a transposition table entry match. */ - if ((bestMove->suit == suit) && - (bestMove->rank == mply[k].rank)) + if ((bestMove.suit == suit) && + (bestMove.rank == mply[k].rank)) mply[k].weight += 55; - else if ((bestMoveTT->suit == suit) && - (bestMoveTT->rank == mply[k].rank)) + else if ((bestMoveTT.suit == suit) && + (bestMoveTT.rank == mply[k].rank)) mply[k].weight += 18; } else @@ -566,37 +541,37 @@ void Moves::WeightAllocTrump0( int thirdBestHand = thrp_rel[aggr].absRank[3][suit].hand; - if ((posPoint->secondBest[suit].hand == partner[leadHand]) && + if ((tpos.secondBest[suit].hand == partner[leadHand]) && (partner[leadHand] == thirdBestHand)) suitWeightDelta += 20; - else if (((posPoint->secondBest[suit].hand == leadHand) && + else if (((tpos.secondBest[suit].hand == leadHand) && (partner[leadHand] == thirdBestHand) && - (posPoint->length[partner[leadHand]][suit] > 1)) || - ((posPoint->secondBest[suit].hand == partner[leadHand]) && + (tpos.length[partner[leadHand]][suit] > 1)) || + ((tpos.secondBest[suit].hand == partner[leadHand]) && (leadHand == thirdBestHand) && - (posPoint->length[partner[leadHand]][suit] > 1))) + (tpos.length[partner[leadHand]][suit] > 1))) suitWeightDelta += 13; /* Higher weight if LHO or RHO has the highest (winning) card as a singleton. */ if (((suitCountLH == 1) && - (posPoint->winner[suit].hand == lho[leadHand])) + (tpos.winner[suit].hand == lho[leadHand])) || ((suitCountRH == 1) && - (posPoint->winner[suit].hand == rho[leadHand]))) + (tpos.winner[suit].hand == rho[leadHand]))) mply[k].weight = suitWeightDelta + rRank + 2; - else if (posPoint->winner[suit].hand == leadHand) + else if (tpos.winner[suit].hand == leadHand) { - if (posPoint->secondBest[suit].hand == partner[leadHand]) + if (tpos.secondBest[suit].hand == partner[leadHand]) /* Opponents win by ruffing */ mply[k].weight = suitWeightDelta + 33 + rRank; - else if (posPoint->winner[suit].rank == mply[k].rank) + else if (tpos.winner[suit].rank == mply[k].rank) /* Opponents win by ruffing */ mply[k].weight = suitWeightDelta + 38; else mply[k].weight = suitWeightDelta - 14 + rRank; } - else if (posPoint->winner[suit].hand == partner[leadHand]) + else if (tpos.winner[suit].hand == partner[leadHand]) { /* Opponents win by ruffing */ mply[k].weight = suitWeightDelta + 34 + rRank; @@ -604,7 +579,7 @@ void Moves::WeightAllocTrump0( /* Encourage playing second highest rank if hand also has third highest rank. */ else if ((mply[k].sequence) && - (mply[k].rank == posPoint->secondBest[suit].rank)) + (mply[k].rank == tpos.secondBest[suit].rank)) mply[k].weight = suitWeightDelta + 35; else mply[k].weight = suitWeightDelta + 17 - (mply[k].rank); @@ -613,8 +588,8 @@ void Moves::WeightAllocTrump0( or was stored as the best move in a transposition table entry match. */ - if ((bestMove->suit == suit) && - (bestMove->rank == mply[k].rank)) + if ((bestMove.suit == suit) && + (bestMove.rank == mply[k].rank)) mply[k].weight += 18; } } @@ -622,27 +597,27 @@ void Moves::WeightAllocTrump0( void Moves::WeightAllocNT0( - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]) + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]) { - int aggr = posPoint->aggr[suit]; + int aggr = tpos.aggr[suit]; /* Discourage a suit selection where the search tree appears larger than for the alternative suits: the search is estimated to be small when the added number of alternative cards to play for the opponents is small. */ - unsigned short suitCountLH = posPoint->length[lho[leadHand]][suit]; - unsigned short suitCountRH = posPoint->length[rho[leadHand]][suit]; + unsigned short suitCountLH = tpos.length[lho[leadHand]][suit]; + unsigned short suitCountRH = tpos.length[rho[leadHand]][suit]; // Why? int countLH = (suitCountLH == 0 ? currTrick + 1 : suitCountLH) << 2; int countRH = (suitCountRH == 0 ? currTrick + 1 : suitCountRH) << 2; int suitWeightD = - (((countLH + countRH) << 5) / 19); - if (posPoint->length[partner[leadHand]][suit] == 0) + if (tpos.length[partner[leadHand]][suit] == 0) suitWeightD += -9; for (int k = lastNumMoves; k < numMoves; k++) @@ -650,22 +625,22 @@ void Moves::WeightAllocNT0( int suitWeightDelta = suitWeightD; int rRank = relRank[aggr][mply[k].rank]; - if (posPoint->winner[suit].rank == mply[k].rank || - (posPoint->rankInSuit[partner[leadHand]][suit] > - (posPoint->rankInSuit[lho[leadHand]][suit] | - posPoint->rankInSuit[rho[leadHand]][suit]))) + if (tpos.winner[suit].rank == mply[k].rank || + (tpos.rankInSuit[partner[leadHand]][suit] > + (tpos.rankInSuit[lho[leadHand]][suit] | + tpos.rankInSuit[rho[leadHand]][suit]))) { // Can win trick, ourselves or partner. // FIX: No distinction? /* Discourage suit if RHO has second best card. Exception: RHO has singleton. */ - if (posPoint->secondBest[suit].hand == rho[leadHand]) + if (tpos.secondBest[suit].hand == rho[leadHand]) { if (suitCountRH != 1) suitWeightDelta += -1; } /* Encourage playing suit if LHO has second highest rank. */ - else if (posPoint->secondBest[suit].hand == lho[leadHand]) + else if (tpos.secondBest[suit].hand == lho[leadHand]) { if (suitCountLH != 1) suitWeightDelta += 22; @@ -677,9 +652,9 @@ void Moves::WeightAllocNT0( current side to play, or if second best is a singleton at LHO or RHO. */ - if (((posPoint->secondBest[suit].hand != lho[leadHand]) + if (((tpos.secondBest[suit].hand != lho[leadHand]) || (suitCountLH == 1)) && - ((posPoint->secondBest[suit].hand != rho[leadHand]) + ((tpos.secondBest[suit].hand != rho[leadHand]) || (suitCountRH == 1))) mply[k].weight = suitWeightDelta + 45 + rRank; else @@ -689,11 +664,11 @@ void Moves::WeightAllocNT0( or was stored as the best move in a transposition table entry match. */ - if ((bestMove->suit == suit) && - (bestMove->rank == mply[k].rank)) + if ((bestMove.suit == suit) && + (bestMove.rank == mply[k].rank)) mply[k].weight += 126; - else if ((bestMoveTT->suit == suit) && - (bestMoveTT->rank == mply[k].rank)) + else if ((bestMoveTT.suit == suit) && + (bestMoveTT.rank == mply[k].rank)) mply[k].weight += 32; } else @@ -701,8 +676,8 @@ void Moves::WeightAllocNT0( /* Discourage suit if RHO has winning or second best card. Exception: RHO has singleton. */ - if ((posPoint->winner[suit].hand == rho[leadHand]) || - (posPoint->secondBest[suit].hand == rho[leadHand])) + if ((tpos.winner[suit].hand == rho[leadHand]) || + (tpos.secondBest[suit].hand == rho[leadHand])) { if (suitCountRH != 1) suitWeightDelta += -10; @@ -711,11 +686,11 @@ void Moves::WeightAllocNT0( /* Try suit if LHO has winning card and partner second best. Exception: partner has singleton. */ - else if ((posPoint->winner[suit].hand == lho[leadHand]) && - (posPoint->secondBest[suit].hand == partner[leadHand])) + else if ((tpos.winner[suit].hand == lho[leadHand]) && + (tpos.secondBest[suit].hand == partner[leadHand])) { /* This case was suggested by Joël Bradmetz. */ - if (posPoint->length[partner[leadHand]][suit] != 1) + if (tpos.length[partner[leadHand]][suit] != 1) suitWeightDelta += 31; } @@ -726,30 +701,30 @@ void Moves::WeightAllocNT0( int thirdBestHand = thrp_rel[aggr].absRank[3][suit].hand; - if ((posPoint->secondBest[suit].hand == partner[leadHand]) && + if ((tpos.secondBest[suit].hand == partner[leadHand]) && (partner[leadHand] == thirdBestHand)) suitWeightDelta += 35; - else if (((posPoint->secondBest[suit].hand == leadHand) && + else if (((tpos.secondBest[suit].hand == leadHand) && (partner[leadHand] == thirdBestHand) && - (posPoint->length[partner[leadHand]][suit] > 1)) || - ((posPoint->secondBest[suit].hand == partner[leadHand]) && + (tpos.length[partner[leadHand]][suit] > 1)) || + ((tpos.secondBest[suit].hand == partner[leadHand]) && (leadHand == thirdBestHand) && - (posPoint->length[partner[leadHand]][suit] > 1))) + (tpos.length[partner[leadHand]][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[leadHand])) + (tpos.winner[suit].hand == lho[leadHand])) || ((suitCountRH == 1) && - (posPoint->winner[suit].hand == rho[leadHand]))) + (tpos.winner[suit].hand == rho[leadHand]))) mply[k].weight = suitWeightDelta + 28 + rRank; - else if (posPoint->winner[suit].hand == leadHand) + else if (tpos.winner[suit].hand == leadHand) mply[k].weight = suitWeightDelta - 17 + rRank; else if (! mply[k].sequence) mply[k].weight = suitWeightDelta + 12 + rRank; - else if (mply[k].rank == posPoint->secondBest[suit].rank) + else if (mply[k].rank == tpos.secondBest[suit].rank) mply[k].weight = suitWeightDelta + 48; else mply[k].weight = suitWeightDelta + 29 - rRank; @@ -758,32 +733,31 @@ void Moves::WeightAllocNT0( or was stored as the best move in a transposition table entry match. */ - if ((bestMove->suit == suit) && (bestMove->rank == mply[k].rank)) + if ((bestMove.suit == suit) && (bestMove.rank == mply[k].rank)) mply[k].weight += 47; - else if ((bestMoveTT->suit == suit) && - (bestMoveTT->rank == mply[k].rank)) + else if ((bestMoveTT.suit == suit) && + (bestMoveTT.rank == mply[k].rank)) mply[k].weight += 19; } } } -void Moves::WeightAllocTrumpNotvoid1( - pos * posPoint) +void Moves::WeightAllocTrumpNotvoid1(const pos& tpos) { - int max3rd = highestRank[ - posPoint->rankInSuit[partner[leadHand]][leadSuit]]; - int maxpd = highestRank[ - posPoint->rankInSuit[rho[leadHand] ][leadSuit]]; - int min3rd = lowestRank [ - posPoint->rankInSuit[partner[leadHand]][leadSuit]]; - int minpd = lowestRank [ - posPoint->rankInSuit[rho[leadHand] ][leadSuit]]; + const int max3rd = highestRank[ + tpos.rankInSuit[partner[leadHand]][leadSuit]]; + const int maxpd = highestRank[ + tpos.rankInSuit[rho[leadHand] ][leadSuit]]; + const int min3rd = lowestRank [ + tpos.rankInSuit[partner[leadHand]][leadSuit]]; + const int minpd = lowestRank [ + tpos.rankInSuit[rho[leadHand] ][leadSuit]]; for (int k = 0; k < numMoves; k++) { bool winMove = false; /* If true, current move can win trick. */ - int rRank = relRank[ posPoint->aggr[leadSuit] ][mply[k].rank]; + int rRank = relRank[ tpos.aggr[leadSuit] ][mply[k].rank]; if (leadSuit == trump) { @@ -798,35 +772,35 @@ void Moves::WeightAllocTrumpNotvoid1( if (mply[k].rank > trackp->move[0].rank && mply[k].rank > max3rd) { if ((max3rd != 0) || - (posPoint->length[partner[leadHand]][trump] == 0)) + (tpos.length[partner[leadHand]][trump] == 0)) winMove = true; else if ((maxpd == 0) - && (posPoint->length[rho[leadHand]][trump] != 0) - && (posPoint->rankInSuit[rho[leadHand]][trump] > - posPoint->rankInSuit[partner[leadHand]][trump])) + && (tpos.length[rho[leadHand]][trump] != 0) + && (tpos.rankInSuit[rho[leadHand]][trump] > + tpos.rankInSuit[partner[leadHand]][trump])) winMove = true; } else if (maxpd > trackp->move[0].rank && maxpd > max3rd) { if ((max3rd != 0) || - (posPoint->length[partner[leadHand]][trump] == 0)) + (tpos.length[partner[leadHand]][trump] == 0)) winMove = true; } else if (trackp->move[0].rank > maxpd && trackp->move[0].rank > max3rd && trackp->move[0].rank > mply[k].rank) { - if ((maxpd == 0) && (posPoint->length[rho[leadHand]][trump] != 0)) + if ((maxpd == 0) && (tpos.length[rho[leadHand]][trump] != 0)) { if ((max3rd != 0) || - (posPoint->length[partner[leadHand]][trump] == 0)) + (tpos.length[partner[leadHand]][trump] == 0)) winMove = true; - else if (posPoint->rankInSuit[rho[leadHand]][trump] - > posPoint->rankInSuit[partner[leadHand]][trump]) + else if (tpos.rankInSuit[rho[leadHand]][trump] + > tpos.rankInSuit[partner[leadHand]][trump]) winMove = true; } } - else if (maxpd == 0 && (posPoint->length[rho[leadHand]][trump] != 0)) + else if (maxpd == 0 && tpos.length[rho[leadHand]][trump] != 0) /* winnerHand is partner to first */ winMove = true; } @@ -837,8 +811,8 @@ void Moves::WeightAllocTrumpNotvoid1( // Partner must be winning -- we can't. mply[k].weight = 40 + rRank; else if ((maxpd > trackp->move[0].rank) && - (posPoint->rankInSuit[leadHand][leadSuit] > - posPoint->rankInSuit[rho[leadHand]][leadSuit])) + (tpos.rankInSuit[leadHand][leadSuit] > + tpos.rankInSuit[rho[leadHand]][leadSuit])) mply[k].weight = 41 + rRank; /* If rho has a card in the leading suit that @@ -884,18 +858,17 @@ void Moves::WeightAllocTrumpNotvoid1( } -void Moves::WeightAllocNTNotvoid1( - pos * posPoint) +void Moves::WeightAllocNTNotvoid1(const pos& tpos) { // FIX: Second test should come first, and outside loop. // Why is better not to be able to beat later players than // not to be able to beat the lead? // Why rRank? - int max3rd = highestRank[ - posPoint->rankInSuit[partner[leadHand]][leadSuit]]; - int maxpd = highestRank[ - posPoint->rankInSuit[rho[leadHand]][leadSuit] ]; + const int max3rd = highestRank[ + tpos.rankInSuit[partner[leadHand]][leadSuit]]; + const int maxpd = highestRank[ + tpos.rankInSuit[rho[leadHand]][leadSuit] ]; if (maxpd > trackp->move[0].rank && maxpd > max3rd) { @@ -906,13 +879,13 @@ void Moves::WeightAllocNTNotvoid1( else { int min3rd = lowestRank [ - posPoint->rankInSuit[partner[leadHand]][leadSuit]]; + tpos.rankInSuit[partner[leadHand]][leadSuit]]; int minpd = lowestRank [ - posPoint->rankInSuit[rho[leadHand]][leadSuit] ]; + tpos.rankInSuit[rho[leadHand]][leadSuit] ]; for (int k = 0; k < numMoves; k++) { - int rRank = relRank[ posPoint->aggr[leadSuit] ][mply[k].rank]; + int rRank = relRank[ tpos.aggr[leadSuit] ][mply[k].rank]; if (mply[k].rank > trackp->move[0].rank && mply[k].rank > max3rd) // We can beat both opponents. @@ -937,21 +910,20 @@ void Moves::WeightAllocNTNotvoid1( } -void Moves::WeightAllocTrumpVoid1( - pos * posPoint) +void Moves::WeightAllocTrumpVoid1(const pos& tpos) { // FIX: // leadSuit == trump: Why differentiate? // suit != trump: Same question. // Don't ruff ahead of partner? - unsigned short suitCount = posPoint->length[currHand][suit]; + const unsigned short suitCount = tpos.length[currHand][suit]; int suitAdd; if (leadSuit == trump) // We pitch { - if (posPoint->rankInSuit[rho[leadHand]][leadSuit] > - (posPoint->rankInSuit[partner[leadHand]][leadSuit] | + if (tpos.rankInSuit[rho[leadHand]][leadSuit] > + (tpos.rankInSuit[partner[leadHand]][leadSuit] | bitMapRank[ trackp->move[0].rank ])) // Partner can win. suitAdd = (suitCount << 6) / 44; @@ -960,7 +932,7 @@ void Moves::WeightAllocTrumpVoid1( // Don't pitch from Kx. suitAdd = (suitCount << 6) / 36; if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + (tpos.secondBest[suit].hand == currHand)) suitAdd += -4; } @@ -971,16 +943,16 @@ void Moves::WeightAllocTrumpVoid1( { // We discard on a side suit. - if (posPoint->length[partner[leadHand]][leadSuit] != 0) + if (tpos.length[partner[leadHand]][leadSuit] != 0) { // 3rd hand will follow. - if (posPoint->rankInSuit[rho[leadHand]][leadSuit] > - (posPoint->rankInSuit[partner[leadHand]][leadSuit] | + if (tpos.rankInSuit[rho[leadHand]][leadSuit] > + (tpos.rankInSuit[partner[leadHand]][leadSuit] | bitMapRank[ trackp->move[0].rank ])) // Partner has winning card. suitAdd = 60 + (suitCount << 6) / 44; - else if ((posPoint->length[rho[leadHand]][leadSuit] == 0) - && (posPoint->length[rho[leadHand]][trump] != 0)) + else if ((tpos.length[rho[leadHand]][leadSuit] == 0) + && (tpos.length[rho[leadHand]][trump] != 0)) // Partner can ruff. suitAdd = 60 + (suitCount << 6) / 44; else @@ -989,17 +961,17 @@ void Moves::WeightAllocTrumpVoid1( suitAdd = -2 + (suitCount << 6) / 36; // Don't pitch from Kx. if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + (tpos.secondBest[suit].hand == currHand)) suitAdd += -4; } } - else if ((posPoint->length[rho[leadHand]][leadSuit] == 0) - && (posPoint->rankInSuit[rho[leadHand]][trump] > - posPoint->rankInSuit[partner[leadHand]][trump])) + else if ((tpos.length[rho[leadHand]][leadSuit] == 0) + && (tpos.rankInSuit[rho[leadHand]][trump] > + tpos.rankInSuit[partner[leadHand]][trump])) // Partner can overruff 3rd hand. suitAdd = 60 + (suitCount << 6) / 44; - else if ((posPoint->length[partner[leadHand]][trump] == 0) - && (posPoint->rankInSuit[rho[leadHand]][leadSuit] > + else if ((tpos.length[partner[leadHand]][trump] == 0) + && (tpos.rankInSuit[rho[leadHand]][leadSuit] > bitMapRank[ trackp->move[0].rank] )) // 3rd hand has no trumps, and partner has suit winner. suitAdd = 60 + (suitCount << 6) / 44; @@ -1009,13 +981,13 @@ void Moves::WeightAllocTrumpVoid1( suitAdd = -2 + (suitCount << 6) / 36; // Don't pitch from Kx. if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + (tpos.secondBest[suit].hand == currHand)) suitAdd += -4; } for (int k = lastNumMoves; k < numMoves; k++) mply[k].weight = -mply[k].rank + suitAdd; } - else if (posPoint->length[partner[leadHand]][leadSuit] != 0) + else if (tpos.length[partner[leadHand]][leadSuit] != 0) { // 3rd hand follows suit while we ruff. // Could be ruffing partner's winner! @@ -1023,10 +995,10 @@ void Moves::WeightAllocTrumpVoid1( for (int k = lastNumMoves; k < numMoves; k++) mply[k].weight = 24 - (mply[k].rank) + suitAdd; } - else if ((posPoint->length[rho[leadHand]][leadSuit] == 0) - && (posPoint->length[rho[leadHand]][trump] != 0) && - (posPoint->rankInSuit[rho[leadHand]][trump] > - posPoint->rankInSuit[partner[leadHand]][trump])) + else if ((tpos.length[rho[leadHand]][leadSuit] == 0) + && (tpos.length[rho[leadHand]][trump] != 0) && + (tpos.rankInSuit[rho[leadHand]][trump] > + tpos.rankInSuit[partner[leadHand]][trump])) { // Everybody is void, and partner can overruff. suitAdd = (suitCount << 6) / 44; @@ -1038,7 +1010,7 @@ void Moves::WeightAllocTrumpVoid1( for (int k = lastNumMoves; k < numMoves; k++) { if (bitMapRank[mply[k].rank] > - posPoint->rankInSuit[partner[leadHand]][trump]) + tpos.rankInSuit[partner[leadHand]][trump]) { // We can ruff, 3rd hand is void but can't overruff. suitAdd = (suitCount << 6) / 44; @@ -1050,7 +1022,7 @@ void Moves::WeightAllocTrumpVoid1( suitAdd = (suitCount << 6) / 36; // Don't ruff from Kx. if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + (tpos.secondBest[suit].hand == currHand)) suitAdd += -4; mply[k].weight = 15 - (mply[k].rank) + suitAdd; } @@ -1059,24 +1031,22 @@ void Moves::WeightAllocTrumpVoid1( } -void Moves::WeightAllocNTVoid1( - pos * posPoint) +void Moves::WeightAllocNTVoid1(const pos& tpos) { // FIX: // Why the different penalties depending on partner? - if (posPoint->rankInSuit[rho[leadHand] ][leadSuit] > - (posPoint->rankInSuit[partner[leadHand]][leadSuit] | + if (tpos.rankInSuit[rho[leadHand] ][leadSuit] > + (tpos.rankInSuit[partner[leadHand]][leadSuit] | bitMapRank[ trackp->move[0].rank ])) { // Partner can win. - unsigned short suitCount = posPoint->length[currHand][suit]; + unsigned short suitCount = tpos.length[currHand][suit]; int suitAdd = (suitCount << 6) / 23; // Discourage pitch from Kx or A stiff. - if (suitCount == 2 && posPoint->secondBest[suit].hand == currHand) + if (suitCount == 2 && tpos.secondBest[suit].hand == currHand) suitAdd += -2; - else if ((suitCount == 1) && - (posPoint->winner[suit].hand == currHand)) + else if (suitCount == 1 && tpos.winner[suit].hand == currHand) suitAdd += -3; for (int k = lastNumMoves; k < numMoves; k++) @@ -1084,17 +1054,17 @@ void Moves::WeightAllocNTVoid1( } else { - unsigned short suitCount = posPoint->length[currHand][suit]; + unsigned short suitCount = tpos.length[currHand][suit]; int suitAdd = (suitCount << 6) / 33; // Discourage pitch from Kx. if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + (tpos.secondBest[suit].hand == currHand)) suitAdd += -6; /* Discourage suit discard of highest card. */ else if ((suitCount == 1) && - (posPoint->winner[suit].hand == currHand)) + (tpos.winner[suit].hand == currHand)) suitAdd += -8; for (int k = lastNumMoves; k < numMoves; k++) @@ -1103,13 +1073,12 @@ void Moves::WeightAllocNTVoid1( } -void Moves::WeightAllocTrumpNotvoid2( - pos * posPoint) +void Moves::WeightAllocTrumpNotvoid2(const pos& tpos) { - int cards4th = posPoint->rankInSuit[rho[leadHand]][leadSuit]; - int max4th = highestRank[cards4th]; - int min4th = lowestRank [cards4th]; - int max3rd = mply[0].rank; + const int cards4th = tpos.rankInSuit[rho[leadHand]][leadSuit]; + const int max4th = highestRank[cards4th]; + const int min4th = lowestRank [cards4th]; + const int max3rd = mply[0].rank; if (leadSuit == trump) { @@ -1280,22 +1249,22 @@ void Moves::WeightAllocTrumpNotvoid2( int Moves::RankForcesAce( - int cards4th) + const int cards4th) const { // Figure out how high we have to play to force out the top. - moveGroupType * mp = &groupData[cards4th]; + const moveGroupType& mp = groupData[cards4th]; - int g = mp->lastGroup; + int g = mp.lastGroup; int removed = static_cast(trackp->removedRanks[leadSuit]); - while (g >= 1 && ((mp->gap[g] & removed) == mp->gap[g])) + while (g >= 1 && ((mp.gap[g] & removed) == mp.gap[g])) g--; if (! g) return -1; // RHO's second-highest rank. - int secondRHO = (g == 0 ? 0 : mp->rank[g - 1]); + int secondRHO = (g == 0 ? 0 : mp.rank[g-1]); if (secondRHO > trackp->move[1].rank) { @@ -1323,37 +1292,36 @@ int Moves::RankForcesAce( void Moves::GetTopNumber( - int ris, - int prank, - int * topNumber, - int * mno) + const int ris, + const int prank, + int& topNumber, + int& mno) const { - * topNumber = -10; + topNumber = -10; // Find the lowest move that still overtakes partner's card. - *mno = 0; - while (*mno < numMoves - 1 && mply[1 + *mno].rank > prank) - (*mno)++; + mno = 0; + while (mno < numMoves - 1 && mply[1 + mno].rank > prank) + mno++; - moveGroupType * mp = &groupData[ris]; - int g = mp->lastGroup; + const moveGroupType& mp = groupData[ris]; + int g = mp.lastGroup; // Remove partner's card as well. int removed = static_cast(trackp->removedRanks[leadSuit] | bitMapRank[prank]); - int fullseq = mp->fullseq[g]; + int fullseq = mp.fullseq[g]; - while (g >= 1 && ((mp->gap[g] & removed) == mp->gap[g])) - fullseq |= mp->fullseq[--g]; + while (g >= 1 && ((mp.gap[g] & removed) == mp.gap[g])) + fullseq |= mp.fullseq[--g]; - *topNumber = counttable[fullseq] - 1; + topNumber = counttable[fullseq] - 1; } -void Moves::WeightAllocNTNotvoid2( - pos * posPoint) +void Moves::WeightAllocNTNotvoid2(const pos& tpos) { // One of the main remaining issues here is cashing out long // suits. Examples: @@ -1361,10 +1329,10 @@ void Moves::WeightAllocNTNotvoid2( // KQx opposite Jxxxx, don't block on the ace. // KJTx opposite 9 with Qx in dummy, do win the T. - int cards4th = posPoint->rankInSuit[rho[leadHand]][leadSuit]; - int max4th = highestRank[cards4th]; - int min4th = lowestRank [cards4th]; - int max3rd = mply[0].rank; + const int cards4th = tpos.rankInSuit[rho[leadHand]][leadSuit]; + const int max4th = highestRank[cards4th]; + const int min4th = lowestRank [cards4th]; + const int max3rd = mply[0].rank; if (trackp->high[1] == 0 && trackp->move[0].rank > max4th) { @@ -1375,20 +1343,20 @@ void Moves::WeightAllocNTNotvoid2( // This doesn't help much, not sure why. It does work. - // if (0 && posPoint->length[leadHand][leadSuit] == 0 && - if (posPoint->length[leadHand][leadSuit] == 0 && - posPoint->winner[leadSuit].hand == currHand) + // if (0 && tpos.length[leadHand][leadSuit] == 0 && + if (tpos.length[leadHand][leadSuit] == 0 && + tpos.winner[leadSuit].hand == currHand) { // Partner has a singleton, and we have the ace. // Maybe we should overtake to run the suit. - int oppLen = posPoint->length[rho[leadHand]][leadSuit] - 1; - int lhoLen = posPoint->length[lho[leadHand]][leadSuit]; + int oppLen = tpos.length[rho[leadHand]][leadSuit] - 1; + int lhoLen = tpos.length[lho[leadHand]][leadSuit]; if (lhoLen > oppLen) oppLen = lhoLen; int topNumber, mno; - GetTopNumber(posPoint->rankInSuit[partner[leadHand]][leadSuit], - trackp->move[0].rank, &topNumber, &mno); + GetTopNumber(tpos.rankInSuit[partner[leadHand]][leadSuit], + trackp->move[0].rank, topNumber, mno); if (oppLen <= topNumber) mply[mno].weight += 20; @@ -1422,16 +1390,15 @@ void Moves::WeightAllocNTNotvoid2( } -void Moves::WeightAllocTrumpVoid2( - pos * posPoint) +void Moves::WeightAllocTrumpVoid2(const pos& tpos) { // Compared to "v2.8": // Moved a test for partner's win out of the k loop. int suitAdd; - unsigned short suitCount = posPoint->length[currHand][suit]; - int max4th = highestRank[ - posPoint->rankInSuit[rho[leadHand]][leadSuit] ]; + const unsigned short suitCount = tpos.length[currHand][suit]; + const int max4th = highestRank[ + tpos.rankInSuit[rho[leadHand]][leadSuit] ]; if (leadSuit == trump || suit != trump) { @@ -1443,7 +1410,7 @@ void Moves::WeightAllocTrumpVoid2( } else if (trackp->high[1] == 0 && trackp->move[0].rank > max4th && - (max4th != 0 || posPoint->length[rho[leadHand]][trump] == 0)) + (max4th != 0 || tpos.length[rho[leadHand]][trump] == 0)) { // Partner already beat 2nd and 4th hands. // Don't overruff partner's sure winner. @@ -1460,7 +1427,7 @@ void Moves::WeightAllocTrumpVoid2( mply[k].rank < trackp->move[1].rank) { // Don't underruff. - int rRank = relRank[ posPoint->aggr[suit] ][mply[k].rank]; + int rRank = relRank[ tpos.aggr[suit] ][mply[k].rank]; suitAdd = (suitCount << 6) / 40; mply[k].weight = -32 + rRank + suitAdd; } @@ -1470,7 +1437,7 @@ void Moves::WeightAllocTrumpVoid2( // We ruff partner's winner over 2nd hand. if (max4th != 0) { - if (posPoint->secondBest[leadSuit].hand == leadHand) + if (tpos.secondBest[leadSuit].hand == leadHand) { // We'd like to know whether partner has KQ or just K, // but that information takes a bit of diggging. It's @@ -1485,7 +1452,7 @@ void Moves::WeightAllocTrumpVoid2( } } else if (bitMapRank[mply[k].rank] > - posPoint->rankInSuit[rho[leadHand]][trump]) + tpos.rankInSuit[rho[leadHand]][trump]) { // We ruff higher than 4th hand. suitAdd = (suitCount << 6) / 50; @@ -1508,7 +1475,7 @@ void Moves::WeightAllocTrumpVoid2( } else if (bitMapRank[mply[k].rank] > - posPoint->rankInSuit[rho[leadHand]][trump]) + tpos.rankInSuit[rho[leadHand]][trump]) { // Ruff higher than 4th hand can. suitAdd = (suitCount << 6) / 50; @@ -1525,8 +1492,7 @@ void Moves::WeightAllocTrumpVoid2( } -void Moves::WeightAllocNTVoid2( - pos * posPoint) +void Moves::WeightAllocNTVoid2(const pos& tpos) { // Compared to "v2.8": // Took only the second branch. The first branch (partner @@ -1534,15 +1500,13 @@ void Moves::WeightAllocNTVoid2( // for no reason that I could see. This is the same or a tiny // bit better. - unsigned short suitCount = posPoint->length[currHand][suit]; + const unsigned short suitCount = tpos.length[currHand][suit]; int suitAdd = (suitCount << 6) / 24; // Try not to pitch from Kx or stiff ace. - if ((suitCount == 2) && - (posPoint->secondBest[suit].hand == currHand)) + if (suitCount == 2 && tpos.secondBest[suit].hand == currHand) suitAdd -= 4; - else if ((suitCount == 1) && - (posPoint->winner[suit].hand == currHand)) + else if (suitCount == 1 && tpos.winner[suit].hand == currHand) suitAdd -= 4; for (int k = lastNumMoves; k < numMoves; k++) @@ -1550,9 +1514,7 @@ void Moves::WeightAllocNTVoid2( } -void Moves::WeightAllocCombinedNotvoid3( - pos * posPoint) -// moveType mply[]) +void Moves::WeightAllocCombinedNotvoid3(const pos& tpos) { // We're always following suit. // This function is very good, but occasionally it is better @@ -1581,13 +1543,11 @@ void Moves::WeightAllocCombinedNotvoid3( mply[k].weight = -mply[k].rank; } } - UNUSED(posPoint); + UNUSED(tpos); } -void Moves::WeightAllocTrumpVoid3( - pos * posPoint) -// moveType mply[]) +void Moves::WeightAllocTrumpVoid3(const pos& tpos) { // Compared to "v2.8": // val removed for trump plays (doesn't really matter, though). @@ -1596,13 +1556,10 @@ void Moves::WeightAllocTrumpVoid3( // rRank vs rank // Don't pitch from Kx or stiff ace. - int mylen = posPoint->length[currHand][suit]; + const int mylen = tpos.length[currHand][suit]; int val = (mylen << 6) / 24; - if ((mylen == 2) && (posPoint->secondBest[suit].hand == currHand)) + if ((mylen == 2) && (tpos.secondBest[suit].hand == currHand)) val -= 2; - // else if ((mylen == 1) && - // (posPoint->winner[suit].hand == currHand)) - // val -= 4; if (leadSuit == trump) { @@ -1626,7 +1583,7 @@ void Moves::WeightAllocTrumpVoid3( { for (int k = lastNumMoves; k < numMoves; k++) { - int rRank = relRank[ posPoint->aggr[suit] ][mply[k].rank]; + int rRank = relRank[ tpos.aggr[suit] ][mply[k].rank]; if (mply[k].rank > trackp->move[2].rank) mply[k].weight = 33 + rRank; // Overruff else @@ -1641,7 +1598,7 @@ void Moves::WeightAllocTrumpVoid3( { for (int k = lastNumMoves; k < numMoves; k++) { - int rRank = relRank[ posPoint->aggr[suit] ][mply[k].rank]; + int rRank = relRank[ tpos.aggr[suit] ][mply[k].rank]; mply[k].weight = 33 + rRank; } } @@ -1653,16 +1610,14 @@ void Moves::WeightAllocTrumpVoid3( } -void Moves::WeightAllocNTVoid3( - pos * posPoint) -// moveType mply[]) +void Moves::WeightAllocNTVoid3(const pos& tpos) { - int mylen = posPoint->length[currHand][suit]; + int mylen = tpos.length[currHand][suit]; int val = (mylen << 6) / 27; // Try not to pitch from Kx, or to pitch a singleton winner. - if ((mylen == 2) && (posPoint->secondBest[suit].hand == currHand)) + if ((mylen == 2) && (tpos.secondBest[suit].hand == currHand)) val -= 6; - else if ((mylen == 1) && (posPoint->winner[suit].hand == currHand)) + else if ((mylen == 1) && (tpos.winner[suit].hand == currHand)) val -= 8; for (int k = lastNumMoves; k < numMoves; k++) @@ -1671,59 +1626,58 @@ void Moves::WeightAllocNTVoid3( inline bool Moves::WinningMove( - moveType * mvp1, - extCard * mvp2, - int ourTrump) + const moveType& mvp1, + const extCard& mvp2, + const int ourTrump) const { /* 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.suit == mvp2.suit) { - if ((mvp1->rank) > (mvp2->rank)) + if (mvp1.rank > mvp2.rank) return true; else return false; } - else if ((mvp1->suit) == ourTrump) + else if (mvp1.suit == ourTrump) return true; else return false; } - int Moves::GetLength( - int trick, - int relHand) + const int trick, + const int relHand) const { return moveList[trick][relHand].last + 1; } void Moves::MakeSpecific( - moveType * ourMply, - int trick, - int relHand) + const moveType& ourMply, + const int trick, + const int relHand) { trackp = &track[trick]; if (relHand == 0) { - trackp->move[0].suit = ourMply->suit; - trackp->move[0].rank = ourMply->rank; - trackp->move[0].sequence = ourMply->sequence; + trackp->move[0].suit = ourMply.suit; + trackp->move[0].rank = ourMply.rank; + trackp->move[0].sequence = ourMply.sequence; trackp->high[0] = 0; - trackp->leadSuit = ourMply->suit; + trackp->leadSuit = ourMply.suit; } - else if (ourMply->suit == trackp->move[relHand - 1].suit) + else if (ourMply.suit == trackp->move[relHand - 1].suit) { - if (ourMply->rank > trackp->move[relHand - 1].rank) + if (ourMply.rank > trackp->move[relHand - 1].rank) { - trackp->move[relHand].suit = ourMply->suit; - trackp->move[relHand].rank = ourMply->rank; - trackp->move[relHand].sequence = ourMply->sequence; + trackp->move[relHand].suit = ourMply.suit; + trackp->move[relHand].rank = ourMply.rank; + trackp->move[relHand].sequence = ourMply.sequence; trackp->high[relHand] = relHand; } else @@ -1732,11 +1686,11 @@ void Moves::MakeSpecific( trackp->high[relHand] = trackp->high[relHand - 1]; } } - else if (ourMply->suit == trump) + else if (ourMply.suit == trump) { - trackp->move[relHand].suit = ourMply->suit; - trackp->move[relHand].rank = ourMply->rank; - trackp->move[relHand].sequence = ourMply->sequence; + trackp->move[relHand].suit = ourMply.suit; + trackp->move[relHand].rank = ourMply.rank; + trackp->move[relHand].sequence = ourMply.sequence; trackp->high[relHand] = relHand; } else @@ -1745,8 +1699,8 @@ void Moves::MakeSpecific( trackp->high[relHand] = trackp->high[relHand - 1]; } - trackp->playSuits[relHand] = ourMply->suit; - trackp->playRanks[relHand] = ourMply->rank; + trackp->playSuits[relHand] = ourMply.suit; + trackp->playRanks[relHand] = ourMply.rank; if (relHand == 3) { @@ -1768,31 +1722,31 @@ void Moves::MakeSpecific( } -moveType * Moves::MakeNext( - int trick, - int relHand, - unsigned short int ourWinRanks[DDS_SUITS]) +moveType const * Moves::MakeNext( + const int trick, + const int relHand, + const unsigned short ourWinRanks[DDS_SUITS]) { // Find moves that are >= ourWinRanks[suit], but allow one // "small" move per suit. int * lwp = track[trick].lowestWin[relHand]; - movePlyType * listp = &moveList[trick][relHand]; + movePlyType& list = moveList[trick][relHand]; trackp = &track[trick]; moveType * currp = nullptr, * prevp; bool found = false; - if (listp->last == -1) + if (list.last == -1) return NULL; - else if (listp->current == 0) + else if (list.current == 0) { - currp = &listp->move[0]; + currp = &list.move[0]; found = true; } else { - prevp = &listp->move[ listp->current - 1 ]; + prevp = &list.move[ list.current - 1 ]; if (lwp[ prevp->suit ] == 0) { int low = lowestRank[ ourWinRanks[prevp->suit] ]; @@ -1802,13 +1756,13 @@ moveType * Moves::MakeNext( lwp[ prevp->suit ] = low; } - while (listp->current <= listp->last && ! found) + while (list.current <= list.last && ! found) { - currp = &listp->move[ listp->current ]; + currp = &list.move[ list.current ]; if (currp->rank >= lwp[ currp->suit ]) found = true; else - listp->current++; + list.current++; } if (! found) @@ -1857,114 +1811,113 @@ moveType * Moves::MakeNext( if (relHand == 3) { - trackType * newp = &track[trick - 1]; + trackType& newt = track[trick - 1]; - newp->leadHand = (trackp->leadHand + trackp->high[3]) % 4; + newt.leadHand = (trackp->leadHand + trackp->high[3]) % 4; int r, s; for (s = 0; s < DDS_SUITS; s++) - newp->removedRanks[s] = trackp->removedRanks[s]; + newt.removedRanks[s] = trackp->removedRanks[s]; for (int h = 0; h < DDS_HANDS; h++) { r = trackp->playRanks[h]; s = trackp->playSuits[h]; - newp->removedRanks[s] |= bitMapRank[r]; + newt.removedRanks[s] |= bitMapRank[r]; } } - listp->current++; + list.current++; return currp; } -moveType * Moves::MakeNextSimple( - int trick, - int relHand) +moveType const * Moves::MakeNextSimple( + const int trick, + const int relHand) { // Don't worry about small moves. Why not, actually? - movePlyType * listp = &moveList[trick][relHand]; - if (listp->current > listp->last) + movePlyType& list = moveList[trick][relHand]; + if (list.current > list.last) return NULL; - moveType * currp = &listp->move[ listp->current ]; + const moveType& curr = list.move[list.current]; trackp = &track[trick]; if (relHand == 0) { - trackp->move[0].suit = currp->suit; - trackp->move[0].rank = currp->rank; - trackp->move[0].sequence = currp->sequence; + trackp->move[0].suit = curr.suit; + trackp->move[0].rank = curr.rank; + trackp->move[0].sequence = curr.sequence; trackp->high[0] = 0; - trackp->leadSuit = currp->suit; + trackp->leadSuit = curr.suit; } - else if (currp->suit == trackp->move[relHand - 1].suit) + else if (curr.suit == trackp->move[relHand-1].suit) { - if (currp->rank > trackp->move[relHand - 1].rank) + if (curr.rank > trackp->move[relHand-1].rank) { - trackp->move[relHand].suit = currp->suit; - trackp->move[relHand].rank = currp->rank; - trackp->move[relHand].sequence = currp->sequence; + trackp->move[relHand].suit = curr.suit; + trackp->move[relHand].rank = curr.rank; + trackp->move[relHand].sequence = curr.sequence; trackp->high[relHand] = relHand; } else { - trackp->move[relHand] = trackp->move[relHand - 1]; - trackp->high[relHand] = trackp->high[relHand - 1]; + trackp->move[relHand] = trackp->move[relHand-1]; + trackp->high[relHand] = trackp->high[relHand-1]; } } - else if (currp->suit == trump) + else if (curr.suit == trump) { - trackp->move[relHand].suit = currp->suit; - trackp->move[relHand].rank = currp->rank; - trackp->move[relHand].sequence = currp->sequence; + trackp->move[relHand].suit = curr.suit; + trackp->move[relHand].rank = curr.rank; + trackp->move[relHand].sequence = curr.sequence; trackp->high[relHand] = relHand; } else { - trackp->move[relHand] = trackp->move[relHand - 1]; - trackp->high[relHand] = trackp->high[relHand - 1]; + trackp->move[relHand] = trackp->move[relHand-1]; + trackp->high[relHand] = trackp->high[relHand-1]; } - trackp->playSuits[relHand] = currp->suit; - trackp->playRanks[relHand] = currp->rank; + trackp->playSuits[relHand] = curr.suit; + trackp->playRanks[relHand] = curr.rank; if (relHand == 3) { - trackType * newp = &track[trick - 1]; - newp->leadHand = (trackp->leadHand + trackp->high[3]) % 4; + track[trick-1].leadHand = (trackp->leadHand + trackp->high[3]) % 4; } - listp->current++; - return currp; + list.current++; + return &curr; } void Moves::Step( - int tricks, - int relHand) + const int tricks, + const int relHand) { moveList[tricks][relHand].current++; } void Moves::Rewind( - int tricks, - int relHand) + const int tricks, + const int relHand) { moveList[tricks][relHand].current = 0; } void Moves::Purge( - int trick, - int ourLeadHand, - moveType forbiddenMoves[]) + const int trick, + const int ourLeadHand, + const moveType forbiddenMoves[]) { - movePlyType * ourMply = &moveList[trick][ourLeadHand]; + movePlyType& ourMply = moveList[trick][ourLeadHand]; for (int k = 1; k <= 13; k++) { @@ -1972,15 +1925,15 @@ void Moves::Purge( int rank = forbiddenMoves[k].rank; if (rank == 0) continue; - for (int r = 0; r <= ourMply->last; r++) + for (int r = 0; r <= ourMply.last; r++) { - if (s == ourMply->move[r].suit && - rank == ourMply->move[r].rank) + if (s == ourMply.move[r].suit && + rank == ourMply.move[r].rank) { /* For the forbidden move r: */ - for (int n = r; n <= ourMply->last; n++) - ourMply->move[n] = ourMply->move[n + 1]; - ourMply->last--; + for (int n = r; n <= ourMply.last; n++) + ourMply.move[n] = ourMply.move[n + 1]; + ourMply.last--; } } } @@ -1988,43 +1941,43 @@ void Moves::Purge( void Moves::Reward( - int tricks, - int relHand) + const int tricks, + const int relHand) { moveList[tricks][relHand]. move[ moveList[tricks][relHand].current - 1 ].weight += 100; } -trickDataType * Moves::GetTrickData( - int tricks) +const trickDataType& Moves::GetTrickData(const int tricks) { - trickDataType * datap = &track[tricks].trickData; + trickDataType& data = track[tricks].trickData; for (int s = 0; s < DDS_SUITS; s++) - datap->playCount[s] = 0; + data.playCount[s] = 0; for (int relh = 0; relh < DDS_HANDS; relh++) - datap->playCount[ trackp->playSuits[relh] ]++; + data.playCount[ trackp->playSuits[relh] ]++; int sum = 0; for (int s = 0; s < DDS_SUITS; s++) - sum += datap->playCount[s]; + sum += data.playCount[s]; + if (sum != 4) { - printf("Sum %d is not four\n", sum); + cout << "Sum " << sum << " is not four" << endl; exit(1); } - datap->bestRank = trackp->move[3].rank; - datap->bestSuit = trackp->move[3].suit; - datap->bestSequence = trackp->move[3].sequence; - datap->relWinner = trackp->high[3]; - return datap; + data.bestRank = trackp->move[3].rank; + data.bestSuit = trackp->move[3].suit; + data.bestSequence = trackp->move[3].sequence; + data.relWinner = trackp->high[3]; + return data; } void Moves::Sort( - int tricks, - int relHand) + const int tricks, + const int relHand) { numMoves = moveList[tricks][relHand].last + 1; mply = moveList[tricks][relHand].move; @@ -2032,6 +1985,9 @@ void Moves::Sort( } +#define CMP_SWAP(i, j) if (mply[i].weight < mply[j].weight) \ + { tmp = mply[i]; mply[i] = mply[j]; mply[j] = tmp; } + void Moves::MergeSort() { moveType tmp; @@ -2039,230 +1995,230 @@ void Moves::MergeSort() switch (numMoves) { case 12: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(6, 7); - CMP_SWAP_NEW(8, 9); - CMP_SWAP_NEW(10, 11); - - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(5, 7); - CMP_SWAP_NEW(9, 11); - - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(8, 10); - - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(9, 10); - - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(6, 10); - CMP_SWAP_NEW(5, 9); - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(6, 10); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(7, 11); - CMP_SWAP_NEW(3, 7); - CMP_SWAP_NEW(4, 8); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(7, 11); - CMP_SWAP_NEW(1, 4); - CMP_SWAP_NEW(7, 10); - CMP_SWAP_NEW(3, 8); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(8, 9); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(7, 9); - CMP_SWAP_NEW(3, 5); - CMP_SWAP_NEW(6, 8); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(7, 8); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(4, 5); + CMP_SWAP(6, 7); + CMP_SWAP(8, 9); + CMP_SWAP(10, 11); + + CMP_SWAP(1, 3); + CMP_SWAP(5, 7); + CMP_SWAP(9, 11); + + CMP_SWAP(0, 2); + CMP_SWAP(4, 6); + CMP_SWAP(8, 10); + + CMP_SWAP(1, 2); + CMP_SWAP(5, 6); + CMP_SWAP(9, 10); + + CMP_SWAP(1, 5); + CMP_SWAP(6, 10); + CMP_SWAP(5, 9); + CMP_SWAP(2, 6); + CMP_SWAP(1, 5); + CMP_SWAP(6, 10); + CMP_SWAP(0, 4); + CMP_SWAP(7, 11); + CMP_SWAP(3, 7); + CMP_SWAP(4, 8); + CMP_SWAP(0, 4); + CMP_SWAP(7, 11); + CMP_SWAP(1, 4); + CMP_SWAP(7, 10); + CMP_SWAP(3, 8); + CMP_SWAP(2, 3); + CMP_SWAP(8, 9); + CMP_SWAP(2, 4); + CMP_SWAP(7, 9); + CMP_SWAP(3, 5); + CMP_SWAP(6, 8); + CMP_SWAP(3, 4); + CMP_SWAP(5, 6); + CMP_SWAP(7, 8); break; case 11: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(6, 7); - CMP_SWAP_NEW(8, 9); - - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(5, 7); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(8, 10); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(9, 10); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(6, 10); - CMP_SWAP_NEW(5, 9); - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(6, 10); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(3, 7); - CMP_SWAP_NEW(4, 8); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(1, 4); - CMP_SWAP_NEW(7, 10); - CMP_SWAP_NEW(3, 8); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(8, 9); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(7, 9); - CMP_SWAP_NEW(3, 5); - CMP_SWAP_NEW(6, 8); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(7, 8); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(4, 5); + CMP_SWAP(6, 7); + CMP_SWAP(8, 9); + + CMP_SWAP(1, 3); + CMP_SWAP(5, 7); + CMP_SWAP(0, 2); + CMP_SWAP(4, 6); + CMP_SWAP(8, 10); + CMP_SWAP(1, 2); + CMP_SWAP(5, 6); + CMP_SWAP(9, 10); + CMP_SWAP(1, 5); + CMP_SWAP(6, 10); + CMP_SWAP(5, 9); + CMP_SWAP(2, 6); + CMP_SWAP(1, 5); + CMP_SWAP(6, 10); + CMP_SWAP(0, 4); + CMP_SWAP(3, 7); + CMP_SWAP(4, 8); + CMP_SWAP(0, 4); + CMP_SWAP(1, 4); + CMP_SWAP(7, 10); + CMP_SWAP(3, 8); + CMP_SWAP(2, 3); + CMP_SWAP(8, 9); + CMP_SWAP(2, 4); + CMP_SWAP(7, 9); + CMP_SWAP(3, 5); + CMP_SWAP(6, 8); + CMP_SWAP(3, 4); + CMP_SWAP(5, 6); + CMP_SWAP(7, 8); break; case 10: - CMP_SWAP_NEW(1, 8); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(5, 9); - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(3, 7); - CMP_SWAP_NEW(0, 3); - CMP_SWAP_NEW(6, 9); - CMP_SWAP_NEW(2, 5); - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(3, 6); - CMP_SWAP_NEW(8, 9); - CMP_SWAP_NEW(4, 7); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(4, 8); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(7, 9); - - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(7, 8); - - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(6, 8); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(5, 7); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(6, 7); - CMP_SWAP_NEW(3, 5); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(4, 5); + CMP_SWAP(1, 8); + CMP_SWAP(0, 4); + CMP_SWAP(5, 9); + CMP_SWAP(2, 6); + CMP_SWAP(3, 7); + CMP_SWAP(0, 3); + CMP_SWAP(6, 9); + CMP_SWAP(2, 5); + CMP_SWAP(0, 1); + CMP_SWAP(3, 6); + CMP_SWAP(8, 9); + CMP_SWAP(4, 7); + CMP_SWAP(0, 2); + CMP_SWAP(4, 8); + CMP_SWAP(1, 5); + CMP_SWAP(7, 9); + + CMP_SWAP(1, 2); + CMP_SWAP(3, 4); + CMP_SWAP(5, 6); + CMP_SWAP(7, 8); + + CMP_SWAP(1, 3); + CMP_SWAP(6, 8); + CMP_SWAP(2, 4); + CMP_SWAP(5, 7); + CMP_SWAP(2, 3); + CMP_SWAP(6, 7); + CMP_SWAP(3, 5); + CMP_SWAP(4, 6); + CMP_SWAP(4, 5); break; case 9: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(6, 7); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(7, 8); - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(6, 7); - CMP_SWAP_NEW(0, 3); - CMP_SWAP_NEW(3, 6); - CMP_SWAP_NEW(0, 3); - CMP_SWAP_NEW(1, 4); - CMP_SWAP_NEW(4, 7); - CMP_SWAP_NEW(1, 4); - CMP_SWAP_NEW(2, 5); - CMP_SWAP_NEW(5, 8); - CMP_SWAP_NEW(2, 5); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(5, 7); - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(5, 6); + CMP_SWAP(0, 1); + CMP_SWAP(3, 4); + CMP_SWAP(6, 7); + CMP_SWAP(1, 2); + CMP_SWAP(4, 5); + CMP_SWAP(7, 8); + CMP_SWAP(0, 1); + CMP_SWAP(3, 4); + CMP_SWAP(6, 7); + CMP_SWAP(0, 3); + CMP_SWAP(3, 6); + CMP_SWAP(0, 3); + CMP_SWAP(1, 4); + CMP_SWAP(4, 7); + CMP_SWAP(1, 4); + CMP_SWAP(2, 5); + CMP_SWAP(5, 8); + CMP_SWAP(2, 5); + CMP_SWAP(1, 3); + CMP_SWAP(5, 7); + CMP_SWAP(2, 6); + CMP_SWAP(4, 6); + CMP_SWAP(2, 4); + CMP_SWAP(2, 3); + CMP_SWAP(5, 6); break; case 8: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(6, 7); - - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(5, 7); - - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(1, 5); - - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(3, 7); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(3, 5); - - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(5, 6); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(4, 5); + CMP_SWAP(6, 7); + + CMP_SWAP(0, 2); + CMP_SWAP(4, 6); + CMP_SWAP(1, 3); + CMP_SWAP(5, 7); + + CMP_SWAP(1, 2); + CMP_SWAP(5, 6); + CMP_SWAP(0, 4); + CMP_SWAP(1, 5); + + CMP_SWAP(2, 6); + CMP_SWAP(3, 7); + CMP_SWAP(2, 4); + CMP_SWAP(3, 5); + + CMP_SWAP(1, 2); + CMP_SWAP(3, 4); + CMP_SWAP(5, 6); break; case 7: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(4, 6); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(5, 6); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(2, 6); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(3, 5); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(3, 4); - CMP_SWAP_NEW(5, 6); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(4, 5); + CMP_SWAP(0, 2); + CMP_SWAP(4, 6); + CMP_SWAP(1, 3); + CMP_SWAP(1, 2); + CMP_SWAP(5, 6); + CMP_SWAP(0, 4); + CMP_SWAP(1, 5); + CMP_SWAP(2, 6); + CMP_SWAP(2, 4); + CMP_SWAP(3, 5); + CMP_SWAP(1, 2); + CMP_SWAP(3, 4); + CMP_SWAP(5, 6); break; case 6: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(4, 5); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(1, 5); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(3, 5); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(3, 4); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(4, 5); + CMP_SWAP(0, 2); + CMP_SWAP(1, 3); + CMP_SWAP(1, 2); + CMP_SWAP(0, 4); + CMP_SWAP(1, 5); + CMP_SWAP(2, 4); + CMP_SWAP(3, 5); + CMP_SWAP(1, 2); + CMP_SWAP(3, 4); break; case 5: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(0, 4); - CMP_SWAP_NEW(2, 4); - CMP_SWAP_NEW(1, 2); - CMP_SWAP_NEW(3, 4); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(0, 2); + CMP_SWAP(1, 3); + CMP_SWAP(1, 2); + CMP_SWAP(0, 4); + CMP_SWAP(2, 4); + CMP_SWAP(1, 2); + CMP_SWAP(3, 4); break; case 4: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(2, 3); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(1, 3); - CMP_SWAP_NEW(1, 2); + CMP_SWAP(0, 1); + CMP_SWAP(2, 3); + CMP_SWAP(0, 2); + CMP_SWAP(1, 3); + CMP_SWAP(1, 2); break; case 3: - CMP_SWAP_NEW(0, 1); - CMP_SWAP_NEW(0, 2); - CMP_SWAP_NEW(1, 2); + CMP_SWAP(0, 1); + CMP_SWAP(0, 2); + CMP_SWAP(1, 2); break; case 2: - CMP_SWAP_NEW(0, 1); + CMP_SWAP(0, 1); break; default: for (int i = 1; i < numMoves; i++) @@ -2279,71 +2235,74 @@ void Moves::MergeSort() } -void Moves::PrintMove( - movePlyType * ourMply) +string Moves::PrintMove(const movePlyType& ourMply) const { - printf("current %d, last %d\n", ourMply->current, ourMply->last); - printf(" i suit sequence rank wgt\n"); - for (int i = 0; i <= ourMply->last; i++) + stringstream ss; + + ss << "current " << ourMply.current << ", last " << ourMply.last << "\n"; + ss << " i suit sequence rank wgt\n"; + for (int i = 0; i <= ourMply.last; i++) { - printf("%2d %2c %08x %2c %2d\n", - i, - cardSuit[ ourMply->move[i].suit ], - ourMply->move[i].sequence, - cardRank[ ourMply->move[i].rank ], - ourMply->move[i].weight); + ss << setw(2) << right << i << + setw(3) << cardSuit[ ourMply.move[i].suit ] << + setw(9) << hex << ourMply.move[i].sequence << + setw(3) << cardRank[ ourMply.move[i].rank ] << + setw(3) << ourMply.move[i].weight << "\n"; } + return ss.str(); } -void Moves::PrintMoves( - int trick, - int relHand) +string Moves::PrintMoves( + const int trick, + const int relHand) const { - movePlyType * listp = &moveList[trick][relHand]; - printf("trick %d relHand %d last %d current %d\n", - trick, relHand, listp->last, listp->current); - Moves::PrintMove(listp); + const movePlyType& list = moveList[trick][relHand]; + + const string st = "trick " + to_string(trick) + + " relHand " + to_string(relHand) + + " last " + to_string(list.last) + + " current " + to_string(list.current) + "\n"; + + return st + Moves::PrintMove(list); } -void Moves::TrickToText( - int trick, - char line[]) +string Moves::TrickToText(const int trick) const { - movePlyType * listp0 = &moveList[trick][0], - * listp1 = &moveList[trick][1], - * listp2 = &moveList[trick][2], - * listp3 = &moveList[trick][3]; - - sprintf(line, "Last trick\t%c: %c%c - %c%c - %c%c - %c%c\n", - cardHand[ track[trick].leadHand ], - cardSuit[ listp0->move[listp0->current].suit ], - cardRank[ listp0->move[listp0->current].rank ], - - cardSuit[ listp1->move[listp1->current].suit ], - cardRank[ listp1->move[listp1->current].rank ], - - cardSuit[ listp2->move[listp2->current].suit ], - cardRank[ listp2->move[listp2->current].rank ], - - cardSuit[ listp3->move[listp3->current].suit ], - cardRank[ listp3->move[listp3->current].rank ]); + const movePlyType& listp0 = moveList[trick][0]; + const movePlyType& listp1 = moveList[trick][1]; + const movePlyType& listp2 = moveList[trick][2]; + const movePlyType& listp3 = moveList[trick][3]; + + stringstream ss; + ss << setw(16) << left << "Last trick" << + cardHand[ track[trick].leadHand ] << ": " << + cardSuit[ listp0.move[listp0.current].suit ] << + cardRank[ listp0.move[listp0.current].rank ] << " - " << + cardSuit[ listp1.move[listp1.current].suit ] << + cardRank[ listp1.move[listp1.current].rank ] << " - " << + cardSuit[ listp2.move[listp2.current].suit ] << + cardRank[ listp2.move[listp2.current].rank ] << " - " << + cardSuit[ listp3.move[listp3.current].suit ] << + cardRank[ listp3.move[listp3.current].rank ] << "\n"; + + return ss.str(); } void Moves::UpdateStatsEntry( - moveStatsType * statp, - int findex, - int hit, - int len) + moveStatsType& stat, + const int findex, + const int hit, + const int len) const { bool found = false; int fno = 0; - for (int i = 0; i < statp->nfuncs; i++) + for (int i = 0; i < stat.nfuncs; i++) { - if (statp->list[i].findex == findex) + if (stat.list[i].findex == findex) { found = true; fno = i; @@ -2354,22 +2313,22 @@ void Moves::UpdateStatsEntry( moveStatType * funp; if (found) { - funp = &statp->list[fno]; + funp = &stat.list[fno]; funp->count++; funp->sumHits += hit; funp->sumLengths += len; } else { - if (statp->nfuncs >= MG_NUM_FUNCTIONS) + if (stat.nfuncs >= MG_SIZE) { - printf("Shouldn't happen, %d\n", statp->nfuncs); - for (int i = 0; i < statp->nfuncs; i++) - printf("%d %d\n", i, statp->list[i].findex); + cout << "Shouldn't happen, " << stat.nfuncs << endl; + for (int i = 0; i < stat.nfuncs; i++) + cout << i << " " << stat.list[i].findex << "\n"; exit(1); } - funp = &statp->list[ statp->nfuncs++ ]; + funp = &stat.list[stat.nfuncs++]; funp->count++; funp->findex = findex; @@ -2380,35 +2339,35 @@ void Moves::UpdateStatsEntry( void Moves::RegisterHit( - int trick, - int relHand) + const int trick, + const int relHand) { - movePlyType * listp = &moveList[trick][relHand]; + const movePlyType& list = moveList[trick][relHand]; - int findex = lastCall[trick][relHand]; - int len = listp->last + 1; + const int findex = lastCall[trick][relHand]; + const int len = list.last + 1; if (findex == -1) { - printf("RegisterHit trick %d relHand %d: findex %d\n", - trick, relHand, -1); + cout << "RegisterHit trick " << trick << + " relHand " << relHand << " findex -1" << endl; exit(1); } - int curr = listp->current; + const int curr = list.current; if (curr < 1 || curr > len) { - printf("current out of bounds\n"); + cout << "current out of bounds" << endl; exit(1); } - int moveSuit = listp->move[curr - 1].suit; + const int moveSuit = list.move[curr-1].suit; int numSuit = 0; int numSeen = 0; for (int i = 0; i < len; i++) { - if (listp->move[i].suit == moveSuit) + if (list.move[i].suit == moveSuit) { numSuit++; if (i == curr - 1) @@ -2416,38 +2375,6 @@ void Moves::RegisterHit( } } -// Used for development -#if 0 - if (findex == MG_COMB_NOTVOID3 && numSeen > 1 && trick >= 10) - // if (0 && findex == MG_TRUMP_VOID3 && numSeen == 1 && curr > 1) - { - char text[12][80]; - RankToText(posPoint->rankInSuit, text); - - for (int i = 0; i < 12; i++) - printf("%s\n", text[i]); - printf("\n", text); - - trackp = &track[trick]; - - printf("Trumps %c, Play %c: %c%c - %c%c - %c%c, best no. %d\n\n", - // printf("Trumps %c, Play %c: %c%c - %c%c, best no. %d\n\n", - // printf("Trumps %c, Play %c: %c%c, best no. %d\n\n", - cardSuit[trump], - cardHand[leadHand], - cardSuit[ trackp->playSuits[0] ], - cardRank[ trackp->playRanks[0] ], - cardSuit[ trackp->playSuits[1] ], - cardRank[ trackp->playRanks[1] ], - cardSuit[ trackp->playSuits[2] ], - cardRank[ trackp->playRanks[2] ], - curr - 1); - - Moves::PrintMoves(trick, relHand); - printf("\n---------------------------------------\n\n"); - } -#endif - // Now we know enough to update the statistics tables. trickTable[trick][relHand].count++; @@ -2458,164 +2385,168 @@ void Moves::RegisterHit( trickSuitTable[trick][relHand].sumHits += numSeen; trickSuitTable[trick][relHand].sumLengths += numSuit; - Moves::UpdateStatsEntry(&trickDetailTable[trick][relHand], - findex, curr, len); + Moves::UpdateStatsEntry(trickDetailTable[trick][relHand], + findex, curr, len); - Moves::UpdateStatsEntry(&trickDetailSuitTable[trick][relHand], - findex, numSeen, numSuit); + Moves::UpdateStatsEntry(trickDetailSuitTable[trick][relHand], + findex, numSeen, numSuit); - Moves::UpdateStatsEntry(&trickFuncTable, - findex, curr, len); + Moves::UpdateStatsEntry(trickFuncTable, + findex, curr, len); - Moves::UpdateStatsEntry(&trickFuncSuitTable, - findex, numSeen, numSuit); + Moves::UpdateStatsEntry(trickFuncSuitTable, + findex, numSeen, numSuit); } -char * Moves::AverageString( - moveStatType * statp, - char str[]) +string Moves::AverageString(const moveStatType& stat) const { - if (statp->count == 0) - sprintf(str, "%5s %4s", "--", "--"); + stringstream ss; + if (stat.count == 0) + ss << setw(5) << right << "--" << setw(5) << "--"; else - sprintf(str, "%5.2f %4.1f", - statp->sumHits / static_cast(statp->count), - 100. * statp->sumHits / static_cast(statp->sumLengths)); + { + ss << setw(5) << setprecision(2) << fixed << + stat.sumHits / static_cast(stat.count) << + setw(5) << setprecision(1) << fixed << + 100. * stat.sumHits / static_cast(stat.sumLengths); + } - return str; + return ss.str(); } -char * Moves::FullAverageString( - moveStatType * statp, - char str[]) +string Moves::FullAverageString(const moveStatType& stat) const { - if (statp->count == 0) - sprintf(str, "%5s %5s %4s %8s %8s", - "--", "--", "--", "--", "--"); + stringstream ss; + if (stat.count == 0) + { + ss << setw(6) << right << "--" << + setw(6) << "--" << + setw(5) << "--" << + setw(9) << "--" << + setw(5) << "--"; + } else { - double avg = statp->sumHits / static_cast(statp->count); + double avg = stat.sumHits / static_cast(stat.count); - sprintf(str, "%5.3f %5.2f %4.1f %8d %8.0f", - avg, - statp->sumLengths / static_cast(statp->count), - 100. * statp->sumHits / static_cast(statp->sumLengths), - statp->count, - (avg * avg * avg - 1) * statp->count); + ss << setw(5) << setprecision(3) << fixed << avg << + setw(6) << setprecision(2) << fixed << + stat.sumLengths / static_cast(stat.count) << + setw(5) << setprecision(1) << fixed << + 100. * stat.sumHits / static_cast(stat.sumLengths) << + setw(9) << stat.count << setprecision(0) << fixed << + (avg * avg * avg - 1) * stat.count; } - return str; + return ss.str(); } -void Moves::PrintTrickTable( - moveStatType tablep[][DDS_HANDS]) +string Moves::PrintTrickTable( + const moveStatType tablep[][DDS_HANDS]) const { - fprintf(fp, "%5s %11s %11s %11s %11s\n", - "Trick", - "Hand 0", - "Hand 1", - "Hand 2", - "Hand 3"); - - fprintf(fp, "%5s %5s %4s %5s %4s %5s %4s %5s %4s\n", - "", - "Avg", "%", - "Avg", "%", - "Avg", "%", - "Avg", "%"); - - char str[DDS_HANDS][16]; - for (int t = 12; t >= 0; t--) - { - fprintf(fp, "%5d %11s %11s %11s %11s\n", - t, - Moves::AverageString(&tablep[t][0], str[0]), - Moves::AverageString(&tablep[t][1], str[1]), - Moves::AverageString(&tablep[t][2], str[2]), - Moves::AverageString(&tablep[t][3], str[3])); - } -} + stringstream ss; + ss << setw(5) << "Trick" << + setw(12) << "Hand 0" << + setw(12) << "Hand 1" << + setw(12) << "Hand 2" << + setw(12) << "Hand 3" << "\n"; -void Moves::PrintTrickStats() -{ - fprintf(fp, "Overall statistics\n\n"); - Moves::PrintTrickTable(trickTable); + ss << setw(6) << "" << + setw(6) << "Avg" << setw(5) << "%" << + setw(6) << "Avg" << setw(5) << "%" << + setw(6) << "Avg" << setw(5) << "%" << + setw(6) << "Avg" << setw(5) << "%" << "\n"; - fprintf(fp, "\n\nStatistics for winning suit\n\n"); - Moves::PrintTrickTable(trickSuitTable); - fprintf(fp, "\n\n"); + for (int t = 12; t >= 0; t--) + { + ss << setw(5) << right << t << + setw(12) << Moves::AverageString(tablep[t][0]) << + setw(12) << Moves::AverageString(tablep[t][1]) << + setw(12) << Moves::AverageString(tablep[t][2]) << + setw(12) << Moves::AverageString(tablep[t][3]) << "\n"; + } + return ss.str(); } -void Moves::PrintFunctionTable( - moveStatsType * statp) +string Moves::PrintFunctionTable(const moveStatsType& stat) const { - char str[2][40]; - - if (statp->nfuncs == 0) - return; + if (stat.nfuncs == 0) + return ""; - fprintf(fp, "%-15s %5s %5s %4s %8s %8s\n", - "Function", "Avg", "Len", "%", "Count", "Imp"); + stringstream ss; + ss << setw(15) << left << "Function" << + setw(6) << "Avg" << + setw(6) << "Len" << + setw(5) << "%" << + setw(9) << "Count" << + setw(9) << "Imp" << "\n"; - for (int fr = 0; fr < MG_NUM_FUNCTIONS; fr++) + for (int fr = 0; fr < MG_SIZE; fr++) { - for (int f = 0; f < statp->nfuncs; f++) + for (int f = 0; f < stat.nfuncs; f++) { - if (statp->list[f].findex != fr) + if (stat.list[f].findex != fr) continue; - sprintf(str[0], "%-15s", funcName[fr]); - - fprintf(fp, "%s %34s\n", - str[0], - Moves::FullAverageString(&statp->list[f], str[1])); + ss << setw(15) << left << funcName[fr] << + Moves::FullAverageString(stat.list[f]) << "\n"; } } + return ss.str(); } -void Moves::PrintTrickDetails() + +void Moves::PrintTrickStats(ofstream& fout) const { - fprintf(fp, "Trick detail statistics\n\n"); + fout << "Overall statistics\n\n"; + fout << Moves::PrintTrickTable(trickTable); + + fout << "\n\nStatistics for winning suit\n\n"; + fout << Moves::PrintTrickTable(trickSuitTable) << "\n\n"; +} + + +void Moves::PrintTrickDetails(ofstream& fout) const +{ + fout << "Trick detail statistics\n\n"; for (int t = 12; t >= 0; t--) { for (int h = 0; h < DDS_HANDS; h++) { - fprintf(fp, "Trick %d, relative hand %d\n", t, h); - Moves::PrintFunctionTable(&trickDetailTable[t][h]); - fprintf(fp, "\n"); + fout << "Trick " << t << ", relative hand " << h << "\n"; + fout << Moves::PrintFunctionTable(trickDetailTable[t][h]) << "\n"; } } - fprintf(fp, "Suit detail statistics\n\n"); + fout << "Suit detail statistics\n\n"; for (int t = 12; t >= 0; t--) { for (int h = 0; h < DDS_HANDS; h++) { - fprintf(fp, "Trick %d, relative hand %d\n", t, h); - Moves::PrintFunctionTable(&trickDetailSuitTable[t][h]); - fprintf(fp, "\n"); + fout << "Trick " << t << ", relative hand " << h << "\n"; + fout << Moves::PrintFunctionTable(trickDetailSuitTable[t][h]) << + "\n"; } } - fprintf(fp, "\n\n"); + fout << "\n\n"; } -void Moves::PrintFunctionStats() +void Moves::PrintFunctionStats(ofstream& fout) const { - fprintf(fp, "Function statistics\n\n"); - Moves::PrintFunctionTable(&trickFuncTable); + fout << "Function statistics\n\n"; + fout << Moves::PrintFunctionTable(trickFuncTable); - fprintf(fp, "\n\nFunction statistics for winning suit\n\n"); - Moves::PrintFunctionTable(&trickFuncSuitTable); - fprintf(fp, "\n\n"); + fout << "\n\nFunction statistics for winning suit\n\n"; + fout << Moves::PrintFunctionTable(trickFuncSuitTable); + fout << "\n\n"; } - diff --git a/src/Moves.h b/src/Moves.h index e46dee8e..46ce2089 100644 --- a/src/Moves.h +++ b/src/Moves.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,33 +10,33 @@ #ifndef DDS_MOVES_H #define DDS_MOVES_H -#include -#include -#include +#include +#include +#include + #include "dds.h" #include "../include/dll.h" -#include "Stats.h" - -#define CMP_SWAP(i, j) if (a[i].weight < a[j].weight) \ - { moveType tmp = a[i]; a[i] = a[j]; a[j] = tmp; } - -#define CMP_SWAP_NEW(i, j) if (mply[i].weight < mply[j].weight) \ - { tmp = mply[i]; mply[i] = mply[j]; mply[j] = tmp; } - -#define MG_NT0 0 -#define MG_TRUMP0 1 -#define MG_NT_VOID1 2 -#define MG_TRUMP_VOID1 3 -#define MG_NT_NOTVOID1 4 -#define MG_TRUMP_NOTVOID1 5 -#define MG_NT_VOID2 6 -#define MG_TRUMP_VOID2 7 -#define MG_NT_NOTVOID2 8 -#define MG_TRUMP_NOTVOID2 9 -#define MG_NT_VOID3 10 -#define MG_TRUMP_VOID3 11 -#define MG_COMB_NOTVOID3 12 -#define MG_NUM_FUNCTIONS 13 + +using namespace std; + + +enum MGtype +{ + MG_NT0 = 0, + MG_TRUMP0 = 1, + MG_NT_VOID1 = 2, + MG_TRUMP_VOID1 = 3, + MG_NT_NOTVOID1 = 4, + MG_TRUMP_NOTVOID1 = 5, + MG_NT_VOID2 = 6, + MG_TRUMP_VOID2 = 7, + MG_NT_NOTVOID2 = 8, + MG_TRUMP_NOTVOID2 = 9, + MG_NT_VOID3 = 10, + MG_TRUMP_VOID3 = 11, + MG_COMB_NOTVOID3 = 12, + MG_SIZE = 13 +}; struct trickDataType @@ -84,9 +84,9 @@ class Moves moveType * mply; - int lastCall[13][DDS_HANDS]; + MGtype lastCall[13][DDS_HANDS]; - char funcName[13][40]; + string funcName[MG_SIZE]; struct moveStatType { @@ -99,7 +99,7 @@ class Moves struct moveStatsType { int nfuncs; - moveStatType list[MG_NUM_FUNCTIONS]; + moveStatType list[MG_SIZE]; }; moveStatType trickTable[13][DDS_HANDS]; @@ -114,191 +114,151 @@ class Moves moveStatsType trickFuncSuitTable; - FILE * fp; - - char fname[80]; - void WeightAllocTrump0( - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]); + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]); void WeightAllocNT0( - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]); - - void WeightAllocTrumpNotvoid1( - pos * posPoint); - - void WeightAllocNTNotvoid1( - pos * posPoint); - - void WeightAllocTrumpVoid1( - pos * posPoint); - - void WeightAllocNTVoid1( - pos * posPoint); - - void WeightAllocTrumpNotvoid2( - pos * posPoint); - - void WeightAllocNTNotvoid2( - pos * posPoint); - - void WeightAllocTrumpVoid2( - pos * posPoint); - - void WeightAllocNTVoid2( - pos * posPoint); - - void WeightAllocCombinedNotvoid3( - pos * posPoint); - - void WeightAllocTrumpVoid3( - pos * posPoint); - - void WeightAllocNTVoid3( - pos * posPoint); + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]); + + void WeightAllocTrumpNotvoid1( const pos& tpos); + void WeightAllocNTNotvoid1(const pos& tpos); + void WeightAllocTrumpVoid1(const pos& tpos); + void WeightAllocNTVoid1(const pos& tpos); + void WeightAllocTrumpNotvoid2(const pos& tpos); + void WeightAllocNTNotvoid2(const pos& tpos); + void WeightAllocTrumpVoid2(const pos& tpos); + void WeightAllocNTVoid2(const pos& tpos); + void WeightAllocCombinedNotvoid3(const pos& tpos); + void WeightAllocTrumpVoid3(const pos& tpos); + void WeightAllocNTVoid3(const pos& tpos); void GetTopNumber( - int ris, - int prank, - int * topNumber, - int * mno); - - int RankForcesAce( - int cards4th); + const int ris, + const int prank, + int& topNumber, + int& mno) const; - typedef void (Moves::*WeightPtr)(pos * posPoint); + int RankForcesAce(int cards4th) const; + typedef void (Moves::*WeightPtr)(const pos& tpos); WeightPtr WeightList[16]; inline bool WinningMove( - moveType * mvp1, - extCard * mvp2, - int trump); + const moveType& mvp1, + const extCard& mvp2, + const int trump) const; - void PrintMove( - movePlyType * mply); + string PrintMove(const movePlyType& mply) const; void MergeSort(); void UpdateStatsEntry( - moveStatsType * statp, - int findex, - int hit, - int len); + moveStatsType& stat, + const int findex, + const int hit, + const int len) const; - char * AverageString( - moveStatType * statp, - char str[]); + string AverageString(const moveStatType& statp) const; - char * FullAverageString( - moveStatType * statp, - char str[]); + string FullAverageString(const moveStatType& statp) const; - void PrintTrickTable( - moveStatType tablep[][DDS_HANDS]); + string PrintTrickTable(const moveStatType tablep[][DDS_HANDS]) const; - void PrintFunctionTable( - moveStatsType * tablep); + string PrintFunctionTable(const moveStatsType& tablep) const; public: Moves(); ~Moves(); - void SetFile(char * fname); - void Init( - int tricks, - int relStartHand, - int initialRanks[], - int initialSuits[], - unsigned short int rankInSuit[DDS_HANDS][DDS_SUITS], - int trump, - int leadHand); + const int tricks, + const int relStartHand, + const int initialRanks[], + const int initialSuits[], + const unsigned short rankInSuit[DDS_HANDS][DDS_SUITS], + const int trump, + const int leadHand); void Reinit( - int tricks, - int leadHand); + const int tricks, + const int leadHand); int MoveGen0( - int tricks, - pos * posPoint, - moveType * bestMove, - moveType * bestMoveTT, - relRanksType thrp_rel[]); + const int tricks, + const pos& tpos, + const moveType& bestMove, + const moveType& bestMoveTT, + const relRanksType thrp_rel[]); int MoveGen123( - int tricks, - int relHand, - pos * posPoint); + const int tricks, + const int relHand, + const pos& tpos); int GetLength( - int trick, - int relHand); + const int trick, + const int relHand) const; void MakeSpecific( - moveType * mply, - int trick, - int relHand); + const moveType& mply, + const int trick, + const int relHand); - moveType * MakeNext( - int trick, - int relHand, - unsigned short int winRanks[DDS_SUITS]); + moveType const * MakeNext( + const int trick, + const int relHand, + const unsigned short winRanks[DDS_SUITS]); - moveType * MakeNextSimple( - int trick, - int relHand); + moveType const * MakeNextSimple( + const int trick, + const int relHand); void Step( - int tricks, - int relHand); + const int tricks, + const int relHand); void Rewind( - int tricks, - int relHand); + const int tricks, + const int relHand); void Purge( - int tricks, - int relHand, - moveType forbiddenMoves[]); + const int tricks, + const int relHand, + const moveType forbiddenMoves[]); void Reward( - int trick, - int relHand); + const int trick, + const int relHand); - trickDataType * GetTrickData( - int tricks); + const trickDataType& GetTrickData(const int tricks); void Sort( - int tricks, - int relHand); + const int tricks, + const int relHand); - void PrintMoves( - int trick, - int relHand); + string PrintMoves( + const int trick, + const int relHand) const; void RegisterHit( - int tricks, - int relHand); - - void TrickToText( - int trick, - char text[]); + const int tricks, + const int relHand); - void PrintTrickStats(); + string TrickToText(const int trick) const; - void PrintTrickDetails(); + void PrintTrickStats(ofstream& fout) const; - void PrintFunctionStats(); + void PrintTrickDetails(ofstream& fout) const; + void PrintFunctionStats(ofstream& fout) const; }; #endif diff --git a/src/PBN.cpp b/src/PBN.cpp index d9ee5994..3a68688c 100644 --- a/src/PBN.cpp +++ b/src/PBN.cpp @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -11,20 +11,18 @@ #include "dds.h" #include "PBN.h" -int IsCard(char cardChar); +int IsCard(const char cardChar); int ConvertFromPBN( - char * dealBuff, + char const * dealBuff, unsigned int remainCards[DDS_HANDS][DDS_SUITS]) { - int bp = 0, first, card, hand, handRelFirst, suitInHand, h, s; - int IsCard(char cardChar); - - for (h = 0; h < DDS_HANDS; h++) - for (s = 0; s < DDS_SUITS; s++) + for (int h = 0; h < DDS_HANDS; h++) + for (int s = 0; s < DDS_SUITS; s++) remainCards[h][s] = 0; + int bp = 0; while (((dealBuff[bp] != 'W') && (dealBuff[bp] != 'N') && (dealBuff[bp] != 'E') && (dealBuff[bp] != 'S') && (dealBuff[bp] != 'w') && (dealBuff[bp] != 'n') && @@ -34,6 +32,7 @@ int ConvertFromPBN( if (bp >= 3) return 0; + int first; if ((dealBuff[bp] == 'N') || (dealBuff[bp] == 'n')) first = 0; else if ((dealBuff[bp] == 'E') || (dealBuff[bp] == 'e')) @@ -46,8 +45,9 @@ int ConvertFromPBN( bp++; bp++; - handRelFirst = 0; - suitInHand = 0; + int handRelFirst = 0; + int suitInHand = 0; + int card, hand; while ((bp < 80) && (dealBuff[bp] != '\0')) { @@ -99,7 +99,7 @@ int ConvertFromPBN( } -int IsCard(char cardChar) +int IsCard(const char cardChar) { switch (cardChar) { @@ -120,23 +120,18 @@ int IsCard(char cardChar) 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': case 'j': return 11; + case 'Q': case 'q': return 12; + case 'K': case 'k': return 13; + case 'A': case 'a': return 14; default: @@ -146,19 +141,19 @@ int IsCard(char cardChar) int ConvertPlayFromPBN( - playTracePBN * playPBN, - playTraceBin * playBin) + const playTracePBN& playPBN, + playTraceBin& playBin) { - int n = playPBN->number; + const int n = playPBN.number; if (n < 0 || n > 52) return RETURN_PLAY_FAULT; - playBin->number = n; + playBin.number = n; for (int i = 0; i < 2 * n; i += 2) { - char suit = playPBN->cards[i]; + char suit = playPBN.cards[i]; int s; if (suit == 's' || suit == 'S') @@ -171,13 +166,13 @@ int ConvertPlayFromPBN( s = 3; else return RETURN_PLAY_FAULT; - playBin->suit[i >> 1] = s; + playBin.suit[i >> 1] = s; - int rank = IsCard(playPBN->cards[i + 1]); + int rank = IsCard(playPBN.cards[i+1]); if (rank == 0) return RETURN_PLAY_FAULT; - playBin->rank[i >> 1] = rank; + playBin.rank[i >> 1] = rank; } return RETURN_NO_FAULT; } diff --git a/src/PBN.h b/src/PBN.h index 12bde699..543784ec 100644 --- a/src/PBN.h +++ b/src/PBN.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,13 +10,15 @@ #ifndef DDS_PBN_H #define DDS_PBN_H +#include "../include/dll.h" + int ConvertFromPBN( - char * dealBuff, + char const * dealBuff, unsigned int remainCards[DDS_HANDS][DDS_SUITS]); int ConvertPlayFromPBN( - struct playTracePBN * playPBN, - struct playTraceBin * playBin); + const playTracePBN& playPBN, + playTraceBin& playBin); #endif diff --git a/src/Par.cpp b/src/Par.cpp index 2b3d400e..89dbe032 100644 --- a/src/Par.cpp +++ b/src/Par.cpp @@ -2,15 +2,21 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ #include +#include +#include #include "dds.h" +#include "PBN.h" + +using namespace std; + struct par_suits_type { @@ -49,7 +55,6 @@ int STDCALL CalcParPBN( { int res; ddTableDeal tableDeal; - int ConvertFromPBN(char * dealBuff, unsigned int remainCards[4][4]); int STDCALL CalcPar(ddTableDeal tableDeal, int vulnerable, ddTableResults * tablep, parResults * presp); @@ -283,7 +288,7 @@ int STDCALL SidesParBin( 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 = max(t1, t2); /* tt is the maximum number of tricks current side can take in denomination.*/ @@ -519,7 +524,8 @@ int STDCALL SidesParBin( checked that the lowered contract still gets the score bonus points that is present in par score.*/ - sc2 = abs(best_par_score[i]); + sc2 = (best_par_score[i] >= 0 ? + best_par_score[i] : -best_par_score[i]); /* Score for making the tentative lower par contract. */ while (max_lower > 0) { @@ -543,7 +549,7 @@ int STDCALL SidesParBin( since the cost for the sacrifice is too small. */ } - int opp_tricks = Max(t3[j], t4[j]); + int opp_tricks = max(t3[j], t4[j]); while (max_lower > 0) { @@ -577,10 +583,11 @@ int STDCALL SidesParBin( k = 2; break; default: - throw std::runtime_error("j not in [0..3] in Par"); + return RETURN_UNKNOWN_FAULT; + // j not in (0..4) } - max_lower = Min(max_low[k][best_par[m][i].par_tricks - 6], + max_lower = min(max_low[k][best_par[m][i].par_tricks - 6], max_lower); sidesRes[i].contracts[m].denom = j; @@ -1209,8 +1216,8 @@ int STDCALL DealerParBin( presp->contracts[k].denom = 4; break; default: - throw std::runtime_error( - "contracts[1] not in (NSHDC) in DealerParBin"); + return RETURN_UNKNOWN_FAULT; + // denomination not in (NSHDC) } if (strstr(parContr2[k].contracts, "NS")) @@ -1388,7 +1395,8 @@ int STDCALL ConvertToDealerTextFormat( strcat(resp, "EW "); break; default: - throw std::runtime_error("Seats not in [N,W,S,W,NS,EW] in ConvertToDealerTextFormat"); + return RETURN_UNKNOWN_FAULT; + // Seats not in (N,W,S,W,NS,EW) } for (i = 0; i < 10; i++) @@ -1414,7 +1422,8 @@ int STDCALL ConvertToDealerTextFormat( strcat(resp, "C"); break; default: - throw std::runtime_error("denom not in [N,S,H,D,C] in ConvertToDealerTextFormat"); + return RETURN_UNKNOWN_FAULT; + // denom not in /N,S,H,D,C) } if (pres->contracts[k].underTricks > 0) @@ -1487,7 +1496,8 @@ int STDCALL ConvertToSidesTextFormat( strcat(resp->parText[i], "EW "); break; default: - throw std::runtime_error("Seats not in [N,W,S,W,NS,EW] in ConvertToSidesTextFormat"); + return RETURN_UNKNOWN_FAULT; + // Seats not in (N,W,S,W,NS,EW) } for (j = 0; j < 10; j++) @@ -1513,7 +1523,8 @@ int STDCALL ConvertToSidesTextFormat( strcat(resp->parText[i], "C"); break; default: - throw std::runtime_error("denom not in [N,S,H,D,C] in ConvertToSidesTextFormat"); + return RETURN_UNKNOWN_FAULT; + // denom not in (N,S,H,D,C) } if ((pres + i)->contracts[k].underTricks > 0) @@ -1562,4 +1573,3 @@ int STDCALL ConvertToSidesTextFormat( return RETURN_NO_FAULT; } - diff --git a/src/PlayAnalyser.cpp b/src/PlayAnalyser.cpp index 494cd225..a7de381a 100644 --- a/src/PlayAnalyser.cpp +++ b/src/PlayAnalyser.cpp @@ -2,37 +2,43 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ - -#include "dds.h" -#include "threadmem.h" +#include "PlayAnalyser.h" #include "SolverIF.h" -#include "PBN.h" +#include "System.h" +#include "Memory.h" #include "Scheduler.h" +#include "PBN.h" +#include "debug.h" + +using namespace std; + // Only single-threaded debugging here. #define DEBUG 0 -#ifdef DDS_SCHEDULER - #define START_BLOCK_TIMER scheduler.StartBlockTimer() - #define END_BLOCK_TIMER scheduler.EndBlockTimer() - #define START_THREAD_TIMER(a) scheduler.StartThreadTimer(a) - #define END_THREAD_TIMER(a) scheduler.EndThreadTimer(a) -#else - #define START_BLOCK_TIMER 1 - #define END_BLOCK_TIMER 1 - #define START_THREAD_TIMER(a) 1 - #define END_THREAD_TIMER(a) 1 -#endif - #if DEBUG -FILE * fp; + ofstream fout; #endif +struct playparamType +{ + int noOfBoards; + playTracesBin * plp; + solvedPlays * solvedp; + int error; +}; + +paramType playparam; +playparamType traceparam; + +extern System sysdep; +extern Memory memory; +extern Scheduler scheduler; int STDCALL AnalysePlayBin( @@ -41,15 +47,20 @@ int STDCALL AnalysePlayBin( solvedPlay * solvedp, int thrId) { + if (! sysdep.ThreadOK(thrId)) + return RETURN_THREAD_INDEX; + + ThreadData * thrp = memory.GetPtr(static_cast(thrId)); + moveType move; futureTricks fut; - int ret = SolveBoard(dl, -1, 1, 1, &fut, thrId); + int ret = SolveBoardInternal(thrp, dl, -1, 1, 1, &fut); if (ret != RETURN_NO_FAULT) return ret; - const int numTricks = ((localVar[thrId].iniDepth + 3) >> 2) + 1; - const int numCardsPlayed = ((48 - localVar[thrId].iniDepth) % 4) + 1; + const int numTricks = ((thrp->iniDepth + 3) >> 2) + 1; + const int numCardsPlayed = ((48 - thrp->iniDepth) % 4) + 1; int last_trick = (play.number + 3) / 4; int last_card = ((play.number + 3) % 4) + 1; @@ -73,14 +84,14 @@ int STDCALL AnalysePlayBin( int solved_declarer = solvedp->tricks[0]; #if DEBUG int initial_par = solved_declarer; - fp = fopen("trace.txt", "a"); - fprintf(fp, "Initial solve: %d\n", initial_par); - fprintf(fp, "no %d, Last trick %d, last card %d\n", - play.number, last_trick, last_card); - fprintf(fp, "%5s %5s %5s %8s %6s %6s %5s %5s %5s\n", - "trick", "card", "rest", "declarer", - "player", "side", "soln0", "soln1", "diff"); - fclose(fp); + fout.open("trace.txt", ofstream::out | ofstream::app); + fout << "Initial solve: " << initial_par << "\n"; + fout << "no " << play.number << ", Last trick " << last_trick << + ", last card " << last_card << "\n"; + fout << setw(5) << "trick" << setw(6) << "card" << + setw(6) << "rest" << setw(9) << "declarer" << + setw(7) << "player" << setw(7) << "side" << + setw(6) << "soln0" << setw(6) << "soln1" << setw(6) << "diff" << "\n"; #endif for (int trick = 1; trick <= last_trick; trick++) @@ -140,10 +151,10 @@ int STDCALL AnalysePlayBin( if (! usingCurrent) { #if DEBUG - fp = fopen("trace.txt", "a"); - fprintf(fp, "ERR Trick %d card %d pl %d: suit %d hold %d\n", - trick, card, running_player, suit, hold); - fclose(fp); + fout << "ERR Trick " << trick << " card " << card << + " pl " << running_player << ": suit " << suit << + " hold " << hold << "\n"; + fout.close(); #endif return RETURN_PLAY_FAULT; } @@ -186,13 +197,13 @@ int STDCALL AnalysePlayBin( if (usingCurrent) continue; - if ((ret = AnalyseLaterBoard(dl.first, - &move, hint, hintDir, &fut, thrId)) + if ((ret = AnalyseLaterBoard(thrp, dl.first, &move, hint, + hintDir, &fut)) != RETURN_NO_FAULT) { #if DEBUG - fp = fopen("trace.txt", "a"); - fprintf(fp, "SolveBoard failed, ret %d\n", ret); + fout << "SolveBoard failed, ret " << ret << "\n"; + fout.close(); #endif return ret; } @@ -203,13 +214,15 @@ int STDCALL AnalysePlayBin( solvedp->tricks[offset + card] = new_solved_decl; #if DEBUG - fp = fopen("trace.txt", "a"); - fprintf(fp, "%5d %5d %5d %8d %6c %6d %5d %5d %5d\n", - trick, card, running_remainder, running_declarer, - cardHand[resp_player], running_side, - solved_declarer, new_solved_decl, - new_solved_decl - solved_declarer); - fclose(fp); + fout << setw(5) << trick << + setw(6) << card << + setw(6) << running_remainder << + setw(9) << running_declarer << + setw(7) << cardHand[resp_player] << + setw(7) << running_side << + setw(6) << solved_declarer << + setw(6) << new_solved_decl << + setw(6) << new_solved_decl - solved_declarer << "\n"; #endif solved_declarer = new_solved_decl; @@ -217,6 +230,9 @@ int STDCALL AnalysePlayBin( } solvedp->number = 4 * last_trick + last_card - 3 - (numCardsPlayed - 1); +#if DEBUG + fout.close(); +#endif return RETURN_NO_FAULT; } @@ -242,267 +258,94 @@ int STDCALL AnalysePlayPBN( dl.currentTrickRank[i] = dlPBN.currentTrickRank[i]; } - if (ConvertPlayFromPBN(&playPBN, &play) != - RETURN_NO_FAULT) + if (ConvertPlayFromPBN(playPBN, play) != RETURN_NO_FAULT) return RETURN_PLAY_FAULT; return AnalysePlayBin(dl, play, solvedp, thrId); } -long pchunk = 0; -int pfail; - - -#if (defined(_WIN32) || defined(__CYGWIN__)) && \ - !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - -HANDLE solveAllPlayEvents[MAXNOOFTHREADS]; -LONG volatile pthreadIndex; -LONG volatile pcurrent; -paramType playparam; -playparamType traceparam; - -DWORD CALLBACK SolveChunkTracePlay (void *); - -DWORD CALLBACK SolveChunkTracePlay (void *) +void PlaySingleCommon( + const int thrId, + const int bno) { - solvedPlay solved[MAXNOOFBOARDS]; - int thid; + solvedPlay solved; + + int res = AnalysePlayBin( + playparam.bop->deals[bno], + traceparam.plp->plays[bno], + &solved, + thrId); + + // If there are multiple errors, this will catch one of them. + if (res == 1) + traceparam.solvedp->solved[bno] = solved; + else + playparam.error = res; +} - thid = InterlockedIncrement(&pthreadIndex); +void PlayChunkCommon(const int thrId) +{ int index; schedType st; + while (1) { - st = scheduler.GetNumber(thid); + st = scheduler.GetNumber(thrId); index = st.number; if (index == -1) break; - START_THREAD_TIMER(thid); - int res = AnalysePlayBin( - playparam.bop->deals[index], - traceparam.plp->plays[index], - &solved[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - traceparam.solvedp->solved[index] = solved[index]; - else - pfail = res; - /* If there are multiple errors, this will catch one of them */ + PlaySingleCommon(thrId, index); } - - if (SetEvent(solveAllPlayEvents[thid]) == 0) - return 0; - - return 1; } - int STDCALL AnalyseAllPlaysBin( boards * bop, playTracesBin * plp, solvedPlays * solvedp, int chunkSize) { + UNUSED(chunkSize); + + playparam.error = 0; + if (bop->noOfBoards > MAXNOOFBOARDS) return RETURN_TOO_MANY_BOARDS; if (bop->noOfBoards != plp->noOfBoards) return RETURN_UNKNOWN_FAULT; - pchunk = chunkSize; - pfail = 1; - - int res; - DWORD solveAllWaitResult; - - pcurrent = 0; - pthreadIndex = -1; - playparam.bop = bop; traceparam.plp = plp; playparam.noOfBoards = bop->noOfBoards; traceparam.noOfBoards = bop->noOfBoards; traceparam.solvedp = solvedp; - scheduler.RegisterTraceDepth(plp, bop->noOfBoards); - scheduler.Register(bop, SCHEDULER_TRACE); - - for (int k = 0; k < noOfThreads; k++) - { - solveAllPlayEvents[k] = CreateEvent(NULL, FALSE, FALSE, 0); - if (solveAllPlayEvents[k] == 0) - return RETURN_THREAD_CREATE; - } - - for (int k = 0; k < noOfThreads; k++) - { - res = QueueUserWorkItem(SolveChunkTracePlay, NULL, - WT_EXECUTELONGFUNCTION); - if (res != 1) - return res; - } + scheduler.RegisterRun(DDS_RUN_TRACE, * bop, * plp); + sysdep.RegisterRun(DDS_RUN_TRACE, * bop); START_BLOCK_TIMER; - solveAllWaitResult = WaitForMultipleObjects( - static_cast(noOfThreads), - solveAllPlayEvents, TRUE, INFINITE); + int retRun = sysdep.RunThreads(); END_BLOCK_TIMER; - if (solveAllWaitResult != WAIT_OBJECT_0) - return RETURN_THREAD_WAIT; - - for (int k = 0; k < noOfThreads; k++) - CloseHandle(solveAllPlayEvents[k]); + if (retRun != RETURN_NO_FAULT) + return retRun; solvedp->noOfBoards = bop->noOfBoards; - return pfail; -} - -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDDS_THREADS_SINGLE) - -// This code for LLVM multi-threading on the Mac was kindly -// contributed by Pierre Cossard. - -int STDCALL AnalyseAllPlaysBin( - boards * bop, - playTracesBin * plp, - solvedPlays * solvedp, - int chunkSize) -{ - if (bop->noOfBoards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - if (bop->noOfBoards != plp->noOfBoards) - return RETURN_UNKNOWN_FAULT; - - pchunk = chunkSize; - pfail = 1; - - solvedPlay *solved = static_cast - (calloc(MAXNOOFBOARDS, sizeof(solvedPlay))); - - scheduler.RegisterTraceDepth(plp, bop->noOfBoards); - scheduler.Register(bop, SCHEDULER_TRACE); - - - START_BLOCK_TIMER; - dispatch_apply(static_cast(noOfThreads), - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), - ^(size_t t) - { - while (1) - { - int thid = static_cast(t); - - schedType st = scheduler.GetNumber(thid); - int index = st.number; - if (index == -1) - break; - - START_THREAD_TIMER(thid); - int res = AnalysePlayBin(bop->deals[index], - plp->plays[index], - &solved[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - solvedp->solved[index] = solved[index]; - else - pfail = res; - } - }); - - END_BLOCK_TIMER; - free(solved); - - solvedp->noOfBoards = bop->noOfBoards; - - return pfail; -} - -#else - -int STDCALL AnalyseAllPlaysBin( - boards * bop, - playTracesBin * plp, - solvedPlays * solvedp, - int chunkSize) -{ - if (bop->noOfBoards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - if (bop->noOfBoards != plp->noOfBoards) - return RETURN_UNKNOWN_FAULT; - - pchunk = chunkSize; - pfail = 1; - - int res; - solvedPlay solved[MAXNOOFBOARDS]; - - scheduler.RegisterTraceDepth(plp, bop->noOfBoards); - scheduler.Register(bop, SCHEDULER_TRACE); - -#if defined (_OPENMP) && !defined(DDS_THREADS_SINGLE) - if (omp_get_dynamic()) - omp_set_dynamic(0); - omp_set_num_threads(noOfThreads); -#elif defined (_OPENMP) - omp_set_num_threads(1); -#endif - - int index, thid; - schedType st; - - START_BLOCK_TIMER; - - #pragma omp parallel default(none) shared(scheduler, bop, plp, solvedp, solved, pchunk, pfail) private(st, index, thid, res) - { - #pragma omp while schedule(dynamic, pchunk) - - while (1) - { -#if defined (_OPENMP) && !defined(DDS_THREADS_SINGLE) - thid = omp_get_thread_num(); -#else - thid = 0; +#ifdef DDS_SCHEDULER + scheduler.PrintTiming(); #endif - st = scheduler.GetNumber(thid); - index = st.number; - if (index == -1) - break; - - START_THREAD_TIMER(thid); - res = AnalysePlayBin(bop->deals[index], - plp->plays[index], - &solved[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - solvedp->solved[index] = solved[index]; - else - pfail = res; - } - } - - END_BLOCK_TIMER; - - solvedp->noOfBoards = bop->noOfBoards; - - return pfail; + if (playparam.error == 0) + return RETURN_NO_FAULT; + else + return playparam.error; } -#endif + int STDCALL AnalyseAllPlaysPBN( boardsPBN * bopPBN, @@ -519,22 +362,20 @@ int STDCALL AnalyseAllPlaysPBN( for (int k = 0; k < bopPBN->noOfBoards; k++) { - deal * dl; - dealPBN * dlp; + deal& dl = bd.deals[k]; + dealPBN& dlp = bopPBN->deals[k]; - dl = &(bd.deals[k]); - dlp = &(bopPBN->deals[k]); - if (ConvertFromPBN(dlp->remainCards, - dl->remainCards) != RETURN_NO_FAULT) + if (ConvertFromPBN(dlp.remainCards, + dl.remainCards) != RETURN_NO_FAULT) return RETURN_PBN_FAULT; - dl->trump = dlp->trump; - dl->first = dlp->first; + dl.trump = dlp.trump; + dl.first = dlp.first; for (int i = 0; i <= 2; i++) { - dl->currentTrickSuit[i] = dlp->currentTrickSuit[i]; - dl->currentTrickRank[i] = dlp->currentTrickRank[i]; + dl.currentTrickSuit[i] = dlp.currentTrickSuit[i]; + dl.currentTrickRank[i] = dlp.currentTrickRank[i]; } } @@ -542,7 +383,7 @@ int STDCALL AnalyseAllPlaysPBN( for (int k = 0; k < plpPBN->noOfBoards; k++) { - if (ConvertPlayFromPBN(&plpPBN->plays[k], &pl.plays[k]) != + if (ConvertPlayFromPBN(plpPBN->plays[k], pl.plays[k]) != RETURN_NO_FAULT) return RETURN_PLAY_FAULT; } @@ -551,3 +392,29 @@ int STDCALL AnalyseAllPlaysPBN( return AnalyseAllPlaysBin(&bd, &pl, solvedp, chunkSize); } + +void DetectPlayDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs) +{ + // This dummy function is there for consistency in System.cpp. + // In practice there is not much point in deteting play repeats, + // as it is highly unlikely that the play went identically at + // two tables. + + uniques.resize(static_cast(bds.noOfBoards)); + crossrefs.resize(static_cast(bds.noOfBoards)); + for (unsigned i = 0; i < uniques.size(); i++) + { + uniques[i] = static_cast(i); + crossrefs[i] = -1; + } +} + + +void CopyPlaySingle(const vector& crossrefs) +{ + UNUSED(crossrefs); +} + diff --git a/src/PlayAnalyser.h b/src/PlayAnalyser.h new file mode 100644 index 00000000..7b860e49 --- /dev/null +++ b/src/PlayAnalyser.h @@ -0,0 +1,35 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_PLAYANALYSER_H +#define DDS_PLAYANALYSER_H + +#include + +#include "dds.h" + +using namespace std; + + +void PlaySingleCommon( + const int thrId, + const int bno); + +void PlayChunkCommon( + const int thrId); + +void DetectPlayDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs); + +void CopyPlaySingle( + const vector& crossrefs); + +#endif diff --git a/src/QuickTricks.cpp b/src/QuickTricks.cpp index 31c4da92..4a9d1f71 100644 --- a/src/QuickTricks.cpp +++ b/src/QuickTricks.cpp @@ -2,111 +2,111 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include "dds.h" -#include "threadmem.h" +#include + #include "QuickTricks.h" int QtricksLeadHandNT( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int * lhoTrumpRanks, - int * rhoTrumpRanks, - bool commPartner, - int commSuit, - int countOwn, - int countPart, - int suit, - int qtricks, - int trump, - int * res); + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + int& lhoTrumpRanks, + int& rhoTrumpRanks, + const bool commPartner, + const int commSuit, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int trump, + int& res); int QtricksLeadHandTrump( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int lhoTrumpRanks, - int rhoTrumpRanks, - int countOwn, - int countPart, - int suit, - int qtricks, - int * res); + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int lhoTrumpRanks, + const int rhoTrumpRanks, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + int& res); int QuickTricksPartnerHandTrump( - int hand, - 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 * res, - localVarType * thrp); + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int lhoTrumpRanks, + const int rhoTrumpRanks, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int commSuit, + const int commRank, + int& res, + const ThreadData& thrd); int QuickTricksPartnerHandNT( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int countOwn, - int countPart, - int suit, - int qtricks, - int commSuit, - int commRank, - int * res, - localVarType * thrp); + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int commSuit, + const int commRank, + int& res, + const ThreadData& thrd); int QuickTricks( - pos * posPoint, - int hand, - int depth, - int target, - int trump, - bool * result, - localVarType * thrp) + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + bool& result, + const ThreadData& thrd) { int suit, commRank = 0, commSuit = -1; int res; int lhoTrumpRanks = 0, rhoTrumpRanks = 0; int cutoff, lowestQtricks = 0; - *result = true; + result = true; int qtricks = 0; - if (thrp->nodeTypeStore[hand] == MAXNODE) - cutoff = target - posPoint->tricksMAX; + if (thrd.nodeTypeStore[hand] == MAXNODE) + cutoff = target - tpos.tricksMAX; else - cutoff = posPoint->tricksMAX - target + (depth >> 2) + 2; + cutoff = tpos.tricksMAX - target + (depth >> 2) + 2; bool commPartner = false; - unsigned short (* ris)[DDS_SUITS] = posPoint->rankInSuit; - unsigned char (* len)[DDS_SUITS] = posPoint->length; - highCardType * winner = posPoint->winner; + const unsigned short (* ris)[DDS_SUITS] = tpos.rankInSuit; + const unsigned char (* len)[DDS_SUITS] = tpos.length; + highCardType const * winner = tpos.winner; for (int s = 0; s < DDS_SUITS; s++) { @@ -128,7 +128,7 @@ int QuickTricks( break; } } - else if ((posPoint->secondBest[s].hand == partner[hand]) && + else if ((tpos.secondBest[s].hand == partner[hand]) && (winner[s].hand == hand) && (len[hand][s] >= 2) && (len[partner[hand]][s] >= 2)) @@ -141,7 +141,7 @@ int QuickTricks( { commPartner = true; commSuit = s; - commRank = posPoint->secondBest[s].rank; + commRank = tpos.secondBest[s].rank; break; } } @@ -159,7 +159,7 @@ int QuickTricks( break; } } - else if ((posPoint->secondBest[s].hand == partner[hand]) && + else if ((tpos.secondBest[s].hand == partner[hand]) && (winner[s].hand == hand) && (len[hand][s] >= 2) && (len[partner[hand]][s] >= 2)) @@ -167,7 +167,7 @@ int QuickTricks( /* Can cross to partner's card: Type Kx opposite Ax */ commPartner = true; commSuit = s; - commRank = posPoint->secondBest[s].rank; + commRank = tpos.secondBest[s].rank; break; } } @@ -276,7 +276,7 @@ int QuickTricks( /* The partner but not the opponents have cards in the trump suit. */ - int sum = Max(countOwn, countPart); + int sum = max(countOwn, countPart); for (int s = 0; s < DDS_SUITS; s++) { if ((sum > 0) && @@ -297,7 +297,7 @@ int QuickTricks( else if (!opps) { /* The partner but not the opponents have cards in the suit. */ - int sum = Min(countOwn, countPart); + int sum = min(countOwn, countPart); if (trump == DDS_NOTRUMP) { if (sum >= cutoff) @@ -321,7 +321,7 @@ int QuickTricks( if ((lhoTrumpRanks == 0) && (rhoTrumpRanks == 0)) { qtricks += countPart; - posPoint->winRanks[depth][commSuit] |= + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; if (qtricks >= cutoff) @@ -343,7 +343,7 @@ int QuickTricks( else { qtricks += countPart; - posPoint->winRanks[depth][commSuit] |= + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; if (qtricks >= cutoff) @@ -369,7 +369,7 @@ int QuickTricks( { if (!opps && (trump != DDS_NOTRUMP) && (suit == trump)) { - int sum = Max(countOwn, countPart); + int sum = max(countOwn, countPart); for (int s = 0; s < DDS_SUITS; s++) { if ((sum > 0) && @@ -384,14 +384,14 @@ int QuickTricks( } if (sum >= cutoff) { - posPoint->winRanks[depth][commSuit] |= + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; return sum; } } else if (!opps) { - int sum = Min(countOwn, countPart); + int sum = min(countOwn, countPart); if (trump == DDS_NOTRUMP) { if (sum >= cutoff) @@ -431,9 +431,9 @@ int QuickTricks( { if ((trump != DDS_NOTRUMP) && (trump != suit)) { - qtricks = QtricksLeadHandTrump(hand, posPoint, cutoff, depth, + qtricks = QtricksLeadHandTrump(hand, tpos, cutoff, depth, countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, - countOwn, countPart, suit, qtricks, &res); + countOwn, countPart, suit, qtricks, res); if (res == 1) return qtricks; @@ -447,10 +447,10 @@ int QuickTricks( } else { - qtricks = QtricksLeadHandNT(hand, posPoint, cutoff, depth, - countLho, countRho, &lhoTrumpRanks, &rhoTrumpRanks, + qtricks = QtricksLeadHandNT(hand, tpos, cutoff, depth, + countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, commPartner, commSuit, countOwn, countPart, - suit, qtricks, trump, &res); + suit, qtricks, trump, res); if (res == 1) return qtricks; @@ -483,10 +483,10 @@ int QuickTricks( /* There is communication with the partner */ if ((trump != DDS_NOTRUMP) && (trump != suit)) { - qtricks = QuickTricksPartnerHandTrump(hand, posPoint, + qtricks = QuickTricksPartnerHandTrump(hand, tpos, cutoff, depth, countLho, countRho, lhoTrumpRanks, rhoTrumpRanks, countOwn, - countPart, suit, qtricks, commSuit, commRank, &res, thrp); + countPart, suit, qtricks, commSuit, commRank, res, thrd); if (res == 1) return qtricks; @@ -500,9 +500,9 @@ int QuickTricks( } else { - qtricks = QuickTricksPartnerHandNT(hand, posPoint, cutoff, + qtricks = QuickTricksPartnerHandNT(hand, tpos, cutoff, depth, countLho, countRho, countOwn, countPart, - suit, qtricks, commSuit, commRank, &res, thrp); + suit, qtricks, commSuit, commRank, res, thrd); if (res == 1) return qtricks; @@ -555,7 +555,7 @@ int QuickTricks( int rr = highestRank[ris[partner[hand]][trump]]; if (rr != 0) { - posPoint->winRanks[depth][trump] |= bitMapRank[rr]; + tpos.winRanks[depth][trump] |= bitMapRank[rr]; if (1 >= cutoff) return 1; } @@ -575,7 +575,7 @@ int QuickTricks( { if ((ris[partner[hand]][trump] & bitMapRank[rr]) != 0) { - posPoint->winRanks[depth][trump] |= bitMapRank[rr]; + tpos.winRanks[depth][trump] |= bitMapRank[rr]; break; } } @@ -597,7 +597,7 @@ int QuickTricks( { if ((ris[partner[hand]][trump] & bitMapRank[rr]) != 0) { - posPoint->winRanks[depth][trump] |= bitMapRank[rr]; + tpos.winRanks[depth][trump] |= bitMapRank[rr]; break; } } @@ -641,15 +641,15 @@ int QuickTricks( continue; if (len[hand][ss] > 0) { - posPoint->winRanks[depth][ss] = bitMapRank[winner[ss].rank]; + tpos.winRanks[depth][ss] = bitMapRank[winner[ss].rank]; } } - if (thrp->nodeTypeStore[hand] != MAXNODE) - cutoff = target - posPoint->tricksMAX; + if (thrd.nodeTypeStore[hand] != MAXNODE) + cutoff = target - tpos.tricksMAX; else { - cutoff = posPoint->tricksMAX - target + (depth >> 2) + 2; + cutoff = tpos.tricksMAX - target + (depth >> 2) + 2; } if (1 >= cutoff) @@ -657,38 +657,38 @@ int QuickTricks( } } - *result = false; + result = false; return qtricks; } int QtricksLeadHandTrump( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int lhoTrumpRanks, - int rhoTrumpRanks, - int countOwn, - int countPart, - int suit, - int qtricks, - int * res) + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int lhoTrumpRanks, + const int rhoTrumpRanks, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + int& res) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ - *res = 1; + res = 1; int qt = qtricks; if (((countLho != 0) || (lhoTrumpRanks == 0)) && ((countRho != 0) || (rhoTrumpRanks == 0))) { - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->winner[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.winner[suit].rank]; qt++; if (qt >= cutoff) return qt; @@ -702,17 +702,17 @@ int QtricksLeadHandTrump( qt += countOwn - 1; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } - if (posPoint->secondBest[suit].hand == hand) + if (tpos.secondBest[suit].hand == hand) { if ((lhoTrumpRanks == 0) && (rhoTrumpRanks == 0)) { - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->secondBest[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; qt++; if (qt >= cutoff) return qt; @@ -721,20 +721,20 @@ int QtricksLeadHandTrump( qt += countOwn - 2; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } } - else if ((posPoint->secondBest[suit].hand == partner[hand]) + else if ((tpos.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]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; qt++; if (qt >= cutoff) return qt; @@ -742,52 +742,52 @@ int QtricksLeadHandTrump( (countRho <= 2) && ((countPart <= 2) || (countOwn <= 2))) { - qt += Max(countOwn - 2, countPart - 2); + qt += max(countOwn - 2, countPart - 2); if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } } - *res = 0; + res = 0; return qt; } int QtricksLeadHandNT( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int * lhoTrumpRanks, - int * rhoTrumpRanks, - bool commPartner, - int commSuit, - int countOwn, - int countPart, - int suit, - int qtricks, - int trump, - int * res) + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + int& lhoTrumpRanks, + int& rhoTrumpRanks, + const bool commPartner, + const int commSuit, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int trump, + int& res) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ - *res = 1; + res = 1; int qt = qtricks; - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->winner[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.winner[suit].rank]; qt++; if (qt >= cutoff) return qt; if ((trump == suit) && ((!commPartner) || (suit != commSuit))) { - (*lhoTrumpRanks) = Max(0, (*lhoTrumpRanks) - 1); - (*rhoTrumpRanks) = Max(0, (*rhoTrumpRanks) - 1); + lhoTrumpRanks = max(0, lhoTrumpRanks - 1); + rhoTrumpRanks = max(0, rhoTrumpRanks - 1); } if ((countLho <= 1) && (countRho <= 1) && (countPart <= 1)) @@ -795,94 +795,94 @@ int QtricksLeadHandNT( qt += countOwn - 1; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } - if (posPoint->secondBest[suit].hand == hand) + if (tpos.secondBest[suit].hand == hand) { - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->secondBest[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.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); + 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; + res = 2; return qt; } } - else if ((posPoint->secondBest[suit].hand == partner[hand]) + else if ((tpos.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]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.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); + 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); + qt += max(countOwn - 2, countPart - 2); if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } - *res = 0; + res = 0; return qt; } int QuickTricksPartnerHandTrump( - int hand, - 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 * res, - localVarType * thrp) + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int lhoTrumpRanks, + const int rhoTrumpRanks, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int commSuit, + const int commRank, + int& res, + const ThreadData& thrd) { /* res=0 Continue with same suit. res=1 Cutoff. res=2 Continue with next suit. */ - *res = 1; + res = 1; int qt = qtricks; if (((countLho != 0) || (lhoTrumpRanks == 0)) && ((countRho != 0) || (rhoTrumpRanks == 0))) { - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->winner[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.winner[suit].rank]; - posPoint->winRanks[depth][commSuit] |= bitMapRank[commRank]; + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; qt++; /* A trick can be taken */ if (qt >= cutoff) @@ -896,21 +896,21 @@ int QuickTricksPartnerHandTrump( qt += countPart - 1; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } - if (posPoint->secondBest[suit].hand == partner[hand]) + if (tpos.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]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; - posPoint->winRanks[depth][commSuit] |= bitMapRank[commRank]; + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; qt++; if (qt >= cutoff) return qt; @@ -919,12 +919,12 @@ int QuickTricksPartnerHandTrump( qt += countPart - 2; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } } - else if ((posPoint->secondBest[suit].hand == hand) && + else if ((tpos.secondBest[suit].hand == hand) && (countPart > 1) && (countOwn > 1)) { @@ -934,10 +934,10 @@ int QuickTricksPartnerHandTrump( if ((lhoTrumpRanks == 0) && (rhoTrumpRanks == 0)) { /* Opponents have no trump */ - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->secondBest[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; - posPoint->winRanks[depth][commSuit] |= bitMapRank[commRank]; + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; qt++; if (qt >= cutoff) @@ -946,29 +946,29 @@ int QuickTricksPartnerHandTrump( (countRho <= 2) && ((countOwn <= 2) || (countPart <= 2))) { - qt += Max(countPart - 2, countOwn - 2); + qt += max(countPart - 2, countOwn - 2); if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } } else if ((suit == commSuit) && - (posPoint->secondBest[suit].hand == lho[hand]) && + (tpos.secondBest[suit].hand == lho[hand]) && ((countLho >= 2) || (lhoTrumpRanks == 0)) && ((countRho >= 2) || (rhoTrumpRanks == 0))) { unsigned short ranks = 0; for (int h = 0; h < DDS_HANDS; h++) - ranks |= posPoint->rankInSuit[h][suit]; + ranks |= tpos.rankInSuit[h][suit]; - if (thrp->rel[ranks].absRank[3][suit].hand == partner[hand]) + if (thrd.rel[ranks].absRank[3][suit].hand == partner[hand]) { - posPoint->winRanks[depth][suit] |= bitMapRank[ - static_cast(thrp->rel[ranks].absRank[3][suit].rank) ]; + tpos.winRanks[depth][suit] |= bitMapRank[ + static_cast(thrd.rel[ranks].absRank[3][suit].rank) ]; - posPoint->winRanks[depth][commSuit] |= bitMapRank[commRank]; + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; qt++; if (qt >= cutoff) @@ -985,34 +985,34 @@ int QuickTricksPartnerHandTrump( } } } - *res = 0; + res = 0; return qt; } int QuickTricksPartnerHandNT( - int hand, - pos * posPoint, - int cutoff, - int depth, - int countLho, - int countRho, - int countOwn, - int countPart, - int suit, - int qtricks, - int commSuit, - int commRank, - int * res, - localVarType * thrp) + const int hand, + pos& tpos, + const int cutoff, + const int depth, + const int countLho, + const int countRho, + const int countOwn, + const int countPart, + const int suit, + const int qtricks, + const int commSuit, + const int commRank, + int& res, + const ThreadData& thrd) { - *res = 1; + res = 1; int qt = qtricks; - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->winner[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.winner[suit].rank]; - posPoint->winRanks[depth][commSuit] |= bitMapRank[commRank]; + tpos.winRanks[depth][commSuit] |= bitMapRank[commRank]; qt++; if (qt >= cutoff) @@ -1022,15 +1022,15 @@ int QuickTricksPartnerHandNT( qt += countPart - 1; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } - if (posPoint->secondBest[suit].hand == partner[hand]) + if (tpos.secondBest[suit].hand == partner[hand]) { /* Second best found in partners hand */ - posPoint->winRanks[depth][suit] |= - bitMapRank[posPoint->secondBest[suit].rank]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; qt++; if (qt >= cutoff) @@ -1040,17 +1040,17 @@ int QuickTricksPartnerHandNT( qt += countPart - 2; if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } - else if ((posPoint->secondBest[suit].hand == hand) + else if ((tpos.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]; + tpos.winRanks[depth][suit] |= + bitMapRank[tpos.secondBest[suit].rank]; qt++; if (qt >= cutoff) @@ -1059,58 +1059,60 @@ int QuickTricksPartnerHandNT( (countRho <= 2) && ((countOwn <= 2) || (countPart <= 2))) { - qt += Max(countPart - 2, countOwn - 2); + qt += max(countPart - 2, countOwn - 2); if (qt >= cutoff) return qt; - *res = 2; + res = 2; return qt; } } else if ((suit == commSuit) && - (posPoint->secondBest[suit].hand == lho[hand])) + (tpos.secondBest[suit].hand == lho[hand])) { unsigned short ranks = 0; for (int h = 0; h < DDS_HANDS; h++) - ranks |= posPoint->rankInSuit[h][suit]; + ranks |= tpos.rankInSuit[h][suit]; - if (thrp->rel[ranks].absRank[3][suit].hand == partner[hand]) + if (thrd.rel[ranks].absRank[3][suit].hand == partner[hand]) { - posPoint->winRanks[depth][suit] |= bitMapRank[ - static_cast(thrp->rel[ranks].absRank[3][suit].rank) ]; + tpos.winRanks[depth][suit] |= bitMapRank[ + static_cast(thrd.rel[ranks].absRank[3][suit].rank) ]; qt++; if (qt >= cutoff) return qt; if ((countOwn <= 2) && (countLho <= 2) && (countRho <= 2)) { - qtricks += countPart - 2; + // TODO: Is the fix to qt correct? + // qtricks += countPart - 2; + qt += countPart - 2; if (qt >= cutoff) return qt; } } } - *res = 0; + res = 0; return qt; } bool QuickTricksSecondHand( - pos * posPoint, - int hand, - int depth, - int target, - int trump, - localVarType * thrp) + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd) { - if (depth == thrp->iniDepth) + if (depth == thrd.iniDepth) return false; - int ss = posPoint->move[depth + 1].suit; - unsigned short (*ris)[DDS_SUITS] = posPoint->rankInSuit; + int ss = tpos.move[depth + 1].suit; + unsigned short (*ris)[DDS_SUITS] = tpos.rankInSuit; unsigned short ranks = static_cast (ris[hand][ss] | ris[partner[hand]][ss]); for (int s = 0; s < DDS_SUITS; s++) - posPoint->winRanks[depth][s] = 0; + tpos.winRanks[depth][s] = 0; if ((trump != DDS_NOTRUMP) && (ss != trump) && (((ris[hand][ss] == 0) && (ris[hand][trump] != 0)) || @@ -1124,7 +1126,7 @@ bool QuickTricksSecondHand( /* Own side can ruff, their side can't. */ } - else if (ranks > (bitMapRank[posPoint->move[depth + 1].rank] | + else if (ranks > (bitMapRank[tpos.move[depth + 1].rank] | ris[lho[hand]][ss])) { if ((trump != DDS_NOTRUMP) && (ss != trump) && @@ -1135,7 +1137,7 @@ bool QuickTricksSecondHand( /* Own side has highest card in suit, which LHO can't ruff. */ int rr = highestRank[ranks]; - posPoint->winRanks[depth][ss] = bitMapRank[rr]; + tpos.winRanks[depth][ss] = bitMapRank[rr]; } else { @@ -1146,10 +1148,10 @@ bool QuickTricksSecondHand( int qtricks = 1; int cutoff; - if (thrp->nodeTypeStore[hand] == MAXNODE) - cutoff = target - posPoint->tricksMAX; + if (thrd.nodeTypeStore[hand] == MAXNODE) + cutoff = target - tpos.tricksMAX; else - cutoff = posPoint->tricksMAX - target + (depth >> 2) + 3; + cutoff = tpos.tricksMAX - target + (depth >> 2) + 3; if (qtricks >= cutoff) return true; @@ -1165,13 +1167,13 @@ bool QuickTricksSecondHand( else hh = partner[hand]; - if ((posPoint->winner[ss].hand == hh) && - (posPoint->secondBest[ss].rank != 0) && - (posPoint->secondBest[ss].hand == hh)) + if ((tpos.winner[ss].hand == hh) && + (tpos.secondBest[ss].rank != 0) && + (tpos.secondBest[ss].hand == hh)) { qtricks++; - posPoint->winRanks[depth][ss] |= - bitMapRank[posPoint->secondBest[ss].rank]; + tpos.winRanks[depth][ss] |= + bitMapRank[tpos.secondBest[ss].rank]; if (qtricks >= cutoff) return true; @@ -1179,25 +1181,25 @@ bool QuickTricksSecondHand( for (int s = 0; s < DDS_SUITS; s++) { - if ((s == ss) || (posPoint->length[hh][s] == 0)) + if ((s == ss) || (tpos.length[hh][s] == 0)) continue; - if ((posPoint->length[lho[hh]][s] == 0) && - (posPoint->length[rho[hh]][s] == 0) && - (posPoint->length[partner[hh]][s] == 0)) + if ((tpos.length[lho[hh]][s] == 0) && + (tpos.length[rho[hh]][s] == 0) && + (tpos.length[partner[hh]][s] == 0)) { /* Long other suit which nobody else holds. */ qtricks += counttable[ris[hh][s]]; if (qtricks >= cutoff) return true; } - else if ((posPoint->winner[s].rank != 0) && - (posPoint->winner[s].hand == hh)) + else if ((tpos.winner[s].rank != 0) && + (tpos.winner[s].hand == hh)) { /* Top winners in other suits. */ qtricks++; - posPoint->winRanks[depth][s] |= - bitMapRank[posPoint->winner[s].rank]; + tpos.winRanks[depth][s] |= + bitMapRank[tpos.winner[s].rank]; if (qtricks >= cutoff) return true; diff --git a/src/QuickTricks.h b/src/QuickTricks.h index bd78d328..4aac0022 100644 --- a/src/QuickTricks.h +++ b/src/QuickTricks.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,22 +10,25 @@ #ifndef DDS_QUICKTRICKS_H #define DDS_QUICKTRICKS_H +#include "dds.h" +#include "Memory.h" + int QuickTricks( - struct pos * posPoint, - int hand, - int depth, - int target, - int trump, - bool * result, - struct localVarType * thrp); + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + bool& result, + const ThreadData& thrd); bool QuickTricksSecondHand( - struct pos * posPoint, - int hand, - int depth, - int target, - int trump, - struct localVarType * thrp); + pos& tpos, + const int hand, + const int depth, + const int target, + const int trump, + const ThreadData& thrd); #endif diff --git a/src/Scheduler.cpp b/src/Scheduler.cpp index 1e050bc1..b3d58b41 100644 --- a/src/Scheduler.cpp +++ b/src/Scheduler.cpp @@ -2,132 +2,82 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ +#include +#include +#include +#include + #include "Scheduler.h" Scheduler::Scheduler() { - // This can be HCP, for instance. Currently it is close to - // 6 - 4 - 2 - 1 - 0.5 for A-K-Q-J-T, but with 6.5 for the ace - // in order to make the sum come out to 28, an even number, so - // that the average number is an integer. - - for (int i = 0; i < 8192; i++) - { - highCards[i] = 0; - - if (i & (1 << 12)) highCards[i] += 13; - if (i & (1 << 11)) highCards[i] += 8; - if (i & (1 << 10)) highCards[i] += 4; - if (i & (1 << 9)) highCards[i] += 2; - if (i & (1 << 8)) highCards[i] += 1; - } - + numThreads = 0; numHands = 0; + Scheduler::InitHighCards(); + #ifdef DDS_SCHEDULER Scheduler::InitTimes(); - for (int i = 0; i < 10000; i++) { timeHist[i] = 0; timeHistNT[i] = 0; timeHistSuit[i] = 0; } - - sprintf(fname, ""); - fp = stdout; #endif -#if defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - omp_init_lock(&lock); -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - lock = dispatch_semaphore_create(1); -#endif + Scheduler::RegisterThreads(1); } -void Scheduler::SetFile(char * ourFname) +void Scheduler::InitHighCards() { -#ifdef DDS_SCHEDULER - if (strlen(ourFname) > 80) - return; + // highCards[i] is a point value of a given suit holding i. + // This can be HCP, for instance. Currently it is close to + // 6 - 4 - 2 - 1 - 0.5 for A-K-Q-J-T, but with 6.5 for the ace + // in order to make the sum come out to 28, an even number, so + // that the average number is an integer. - if (fp != stdout) // Already set - return; - strncpy(fname, ourFname, strlen(ourFname)); + highCards.resize(1 << 13); + const unsigned pA = 1 << 12; + const unsigned pK = 1 << 11; + const unsigned pQ = 1 << 10; + const unsigned pJ = 1 << 9; + const unsigned pT = 1 << 8; - fp = fopen(fname, "w"); - if (! fp) - fp = stdout; -#else - UNUSED(ourFname); -#endif + for (unsigned suit = 0; suit < (1 << 13); suit++) + { + int j = 0; + if (suit & pA) j += 13; + if (suit & pK) j += 8; + if (suit & pQ) j += 4; + if (suit & pJ) j += 2; + if (suit & pT) j += 1; + highCards[suit] = j; + } } #ifdef DDS_SCHEDULER void Scheduler::InitTimes() { - for (int s = 0; s < 2; s++) - { - timeStrain[s].cum = 0; - timeStrain[s].cumsq = 0; - timeStrain[s].number = 0; - - timeGroupActualStrain[s].cum = 0; - timeGroupActualStrain[s].cumsq = 0; - timeGroupActualStrain[s].number = 0; + timeStrain.Init("Suit/NT", 2); + timeRepeat.Init("Repeat number", 16); + timeDepth.Init("Trace depth", 60); + timeStrength.Init("Evenness", 60); + timeFanout.Init("Fanout", 100); + timeThread.Init("Threads", numThreads); - timeGroupPredStrain[s].cum = 0; - timeGroupPredStrain[s].cumsq = 0; - timeGroupPredStrain[s].number = 0; - - timeGroupDiffStrain[s].cum = 0; - timeGroupDiffStrain[s].cumsq = 0; - timeGroupDiffStrain[s].number = 0; - } - - for (int s = 0; s < 16; s++) - { - timeRepeat[s].cum = 0; - timeRepeat[s].cumsq = 0; - timeRepeat[s].number = 0; - } - - for (int s = 0; s < 60; s++) - { - timeDepth[s].cum = 0; - timeDepth[s].cumsq = 0; - timeDepth[s].number = 0; - } - - for (int s = 0; s < 60; s++) - { - timeStrength[s].cum = 0; - timeStrength[s].cumsq = 0; - timeStrength[s].number = 0; - } - - for (int s = 0; s < 100; s++) - { - timeFanout[s].cum = 0; - timeFanout[s].cumsq = 0; - timeFanout[s].number = 0; - } - - for (int s = 0; s < MAXNOOFTHREADS; s++) - { - timeThread[s].cum = 0; - timeThread[s].cumsq = 0; - timeThread[s].number = 0; - } + timeGroupActualStrain.Init("Group actual suit/NT", 2); + timeGroupPredStrain.Init("Group predicted suit/NT", 2); + timeGroupDiffStrain.Init("Group diff suit/NT", 2); blockMax = 0; timeBlock = 0; @@ -137,16 +87,6 @@ void Scheduler::InitTimes() Scheduler::~Scheduler() { -#ifdef DDS_SCHEDULER - if (fp != stdout && fp != nullptr) - fclose(fp); -#endif - -#if defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - omp_destroy_lock(&lock); -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - dispatch_release(lock); -#endif } @@ -163,8 +103,7 @@ void Scheduler::Reset() for (int key = 0; key < HASH_MAX; key++) list[strain][key].first = -1; - - for (int t = 0; t < MAXNOOFTHREADS; t++) + for (unsigned t = 0; t < static_cast(numThreads); t++) { threadGroup[t] = -1; threadCurrGroup[t] = -1; @@ -174,60 +113,80 @@ void Scheduler::Reset() } -void Scheduler::RegisterTraceDepth( - playTracesBin * plp, - int number) +void Scheduler::RegisterThreads( + const int n) { - // This is only used for traces, so it is entered separately. + if (n == numThreads) + return; + numThreads = n; + + const unsigned nu = static_cast(n); + threadGroup.resize(nu); + threadCurrGroup.resize(nu); + threadToHand.resize(nu); #ifdef DDS_SCHEDULER - for (int b = 0; b < number; b++) - hands[b].depth = plp->plays[b].number; -#else - UNUSED(plp); - UNUSED(number); + timeThread.Init("Threads", numThreads); + timersThread.resize(numThreads); #endif } -void Scheduler::Register( - boards * bop, - int sortMode) +void Scheduler::RegisterRun( + const enum RunMode mode, + const boards& bds, + const playTracesBin& pl) +{ + for (int b = 0; b < bds.noOfBoards; b++) + hands[b].depth = pl.plays[b].number; + + Scheduler::RegisterRun(mode, bds); +} + + +void Scheduler::RegisterRun( + const enum RunMode mode, + const boards& bds) { Scheduler::Reset(); - numHands = bop->noOfBoards; + numHands = bds.noOfBoards; // First split the hands according to strain and hash key. // This will lead to a few random collisions as well. - Scheduler::MakeGroups(bop); + Scheduler::MakeGroups(bds); // Then check whether groups with at least two elements are // homogeneous or whether they need to be split. Scheduler::FinetuneGroups(); + Scheduler::SortHands(mode); +} + + +void Scheduler::SortHands(const enum RunMode mode) +{ // Make predictions per group. - if (sortMode == SCHEDULER_SOLVE) + if (mode == DDS_RUN_SOLVE) Scheduler::SortSolve(); - else if (sortMode == SCHEDULER_CALC) + else if (mode == DDS_RUN_CALC) Scheduler::SortCalc(); - else if (sortMode == SCHEDULER_TRACE) + else if (mode == DDS_RUN_TRACE) Scheduler::SortTrace(); } -void Scheduler::MakeGroups( - boards * bop) +void Scheduler::MakeGroups(const boards& bds) { - deal * dl; + deal const * dl; listType * lp; for (int b = 0; b < numHands; b++) { - dl = &bop->deals[b]; + dl = &bds.deals[b]; int strain = dl->trump; @@ -252,8 +211,8 @@ void Scheduler::MakeGroups( hands[b].NTflag = (strain == 4 ? 1 : 0); hands[b].first = dl->first; hands[b].strain = strain; - hands[b].fanout = Scheduler::Fanout(dl); - // hands[b].strength = Scheduler::Strength(dl); + hands[b].fanout = Scheduler::Fanout(* dl); + // hands[b].strength = Scheduler::Strength(* dl); lp = &list[strain][key]; @@ -433,8 +392,8 @@ void Scheduler::FinetuneGroups() bool Scheduler::SameHand( - int hno1, - int hno2) + const int hno1, + const int hno2) const { for (int h = 0; h < DDS_HANDS; h++) for (int s = 0; s < DDS_SUITS; s++) @@ -704,26 +663,25 @@ void Scheduler::SortTrace() } -int Scheduler::Strength( - deal * dl) +int Scheduler::Strength(const deal& dl) const { // If the strength in all suits is evenly split, then the // "strength" returned is close to 0. Maximum is 49. - unsigned sp = (dl->remainCards[0][0] | dl->remainCards[2][0]) >> 2; - unsigned he = (dl->remainCards[0][1] | dl->remainCards[2][1]) >> 2; - unsigned di = (dl->remainCards[0][2] | dl->remainCards[2][2]) >> 2; - unsigned cl = (dl->remainCards[0][3] | dl->remainCards[2][3]) >> 2; + const unsigned sp = (dl.remainCards[0][0] | dl.remainCards[2][0]) >> 2; + const unsigned he = (dl.remainCards[0][1] | dl.remainCards[2][1]) >> 2; + const unsigned di = (dl.remainCards[0][2] | dl.remainCards[2][2]) >> 2; + const unsigned cl = (dl.remainCards[0][3] | dl.remainCards[2][3]) >> 2; - int hsp = highCards[sp]; - int hhe = highCards[he]; - int hdi = highCards[di]; - int hcl = highCards[cl]; + const int hsp = highCards[sp]; + const int hhe = highCards[he]; + const int hdi = highCards[di]; + const int hcl = highCards[cl]; int dev = (hsp >= 14 ? hsp - 14 : 14 - hsp) + - (hhe >= 14 ? hhe - 14 : 14 - hhe) + - (hdi >= 14 ? hdi - 14 : 14 - hdi) + - (hcl >= 14 ? hcl - 14 : 14 - hcl); + (hhe >= 14 ? hhe - 14 : 14 - hhe) + + (hdi >= 14 ? hdi - 14 : 14 - hdi) + + (hcl >= 14 ? hcl - 14 : 14 - hcl); if (dev >= 50) dev = 49; @@ -731,8 +689,7 @@ int Scheduler::Strength( } -int Scheduler::Fanout( - deal * dl) +int Scheduler::Fanout(const deal& dl) const { // The fanout for a given suit and a given player is the number // of bit groups, so KT982 has 3 groups. In a given suit the @@ -748,7 +705,7 @@ int Scheduler::Fanout( numVoids = 0; for (int s = 0; s < DDS_SUITS; s++) { - c = static_cast(dl->remainCards[h][s] >> 2); + c = static_cast(dl.remainCards[h][s] >> 2); fanoutSuit += groupData[c].lastGroup + 1; if (c == 0) numVoids++; @@ -761,10 +718,10 @@ int Scheduler::Fanout( } -schedType Scheduler::GetNumber( - int thrId) +schedType Scheduler::GetNumber(const int thrId) { - int g = threadGroup[thrId]; + const unsigned tu = static_cast(thrId); + int g = threadGroup[tu]; listType * lp; schedType st; @@ -780,20 +737,8 @@ schedType Scheduler::GetNumber( return st; } -#if (defined(_WIN32) || defined(__CYGWIN__)) && \ - !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - g = InterlockedIncrement(&currGroup); -#elif defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - omp_set_lock(&lock); - g = ++currGroup; - omp_unset_lock(&lock); -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); + // Atomic. g = ++currGroup; - dispatch_semaphore_signal(lock); -#else - g = ++currGroup; -#endif if (g >= numGroups) { @@ -807,8 +752,8 @@ schedType Scheduler::GetNumber( // A bit inelegant to duplicate this, but seems better than // the alternative, as threadGroup must get set to -1 in some // cases. - threadGroup[thrId] = g; - threadCurrGroup[thrId] = g; + threadGroup[tu] = g; + threadCurrGroup[tu] = g; group[g].repeatNo = 0; group[g].actual = 0; } @@ -846,36 +791,33 @@ schedType Scheduler::GetNumber( hands[st.number].repeatNo = group[g].repeatNo++; - threadToHand[thrId] = st.number; + threadToHand[tu] = st.number; if (lp->first == -1) - threadGroup[thrId] = -1; + threadGroup[tu] = -1; return st; } +int Scheduler::NumGroups() const +{ + return numGroups; +} + + #ifdef DDS_SCHEDULER -void Scheduler::StartThreadTimer(int thrId) +void Scheduler::StartThreadTimer(const int thrId) { -#ifdef _WIN32 - QueryPerformanceCounter(&timeStart[thrId]); -#else - gettimeofday(&timeStart[thrId], NULL); -#endif + timersThread[thrId].Reset(); + timersThread[thrId].Start(); } -void Scheduler::EndThreadTimer(int thrId) +void Scheduler::EndThreadTimer(const int thrId) { -#ifdef _WIN32 - QueryPerformanceCounter(&timeEnd[thrId]); - int timeUser = (timeEnd [thrId].QuadPart - - timeStart[thrId].QuadPart); -#else - gettimeofday(&timerListUser1[no], NULL); - int timeUser = Scheduler::timeDiff(timeEnd[thrId], timeStart[thrId]); -#endif + timersThread[thrId].End(); + int timeUser = timersThread[thrId].UserTime(); hands[ threadToHand[thrId] ].time = timeUser; hands[ threadToHand[thrId] ].thread = thrId; @@ -886,24 +828,15 @@ void Scheduler::EndThreadTimer(int thrId) void Scheduler::StartBlockTimer() { -#ifdef _WIN32 - QueryPerformanceCounter(&blockStart); -#else - gettimeofday(&blockStart, NULL); -#endif + timerBlock.Reset(); + timerBlock.Start(); } void Scheduler::EndBlockTimer() { -#ifdef _WIN32 - QueryPerformanceCounter(&blockEnd); - int timeUser = (blockEnd .QuadPart - - blockStart.QuadPart); -#else - gettimeofday(&blockEnd, NULL); - int timeUser = Scheduler::timeDiff(blockEnd, blockStart); -#endif + timerBlock.End(); + const int timeUserBlock = timerBlock.UserTime(); handType * hp; for (int b = 0; b < numHands; b++) @@ -914,29 +847,15 @@ void Scheduler::EndBlockTimer() if (hp->selectFlag) { - timeStrain [ hp->NTflag ].number++; - timeStrain [ hp->NTflag ].cum += timeUser; - timeStrain [ hp->NTflag ].cumsq += timesq; - - timeRepeat [ hp->repeatNo ].number++; - timeRepeat [ hp->repeatNo ].cum += timeUser; - timeRepeat [ hp->repeatNo ].cumsq += timesq; - - timeDepth [ hp->depth ].number++; - timeDepth [ hp->depth ].cum += timeUser; - timeDepth [ hp->depth ].cumsq += timesq; - - timeStrength[ hp->strength ].number++; - timeStrength[ hp->strength ].cum += timeUser; - timeStrength[ hp->strength ].cumsq += timesq; - - timeFanout [ hp->fanout ].number++; - timeFanout [ hp->fanout ].cum += timeUser; - timeFanout [ hp->fanout ].cumsq += timesq; - - timeThread [ hp->thread ].number++; - timeThread [ hp->thread ].cum += timeUser; - timeThread [ hp->thread ].cumsq += timesq; + TimeStat ts; + ts.Set(timeUser, timesq); + + timeStrain.Add(hp->NTflag, ts); + timeRepeat.Add(hp->repeatNo, ts); + timeDepth.Add(hp->depth, ts); + timeStrength.Add(hp->strength, ts); + timeFanout.Add(hp->fanout, ts); + timeThread.Add(hp->thread, ts); } if (timeUser > blockMax) @@ -958,138 +877,79 @@ void Scheduler::EndBlockTimer() int head = group[g].head; int NTflag = (hands[head].strain == 4 ? 1 : 0); - timeGroupActualStrain[NTflag].number++; - timeGroupActualStrain[NTflag].cum += group[g].actual; - timeGroupActualStrain[NTflag].cumsq += - (double) group[g].actual * (double) group[g].actual; + TimeStat ts; - timeGroupPredStrain [NTflag].number++; - timeGroupPredStrain [NTflag].cum += group[g].pred; - timeGroupPredStrain [NTflag].cumsq += - group[g].pred * group[g].pred; + ts.Set(group[g].actual); + timeGroupActualStrain.Add(NTflag, ts); - double diff = group[g].actual - group[g].pred; + ts.Set(group[g].pred); + timeGroupPredStrain.Add(NTflag, ts); - timeGroupDiffStrain [NTflag].number++; - timeGroupDiffStrain [NTflag].cum += diff; - timeGroupDiffStrain [NTflag].cumsq += diff * diff; + int diff = group[g].actual - group[g].pred; + ts.Set(diff); + timeGroupDiffStrain.Add(NTflag, ts); } - timeBlock += timeUser; + + timeBlock += timeUserBlock; timeMax += blockMax; blockMax = 0; } -void Scheduler::PrintTimingList( - timeType * tp, - int length, - const char title[]) -{ - bool empty = true; - for (int no = 0; no < length && empty; no++) - { - if (tp[no].number) - empty = false; - } - if (empty) - return; - - fprintf(fp, "%s\n\n", title); - fprintf(fp, "%5s %8s %12s %12s %12s %12s\n", - "n", "Number", "Cum time", "Average", "Sdev", "Sdev/mu"); - - long long sn = 0, st = 0; - double sq = 0; - - for (int no = 0; no < length; no++) - { - if (tp[no].number == 0) - continue; - - sn += tp[no].number; - st += tp[no].cum; - sq += tp[no].cumsq; - - double avg = (double) tp[no].cum / (double) tp[no].number; - double arg = (tp[no].cumsq / (double) tp[no].number) - - (double) avg * (double) avg; - double sdev = (arg >= 0. ? sqrt(arg) : 0.); - - fprintf(fp, "%5d %8d %12lld ", - no, - tp[no].number, - tp[no].cum); - fprintf(fp, "%12.0f %12.0f %12.2f\n", avg, sdev, sdev / avg); - } - - if (sn) - { - double avg = (double) st / (double) sn; - double arg = (sq / (double) sn) - (double) avg * (double) avg; - double sdev = (arg >= 0. ? sqrt(arg) : 0.); - fprintf(fp, " Avg %8lld %12lld ", sn, st); - fprintf(fp, "%12.0f %12.0f %12.2f\n", avg, sdev, sdev / avg); - } - - fprintf(fp, "\n"); -} - - -void Scheduler::PrintTiming() +void Scheduler::PrintTiming() const { - Scheduler::PrintTimingList(timeStrain , 2, "Suit/NT"); - Scheduler::PrintTimingList(timeRepeat , 16, "Repeat number"); - Scheduler::PrintTimingList(timeDepth , 60, "Trace depth"); - Scheduler::PrintTimingList(timeStrength, 60, "Evenness"); - Scheduler::PrintTimingList(timeFanout , 100, "Fanout"); - Scheduler::PrintTimingList(timeThread , MAXNOOFTHREADS, "Threads"); - - Scheduler::PrintTimingList(timeGroupActualStrain, 2, - "Group actual suit/NT"); - Scheduler::PrintTimingList(timeGroupPredStrain , 2, - "Group predicted suit/NT"); - Scheduler::PrintTimingList(timeGroupDiffStrain , 2, - "Group diff suit/NT"); + const string fname = string(DDS_SCHEDULER_PREFIX) + DDS_DEBUG_SUFFIX; + ofstream fout; + fout.open(fname); + + fout << timeStrain.List(); + fout << timeRepeat.List(); + fout << timeDepth.List(); + fout << timeStrength.List(); + fout << timeFanout.List(); + fout << timeThread.List(); + fout << timeGroupActualStrain.List(); + fout << timeGroupPredStrain.List(); + fout << timeGroupDiffStrain.List(); #if 0 + fout << setw(13) << "Hist" << + setw(10) << "Hist suit" << + setw(10) << "Hist NT" << "\n"; for (int i = 0; i < 10000; i++) + { if (timeHist[i] || timeHistSuit[i] || timeHistNT[i]) - fprintf(fp, "%4d %8d %8d %8d\n", - i, timeHist[i], timeHistSuit[i], timeHistNT[i]); - fprintf(fp, "\n"); + { + fout << setw(4) << i << + setw(9) << timeHist[i] << + setw(10) << timeHistSuit[i] << + setw(10) << timeHistNT[i] << "\n"; + } + } + fout << endl; #endif if (timeBlock == 0) return; - // Continuing problems with ld in long fprintf's... - double avg = 100. * (double) timeMax / (double) timeBlock; - fprintf(fp, "Largest hand %12lld ", timeMax); - fprintf(fp, "%12lld ", timeBlock); - fprintf(fp, "%5.2f%%\n\n", avg); -} - + const double avg = 100. * (double) timeMax / (double) timeBlock; + fout << "Largest hand" << + setw(13) << timeMax << + setw(13) << timeBlock << + setw(6) << setprecision(2) << fixed << avg << "%\n\n"; -#ifndef _WIN32 -int Scheduler::timeDiff( - timeval x, - timeval y) -{ - /* Elapsed time, x-y, in milliseconds */ - return 1000 * (x.tv_sec - y.tv_sec ) - + (x.tv_usec - y.tv_usec) / 1000; + fout.close(); } -#endif #endif // DDS_SCHEDULER int Scheduler::PredictedTime( - deal * dl, - int number) + deal& dl, + int number) const { - int trump = dl->trump; + int trump = dl.trump; int NT = (trump == 4 ? 100 : 0); int dev1 = Scheduler::Strength(dl); @@ -1124,4 +984,3 @@ int Scheduler::PredictedTime( return pred; } - diff --git a/src/Scheduler.h b/src/Scheduler.h index df4a6cb1..606f9953 100644 --- a/src/Scheduler.h +++ b/src/Scheduler.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,27 +10,26 @@ #ifndef DDS_SCHEDULER_H #define DDS_SCHEDULER_H -#include -#include -#include -#include -#include "dds.h" -#include "../include/dll.h" +#include -#ifndef _WIN32 - #include -#endif +#include "dds.h" +#include "TimeStatList.h" +#include "Timer.h" -#define SCHEDULER_NOSORT 0 -#define SCHEDULER_SOLVE 1 -#define SCHEDULER_CALC 2 -#define SCHEDULER_TRACE 3 +using namespace std; #define HASH_MAX 200 - -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDDS_THREADS_SINGLE) - #include +#ifdef DDS_SCHEDULER + #define START_BLOCK_TIMER scheduler.StartBlockTimer() + #define END_BLOCK_TIMER scheduler.EndBlockTimer() + #define START_THREAD_TIMER(a) scheduler.StartThreadTimer(a) + #define END_THREAD_TIMER(a) scheduler.EndThreadTimer(a) +#else + #define START_BLOCK_TIMER 1 + #define END_BLOCK_TIMER 1 + #define START_THREAD_TIMER(a) 1 + #define END_THREAD_TIMER(a) 1 #endif @@ -45,12 +44,6 @@ class Scheduler { private: -#if defined(_OPENMP) && !defined(DDDS_THREADS_SINGLE) - omp_lock_t lock; -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDDS_THREADS_SINGLE) - dispatch_semaphore_t lock; -#endif - struct listType { int first; @@ -96,105 +89,73 @@ class Scheduler groupType group[MAXNOOFBOARDS]; int numGroups; int extraGroups; -#ifdef _WIN32 - LONG volatile currGroup; -#else - int volatile currGroup; -#endif + + atomic currGroup; listType list[DDS_SUITS + 2][HASH_MAX]; sortType sortList[MAXNOOFBOARDS]; int sortLen; - int threadGroup[MAXNOOFTHREADS]; - int threadCurrGroup[MAXNOOFTHREADS]; - - int threadToHand[MAXNOOFTHREADS]; + vector threadGroup; + vector threadCurrGroup; + vector threadToHand; + int numThreads; int numHands; - int highCards[8192]; + vector highCards; - int Strength( - deal * dl); + void InitHighCards(); - int Fanout( - deal * dl); + void SortHands(const enum RunMode mode); + + int Strength(const deal& dl) const; + int Fanout(const deal& dl) const; void Reset(); -#ifdef _WIN32 - LARGE_INTEGER timeStart[MAXNOOFTHREADS]; - LARGE_INTEGER timeEnd[MAXNOOFTHREADS]; - LARGE_INTEGER blockStart; - LARGE_INTEGER blockEnd; -#else - int timeDiff( - timeval x, - timeval y); - - timeval startTime[MAXNOOFTHREADS]; - timeval endTime[MAXNOOFTHREADS]; - timeval blockStart; - timeval blockEnd; -#endif + vector timersThread; + Timer timerBlock; - void MakeGroups( - boards * bop); + void MakeGroups(const boards& bds); void FinetuneGroups(); bool SameHand( - int hno1, - int hno2); + const int hno1, + const int hno2) const; void SortSolve(), SortCalc(), SortTrace(); #ifdef DDS_SCHEDULER - FILE * fp; - - char fname[80]; int timeHist[10000]; int timeHistNT[10000]; int timeHistSuit[10000]; - struct timeType - { - long long cum; - double cumsq; - int number; - }; - - timeType timeStrain[2]; - timeType timeRepeat[16]; - timeType timeDepth[60]; - timeType timeStrength[60]; - timeType timeFanout[100]; - timeType timeThread[MAXNOOFTHREADS]; + TimeStatList timeStrain; + TimeStatList timeRepeat; + TimeStatList timeDepth; + TimeStatList timeStrength; + TimeStatList timeFanout; + TimeStatList timeThread; + TimeStatList timeGroupActualStrain; + TimeStatList timeGroupPredStrain; + TimeStatList timeGroupDiffStrain; long long timeMax; long long blockMax; long long timeBlock; - timeType timeGroupActualStrain[2]; - timeType timeGroupPredStrain[2]; - timeType timeGroupDiffStrain[2]; - void InitTimes(); - - void PrintTimingList( - timeType * tp, - int length, - const char title[]); #endif int PredictedTime( - deal * dl, - int number); + deal& dl, + int number) const; public: @@ -203,31 +164,32 @@ class Scheduler ~Scheduler(); - void SetFile(char * fname); + void RegisterThreads( + const int n); + + void RegisterRun( + const enum RunMode mode, + const boards& bds, + const playTracesBin& pl); - void RegisterTraceDepth( - playTracesBin * plp, - int number); + void RegisterRun( + const enum RunMode mode, + const boards& bds); - void Register( - boards * bop, - int sortMode); + schedType GetNumber(const int thrId); - schedType GetNumber( - int thrId); + int NumGroups() const; #ifdef DDS_SCHEDULER - void StartThreadTimer( - int thrId); + void StartThreadTimer(const int thrId); - void EndThreadTimer( - int thrId); + void EndThreadTimer(const int thrId); void StartBlockTimer(); void EndBlockTimer(); - void PrintTiming(); + void PrintTiming() const; #endif }; diff --git a/src/SolveBoard.cpp b/src/SolveBoard.cpp index b62c4e00..0a60ed8f 100644 --- a/src/SolveBoard.cpp +++ b/src/SolveBoard.cpp @@ -2,614 +2,149 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include "dds.h" -#include "threadmem.h" #include "SolverIF.h" #include "SolveBoard.h" +#include "System.h" +#include "Memory.h" #include "Scheduler.h" #include "PBN.h" #include "debug.h" -#ifdef DDS_SCHEDULER - #define START_BLOCK_TIMER scheduler.StartBlockTimer() - #define END_BLOCK_TIMER scheduler.EndBlockTimer() - #define START_THREAD_TIMER(a) scheduler.StartThreadTimer(a) - #define END_THREAD_TIMER(a) scheduler.EndThreadTimer(a) -#else - #define START_BLOCK_TIMER 1 - #define END_BLOCK_TIMER 1 - #define START_THREAD_TIMER(a) 1 - #define END_THREAD_TIMER(a) 1 -#endif - -extern int noOfThreads; -#if (defined(_WIN32) || defined(__CYGWIN__)) && \ - !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) -HANDLE solveAllEvents[MAXNOOFTHREADS]; paramType param; -LONG volatile threadIndex; -LONG volatile current; -long chunk; +extern System sysdep; +extern Memory memory; +extern Scheduler scheduler; -DWORD CALLBACK SolveChunk (void *); -DWORD CALLBACK SolveChunkDDtable (void *); +int SolveAllBoardsN( + boards& bds, + solvedBoards& solved); -DWORD CALLBACK SolveChunk (void *) -{ - futureTricks fut[MAXNOOFBOARDS]; - int thid; +bool SameBoard( + const boards& bds, + const unsigned index1, + const unsigned index2); - thid = InterlockedIncrement(&threadIndex); - int index; - schedType st; - while (1) - { - st = scheduler.GetNumber(thid); - index = st.number; - if (index == -1) - break; +void SolveSingleCommon( + const int thrId, + const int bno) +{ + futureTricks fut; + + START_THREAD_TIMER(thrId); + int res = SolveBoard( + param.bop->deals[bno], + param.bop->target[bno], + param.bop->solutions[bno], + param.bop->mode[bno], + &fut, + thrId); + END_THREAD_TIMER(thrId); + + if (res == 1) + param.solvedp->solvedBoard[bno] = fut; + else + param.error = res; +} - // This is not a perfect repeat detector, as the hands in - // a group might have declarers N, S, N, N. Then the second - // N would not reuse the first N. However, must reuses are - // reasonably adjacent, and this is just an optimization anyway. - if (st.repeatOf != -1 && - param.bop->deals[index ].first == - param.bop->deals[st.repeatOf].first) - { - START_THREAD_TIMER(thid); - param.solvedp->solvedBoard[index] = fut[ st.repeatOf ]; - END_THREAD_TIMER(thid); +void CopySolveSingle(const vector& crossrefs) +{ + for (unsigned i = 0; i < crossrefs.size(); i++) + { + if (crossrefs[i] == -1) continue; - } - else - { - START_THREAD_TIMER(thid); - int res = SolveBoard( - param.bop->deals[index], - param.bop->target[index], - param.bop->solutions[index], - param.bop->mode[index], - &fut[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - param.solvedp->solvedBoard[index] = fut[index]; - else - param.error = res; - } - } - - if (SetEvent(solveAllEvents[thid]) == 0) - return 0; - - return 1; + START_THREAD_TIMER(thrId); + param.solvedp->solvedBoard[i] = + param.solvedp->solvedBoard[crossrefs[i]]; + END_THREAD_TIMER(thrId); + } } -DWORD CALLBACK SolveChunkDDtable (void *) +void SolveChunkCommon( + const int thrId) { - futureTricks fut[MAXNOOFBOARDS]; - int thid; - - thid = InterlockedIncrement(&threadIndex); - int index; schedType st; while (1) { - st = scheduler.GetNumber(thid); + st = scheduler.GetNumber(thrId); index = st.number; if (index == -1) break; - if (st.repeatOf != -1) + // This is not a perfect repeat detector, as the hands in + // a group might have declarers N, S, N, N. Then the second + // N would not reuse the first N. However, must reuses are + // reasonably adjacent, and this is just an optimization anyway. + + if (st.repeatOf != -1 && + param.bop->deals[index ].first == + param.bop->deals[st.repeatOf].first) { - START_THREAD_TIMER(thid); - for (int k = 0; k < chunk; k++) - { - param.bop->deals[index].first = k; - - param.solvedp->solvedBoard[index].score[k] = - param.solvedp->solvedBoard[ st.repeatOf ].score[k]; - } - END_THREAD_TIMER(thid); + START_THREAD_TIMER(thrId); + param.solvedp->solvedBoard[index] = + param.solvedp->solvedBoard[st.repeatOf]; + END_THREAD_TIMER(thrId); continue; } - - param.bop->deals[index].first = 0; - - START_THREAD_TIMER(thid); - int res = SolveBoard( - param.bop->deals[index], - param.bop->target[index], - param.bop->solutions[index], - param.bop->mode[index], - &fut[index], - thid); - - // SH: I'm making a terrible use of the fut structure here. - - if (res == 1) - param.solvedp->solvedBoard[index].score[0] = fut[index].score[0]; else - param.error = res; - - for (int k = 1; k < chunk; k++) { - int hint = (k == 2 ? fut[index].score[0] : - 13 - fut[index].score[0]); - - param.bop->deals[index].first = k; // Next declarer - - res = SolveSameBoard( - param.bop->deals[index], - &fut[index], - hint, - thid); - - if (res == 1) - param.solvedp->solvedBoard[index].score[k] = - fut[index].score[0]; - else - param.error = res; + SolveSingleCommon(thrId, index); } - END_THREAD_TIMER(thid); } - - if (SetEvent(solveAllEvents[thid]) == 0) - return 0; - - return 1; } int SolveAllBoardsN( - boards * bop, - solvedBoards * solvedp, - int chunkSize, - int source) // 0 solve, 1 calc + boards& bds, + solvedBoards& solved) { - int k; - int res; - DWORD solveAllWaitResult; - - current = 0; - threadIndex = -1; - chunk = chunkSize; param.error = 0; - if (bop->noOfBoards > MAXNOOFBOARDS) + if (bds.noOfBoards > MAXNOOFBOARDS) return RETURN_TOO_MANY_BOARDS; - for (k = 0; k < noOfThreads; k++) - { - solveAllEvents[k] = CreateEvent(NULL, FALSE, FALSE, 0); - if (solveAllEvents[k] == 0) - return RETURN_THREAD_CREATE; - } + param.bop = &bds; + param.solvedp = &solved; + param.noOfBoards = bds.noOfBoards; - param.bop = bop; - param.solvedp = solvedp; - param.noOfBoards = bop->noOfBoards; - - if (source == 0) - scheduler.Register(bop, SCHEDULER_SOLVE); - else - scheduler.Register(bop, SCHEDULER_CALC); + scheduler.RegisterRun(DDS_RUN_SOLVE, bds); + sysdep.RegisterRun(DDS_RUN_SOLVE, bds); - for (k = 0; k < MAXNOOFBOARDS; k++) - solvedp->solvedBoard[k].cards = 0; - - if (chunkSize != 1) - { - for (k = 0; k < noOfThreads; k++) - { - res = QueueUserWorkItem(SolveChunkDDtable, NULL, - WT_EXECUTELONGFUNCTION); - if (res != 1) - return res; - } - } - else - { - for (k = 0; k < noOfThreads; k++) - { - res = QueueUserWorkItem(SolveChunk, NULL, - WT_EXECUTELONGFUNCTION); - if (res != 1) - return res; - } - } + for (int k = 0; k < MAXNOOFBOARDS; k++) + solved.solvedBoard[k].cards = 0; START_BLOCK_TIMER; - solveAllWaitResult = WaitForMultipleObjects( - static_cast(noOfThreads), - solveAllEvents, TRUE, INFINITE); + int retRun = sysdep.RunThreads(); END_BLOCK_TIMER; - if (solveAllWaitResult != WAIT_OBJECT_0) - return RETURN_THREAD_WAIT; - - for (k = 0; k < noOfThreads; k++) - CloseHandle(solveAllEvents[k]); + if (retRun != RETURN_NO_FAULT) + return retRun; - /* Calculate number of solved boards. */ + solved.noOfBoards = param.noOfBoards; - solvedp->noOfBoards = param.noOfBoards; +#ifdef DDS_SCHEDULER + scheduler.PrintTiming(); +#endif if (param.error == 0) - return 1; + return RETURN_NO_FAULT; else return param.error; } -#elif (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) || defined(__MAC_OS_X_VERSION_MAX_ALLOWED)) && !defined(_OPENMP) && !defined(DDS_THREADS_SINGLE) - -// This code for LLVM multi-threading on the Mac was kindly -/// contributed by Pierre Cossard. - -int SolveAllBoardsN( - boards * bop, - solvedBoards * solvedp, - int chunkSize, - int source) // 0 solve, 1 calc -{ - __block int chunk; - __block int fail; - - chunk = chunkSize; - fail = 1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - futureTricks *fut = static_cast - (calloc(MAXNOOFBOARDS, sizeof(futureTricks))); - - for (int i = 0; i < MAXNOOFBOARDS; i++) - solvedp->solvedBoard[i].cards = 0; - - START_BLOCK_TIMER; - - if (source == 0) - scheduler.Register(bop, SCHEDULER_SOLVE); - else - scheduler.Register(bop, SCHEDULER_CALC); - - if (chunkSize == 1) - { - dispatch_apply(static_cast(noOfThreads), - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), - ^(size_t t) - { - while (1) - { - int thid = static_cast(t); - schedType st = scheduler.GetNumber(thid); - int index = st.number; - if (index == -1) - break; - - // This is not a perfect repeat detector, as the hands in - // a group might have declarers N, S, N, N. Then the second - // N would not reuse the first N. However, most reuses are - // reasonably adjacent, and this is just an optimization anyway. - - if (st.repeatOf != -1 && - (bop->deals[index ].first == - bop->deals[st.repeatOf].first)) - { - START_THREAD_TIMER(thid); - solvedp->solvedBoard[index] = fut[ st.repeatOf ]; - END_THREAD_TIMER(thid); - continue; - } - else - { - START_THREAD_TIMER(thid); - int res = SolveBoard( - bop->deals[index], - bop->target[index], - bop->solutions[index], - bop->mode[index], - &fut[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - solvedp->solvedBoard[index] = fut[index]; - else - fail = res; - - } - } - }); - - } - else - { - dispatch_apply(static_cast(noOfThreads), - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), - ^(size_t t) - { - while (1) - { - int thid = static_cast(t); - - schedType st = scheduler.GetNumber(thid); - int index = st.number; - if (index == -1) - break; - - if (st.repeatOf != -1) - { - START_THREAD_TIMER(thid); - for (int k = 0; k < chunk; k++) - { - bop->deals[index].first = k; - - solvedp->solvedBoard[index].score[k] = - solvedp->solvedBoard[ st.repeatOf ].score[k]; - } - END_THREAD_TIMER(thid); - continue; - } - - bop->deals[index].first = 0; - - START_THREAD_TIMER(thid); - int res = SolveBoard( - bop->deals[index], - bop->target[index], - bop->solutions[index], - bop->mode[index], - &fut[index], - thid); - - // SH: I'm making a terrible use of the fut structure here. - - if (res == 1) - solvedp->solvedBoard[index].score[0] = fut[index].score[0]; - else - fail = res; - - for (int k = 1; k < chunk; k++) - { - int hint = (k == 2 ? fut[index].score[0] : - 13 - fut[index].score[0]); - - bop->deals[index].first = k; // Next declarer - - res = SolveSameBoard( - bop->deals[index], - &fut[index], - hint, - thid); - - if (res == 1) - solvedp->solvedBoard[index].score[k] = - fut[index].score[0]; - else - fail = res; - } - END_THREAD_TIMER(thid); - } - }); - } - - END_BLOCK_TIMER; - - free(fut); - - if (fail != 1) - return fail; - - solvedp->noOfBoards = 0; - for (int i = 0; i < MAXNOOFBOARDS; i++) - if (solvedp->solvedBoard[i].cards != 0) - solvedp->noOfBoards++; - - return 1; -} - -#else - -int SolveAllBoardsN( - boards * bop, - solvedBoards * solvedp, - int chunkSize, - int source) // 0 solve, 1 calc -{ - int k, i, res, chunk, fail; - futureTricks fut[MAXNOOFBOARDS]; - - chunk = chunkSize; - fail = 1; - - if (bop->noOfBoards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - for (i = 0; i < MAXNOOFBOARDS; i++) - solvedp->solvedBoard[i].cards = 0; - -#if defined (_OPENMP) && !defined(DDS_THREADS_SINGLE) - if (omp_get_dynamic()) - omp_set_dynamic(0); - omp_set_num_threads(noOfThreads); - /* Added after suggestion by Dirk Willecke. */ -#elif defined (_OPENMP) - omp_set_num_threads(1); -#endif - - int index, thid, hint; - schedType st; - - START_BLOCK_TIMER; - - if (source == 0) - scheduler.Register(bop, SCHEDULER_SOLVE); - else - scheduler.Register(bop, SCHEDULER_CALC); - - if (chunkSize == 1) - { - #pragma omp parallel default(none) shared(scheduler, fut, bop, solvedp, chunk, fail) private(st, index, thid, res) - { - #pragma omp while schedule(dynamic, chunk) - - while (1) - { -#if defined (_OPENMP) && !defined(DDS_THREADS_SINGLE) - thid = omp_get_thread_num(); -#else - thid = 0; -#endif - - st = scheduler.GetNumber(thid); - index = st.number; - if (index == -1) - break; - - // This is not a perfect repeat detector, as the hands in - // a group might have declarers N, S, N, N. Then the second - // N would not reuse the first N. However, must reuses are - // reasonably adjacent, and this is just an optimization anyway. - - if (st.repeatOf != -1 && - (bop->deals[index ].first == - bop->deals[st.repeatOf].first)) - { - START_THREAD_TIMER(thid); - solvedp->solvedBoard[index] = fut[ st.repeatOf ]; - END_THREAD_TIMER(thid); - continue; - } - else - { - START_THREAD_TIMER(thid); - res = SolveBoard( - bop->deals[index], - bop->target[index], - bop->solutions[index], - bop->mode[index], - &fut[index], - thid); - END_THREAD_TIMER(thid); - - if (res == 1) - solvedp->solvedBoard[index] = fut[index]; - else - fail = res; - - } - } - } - } - else - { - #pragma omp parallel default(none) shared(scheduler, bop, fut, solvedp, chunk, fail) private(st, index, thid, k, hint, res) - { - #pragma omp while schedule(dynamic, chunk) - - while (1) - { -#if defined (_OPENMP) && !defined(DDS_THREADS_SINGLE) - thid = omp_get_thread_num(); -#else - thid = 0; -#endif - - st = scheduler.GetNumber(thid); - index = st.number; - if (index == -1) - break; - - if (st.repeatOf != -1) - { - START_THREAD_TIMER(thid); - for (k = 0; k < chunk; k++) - { - bop->deals[index].first = k; - - solvedp->solvedBoard[index].score[k] = - solvedp->solvedBoard[ st.repeatOf ].score[k]; - } - END_THREAD_TIMER(thid); - continue; - } - - bop->deals[index].first = 0; - - START_THREAD_TIMER(thid); - res = SolveBoard( - bop->deals[index], - bop->target[index], - bop->solutions[index], - bop->mode[index], - &fut[index], - thid); - - // SH: I'm making a terrible use of the fut structure here. - - if (res == 1) - solvedp->solvedBoard[index].score[0] = fut[index].score[0]; - else - fail = res; - - for (k = 1; k < chunk; k++) - { - hint = (k == 2 ? fut[index].score[0] : - 13 - fut[index].score[0]); - - bop->deals[index].first = k; // Next declarer - - res = SolveSameBoard( - bop->deals[index], - &fut[index], - hint, - thid); - - if (res == 1) - solvedp->solvedBoard[index].score[k] = - fut[index].score[0]; - else - fail = res; - } - END_THREAD_TIMER(thid); - } - } - - } - - END_BLOCK_TIMER; - - if (fail != 1) - return fail; - - solvedp->noOfBoards = 0; - for (i = 0; i < MAXNOOFBOARDS; i++) - if (solvedp->solvedBoard[i].cards != 0) - solvedp->noOfBoards++; - - return 1; -} - -#endif - int STDCALL SolveBoardPBN( dealPBN dlpbn, @@ -617,16 +152,13 @@ int STDCALL SolveBoardPBN( int solutions, int mode, futureTricks * futp, - int thrIndex) + int thrId) { - - int res, k; deal dl; - if (ConvertFromPBN(dlpbn.remainCards, dl.remainCards) != RETURN_NO_FAULT) return RETURN_PBN_FAULT; - for (k = 0; k <= 2; k++) + for (int k = 0; k <= 2; k++) { dl.currentTrickRank[k] = dlpbn.currentTrickRank[k]; dl.currentTrickSuit[k] = dlpbn.currentTrickSuit[k]; @@ -634,8 +166,7 @@ int STDCALL SolveBoardPBN( dl.first = dlpbn.first; dl.trump = dlpbn.trump; - res = SolveBoard(dl, target, solutions, mode, futp, thrIndex); - + int res = SolveBoard(dl, target, solutions, mode, futp, thrId); return res; } @@ -645,33 +176,34 @@ int STDCALL SolveAllBoards( solvedBoards * solvedp) { boards bo; - int k, i, res; - bo.noOfBoards = bop->noOfBoards; if (bo.noOfBoards > MAXNOOFBOARDS) return RETURN_TOO_MANY_BOARDS; - for (k = 0; k < bop->noOfBoards; k++) + for (int k = 0; k < bop->noOfBoards; 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++) + + for (int 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) + + if (ConvertFromPBN(bop->deals[k].remainCards, bo.deals[k].remainCards) + != 1) return RETURN_PBN_FAULT; } - res = SolveAllBoardsN(&bo, solvedp, 1, 0); - + int res = SolveAllBoardsN(bo, * solvedp); return res; } + int STDCALL SolveAllChunksPBN( boardsPBN * bop, solvedBoards * solvedp, @@ -707,7 +239,74 @@ int STDCALL SolveAllChunksBin( if (chunkSize < 1) return RETURN_CHUNK_SIZE; - return SolveAllBoardsN(bop, solvedp, 1, 0); + return SolveAllBoardsN(* bop, * solvedp); +} + + +void DetectSolveDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs) +{ + const unsigned nu = static_cast(bds.noOfBoards); + + uniques.clear(); + crossrefs.resize(nu); + + for (unsigned i = 0; i < nu; i++) + crossrefs[i] = -1; + + for (unsigned i = 0; i < nu; i++) + { + if (crossrefs[i] != -1) + continue; + + uniques.push_back(static_cast(i)); + + for (unsigned index = i+1; index < nu; index++) + { + if (SameBoard(bds, i, index)) + crossrefs[index] = static_cast(i); + } + } } +bool SameBoard( + const boards& bds, + const unsigned index1, + const unsigned index2) +{ + for (int h = 0; h < DDS_HANDS; h++) + { + for (int s = 0; s < DDS_SUITS; s++) + { + if (bds.deals[index1].remainCards[h][s] != + bds.deals[index2].remainCards[h][s]) + return false; + } + } + + if (bds.mode[index1] != bds.mode[index2]) + return false; + if (bds.solutions[index1] != bds.solutions[index2]) + return false; + if (bds.target[index1] != bds.target[index2]) + return false; + if (bds.deals[index1].first != bds.deals[index2].first) + return false; + if (bds.deals[index1].trump != bds.deals[index2].trump) + return false; + + for (int k = 0; k < 3; k++) + { + if (bds.deals[index1].currentTrickSuit[k] != + bds.deals[index2].currentTrickSuit[k]) + return false; + if (bds.deals[index1].currentTrickRank[k] != + bds.deals[index2].currentTrickRank[k]) + return false; + } + return true; +} + diff --git a/src/SolveBoard.h b/src/SolveBoard.h index 25159fd0..c14a9809 100644 --- a/src/SolveBoard.h +++ b/src/SolveBoard.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,11 +10,26 @@ #ifndef DDS_SOLVEBOARD_H #define DDS_SOLVEBOARD_H +#include -int SolveAllBoardsN( - struct boards * bop, - struct solvedBoards * solvedp, - int chunkSize, - int source); // 0 source, 1 calc +#include "dds.h" + +using namespace std; + + +void SolveSingleCommon( + const int thrId, + const int bno); + +void CopySolveSingle( + const vector& crossrefs); + +void SolveChunkCommon( + const int thrId); + +void DetectSolveDuplicates( + const boards& bds, + vector& uniques, + vector& crossrefs); #endif diff --git a/src/SolverIF.cpp b/src/SolverIF.cpp index 84a54ffe..92d9e438 100644 --- a/src/SolverIF.cpp +++ b/src/SolverIF.cpp @@ -2,78 +2,69 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include +#include +#include +#include -#include "dds.h" +#include "SolverIF.h" #include "Init.h" -#include "Moves.h" -#include "threadmem.h" #include "ABsearch.h" -#include "Stats.h" -#include "SolverIF.h" +#include "TimerList.h" +#include "System.h" +#include "Scheduler.h" +#include "dump.h" +#include "debug.h" + +extern System sysdep; +extern Memory memory; +extern Scheduler scheduler; int BoardRangeChecks( - deal * dl, - int target, - int solutions, - int mode, - int thrId); + const deal& dl, + const int target, + const int solutions, + const int mode); int BoardValueChecks( - deal * dl, - int target, - int solutions, - int mode, - localVarType * thrp); + const deal& dl, + const int target, + const int solutions, + const int mode, + ThreadData const * thrp); void LastTrickWinner( - deal * dl, - localVarType * thrp, - int handToPlay, - int handRelFirst, - int * leadRank, - int * leadSuit, - int * leadSideWins); - -int DumpInput( - int errCode, - deal * dl, - int target, - int solutions, - int mode); - -void PrintDeal( - FILE * fp, - unsigned short ranks[][DDS_SUITS]); - - -extern int noOfThreads; - + const deal& dl, + ThreadData const * thrp, + const int handToPlay, + const int handRelFirst, + int& leadRank, + int& leadSuit, + int& leadSideWins); bool (* AB_ptr_list[DDS_HANDS])( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) = { ABsearch, ABsearch1, ABsearch2, ABsearch3 }; bool (* AB_ptr_trace_list[DDS_HANDS])( pos * posPoint, - int target, - int depth, - localVarType * thrp) + const int target, + const int depth, + ThreadData * thrp) = { ABsearch0, ABsearch1, ABsearch2, ABsearch3 }; void (* Make_ptr_list[3])( pos * posPoint, - int depth, - moveType * mply) + const int depth, + moveType const * mply) = { Make0, Make1, Make2 }; @@ -85,13 +76,27 @@ int STDCALL SolveBoard( futureTricks * futp, int thrId) { - localVarType * thrp = &localVar[thrId]; + if (! sysdep.ThreadOK(thrId)) + return RETURN_THREAD_INDEX; + + return SolveBoardInternal(memory.GetPtr(static_cast(thrId)), + dl, target, solutions, mode, futp); +} + +int SolveBoardInternal( + ThreadData * thrp, + const deal& dl, + const int target, + const int solutions, + const int mode, + futureTricks * futp) +{ // ---------------------------------------------------------- // Formal parameter checks. // ---------------------------------------------------------- - int ret = BoardRangeChecks(&dl, target, solutions, mode, thrId); + int ret = BoardRangeChecks(dl, target, solutions, mode); if (ret != RETURN_NO_FAULT) return ret; @@ -169,7 +174,7 @@ int STDCALL SolveBoard( // Consistency checks. // ---------------------------------------------------------- - ret = BoardValueChecks(&dl, target, solutions, mode, thrp); + ret = BoardValueChecks(dl, target, solutions, mode, thrp); if (ret != RETURN_NO_FAULT) return ret; @@ -182,8 +187,8 @@ int STDCALL SolveBoard( { int leadRank, leadSuit, leadSideWins; - LastTrickWinner(&dl, thrp, handToPlay, handRelFirst, - &leadRank, &leadSuit, &leadSideWins); + LastTrickWinner(dl, thrp, handToPlay, handRelFirst, + leadRank, leadSuit, leadSideWins); futp->nodes = 0; futp->cards = 1; @@ -205,14 +210,14 @@ int STDCALL SolveBoard( newTrump || (thrp->nodes > SIMILARMAXWINNODES))) { - int reason = UNKNOWN_REASON; + TTresetReason reason = TT_RESET_UNKNOWN; if (thrp->nodes > SIMILARMAXWINNODES) - reason = TOO_MANY_NODES; + reason = TT_RESET_TOO_MANY_NODES; else if (newDeal && ! similarDeal) - reason = NEW_DEAL; + reason = TT_RESET_NEW_DEAL; else if (newTrump) - reason = NEW_TRUMP; - thrp->transTable.ResetMemory(reason); + reason = TT_RESET_NEW_TRUMP; + thrp->transTable->ResetMemory(reason); } if (newDeal) @@ -259,21 +264,21 @@ int STDCALL SolveBoard( if (k == 0) thrp->moves.MoveGen0( trick, - &thrp->lookAheadPos, - &thrp->bestMove[iniDepth], - &thrp->bestMoveTT[iniDepth], + thrp->lookAheadPos, + thrp->bestMove[iniDepth], + thrp->bestMoveTT[iniDepth], thrp->rel); else thrp->moves.MoveGen123( trick, k, - &thrp->lookAheadPos); + thrp->lookAheadPos); thrp->lookAheadPos.move[iniDepth + handRelFirst - k] = mv; - thrp->moves.MakeSpecific(&mv, trick, k); + thrp->moves.MakeSpecific(mv, trick, k); } - InitWinners(&dl, &thrp->lookAheadPos, thrp); + InitWinners(dl, thrp->lookAheadPos, thrp); #ifdef DDS_AB_STATS thrp->ABStats.Reset(); @@ -296,15 +301,15 @@ int STDCALL SolveBoard( if (handRelFirst == 0) thrp->moves.MoveGen0( trick, - &thrp->lookAheadPos, - &thrp->bestMove[iniDepth], - &thrp->bestMoveTT[iniDepth], + thrp->lookAheadPos, + thrp->bestMove[iniDepth], + thrp->bestMoveTT[iniDepth], thrp->rel); else thrp->moves.MoveGen123( trick, handRelFirst, - &thrp->lookAheadPos); + thrp->lookAheadPos); noMoves = thrp->moves.GetLength(trick, handRelFirst); @@ -314,7 +319,7 @@ int STDCALL SolveBoard( if (mode == 0 && noMoves == 1) { - moveType * mp = thrp->moves.MakeNextSimple(trick, handRelFirst); + moveType const * mp = thrp->moves.MakeNextSimple(trick, handRelFirst); futp->nodes = 0; futp->cards = 1; @@ -345,16 +350,17 @@ int STDCALL SolveBoard( { ResetBestMoves(thrp); - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = (* AB_ptr_list[handRelFirst])( &thrp->lookAheadPos, guess, iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, guess, lowerbound, upperbound, 1); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, guess, lowerbound, upperbound, 1); #endif if (thrp->val) @@ -387,10 +393,10 @@ int STDCALL SolveBoard( int noLeft = thrp->moves.GetLength(trick, handRelFirst); thrp->moves.Rewind(trick, handRelFirst); - moveType * mp; for (int j = 0; j < noLeft; j++) { - mp = thrp->moves.MakeNextSimple(trick, handRelFirst); + moveType const * mp = + thrp->moves.MakeNextSimple(trick, handRelFirst); futp->suit[mno + j] = mp->suit; futp->rank[mno + j] = mp->rank; @@ -415,7 +421,9 @@ int STDCALL SolveBoard( for (int mno = 0; mno < noMoves; mno++) { - moveType * mp = thrp->moves.MakeNextSimple(trick, handRelFirst); + moveType const * mp = + thrp->moves.MakeNextSimple(trick, handRelFirst); + futp->suit[mno] = mp->suit; futp->rank[mno] = mp->rank; futp->equals[mno] = mp->sequence << 2; @@ -439,15 +447,16 @@ int STDCALL SolveBoard( { ResetBestMoves(thrp); - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = (* AB_ptr_list[handRelFirst])(&thrp->lookAheadPos, guess, iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, guess, lowerbound, upperbound, 1); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, guess, lowerbound, upperbound, 1); #endif if (thrp->val) @@ -471,11 +480,11 @@ int STDCALL SolveBoard( else // solutions == 2, so return all cards futp->cards = noMoves; - moveType * mp; thrp->moves.Rewind(trick, handRelFirst); for (int i = 0; i < noMoves; i++) { - mp = thrp->moves.MakeNextSimple(trick, handRelFirst); + moveType const * mp = + thrp->moves.MakeNextSimple(trick, handRelFirst); futp->score[i] = 0; futp->suit[i] = mp->suit; @@ -504,16 +513,17 @@ int STDCALL SolveBoard( else { - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = (* AB_ptr_list[handRelFirst])( &thrp->lookAheadPos, target, iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, target, -1, -1, 0); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, target, -1, -1, 0); #endif if (! thrp->val) @@ -545,7 +555,6 @@ int STDCALL SolveBoard( // This applies both to target == -1 and target >= 1. // ---------------------------------------------------------- - moveType * mp; forb = 1; ind = 1; @@ -558,7 +567,8 @@ int STDCALL SolveBoard( for (int k = 0; k < num; k++) { - mp = thrp->moves.MakeNextSimple(trick, handRelFirst); + moveType const * mp = + thrp->moves.MakeNextSimple(trick, handRelFirst); thrp->forbiddenMoves[forb] = * mp; forb++; @@ -569,16 +579,17 @@ int STDCALL SolveBoard( ResetBestMoves(thrp); - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = (* AB_ptr_list[handRelFirst])( &thrp->lookAheadPos, futp->score[0], iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, target, -1, -1, 2); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, target, -1, -1, 2); #endif if (! thrp->val) @@ -602,30 +613,35 @@ int STDCALL SolveBoard( } #ifdef DDS_TIMING - thrp->timer.PrintStats(); + thrp->timerList.PrintStats(thrp->fileTimerList.GetStream()); #endif #ifdef DDS_TT_STATS - // thrp->transTable.PrintAllSuits(); - // thrp->transTable.PrintEntries(10, 0); - thrp->transTable.PrintSummarySuitStats(); - thrp->transTable.PrintSummaryEntryStats(); - // thrp->transTable.PrintPageSummary(); + // These are for the large TT -- empty if not. + // thrp->transTable->PrintAllSuits(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllSuitStats(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntries(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntryStats(thrp->fileTTstats.GetStream()); + + thrp->transTable->PrintSummarySuitStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintSummaryEntryStats(thrp->fileTTstats.GetStream()); + + // These are for the small TT -- empty if not. + thrp->transTable->PrintNodeStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintResetStats(thrp->fileTTstats.GetStream()); #endif #ifdef DDS_MOVES - thrp->moves.PrintTrickStats(); + thrp->moves.PrintTrickStats(thrp->fileMoves.GetStream()); #ifdef DDS_MOVES_DETAILS - thrp->moves.PrintTrickDetails(); + thrp->moves.PrintTrickDetails(thrp->fileMoves.GetStream()); #endif - thrp->moves.PrintFunctionStats(); + thrp->moves.PrintFunctionStats(thrp->fileMoves.GetStream()); #endif SOLVER_DONE: - thrp->memUsed = thrp->transTable.MemoryInUse() + - ThreadMemoryUsed(); - + thrp->memUsed = thrp->transTable->MemoryInUse() + ThreadMemoryUsed(); futp->nodes = thrp->trickNodes; #ifdef DDS_MEMORY_LEAKS_WIN32 @@ -637,10 +653,10 @@ int STDCALL SolveBoard( int SolveSameBoard( - deal dl, + ThreadData * thrp, + const deal& dl, futureTricks * futp, - int hint, - int thrId) + const int hint) { // Specialized function for SolveChunkDDtable for repeat solves. // No further parameter checks! This function makes heavy reuse @@ -649,8 +665,6 @@ int SolveSameBoard( // target == -1, solutions == 1, mode == 2. // The function only needs to return fut.score[0]. - localVarType * thrp = &localVar[thrId]; - int iniDepth = thrp->iniDepth; int trick = (iniDepth + 3) >> 2; thrp->trickNodes = 0; @@ -691,16 +705,17 @@ int SolveSameBoard( { ResetBestMoves(thrp); - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = ABsearch( &thrp->lookAheadPos, guess, iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, guess, lowerbound, upperbound, 1); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, guess, lowerbound, upperbound, 1); #endif if (thrp->val) @@ -713,24 +728,34 @@ int SolveSameBoard( futp->cards = 1; futp->score[0] = lowerbound; - thrp->memUsed = thrp->transTable.MemoryInUse() + + thrp->memUsed = thrp->transTable->MemoryInUse() + ThreadMemoryUsed(); #ifdef DDS_TIMING - thrp->timer.PrintStats(); + thrp->timerList.PrintStats(thrp->fileTimerList.GetStream()); #endif #ifdef DDS_TT_STATS - thrp->transTable.PrintSummarySuitStats(); - thrp->transTable.PrintSummaryEntryStats(); + // These are for the large TT -- empty if not. + // thrp->transTable->PrintAllSuits(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllSuitStats(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntries(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntryStats(thrp->fileTTstats.GetStream()); + + thrp->transTable->PrintSummarySuitStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintSummaryEntryStats(thrp->fileTTstats.GetStream()); + + // These are for the small TT -- empty if not. + thrp->transTable->PrintNodeStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintResetStats(thrp->fileTTstats.GetStream()); #endif #ifdef DDS_MOVES - thrp->moves.PrintTrickStats(); + thrp->moves.PrintTrickStats(thrp->fileMoves.GetStream()); #ifdef DDS_MOVES_DETAILS - thrp->moves.PrintTrickDetails(); + thrp->moves.PrintTrickDetails(thrp->fileMoves.GetStream()); #endif - thrp->moves.PrintFunctionStats(); + thrp->moves.PrintFunctionStats(thrp->fileMoves.GetStream()); #endif futp->nodes = thrp->trickNodes; @@ -744,12 +769,12 @@ int SolveSameBoard( int AnalyseLaterBoard( - int leadHand, - moveType * move, - int hint, - int hintDir, - futureTricks * futp, - int thrId) + ThreadData * thrp, + const int leadHand, + moveType const * move, + const int hint, + const int hintDir, + futureTricks * futp) { // Specialized function for PlayAnalyser for cards after the // opening lead. No further parameter checks! This function @@ -758,8 +783,6 @@ int AnalyseLaterBoard( // target == -1, solutions == 1, mode == 2. // The function only needs to return fut.score[0]. - localVarType * thrp = &localVar[thrId]; - int iniDepth = --thrp->iniDepth; int cardCount = iniDepth + 4; int trick = (iniDepth + 3) >> 2; @@ -785,23 +808,23 @@ int AnalyseLaterBoard( if (handRelFirst == 0) { - thrp->moves.MakeSpecific(move, trick + 1, 3); + thrp->moves.MakeSpecific(* move, trick + 1, 3); unsigned short int ourWinRanks[DDS_SUITS]; // Unused here Make3(&thrp->lookAheadPos, ourWinRanks, iniDepth + 1, move, thrp); } else if (handRelFirst == 1) { - thrp->moves.MakeSpecific(move, trick, 0); + thrp->moves.MakeSpecific(* move, trick, 0); Make0(&thrp->lookAheadPos, iniDepth + 1, move); } else if (handRelFirst == 2) { - thrp->moves.MakeSpecific(move, trick, 1); + thrp->moves.MakeSpecific(* move, trick, 1); Make1(&thrp->lookAheadPos, iniDepth + 1, move); } else { - thrp->moves.MakeSpecific(move, trick, 2); + thrp->moves.MakeSpecific(* move, trick, 2); Make2(&thrp->lookAheadPos, iniDepth + 1, move); } @@ -843,16 +866,17 @@ int AnalyseLaterBoard( { ResetBestMoves(thrp); - TIMER_START(TIMER_AB + iniDepth); + TIMER_START(TIMER_NO_AB, iniDepth); thrp->val = (* AB_ptr_trace_list[handRelFirst])( &thrp->lookAheadPos, guess, iniDepth, thrp); - TIMER_END(TIMER_AB + iniDepth); + TIMER_END(TIMER_NO_AB, iniDepth); #ifdef DDS_TOP_LEVEL - DumpTopLevel(thrp, guess, lowerbound, upperbound, 1); + DumpTopLevel(thrp->fileTopLevel.GetStream(), + * thrp, guess, lowerbound, upperbound, 1); #endif if (thrp->val) @@ -866,24 +890,34 @@ int AnalyseLaterBoard( futp->score[0] = lowerbound; futp->nodes = thrp->trickNodes; - thrp->memUsed = thrp->transTable.MemoryInUse() + + thrp->memUsed = thrp->transTable->MemoryInUse() + ThreadMemoryUsed(); #ifdef DDS_TIMING - thrp->timer.PrintStats(); + thrp->timerList.PrintStats(thrp->fileTimerList.GetStream()); #endif #ifdef DDS_TT_STATS - thrp->transTable.PrintSummarySuitStats(); - thrp->transTable.PrintSummaryEntryStats(); + // These are for the large TT -- empty if not. + // thrp->transTable->PrintAllSuits(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllSuitStats(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntries(thrp->fileTTstats.GetStream()); + // thrp->transTable->PrintAllEntryStats(thrp->fileTTstats.GetStream()); + + thrp->transTable->PrintSummarySuitStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintSummaryEntryStats(thrp->fileTTstats.GetStream()); + + // These are for the small TT -- empty if not. + thrp->transTable->PrintNodeStats(thrp->fileTTstats.GetStream()); + thrp->transTable->PrintResetStats(thrp->fileTTstats.GetStream()); #endif #ifdef DDS_MOVES - thrp->moves.PrintTrickStats(); + thrp->moves.PrintTrickStats(thrp->fileMoves.GetStream()); #ifdef DDS_MOVES_DETAILS - thrp->moves.PrintTrickDetails(); + thrp->moves.PrintTrickDetails(thrp->fileMoves.GetStream()); #endif - thrp->moves.PrintFunctionStats(); + thrp->moves.PrintFunctionStats(thrp->fileMoves.GetStream()); #endif #ifdef DDS_MEMORY_LEAKS_WIN32 @@ -895,11 +929,10 @@ int AnalyseLaterBoard( int BoardRangeChecks( - deal * dl, - int target, - int solutions, - int mode, - int thrId) + const deal& dl, + const int target, + const int solutions, + const int mode) { if (target < -1) { @@ -937,20 +970,13 @@ int BoardRangeChecks( return RETURN_MODE_WRONG_HI; } - if (thrId < 0 || thrId >= noOfThreads) - /* Fault corrected after suggestion by Dirk Willecke. */ - { - DumpInput(RETURN_THREAD_INDEX, dl, target, solutions, mode); - return RETURN_THREAD_INDEX; - } - - if (dl->trump < 0 || dl->trump > 4) + if (dl.trump < 0 || dl.trump > 4) { DumpInput(RETURN_TRUMP_WRONG, dl, target, solutions, mode); return RETURN_TRUMP_WRONG; } - if (dl->first < 0 || dl->first > 3) + if (dl.first < 0 || dl.first > 3) { DumpInput(RETURN_FIRST_WRONG, dl, target, solutions, mode); return RETURN_FIRST_WRONG; @@ -959,7 +985,7 @@ int BoardRangeChecks( int rankSeen[3] = {0, 0, 0}; for (int k = 0; k < 3; k++) { - int r = dl->currentTrickRank[k]; + int r = dl.currentTrickRank[k]; if (r == 0) continue; @@ -971,7 +997,7 @@ int BoardRangeChecks( return RETURN_SUIT_OR_RANK; } - if (dl->currentTrickSuit[k] < 0 || dl->currentTrickSuit[k] > 3) + if (dl.currentTrickSuit[k] < 0 || dl.currentTrickSuit[k] > 3) { DumpInput(RETURN_SUIT_OR_RANK, dl, target, solutions, mode); return RETURN_SUIT_OR_RANK; @@ -989,7 +1015,7 @@ int BoardRangeChecks( { for (int s = 0; s < DDS_SUITS; s++) { - unsigned c = dl->remainCards[h][s]; + unsigned c = dl.remainCards[h][s]; if (c != 0 && (c < 0x0004 || c >= 0x8000)) { DumpInput(RETURN_SUIT_OR_RANK, dl, target, solutions, mode); @@ -1003,11 +1029,11 @@ int BoardRangeChecks( int BoardValueChecks( - deal * dl, - int target, - int solutions, - int mode, - localVarType * thrp) + const deal& dl, + const int target, + const int solutions, + const int mode, + ThreadData const * thrp) { int cardCount = thrp->iniDepth + 4; if (cardCount <= 0) @@ -1038,7 +1064,7 @@ int BoardValueChecks( int noOfCardsPerHand[DDS_HANDS] = {0, 0, 0, 0}; for (int k = 0; k < handRelFirst; k++) - noOfCardsPerHand[handId(dl->first, k)] = 1; + noOfCardsPerHand[handId(dl.first, k)] = 1; for (int h = 0; h < DDS_HANDS; h++) for (int s = 0; s < DDS_SUITS; s++) @@ -1057,9 +1083,9 @@ int BoardValueChecks( { unsigned short int aggrRemain = 0; for (int h = 0; h < DDS_HANDS; h++) - aggrRemain |= (dl->remainCards[h][dl->currentTrickSuit[k]] >> 2); + aggrRemain |= (dl.remainCards[h][dl.currentTrickSuit[k]] >> 2); - if ((aggrRemain & bitMapRank[dl->currentTrickRank[k]]) != 0) + if ((aggrRemain & bitMapRank[dl.currentTrickRank[k]]) != 0) { DumpInput(RETURN_PLAYED_CARD, dl, target, solutions, mode); return RETURN_PLAYED_CARD; @@ -1093,13 +1119,13 @@ int BoardValueChecks( void LastTrickWinner( - deal * dl, - localVarType * thrp, - int handToPlay, - int handRelFirst, - int * leadRank, - int * leadSuit, - int * leadSideWins) + const deal& dl, + ThreadData const * thrp, + const int handToPlay, + const int handRelFirst, + int& leadRank, + int& leadSuit, + int& leadSideWins) { int lastTrickSuit[DDS_HANDS], lastTrickRank[DDS_HANDS], @@ -1108,14 +1134,14 @@ void LastTrickWinner( for (h = 0; h < handRelFirst; h++) { - hp = handId(dl->first, h); - lastTrickSuit[hp] = dl->currentTrickSuit[h]; - lastTrickRank[hp] = dl->currentTrickRank[h]; + hp = handId(dl.first, h); + lastTrickSuit[hp] = dl.currentTrickSuit[h]; + lastTrickRank[hp] = dl.currentTrickRank[h]; } for (h = handRelFirst; h < DDS_HANDS; h++) { - hp = handId(dl->first, h); + hp = handId(dl.first, h); for (int s = 0; s < DDS_SUITS; s++) { if (thrp->suit[hp][s] != 0) @@ -1132,15 +1158,15 @@ void LastTrickWinner( maxHand = -1; /* Highest trump? */ - if (dl->trump != DDS_NOTRUMP) + if (dl.trump != DDS_NOTRUMP) { for (h = 0; h < DDS_HANDS; h++) { - if ((lastTrickSuit[h] == dl->trump) && + if ((lastTrickSuit[h] == dl.trump) && (lastTrickRank[h] > maxRank)) { maxRank = lastTrickRank[h]; - maxSuit = dl->trump; + maxSuit = dl.trump; maxHand = h; } } @@ -1149,9 +1175,9 @@ void LastTrickWinner( /* Highest card in leading suit */ if (maxRank == 0) { - maxRank = lastTrickRank[dl->first]; - maxSuit = lastTrickSuit[dl->first]; - maxHand = dl->first; + maxRank = lastTrickRank[dl.first]; + maxSuit = lastTrickSuit[dl.first]; + maxHand = dl.first; for (h = 0; h < DDS_HANDS; h++) { @@ -1164,128 +1190,10 @@ void LastTrickWinner( } } - hp = handId(dl->first, handRelFirst); - * leadRank = lastTrickRank[hp]; - * leadSuit = lastTrickSuit[hp]; - * leadSideWins = ((handToPlay == maxHand || - partner[handToPlay] == maxHand) ? 1 : 0); -} - - - -int DumpInput( - int errCode, - 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 == nullptr) - return RETURN_UNKNOWN_FAULT; - 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] = static_cast - (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, trickCount = 0, s, r; - bool ec[4]; - 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 < DDS_SUITS; 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 < DDS_SUITS; 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 < DDS_SUITS; 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; + hp = handId(dl.first, handRelFirst); + leadRank = lastTrickRank[hp]; + leadSuit = lastTrickSuit[hp]; + leadSideWins = ((handToPlay == maxHand || + partner[handToPlay] == maxHand) ? 1 : 0); } diff --git a/src/SolverIF.h b/src/SolverIF.h index 14b43ad8..066076f5 100644 --- a/src/SolverIF.h +++ b/src/SolverIF.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,19 +10,30 @@ #ifndef DDS_SOLVERIF_H #define DDS_SOLVERIF_H +#include "dds.h" +#include "Memory.h" + + +int SolveBoardInternal( + ThreadData * thrp, + const deal& dl, + const int target, + const int solutions, + const int mode, + futureTricks * futp); int SolveSameBoard( - deal dl, + ThreadData * thrp, + const deal& dl, futureTricks * futp, - int hint, - int thrId); + const int hint); int AnalyseLaterBoard( - int leadHand, - moveType * move, - int hint, - int hintDir, - futureTricks * futp, - int thrp); + ThreadData * thrp, + const int leadHand, + moveType const * move, + const int hint, + const int hintDir, + futureTricks * futp); #endif diff --git a/src/Stats.cpp b/src/Stats.cpp deleted file mode 100644 index dcc7101a..00000000 --- a/src/Stats.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - -#include - -#include "dds.h" -#include "Stats.h" - -#define NUM_TIMERS 2000 -#define COUNTER_SLOTS 200 - -#include - -#ifdef _WIN32 -LARGE_INTEGER timerFreq; -LARGE_INTEGER timerUser0; -LARGE_INTEGER timerUser1; -LARGE_INTEGER timerListUser0[NUM_TIMERS]; -LARGE_INTEGER timerListUser1[NUM_TIMERS]; -#else -#include -int timevalDiff(timeval x, timeval y); - -timeval timerUser0; -timeval timerUser1; -timeval timerListUser0[NUM_TIMERS]; -timeval timerListUser1[NUM_TIMERS]; -#endif - -clock_t timerSys0; -clock_t timerSys1; -clock_t timerListSys0[NUM_TIMERS]; -clock_t timerListSys1[NUM_TIMERS]; - -int timerCount; -int timerListCount[NUM_TIMERS]; - -int timerNameSet; - -char timerName[80]; - -long long timerUserCum; -long long timerSysCum; -long long timerListUserCum[NUM_TIMERS]; -long long timerListSysCum[NUM_TIMERS]; -long long predError; -long long predAbsError; - - -void InitTimer() -{ - timerCount = 0; - timerUserCum = 0; - timerSysCum = 0; - timerNameSet = 0; - - predError = 0; - predAbsError = 0; -} - - -void SetTimerName(char * name) -{ - strcpy(timerName, name); - timerNameSet = 1; -} - - -void StartTimer() -{ - timerCount++; - timerSys0 = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&timerUser0); -#else - gettimeofday(&timerUser0, nullptr); -#endif -} - - -void EndTimer() -{ - timerSys1 = clock(); - -#ifdef _WIN32 - // To get "real" seconds we would have to divide by - // timerFreq.QuadPart which needs to be initialized. - QueryPerformanceCounter(&timerUser1); - int timeUser = static_cast - ((timerUser1.QuadPart - timerUser0.QuadPart)); -#else - gettimeofday(&timerUser1, nullptr); - int timeUser = timevalDiff(timerUser1, timerUser0); -#endif - - timerUserCum += timeUser; - - timerSysCum += static_cast((1000 * (timerSys1 - timerSys0)) / - static_cast(CLOCKS_PER_SEC)); -} - - -void PrintTimer() -{ - if (timerNameSet) - printf("%-18s : %s\n", "Timer name", timerName); - - printf("%-18s : %10d\n", "Number of calls", timerCount); - if (timerCount == 0) return; - - if (timerUserCum == 0) - printf("%-18s : %s\n", "User time", "zero"); - else - { - printf("%-18s : %10lld\n", "User time/ticks", timerUserCum); - printf("%-18s : %10.2f\n", "User per call", - static_cast(timerUserCum / timerCount)); - } - - if (timerSysCum == 0) - printf("%-18s : %s\n", "Sys time", "zero"); - else - { - printf("%-18s : %10lld\n", "Sys time/ticks", timerSysCum); - printf("%-18s : %10.2f\n", "Sys per call", - static_cast(timerSysCum / timerCount)); - printf("%-18s : %10.2f\n", "Ratio", - static_cast(timerSysCum / timerUserCum)); - } - printf("\n"); -} - - -void InitTimerList() -{ - for (int i = 0; i < NUM_TIMERS; i++) - { - timerListCount [i] = 0; - timerListUserCum[i] = 0; - timerListSysCum [i] = 0; - } -} - - -void StartTimerNo(int no) -{ - timerListCount[no]++; - timerListSys0[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&timerListUser0[no]); -#else - gettimeofday(&timerListUser0[no], nullptr); -#endif -} - - -void EndTimerNo(int no) -{ - timerListSys1[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&timerListUser1[no]); - int timeUser = static_cast - ((timerListUser1[no].QuadPart - timerListUser0[no].QuadPart)); -#else - gettimeofday(&timerListUser1[no], nullptr); - int timeUser = timevalDiff(timerListUser1[no], timerListUser0[no]); -#endif - - timerListUserCum[no] += static_cast(timeUser); - - timerListSysCum[no] += - static_cast((1000 * - (timerListSys1[no] - timerListSys0[no])) / - static_cast(CLOCKS_PER_SEC)); -} - - -void EndTimerNoAndComp(int no, int pred) -{ - timerListSys1[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&timerListUser1[no]); - int timeUser = static_cast - ((timerListUser1[no].QuadPart - timerListUser0[no].QuadPart)); -#else - gettimeofday(&timerListUser1[no], nullptr); - int timeUser = timevalDiff(timerListUser1[no], timerListUser0[no]); -#endif - - timerListUserCum[no] += static_cast(timeUser); - - predError += timeUser - pred; - - predAbsError += (timeUser >= pred ? - timeUser - pred : pred - timeUser); - - timerListSysCum[no] += - static_cast( - (1000 * (timerListSys1[no] - timerListSys0[no])) / - static_cast(CLOCKS_PER_SEC)); -} - - -void PrintTimerList() -{ - printf("%5s %10s %12s %10s %10s\n", - "n", "Number", "User ticks", "Avg", "Syst time"); - - int totNum = 0; - for (int no = 0; no < NUM_TIMERS; no++) - { - if (timerListCount[no] == 0) - continue; - - totNum += timerListCount[no]; - - double avg = static_cast(timerListUserCum[no]) / - static_cast(timerListCount[no]); - - // For some reason I have trouble when putting it on one line... - printf("%5d %10d %12lld ", - no, - timerListCount[no], - timerListUserCum[no]); - printf(" %10.2f %10lld\n", - avg, - timerListSysCum[no]); - } - printf("\n"); - if (predError != 0) - { - printf("Total number %10d\n", totNum); - printf("Prediction mean %10.0f\n", - static_cast(predError) / - static_cast(totNum)); - printf("Prediction abs mean %10.0f\n", - static_cast(predAbsError) / - static_cast(totNum)); - printf("\n"); - } -} - - -#ifndef _WIN32 -int timevalDiff(timeval x, timeval y) -{ - /* Elapsed time, x-y, in milliseconds */ - return 1000 * (x.tv_sec - y.tv_sec ) - + (x.tv_usec - y.tv_usec) / 1000; -} -#endif - - -long long counter[COUNTER_SLOTS]; - -void InitCounter() -{ - for (int i = 0; i < COUNTER_SLOTS; i++) - counter[i] = 0; -} - - -void PrintCounter() -{ - for (int i = 0; i < COUNTER_SLOTS; i++) - { - if (counter[i]) - printf("%d\t%12lld\n", i, counter[i]); - } - printf("\n"); -} - - diff --git a/src/Stats.h b/src/Stats.h deleted file mode 100644 index c4a62bf9..00000000 --- a/src/Stats.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - -#ifndef DDS_STATS_H -#define DDS_STATS_H - -void InitTimer(); - -void SetTimerName(char * name); - -void StartTimer(); - -void EndTimer(); - -void PrintTimer(); - -void InitTimerList(); - -void StartTimerNo(int n); - -void EndTimerNo(int n); - -void EndTimerNoAndComp(int n, int pred); - -void PrintTimerList(); - -void InitCounter(); - -void PrintCounter(); - -#endif diff --git a/src/System.cpp b/src/System.cpp new file mode 100644 index 00000000..2b3ed372 --- /dev/null +++ b/src/System.cpp @@ -0,0 +1,837 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include +#include + +#include "SolveBoard.h" +#include "CalcTables.h" +#include "PlayAnalyser.h" +#include "parallel.h" +#include "System.h" +#include "Memory.h" +#include "Scheduler.h" +#include "ThreadMgr.h" + +extern Scheduler scheduler; +extern Memory memory; +extern ThreadMgr threadMgr; + + +const vector DDS_SYSTEM_PLATFORM = +{ + "", + "Windows", + "Cygwin", + "Linux", + "Apple" +}; + +const vector DDS_SYSTEM_COMPILER = +{ + "", + "Microsoft Visual C++", + "MinGW", + "GNU g++", + "clang" +}; + +const vector DDS_SYSTEM_CONSTRUCTOR = +{ + "", + "DllMain", + "Unix-style" +}; + +const vector DDS_SYSTEM_THREADING = +{ + "None", + "Windows", + "OpenMP", + "GCD", + "Boost", + "STL", + "TBB", + "STL-impl", + "PPL-impl" +}; + +#define DDS_SYSTEM_THREAD_BASIC 0 +#define DDS_SYSTEM_THREAD_WINAPI 1 +#define DDS_SYSTEM_THREAD_OPENMP 2 +#define DDS_SYSTEM_THREAD_GCD 3 +#define DDS_SYSTEM_THREAD_BOOST 4 +#define DDS_SYSTEM_THREAD_STL 5 +#define DDS_SYSTEM_THREAD_TBB 6 +#define DDS_SYSTEM_THREAD_STLIMPL 7 +#define DDS_SYSTEM_THREAD_PPLIMPL 8 +#define DDS_SYSTEM_THREAD_SIZE 9 + + +System::System() +{ + System::Reset(); +} + + +System::~System() +{ +} + + +void System::Reset() +{ + runCat = DDS_RUN_SOLVE; + numThreads = 1; + preferredSystem = DDS_SYSTEM_THREAD_BASIC; + + availableSystem.resize(DDS_SYSTEM_THREAD_SIZE); + availableSystem[DDS_SYSTEM_THREAD_BASIC] = true; + for (unsigned i = 1; i < DDS_SYSTEM_THREAD_SIZE; i++) + availableSystem[i] = false; + +#ifdef DDS_THREADS_WINAPI + availableSystem[DDS_SYSTEM_THREAD_WINAPI] = true; +#endif + +#ifdef DDS_THREADS_OPENMP + availableSystem[DDS_SYSTEM_THREAD_OPENMP] = true; +#endif + +#ifdef DDS_THREADS_GCD + availableSystem[DDS_SYSTEM_THREAD_GCD] = true; +#endif + +#ifdef DDS_THREADS_BOOST + availableSystem[DDS_SYSTEM_THREAD_BOOST] = true; +#endif + +#ifdef DDS_THREADS_STL + availableSystem[DDS_SYSTEM_THREAD_STL] = true; +#endif + +#ifdef DDS_THREADS_TBB + availableSystem[DDS_SYSTEM_THREAD_TBB] = true; +#endif + +#ifdef DDS_THREADS_STLIMPL + availableSystem[DDS_SYSTEM_THREAD_STLIMPL] = true; +#endif + +#ifdef DDS_THREADS_PPLIMPL + availableSystem[DDS_SYSTEM_THREAD_PPLIMPL] = true; +#endif + + // Take the first of any multi-threading system defined. + for (unsigned k = 1; k < availableSystem.size(); k++) + { + if (availableSystem[k]) + { + preferredSystem = k; + break; + } + } + + RunPtrList.resize(DDS_SYSTEM_THREAD_SIZE); + RunPtrList[DDS_SYSTEM_THREAD_BASIC] = &System::RunThreadsBasic; + RunPtrList[DDS_SYSTEM_THREAD_WINAPI] = &System::RunThreadsWinAPI; + RunPtrList[DDS_SYSTEM_THREAD_OPENMP] = &System::RunThreadsOpenMP; + RunPtrList[DDS_SYSTEM_THREAD_GCD] = &System::RunThreadsGCD; + RunPtrList[DDS_SYSTEM_THREAD_BOOST] = &System::RunThreadsBoost; + RunPtrList[DDS_SYSTEM_THREAD_STL] = &System::RunThreadsSTL; + RunPtrList[DDS_SYSTEM_THREAD_TBB] = &System::RunThreadsTBB; + RunPtrList[DDS_SYSTEM_THREAD_STLIMPL] = + &System::RunThreadsSTLIMPL; + RunPtrList[DDS_SYSTEM_THREAD_PPLIMPL] = + &System::RunThreadsPPLIMPL; + + CallbackSimpleList.resize(DDS_RUN_SIZE); + CallbackSimpleList[DDS_RUN_SOLVE] = SolveChunkCommon; + CallbackSimpleList[DDS_RUN_CALC] = CalcChunkCommon; + CallbackSimpleList[DDS_RUN_TRACE] = PlayChunkCommon; + + CallbackDuplList.resize(DDS_RUN_SIZE); + CallbackDuplList[DDS_RUN_SOLVE] = DetectSolveDuplicates; + CallbackDuplList[DDS_RUN_CALC] = DetectCalcDuplicates; + CallbackDuplList[DDS_RUN_TRACE] = DetectPlayDuplicates; + + CallbackSingleList.resize(DDS_RUN_SIZE); + CallbackSingleList[DDS_RUN_SOLVE] = SolveSingleCommon; + CallbackSingleList[DDS_RUN_CALC] = CalcSingleCommon; + CallbackSingleList[DDS_RUN_TRACE] = PlaySingleCommon; + + CallbackCopyList.resize(DDS_RUN_SIZE); + CallbackCopyList[DDS_RUN_SOLVE] = CopySolveSingle; + CallbackCopyList[DDS_RUN_CALC] = CopyCalcSingle; + CallbackCopyList[DDS_RUN_TRACE] = CopyPlaySingle; +} + + +void System::GetHardware( + int& ncores, + unsigned long long& kilobytesFree) const +{ + kilobytesFree = 0; + ncores = 1; + (void) System::GetCores(ncores); + +#if defined(_WIN32) || defined(__CYGWIN__) + // Using GlobalMemoryStatusEx instead of GlobalMemoryStatus + // was suggested by Lorne Anderson. + MEMORYSTATUSEX statex; + statex.dwLength = sizeof(statex); + GlobalMemoryStatusEx(&statex); + kilobytesFree = static_cast( + statex.ullTotalPhys / 1024); + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + ncores = static_cast(sysinfo.dwNumberOfProcessors); + return; +#endif + +#ifdef __APPLE__ + // The code for Mac OS X was suggested by Matthew Kidd. + + // This is physical memory, rather than "free" memory as below + // for Linux. Always leave 0.5 GB for the OS and other stuff. + // It would be better to find free memory (how?) but in practice + // the number of cores rather than free memory is almost certainly + // the limit for Macs which have standardized hardware (whereas + // say a 32 core Linux server is hardly unusual). + FILE * fifo = popen("sysctl -n hw.memsize", "r"); + fscanf(fifo, "%lld", &kilobytesFree); + fclose(fifo); + + kilobytesFree /= 1024; + if (kilobytesFree > 500000) + { + kilobytesFree -= 500000; + } + + ncores = sysconf(_SC_NPROCESSORS_ONLN); + return; +#endif + +#ifdef __linux__ + // The code for linux was suggested by Antony Lee. + FILE * fifo = popen( + "free -k | tail -n+3 | head -n1 | awk '{print $NF}'", "r"); + int ignore = fscanf(fifo, "%llu", &kilobytesFree); + fclose(fifo); + + ncores = sysconf(_SC_NPROCESSORS_ONLN); + return; +#endif +} + + +int System::RegisterParams( + const int nThreads, + const int mem_usable_MB) +{ + // No upper limit -- caveat emptor. + if (nThreads < 1) + return RETURN_THREAD_INDEX; + + numThreads = nThreads; + sysMem_MB = mem_usable_MB; + return RETURN_NO_FAULT; +} + + +int System::RegisterRun( + const RunMode mode, + const boards& bdsIn) +{ + if (mode >= DDS_RUN_SIZE) + return RETURN_THREAD_MISSING; // Not quite right; + + runCat = mode; + bop = &bdsIn; + return RETURN_NO_FAULT; +} + + +bool System::IsSingleThreaded() const +{ + return (preferredSystem == DDS_SYSTEM_THREAD_BASIC); +} + + +bool System::IsIMPL() const +{ + return (preferredSystem >= DDS_SYSTEM_THREAD_STLIMPL); +} + + +unsigned System::NumThreads() const +{ + return static_cast(numThreads); +} + + +bool System::ThreadOK(const int thrId) const +{ + return (thrId >= 0 && thrId < numThreads); +} + + +int System::PreferThreading(const unsigned code) +{ + if (code >= DDS_SYSTEM_THREAD_SIZE) + return RETURN_THREAD_MISSING; + + if (! availableSystem[code]) + return RETURN_THREAD_MISSING; + + preferredSystem = code; + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// Basic // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsBasic() +{ + (*fptr)(0); + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// WinAPI // +////////////////////////////////////////////////////////////////////// + +#ifdef DDS_THREADS_WINAPI +struct WinWrapType +{ + int thrId; + fptrType fptr; + HANDLE *waitPtr; +}; + +DWORD CALLBACK WinCallback(void * p); + +DWORD CALLBACK WinCallback(void * p) +{ + WinWrapType * winWrap = static_cast(p); + (*(winWrap->fptr))(winWrap->thrId); + + if (SetEvent(winWrap->waitPtr[winWrap->thrId]) == 0) + return 0; + + return 1; +} +#endif + + +int System::RunThreadsWinAPI() +{ +#ifdef DDS_THREADS_WINAPI + HANDLE * solveAllEvents = static_cast( + malloc(static_cast(numThreads) * sizeof(HANDLE))); + + for (int k = 0; k < numThreads; k++) + { + solveAllEvents[k] = CreateEvent(NULL, FALSE, FALSE, 0); + if (solveAllEvents[k] == 0) + return RETURN_THREAD_CREATE; + } + + vector winWrap; + const unsigned nt = static_cast(numThreads); + winWrap.resize(nt); + + for (unsigned k = 0; k < nt; k++) + { + winWrap[k].thrId = static_cast(k); + winWrap[k].fptr = fptr; + winWrap[k].waitPtr = solveAllEvents; + + int res = QueueUserWorkItem(WinCallback, + static_cast(&winWrap[k]), WT_EXECUTELONGFUNCTION); + if (res != 1) + return res; + } + + DWORD solveAllWaitResult; + solveAllWaitResult = WaitForMultipleObjects( + static_cast(numThreads), solveAllEvents, TRUE, INFINITE); + + if (solveAllWaitResult != WAIT_OBJECT_0) + return RETURN_THREAD_WAIT; + + for (int k = 0; k < numThreads; k++) + CloseHandle(solveAllEvents[k]); + + free(solveAllEvents); +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// OpenMP // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsOpenMP() +{ +#ifdef DDS_THREADS_OPENMP + // Added after suggestion by Dirk Willecke. + if (omp_get_dynamic()) + omp_set_dynamic(0); + + omp_set_num_threads(numThreads); + + #pragma omp parallel default(none) + { + #pragma omp for schedule(dynamic) + for (int k = 0; k < numThreads; k++) + { + int thrId = omp_get_thread_num(); + (*fptr)(thrId); + } + } +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// GCD // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsGCD() +{ +#ifdef DDS_THREADS_GCD + dispatch_apply(static_cast(numThreads), + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), + ^(size_t t) + { + int thrId = static_cast(t); + (*fptr)(thrId); + }); +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// Boost // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsBoost() +{ +#ifdef DDS_THREADS_BOOST + vector threads; + + const unsigned nu = static_cast(numThreads); + threads.resize(nu); + + for (unsigned k = 0; k < nu; k++) + threads[k] = new boost::thread(fptr, k); + + for (unsigned k = 0; k < nu; k++) + { + threads[k]->join(); + delete threads[k]; + } +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// STL // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsSTL() +{ +#ifdef DDS_THREADS_STL + vector threads; + + vector uniques; + vector crossrefs; + (* CallbackDuplList[runCat])(* bop, uniques, crossrefs); + + const unsigned nu = static_cast(numThreads); + threads.resize(nu); + + for (unsigned k = 0; k < nu; k++) + threads[k] = new thread(fptr, k); + + for (unsigned k = 0; k < nu; k++) + { + threads[k]->join(); + delete threads[k]; + } +#endif + + return RETURN_NO_FAULT; +} + + +int System::RunThreadsSTLIMPL() +{ +#ifdef DDS_THREADS_STLIMPL + vector uniques; + vector crossrefs; + (* CallbackDuplList[runCat])(* bop, uniques, crossrefs); + + static atomic thrIdNext = 0; + bool err = false; + + threadMgr.Reset(numThreads); + + for_each(std::execution::par, uniques.begin(), uniques.end(), + [&](int &bno) + { + thread_local int thrId = -1; + thread_local int realThrId; + if (thrId == -1) + thrId = thrIdNext++; + + realThrId = threadMgr.Occupy(thrId); + + if (realThrId == -1) + err = true; + else + (* CallbackSingleList[runCat])(realThrId, bno); + + if (! threadMgr.Release(thrId)) + err = true; + }); + + if (err) + { + cout << "Too many threads, numThreads " << numThreads << endl; + return RETURN_THREAD_INDEX; + } + + (* CallbackCopyList[runCat])(crossrefs); +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// TBB // +////////////////////////////////////////////////////////////////////// + +int System::RunThreadsTBB() +{ +#ifdef DDS_THREADS_TBB + vector threads; + + const unsigned nu = static_cast(numThreads); + threads.resize(nu); + + for (unsigned k = 0; k < nu; k++) + threads[k] = new tbb::tbb_thread(fptr, k); + + for (unsigned k = 0; k < nu; k++) + { + threads[k]->join(); + delete threads[k]; + } +#endif + + return RETURN_NO_FAULT; +} + + +////////////////////////////////////////////////////////////////////// +// PPL // +////////////////////////////////////////////////////////////////////// + + +int System::RunThreadsPPLIMPL() +{ +#ifdef DDS_THREADS_PPLIMPL + vector uniques; + vector crossrefs; + (* CallbackDuplList[runCat])(* bop, uniques, crossrefs); + + static atomic thrIdNext = 0; + bool err = false; + + threadMgr.Reset(numThreads); + + using namespace Concurrency; + Concurrency::Scheduler * sched = Concurrency::Scheduler::Create( + SchedulerPolicy(1, MaxConcurrency, numThreads)); + sched->Attach(); + + Concurrency::parallel_for_each(uniques.begin(), uniques.end(), + [&](int &bno) + { + thread_local int thrId = -1; + thread_local int realThrId; + if (thrId == -1) + thrId = thrIdNext++; + + realThrId = threadMgr.Occupy(thrId); + + if (realThrId == -1) + err = true; + else + (* CallbackSingleList[runCat])(realThrId, bno); + + if (! threadMgr.Release(thrId)) + err = true; + }); + + CurrentScheduler::Detach(); + sched->Release(); + + if (err) + { + cout << "Too many threads, numThreads " << numThreads << endl; + return RETURN_THREAD_INDEX; + } + + (* CallbackCopyList[runCat])(crossrefs); +#endif + + return RETURN_NO_FAULT; +} + + + +int System::RunThreads() +{ + fptr = CallbackSimpleList[runCat]; + + return (this->*RunPtrList[preferredSystem])(); +} + + +////////////////////////////////////////////////////////////////////// +// Self-identification // +////////////////////////////////////////////////////////////////////// + +string System::GetVersion( + int& major, + int& minor, + int& patch) const +{ + major = DDS_VERSION / 10000; + minor = (DDS_VERSION - major * 10000) / 100; + patch = DDS_VERSION % 100; + + string st = to_string(major) + "." + to_string(minor) + + "." + to_string(patch); + return st; +} + + +string System::GetSystem(int& sys) const +{ +#if defined(_WIN32) + sys = 1; +#elif defined(__CYGWIN__) + sys = 2; +#elif defined(__linux) + sys = 3; +#elif defined(__APPLE__) + sys = 4; +#else + sys = 0; +#endif + + return DDS_SYSTEM_PLATFORM[static_cast(sys)]; +} + + +string System::GetBits(int& bits) const +{ +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) +#endif + + string st; + if (sizeof(void *) == 4) + { + bits = 32; + st = "32 bits"; + } + else if (sizeof(void *) == 8) + { + bits = 64; + st = "64 bits"; + } + else + { + bits = 0; + st = "unknown"; + } +#ifdef _MSC_VER + #pragma warning(pop) +#endif + + return st; +} + + +string System::GetCompiler(int& comp) const +{ +#if defined(_MSC_VER) + comp = 1; +#elif defined(__MINGW32__) + comp = 2; +#elif defined(__clang__) + comp = 4; // Out-of-order on purpose +#elif defined(__GNUC__) + comp = 3; +#else + comp = 0; +#endif + + return DDS_SYSTEM_COMPILER[static_cast(comp)]; +} + + +string System::GetConstructor(int& cons) const +{ +#if defined(USES_DLLMAIN) + cons = 1; +#elif defined(USES_CONSTRUCTOR) + cons = 2; +#else + cons = 0; +#endif + + return DDS_SYSTEM_CONSTRUCTOR[static_cast(cons)]; +} + + +string System::GetCores(int& cores) const +{ +#if defined(_WIN32) || defined(__CYGWIN__) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + cores = static_cast(sysinfo.dwNumberOfProcessors); +#elif defined(__APPLE__) || defined(__linux__) + cores = sysconf(_SC_NPROCESSORS_ONLN); +#endif + + // TODO Think about thread::hardware_concurrency(). + // This should be standard in C++11. + + return to_string(cores); +} + + +string System::GetThreading(int& thr) const +{ + string st = ""; + thr = 0; + for (unsigned k = 0; k < DDS_SYSTEM_THREAD_SIZE; k++) + { + if (availableSystem[k]) + { + st += " " + DDS_SYSTEM_THREADING[k]; + if (k == preferredSystem) + { + st += "(*)"; + thr = static_cast(k); + } + } + } + return st; +} + + +string System::GetThreadSizes(char * sizes) const +{ + int l = 0, s = 0; + for (unsigned i = 0; i < static_cast(numThreads); i++) + { + if (memory.ThreadSize(i) == "S") + s++; + else + l++; + } + + const string st = to_string(s) + " S, " + to_string(l) + " L"; + strcpy(sizes, st.c_str()); + return st; +} + + +string System::str(DDSInfo * info) const +{ + stringstream ss; + ss << "DDS DLL\n-------\n"; + + const string strSystem = System::GetSystem(info->system); + ss << left << setw(13) << "System" << + setw(20) << right << strSystem << "\n"; + + const string strBits = System::GetBits(info->numBits); + ss << left << setw(13) << "Word size" << + setw(20) << right << strBits << "\n"; + + const string strCompiler = System::GetCompiler(info->compiler); + ss << left << setw(13) << "Compiler" << + setw(20) << right << strCompiler << "\n"; + + const string strConstructor = System::GetConstructor(info->constructor); + ss << left << setw(13) << "Constructor" << + setw(20) << right << strConstructor << "\n"; + + const string strVersion = System::GetVersion(info->major, + info->minor, info->patch); + ss << left << setw(13) << "Version" << + setw(20) << right << strVersion << "\n"; + strcpy(info->versionString, strVersion.c_str()); + + ss << left << setw(17) << "Memory max (MB)" << + setw(16) << right << sysMem_MB << "\n"; + + const string stm = to_string(THREADMEM_SMALL_DEF_MB) + "-" + + to_string(THREADMEM_SMALL_MAX_MB) + " / " + + to_string(THREADMEM_LARGE_DEF_MB) + "-" + + to_string(THREADMEM_LARGE_MAX_MB); + ss << left << setw(17) << "Threads (MB)" << + setw(16) << right << stm << "\n"; + + System::GetCores(info->numCores); + ss << left << setw(17) << "Number of cores" << + setw(16) << right << info->numCores << "\n"; + + info->noOfThreads = numThreads; + ss << left << setw(17) << "Number of threads" << + setw(16) << right << numThreads << "\n"; + + const string strThrSizes = System::GetThreadSizes(info->threadSizes); + ss << left << setw(13) << "Thread sizes" << + setw(20) << right << strThrSizes << "\n"; + + const string strThreading = System::GetThreading(info->threading); + ss << left << setw(9) << "Threading" << + setw(24) << right << strThreading << "\n"; + + const string st = ss.str(); + strcpy(info->systemString, st.c_str()); + return st; +} + diff --git a/src/System.h b/src/System.h new file mode 100644 index 00000000..fd7e8fcc --- /dev/null +++ b/src/System.h @@ -0,0 +1,116 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_SYSTEM_H +#define DDS_SYSTEM_H + +/* + This class encapsulates all the system-dependent stuff. + */ + +#include +#include + +#include "dds.h" + +using namespace std; + +typedef void (*fptrType)(const int thid); +typedef void (*fduplType)( + const boards& bds, vector& uniques, vector& crossrefs); +typedef void (*fsingleType)(const int thid, const int bno); +typedef void (*fcopyType)(const vector& crossrefs); + + +class System +{ + private: + + RunMode runCat; // SOLVE / CALC / PLAY + + int numThreads; + int sysMem_MB; + int thrDef_MB; + int thrMax_MB; + + unsigned preferredSystem; + + vector availableSystem; + + vector CallbackSimpleList; + vector CallbackDuplList; + vector CallbackSingleList; + vector CallbackCopyList; + + typedef int (System::*RunPtr)(); + vector RunPtrList; + + fptrType fptr; + + boards const * bop; + + int RunThreadsBasic(); + int RunThreadsBoost(); + int RunThreadsOpenMP(); + int RunThreadsGCD(); + int RunThreadsWinAPI(); + int RunThreadsSTL(); + int RunThreadsTBB(); + int RunThreadsSTLIMPL(); + int RunThreadsPPLIMPL(); + + string GetVersion( + int& major, + int& minor, + int& patch) const; + string GetSystem(int& sys) const; + string GetBits(int& bits) const; + string GetCompiler(int& comp) const; + string GetCores(int& comp) const; + string GetConstructor(int& cons) const; + string GetThreading(int& thr) const; + string GetThreadSizes(char * c) const; + + + public: + System(); + + ~System(); + + void Reset(); + + int RegisterParams( + const int nThreads, + const int mem_usable_MB); + + int RegisterRun( + const RunMode r, + const boards& bop); + + bool IsSingleThreaded() const; + + bool IsIMPL() const; + + unsigned NumThreads() const; + + bool ThreadOK(const int thrId) const; + + void GetHardware( + int& ncores, + unsigned long long& kilobytesFree) const; + + int PreferThreading(const unsigned code); + + int RunThreads(); + + string str(DDSInfo * info) const; +}; + +#endif + diff --git a/src/ThreadMgr.cpp b/src/ThreadMgr.cpp new file mode 100644 index 00000000..d922ad23 --- /dev/null +++ b/src/ThreadMgr.cpp @@ -0,0 +1,155 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "ThreadMgr.h" + +mutex mtx; +mutex mtxPrint; + + +ThreadMgr::ThreadMgr() +{ + numRealThreads = 0; + numMachineThreads = 0; +} + + +ThreadMgr::~ThreadMgr() +{ +} + + +void ThreadMgr::Reset(const int nThreads) +{ + if (nThreads > numRealThreads) + { + realThreads.resize(nThreads); + for (int t = numRealThreads; t < nThreads; t++) + realThreads[t] = false; + numRealThreads = nThreads; + } + + if (nThreads > numMachineThreads) + { + machineThreads.resize(nThreads); + for (int t = numMachineThreads; t < nThreads; t++) + machineThreads[t] = -1; + numMachineThreads = nThreads; + } +} + + +int ThreadMgr::Occupy(const int machineId) +{ + if (machineId >= numMachineThreads) + { + numMachineThreads = machineId + 1; + machineThreads.resize(numMachineThreads); + for (int t = machineId; t < numMachineThreads; t++) + machineThreads[t] = -1; + } + + if (machineThreads[machineId] != -1) + { + // Error: Already in use. + return -1; + } + + int res = -1; + + do + { + mtx.lock(); + for (int t = 0; t < numRealThreads; t++) + { + if (realThreads[t] == false) + { + realThreads[t] = true; + machineThreads[machineId] = t; + res = t; + break; + } + } + // ThreadMgr::Print("thr.txt", "In Occupy " + + // to_string(machineId) + " " + to_string(res)); + mtx.unlock(); + + if (res == -1) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } + while (res == -1); + + return res; +} + + +bool ThreadMgr::Release(const int machineId) +{ + const int r = machineThreads[machineId]; + if (r == -1) + { + // Error: Not in use. + return false; + } + + if (! realThreads[r]) + { + // Error: Refers to a real thread that is not in use. + return false; + } + + mtx.lock(); + realThreads[r] = false; + machineThreads[machineId] = -1; + mtx.unlock(); + return true; +} + + +void ThreadMgr::Print( + const string& fname, + const string& tag) const +{ + mtxPrint.lock(); + ofstream fo; + fo.open(fname, std::ios_base::app); + + fo << tag << + ": Real threads occupied (out of " << numRealThreads << "):\n"; + for (int t = 0; t < numRealThreads; t++) + { + if (realThreads[t]) + fo << t << endl; + } + fo << endl; + + fo << "Machine threads overview:\n"; + for (int t = 0; t < numMachineThreads; t++) + { + if (machineThreads[t] != -1) + { + fo << setw(4) << left << t << machineThreads[t] << endl; + } + } + fo << endl; + fo.close(); + mtxPrint.unlock(); +} + diff --git a/src/ThreadMgr.h b/src/ThreadMgr.h new file mode 100644 index 00000000..f9c595ff --- /dev/null +++ b/src/ThreadMgr.h @@ -0,0 +1,44 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_THREADMGR_H +#define DDS_THREADMGR_H + +#include + +using namespace std; + + +class ThreadMgr +{ + private: + + vector realThreads; + vector machineThreads; + int numRealThreads; + int numMachineThreads; + + public: + + ThreadMgr(); + + ~ThreadMgr(); + + void Reset(const int nThreads); + + int Occupy(const int MachineThrId); + + bool Release(const int MachineThrId); + + void Print( + const string& fname, + const string& tag) const; +}; + +#endif diff --git a/src/TimeStat.cpp b/src/TimeStat.cpp new file mode 100644 index 00000000..ff15b08e --- /dev/null +++ b/src/TimeStat.cpp @@ -0,0 +1,100 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include +#include + +#include "TimeStat.h" + + +TimeStat::TimeStat() +{ + TimeStat::Reset(); +} + + +TimeStat::~TimeStat() +{ +} + + +void TimeStat::Reset() +{ + number = 0; + cum = 0; + cumsq = 0.; +} + + +void TimeStat::Set(const int timeUser) +{ + number = 1; + cum = timeUser; + cumsq = static_cast(timeUser) * static_cast(timeUser); +} + + +void TimeStat::Set( + const int timeUser, + const double timesq) +{ + number = 1; + cum = timeUser; + cumsq = timesq; +} + + +void TimeStat::operator +=(const TimeStat& add) +{ + number += add.number; + cum += add.cum; + cumsq += add.cumsq; +} + + +bool TimeStat::Used() const +{ + return (number > 0); +} + +string TimeStat::Header() const +{ + stringstream ss; + ss << setw(5) << right << "n" << + setw(9) << right << "Number" << + setw(13) << "Cum time" << + setw(13) << "Average" << + setw(13) << "Sdev" << + setw(13) << "Sdev/mu" << "\n"; + + return ss.str(); +} + + +string TimeStat::Line() const +{ + if (number == 0) + return ""; + + double avg = static_cast(cum) / static_cast(number); + double arg = (cumsq / static_cast(number)) - avg * avg; + double sdev = (arg >= 0. ? sqrt(arg) : 0.); + + stringstream ss; + ss << setw(9) << right << number << + setw(13) << cum << + setw(13) << setprecision(0) << fixed << avg << + setw(13) << setprecision(0) << fixed << sdev << + setw(13) << setprecision(2) << fixed << sdev/avg << "\n"; + + return ss.str(); +} diff --git a/src/TimeStat.h b/src/TimeStat.h new file mode 100644 index 00000000..0a3b630a --- /dev/null +++ b/src/TimeStat.h @@ -0,0 +1,47 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_TIMESTAT_H +#define DDS_TIMESTAT_H + +#include + +using namespace std; + + +class TimeStat +{ + private: + + int number; + long long cum; + double cumsq; + + public: + + TimeStat(); + + ~TimeStat(); + + void Reset(); + + void Set(const int timeUser); + void Set( + const int timeUser, + const double timesq); + + void operator += (const TimeStat& add); + + bool Used() const; + + string Header() const; + string Line() const; +}; + +#endif diff --git a/src/TimeStatList.cpp b/src/TimeStatList.cpp new file mode 100644 index 00000000..6a60c5f4 --- /dev/null +++ b/src/TimeStatList.cpp @@ -0,0 +1,85 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include + +#include "TimeStatList.h" + + +TimeStatList::TimeStatList() +{ + TimeStatList::Reset(); +} + + +TimeStatList::~TimeStatList() +{ +} + + +void TimeStatList::Reset() +{ +} + + +void TimeStatList::Init( + const string& tname, + const unsigned len) +{ + name = tname; + list.resize(len); +} + + +void TimeStatList::Add( + const unsigned pos, + const TimeStat& add) +{ + list[pos] += add; +} + + +bool TimeStatList::Used() const +{ + for (unsigned i = 0; i < list.size(); i++) + { + if (list[i].Used()) + return true; + } + return false; +} + + +string TimeStatList::List() const +{ + if (! TimeStatList::Used()) + return ""; + + stringstream ss; + ss << name << "\n\n"; + ss << list[0].Header(); + + TimeStat tsum; + for (unsigned i = 0; i < list.size(); i++) + { + if (! list[i].Used()) + continue; + + tsum += list[i]; + ss << setw(5) << right << i << list[i].Line(); + } + + ss << setw(5) << right << "Avg" << tsum.Line() << "\n"; + + return ss.str(); +} + diff --git a/src/TimeStatList.h b/src/TimeStatList.h new file mode 100644 index 00000000..53bb20c7 --- /dev/null +++ b/src/TimeStatList.h @@ -0,0 +1,50 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_TIMESTATLIST_H +#define DDS_TIMESTATLIST_H + +#include +#include + +#include "TimeStat.h" + +using namespace std; + + +class TimeStatList +{ + private: + + vector list; + + string name; + + public: + + TimeStatList(); + + ~TimeStatList(); + + void Reset(); + + void Init( + const string& tname, + const unsigned len); + + void Add( + const unsigned pos, + const TimeStat& add); + + bool Used() const; + + string List() const; +}; + +#endif diff --git a/src/Timer.cpp b/src/Timer.cpp index 94312ff8..f6ee618e 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -2,35 +2,20 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -/* - See Timer.h for some description. -*/ - -#include +#include +#include +#include -#include "dds.h" #include "Timer.h" - -const char * TIMER_NAMES[TIMER_GROUPS] = -{ - "AB", - "Make", - "Undo", - "Evaluate", - "NextMove", - "QuickTricks", - "LaterTricks", - "MoveGen", - "Lookup", - "Build" -}; +using std::chrono::duration_cast; +using std::chrono::microseconds; Timer::Timer() @@ -41,347 +26,129 @@ Timer::Timer() Timer::~Timer() { - if (fp != stdout && fp != nullptr) - fclose(fp); } void Timer::Reset() { - strcpy(fname, ""); - - for (int i = 0; i < DDS_TIMERS; i++) - { - sprintf(name[i], "Timer %4d", i); - count[i] = 0; - userCum[i] = 0; - systCum[i] = 0.; - } + name = ""; + count = 0; + userCum = 0; + systCum = 0; } -void Timer::SetFile(char * ourFname) +void Timer::SetName(const string& nameIn) { - if (strlen(ourFname) > DDS_FNAME_LEN) - return; - - strncpy(fname, ourFname, strlen(ourFname)); - - fp = fopen(fname, "w"); - if (!fp) - fp = stdout; + name = nameIn; } -void Timer::SetName(int no, char * ourName) +void Timer::Start() { - if (no < 0 || no >= DDS_TIMERS) - return; - - sprintf(name[no], "%s", ourName); + user0 = Clock::now(); + syst0 = clock(); } -void Timer::SetNames() +void Timer::End() { - char tag[LINE_LEN]; + time_point user1 = Clock::now(); + clock_t syst1 = clock(); - for (int d = 0; d < TIMER_SPACING; d++) - { - int c = d % 4; - sprintf(tag, "AB%d %d", c, d); - Timer::SetName(TIMER_AB + d, tag); - - for (int n = 1; n < TIMER_GROUPS; n++) - { - sprintf(tag, "%s %d", TIMER_NAMES[n], d); - Timer::SetName(n * TIMER_SPACING + d, tag); - } - } -} - -void Timer::Start(int no) -{ - if (no < 0 || no >= DDS_TIMERS) - return; + chrono::duration d = user1 - user0; + int tuser = static_cast(d.count()); - systTimes0[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&userTimes0[no]); -#else - gettimeofday(&userTimes0[no], nullptr); -#endif + count++; + userCum += tuser; + systCum += static_cast(syst1) - + static_cast(syst0); } -void Timer::End(int no) +bool Timer::Used() const { - if (no < 0 || no >= DDS_TIMERS) - return; - - systTimes1[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&userTimes1[no]); - int timeUser = static_cast - (userTimes1[no].QuadPart - userTimes0[no].QuadPart); -#else - gettimeofday(&userTimes1[no], nullptr); - int timeUser = Timer::TimevalDiff(userTimes1[no], - userTimes0[no]); -#endif - - count[no]++; - - // This is more or less in milli-seconds except on Windows, - // where it is in "wall ticks". It is possible to convert - // to milli-seconds, but the resolution is so poor for fast - // functions that I leave it in integer form. - - userCum[no] += timeUser; - systCum[no] += systTimes1[no] - systTimes0[no]; + return (count > 0); } -void Timer::OutputDetails() +int Timer::UserTime() const { - fprintf(fp, "%-14s %10s %10s %10s %10s %10s\n", - "Name", - "Number", - "User ticks", - "Avg", - "System", - "Avg ms"); - - for (int no = 0; no < DDS_TIMERS; no++) - { - if (count[no] == 0) - continue; - - fprintf(fp, "%-14s %10d %10lld %10.2f %10.0f %10.2f\n", - name[no], - count[no], - static_cast(userCum[no]), - static_cast(userCum[no]) / - static_cast(count[no]), - 1000. * systCum[no], - 1000. * static_cast(systCum[no]) / - static_cast(count[no])); - } - fprintf(fp, "\n"); + return static_cast(userCum); } -void Timer::PrintStats() +void Timer::operator +=(const Timer& add) { - bool used = false; - for (int no = 0; no < DDS_TIMERS; no++) - { - if (count[no]) - { - used = true; - break; - } - } - - if (! used) - return; - - // Approximate the exclusive times of each function. - // The ABsearch*() functions are recursively nested, - // so subtract out the one below. - // The other ones are subtracted out based on knowledge - // of the functions. + count += add.count; + userCum += add.userCum; + systCum += add.systCum; +} - int64_t AB_userCum[TIMER_SPACING]; - double AB_systCum[TIMER_SPACING]; - AB_userCum[0] = userCum[0]; - AB_systCum[0] = systCum[0]; +void Timer::operator -=(const Timer& deduct) +{ + if (deduct.userCum > userCum) + userCum = 0; + else + userCum -= deduct.userCum; - int64_t AB_ct = count[0]; - int64_t AB_ucum = AB_userCum[0]; - double AB_scum = AB_systCum[0]; + if (deduct.systCum > systCum) + systCum = 0; + else + systCum -= deduct.systCum; +} - for (int d = 1; d < TIMER_SPACING; d++) - { - AB_ct += count[d]; - - if (userCum[d - 1] > userCum[d]) - { - AB_userCum[d] = 0; - AB_systCum[d] = 0; - continue; - } - - AB_userCum[d] = userCum[d] - userCum[d - 1]; - AB_systCum[d] = systCum[d] - systCum[d - 1]; - - for (int no = 1; no < TIMER_GROUPS; no++) - { - int offset = no * TIMER_SPACING; - AB_userCum[d] -= userCum[offset + d ]; - AB_systCum[d] -= systCum[offset + d ]; - } - - AB_ucum += AB_userCum[d]; - AB_scum += AB_systCum[d]; - } - int64_t all_ucum = AB_ucum; - double all_scum = AB_scum; - for (int no = TIMER_SPACING; no < DDS_TIMERS; no++) - { - all_ucum += userCum[no]; - all_scum += systCum[no]; - } - - fprintf(fp, "%-14s %8s %10s %6s %4s %10s %6s %4s\n", - "Name", - "Count", - "User", - "Avg", - "%", - "Syst", - "Avg", - "%"); - - if (AB_ct) +string Timer::SumLine( + const Timer& divisor, + const string& bname) const +{ + stringstream ss; + if (count > 0) { - fprintf(fp, "%-14s %8lld %10lld %6.2f %4.1f %10.0f %6.2f %4.1f\n", - TIMER_NAMES[0], - static_cast(AB_ct), - static_cast(AB_ucum), - AB_ucum / static_cast(AB_ct), - 100. * AB_ucum / all_ucum, - 1000. * AB_scum, - 1000. * AB_scum / static_cast(AB_ct), - 100. * AB_scum / all_scum); + ss << setw(14) << left << (bname == "" ? name : bname) << + setw(9) << right << count << + setw(11) << userCum << + setw(7) << setprecision(2) << fixed << + userCum / static_cast(count) << + setw(5) << setprecision(1) << fixed << + 100. * userCum / divisor.userCum << + setw(11) << setprecision(0) << fixed << + 1000000 * systCum / static_cast(CLOCKS_PER_SEC) << + setw(7) << setprecision(2) << fixed << + 1000000 * systCum / static_cast(count * CLOCKS_PER_SEC) << + setw(5) << setprecision(1) << fixed << + 100. * systCum / divisor.systCum << "\n"; } else { - fprintf(fp, "%-14s %8lld %10lld %6s %4s %10.0f %6s %4s\n", - TIMER_NAMES[0], - static_cast(AB_ct), - static_cast(AB_ucum), - "-", - "-", - 1000. * AB_scum, - "-", - "-"); + ss << setw(14) << left << (bname == "" ? name : bname) << + setw(9) << right << count << + setw(11) << userCum << + setw(7) << "-" << + setw(5) << "-" << + setw(11) << 1000000 * systCum / static_cast(CLOCKS_PER_SEC) << + setw(7) << "-" << + setw(5) << "-" << "\n"; } - - int64_t ct[TIMER_GROUPS]; - for (int no = 1; no < TIMER_GROUPS; no++) - { - int offset = no * TIMER_SPACING; - - int64_t ucum = 0; - double scum = 0; - ct[no] = 0; - - for (int d = 0; d < TIMER_SPACING; d++) - { - ct[no] += count[offset + d]; - ucum += userCum[offset + d]; - scum += systCum[offset + d]; - } - - if (ct[no]) - { - fprintf(fp, "%-14s %8lld %10lld %6.2f %4.1f %10.0f %6.2f %4.1f\n", - TIMER_NAMES[no], - static_cast(ct[no]), - static_cast(ucum), - ucum / static_cast(ct[no]), - 100. * ucum / all_ucum, - 1000. * scum, - 1000. * scum / static_cast(ct[no]), - 100. * scum / all_scum); - } - else - { - fprintf(fp, "%-14s %8lld %10lld %6s %4s %10.0f %6s %4s\n", - TIMER_NAMES[no], - static_cast(ct[no]), - static_cast(ucum), - "-", - "-", - 1000. * scum, - "-", - "-"); - } - } - fprintf(fp, "----------------------------------"); - fprintf(fp, "-----------------------------------\n"); - fprintf(fp, "%-14s %8s %10lld %6s %4s %10.0f\n\n\n", - "Sum", - "", - static_cast(all_ucum), - "", - "", - 1000. * all_scum); - - // This doesn't work properly yet. The issue is that on some - // loops there is no success, and in that case we have to try - // all moves to see this. But no move ordering could have done - // better. So we need to know the proportion for the successes - // only. This probably becomes more natural when there is a Move - // object. It doesn't really belong in Timer anyway. - - //double genMoves = ct[TIMER_NO_MOVEGEN] + ct[TIMER_NO_NEXTMOVE]; - //if (genMoves) - //fprintf(fp, "Move generation quality %.1f%%\n\n\n", - //100. * (1. - ct[TIMER_NO_MAKE] / genMoves)); - - if (AB_ucum > 0. && AB_scum > 0.) - { - fprintf(fp, "%-14s %8s %10s %6s %4s %10s %6s %4s\n", - "Name", - "Count", - "User", - "Avg", - "%", - "Syst", - "Avg", - "%"); - - for (int no = TIMER_SPACING - 1; no >= 0; no--) - { - if (count[no] == 0) - continue; - - fprintf(fp, "%-14s %8d %10lld %6.2f %4.1f %10.0f %6.2f %4.1f\n", - name[TIMER_AB + no], - count[no], - static_cast(AB_userCum[no]), - AB_userCum[no] / static_cast(count[no]), - 100. * AB_userCum[no] / AB_ucum, - 1000. * AB_systCum[no], - 1000. * AB_systCum[no] / static_cast(count[no]), - 100. * AB_systCum[no] / static_cast(AB_scum)); - - } - fprintf(fp, "----------------------------------"); - fprintf(fp, "-----------------------------------\n"); - fprintf(fp, "%-14s %8lld %10lld %6s %4s %10.0f\n\n\n", - "Sum", - static_cast(AB_ct), - static_cast(AB_ucum), - "", - "", - 1000. * AB_scum); - } - -#ifdef DDS_TIMING_DETAILS - Timer::OutputDetails(); -#endif + return ss.str(); } -int Timer::TimevalDiff(timeval x, timeval y) +string Timer::DetailLine() const { - return 1000 * (x.tv_sec - y.tv_sec ) - + (x.tv_usec - y.tv_usec) / 1000; + stringstream ss; + ss << setw(15) << left << name << + setw(10) << right << count << + setw(11) << right << userCum << + setw(11) << setprecision(2) << fixed << + userCum / static_cast(count) << + setw(11) << setprecision(0) << fixed << + 1000000 * systCum / static_cast(CLOCKS_PER_SEC) << + setw(11) << setprecision(2) << fixed << + 1000000 * systCum / + static_cast(count * CLOCKS_PER_SEC) << "\n"; + + return ss.str(); } diff --git a/src/Timer.h b/src/Timer.h index b54a2d27..31ac9385 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,129 +10,54 @@ #ifndef DDS_TIMING_H #define DDS_TIMING_H -/* - It is a simple object for timing functions or code pieces. - As it stands, it is somewhat specific to AB searches, - but it can of course be generalized. - - There are groups of 50 timers. - - Each group corresponds to something that should be timed at - multiple AB depths, i.e. cards played. The first card of a - new game is number 48, and the last card is number 0. - - The AB timer is special, as the AB functions are recursive - and so their timing includes not only the other functions they - contain, but also their own recursive calls at lower depths. - The AB timer group must be the first one. - - The object calculates an approximation to exclusive function - times, so it is a "poor man's profiler". - - For AB, first the times at depth-1 are subtracted out, and then - the times for all calls at the same depth are subtracted out. - This still leaves the overhead of the timing itself. As an - approximation, there is one timing overhead left for each - function, and it is on the order of the execution time of - Evaluate(), which is a very fast function. - */ - - -#include -#include -#include -#include - -#ifdef _WIN32 - #include -#else - #include -#endif - -/* - TIMER_START and TIMER_END are macros for bracketing code - to be timed, so +#include +#include - TIMER_START(TIMER_AB + depth); - ABsearch(...); - TIMER_END; +using Clock = std::chrono::steady_clock; +using std::chrono::time_point; - This avoid the tedious #ifdef's at every place of a timer. -*/ - -#ifdef DDS_TIMING - #define TIMER_START(a) thrp->timer.Start(a) - #define TIMER_END(a) thrp->timer.End(a) -#else - #define TIMER_START(a) 1 - #define TIMER_END(a) 1 -#endif - -#define LINE_LEN 20 -#define TIMER_SPACING 50 -#define TIMER_GROUPS 10 - -#define TIMER_NO_AB 0 -#define TIMER_NO_MAKE 1 -#define TIMER_NO_UNDO 2 -#define TIMER_NO_EVALUATE 3 -#define TIMER_NO_NEXTMOVE 4 -#define TIMER_NO_QT 5 -#define TIMER_NO_LT 6 -#define TIMER_NO_MOVEGEN 7 -#define TIMER_NO_LOOKUP 8 -#define TIMER_NO_BUILD 9 - -#define TIMER_AB TIMER_NO_AB -#define TIMER_MAKE ( TIMER_NO_MAKE * TIMER_SPACING) -#define TIMER_UNDO ( TIMER_NO_UNDO * TIMER_SPACING) -#define TIMER_EVALUATE ( TIMER_NO_EVALUATE * TIMER_SPACING) -#define TIMER_NEXTMOVE ( TIMER_NO_NEXTMOVE * TIMER_SPACING) -#define TIMER_QT ( TIMER_NO_QT * TIMER_SPACING) -#define TIMER_LT ( TIMER_NO_LT * TIMER_SPACING) -#define TIMER_MOVEGEN ( TIMER_NO_MOVEGEN * TIMER_SPACING) -#define TIMER_LOOKUP ( TIMER_NO_LOOKUP * TIMER_SPACING) -#define TIMER_BUILD ( TIMER_NO_BUILD * TIMER_SPACING) - -#define DDS_TIMERS (TIMER_GROUPS * TIMER_SPACING) +using namespace std; class Timer { private: - FILE * fp; - char fname[DDS_FNAME_LEN]; - char name[DDS_TIMERS][LINE_LEN]; - - clock_t systTimes0[DDS_TIMERS]; - clock_t systTimes1[DDS_TIMERS]; - -#ifdef _WIN32 - LARGE_INTEGER userTimes0[DDS_TIMERS]; - LARGE_INTEGER userTimes1[DDS_TIMERS]; -#else - timeval userTimes0[DDS_TIMERS], - userTimes1[DDS_TIMERS]; -#endif - int count[DDS_TIMERS]; - int64_t userCum[DDS_TIMERS]; - double systCum[DDS_TIMERS]; + string name; + int count; + long userCum; + long systCum; - void OutputStats(char * t); - int TimevalDiff(timeval x, timeval y); - void OutputDetails(); + time_point user0; + clock_t syst0; public: + Timer(); + ~Timer(); + void Reset(); - void SetFile(char * fname); - void SetName(int no, char * name); - void SetNames(); - void Start(int no); - void End(int no); - void PrintStats(); + + void SetName(const string& nameIn); + + void Start(); + + void End(); + + bool Used() const; + + int UserTime() const; + + void operator += (const Timer& add); + + void operator -= (const Timer& deduct); + + string SumLine( + const Timer& divisor, + const string& bname = "") const; + + string DetailLine() const; }; #endif diff --git a/src/TimerGroup.cpp b/src/TimerGroup.cpp new file mode 100644 index 00000000..dbc7a4f4 --- /dev/null +++ b/src/TimerGroup.cpp @@ -0,0 +1,177 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#define TIMER_DEPTH 50 + +#include +#include +#include + +#include "TimerGroup.h" + + +TimerGroup::TimerGroup() +{ + TimerGroup::Reset(); +} + + +TimerGroup::~TimerGroup() +{ +} + + +void TimerGroup::Reset() +{ + timers.resize(TIMER_DEPTH); + for (unsigned i = 0; i < timers.size(); i++) + timers[i].Reset(); +} + + +void TimerGroup::SetNames(const string& baseName) +{ + string st; + if (baseName == "AB") + { + // Special format emphasizing the card number within the trick. + for (unsigned i = 0; i < timers.size(); i++) + { + st = baseName + to_string(i % 4) + " " + to_string(i); + timers[i].SetName(st); + } + } + else + { + for (unsigned i = 0; i < timers.size(); i++) + { + st = baseName + to_string(i); + timers[i].SetName(st); + } + } + bname = baseName; +} + + +void TimerGroup::Start(const unsigned no) +{ + timers[no].Start(); +} + + +void TimerGroup::End(const unsigned no) +{ + timers[no].End(); +} + + +bool TimerGroup::Used() const +{ + for (unsigned i = 0; i < timers.size(); i++) + { + if (timers[i].Used()) + return true; + } + return false; +} + + +void TimerGroup::Differentiate() +{ + for (unsigned r = 0; r < timers.size()-1; r++) + { + unsigned i = timers.size() - 1 - r; + timers[i] -= timers[i-1]; + } +} + + +void TimerGroup::Sum(Timer& sum) const +{ + sum = timers[0]; + for (unsigned i = 1; i < timers.size(); i++) + sum += timers[i]; +} + + +void TimerGroup::operator -= (const TimerGroup& deduct) +{ + for (unsigned i = 0; i < timers.size(); i++) + timers[i] -= deduct.timers[i]; +} + + +string TimerGroup::Header() const +{ + stringstream ss; + ss << setw(14) << left << "Name" << + setw(9) << right << "Count" << + setw(11) << "User" << + setw(7) << "Avg" << + setw(5) << "%" << + setw(11) << "Syst" << + setw(7) << "Avg" << + setw(5) << "%" << "\n"; + return ss.str(); +} + + +string TimerGroup::DetailHeader() const +{ + stringstream ss; + ss << setw(14) << left << "Name " << + setw(11) << right << "Number" << + setw(11) << "User ticks" << + setw(11) << "Avg" << + setw(11) << "System" << + setw(11) << "Avg ms" << "\n"; + return ss.str(); +} + + +string TimerGroup::SumLine(const Timer& sumTotal) const +{ + Timer ownSum; + TimerGroup::Sum(ownSum); + + return ownSum.SumLine(sumTotal, bname); +} + + +string TimerGroup::TimerLines(const Timer& sumTotal) const +{ + string st = ""; + for (unsigned r = 0; r < timers.size(); r++) + { + unsigned i = timers.size() - r - 1; + if (timers[i].Used()) + st += timers[i].SumLine(sumTotal); + } + return st; +} + + +string TimerGroup::DetailLines() const +{ + stringstream ss; + for (unsigned i = 0; i < timers.size(); i++) + { + if (timers[i].Used()) + ss << timers[i].DetailLine(); + } + + return ss.str(); +} + + +string TimerGroup::DashLine() const +{ + return string(69, '-') + "\n"; +} + diff --git a/src/TimerGroup.h b/src/TimerGroup.h new file mode 100644 index 00000000..ef94c45b --- /dev/null +++ b/src/TimerGroup.h @@ -0,0 +1,58 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_TIMERGROUP_H +#define DDS_TIMERGROUP_H + +#include +#include + +#include "Timer.h" + +using namespace std; + + +class TimerGroup +{ + private: + + vector timers; + string bname; + + public: + + TimerGroup(); + + ~TimerGroup(); + + void Reset(); + + void SetNames(const string& baseName); + + void Start(const unsigned no); + + void End(const unsigned no); + + bool Used() const; + + void Differentiate(); + + void Sum(Timer& sum) const; + + void operator -= (const TimerGroup& deduct); + + string Header() const; + string DetailHeader() const; + string SumLine(const Timer& sumTotal) const; + string TimerLines(const Timer& sumTotal) const; + string DetailLines() const; + string DashLine() const; +}; + +#endif diff --git a/src/TimerList.cpp b/src/TimerList.cpp new file mode 100644 index 00000000..1722ff57 --- /dev/null +++ b/src/TimerList.cpp @@ -0,0 +1,132 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +/* + See TimerList.h for some description. +*/ + +// #include + +// #include "dds.h" +#include "TimerList.h" + + +TimerList::TimerList() +{ + TimerList::Reset(); +} + + +TimerList::~TimerList() +{ +} + + +void TimerList::Reset() +{ + timerGroups.resize(TIMER_NO_SIZE); + + timerGroups[TIMER_NO_AB].SetNames("AB"); + timerGroups[TIMER_NO_MAKE].SetNames("Make"); + timerGroups[TIMER_NO_UNDO].SetNames("Undo"); + timerGroups[TIMER_NO_EVALUATE].SetNames("Evaluate"); + timerGroups[TIMER_NO_NEXTMOVE].SetNames("NextMove"); + timerGroups[TIMER_NO_QT].SetNames("QuickTricks"); + timerGroups[TIMER_NO_LT].SetNames("LaterTricks"); + timerGroups[TIMER_NO_MOVEGEN].SetNames("MoveGen"); + timerGroups[TIMER_NO_LOOKUP].SetNames("Lookup"); + timerGroups[TIMER_NO_BUILD].SetNames("Build"); +} + + +void TimerList::Start( + const ABTimerType groupno, + const unsigned timerno) +{ + if (groupno >= TIMER_NO_SIZE) + return; + timerGroups[groupno].Start(timerno); +} + + +void TimerList::End( + const ABTimerType groupno, + const unsigned timerno) +{ + if (groupno >= TIMER_NO_SIZE) + return; + timerGroups[groupno].End(timerno); +} + + +bool TimerList::Used() const +{ + for (unsigned g = 0; g < TIMER_NO_SIZE; g++) + { + if (timerGroups[g].Used()) + return true; + } + return false; +} + + +void TimerList::PrintStats(ofstream& fout) const +{ + if (! TimerList::Used()) + return; + + // Approximate the exclusive times of each function. + // The ABsearch*() functions are recursively nested, + // so subtract out the one below. + // The other ones are subtracted out based on knowledge + // of the functions. + + TimerGroup ABGroup; + ABGroup = timerGroups[0]; + ABGroup.Differentiate(); + for (unsigned g = 1; g < TIMER_NO_SIZE; g++) + ABGroup -= timerGroups[g]; + + Timer ABTotal; + ABGroup.SetNames("AB"); + ABGroup.Sum(ABTotal); + ABTotal.SetName("Sum"); + + Timer sumTotal = ABTotal; + for (unsigned g = 1; g < TIMER_NO_SIZE; g++) + { + Timer t; + timerGroups[g].Sum(t); + sumTotal += t; + } + + fout << timerGroups[0].Header(); + fout << ABGroup.SumLine(sumTotal); + for (unsigned g = 1; g < TIMER_NO_SIZE; g++) + fout << timerGroups[g].SumLine(sumTotal); + fout << timerGroups[0].DashLine(); + fout << sumTotal.SumLine(sumTotal) << endl; + + if (ABGroup.Used()) + { + fout << ABGroup.Header(); + fout << ABGroup.TimerLines(ABTotal); + fout << ABGroup.DashLine(); + fout << ABTotal.SumLine(ABTotal) << endl; + } + +#ifdef DDS_TIMING_DETAILS + fout << timerGroups[0].DetailHeader(); + for (unsigned g = 0; g < TIMER_NO_SIZE; g++) + fout << timerGroups[g].DetailLines(); + fout << endl; +#endif +} + diff --git a/src/TimerList.h b/src/TimerList.h new file mode 100644 index 00000000..6838d4a3 --- /dev/null +++ b/src/TimerList.h @@ -0,0 +1,107 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +/* + TimerList consists of a number of groups, one for each piece + of the code being timed (ABsearch etc). + + Each group corresponds to something that should be timed at + multiple AB depths, i.e. cards played. The first card of a + new game is number 48, and the last card is number 0. + + The AB timer is special, as the AB functions are recursive + and so their timing includes not only the other functions they + contain, but also their own recursive calls at lower depths. + The AB timer group must be the first one. + + The object calculates an approximation to exclusive function + times, so it is a "poor man's profiler". + + For AB, first the times at depth-1 are subtracted out, and then + the times for all calls at the same depth are subtracted out. + This still leaves the overhead of the timing itself. As an + approximation, there is one timing overhead left for each + function, and it is on the order of the execution time of + Evaluate(), which is a very fast function. + + TIMER_START and TIMER_END are macros for bracketing code + to be timed, so + + TIMER_START(TIMER_NO_AB, depth); + ABsearch(...); + TIMER_END(TIMER_NO_AB, depth); + + This avoids the tedious #ifdef's at every place of a timer. + */ + +#ifndef DDS_TIMERLIST_H +#define DDS_TIMERLIST_H + +#include +#include +#include +#include + +#include "TimerGroup.h" +#include "debug.h" + +using namespace std; + + +#ifdef DDS_TIMING + #define TIMER_START(g, a) thrp->timerList.Start(g, a) + #define TIMER_END(g, a) thrp->timerList.End(g, a) +#else + #define TIMER_START(g, a) 1 + #define TIMER_END(g, a) 1 +#endif + +enum ABTimerType +{ + TIMER_NO_AB = 0, + TIMER_NO_MAKE = 1, + TIMER_NO_UNDO = 2, + TIMER_NO_EVALUATE = 3, + TIMER_NO_NEXTMOVE = 4, + TIMER_NO_QT = 5, + TIMER_NO_LT = 6, + TIMER_NO_MOVEGEN = 7, + TIMER_NO_LOOKUP = 8, + TIMER_NO_BUILD = 9, + TIMER_NO_SIZE = 10 +}; + + +class TimerList +{ + private: + + vector timerGroups; + + public: + TimerList(); + + ~TimerList(); + + void Reset(); + + void Start( + const ABTimerType groupno, + const unsigned timerno); + + void End( + const ABTimerType groupno, + const unsigned timerno); + + bool Used() const; + + void PrintStats(ofstream& fout) const; +}; + +#endif diff --git a/src/TransTable.cpp b/src/TransTable.cpp deleted file mode 100644 index 10b20eba..00000000 --- a/src/TransTable.cpp +++ /dev/null @@ -1,2968 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - -#include - -#include "dds.h" -#include "TransTable.h" - -extern unsigned char cardRank[16]; -extern char relRank[8192][15]; - -const char * players[DDS_HANDS] = -{ - "North", "East", "South", "West" -}; - - - -/* - This combines a small-memory and a full-memory version that - are implemented completely differently, but they share a common - interface. - - Explanation of full memory version: - - There are some constants that only need to be calculated - once. In fact they are the same for all instances of the - object. In order to save time and memory, they share a - single memory. - - Each 13-bit number, aggr, represents a possible set of cards - remaining in a suit. For example, 0x15a2 represents - A(1) QT(5) 97(a) 3(2). - - TTlowestRank[aggr] gives the lowest relative rank that is in - play in aggr. The ace is 14, the deuce is 2. A void counts as - rank 15 ("not even the ace"). It would go horribly wrong - if this rank were chosen to be 0, as might seem intuitive. - This is not the same as lowestRank, the lowest absolute rank. - - maskBytes[aggr][suit] is a set of 4 32-bit integers, - where suit is 0 ..3 (spades .. clubs). Each integer only - has 8 of its 32 bits set, but these 8 bits could be either - in the top byte (byte 0) or any of the others (bytes 1 ..3). - The bytes are abbreviated as B0 .. B3 below. - - int 0 int 1 int 2 int 3 - suit 0, spades B0 R0 B0 R1 B0 R2 B0 R3 - suit 1, hearts B1 R0 B1 R1 B1 R2 B1 R3 - suit 2, diamonds B2 R0 B2 R1 B2 R2 B2 - suit 3, clubs B3 R0 B3 R1 B3 R2 B3 - - R0 .. R3 are explained now. The purpose of maskBytes is - to generate 32-bit masks for later use with actual suits. - As a card can be with either of 4 players, 2 bits are needed - to encode the position of a card. Therefore the masks also - need 2 bits per card, even though the 2 bits are identical. - - In the table, R0 means the top byte (8 bits = 4 cards) of - a holding. - - R0 AKQJ - R1 T987 - R2 6543 - R3 2 - - For example, if the ace is held by North, the king by South, the - queen and jack by West, then the top byte for that SUIT would be - - 00(North) 10(South) 11(West) 11(West) - - The MASK for that holding would be 11 11 11 11, as all four - cards are in play. - - If the jack were missing, because it had already been played, - then the suit would be 00 10 11 00 (a missing card is also - encoded as 00), and the mask would be 11 11 11 00. - - Later on, when we have a specific set of spades .. clubs, - we want to check whether those cards are already in the - transposition table. As far as the necessary masks is - concerned, this is generated by an OR (|) of the four - 32-bit integers in a column of the table above. - - So the first column yields four bytes which are already - shifted in place, all corresponding to R0. The mask - corresponds to the AKQJ of the four suits in order. - - It's not really AKQJ, but the four highest cards still in - play in that suit. So missing cards are always at the end - of the list. -*/ - -bool _constantsSet = false; -int TTlowestRank[8192]; -#ifndef SMALL_MEMORY_OPTION - unsigned maskBytes[8192][DDS_SUITS][TT_BYTES]; -#endif - - -TransTable::TransTable() -{ - if (! _constantsSet) - { - _constantsSet = true; - TransTable::SetConstants(); - } - -#ifndef SMALL_MEMORY_OPTION - poolp = nullptr; - pagesDefault = NUM_PAGES_DEFAULT; - pagesMaximum = NUM_PAGES_MAXIMUM; - pagesCurrent = 0; - - memState = FROM_POOL; - harvestTrick = FIRST_HARVEST_TRICK; - harvestHand = 0; - - harvested.nextBlockNo = 0; - - timestamp = 0; - - pageStats.numResets = 0; - pageStats.numCallocs = 0; - pageStats.numFrees = 0; - pageStats.numHarvests = 0; - pageStats.lastCurrent = 0; -#endif - - TTInUse = 0; - - strcpy(fname, ""); - fp = stdout; -} - - -TransTable::~TransTable() -{ - TransTable::ReturnAllMemory(); - - if (fp != stdout && fp != nullptr) - fclose(fp); -} - - -void TransTable::SetConstants() -{ - unsigned int topBitRank = 1; - TTlowestRank[0] = 15; // Void -#ifndef SMALL_MEMORY_OPTION - unsigned winMask[8192]; - winMask[0] = 0; -#endif - - for (unsigned ind = 1; ind < 8192; ind++) - { - if (ind >= (topBitRank + topBitRank)) /* Next top bit */ - topBitRank <<= 1; - -#ifndef SMALL_MEMORY_OPTION - // winMask is a growing list of 11's. In the end it will - // have 26 bits, so 13 groups of two bits. It always - // consists of all 11's, then all 00's. - - winMask[ind] = (winMask[ind ^ topBitRank] >> 2) | (3 << 24); - - maskBytes[ind][0][0] = (winMask[ind] << 6) & 0xff000000; - maskBytes[ind][0][1] = (winMask[ind] << 14) & 0xff000000; - maskBytes[ind][0][2] = (winMask[ind] << 22) & 0xff000000; - maskBytes[ind][0][3] = (winMask[ind] << 30) & 0xff000000; - - maskBytes[ind][1][0] = (winMask[ind] >> 2) & 0x00ff0000; - maskBytes[ind][1][1] = (winMask[ind] << 6) & 0x00ff0000; - maskBytes[ind][1][2] = (winMask[ind] << 14) & 0x00ff0000; - maskBytes[ind][1][3] = (winMask[ind] << 22) & 0x00ff0000; - - maskBytes[ind][2][0] = (winMask[ind] >> 10) & 0x0000ff00; - maskBytes[ind][2][1] = (winMask[ind] >> 2) & 0x0000ff00; - maskBytes[ind][2][2] = (winMask[ind] << 6) & 0x0000ff00; - maskBytes[ind][2][3] = (winMask[ind] << 14) & 0x0000ff00; - - maskBytes[ind][3][0] = (winMask[ind] >> 18) & 0x000000ff; - maskBytes[ind][3][1] = (winMask[ind] >> 10) & 0x000000ff; - maskBytes[ind][3][2] = (winMask[ind] >> 2) & 0x000000ff; - maskBytes[ind][3][3] = (winMask[ind] << 6) & 0x000000ff; -#endif - - TTlowestRank[ind] = TTlowestRank[ind ^ topBitRank] - 1; - } -} - - -#ifdef SMALL_MEMORY_OPTION -void TransTable::Init(int handLookup[][15]) -{ - unsigned int topBitRank = 1; - unsigned int topBitNo = 2; - - for (int s = 0; s < DDS_SUITS; s++) - { - aggp[0].aggrRanks[s] = 0; - aggp[0].winMask[s] = 0; - } - - for (unsigned int ind = 1; ind < 8192; ind++) - { - if (ind >= (topBitRank + topBitRank)) - { - /* Next top bit */ - topBitRank <<= 1; - topBitNo++; - } - aggp[ind] = aggp[ind ^ topBitRank]; - - for (int s = 0; s < 4; s++) - { - aggp[ind].aggrRanks[s] = - (aggp[ind].aggrRanks[s] >> 2) | - (handLookup[s][topBitNo] << 24); - - aggp[ind].winMask[s] = - (aggp[ind].winMask[s] >> 2) | (3 << 24); - } - } - - return; -} - -#else -void TransTable::Init(int handLookup[][15]) -{ - // This is very similar to SetConstants, except that it - // happens with actual cards. It also makes sense to - // keep a record of aggrRanks for each suit. These are - // only used later for xorSet. - - unsigned int topBitRank = 1; - unsigned int topBitNo = 2; - aggrType * ap; - - for (int s = 0; s < DDS_SUITS; s++) - { - aggr[0].aggrRanks[s] = 0; - aggr[0].aggrBytes[s][0] = 0; - aggr[0].aggrBytes[s][1] = 0; - aggr[0].aggrBytes[s][2] = 0; - aggr[0].aggrBytes[s][3] = 0; - } - - for (unsigned ind = 1; ind < 8192; ind++) - { - if (ind >= (topBitRank << 1)) - { - /* Next top bit */ - topBitRank <<= 1; - topBitNo++; - } - - aggr[ind] = aggr[ind ^ topBitRank]; - ap = &aggr[ind]; - - for (int s = 0; s < DDS_SUITS; s++) - { - ap->aggrRanks[s] = ap->aggrRanks[s] >> 2 | - static_cast(handLookup[s][topBitNo] << 24); - } - - ap->aggrBytes[0][0] = (ap->aggrRanks[0] << 6) & 0xff000000; - ap->aggrBytes[0][1] = (ap->aggrRanks[0] << 14) & 0xff000000; - ap->aggrBytes[0][2] = (ap->aggrRanks[0] << 22) & 0xff000000; - ap->aggrBytes[0][3] = (ap->aggrRanks[0] << 30) & 0xff000000; - - ap->aggrBytes[1][0] = (ap->aggrRanks[1] >> 2) & 0x00ff0000; - ap->aggrBytes[1][1] = (ap->aggrRanks[1] << 6) & 0x00ff0000; - ap->aggrBytes[1][2] = (ap->aggrRanks[1] << 14) & 0x00ff0000; - ap->aggrBytes[1][3] = (ap->aggrRanks[1] << 22) & 0x00ff0000; - - ap->aggrBytes[2][0] = (ap->aggrRanks[2] >> 10) & 0x0000ff00; - ap->aggrBytes[2][1] = (ap->aggrRanks[2] >> 2) & 0x0000ff00; - ap->aggrBytes[2][2] = (ap->aggrRanks[2] << 6) & 0x0000ff00; - ap->aggrBytes[2][3] = (ap->aggrRanks[2] << 14) & 0x0000ff00; - - ap->aggrBytes[3][0] = (ap->aggrRanks[3] >> 18) & 0x000000ff; - ap->aggrBytes[3][1] = (ap->aggrRanks[3] >> 10) & 0x000000ff; - ap->aggrBytes[3][2] = (ap->aggrRanks[3] >> 2) & 0x000000ff; - ap->aggrBytes[3][3] = (ap->aggrRanks[3] << 6) & 0x000000ff; - } -} -#endif - - -void TransTable::SetMemoryDefault(int megabytes) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(megabytes); -#else - double blockMem = BLOCKS_PER_PAGE * sizeof(winBlockType) / - static_cast(1024.); - - pagesDefault = static_cast((1024 * megabytes) / blockMem); -#endif -} - - -void TransTable::SetMemoryMaximum(int megabytes) -{ -#ifdef SMALL_MEMORY_OPTION - maxmem = static_cast(1000000 * megabytes); -#else - double blockMem = BLOCKS_PER_PAGE * sizeof(winBlockType) / - static_cast(1024.); - - pagesMaximum = static_cast((1024 * megabytes) / blockMem); -#endif -} - - -///////////////////////////////////////////////////////////// -// // -// Small memory TT functions. // -// // -///////////////////////////////////////////////////////////// - -#ifdef SMALL_MEMORY_OPTION -void TransTable::MakeTT() -{ - int i; - - if (!TTInUse) - { - TTInUse = 1; - - summem = (WINIT + 1) * sizeof(winCardType) + - (NINIT + 1) * sizeof(nodeCardsType) + - (LSIZE + 1) * 52 * sizeof(posSearchTypeSmall); - wmem = static_cast((WSIZE + 1) * sizeof(winCardType)); - nmem = static_cast((NSIZE + 1) * sizeof(nodeCardsType)); - - maxIndex = static_cast( - (maxmem - summem) / ((WSIZE + 1) * sizeof(winCardType))); - - pw = static_cast(calloc(static_cast(maxIndex + 1), sizeof(struct winCardType *))); - if (pw == NULL) - exit(1); - - - pn = static_cast(calloc(static_cast(maxIndex + 1), sizeof(struct nodeCardsType *))); - if (pn == NULL) - exit(1); - - - for (int k = 1; k <= 13; k++) - for (int h = 0; h < DDS_HANDS; h++) - { - pl[k][h] = static_cast - (calloc(static_cast(maxIndex + 1), - sizeof(posSearchTypeSmall *))); - if (pl[k][h] == NULL) - exit(1); - } - - - for (i = 0; i <= maxIndex; i++) - { - if (pw[i]) - free(pw[i]); - pw[i] = NULL; - } - - for (i = 0; i <= maxIndex; i++) - { - if (pn[i]) - free(pn[i]); - pn[i] = NULL; - } - - for (int k = 1; k <= 13; k++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - for (i = 0; i <= maxIndex; i++) - { - if (pl[k][h][i]) - free(pl[k][h][i]); - pl[k][h][i] = NULL; - } - } - } - - pw[0] = static_cast(calloc(WINIT + 1, sizeof(struct winCardType))); - if (pw[0] == NULL) - exit(1); - - pn[0] = static_cast(calloc(NINIT + 1, sizeof(struct nodeCardsType))); - if (pn[0] == NULL) - exit(1); - - for (int k = 1; k <= 13; k++) - for (int h = 0; h < DDS_HANDS; h++) - { - pl[k][h][0] = static_cast(calloc((LSIZE + 1), - sizeof(struct posSearchTypeSmall))); - if (pl[k][h][0] == NULL) - exit(1); - } - - aggp = static_cast(calloc(8192, sizeof(struct ttAggrType))); - if (aggp == NULL) - exit(1); - - InitTT(); - - for (int k = 1; k <= 13; k++) - aggrLenSets[k] = 0; -#if defined(DDS_TT_STATS) - fprintf(fp, "Report of generated PosSearch nodes per trick level.\n"); - fprintf(fp, "Trick level 13 is highest level with all 52 cards.\n"); - fprintf(fp, "---------------------------------------------------\n"); -#endif - statsResets.noOfResets = 0; - for (int k = 0; k <= 5; k++) - statsResets.aggrResets[k] = 0; - resetText[0] = "Unknown reason"; - resetText[1] = "Too many nodes"; - resetText[2] = "New deal"; - resetText[3] = "New trump"; - resetText[4] = "Memory exhausted"; - resetText[5] = "Free thread memory"; - } - - return; -} - - -void TransTable::Wipe() -{ - int m; - - for (m = 1; m <= wcount; m++) - { - if (pw[m]) - free(pw[m]); - pw[m] = NULL; - } - for (m = 1; m <= ncount; m++) - { - if (pn[m]) - free(pn[m]); - pn[m] = NULL; - } - - for (int k = 1; k <= 13; k++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - for (m = 1; m <= lcount[k][h]; m++) - { - if (pl[k][h][m]) - free(pl[k][h][m]); - pl[k][h][m] = NULL; - } - } - } - - allocmem = summem; - - return; -} - - - -void TransTable::InitTT() -{ - winSetSizeLimit = WINIT; - nodeSetSizeLimit = NINIT; - allocmem = (WINIT + 1) * sizeof(struct winCardType); - allocmem += (NINIT + 1) * sizeof(struct nodeCardsType); - allocmem += (LSIZE + 1) * 52 * sizeof(struct posSearchTypeSmall); - winCards = pw[0]; - nodeCards = pn[0]; - wcount = 0; - ncount = 0; - - nodeSetSize = 0; - winSetSize = 0; - - clearTTflag = false; - windex = -1; - - for (int k = 1; k <= 13; k++) - for (int h = 0; h < DDS_HANDS; h++) - { - posSearch[k][h] = pl[k][h][0]; - lenSetInd[k][h] = 0; - lcount[k][h] = 0; - } -} - - -void TransTable::ResetMemory(int reason) -{ - Wipe(); - - InitTT(); - - for (int k = 1; k <= 13; k++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - rootnp[k][h] = &(posSearch[k][h][0]); - posSearch[k][h][0].suitLengths = 0; - posSearch[k][h][0].posSearchPoint = NULL; - posSearch[k][h][0].left = NULL; - posSearch[k][h][0].right = NULL; - - lenSetInd[k][h] = 1; - } - } - -#if defined(DDS_TT_STATS) - statsResets.noOfResets++; - statsResets.aggrResets[reason]++; -#else - UNUSED(reason); -#endif - - return; -} - -void TransTable::ReturnAllMemory() -{ - - if (!TTInUse) - return; - TTInUse = 0; - -#if defined(DDS_TT_STATS) - PrintResetStats(); - PrintNodeStats(); -#endif - - - Wipe(); - - if (pw[0]) - free(pw[0]); - pw[0] = NULL; - - if (pn[0]) - free(pn[0]); - pn[0] = NULL; - - for (int k = 1; k <= 13; k++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - if (pl[k][h][0]) - free(pl[k][h][0]); - pl[k][h][0] = NULL; - } - } - - if (pw) - free(pw); - pw = NULL; - - if (pn) - free(pn); - pn = NULL; - - if (aggp) - free(aggp); - aggp = NULL; - - return; -} -#endif - - - -///////////////////////////////////////////////////////////// -// // -// Full memory TT functions. // -// // -///////////////////////////////////////////////////////////// - -#ifndef SMALL_MEMORY_OPTION -void TransTable::MakeTT() -{ - if (! TTInUse) - { - TTInUse = 1; - - for (int t = 0; t < TT_TRICKS; t++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - TTroot[t][h] = static_cast - (malloc(256 * sizeof(distHashType))); - - if (TTroot[t][h] == nullptr) - exit(1); - } - } - } - - TransTable::InitTT(); -} - - -void TransTable::InitTT() -{ - for (int c = 0; c < TT_TRICKS; c++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - for (int i = 0; i < 256; i++) - { - TTroot[c][h][i].nextNo = 0; - TTroot[c][h][i].nextWriteNo = 0; - - } - lastBlockSeen[c][h] = nullptr; - } - } -} - - -void TransTable::ReleaseTT() -{ - if (! TTInUse) - return; - TTInUse = 0; - - for (int t = 0; t < TT_TRICKS; t++) - { - for (int h = 0; h < DDS_HANDS; h++) - { - if (TTroot[t][h] == nullptr) - continue; - - free(TTroot[t][h]); - } - } -} - - -void TransTable::ResetMemory(int reason) -{ - UNUSED(reason); - if (poolp == nullptr) - return; - - pageStats.numResets++; - pageStats.numCallocs += pagesCurrent - pageStats.lastCurrent; - pageStats.lastCurrent = pagesCurrent; - - while (pagesCurrent > pagesDefault) - { - free(poolp->list); - poolp = poolp->prev; - - free(poolp->next); - poolp->next = nullptr; - - pagesCurrent--; - } - - pageStats.numFrees += pageStats.lastCurrent - pagesCurrent; - pageStats.lastCurrent = pagesCurrent; - - while (poolp->prev) - poolp = poolp->prev; - - poolp->nextBlockNo = 0; - nextBlockp = poolp->list; - - TransTable::InitTT(); - - timestamp = 0; - - memState = FROM_POOL; - - return; -} - - -void TransTable::ReturnAllMemory() -{ - poolType * tmp; - - if (poolp) - { - while (poolp->next) - poolp = poolp->next; - - while (poolp) - { - free(poolp->list); - tmp = poolp; - poolp = poolp->prev; - free(tmp); - } - } - - pagesCurrent = 0; - - pageStats.numResets = 0; - pageStats.numCallocs = 0; - pageStats.numFrees = 0; - pageStats.numHarvests = 0; - pageStats.lastCurrent = 0; - - TransTable::ReleaseTT(); - - return; -} -#endif - - -int TransTable::BlocksInUse() -{ -#ifndef SMALL_MEMORY_OPTION - poolType * pp = poolp; - int count = 0; - - do - { - count += pp->nextBlockNo; - pp = pp->prev; - } - while (pp); - - return count; -#else - return 0; -#endif -} - - -double TransTable::MemoryInUse() -{ -#ifdef SMALL_MEMORY_OPTION - int ttMem = static_cast(allocmem); - int aggrMem = 8192 * static_cast(sizeof(ttAggrType)); - return (ttMem + aggrMem) / static_cast(1024.); -#else - int blockMem = BLOCKS_PER_PAGE * pagesCurrent * - static_cast(sizeof(winBlockType)); - int aggrMem = 8192 * static_cast(sizeof(aggrType)); - int rootMem = TT_TRICKS * DDS_HANDS * 256 * - static_cast(sizeof(distHashType)); - - return (blockMem + aggrMem + rootMem) / static_cast(1024.); -#endif - -} - - -TransTable::winBlockType * TransTable::GetNextCardBlock() -{ - /* - Spaghetti code. The basic idea is that there is a pool of - pages. When a page runs out, we get a next pool. But we're - only allowed a certain maximum number, and calloc might also - fail before then. We have a default number of pages that - we don't give back voluntarily once we have acquired them, - but we give back anything more than that at the end of each - hand. If this overall mechanism fails, then we try to harvest - old entries scattered throughout the TT memory. If we get - enough for a "page", then we use that single page, and if - that runs out later, we try to harvest some more, starting - where we left off harvesting last time. If the harvesting also - fails, then we reset whatever TT memory we do have, and we - continue with that. - */ - -#ifdef SMALL_MEMORY_OPTION - return NULL; -#else - if (poolp == nullptr) - { - // Have to be able to get at least one pool. - poolp = static_cast(calloc(1, sizeof(poolType))); - if (poolp == nullptr) - exit(1); - - poolp->list = static_cast - (malloc(BLOCKS_PER_PAGE * sizeof(winBlockType))); - - if (! poolp->list) - exit(1); - - poolp->next = nullptr; - poolp->prev = nullptr; - poolp->nextBlockNo = 1; - - nextBlockp = poolp->list; - - pagesCurrent++; - - return nextBlockp++; - } - else if (memState == FROM_HARVEST) - { - // Not allowed to get more memory, so reuse old one. - int n = harvested.nextBlockNo; - if (n == BLOCKS_PER_PAGE) - { - if (! TransTable::Harvest()) - { - TransTable::ResetMemory(UNKNOWN_REASON); - poolp->nextBlockNo++; - return nextBlockp++; - } - n = 0; - } - - harvested.nextBlockNo++; - return harvested.list[n]; - } - else if (poolp->nextBlockNo == BLOCKS_PER_PAGE) - { - if (poolp->next) - { - // Reuse a dormant block that has not been freed. - poolp = poolp->next; - poolp->nextBlockNo = 1; - nextBlockp = poolp->list; - - return nextBlockp++; - } - else if (pagesCurrent == pagesMaximum) - { - // Have to try to reclaim memory. - if (! TransTable::Harvest()) - { - TransTable::ResetMemory(UNKNOWN_REASON); - poolp->nextBlockNo++; - return nextBlockp++; - } - - memState = FROM_HARVEST; - harvested.nextBlockNo++; - return harvested.list[0]; - } - else - { - // Make a new pool. - poolType * newpoolp = static_cast - (calloc(1, sizeof(poolType))); - - if (newpoolp == nullptr) - { - // Unexpected, but try harvesting before we give up - // and start over. - if (! TransTable::Harvest()) - { - TransTable::ResetMemory(UNKNOWN_REASON); - poolp->nextBlockNo++; - return nextBlockp++; - } - - memState = FROM_HARVEST; - harvested.nextBlockNo++; - return harvested.list[0]; - } - - newpoolp->list = static_cast - (malloc(BLOCKS_PER_PAGE * sizeof(winBlockType))); - - if (! newpoolp->list) - { - if (! TransTable::Harvest()) - { - TransTable::ResetMemory(UNKNOWN_REASON); - poolp->nextBlockNo++; - return nextBlockp++; - } - - memState = FROM_HARVEST; - harvested.nextBlockNo++; - return harvested.list[0]; - } - - newpoolp->nextBlockNo = 1; - newpoolp->next = nullptr; - newpoolp->prev = poolp; - - poolp->next = newpoolp; - poolp = newpoolp; - - nextBlockp = newpoolp->list; - - pagesCurrent++; - - return nextBlockp++; - } - } - - poolp->nextBlockNo++; - return nextBlockp++; -#endif -} - - -bool TransTable::Harvest() -{ -#ifdef SMALL_MEMORY_OPTION - return false; -#else - distHashType * rootptr = TTroot[harvestTrick][harvestHand]; - distHashType * ptr; - winBlockType * bp; - - int trick = harvestTrick; - int hand = harvestHand; - int hash, suit, hno = 0; - - while (1) - { - for (hash = 0; hash < 256; hash++) - { - ptr = &rootptr[hash]; - for (suit = ptr->nextNo - 1; suit >= 0; suit--) - { - bp = ptr->list[suit].posBlock; - if (timestamp - bp->timestampRead > HARVEST_AGE) - { - bp->nextMatchNo = 0; - bp->nextWriteNo = 0; - bp->timestampRead = timestamp; - harvested.list[hno] = bp; - - // Swap the last element down. - if (suit != ptr->nextNo - 1) - ptr->list[suit] = ptr->list[ ptr->nextNo - 1 ]; - - ptr->nextNo--; - ptr->nextWriteNo = ptr->nextNo; - - if (++hno == BLOCKS_PER_PAGE) - { - if (++harvestHand >= DDS_HANDS) - { - // Skip rest of this [trick][hand] for simplicity. - harvestHand = 0; - if (--harvestTrick < 0) - harvestTrick = FIRST_HARVEST_TRICK; - } - - harvested.nextBlockNo = 0; - pageStats.numHarvests++; - return true; - } - } - } - } - - if (++harvestHand >= DDS_HANDS) - { - harvestHand = 0; - if (--harvestTrick < 0) - harvestTrick = FIRST_HARVEST_TRICK; - } - - if (harvestTrick == trick && harvestHand == hand) - return false; - - rootptr = TTroot[harvestTrick][harvestHand]; - } -#endif -} - - -int TransTable::hash8(int * handDist) -{ - /* - handDist is an array of hand distributions, North .. West. - Each entry is a 12-bit number with 3 groups of 4 bits. - Each group is the binary representation of the number of - cards held in that suit. The suits are in order spades, - hearts, diamonds. Clubs can be neglected, as the total - number of cards in a hand is given by the trick number. - - For example, if handDist[1] equals 0x0433, then East holds - 4 spades, 3 hearts, 3 diamonds and the rest in clubs. - If this is after the second trick, there are 11 cards, so - East must hold 1 club. - - The hash function turns all 4 hand distributions into a - single 8-bit number. The numbers should be spread as - evenly as possible across the 256 possibilities. I've not - done extensive research into finding the best hash function, - but this one seems OK. It uses a small prime, 5, and its - powers. The shift at the end is in order to get some use - out of the bits above the first 8 ones. - */ - - int h = - (handDist[0] ^ - ((handDist[1] * 5) ) ^ - ((handDist[2] * 25) ) ^ - ((handDist[3] * 125) ) ); - - return (h ^ (h >> 5)) & 0xff; -} - - -///////////////////////////////////////////////////////////// -// // -// Small memory TT functions. // -// // -///////////////////////////////////////////////////////////// - - -#ifdef SMALL_MEMORY_OPTION -nodeCardsType * TransTable::Lookup( - int trick, - int hand, - unsigned short * aggrTarget, - int * handDist, - int limit, - bool * lowerFlag) -{ - bool res; - struct posSearchTypeSmall * pp; - int orderSet[DDS_SUITS]; - struct nodeCardsType * cardsP; - - suitLengths[trick] = - (static_cast(handDist[0]) << 36) | - (static_cast(handDist[1]) << 24) | - (static_cast(handDist[2]) << 12) | - (static_cast(handDist[3])); - - pp = SearchLenAndInsert(rootnp[trick][hand], - suitLengths[trick], false, trick, hand, &res); - - /* Find node that fits the suit lengths */ - if ((pp != NULL) && res) - { - for (int ss = 0; ss < DDS_SUITS; ss++) - { - orderSet[ss] = - aggp[aggrTarget[ss]].aggrRanks[ss]; - } - - if (pp->posSearchPoint == NULL) - cardsP = NULL; - else - { - cardsP = FindSOP(orderSet, limit, pp->posSearchPoint, - hand, lowerFlag); - - if (cardsP == NULL) - return cardsP; - } - } - else - { - cardsP = NULL; - } - return cardsP; -} - - -void TransTable::Add( - int tricks, - int hand, - unsigned short * aggrTarget, - unsigned short * ourWinRanks, - nodeCardsType * first, - bool flag) -{ - BuildSOP(ourWinRanks, aggrTarget, first, suitLengths[tricks], - tricks, hand, tricks, flag); - - if (clearTTflag) - { - ResetMemory(MEMORY_EXHAUSTED); - } - - return; -} -#endif - - -void TransTable::AddWinSet() -{ -#ifdef SMALL_MEMORY_OPTION - if (clearTTflag) - { - windex++; - winSetSize = windex; - winCards = &(temp_win[windex]); - } - else if (winSetSize >= winSetSizeLimit) - { - /* The memory chunk for the winCards structure will be exceeded. */ - if (((allocmem + static_cast(wmem)) > maxmem) || (wcount >= maxIndex) || - (winSetSize > SIMILARMAXWINNODES)) - { - /* Already allocated memory plus needed allocation overshot maxmem */ - windex++; - winSetSize = windex; - clearTTflag = true; - winCards = &(temp_win[windex]); - } - else - { - wcount++; - winSetSizeLimit = WSIZE; - pw[wcount] = - static_cast(calloc((WSIZE + 1), sizeof(struct winCardType))); - if (pw[wcount] == NULL) - { - clearTTflag = true; - windex++; - winSetSize = windex; - winCards = &(temp_win[windex]); - } - else - { - allocmem += (WSIZE + 1) * sizeof(struct winCardType); - winSetSize = 0; - winCards = pw[wcount]; - } - } - } - else - winSetSize++; - return; -#endif -} - -void TransTable::AddNodeSet() -{ -#ifdef SMALL_MEMORY_OPTION - if (nodeSetSize >= nodeSetSizeLimit) - { - /* The memory chunk for the nodeCards structure will be exceeded. */ - if (((allocmem + static_cast(nmem)) > maxmem) || (ncount >= maxIndex)) - { - /* Already allocated memory plus needed allocation overshot maxmem */ - clearTTflag = true; - } - else - { - ncount++; - nodeSetSizeLimit = NSIZE; - pn[ncount] = - static_cast(calloc((NSIZE + 1), sizeof(struct nodeCardsType))); - if (pn[ncount] == NULL) - { - clearTTflag = true; - } - else - { - allocmem += (NSIZE + 1) * sizeof(struct nodeCardsType); - nodeSetSize = 0; - nodeCards = pn[ncount]; - } - } - } - else - nodeSetSize++; - return; -#endif -} - -void TransTable::AddLenSet(int trick, int firstHand) -{ -#ifndef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(firstHand); -#else - if (lenSetInd[trick][firstHand] >= LSIZE) - { - /* The memory chunk for the posSearchTypeSmall structure will be exceeded. */ - if (((allocmem + (LSIZE + 1) * sizeof(struct posSearchTypeSmall)) > maxmem) - || (lcount[trick][firstHand] >= maxIndex)) - { - /* Already allocated memory plus needed allocation overshot maxmem */ - clearTTflag = true; - - return; - } - - /* Obtain another memory chunk LSIZE.*/ - - lcount[trick][firstHand]++; - - pl[trick][firstHand][lcount[trick][firstHand]] = - static_cast(calloc(LSIZE + 1, sizeof(struct posSearchTypeSmall))); - - if (pl[trick][firstHand][lcount[trick][firstHand]] == NULL) - - { - clearTTflag = true; - - return; - } - else - { - allocmem += (LSIZE + 1) * sizeof(struct posSearchTypeSmall); - lenSetInd[trick][firstHand] = 0; - posSearch[trick][firstHand] = - pl[trick][firstHand][lcount[trick][firstHand]]; - -#if defined(DDS_TT_STATS) - aggrLenSets[trick]++; -#endif - } - } - else - { - lenSetInd[trick][firstHand]++; -#if defined(DDS_TT_STATS) - aggrLenSets[trick]++; -#endif - } - return; -#endif -} - - -void TransTable::BuildSOP( - unsigned short ourWinRanks[DDS_SUITS], - unsigned short aggrArg[DDS_SUITS], - struct nodeCardsType * first, - long long lengths, - int tricks, - int firstHand, - int depth, - bool flag) -{ - UNUSED(depth); -#ifndef SMALL_MEMORY_OPTION - UNUSED(ourWinRanks); - UNUSED(aggrArg); - UNUSED(first); - UNUSED(lengths); - UNUSED(tricks); - UNUSED(firstHand); - UNUSED(flag); -#else - bool res; - int w; - unsigned short int temp; - struct nodeCardsType * cardsP; - struct posSearchTypeSmall * np; - - int winMask[DDS_SUITS]; - int winOrderSet[DDS_SUITS]; - char low[DDS_SUITS]; - - for (int ss = 0; ss < DDS_SUITS; ss++) - { - w = ourWinRanks[ss]; - if (w == 0) - { - winMask[ss] = 0; - winOrderSet[ss] = 0; - low[ss] = 15; - } - else - { - w = w & (-w); /* Only lowest win */ - temp = static_cast(aggrArg[ss] & (-w)); - low[ss] = static_cast(TTlowestRank[temp]); - - winMask[ss] = aggp[temp].winMask[ss]; - winOrderSet[ss] = aggp[temp].aggrRanks[ss]; - } - } - - np = SearchLenAndInsert(rootnp[tricks][firstHand], - lengths, true, tricks, firstHand, &res); - - cardsP = BuildPath(winMask, winOrderSet, - static_cast(first->ubound), static_cast(first->lbound), - static_cast(first->bestMoveSuit), static_cast(first->bestMoveRank), - np, &res); - - - if (res) - { - cardsP->ubound = static_cast(first->ubound); - cardsP->lbound = static_cast(first->lbound); - - if (flag) - { - cardsP->bestMoveSuit = static_cast(first->bestMoveSuit); - cardsP->bestMoveRank = static_cast(first->bestMoveRank); - } - else - { - cardsP->bestMoveSuit = 0; - cardsP->bestMoveRank = 0; - } - - for (int k = 0; k < DDS_SUITS; k++) - cardsP->leastWin[k] = 15 - low[k]; - } -#endif -} - - -struct nodeCardsType * TransTable::BuildPath( - int * winMask, - int * winOrderSet, - int ubound, - int lbound, - char bestMoveSuit, - char bestMoveRank, - struct posSearchTypeSmall * nodep, - bool * result) -{ - /* 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 */ - -#ifndef SMALL_MEMORY_OPTION - UNUSED(winMask); - UNUSED(winOrderSet); - UNUSED(ubound); - UNUSED(lbound); - UNUSED(bestMoveSuit); - UNUSED(bestMoveRank); - UNUSED(nodep); - UNUSED(result); - return NULL; -#else - bool found; - struct winCardType * np, *p2, *nprev, *fnp, *pnp; - struct winCardType temp; - struct nodeCardsType * sopP = 0, *p; - - 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 = &(winCards[winSetSize]); - AddWinSet(); - p2->next = NULL; - p2->nextWin = NULL; - p2->prevWin = NULL; - nodep->posSearchPoint = p2; - p2->winMask = winMask[suit]; - p2->orderSet = winOrderSet[suit]; - p2->first = NULL; - np = p2; /* Latest winning node */ - suit++; - while (suit < 4) - { - p2 = &(winCards[winSetSize]); - AddWinSet(); - np->nextWin = p2; - p2->prevWin = np; - p2->next = NULL; - p2->nextWin = NULL; - p2->winMask = winMask[suit]; - p2->orderSet = winOrderSet[suit]; - p2->first = NULL; - np = p2; /* Latest winning node */ - suit++; - } - p = &(nodeCards[nodeSetSize]); - AddNodeSet(); - 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 == winMask[suit]) && - (np->orderSet == 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(ubound, lbound, bestMoveSuit, bestMoveRank, - 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 = &(winCards[winSetSize]); - AddWinSet(); - 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 = winMask[suit]; - p2->orderSet = winOrderSet[suit]; - p2->first = NULL; - np = p2; /* Latest winning node */ - suit++; - - /* Rest of path must be created */ - while (suit < 4) - { - p2 = &(winCards[winSetSize]); - AddWinSet(); - np->nextWin = p2; - p2->prevWin = np; - p2->next = NULL; - p2->winMask = winMask[suit]; - p2->orderSet = 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 = &(nodeCards[nodeSetSize]); - AddNodeSet(); - np->first = p; - *result = true; - return p; - } -#endif -} - -struct TransTable::posSearchTypeSmall * TransTable::SearchLenAndInsert( - struct posSearchTypeSmall * rootp, - long long key, - bool insertNode, - int trick, - int firstHand, - bool * result) -{ - /* 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. */ - -#ifndef SMALL_MEMORY_OPTION - UNUSED(rootp); - UNUSED(key); - UNUSED(insertNode); - UNUSED(trick); - UNUSED(firstHand); - UNUSED(result); - return NULL; -#else - struct posSearchTypeSmall * np, *p, *sp; - - sp = NULL; - if (insertNode) - sp = &(posSearch[trick][firstHand][lenSetInd[trick][firstHand]]); - - 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(trick, firstHand); - 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(trick, firstHand); - np->right = p; - p->posSearchPoint = NULL; - p->suitLengths = key; - p->left = NULL; - p->right = NULL; - *result = true; - return p; - } - else - { - *result = false; - return NULL; - } - } - } -#endif -} - - -struct nodeCardsType * TransTable::UpdateSOP( - int ubound, - int lbound, - char bestMoveSuit, - char bestMoveRank, - nodeCardsType * nodep) -{ - /* Update SOP node with new values for upper and lower - bounds. */ -#ifndef SMALL_MEMORY_OPTION - UNUSED(ubound); - UNUSED(lbound); - UNUSED(bestMoveSuit); - UNUSED(bestMoveRank); - UNUSED(nodep); - return NULL; -#else - if ((lbound > nodep->lbound) || - (nodep->lbound == -1)) - nodep->lbound = static_cast(lbound); - if ((ubound < nodep->ubound) || - (nodep->ubound == -1)) - nodep->ubound = static_cast(ubound); - - nodep->bestMoveSuit = bestMoveSuit; - nodep->bestMoveRank = bestMoveRank; - - return nodep; -#endif -} - - -struct nodeCardsType * TransTable::FindSOP( - int orderSet[], - int limit, - winCardType * nodeP, - int firstHand, - bool * lowerFlag) -{ - struct winCardType * np; - UNUSED(firstHand); - - np = nodeP; - int s = 0; - - while (np) - { - if ((np->winMask & orderSet[s]) == np->orderSet) - { - /* Winning rank set fits position */ - if (s != 3) - { - np = np->nextWin; - s++; - continue; - } - - if (np->first->lbound > limit) - { - *lowerFlag = true; - return np->first; - } - else if (np->first->ubound <= limit) - { - *lowerFlag = false; - return np->first; - } - } - - while (np->next == NULL) - { - np = np->prevWin; - s--; - if (np == NULL) /* Previous node is header node? */ - return NULL; - } - np = np->next; - } - return NULL; -} - - - -///////////////////////////////////////////////////////////// -// // -// Full memory TT functions. // -// // -///////////////////////////////////////////////////////////// - -#ifndef SMALL_MEMORY_OPTION -nodeCardsType * TransTable::Lookup( - int tricks, - int hand, - unsigned short aggrTarget[], - int handDist[], - int limit, - bool * lowerFlag) -{ - // First look up distribution. - long long suitLengths = - (static_cast(handDist[0]) << 36) | - (static_cast(handDist[1]) << 24) | - (static_cast(handDist[2]) << 12) | - (static_cast(handDist[3]) ); - - int hashkey = hash8(handDist); - - bool empty; - lastBlockSeen[tricks][hand] = - LookupSuit(&TTroot[tricks][hand][hashkey], - suitLengths, &empty); - if (empty) - return nullptr; - - // If that worked, look up cards. - unsigned * ab0 = aggr[ aggrTarget[0] ].aggrBytes[0]; - unsigned * ab1 = aggr[ aggrTarget[1] ].aggrBytes[1]; - unsigned * ab2 = aggr[ aggrTarget[2] ].aggrBytes[2]; - unsigned * ab3 = aggr[ aggrTarget[3] ].aggrBytes[3]; - - winMatchType TTentry; - TTentry.topSet1 = ab0[0] | ab1[0] | ab2[0] | ab3[0]; - TTentry.topSet2 = ab0[1] | ab1[1] | ab2[1] | ab3[1]; - TTentry.topSet3 = ab0[2] | ab1[2] | ab2[2] | ab3[2]; - TTentry.topSet4 = ab0[3] | ab1[3] | ab2[3] | ab3[3]; - - return TransTable::LookupCards(&TTentry, - lastBlockSeen[tricks][hand], limit, lowerFlag); -} -#endif - - -TransTable::winBlockType * TransTable::LookupSuit( - distHashType * dp, - long long key, - bool * empty) -{ - /* - Always returns a valid winBlockType. - If empty == true, there was no match, so there is - no point in looking for a card match. - If empty == false, there were entries already. - */ - - int n = dp->nextNo; - for (int i = 0; i < n; i++) - { - if (dp->list[i].key == key) - { - *empty = false; - return dp->list[i].posBlock; - } - } - - *empty = true; - int m; - - if (n == DISTS_PER_ENTRY) - { - // No room for new exact suits at this hash position. - // Have to reuse an existing posBlock. - if (dp->nextWriteNo == DISTS_PER_ENTRY) - { - m = 0; - dp->nextWriteNo = 1; - } - else - m = dp->nextWriteNo++; - } - else - { - // Didn't find an exact match, but there is still room. - // The following looks a bit odd because it is possible that - // GetNextCardBlock wipes out the whole memory, so we - // have to use the up-to-date location, not m from above. - - winBlockType * bp = GetNextCardBlock(); - m = dp->nextWriteNo++; - dp->list[m].posBlock = bp; - dp->list[m].posBlock->timestampRead = timestamp; - dp->nextNo++; - } - - // As long as the secondary Lookup loop in ABsearch exists, - // it will cause spurious extra blocks to be created here - // which are not useful, because nothing is ever Add'ed. - // This is not a memory leak, as the memory is properly freed, - // but it is also a small waste of about 0.5%. I don't mind. - - dp->list[m].key = key; - dp->list[m].posBlock->nextMatchNo = 0; - dp->list[m].posBlock->nextWriteNo = 0; - - return dp->list[m].posBlock; -} - - -nodeCardsType * TransTable::LookupCards( - winMatchType * searchp, - winBlockType * bp, - int limit, - bool * lowerFlag) -{ - winMatchType * wp; - - int n = bp->nextWriteNo - 1; - wp = &bp->list[n]; - - // It may be a bit silly to duplicate the code like this. - // It could be combined to one loop with a slight overhead. - - for (int i = n; i >= 0; i--, wp--) - { - if ((wp->topSet1 ^ searchp->topSet1) & wp->topMask1) - continue; - - if (wp->lastMaskNo != 1) - { - if ((wp->topSet2 ^ searchp->topSet2) & wp->topMask2) - continue; - - if (wp->lastMaskNo != 2) - { - if ((wp->topSet3 ^ searchp->topSet3) & wp->topMask3) - continue; - } - } - - // Check bounds. - nodeCardsType * nodep = &wp->first; - if (nodep->lbound > limit) - { - bp->timestampRead = ++timestamp; - * lowerFlag = true; - return nodep; - } - else if (nodep->ubound <= limit) - { - bp->timestampRead = ++timestamp; - * lowerFlag = false; - return nodep; - } - } - - int n2 = bp->nextMatchNo - 1; - wp = &bp->list[n2]; - - for (int i = n2; i > n; i--, wp--) - { - if ((wp->topSet1 ^ searchp->topSet1) & wp->topMask1) - continue; - - if (wp->lastMaskNo != 1) - { - if ((wp->topSet2 ^ searchp->topSet2) & wp->topMask2) - continue; - - if (wp->lastMaskNo != 2) - { - if ((wp->topSet3 ^ searchp->topSet3) & wp->topMask3) - continue; - } - } - - nodeCardsType * nodep = &wp->first; - if (nodep->lbound > limit) - { - * lowerFlag = true; - bp->timestampRead = ++timestamp; - return nodep; - } - else if (nodep->ubound <= limit) - { - * lowerFlag = false; - bp->timestampRead = ++timestamp; - return nodep; - } - } - - return nullptr; -} - - -void TransTable::CreateOrUpdate( - winBlockType * bp, - winMatchType * searchp, - bool flag) -{ - // Either updates an existing SOP or creates a new one. - // A new one is created at the end of the bp list if this - // is not already full, or the oldest one in the list is - // overwritten. - - winMatchType * wp = bp->list; - int n = bp->nextMatchNo; - - for (int i = 0; i < n; i++, wp++) - { - if (wp->xorSet != searchp->xorSet ) continue; - if (wp->maskIndex != searchp->maskIndex) continue; - if (wp->topSet1 != searchp->topSet1 ) continue; - if (wp->topSet2 != searchp->topSet2 ) continue; - if (wp->topSet3 != searchp->topSet3 ) continue; - - nodeCardsType * nodep = &wp->first; - if (searchp->first.lbound > nodep->lbound) - nodep->lbound = searchp->first.lbound; - if (searchp->first.ubound < nodep->ubound) - nodep->ubound = searchp->first.ubound; - - nodep->bestMoveSuit = searchp->first.bestMoveSuit; - nodep->bestMoveRank = searchp->first.bestMoveRank; - return; - } - - if (n == BLOCKS_PER_ENTRY) - { - if (bp->nextWriteNo >= BLOCKS_PER_ENTRY) - bp->nextWriteNo = 0; - } - else - bp->nextMatchNo++; - - - wp = &bp->list[ bp->nextWriteNo++ ]; - *wp = *searchp; - - if (!flag) - { - wp->first.bestMoveSuit = 0; - wp->first.bestMoveRank = 0; - } -} - - -#ifndef SMALL_MEMORY_OPTION -void TransTable::Add( - int tricks, - int hand, - unsigned short * aggrTarget, - unsigned short * ourWinRanks, - nodeCardsType * first, - bool flag) -{ - if (lastBlockSeen[tricks][hand] == nullptr) - { - // We have recently reset the entire memory, and we were - // in the middle of a recursion. So we'll just have to - // drop this entry that we were supposed to be adding. - return; - } - - unsigned * ab[DDS_SUITS]; - unsigned * mb[DDS_SUITS]; - char low[DDS_SUITS]; - unsigned short int ag; - int w; - winMatchType TTentry; - - // Inefficient, as it also copies leastWin. - // In fact I'm not quite happy with the treatment of - // leastWin in general. - - TTentry.first = *first; - - TTentry.xorSet = 0; - - for (int ss = 0; ss < DDS_SUITS; ss++) - { - w = static_cast(ourWinRanks[ss]); - if (w == 0) - { - ab[ss] = aggr[0].aggrBytes[ss]; - mb[ss] = maskBytes[0][ss]; - low[ss] = 15; - TTentry.first.leastWin[ss] = 0; - } - else - { - w = w & (-w); /* Only lowest win */ - ag = static_cast(aggrTarget[ss] & (-w)); - - ab[ss] = aggr[ag].aggrBytes[ss]; - mb[ss] = maskBytes[ag][ss]; - low[ss] = static_cast(TTlowestRank[ag]); - - TTentry.first.leastWin[ss] = 15 - low[ss]; - TTentry.xorSet ^= aggr[ag].aggrRanks[ss]; - } - } - - // It's a bit annoying that we may be regenerating these. - // But winRanks can cause them to change after lookup(). - - TTentry.topSet1 = ab[0][0] | ab[1][0] | ab[2][0] | ab[3][0]; - TTentry.topSet2 = ab[0][1] | ab[1][1] | ab[2][1] | ab[3][1]; - TTentry.topSet3 = ab[0][2] | ab[1][2] | ab[2][2] | ab[3][2]; - TTentry.topSet4 = ab[0][3] | ab[1][3] | ab[2][3] | ab[3][3]; - - TTentry.topMask1 = mb[0][0] | mb[1][0] | mb[2][0] | mb[3][0]; - TTentry.topMask2 = mb[0][1] | mb[1][1] | mb[2][1] | mb[3][1]; - TTentry.topMask3 = mb[0][2] | mb[1][2] | mb[2][2] | mb[3][2]; - TTentry.topMask4 = mb[0][3] | mb[1][3] | mb[2][3] | mb[3][3]; - - TTentry.maskIndex = - (low[0] << 12) | (low[1] << 8) | (low[2] << 4) | low[3]; - - if (TTentry.topMask2 == 0) - TTentry.lastMaskNo = 1; - else if (TTentry.topMask3 == 0) - TTentry.lastMaskNo = 2; - else if (TTentry.topMask4 == 0) - TTentry.lastMaskNo = 3; - else - TTentry.lastMaskNo = 4; - - TransTable::CreateOrUpdate(lastBlockSeen[tricks][hand], - &TTentry, flag); -} -#endif - - - -void TransTable::PrintMatch( - winMatchType * wp, - unsigned char lengths[DDS_HANDS][DDS_SUITS]) -{ - char hands[DDS_HANDS][DDS_SUITS][TT_LINE_LEN]; - int used[DDS_HANDS][DDS_SUITS]; - - for (int h = 0; h < DDS_HANDS; h++) - { - for (int s = 0; s < DDS_SUITS; s++) - { - used[h][s] = 0; - for (int c = 0; c < TT_LINE_LEN; c++) - hands[h][s][c] = 0; - } - } - - TransTable::SetToPartialHands( - wp->topSet1, wp->topMask1, 14, 4, hands, used); - TransTable::SetToPartialHands( - wp->topSet2, wp->topMask2, 10, 4, hands, used); - TransTable::SetToPartialHands( - wp->topSet3, wp->topMask3, 6, 4, hands, used); - TransTable::SetToPartialHands( - wp->topSet4, wp->topMask4, 2, 1, hands, used); - - TransTable::DumpHands(hands, lengths); - - TransTable::PrintNodeValues(&wp->first); -} - - -void TransTable::PrintNodeValues( - nodeCardsType * np) -{ - if (!np) - { - fprintf(fp, "np == nullptr\n"); - return; - } - - fprintf(fp, "Lowest used\t%c%c, %c%c, %c%c, %c%c\n", - cardSuit[0], cardRank[ 15 - static_cast(np->leastWin[0]) ], - cardSuit[1], cardRank[ 15 - static_cast(np->leastWin[1]) ], - cardSuit[2], cardRank[ 15 - static_cast(np->leastWin[2]) ], - cardSuit[3], cardRank[ 15 - static_cast(np->leastWin[3]) ]); - - fprintf(fp, "Bounds\t\t%d to %2d tricks\n", - static_cast(np->lbound), - static_cast(np->ubound)); - - fprintf(fp, "Best move\t%c%c\n", - cardSuit[ static_cast(np->bestMoveSuit) ], - cardRank[ static_cast(np->bestMoveRank) ]); - - fprintf(fp, "\n"); -} - - -void TransTable::MakeHolding( - char * high, - unsigned len, - char * res) -{ - unsigned l = strlen(high); - strcpy(res, high); - - if (len == 0 && (l == 0 || (l == 1 && high[0] == '\0'))) - { - res[0] = '-'; - res[1] = '\0'; - return; - } - - for (unsigned i = l; i < len; i++) - { - res[i] = 'x'; - } - res[len] = '\0'; -} - - -void TransTable::DumpHands( - char hands[DDS_HANDS][DDS_SUITS][TT_LINE_LEN], - unsigned char lengths[DDS_HANDS][DDS_SUITS]) -{ - char res_a[TT_LINE_LEN], res_b[TT_LINE_LEN]; - - for (int i = 0; i < DDS_SUITS; i++) - { - TransTable::MakeHolding(hands[0][i], - static_cast(lengths[0][i]), res_a); - fprintf(fp, "%16s%s\n", "", res_a); - } - - for (int i = 0; i < DDS_SUITS; i++) - { - TransTable::MakeHolding(hands[3][i], - static_cast(lengths[3][i]), res_a); - TransTable::MakeHolding(hands[1][i], - static_cast(lengths[1][i]), res_b); - fprintf(fp, "%-16s%16s%-16s\n", res_a, "", res_b); - } - - for (int i = 0; i < DDS_SUITS; i++) - { - char res[16]; - TransTable::MakeHolding(hands[2][i], - static_cast(lengths[2][i]), res); - fprintf(fp, "%16s%s\n", "", res); - } - fprintf(fp, "\n"); -} - - -void TransTable::SetToPartialHands( - unsigned set, - unsigned mask, - int maxRank, - int numRanks, - char hands[DDS_HANDS][DDS_SUITS][TT_LINE_LEN], - int used[DDS_HANDS][DDS_SUITS]) -{ - for (int s = 0; s < DDS_SUITS; s++) - { - for (int rank = maxRank; rank > maxRank - numRanks; rank--) - { - int shift = 8 * (3 - s) + 2 * (rank - maxRank + 3); - unsigned maskCard = mask >> shift; - - if (maskCard & 3) - { - unsigned player = (set >> shift) & 3; - hands[player][s][ used[player][s]++ ] = - static_cast(cardRank[rank]); - } - } - } -} - - -void TransTable::SetFile(char * ourFname) -{ - if (strlen(ourFname) > TT_LINE_LEN) - return; - - if (fp != stdout) // Already set - return; - - strncpy(fname, ourFname, strlen(ourFname)); - - fp = fopen(fname, "w"); - if (! fp) - fp = stdout; -} - - -void TransTable::KeyToDist( - long long key, - int handDist[]) -{ - handDist[0] = static_cast((key >> 36) & 0x00000fff); - handDist[1] = static_cast((key >> 24) & 0x00000fff); - handDist[2] = static_cast((key >> 12) & 0x00000fff); - handDist[3] = static_cast((key ) & 0x00000fff); -} - - -void TransTable::DistToLengths( - int trick, - int handDist[], - unsigned char lengths[DDS_HANDS][DDS_SUITS]) -{ - for (int h = 0; h < DDS_HANDS; h++) - { - lengths[h][0] = static_cast((handDist[h] >> 8) & 0xf); - lengths[h][1] = static_cast((handDist[h] >> 4) & 0xf); - lengths[h][2] = static_cast((handDist[h] ) & 0xf); - lengths[h][3] = static_cast - (trick + 1 - - lengths[h][0] - - lengths[h][1] - - lengths[h][2]); - } -} - - -void TransTable::LenToStr( - unsigned char len[DDS_HANDS][DDS_SUITS], - char * line) -{ - sprintf(line, - "%d=%d=%d=%d \t%d=%d=%d=%d \t%d=%d=%d=%d \t%d=%d=%d=%d", - len[0][0], len[0][1], len[0][2], len[0][3], - len[1][0], len[1][1], len[1][2], len[1][3], - len[2][0], len[2][1], len[2][2], len[2][3], - len[3][0], len[3][1], len[3][2], len[3][3]); -} - - -void TransTable::PrintSuits( - int trick, - int hand) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); -#else - distHashType * dp; - int handDist[DDS_HANDS]; - unsigned char len[DDS_HANDS][DDS_SUITS]; - char line[40]; - - fprintf(fp, "%4s %2s %-8s\t%-8s\t%-8s\t%-8s\n", - "Key", - "No", - players[0], - players[1], - players[2], - players[3]); - - for (int hashkey = 0; hashkey < 256; hashkey++) - { - dp = &TTroot[trick][hand][hashkey]; - if (dp->nextNo == 0) - continue; - - for (int i = 0; i < dp->nextNo; i++) - { - if (i == 0) - fprintf(fp, "0x%02x %2d ", hashkey, dp->nextNo); - else - fprintf(fp, "%4s %2s " , "", ""); - - TransTable::KeyToDist(dp->list[i].key, handDist); - TransTable::DistToLengths(trick, handDist, len); - - TransTable::LenToStr(len, line); - fprintf(fp, "%s\n", line); - } - } - fprintf(fp, "\n"); -#endif -} - - -void TransTable::PrintAllSuits() -{ -#ifndef SMALL_MEMORY_OPTION - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - fprintf(fp, "Trick %d, hand %s\n", trick, players[hand]); - fprintf(fp, "====================\n\n"); - - TransTable::PrintSuits(trick, hand); - } - } -#endif -} - - -void TransTable::MakeHistStats( - int hist[], - int * count, - int * prod_sum, - int * prod_sumsq, - int * max_len, - int last_index) -{ - *count = 0; - *prod_sum = 0; - *prod_sumsq = 0; - *max_len = 0; - - for (int i = 1; i <= last_index; i++) - { - if (hist[i]) - { - *prod_sum += i * hist[i]; - *prod_sumsq += i * i * hist[i]; - *count += hist[i]; - - if (i > *max_len) - *max_len = i; - } - } -} - - -int TransTable::CalcPercentile( - int hist[], - double threshold, - int last_index) -{ - int cum = 0; - - for (int i = 1; i <= last_index; i++) - { - cum += hist[i]; - if (cum >= threshold) - return i; - } - return -1; -} - - -void TransTable::PrintHist( - int hist[], - int num_wraps, - int last_index) -{ - int count, prod_sum, prod_sumsq, max_len; - - TransTable::MakeHistStats(hist, - &count, &prod_sum, &prod_sumsq, &max_len, last_index); - - for (int i = 1; i <= last_index; i++) - if (hist[i]) - fprintf(fp, "%7d\t%5d\n", i, hist[i]); - - fprintf(fp, "\n"); - fprintf(fp, "Entries\t%5d\n", count); - if (count) - { - fprintf(fp, "Full\t%5d\n", num_wraps); - - double mean = prod_sum / static_cast(count); - fprintf(fp, "Average\t%5.2f\n", mean); - - double var = prod_sumsq / - static_cast(count - mean * mean); - if (var >= 0.) - fprintf(fp, "Std.dev\t%5.2f\n", sqrt(var)); - - fprintf(fp, "Maximum\t%5d\n", max_len); - } - fprintf(fp, "\n"); -} - - -void TransTable::UpdateSuitHist( - int trick, - int hand, - int hist[], - int * num_wraps) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); - UNUSED(hist); - UNUSED(num_wraps); -#else - distHashType * dp; - - * num_wraps = 0; - for (int i = 0; i <= DISTS_PER_ENTRY; i++) - hist[i] = 0; - - for (int hashkey = 0; hashkey < 256; hashkey++) - { - dp = &TTroot[trick][hand][hashkey]; - hist [ dp->nextNo ]++; - suitHist[ dp->nextNo ]++; - - if (dp->nextNo != dp->nextWriteNo) - { - (*num_wraps)++; // Not entirely correct - suitWraps++; - } - } -#endif -} - - -void TransTable::PrintSuitStats( - int trick, - int hand) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); -#else - int hist[DISTS_PER_ENTRY + 1]; - int num_wraps; - - TransTable::UpdateSuitHist(trick, hand, hist, &num_wraps); - - fprintf(fp, "Suit histogram for trick %d, hand %s\n", - trick, players[hand]); - TransTable::PrintHist(hist, num_wraps, DISTS_PER_ENTRY); -#endif -} - - -void TransTable::PrintAllSuitStats() -{ -#ifndef SMALL_MEMORY_OPTION - suitWraps = 0; - for (int i = 0; i <= DISTS_PER_ENTRY; i++) - suitHist[i] = 0; - - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - fprintf(fp, "Suit, Trick %d, hand %s\n", trick, players[hand]); - fprintf(fp, "==========================\n\n"); - TransTable::PrintSuitStats(trick, hand); - } - } - - fprintf(fp, "Overall suit histogram\n"); - TransTable::PrintHist(suitHist, suitWraps, DISTS_PER_ENTRY); -#endif -} - - -void TransTable::PrintSummarySuitStats() -{ -#ifndef SMALL_MEMORY_OPTION - int hist[DISTS_PER_ENTRY + 1]; - int count, prod_sum, prod_sumsq, - max_len, num_wraps; - - suitWraps = 0; - for (int i = 0; i <= DISTS_PER_ENTRY; i++) - suitHist[i] = 0; - - fprintf(fp, "Suit depth statistics\n\n"); - - fprintf(fp, "%5s %6s %7s %7s %7s %7s %7s P%-4.2f\n", - "Trick", - "Player", - "Entries", - "Full", - "Average", - "Std.dev", - "Maximum", - TT_PERCENTILE); - - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - TransTable::UpdateSuitHist(trick, hand, hist, &num_wraps); - TransTable::MakeHistStats(hist, - &count, &prod_sum, &prod_sumsq, &max_len, DISTS_PER_ENTRY); - - double mean = 0., var = 0.; - if (count > 0) - { - mean = prod_sum / static_cast(count); - var = prod_sumsq / - static_cast(count - mean * mean); - if (var < 0.) - var = 0.; - } - - int percentile = - TransTable::CalcPercentile(hist, - TT_PERCENTILE * count, DISTS_PER_ENTRY); - - if (count > 0) - fprintf(fp, "%5d %-6s %7d %7d %7.2f %7.2f %7d %7d\n", - trick, - players[hand], - count, - num_wraps, - mean, - sqrt(var), - max_len, - percentile); - else - fprintf(fp, "%5d %-6s %7d %7d %7s %7s %7d %7d\n", - trick, - players[hand], - count, - num_wraps, - "-", - "-", - max_len, - percentile); - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); -#endif -} - - -TransTable::winBlockType * TransTable::FindMatchingDist( - int trick, - int hand, - int handDistSought[DDS_HANDS]) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); - UNUSED(handDistSought); - return NULL; -#else - winBlockType * bp; - distHashType * dp; - int handDist[DDS_HANDS]; - - for (int hashkey = 0; hashkey < 256; hashkey++) - { - dp = &TTroot[trick][hand][hashkey]; - for (int i = 0; i < dp->nextNo; i++) - { - bp = dp->list[i].posBlock; - TransTable::KeyToDist(dp->list[i].key, handDist); - - bool same = true; - for (int h = 0; h < DDS_HANDS; h++) - { - if (handDist[h] != handDistSought[h]) - { - same = false; - break; - } - } - if (same) - return bp; - } - } - return nullptr; -#endif -} - - -void TransTable::PrintEntriesBlock( - winBlockType * bp, - unsigned char lengths[DDS_HANDS][DDS_SUITS]) -{ - char line[40]; - char lines[2][80]; - - TransTable::LenToStr(lengths, line); - - sprintf(lines[0], - "%d matches for %s\n", bp->nextMatchNo, line); - memset(lines[1], '=', 71); - lines[1][71] = '\0'; - - fprintf(fp, "%s%s\n\n", lines[0], lines[1]); - - for (int j = 0; j < bp->nextMatchNo; j++) - { - fprintf(fp, "Entry number %3d\n", j + 1); - fprintf(fp, "----------------\n\n"); - TransTable::PrintMatch(&bp->list[j], lengths); - } -} - - - -void TransTable::PrintEntriesDistAndCards( - int trick, - int hand, - unsigned short * aggrTarget, - int handDist[DDS_HANDS]) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); - UNUSED(aggrTarget); - UNUSED(handDist); -#else - char line[40]; - unsigned char len[DDS_HANDS][DDS_SUITS]; - - winBlockType * bp = - TransTable::FindMatchingDist(trick, hand, handDist); - - TransTable::DistToLengths(trick, handDist, len); - - fprintf(fp, "Looking up entry for trick %d, hand %d\n", - trick, hand); - TransTable::LenToStr(len, line); - fprintf(fp, "%s\n\n", line); - - if (! bp) - { - fprintf(fp, "Entry not found\n\n"); - return; - } - - unsigned * ab0 = aggr[ aggrTarget[0] ].aggrBytes[0]; - unsigned * ab1 = aggr[ aggrTarget[1] ].aggrBytes[1]; - unsigned * ab2 = aggr[ aggrTarget[2] ].aggrBytes[2]; - unsigned * ab3 = aggr[ aggrTarget[3] ].aggrBytes[3]; - - winMatchType TTentry; - TTentry.topSet1 = ab0[0] | ab1[0] | ab2[0] | ab3[0]; - TTentry.topSet2 = ab0[1] | ab1[1] | ab2[1] | ab3[1]; - TTentry.topSet3 = ab0[2] | ab1[2] | ab2[2] | ab3[2]; - TTentry.topSet4 = ab0[3] | ab1[3] | ab2[3] | ab3[3]; - - int matchNo = 1; - int n = bp->nextMatchNo - 1; - winMatchType * wp = &bp->list[n]; - - for (int i = n; i >= 0; i--, wp--) - { - if ((wp->topSet1 ^ TTentry.topSet1) & wp->topMask1) - continue; - - if (wp->lastMaskNo != 1) - { - if ((wp->topSet2 ^ TTentry.topSet2) & wp->topMask2) - continue; - - if (wp->lastMaskNo != 2) - { - if ((wp->topSet3 ^ TTentry.topSet3) & wp->topMask3) - continue; - } - } - - fprintf(fp, "Match number %d\n", matchNo++); - fprintf(fp, "---------------\n"); - TransTable::PrintMatch(&bp->list[i], len); - } - - if (matchNo == 1) - fprintf(fp, "%d matches for suit, none for cards\n\n", n); - else - fprintf(fp, "\n"); -#endif -} - - -void TransTable::PrintEntriesDist( - int trick, - int hand, - int handDist[DDS_HANDS]) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); - UNUSED(handDist); -#else - unsigned char len[DDS_HANDS][DDS_SUITS]; - - winBlockType * bp = - TransTable::FindMatchingDist(trick, hand, handDist); - - TransTable::DistToLengths(trick, handDist, len); - - if (! bp) - { - fprintf(fp, "Entry not found: Trick %d, hand %d\n", - trick, hand); - char line[80]; - TransTable::LenToStr(len, line); - fprintf(fp, "%s\n\n", line); - return; - } - - TransTable::PrintEntriesBlock(bp, len); -#endif -} - - -void TransTable::PrintEntries( - int trick, - int hand) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); -#else - winBlockType * bp; - distHashType * dp; - int handDist[DDS_HANDS]; - unsigned char lengths[DDS_HANDS][DDS_SUITS]; - - for (int hashkey = 0; hashkey < 256; hashkey++) - { - dp = &TTroot[trick][hand][hashkey]; - for (int i = 0; i < dp->nextNo; i++) - { - bp = dp->list[i].posBlock; - TransTable::KeyToDist(dp->list[i].key, handDist); - TransTable::DistToLengths(trick, handDist, lengths); - - TransTable::PrintEntriesBlock(bp, lengths); - } - } -#endif -} - - -void TransTable::PrintAllEntries() -{ -#ifndef SMALL_MEMORY_OPTION - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - fprintf(fp, "Entries, trick %d, hand %s\n", trick, players[hand]); - fprintf(fp, "==============================\n\n"); - TransTable::PrintEntries(trick, hand); - } - } - fprintf(fp, "\n"); -#endif -} - - -void TransTable::UpdateEntryHist( - int trick, - int hand, - int hist[], - int * num_wraps) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); - UNUSED(hist); - UNUSED(num_wraps); -#else - distHashType * dp; - - * num_wraps = 0; - for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) - hist[i] = 0; - - for (int hashkey = 0; hashkey < 256; hashkey++) - { - dp = &TTroot[trick][hand][hashkey]; - for (int i = 0; i < dp->nextNo; i++) - { - int c = dp->list[i].posBlock->nextMatchNo; - hist [c]++; - suitHist[c]++; - - if (c != dp->list[i].posBlock->nextWriteNo) - { - (*num_wraps)++; // Not entirely correct - suitWraps++; - } - } - } -#endif -} - - -void TransTable::PrintEntryStats( - int trick, - int hand) -{ -#ifdef SMALL_MEMORY_OPTION - UNUSED(trick); - UNUSED(hand); -#else - int hist[BLOCKS_PER_ENTRY + 1]; - int num_wraps; - - TransTable::UpdateEntryHist(trick, hand, hist, &num_wraps); - - fprintf(fp, "Entry histogram for trick %d, hand %s\n", - trick, players[hand]); - TransTable::PrintHist(hist, num_wraps, BLOCKS_PER_ENTRY); -#endif -} - - -void TransTable::PrintAllEntryStats() -{ -#ifndef SMALL_MEMORY_OPTION - suitWraps = 0; - for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) - suitHist[i] = 0; - - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - fprintf(fp, "Entry, trick %d, hand %s\n", trick, players[hand]); - fprintf(fp, "============================\n\n"); - TransTable::PrintEntryStats(trick, hand); - } - } - - fprintf(fp, "Overall entry histogram\n"); - TransTable::PrintHist(suitHist, suitWraps, BLOCKS_PER_ENTRY); -#endif -} - - -int TransTable::EffectOfBlockBound( - int hist[], - int size) -{ - // Calculates the number of blocks used if the blocks - // are divided up in units of size, rather than in units - // of BLOCKS_PER_ENTRY. Only makes sense if size is less - // than BLOCKS_PER_ENTRY, as we won't have statistics for - // how many blocks above BLOCKS_PER_ENTRY would be created - // if BLOCKS_PER_ENTRY were larger. - - int cum_memory = 0; - int unit_size = 0; - - for (int i = 1; i <= BLOCKS_PER_ENTRY; i++) - { - if ((i - 1) % size == 0) - unit_size += size; - - cum_memory += hist[i] * unit_size; - } - return cum_memory; -} - - -// #define TT_MEMORY_SCENARIO - -void TransTable::PrintSummaryEntryStats() -{ -#ifndef SMALL_MEMORY_OPTION - int hist[BLOCKS_PER_ENTRY + 1]; - int count, prod_sum, prod_sumsq, - max_len, num_wraps; - - int cumCount = 0; - double cumProd = 0.; -#ifdef TT_MEMORY_SCENARIO - int cumMemory = 0; -#endif - - suitWraps = 0; - for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) - suitHist[i] = 0; - - fprintf(fp, "Entry depth statistics\n\n"); - - fprintf(fp, "%5s %6s %7s %7s %7s %7s %7s P%-4.2f\n", - "Trick", - "Player", - "Entries", - "Full", - "Average", - "Std.dev", - "Maximum", - TT_PERCENTILE); - - for (int trick = 11; trick >= 1; trick--) - { - for (int hand = 0; hand < DDS_HANDS; hand++) - { - TransTable::UpdateEntryHist(trick, hand, hist, &num_wraps); - TransTable::MakeHistStats(hist, - &count, &prod_sum, &prod_sumsq, &max_len, BLOCKS_PER_ENTRY); - - cumCount += count; - cumProd += prod_sum; -#ifdef TT_MEMORY_SCENARIO - cumMemory += TransTable::EffectOfBlockBound(hist, 20); -#endif - - double mean = prod_sum / static_cast(count); - double var = prod_sumsq / - static_cast(count - mean * mean); - if (var < 0.) - var = 0.; - - int percentile = - TransTable::CalcPercentile(hist, - TT_PERCENTILE * count, BLOCKS_PER_ENTRY); - - fprintf(fp, "%5d %-6s %7d %7d %7.2f %7.2f %7d %7d\n", - trick, - players[hand], - count, - num_wraps, - mean, - sqrt(var), - max_len, - percentile); - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); - - fprintf(fp, "Blocks counted\t%8d\n", cumCount); - - fprintf(fp, "Blocks produced\t%8d\n", TransTable::BlocksInUse()); - -#ifdef TT_MEMORY_SCENARIO - fprintf(fp, "Mem scenario\t%7.2f%%\n", - 100. * cumMemory / - (static_cast(BLOCKS_PER_ENTRY * cumCount))); -#endif - - if (cumCount) - fprintf(fp, "Fullness\t%7.2f%%\n", - 100. * cumProd / (BLOCKS_PER_ENTRY * cumCount)); - fprintf(fp, "\n"); -#endif -} - - -void TransTable::PrintPageSummary() -{ -#ifndef SMALL_MEMORY_OPTION - if (pageStats.numResets == 0) - return; - - fprintf(fp, "Page statistics\n\n"); - - fprintf(fp, "%-10s %6s %6s\n", - "Type", "Number", "Avg"); - - fprintf(fp, "%-10s %6d\n", - "Resets", - pageStats.numResets); - fprintf(fp, "%-10s %6d %6.2f\n", - "calloc", - pageStats.numCallocs, - pageStats.numCallocs / static_cast(pageStats.numResets)); - fprintf(fp, "%-10s %6d %6.2f\n", - "free", - pageStats.numFrees, - pageStats.numFrees / static_cast(pageStats.numResets)); - fprintf(fp, "%-10s %6d %6.2f\n\n", - "harvest", - pageStats.numHarvests, - pageStats.numHarvests / static_cast(pageStats.numResets)); -#endif -} - -void TransTable::PrintNodeStats() -{ -#ifdef SMALL_MEMORY_OPTION - for (int k = 13; k > 0; k--) - fprintf(fp, "Trick %d: Created nodes: %ld\n", k, - static_cast(aggrLenSets[k - 1])); - fprintf(fp, "\n"); -#endif -} - -void TransTable::PrintResetStats() -{ -#ifdef SMALL_MEMORY_OPTION - fprintf(fp, "Total no of Resets: %d\n", statsResets.noOfResets); - fprintf(fp, "\n"); - - for (int k = 0; k <= 5; k++) - fprintf(fp, "%s: %d\n", resetText[k], statsResets.aggrResets[k]); - fprintf(fp, "\n"); -#endif -} - diff --git a/src/TransTable.h b/src/TransTable.h index 0d880521..ab97f3f5 100644 --- a/src/TransTable.h +++ b/src/TransTable.h @@ -2,62 +2,40 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#ifndef DDS_TRANSTABLES_H -#define DDS_TRANSTABLES_H - /* - This is an object for managing transposition tables and the - associated memory. + This is the parent class of TransTableS and TransTableL. + Those two are different implementations. The S version has a + much smaller memory and a somewhat slower execution time. */ +#ifndef DDS_TRANSTABLE_H +#define DDS_TRANSTABLE_H -#include -#include -#include -#include "dds.h" -#include "../include/dll.h" - -// ResetMemory reasons -#define UNKNOWN_REASON 0 -#define TOO_MANY_NODES 1 -#define NEW_DEAL 2 -#define NEW_TRUMP 3 -#define MEMORY_EXHAUSTED 4 -#define FREE_THREAD_MEM 5 - +#include +#include +#include -// For SMALL_MEMORY_OPTION -#define NSIZE 50000 -#define WSIZE 50000 -#define NINIT 60000 -#define WINIT 170000 -#define LSIZE 200 // Per trick and first hand - -// For full memory option -#define NUM_PAGES_DEFAULT 15 -#define NUM_PAGES_MAXIMUM 25 -#define BLOCKS_PER_PAGE 1000 -#define DISTS_PER_ENTRY 32 -#define BLOCKS_PER_ENTRY 125 -#define FIRST_HARVEST_TRICK 8 -#define HARVEST_AGE 10000 - -#define TT_BYTES 4 -#define TT_TRICKS 12 - -#define TT_LINE_LEN 20 +#include "dds.h" -#define TT_PERCENTILE 0.9 +using namespace std; -#define HISTSIZE 100000 +enum TTresetReason +{ + TT_RESET_UNKNOWN = 0, + TT_RESET_TOO_MANY_NODES = 1, + TT_RESET_NEW_DEAL = 2, + TT_RESET_NEW_TRUMP = 3, + TT_RESET_MEMORY_EXHAUSTED = 4, + TT_RESET_FREE_MEMORY = 5, + TT_RESET_SIZE = 6 +}; -// Also used in ABSearch struct nodeCardsType // 8 bytes { char ubound; // For N-S @@ -67,453 +45,121 @@ struct nodeCardsType // 8 bytes char leastWin[DDS_SUITS]; }; - - -class TransTable -{ - private: - - // Structures for the small memory option. - - struct winCardType - { - int orderSet; - int winMask; - struct nodeCardsType * first; - struct winCardType * prevWin; - struct winCardType * nextWin; - struct winCardType * next; - }; - - struct posSearchTypeSmall - { - struct winCardType * posSearchPoint; - long long suitLengths; - struct posSearchTypeSmall * left; - struct posSearchTypeSmall * right; - }; - - struct ttAggrType - { - int aggrRanks[DDS_SUITS]; - int winMask[DDS_SUITS]; - }; - - struct statsResetsType - { - int noOfResets; - int aggrResets[6]; - }; - - - // Structures for the full memory option. - - struct winMatchType // 52 bytes - { - unsigned xorSet; - unsigned topSet1 , topSet2 , topSet3 , topSet4 ; - unsigned topMask1, topMask2, topMask3, topMask4; - int maskIndex; - int lastMaskNo; - nodeCardsType first; - }; - - struct winBlockType // 6508 bytes when BLOCKS_PER_ENTRY == 125 - { - int nextMatchNo; - int nextWriteNo; - // int timestampWrite; - int timestampRead; - winMatchType list[BLOCKS_PER_ENTRY]; - }; - - struct posSearchType // 16 bytes (inefficiency, 12 bytes enough) - { - winBlockType * posBlock; - long long key; - }; - - struct distHashType // 520 bytes when DISTS_PER_ENTRY == 32 - { - int nextNo; - int nextWriteNo; - posSearchType list[DISTS_PER_ENTRY]; - }; - - struct aggrType // 80 bytes - { - unsigned aggrRanks[DDS_SUITS]; - unsigned aggrBytes[DDS_SUITS][TT_BYTES]; - }; - - struct poolType // 16 bytes - { - poolType * next; - poolType * prev; - int nextBlockNo; - winBlockType * list; - }; - - struct pageStatsType - { - int numResets, - numCallocs, - numFrees, - numHarvests, - lastCurrent; - }; - - struct harvestedType // 16 bytes - { - int nextBlockNo; - winBlockType * list [BLOCKS_PER_PAGE]; - }; - - enum memStateType - { - FROM_POOL, - FROM_HARVEST - }; - - -#ifdef SMALL_MEMORY_OPTION - // Private data for the small memory version. - - long long aggrLenSets[14]; - struct statsResetsType statsResets; - - struct winCardType temp_win[5]; - int nodeSetSizeLimit; - int winSetSizeLimit; - unsigned long long maxmem; - unsigned long long allocmem; - unsigned long long summem; - int wmem; - int nmem; - int maxIndex; - int wcount; - int ncount; - bool clearTTflag; - int windex; - struct ttAggrType * aggp; - - struct posSearchTypeSmall * rootnp[14][DDS_HANDS]; - struct winCardType ** pw; - struct nodeCardsType ** pn; - struct posSearchTypeSmall ** pl[14][DDS_HANDS]; - struct nodeCardsType * nodeCards; - struct winCardType * winCards; - struct posSearchTypeSmall * posSearch[14][DDS_HANDS]; - int nodeSetSize; /* Index with range 0 to nodeSetSizeLimit */ - int winSetSize; /* Index with range 0 to winSetSizeLimit */ - int lenSetInd[14][DDS_HANDS]; - int lcount[14][DDS_HANDS]; - - const char * resetText[6]; - - long long suitLengths[14]; -#else - // Private data for the full memory version. - memStateType memState; - - int pagesDefault, - pagesCurrent, - pagesMaximum; - - int harvestTrick, - harvestHand; - - pageStatsType pageStats; - - - // aggr is constant for a given hand. - aggrType aggr[8192]; // 64 KB - - // This is the real transposition table. - // The last index is the hash. - // 6240 KB with above assumptions - // distHashType TTroot[TT_TRICKS][DDS_HANDS][256]; - distHashType * TTroot[TT_TRICKS][DDS_HANDS]; - - // It is useful to remember the last block we looked at. - winBlockType * lastBlockSeen[TT_TRICKS][DDS_HANDS]; - - // The pool of card entries for a given suit distribution. - poolType * poolp; - winBlockType * nextBlockp; - harvestedType harvested; +#ifdef _MSC_VER + // Disable warning for unused arguments. + #pragma warning(push) + #pragma warning(disable: 4100) #endif - int timestamp; - int TTInUse; - - // Private functions for small memory option. - - void Wipe(); - - void AddWinSet(); - - void AddNodeSet(); - - void AddLenSet(int trick, int firstHand); - - void BuildSOP( - unsigned short ourWinRanks[DDS_SUITS], - unsigned short aggr[DDS_SUITS], - nodeCardsType * first, - long long suitLengths, - int tricks, - int firstHand, - int depth, - bool flag); - - struct nodeCardsType * BuildPath( - int * winMask, - int * winOrderSet, - int ubound, - int lbound, - char bestMoveSuit, - char bestMoveRank, - struct posSearchTypeSmall * nodep, - bool * result); - - struct posSearchTypeSmall * SearchLenAndInsert( - struct posSearchTypeSmall * rootp, - long long key, - bool insertNode, - int trick, - int firstHand, - bool * result); - - struct nodeCardsType * UpdateSOP( - int ubound, - int lbound, - char bestMoveSuit, - char bestMoveRank, - struct nodeCardsType * nodep); - - struct nodeCardsType * FindSOP( - int orderSet[], - int limit, - struct winCardType * nodeP, - int firstHand, - bool * lowerFlag); - - - // Full memory private functions, and common functions. - - void InitTT(); - - void ReleaseTT(); - - void SetConstants(); - - int hash8(int * handDist); - - winBlockType * GetNextCardBlock(); - - winBlockType * LookupSuit( - distHashType * dp, - long long key, - bool * empty); - - - nodeCardsType * LookupCards( - winMatchType * searchp, - winBlockType * bp, - int limit, - bool * lowerFlag); - - void CreateOrUpdate( - winBlockType * bp, - winMatchType * searchp, - bool flag); - - bool Harvest(); - - // Debug - - FILE * fp; - - char fname[TT_LINE_LEN]; - - // Really the maximum of BLOCKS_PER_ENTRY and DISTS_PER_ENTRY - int suitHist[BLOCKS_PER_ENTRY + 1], - suitWraps; - - void KeyToDist( - long long key, - int handDist[]); - - void DistToLengths( - int trick, - int handDist[], - unsigned char lengths[DDS_HANDS][DDS_SUITS]); - - void LenToStr( - unsigned char lengths[DDS_HANDS][DDS_SUITS], - char * line); - - void MakeHistStats( - int hist[], - int * count, - int * prod_sum, - int * prod_sumsq, - int * max_len, - int last_index); - - int CalcPercentile( - int hist[], - double threshold, - int last_index); - - void PrintHist( - int hist[], - int num_wraps, - int last_index); - - void UpdateSuitHist( - int trick, - int hand, - int hist[], - int * num_wraps); - - winBlockType * FindMatchingDist( - int trick, - int hand, - int handDistSought[DDS_HANDS]); - - void PrintEntriesBlock( - winBlockType * bp, - unsigned char lengths[DDS_HANDS][DDS_SUITS]); - - void UpdateEntryHist( - int trick, - int hand, - int hist[], - int * num_wraps); - - int EffectOfBlockBound( - int hist[], - int size); - - void PrintNodeValues( - nodeCardsType * np); - - void PrintMatch( - winMatchType * wp, - unsigned char lengths[DDS_HANDS][DDS_SUITS]); - - void MakeHolding( - char * high, - unsigned len, - char * res); +#ifdef __APPLE__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-parameter" +#endif - void DumpHands( - char hands[DDS_SUITS][DDS_HANDS][TT_LINE_LEN], - unsigned char lengths[DDS_HANDS][DDS_SUITS]); - - void SetToPartialHands( - unsigned set, - unsigned mask, - int maxRank, - int numRanks, - char hands[DDS_SUITS][DDS_HANDS][TT_LINE_LEN], - int used[DDS_SUITS][DDS_HANDS]); - - int BlocksInUse(); +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +class TransTable +{ public: - TransTable(); + TransTable(){}; - ~TransTable(); + virtual ~TransTable(){}; - void Init(int handLookup[][15]); + virtual void Init(const int handLookup[][15]){}; - void SetMemoryDefault(int megabytes); + virtual void SetMemoryDefault(const int megabytes){}; - void SetMemoryMaximum(int megabytes); + virtual void SetMemoryMaximum(const int megabytes){}; - void MakeTT(); + virtual void MakeTT(){}; - void ResetMemory(int reason); + virtual void ResetMemory(const TTresetReason reason){}; - void ReturnAllMemory(); + virtual void ReturnAllMemory(){}; - double MemoryInUse(); + virtual double MemoryInUse() const {return 0.;}; - nodeCardsType * Lookup( - int trick, - int hand, - unsigned short * aggrTarget, - int * handDist, - int limit, - bool * lowerFlag); + virtual nodeCardsType const * Lookup( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[], + const int limit, + bool& lowerFlag){return NULL;}; - void Add( - int trick, - int hand, - unsigned short * aggrTarget, - unsigned short * winRanks, - nodeCardsType * first, - bool flag); + virtual void Add( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const unsigned short winRanksArg[], + const nodeCardsType& first, + const bool flag){}; - // Debug functions + virtual void PrintSuits( + ofstream& fout, + const int trick, + const int hand) const {}; - void SetFile( - char * fname); + virtual void PrintAllSuits(ofstream& fout) const {}; - void PrintSuits( - int trick, - int hand); + virtual void PrintSuitStats( + ofstream& fout, + const int trick, + const int hand) const {}; - void PrintAllSuits(); + virtual void PrintAllSuitStats(ofstream& fout) const {}; - void PrintSuitStats( - int trick, - int hand); + virtual void PrintSummarySuitStats(ofstream& fout) const {}; - void PrintAllSuitStats(); + virtual void PrintEntriesDist( + ofstream& fout, + const int trick, + const int hand, + const int handDist[]) const {}; - void PrintSummarySuitStats(); + virtual void PrintEntriesDistAndCards( + ofstream& fout, + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[]) const {}; - // Examples: - // int hd[DDS_HANDS] = { 0x0342, 0x0334, 0x0232, 0x0531 }; - // thrp->transTable.PrintEntriesDist(11, 1, hd); - // unsigned short ag[DDS_HANDS] = - // { 0x1fff, 0x1fff, 0x0f75, 0x1fff }; - // thrp->transTable.PrintEntriesDistAndCards(11, 1, ag, hd); + virtual void PrintEntries( + ofstream& fout, + const int trick, + const int hand) const {}; - void PrintEntriesDist( - int trick, - int hand, - int handDist[DDS_HANDS]); + virtual void PrintAllEntries(ofstream& fout) const {}; - void PrintEntriesDistAndCards( - int trick, - int hand, - unsigned short * aggrTarget, - int handDist[DDS_HANDS]); + virtual void PrintEntryStats( + ofstream& fout, + const int trick, + const int hand) const {}; - void PrintEntries( - int trick, - int hand); + virtual void PrintAllEntryStats(ofstream& fout) const {}; - void PrintAllEntries(); + virtual void PrintSummaryEntryStats(ofstream& fout) const {}; - void PrintEntryStats( - int trick, - int hand); + virtual void PrintPageSummary(ofstream& fout) const {}; - void PrintAllEntryStats(); + virtual void PrintNodeStats(ofstream& fout) const {}; - void PrintSummaryEntryStats(); + virtual void PrintResetStats(ofstream& fout) const {}; +}; - void PrintPageSummary(); +#ifdef _MSC_VER + #pragma warning(pop) +#endif - void PrintNodeStats(); +#ifdef __APPLE__ + #pragma clang diagnostic pop +#endif - void PrintResetStats(); -}; +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif #endif diff --git a/src/TransTableL.cpp b/src/TransTableL.cpp new file mode 100644 index 00000000..1fccfe95 --- /dev/null +++ b/src/TransTableL.cpp @@ -0,0 +1,1841 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +/* + Explanation of full memory version: + + There are some constants that only need to be calculated + once. In fact they are the same for all instances of the + object. In order to save time and memory, they share a + single memory. + + Each 13-bit number, aggr, represents a possible set of cards + remaining in a suit. For example, 0x15a2 represents + A(1) QT(5) 97(a) 3(2). + + TTlowestRank[aggr] gives the lowest relative rank that is in + play in aggr. The ace is 14, the deuce is 2. A void counts as + rank 15 ("not even the ace"). It would go horribly wrong + if this rank were chosen to be 0, as might seem intuitive. + This is not the same as lowestRank, the lowest absolute rank. + + maskBytes[aggr][suit] is a set of 4 32-bit integers, + where suit is 0 ..3 (spades .. clubs). Each integer only + has 8 of its 32 bits set, but these 8 bits could be either + in the top byte (byte 0) or any of the others (bytes 1 ..3). + The bytes are abbreviated as B0 .. B3 below. + + int 0 int 1 int 2 int 3 + suit 0, spades B0 R0 B0 R1 B0 R2 B0 R3 + suit 1, hearts B1 R0 B1 R1 B1 R2 B1 R3 + suit 2, diamonds B2 R0 B2 R1 B2 R2 B2 + suit 3, clubs B3 R0 B3 R1 B3 R2 B3 + + R0 .. R3 are explained now. The purpose of maskBytes is + to generate 32-bit masks for later use with actual suits. + As a card can be with either of 4 players, 2 bits are needed + to encode the position of a card. Therefore the masks also + need 2 bits per card, even though the 2 bits are identical. + + In the table, R0 means the top byte (8 bits = 4 cards) of + a holding. + + R0 AKQJ + R1 T987 + R2 6543 + R3 2 + + For example, if the ace is held by North, the king by South, the + queen and jack by West, then the top byte for that SUIT would be + + 00(North) 10(South) 11(West) 11(West) + + The MASK for that holding would be 11 11 11 11, as all four + cards are in play. + + If the jack were missing, because it had already been played, + then the suit would be 00 10 11 00 (a missing card is also + encoded as 00), and the mask would be 11 11 11 00. + + Later on, when we have a specific set of spades .. clubs, + we want to check whether those cards are already in the + transposition table. As far as the necessary masks is + concerned, this is generated by an OR (|) of the four + 32-bit integers in a column of the table above. + + So the first column yields four bytes which are already + shifted in place, all corresponding to R0. The mask + corresponds to the AKQJ of the four suits in order. + + It's not really AKQJ, but the four highest cards still in + play in that suit. So missing cards are always at the end + of the list. +*/ + + +#include +#include +#include + +#include "TransTableL.h" +#include "debug.h" + + +extern unsigned char cardRank[16]; +extern char relRank[8192][15]; + +static bool _constantsSet = false; +static int TTlowestRank[8192]; +static unsigned maskBytes[8192][DDS_SUITS][TT_BYTES]; + +static vector players = +{ + "North", "East", "South", "West" +}; + + +TransTableL::TransTableL() +{ + if (! _constantsSet) + { + _constantsSet = true; + TransTableL::SetConstants(); + } + + poolp = nullptr; + pagesDefault = NUM_PAGES_DEFAULT; + pagesMaximum = NUM_PAGES_MAXIMUM; + pagesCurrent = 0; + + memState = FROM_POOL; + harvestTrick = FIRST_HARVEST_TRICK; + harvestHand = 0; + + harvested.nextBlockNo = 0; + + timestamp = 0; + + pageStats.numResets = 0; + pageStats.numCallocs = 0; + pageStats.numFrees = 0; + pageStats.numHarvests = 0; + pageStats.lastCurrent = 0; + + TTInUse = 0; +} + + +TransTableL::~TransTableL() +{ + TransTableL::ReturnAllMemory(); +} + + +void TransTableL::SetConstants() +{ + unsigned int topBitRank = 1; + TTlowestRank[0] = 15; // Void + unsigned winMask[8192]; + winMask[0] = 0; + + for (unsigned ind = 1; ind < 8192; ind++) + { + if (ind >= (topBitRank + topBitRank)) /* Next top bit */ + topBitRank <<= 1; + + // winMask is a growing list of 11's. In the end it will + // have 26 bits, so 13 groups of two bits. It always + // consists of all 11's, then all 00's. + + winMask[ind] = (winMask[ind ^ topBitRank] >> 2) | (3 << 24); + + maskBytes[ind][0][0] = (winMask[ind] << 6) & 0xff000000; + maskBytes[ind][0][1] = (winMask[ind] << 14) & 0xff000000; + maskBytes[ind][0][2] = (winMask[ind] << 22) & 0xff000000; + maskBytes[ind][0][3] = (winMask[ind] << 30) & 0xff000000; + + maskBytes[ind][1][0] = (winMask[ind] >> 2) & 0x00ff0000; + maskBytes[ind][1][1] = (winMask[ind] << 6) & 0x00ff0000; + maskBytes[ind][1][2] = (winMask[ind] << 14) & 0x00ff0000; + maskBytes[ind][1][3] = (winMask[ind] << 22) & 0x00ff0000; + + maskBytes[ind][2][0] = (winMask[ind] >> 10) & 0x0000ff00; + maskBytes[ind][2][1] = (winMask[ind] >> 2) & 0x0000ff00; + maskBytes[ind][2][2] = (winMask[ind] << 6) & 0x0000ff00; + maskBytes[ind][2][3] = (winMask[ind] << 14) & 0x0000ff00; + + maskBytes[ind][3][0] = (winMask[ind] >> 18) & 0x000000ff; + maskBytes[ind][3][1] = (winMask[ind] >> 10) & 0x000000ff; + maskBytes[ind][3][2] = (winMask[ind] >> 2) & 0x000000ff; + maskBytes[ind][3][3] = (winMask[ind] << 6) & 0x000000ff; + + TTlowestRank[ind] = TTlowestRank[ind ^ topBitRank] - 1; + } +} + + +void TransTableL::Init(const int handLookup[][15]) +{ + // This is very similar to SetConstants, except that it + // happens with actual cards. It also makes sense to + // keep a record of aggrRanks for each suit. These are + // only used later for xorSet. + + unsigned int topBitRank = 1; + unsigned int topBitNo = 2; + aggrType * ap; + + for (int s = 0; s < DDS_SUITS; s++) + { + aggr[0].aggrRanks[s] = 0; + aggr[0].aggrBytes[s][0] = 0; + aggr[0].aggrBytes[s][1] = 0; + aggr[0].aggrBytes[s][2] = 0; + aggr[0].aggrBytes[s][3] = 0; + } + + for (unsigned ind = 1; ind < 8192; ind++) + { + if (ind >= (topBitRank << 1)) + { + /* Next top bit */ + topBitRank <<= 1; + topBitNo++; + } + + aggr[ind] = aggr[ind ^ topBitRank]; + ap = &aggr[ind]; + + for (int s = 0; s < DDS_SUITS; s++) + { + ap->aggrRanks[s] = ap->aggrRanks[s] >> 2 | + static_cast(handLookup[s][topBitNo] << 24); + } + + ap->aggrBytes[0][0] = (ap->aggrRanks[0] << 6) & 0xff000000; + ap->aggrBytes[0][1] = (ap->aggrRanks[0] << 14) & 0xff000000; + ap->aggrBytes[0][2] = (ap->aggrRanks[0] << 22) & 0xff000000; + ap->aggrBytes[0][3] = (ap->aggrRanks[0] << 30) & 0xff000000; + + ap->aggrBytes[1][0] = (ap->aggrRanks[1] >> 2) & 0x00ff0000; + ap->aggrBytes[1][1] = (ap->aggrRanks[1] << 6) & 0x00ff0000; + ap->aggrBytes[1][2] = (ap->aggrRanks[1] << 14) & 0x00ff0000; + ap->aggrBytes[1][3] = (ap->aggrRanks[1] << 22) & 0x00ff0000; + + ap->aggrBytes[2][0] = (ap->aggrRanks[2] >> 10) & 0x0000ff00; + ap->aggrBytes[2][1] = (ap->aggrRanks[2] >> 2) & 0x0000ff00; + ap->aggrBytes[2][2] = (ap->aggrRanks[2] << 6) & 0x0000ff00; + ap->aggrBytes[2][3] = (ap->aggrRanks[2] << 14) & 0x0000ff00; + + ap->aggrBytes[3][0] = (ap->aggrRanks[3] >> 18) & 0x000000ff; + ap->aggrBytes[3][1] = (ap->aggrRanks[3] >> 10) & 0x000000ff; + ap->aggrBytes[3][2] = (ap->aggrRanks[3] >> 2) & 0x000000ff; + ap->aggrBytes[3][3] = (ap->aggrRanks[3] << 6) & 0x000000ff; + } +} + + +void TransTableL::SetMemoryDefault(int megabytes) +{ + double blockMem = BLOCKS_PER_PAGE * sizeof(winBlockType) / + static_cast(1024.); + + pagesDefault = static_cast((1024 * megabytes) / blockMem); +} + + +void TransTableL::SetMemoryMaximum(int megabytes) +{ + double blockMem = BLOCKS_PER_PAGE * sizeof(winBlockType) / + static_cast(1024.); + + pagesMaximum = static_cast((1024 * megabytes) / blockMem); +} + + +///////////////////////////////////////////////////////////// +// // +// Full memory TT functions. // +// // +///////////////////////////////////////////////////////////// + +void TransTableL::MakeTT() +{ + if (! TTInUse) + { + TTInUse = 1; + + for (int t = 0; t < TT_TRICKS; t++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + TTroot[t][h] = static_cast + (malloc(256 * sizeof(distHashType))); + + if (TTroot[t][h] == nullptr) + exit(1); + } + } + } + + TransTableL::InitTT(); +} + + +void TransTableL::InitTT() +{ + for (int c = 0; c < TT_TRICKS; c++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + for (int i = 0; i < 256; i++) + { + TTroot[c][h][i].nextNo = 0; + TTroot[c][h][i].nextWriteNo = 0; + + } + lastBlockSeen[c][h] = nullptr; + } + } +} + + +void TransTableL::ReleaseTT() +{ + if (! TTInUse) + return; + TTInUse = 0; + + for (int t = 0; t < TT_TRICKS; t++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + if (TTroot[t][h] == nullptr) + continue; + + free(TTroot[t][h]); + } + } +} + + +void TransTableL::ResetMemory(const TTresetReason reason) +{ + UNUSED(reason); + if (poolp == nullptr) + return; + + pageStats.numResets++; + pageStats.numCallocs += pagesCurrent - pageStats.lastCurrent; + pageStats.lastCurrent = pagesCurrent; + + while (pagesCurrent > pagesDefault) + { + free(poolp->list); + poolp = poolp->prev; + + free(poolp->next); + poolp->next = nullptr; + + pagesCurrent--; + } + + pageStats.numFrees += pageStats.lastCurrent - pagesCurrent; + pageStats.lastCurrent = pagesCurrent; + + while (poolp->prev) + poolp = poolp->prev; + + poolp->nextBlockNo = 0; + nextBlockp = poolp->list; + + TransTableL::InitTT(); + + timestamp = 0; + + memState = FROM_POOL; + + return; +} + + +void TransTableL::ReturnAllMemory() +{ + poolType * tmp; + + if (poolp) + { + while (poolp->next) + poolp = poolp->next; + + while (poolp) + { + free(poolp->list); + tmp = poolp; + poolp = poolp->prev; + free(tmp); + } + } + + pagesCurrent = 0; + + pageStats.numResets = 0; + pageStats.numCallocs = 0; + pageStats.numFrees = 0; + pageStats.numHarvests = 0; + pageStats.lastCurrent = 0; + + TransTableL::ReleaseTT(); + + return; +} + + +int TransTableL::BlocksInUse() const +{ + poolType * pp = poolp; + int count = 0; + + do + { + count += pp->nextBlockNo; + pp = pp->prev; + } + while (pp); + + return count; +} + + +double TransTableL::MemoryInUse() const +{ + int blockMem = BLOCKS_PER_PAGE * pagesCurrent * + static_cast(sizeof(winBlockType)); + int aggrMem = 8192 * static_cast(sizeof(aggrType)); + int rootMem = TT_TRICKS * DDS_HANDS * 256 * + static_cast(sizeof(distHashType)); + + return (blockMem + aggrMem + rootMem) / static_cast(1024.); +} + + +TransTableL::winBlockType * TransTableL::GetNextCardBlock() +{ + /* + Spaghetti code. The basic idea is that there is a pool of + pages. When a page runs out, we get a next pool. But we're + only allowed a certain maximum number, and calloc might also + fail before then. We have a default number of pages that + we don't give back voluntarily once we have acquired them, + but we give back anything more than that at the end of each + hand. If this overall mechanism fails, then we try to harvest + old entries scattered throughout the TT memory. If we get + enough for a "page", then we use that single page, and if + that runs out later, we try to harvest some more, starting + where we left off harvesting last time. If the harvesting also + fails, then we reset whatever TT memory we do have, and we + continue with that. + */ + + if (poolp == nullptr) + { + // Have to be able to get at least one pool. + poolp = static_cast(calloc(1, sizeof(poolType))); + if (poolp == nullptr) + exit(1); + + poolp->list = static_cast + (malloc(BLOCKS_PER_PAGE * sizeof(winBlockType))); + + if (! poolp->list) + exit(1); + + poolp->next = nullptr; + poolp->prev = nullptr; + poolp->nextBlockNo = 1; + + nextBlockp = poolp->list; + + pagesCurrent++; + + return nextBlockp++; + } + else if (memState == FROM_HARVEST) + { + // Not allowed to get more memory, so reuse old one. + int n = harvested.nextBlockNo; + if (n == BLOCKS_PER_PAGE) + { + if (! TransTableL::Harvest()) + { + TransTableL::ResetMemory(TT_RESET_UNKNOWN); + poolp->nextBlockNo++; + return nextBlockp++; + } + n = 0; + } + + harvested.nextBlockNo++; + return harvested.list[n]; + } + else if (poolp->nextBlockNo == BLOCKS_PER_PAGE) + { + if (poolp->next) + { + // Reuse a dormant block that has not been freed. + poolp = poolp->next; + poolp->nextBlockNo = 1; + nextBlockp = poolp->list; + + return nextBlockp++; + } + else if (pagesCurrent == pagesMaximum) + { + // Have to try to reclaim memory. + if (! TransTableL::Harvest()) + { + TransTableL::ResetMemory(TT_RESET_UNKNOWN); + poolp->nextBlockNo++; + return nextBlockp++; + } + + memState = FROM_HARVEST; + harvested.nextBlockNo++; + return harvested.list[0]; + } + else + { + // Make a new pool. + poolType * newpoolp = static_cast + (calloc(1, sizeof(poolType))); + + if (newpoolp == nullptr) + { + // Unexpected, but try harvesting before we give up + // and start over. + if (! TransTableL::Harvest()) + { + TransTableL::ResetMemory(TT_RESET_UNKNOWN); + poolp->nextBlockNo++; + return nextBlockp++; + } + + memState = FROM_HARVEST; + harvested.nextBlockNo++; + return harvested.list[0]; + } + + newpoolp->list = static_cast + (malloc(BLOCKS_PER_PAGE * sizeof(winBlockType))); + + if (! newpoolp->list) + { + if (! TransTableL::Harvest()) + { + TransTableL::ResetMemory(TT_RESET_UNKNOWN); + poolp->nextBlockNo++; + return nextBlockp++; + } + + memState = FROM_HARVEST; + harvested.nextBlockNo++; + return harvested.list[0]; + } + + newpoolp->nextBlockNo = 1; + newpoolp->next = nullptr; + newpoolp->prev = poolp; + + poolp->next = newpoolp; + poolp = newpoolp; + + nextBlockp = newpoolp->list; + + pagesCurrent++; + + return nextBlockp++; + } + } + + poolp->nextBlockNo++; + return nextBlockp++; +} + + +bool TransTableL::Harvest() +{ + distHashType * rootptr = TTroot[harvestTrick][harvestHand]; + distHashType * ptr; + winBlockType * bp; + + int trick = harvestTrick; + int hand = harvestHand; + int hash, suit, hno = 0; + + while (1) + { + for (hash = 0; hash < 256; hash++) + { + ptr = &rootptr[hash]; + for (suit = ptr->nextNo - 1; suit >= 0; suit--) + { + bp = ptr->list[suit].posBlock; + if (timestamp - bp->timestampRead > HARVEST_AGE) + { + bp->nextMatchNo = 0; + bp->nextWriteNo = 0; + bp->timestampRead = timestamp; + harvested.list[hno] = bp; + + // Swap the last element down. + if (suit != ptr->nextNo - 1) + ptr->list[suit] = ptr->list[ ptr->nextNo - 1 ]; + + ptr->nextNo--; + ptr->nextWriteNo = ptr->nextNo; + + if (++hno == BLOCKS_PER_PAGE) + { + if (++harvestHand >= DDS_HANDS) + { + // Skip rest of this [trick][hand] for simplicity. + harvestHand = 0; + if (--harvestTrick < 0) + harvestTrick = FIRST_HARVEST_TRICK; + } + + harvested.nextBlockNo = 0; + pageStats.numHarvests++; + return true; + } + } + } + } + + if (++harvestHand >= DDS_HANDS) + { + harvestHand = 0; + if (--harvestTrick < 0) + harvestTrick = FIRST_HARVEST_TRICK; + } + + if (harvestTrick == trick && harvestHand == hand) + return false; + + rootptr = TTroot[harvestTrick][harvestHand]; + } +} + + +int TransTableL::hash8(const int handDist[]) const +{ + /* + handDist is an array of hand distributions, North .. West. + Each entry is a 12-bit number with 3 groups of 4 bits. + Each group is the binary representation of the number of + cards held in that suit. The suits are in order spades, + hearts, diamonds. Clubs can be neglected, as the total + number of cards in a hand is given by the trick number. + + For example, if handDist[1] equals 0x0433, then East holds + 4 spades, 3 hearts, 3 diamonds and the rest in clubs. + If this is after the second trick, there are 11 cards, so + East must hold 1 club. + + The hash function turns all 4 hand distributions into a + single 8-bit number. The numbers should be spread as + evenly as possible across the 256 possibilities. I've not + done extensive research into finding the best hash function, + but this one seems OK. It uses a small prime, 5, and its + powers. The shift at the end is in order to get some use + out of the bits above the first 8 ones. + */ + + int h = + (handDist[0] ^ + ((handDist[1] * 5) ) ^ + ((handDist[2] * 25) ) ^ + ((handDist[3] * 125) ) ); + + return (h ^ (h >> 5)) & 0xff; +} + + +nodeCardsType * TransTableL::Lookup( + const int tricks, + const int hand, + const unsigned short aggrTarget[], + const int handDist[], + const int limit, + bool& lowerFlag) +{ + // First look up distribution. + long long suitLengths = + (static_cast(handDist[0]) << 36) | + (static_cast(handDist[1]) << 24) | + (static_cast(handDist[2]) << 12) | + (static_cast(handDist[3]) ); + + int hashkey = hash8(handDist); + + bool empty; + lastBlockSeen[tricks][hand] = + LookupSuit(&TTroot[tricks][hand][hashkey], suitLengths, empty); + if (empty) + return nullptr; + + // If that worked, look up cards. + unsigned * ab0 = aggr[ aggrTarget[0] ].aggrBytes[0]; + unsigned * ab1 = aggr[ aggrTarget[1] ].aggrBytes[1]; + unsigned * ab2 = aggr[ aggrTarget[2] ].aggrBytes[2]; + unsigned * ab3 = aggr[ aggrTarget[3] ].aggrBytes[3]; + + winMatchType TTentry; + TTentry.topSet1 = ab0[0] | ab1[0] | ab2[0] | ab3[0]; + TTentry.topSet2 = ab0[1] | ab1[1] | ab2[1] | ab3[1]; + TTentry.topSet3 = ab0[2] | ab1[2] | ab2[2] | ab3[2]; + TTentry.topSet4 = ab0[3] | ab1[3] | ab2[3] | ab3[3]; + + return TransTableL::LookupCards(TTentry, + lastBlockSeen[tricks][hand], limit, lowerFlag); +} + + +TransTableL::winBlockType * TransTableL::LookupSuit( + distHashType * dp, + const long long key, + bool& empty) +{ + /* + Always returns a valid winBlockType. + If empty == true, there was no match, so there is + no point in looking for a card match. + If empty == false, there were entries already. + */ + + int n = dp->nextNo; + for (int i = 0; i < n; i++) + { + if (dp->list[i].key == key) + { + empty = false; + return dp->list[i].posBlock; + } + } + + empty = true; + int m; + + if (n == DISTS_PER_ENTRY) + { + // No room for new exact suits at this hash position. + // Have to reuse an existing posBlock. + if (dp->nextWriteNo == DISTS_PER_ENTRY) + { + m = 0; + dp->nextWriteNo = 1; + } + else + m = dp->nextWriteNo++; + } + else + { + // Didn't find an exact match, but there is still room. + // The following looks a bit odd because it is possible that + // GetNextCardBlock wipes out the whole memory, so we + // have to use the up-to-date location, not m from above. + + winBlockType * bp = GetNextCardBlock(); + m = dp->nextWriteNo++; + dp->list[m].posBlock = bp; + dp->list[m].posBlock->timestampRead = timestamp; + dp->nextNo++; + } + + // As long as the secondary Lookup loop in ABsearch exists, + // it will cause spurious extra blocks to be created here + // which are not useful, because nothing is ever Add'ed. + // This is not a memory leak, as the memory is properly freed, + // but it is also a small waste of about 0.5%. I don't mind. + + dp->list[m].key = key; + dp->list[m].posBlock->nextMatchNo = 0; + dp->list[m].posBlock->nextWriteNo = 0; + + return dp->list[m].posBlock; +} + + +nodeCardsType * TransTableL::LookupCards( + const winMatchType& search, + winBlockType * bp, + const int limit, + bool& lowerFlag) +{ + const int n = bp->nextWriteNo - 1; + winMatchType * wp = &bp->list[n]; + + // It may be a bit silly to duplicate the code like this. + // It could be combined to one loop with a slight overhead. + + for (int i = n; i >= 0; i--, wp--) + { + if ((wp->topSet1 ^ search.topSet1) & wp->topMask1) + continue; + + if (wp->lastMaskNo != 1) + { + if ((wp->topSet2 ^ search.topSet2) & wp->topMask2) + continue; + + if (wp->lastMaskNo != 2) + { + if ((wp->topSet3 ^ search.topSet3) & wp->topMask3) + continue; + } + } + + // Check bounds. + nodeCardsType * nodep = &wp->first; + if (nodep->lbound > limit) + { + bp->timestampRead = ++timestamp; + lowerFlag = true; + return nodep; + } + else if (nodep->ubound <= limit) + { + bp->timestampRead = ++timestamp; + lowerFlag = false; + return nodep; + } + } + + const int n2 = bp->nextMatchNo - 1; + wp = &bp->list[n2]; + + for (int i = n2; i > n; i--, wp--) + { + if ((wp->topSet1 ^ search.topSet1) & wp->topMask1) + continue; + + if (wp->lastMaskNo != 1) + { + if ((wp->topSet2 ^ search.topSet2) & wp->topMask2) + continue; + + if (wp->lastMaskNo != 2) + { + if ((wp->topSet3 ^ search.topSet3) & wp->topMask3) + continue; + } + } + + nodeCardsType * nodep = &wp->first; + if (nodep->lbound > limit) + { + lowerFlag = true; + bp->timestampRead = ++timestamp; + return nodep; + } + else if (nodep->ubound <= limit) + { + lowerFlag = false; + bp->timestampRead = ++timestamp; + return nodep; + } + } + + return nullptr; +} + + +void TransTableL::CreateOrUpdate( + winBlockType * bp, + const winMatchType& search, + const bool flag) +{ + // Either updates an existing SOP or creates a new one. + // A new one is created at the end of the bp list if this + // is not already full, or the oldest one in the list is + // overwritten. + + winMatchType * wp = bp->list; + int n = bp->nextMatchNo; + + for (int i = 0; i < n; i++, wp++) + { + if (wp->xorSet != search.xorSet ) continue; + if (wp->maskIndex != search.maskIndex) continue; + if (wp->topSet1 != search.topSet1 ) continue; + if (wp->topSet2 != search.topSet2 ) continue; + if (wp->topSet3 != search.topSet3 ) continue; + + nodeCardsType& node = wp->first; + if (search.first.lbound > node.lbound) + node.lbound = search.first.lbound; + if (search.first.ubound < node.ubound) + node.ubound = search.first.ubound; + + node.bestMoveSuit = search.first.bestMoveSuit; + node.bestMoveRank = search.first.bestMoveRank; + return; + } + + if (n == BLOCKS_PER_ENTRY) + { + if (bp->nextWriteNo >= BLOCKS_PER_ENTRY) + bp->nextWriteNo = 0; + } + else + bp->nextMatchNo++; + + + wp = &bp->list[ bp->nextWriteNo++ ]; + *wp = search; + + if (!flag) + { + wp->first.bestMoveSuit = 0; + wp->first.bestMoveRank = 0; + } +} + + +void TransTableL::Add( + const int tricks, + const int hand, + const unsigned short aggrTarget[], + const unsigned short ourWinRanks[], + const nodeCardsType& first, + const bool flag) +{ + if (lastBlockSeen[tricks][hand] == nullptr) + { + // We have recently reset the entire memory, and we were + // in the middle of a recursion. So we'll just have to + // drop this entry that we were supposed to be adding. + return; + } + + unsigned * ab[DDS_SUITS]; + unsigned * mb[DDS_SUITS]; + char low[DDS_SUITS]; + unsigned short int ag; + int w; + winMatchType TTentry; + + // Inefficient, as it also copies leastWin. + // In fact I'm not quite happy with the treatment of + // leastWin in general. + + TTentry.first = first; + + TTentry.xorSet = 0; + + for (int ss = 0; ss < DDS_SUITS; ss++) + { + w = static_cast(ourWinRanks[ss]); + if (w == 0) + { + ab[ss] = aggr[0].aggrBytes[ss]; + mb[ss] = maskBytes[0][ss]; + low[ss] = 15; + TTentry.first.leastWin[ss] = 0; + } + else + { + w = w & (-w); /* Only lowest win */ + ag = static_cast(aggrTarget[ss] & (-w)); + + ab[ss] = aggr[ag].aggrBytes[ss]; + mb[ss] = maskBytes[ag][ss]; + low[ss] = static_cast(TTlowestRank[ag]); + + TTentry.first.leastWin[ss] = 15 - low[ss]; + TTentry.xorSet ^= aggr[ag].aggrRanks[ss]; + } + } + + // It's a bit annoying that we may be regenerating these. + // But winRanks can cause them to change after lookup(). + + TTentry.topSet1 = ab[0][0] | ab[1][0] | ab[2][0] | ab[3][0]; + TTentry.topSet2 = ab[0][1] | ab[1][1] | ab[2][1] | ab[3][1]; + TTentry.topSet3 = ab[0][2] | ab[1][2] | ab[2][2] | ab[3][2]; + TTentry.topSet4 = ab[0][3] | ab[1][3] | ab[2][3] | ab[3][3]; + + TTentry.topMask1 = mb[0][0] | mb[1][0] | mb[2][0] | mb[3][0]; + TTentry.topMask2 = mb[0][1] | mb[1][1] | mb[2][1] | mb[3][1]; + TTentry.topMask3 = mb[0][2] | mb[1][2] | mb[2][2] | mb[3][2]; + TTentry.topMask4 = mb[0][3] | mb[1][3] | mb[2][3] | mb[3][3]; + + TTentry.maskIndex = + (low[0] << 12) | (low[1] << 8) | (low[2] << 4) | low[3]; + + if (TTentry.topMask2 == 0) + TTentry.lastMaskNo = 1; + else if (TTentry.topMask3 == 0) + TTentry.lastMaskNo = 2; + else if (TTentry.topMask4 == 0) + TTentry.lastMaskNo = 3; + else + TTentry.lastMaskNo = 4; + + TransTableL::CreateOrUpdate(lastBlockSeen[tricks][hand], + TTentry, flag); +} + + +void TransTableL::PrintMatch( + ofstream& fout, + const winMatchType& wp, + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const +{ + vector> hands; + hands.resize(DDS_HANDS); + for (unsigned i = 0; i < DDS_HANDS; i++) + hands[i].resize(DDS_SUITS); + + TransTableL::SetToPartialHands(wp.topSet1, wp.topMask1, 14, 4, hands); + TransTableL::SetToPartialHands(wp.topSet2, wp.topMask2, 10, 4, hands); + TransTableL::SetToPartialHands(wp.topSet3, wp.topMask3, 6, 4, hands); + TransTableL::SetToPartialHands(wp.topSet4, wp.topMask4, 2, 1, hands); + + TransTableL::DumpHands(fout, hands, lengths); + + TransTableL::PrintNodeValues(fout, wp.first); +} + + +void TransTableL::PrintNodeValues( + ofstream& fout, + const nodeCardsType& np) const +{ + fout << setw(16) << left << "Lowest used" << + cardSuit[0] << cardRank[15-static_cast(np.leastWin[0])] << ", " << + cardSuit[1] << cardRank[15-static_cast(np.leastWin[1])] << ", " << + cardSuit[2] << cardRank[15-static_cast(np.leastWin[2])] << ", " << + cardSuit[3] << cardRank[15-static_cast(np.leastWin[3])] << "\n"; + + fout << setw(16) << left << "Bounds" << + to_string(np.lbound) << " to " << + to_string(np.ubound) << " tricks\n"; + + fout << setw(16) << left << "Best move" << + cardSuit[ static_cast(np.bestMoveSuit) ] << + cardRank[ static_cast(np.bestMoveRank) ] << "\n\n"; +} + + +string TransTableL::MakeHolding( + const string& high, + const unsigned len) const +{ + const unsigned l = high.size(); + if (l == 0) + return "-"; + else if (l == len) + return high; + else + return high.substr(0, l) + string(len-l, 'x'); +} + + +void TransTableL::DumpHands( + ofstream& fout, + const vector>& hands, + const unsigned char lengths[][DDS_SUITS]) const +{ + for (unsigned i = 0; i < DDS_SUITS; i++) + { + fout << setw(16) << "" << + TransTableL::MakeHolding(hands[0][i], lengths[0][i]) << "\n"; + } + + for (unsigned i = 0; i < DDS_SUITS; i++) + { + fout << setw(16) << left << + TransTableL::MakeHolding(hands[3][i], lengths[3][i]) << + setw(16) << "" << + setw(16) << + TransTableL::MakeHolding(hands[1][i], lengths[1][i]) << "\n"; + } + + for (unsigned i = 0; i < DDS_SUITS; i++) + { + fout << setw(16) << "" << + TransTableL::MakeHolding(hands[2][i], lengths[2][i]) << "\n"; + } + fout << "\n"; +} + + +void TransTableL::SetToPartialHands( + const unsigned set, + const unsigned mask, + const int maxRank, + const int numRanks, + vector>& hands) const +{ + for (unsigned s = 0; s < DDS_SUITS; s++) + { + for (int rank = maxRank; rank > maxRank - numRanks; rank--) + { + int shift = 8 * static_cast(3 - s) + 2 * (rank - maxRank + 3); + unsigned maskCard = mask >> shift; + + if (maskCard & 3) + { + unsigned player = (set >> shift) & 3; + hands[player][s] += static_cast(cardRank[rank]); + } + } + } +} + + +void TransTableL::KeyToDist( + const long long key, + int handDist[]) const +{ + handDist[0] = static_cast((key >> 36) & 0x00000fff); + handDist[1] = static_cast((key >> 24) & 0x00000fff); + handDist[2] = static_cast((key >> 12) & 0x00000fff); + handDist[3] = static_cast((key ) & 0x00000fff); +} + + +void TransTableL::DistToLengths( + const int trick, + const int handDist[], + unsigned char lengths[DDS_HANDS][DDS_SUITS]) const +{ + for (int h = 0; h < DDS_HANDS; h++) + { + lengths[h][0] = static_cast((handDist[h] >> 8) & 0xf); + lengths[h][1] = static_cast((handDist[h] >> 4) & 0xf); + lengths[h][2] = static_cast((handDist[h] ) & 0xf); + lengths[h][3] = static_cast + (trick + 1 - lengths[h][0] - lengths[h][1] - lengths[h][2]); + } +} + + +string TransTableL::SingleLenToStr(const unsigned char len[]) const +{ + return to_string(static_cast(len[0])) + "=" + + to_string(static_cast(len[1])) + "=" + + to_string(static_cast(len[2])) + "=" + + to_string(static_cast(len[3])); +} + + +string TransTableL::LenToStr( + const unsigned char len[DDS_HANDS][DDS_SUITS]) const +{ + return TransTableL::SingleLenToStr(len[0]) + " " + + TransTableL::SingleLenToStr(len[1]) + " " + + TransTableL::SingleLenToStr(len[2]) + " " + + TransTableL::SingleLenToStr(len[3]); +} + + +void TransTableL::PrintSuits( + ofstream& fout, + const int trick, + const int hand) const +{ + distHashType * dp; + int handDist[DDS_HANDS]; + unsigned char len[DDS_HANDS][DDS_SUITS]; + + fout << setw(4) << left << "Key" << + setw(3) << right << "No" << + setw(8) << right << players[0] << + setw(8) << players[1] << + setw(8) << players[2] << + setw(8) << players[3] << "\n"; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + if (dp->nextNo == 0) + continue; + + for (int i = 0; i < dp->nextNo; i++) + { + if (i == 0) + fout << "0x" << setw(2) << hex << hashkey << + setw(3) << right << dec << dp->nextNo << " "; + else + fout << setw(8) << ""; + + TransTableL::KeyToDist(dp->list[i].key, handDist); + TransTableL::DistToLengths(trick, handDist, len); + + fout << TransTableL::LenToStr(len) << "\n"; + } + } + fout << "\n"; +} + + +void TransTableL::PrintAllSuits(ofstream& fout) const +{ + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + fout << "Trick " << trick << ", hand " << + players[static_cast(hand)] << "\n"; + fout << string(20, '=') << "\n\n"; + + TransTableL::PrintSuits(fout, trick, hand); + } + } +} + + +void TransTableL::MakeHistStats( + const int hist[], + int& count, + int& prod_sum, + int& prod_sumsq, + int& max_len, + const int last_index) const +{ + count = 0; + prod_sum = 0; + prod_sumsq = 0; + max_len = 0; + + for (int i = 1; i <= last_index; i++) + { + if (hist[i]) + { + prod_sum += i * hist[i]; + prod_sumsq += i * i * hist[i]; + count += hist[i]; + + if (i > max_len) + max_len = i; + } + } +} + + +int TransTableL::CalcPercentile( + const int hist[], + const double threshold, + const int last_index) const +{ + int cum = 0; + + for (int i = 1; i <= last_index; i++) + { + cum += hist[i]; + if (cum >= threshold) + return i; + } + return -1; +} + + +void TransTableL::PrintHist( + ofstream& fout, + const int hist[], + const int num_wraps, + const int last_index) const +{ + int count, prod_sum, prod_sumsq, max_len; + + TransTableL::MakeHistStats(hist, + count, prod_sum, prod_sumsq, max_len, last_index); + + for (int i = 1; i <= last_index; i++) + if (hist[i]) + fout << setw(7) << right << i << + setw(6) << right << hist[i] << "\n"; + + fout << "\n"; + fout << setw(7) << left << "Entries" << + setw(6) << right << count << "\n"; + + if (count > 1) + { + fout << setw(7) << left << "Full" << + setw(6) << right << num_wraps << "\n"; + + double mean = prod_sum / static_cast(count); + fout << setw(7) << left << "Average" << + setw(6) << right << setprecision(2) << fixed << mean << "\n"; + + double var = (prod_sumsq - count*mean*mean) / + static_cast(count-1); + + if (var >= 0.) + fout << setw(7) << left << "Std.dev" << + setw(6) << right << setprecision(2) << fixed << sqrt(var) << "\n"; + + fout << setw(7) << left << "Maximum" << + setw(6) << right << max_len << "\n"; + } + fout << "\n"; +} + + +void TransTableL::UpdateSuitHist( + const int trick, + const int hand, + int hist[], + int& num_wraps) const +{ + distHashType * dp; + + num_wraps = 0; + for (int i = 0; i <= DISTS_PER_ENTRY; i++) + hist[i] = 0; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + hist [ dp->nextNo ]++; + + if (dp->nextNo != dp->nextWriteNo) + num_wraps++; // Not entirely correct + } +} + + +void TransTableL::UpdateSuitHist( + const int trick, + const int hand, + int hist[], + int suitHist[], + int& num_wraps, + int& suitWraps) const +{ + distHashType * dp; + + num_wraps = 0; + for (int i = 0; i <= DISTS_PER_ENTRY; i++) + hist[i] = 0; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + hist [ dp->nextNo ]++; + suitHist[ dp->nextNo ]++; + + if (dp->nextNo != dp->nextWriteNo) + { + num_wraps++; // Not entirely correct + suitWraps++; + } + } +} + + +void TransTableL::PrintSuitStats( + ofstream& fout, + const int trick, + const int hand) const +{ + int hist[DISTS_PER_ENTRY+1]; + int num_wraps; + + TransTableL::UpdateSuitHist(trick, hand, hist, num_wraps); + + fout << "Suit histogram for trick " << trick << ", hand " << + players[static_cast(hand)] << "\n"; + TransTableL::PrintHist(fout, hist, num_wraps, DISTS_PER_ENTRY); +} + + +void TransTableL::PrintAllSuitStats(ofstream& fout) const +{ + int num_wraps; + int suitWraps = 0; + + // Really the maximum of BLOCKS_PER_ENTRY and DISTS_PER_ENTRY. + int hist[DISTS_PER_ENTRY+1]; + int suitHist[DISTS_PER_ENTRY+1]; + + for (int i = 0; i <= DISTS_PER_ENTRY; i++) + suitHist[i] = 0; + + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + TransTableL::UpdateSuitHist(trick, hand, hist, suitHist, + num_wraps, suitWraps); + + fout << "Suit histogram for trick " << trick << ", hand " << + players[static_cast(hand)] << "\n"; + TransTableL::PrintHist(fout, hist, num_wraps, DISTS_PER_ENTRY); + } + } + + fout << "Overall suit histogram\n"; + TransTableL::PrintHist(fout, suitHist, suitWraps, DISTS_PER_ENTRY); +} + + +void TransTableL::PrintSummarySuitStats(ofstream& fout) const +{ + int hist[DISTS_PER_ENTRY+1]; + int count, prod_sum, prod_sumsq, max_len, num_wraps; + + fout << "Suit depth statistics\n\n"; + + fout << setw(5) << right << "Trick" << + setw(7) << "Player" << + setw(8) << "Entries" << + setw(8) << "Full" << + setw(8) << "Average" << + setw(8) << "Std.dev" << + setw(8) << "Maximum" << + " P" << setw(4) << setprecision(2) << fixed << TT_PERCENTILE << "\n"; + + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + TransTableL::UpdateSuitHist(trick, hand, hist, num_wraps); + TransTableL::MakeHistStats(hist, + count, prod_sum, prod_sumsq, max_len, DISTS_PER_ENTRY); + + double mean = 0., var = 0.; + if (count > 1) + { + mean = prod_sum / static_cast(count); + + var = (prod_sumsq - count*mean*mean) / + static_cast(count-1); + if (var < 0.) + var = 0.; + } + + const int percentile = + TransTableL::CalcPercentile(hist, + TT_PERCENTILE * count, DISTS_PER_ENTRY); + + fout << setw(5) << right << trick << + setw(7) << players[static_cast(hand)] << + setw(8) << count << + setw(8) << num_wraps; + + if (count > 0) + fout << setw(8) << mean << + setw(8) << setprecision(2) << fixed << sqrt(var); + else + fout << setw(8) << '-' << setw(8) << '-'; + + fout << setw(8) << max_len << + setw(8) << setprecision(2) << fixed << percentile << "\n"; + } + fout << "\n"; + } + fout << "\n"; +} + + +TransTableL::winBlockType const * TransTableL::FindMatchingDist( + const int trick, + const int hand, + const int handDistSought[]) const +{ + winBlockType * bp; + distHashType * dp; + int handDist[DDS_HANDS]; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + for (int i = 0; i < dp->nextNo; i++) + { + bp = dp->list[i].posBlock; + TransTableL::KeyToDist(dp->list[i].key, handDist); + + bool same = true; + for (int h = 0; h < DDS_HANDS; h++) + { + if (handDist[h] != handDistSought[h]) + { + same = false; + break; + } + } + if (same) + return bp; + } + } + return nullptr; +} + + +void TransTableL::PrintEntriesBlock( + ofstream& fout, + winBlockType const * bp, + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const +{ + string st = to_string(bp->nextMatchNo) + + " matches for " + TransTableL::LenToStr(lengths); + + fout << st << "\n" << string(st.size(), '=') << "\n\n"; + + for (int j = 0; j < bp->nextMatchNo; j++) + { + st = "Entry number " + to_string(j+1); + fout << st << "\n"; + fout << string(st.size(), '-') << "\n\n"; + TransTableL::PrintMatch(fout, bp->list[j], lengths); + } +} + + + +void TransTableL::PrintEntriesDistAndCards( + ofstream& fout, + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[]) const +{ + unsigned char len[DDS_HANDS][DDS_SUITS]; + + winBlockType const * bp = + TransTableL::FindMatchingDist(trick, hand, handDist); + + TransTableL::DistToLengths(trick, handDist, len); + + fout << "Looking up entry for trick " << trick << ", hand " << + players[static_cast(hand)] << "\n"; + fout << TransTableL::LenToStr(len) << "\n\n"; + + if (! bp) + { + fout << "Entry not found\n\n"; + return; + } + + unsigned const * ab0 = aggr[ aggrTarget[0] ].aggrBytes[0]; + unsigned const * ab1 = aggr[ aggrTarget[1] ].aggrBytes[1]; + unsigned const * ab2 = aggr[ aggrTarget[2] ].aggrBytes[2]; + unsigned const * ab3 = aggr[ aggrTarget[3] ].aggrBytes[3]; + + winMatchType TTentry; + TTentry.topSet1 = ab0[0] | ab1[0] | ab2[0] | ab3[0]; + TTentry.topSet2 = ab0[1] | ab1[1] | ab2[1] | ab3[1]; + TTentry.topSet3 = ab0[2] | ab1[2] | ab2[2] | ab3[2]; + TTentry.topSet4 = ab0[3] | ab1[3] | ab2[3] | ab3[3]; + + int matchNo = 1; + int n = bp->nextMatchNo - 1; + winMatchType const * wp = &bp->list[n]; + + for (int i = n; i >= 0; i--, wp--) + { + if ((wp->topSet1 ^ TTentry.topSet1) & wp->topMask1) + continue; + + if (wp->lastMaskNo != 1) + { + if ((wp->topSet2 ^ TTentry.topSet2) & wp->topMask2) + continue; + + if (wp->lastMaskNo != 2) + { + if ((wp->topSet3 ^ TTentry.topSet3) & wp->topMask3) + continue; + } + } + + fout << "Match number " << matchNo++ << "\n"; + fout << string(15, '-') << "\n"; + TransTableL::PrintMatch(fout, bp->list[i], len); + } + + if (matchNo == 1) + fout << n << " matches for suit, none for cards\n\n"; + else + fout << "\n"; +} + + +void TransTableL::PrintEntriesDist( + ofstream& fout, + const int trick, + const int hand, + const int handDist[]) const +{ + unsigned char len[DDS_HANDS][DDS_SUITS]; + + winBlockType const * bp = + TransTableL::FindMatchingDist(trick, hand, handDist); + + TransTableL::DistToLengths(trick, handDist, len); + + if (! bp) + { + fout << "Entry not found: Trick " << trick << ", hand " << + players[static_cast(hand)] << "\n"; + fout << TransTableL::LenToStr(len) << "\n\n"; + return; + } + + TransTableL::PrintEntriesBlock(fout, bp, len); +} + + +void TransTableL::PrintEntries( + ofstream& fout, + const int trick, + const int hand) const +{ + winBlockType * bp; + distHashType * dp; + int handDist[DDS_HANDS]; + unsigned char lengths[DDS_HANDS][DDS_SUITS]; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + for (int i = 0; i < dp->nextNo; i++) + { + bp = dp->list[i].posBlock; + TransTableL::KeyToDist(dp->list[i].key, handDist); + TransTableL::DistToLengths(trick, handDist, lengths); + + TransTableL::PrintEntriesBlock(fout, bp, lengths); + } + } +} + + +void TransTableL::PrintAllEntries(ofstream& fout) const +{ + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + const string st = "Entries, trick " + to_string(trick) + + ", hand " + players[static_cast(hand)]; + fout << st << "\n"; + fout << string(st.size(), '=') << "\n\n"; + TransTableL::PrintEntries(fout, trick, hand); + } + } + fout << "\n"; +} + + +void TransTableL::UpdateEntryHist( + const int trick, + const int hand, + int hist[], + int& num_wraps) const +{ + distHashType * dp; + + num_wraps = 0; + for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) + hist[i] = 0; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + for (int i = 0; i < dp->nextNo; i++) + { + int c = dp->list[i].posBlock->nextMatchNo; + hist [c]++; + + if (c != dp->list[i].posBlock->nextWriteNo) + num_wraps++; // Not entirely correct + } + } +} + + +void TransTableL::UpdateEntryHist( + const int trick, + const int hand, + int hist[], + int suitHist[], + int& num_wraps, + int& suitWraps) const +{ + distHashType * dp; + + num_wraps = 0; + for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) + hist[i] = 0; + + for (int hashkey = 0; hashkey < 256; hashkey++) + { + dp = &TTroot[trick][hand][hashkey]; + for (int i = 0; i < dp->nextNo; i++) + { + int c = dp->list[i].posBlock->nextMatchNo; + hist [c]++; + suitHist[c]++; + + if (c != dp->list[i].posBlock->nextWriteNo) + { + num_wraps++; // Not entirely correct + suitWraps++; + } + } + } +} + + +void TransTableL::PrintEntryStats( + ofstream& fout, + const int trick, + const int hand) const +{ + int hist[BLOCKS_PER_ENTRY+1]; + int num_wraps; + + TransTableL::UpdateEntryHist(trick, hand, hist, num_wraps); + + fout << "Entry histogram for trick " << trick << ", hands " << + players[static_cast(hand)] << "\n"; + TransTableL::PrintHist(fout, hist, num_wraps, BLOCKS_PER_ENTRY); +} + + +void TransTableL::PrintAllEntryStats(ofstream& fout) const +{ + int hist[BLOCKS_PER_ENTRY+1]; + int num_wraps; + + int suitWraps = 0; + int suitHist[BLOCKS_PER_ENTRY+1]; + for (int i = 0; i <= BLOCKS_PER_ENTRY; i++) + suitHist[i] = 0; + + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + TransTableL::UpdateEntryHist(trick, hand, hist, suitHist, + num_wraps, suitWraps); + + fout << "Entry histogram for trick " << trick << ", hands " << + players[static_cast(hand)] << "\n"; + TransTableL::PrintHist(fout, hist, num_wraps, BLOCKS_PER_ENTRY); + } + } + + fout << "Overall entry histogram\n"; + TransTableL::PrintHist(fout, suitHist, suitWraps, BLOCKS_PER_ENTRY); +} + + +int TransTableL::EffectOfBlockBound( + const int hist[], + const int size) const +{ + // Calculates the number of blocks used if the blocks + // are divided up in units of size, rather than in units + // of BLOCKS_PER_ENTRY. Only makes sense if size is less + // than BLOCKS_PER_ENTRY, as we won't have statistics for + // how many blocks above BLOCKS_PER_ENTRY would be created + // if BLOCKS_PER_ENTRY were larger. + + int cum_memory = 0; + int unit_size = 0; + + for (int i = 1; i <= BLOCKS_PER_ENTRY; i++) + { + if ((i - 1) % size == 0) + unit_size += size; + + cum_memory += hist[i] * unit_size; + } + return cum_memory; +} + + +void TransTableL::PrintSummaryEntryStats(ofstream& fout) const +{ + int hist[BLOCKS_PER_ENTRY + 1]; + int count, prod_sum, prod_sumsq, max_len, num_wraps; + + int cumCount = 0; + double cumProd = 0.; + int cumMemory = 0; + + fout << "Entry depth statistics\n\n"; + + fout << setw(5) << right << "Trick" << + setw(7) << "Player" << + setw(8) << "Entries" << + setw(8) << "Full" << + setw(8) << "Average" << + setw(8) << "Std.dev" << + setw(8) << "Maximum" << + " P" << setw(4) << setprecision(2) << fixed << TT_PERCENTILE << "\n"; + + for (int trick = 11; trick >= 1; trick--) + { + for (int hand = 0; hand < DDS_HANDS; hand++) + { + TransTableL::UpdateEntryHist(trick, hand, hist, num_wraps); + TransTableL::MakeHistStats(hist, + count, prod_sum, prod_sumsq, max_len, BLOCKS_PER_ENTRY); + + cumCount += count; + cumProd += prod_sum; + cumMemory += TransTableL::EffectOfBlockBound(hist, 20); + + double mean = prod_sum / static_cast(count); + double var = (count > 1 ? + (prod_sumsq - count*mean*mean) / + static_cast(count-1) : 0.); + + if (var < 0.) + var = 0.; + + const int percentile = TransTableL::CalcPercentile(hist, + TT_PERCENTILE * count, BLOCKS_PER_ENTRY); + + fout << setw(5) << right << trick << + setw(7) << players[static_cast(hand)] << + setw(8) << count << + setw(8) << num_wraps << + setw(8) << mean << + setw(8) << sqrt(var) << + setw(8) << max_len << + setw(8) << setprecision(2) << fixed << percentile << "\n"; + } + fout << "\n"; + } + fout << "\n"; + + fout << setw(16) << left << "Blocks counted " << + setw(8) << right << cumCount << "\n"; + fout << setw(16) << left << "Blocks produced " << + setw(8) << right << TransTableL::BlocksInUse() << "\n"; + fout << setw(16) << left << "Mem scenario" << + setw(7) << right << setprecision(2) << fixed << + 100. * cumMemory / + (static_cast(BLOCKS_PER_ENTRY * cumCount)) << "%\n"; + + if (cumCount) + fout << setw(16) << left << "Fullness" << + setw(7) << right << setprecision(2) << fixed << + 100. * cumProd / (BLOCKS_PER_ENTRY * cumCount) << "%\n"; + fout << "\n"; +} + diff --git a/src/TransTableL.h b/src/TransTableL.h new file mode 100644 index 00000000..7a460e10 --- /dev/null +++ b/src/TransTableL.h @@ -0,0 +1,369 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_TRANSTABLEL_H +#define DDS_TRANSTABLEL_H + +/* + This is an implementation of the transposition table that requires + a lot of memory and is somewhat faster than the small version. +*/ + + +#include +#include + +#include "../include/dll.h" +#include "dds.h" + +#include "TransTable.h" + +using namespace std; + + +#define NUM_PAGES_DEFAULT 15 +#define NUM_PAGES_MAXIMUM 25 +#define BLOCKS_PER_PAGE 1000 +#define DISTS_PER_ENTRY 32 +#define BLOCKS_PER_ENTRY 125 +#define FIRST_HARVEST_TRICK 8 +#define HARVEST_AGE 10000 + +#define TT_BYTES 4 +#define TT_TRICKS 12 + +#define TT_LINE_LEN 20 + +#define TT_PERCENTILE 0.9 + + +class TransTableL: public TransTable +{ + private: + + struct winMatchType // 52 bytes + { + unsigned xorSet; + unsigned topSet1 , topSet2 , topSet3 , topSet4 ; + unsigned topMask1, topMask2, topMask3, topMask4; + int maskIndex; + int lastMaskNo; + nodeCardsType first; + }; + + struct winBlockType // 6508 bytes when BLOCKS_PER_ENTRY == 125 + { + int nextMatchNo; + int nextWriteNo; + int timestampRead; + winMatchType list[BLOCKS_PER_ENTRY]; + }; + + struct posSearchType // 16 bytes (inefficiency, 12 bytes enough) + { + winBlockType * posBlock; + long long key; + }; + + struct distHashType // 520 bytes when DISTS_PER_ENTRY == 32 + { + int nextNo; + int nextWriteNo; + posSearchType list[DISTS_PER_ENTRY]; + }; + + struct aggrType // 80 bytes + { + unsigned aggrRanks[DDS_SUITS]; + unsigned aggrBytes[DDS_SUITS][TT_BYTES]; + }; + + struct poolType // 16 bytes + { + poolType * next; + poolType * prev; + int nextBlockNo; + winBlockType * list; + }; + + struct pageStatsType + { + int numResets; + int numCallocs; + int numFrees; + int numHarvests; + int lastCurrent; + }; + + struct harvestedType // 16 bytes + { + int nextBlockNo; + winBlockType * list [BLOCKS_PER_PAGE]; + }; + + enum memStateType + { + FROM_POOL, + FROM_HARVEST + }; + + // Private data for the full memory version. + memStateType memState; + + int pagesDefault; + int pagesCurrent; + int pagesMaximum; + + int harvestTrick; + int harvestHand; + + pageStatsType pageStats; + + // aggr is constant for a given hand. + aggrType aggr[8192]; // 64 KB + + // This is the real transposition table. + // The last index is the hash. + // 6240 KB with above assumptions + // distHashType TTroot[TT_TRICKS][DDS_HANDS][256]; + distHashType * TTroot[TT_TRICKS][DDS_HANDS]; + + // It is useful to remember the last block we looked at. + winBlockType * lastBlockSeen[TT_TRICKS][DDS_HANDS]; + + // The pool of card entries for a given suit distribution. + poolType * poolp; + winBlockType * nextBlockp; + harvestedType harvested; + + int timestamp; + int TTInUse; + + + void InitTT(); + + void ReleaseTT(); + + void SetConstants(); + + int hash8(const int handDist[]) const; + + winBlockType * GetNextCardBlock(); + + winBlockType * LookupSuit( + distHashType * dp, + const long long key, + bool& empty); + + nodeCardsType * LookupCards( + const winMatchType& search, + winBlockType * bp, + const int limit, + bool& lowerFlag); + + void CreateOrUpdate( + winBlockType * bp, + const winMatchType& search, + const bool flag); + + bool Harvest(); + + // Debug functions from here on. + + void KeyToDist( + const long long key, + int handDist[]) const; + + void DistToLengths( + const int trick, + const int handDist[], + unsigned char lengths[DDS_HANDS][DDS_SUITS]) const; + + string SingleLenToStr(const unsigned char length[]) const; + + string LenToStr( + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const; + + void MakeHistStats( + const int hist[], + int& count, + int& prod_sum, + int& prod_sumsq, + int& max_len, + const int last_index) const; + + int CalcPercentile( + const int hist[], + const double threshold, + const int last_index) const; + + void PrintHist( + ofstream& fout, + const int hist[], + const int num_wraps, + const int last_index) const; + + void UpdateSuitHist( + const int trick, + const int hand, + int hist[], + int& num_wraps) const; + + void UpdateSuitHist( + const int trick, + const int hand, + int hist[], + int suitHist[], + int& num_wraps, + int& suitWraps) const; + + winBlockType const * FindMatchingDist( + const int trick, + const int hand, + const int handDistSought[]) const; + + void PrintEntriesBlock( + ofstream& fout, + winBlockType const * bp, + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const; + + void UpdateEntryHist( + const int trick, + const int hand, + int hist[], + int& num_wraps) const; + + void UpdateEntryHist( + const int trick, + const int hand, + int hist[], + int suitHist[], + int& num_wraps, + int& suitWraps) const; + + int EffectOfBlockBound( + const int hist[], + const int size) const; + + void PrintNodeValues( + ofstream& fout, + const nodeCardsType& np) const; + + void PrintMatch( + ofstream& fout, + const winMatchType& wp, + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const; + + string MakeHolding( + const string& high, + const unsigned len) const; + + void DumpHands( + ofstream& fout, + const vector>& hands, + const unsigned char lengths[DDS_HANDS][DDS_SUITS]) const; + + void SetToPartialHands( + const unsigned set, + const unsigned mask, + const int maxRank, + const int numRanks, + vector>& hands) const; + + int BlocksInUse() const; + + public: + TransTableL(); + + ~TransTableL(); + + void Init(const int handLookup[][15]); + + void SetMemoryDefault(const int megabytes); + + void SetMemoryMaximum(const int megabytes); + + void MakeTT(); + + void ResetMemory(const TTresetReason reason); + + void ReturnAllMemory(); + + double MemoryInUse() const; + + nodeCardsType * Lookup( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[], + const int limit, + bool& lowerFlag); + + void Add( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const unsigned short winRanksArg[], + const nodeCardsType& first, + const bool flag); + + void PrintSuits( + ofstream& fout, + const int trick, + const int hand) const; + + void PrintAllSuits(ofstream& fout) const; + + void PrintSuitStats( + ofstream& fout, + const int trick, + const int hand) const; + + void PrintAllSuitStats(ofstream& fout) const; + + void PrintSummarySuitStats(ofstream& fout) const; + + // Examples: + // int hd[DDS_HANDS] = { 0x0342, 0x0334, 0x0232, 0x0531 }; + // thrp->transTable.PrintEntriesDist(cout, 11, 1, hd); + // unsigned short ag[DDS_HANDS] = + // { 0x1fff, 0x1fff, 0x0f75, 0x1fff }; + // thrp->transTable.PrintEntriesDistAndCards(cout, 11, 1, ag, hd); + + void PrintEntriesDist( + ofstream& fout, + const int trick, + const int hand, + const int handDist[]) const; + + void PrintEntriesDistAndCards( + ofstream& fout, + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[]) const; + + void PrintEntries( + ofstream& fout, + const int trick, + const int hand) const; + + void PrintAllEntries(ofstream& fout) const; + + void PrintEntryStats( + ofstream& fout, + const int trick, + const int hand) const; + + void PrintAllEntryStats(ofstream& fout) const; + + void PrintSummaryEntryStats(ofstream& fout) const; +}; + +#endif diff --git a/src/TransTableS.cpp b/src/TransTableS.cpp new file mode 100644 index 00000000..8f99fdde --- /dev/null +++ b/src/TransTableS.cpp @@ -0,0 +1,946 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#include + +#include "TransTableS.h" +#include "debug.h" + + +#define NSIZE 50000 +#define WSIZE 50000 +#define NINIT 60000 +#define WINIT 170000 +#define LSIZE 200 // Per trick and first hand + + +static bool _constantsSet = false; +static int TTlowestRank[8192]; + + +TransTableS::TransTableS() +{ + if (! _constantsSet) + { + _constantsSet = true; + TransTableS::SetConstants(); + } + + TTInUse = 0; +} + + +TransTableS::~TransTableS() +{ + TransTableS::ReturnAllMemory(); +} + + +void TransTableS::SetConstants() +{ + unsigned int topBitRank = 1; + TTlowestRank[0] = 15; // Void + + for (unsigned ind = 1; ind < 8192; ind++) + { + if (ind >= (topBitRank + topBitRank)) /* Next top bit */ + topBitRank <<= 1; + + TTlowestRank[ind] = TTlowestRank[ind ^ topBitRank] - 1; + } + +} + + +void TransTableS::Init(const int handLookup[][15]) +{ + unsigned int topBitRank = 1; + unsigned int topBitNo = 2; + + for (int s = 0; s < DDS_SUITS; s++) + { + aggp[0].aggrRanks[s] = 0; + aggp[0].winMask[s] = 0; + } + + for (unsigned int ind = 1; ind < 8192; ind++) + { + if (ind >= (topBitRank + topBitRank)) + { + /* Next top bit */ + topBitRank <<= 1; + topBitNo++; + } + aggp[ind] = aggp[ind ^ topBitRank]; + + for (int s = 0; s < 4; s++) + { + aggp[ind].aggrRanks[s] = + (aggp[ind].aggrRanks[s] >> 2) | + (handLookup[s][topBitNo] << 24); + + aggp[ind].winMask[s] = + (aggp[ind].winMask[s] >> 2) | (3 << 24); + } + } + + resetText.resize(TT_RESET_SIZE); + resetText[TT_RESET_UNKNOWN] = "Unknown reason"; + resetText[TT_RESET_TOO_MANY_NODES] = "Too many nodes"; + resetText[TT_RESET_NEW_DEAL] = "New deal"; + resetText[TT_RESET_NEW_TRUMP] = "New trump"; + resetText[TT_RESET_MEMORY_EXHAUSTED] = "Memory exhausted"; + resetText[TT_RESET_FREE_MEMORY] = "Free thread memory"; + + return; +} + + +void TransTableS::SetMemoryDefault(const int megabytes) +{ + UNUSED(megabytes); +} + + +void TransTableS::SetMemoryMaximum(const int megabytes) +{ + maxmem = static_cast(1000000 * megabytes); +} + + +void TransTableS::MakeTT() +{ + int i; + + if (!TTInUse) + { + TTInUse = 1; + + summem = (WINIT + 1) * sizeof(winCardType) + + (NINIT + 1) * sizeof(nodeCardsType) + + (LSIZE + 1) * 52 * sizeof(posSearchTypeSmall); + wmem = static_cast((WSIZE + 1) * sizeof(winCardType)); + nmem = static_cast((NSIZE + 1) * sizeof(nodeCardsType)); + + maxIndex = static_cast( + (maxmem - summem) / ((WSIZE + 1) * sizeof(winCardType))); + + pw = static_cast(calloc(static_cast(maxIndex + 1), sizeof(winCardType *))); + if (pw == NULL) + exit(1); + + pn = static_cast(calloc(static_cast(maxIndex + 1), sizeof(nodeCardsType *))); + if (pn == NULL) + exit(1); + + for (int k = 1; k <= 13; k++) + for (int h = 0; h < DDS_HANDS; h++) + { + pl[k][h] = static_cast + (calloc(static_cast(maxIndex + 1), + sizeof(posSearchTypeSmall *))); + if (pl[k][h] == NULL) + exit(1); + } + + for (i = 0; i <= maxIndex; i++) + { + if (pw[i]) + free(pw[i]); + pw[i] = NULL; + } + + for (i = 0; i <= maxIndex; i++) + { + if (pn[i]) + free(pn[i]); + pn[i] = NULL; + } + + for (int k = 1; k <= 13; k++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + for (i = 0; i <= maxIndex; i++) + { + if (pl[k][h][i]) + free(pl[k][h][i]); + pl[k][h][i] = NULL; + } + } + } + + pw[0] = static_cast(calloc(WINIT + 1, sizeof(winCardType))); + if (pw[0] == NULL) + exit(1); + + pn[0] = static_cast(calloc(NINIT + 1, sizeof(nodeCardsType))); + if (pn[0] == NULL) + exit(1); + + for (int k = 1; k <= 13; k++) + for (int h = 0; h < DDS_HANDS; h++) + { + pl[k][h][0] = static_cast(calloc((LSIZE + 1), + sizeof(posSearchTypeSmall))); + if (pl[k][h][0] == NULL) + exit(1); + } + + aggp = static_cast(calloc(8192, sizeof(ttAggrType))); + if (aggp == NULL) + exit(1); + + InitTT(); + + for (int k = 1; k <= 13; k++) + aggrLenSets[k] = 0; + statsResets.noOfResets = 0; + for (int k = 0; k <= 5; k++) + statsResets.aggrResets[k] = 0; + + } + + return; +} + + +void TransTableS::Wipe() +{ + int m; + + for (m = 1; m <= wcount; m++) + { + if (pw[m]) + free(pw[m]); + pw[m] = NULL; + } + for (m = 1; m <= ncount; m++) + { + if (pn[m]) + free(pn[m]); + pn[m] = NULL; + } + + for (int k = 1; k <= 13; k++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + for (m = 1; m <= lcount[k][h]; m++) + { + if (pl[k][h][m]) + free(pl[k][h][m]); + pl[k][h][m] = NULL; + } + } + } + + allocmem = summem; + + return; +} + + + +void TransTableS::InitTT() +{ + winSetSizeLimit = WINIT; + nodeSetSizeLimit = NINIT; + allocmem = (WINIT + 1) * sizeof(winCardType); + allocmem += (NINIT + 1) * sizeof(nodeCardsType); + allocmem += (LSIZE + 1) * 52 * sizeof(posSearchTypeSmall); + winCards = pw[0]; + nodeCards = pn[0]; + wcount = 0; + ncount = 0; + + nodeSetSize = 0; + winSetSize = 0; + + clearTTflag = false; + windex = -1; + + for (int k = 1; k <= 13; k++) + for (int h = 0; h < DDS_HANDS; h++) + { + posSearch[k][h] = pl[k][h][0]; + lenSetInd[k][h] = 0; + lcount[k][h] = 0; + } +} + + +void TransTableS::ResetMemory(const TTresetReason reason) +{ + Wipe(); + + InitTT(); + + for (int k = 1; k <= 13; k++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + rootnp[k][h] = &(posSearch[k][h][0]); + posSearch[k][h][0].suitLengths = 0; + posSearch[k][h][0].posSearchPoint = NULL; + posSearch[k][h][0].left = NULL; + posSearch[k][h][0].right = NULL; + + lenSetInd[k][h] = 1; + } + } + +#if defined(DDS_TT_STATS) + statsResets.noOfResets++; + statsResets.aggrResets[reason]++; +#else + UNUSED(reason); +#endif + + return; +} + +void TransTableS::ReturnAllMemory() +{ + + if (!TTInUse) + return; + TTInUse = 0; + + Wipe(); + + if (pw[0]) + free(pw[0]); + pw[0] = NULL; + + if (pn[0]) + free(pn[0]); + pn[0] = NULL; + + for (int k = 1; k <= 13; k++) + { + for (int h = 0; h < DDS_HANDS; h++) + { + if (pl[k][h][0]) + free(pl[k][h][0]); + pl[k][h][0] = NULL; + } + } + + if (pw) + free(pw); + pw = NULL; + + if (pn) + free(pn); + pn = NULL; + + if (aggp) + free(aggp); + aggp = NULL; + + return; +} + + +double TransTableS::MemoryInUse() const +{ + int ttMem = static_cast(allocmem); + int aggrMem = 8192 * static_cast(sizeof(ttAggrType)); + return (ttMem + aggrMem) / static_cast(1024.); +} + + +nodeCardsType const * TransTableS::Lookup( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[], + const int limit, + bool& lowerFlag) +{ + bool res; + posSearchTypeSmall * pp; + int orderSet[DDS_SUITS]; + nodeCardsType const * cardsP; + + suitLengths[trick] = + (static_cast(handDist[0]) << 36) | + (static_cast(handDist[1]) << 24) | + (static_cast(handDist[2]) << 12) | + (static_cast(handDist[3])); + + pp = SearchLenAndInsert(rootnp[trick][hand], + suitLengths[trick], false, trick, hand, res); + + /* Find node that fits the suit lengths */ + if ((pp != NULL) && res) + { + for (int ss = 0; ss < DDS_SUITS; ss++) + { + orderSet[ss] = + aggp[aggrTarget[ss]].aggrRanks[ss]; + } + + if (pp->posSearchPoint == NULL) + cardsP = NULL; + else + { + cardsP = FindSOP(orderSet, limit, pp->posSearchPoint, lowerFlag); + + if (cardsP == NULL) + return cardsP; + } + } + else + { + cardsP = NULL; + } + return cardsP; +} + + +void TransTableS::Add( + const int tricks, + const int hand, + const unsigned short aggrTarget[], + const unsigned short ourWinRanks[], + const nodeCardsType& first, + const bool flag) +{ + BuildSOP(ourWinRanks, aggrTarget, first, suitLengths[tricks], + tricks, hand, flag); + + if (clearTTflag) + ResetMemory(TT_RESET_MEMORY_EXHAUSTED); + + return; +} + + +void TransTableS::AddWinSet() +{ + if (clearTTflag) + { + windex++; + winSetSize = windex; + winCards = &(temp_win[windex]); + } + else if (winSetSize >= winSetSizeLimit) + { + /* The memory chunk for the winCards structure will be exceeded. */ + if (((allocmem + static_cast(wmem)) > maxmem) || (wcount >= maxIndex) || + (winSetSize > SIMILARMAXWINNODES)) + { + /* Already allocated memory plus needed allocation overshot maxmem */ + windex++; + winSetSize = windex; + clearTTflag = true; + winCards = &(temp_win[windex]); + } + else + { + wcount++; + winSetSizeLimit = WSIZE; + pw[wcount] = + static_cast(malloc((WSIZE + 1) * sizeof(winCardType))); + if (pw[wcount] == NULL) + { + clearTTflag = true; + windex++; + winSetSize = windex; + winCards = &(temp_win[windex]); + } + else + { + allocmem += (WSIZE + 1) * sizeof(winCardType); + winSetSize = 0; + winCards = pw[wcount]; + } + } + } + else + winSetSize++; + return; +} + +void TransTableS::AddNodeSet() +{ + if (nodeSetSize >= nodeSetSizeLimit) + { + /* The memory chunk for the nodeCards structure will be exceeded. */ + if (((allocmem + static_cast(nmem)) > maxmem) || (ncount >= maxIndex)) + { + /* Already allocated memory plus needed allocation overshot maxmem */ + clearTTflag = true; + } + else + { + ncount++; + nodeSetSizeLimit = NSIZE; + pn[ncount] = + static_cast(malloc((NSIZE + 1) * sizeof(nodeCardsType))); + if (pn[ncount] == NULL) + { + clearTTflag = true; + } + else + { + allocmem += (NSIZE + 1) * sizeof(nodeCardsType); + nodeSetSize = 0; + nodeCards = pn[ncount]; + } + } + } + else + nodeSetSize++; + return; +} + +void TransTableS::AddLenSet( + const int trick, + const int firstHand) +{ + if (lenSetInd[trick][firstHand] < LSIZE) + { + lenSetInd[trick][firstHand]++; +#if defined(DDS_TT_STATS) + aggrLenSets[trick]++; +#endif + return; + } + + // The memory chunk for the posSearchTypeSmall structure + // will be exceeded. + + const int incr = (LSIZE+1) * sizeof(posSearchTypeSmall); + + if ((allocmem + incr > maxmem) || (lcount[trick][firstHand] >= maxIndex)) + { + // Already allocated memory plus needed allocation overshot maxmem. + clearTTflag = true; + return; + } + + // Obtain another memory chunk LSIZE. + + lcount[trick][firstHand]++; + + pl[trick][firstHand][lcount[trick][firstHand]] = + static_cast(malloc(incr)); + + if (pl[trick][firstHand][lcount[trick][firstHand]] == NULL) + { + clearTTflag = true; + return; + } + + allocmem += incr; + lenSetInd[trick][firstHand] = 0; + posSearch[trick][firstHand] = + pl[trick][firstHand][lcount[trick][firstHand]]; +#if defined(DDS_TT_STATS) + aggrLenSets[trick]++; +#endif +} + + +void TransTableS::BuildSOP( + const unsigned short ourWinRanks[DDS_SUITS], + const unsigned short aggrArg[DDS_SUITS], + const nodeCardsType& first, + const long long lengths, + const int tricks, + const int firstHand, + const bool flag) +{ + int winMask[DDS_SUITS]; + int winOrderSet[DDS_SUITS]; + char low[DDS_SUITS]; + + for (int ss = 0; ss < DDS_SUITS; ss++) + { + int w = ourWinRanks[ss]; + if (w == 0) + { + winMask[ss] = 0; + winOrderSet[ss] = 0; + low[ss] = 15; + } + else + { + w = w & (-w); /* Only lowest win */ + const unsigned short temp = + static_cast(aggrArg[ss] & (-w)); + + winMask[ss] = aggp[temp].winMask[ss]; + winOrderSet[ss] = aggp[temp].aggrRanks[ss]; + low[ss] = static_cast(TTlowestRank[temp]); + } + } + + bool res; + posSearchTypeSmall * np = SearchLenAndInsert( + rootnp[tricks][firstHand], lengths, true, tricks, firstHand, res); + + nodeCardsType * cardsP = BuildPath( + winMask, + winOrderSet, + static_cast(first.ubound), + static_cast(first.lbound), + static_cast(first.bestMoveSuit), + static_cast(first.bestMoveRank), + np, + res); + + if (res) + { + cardsP->ubound = static_cast(first.ubound); + cardsP->lbound = static_cast(first.lbound); + + if (flag) + { + cardsP->bestMoveSuit = static_cast(first.bestMoveSuit); + cardsP->bestMoveRank = static_cast(first.bestMoveRank); + } + else + { + cardsP->bestMoveSuit = 0; + cardsP->bestMoveRank = 0; + } + + for (int k = 0; k < DDS_SUITS; k++) + cardsP->leastWin[k] = 15 - low[k]; + } +} + + +nodeCardsType * TransTableS::BuildPath( + const int winMask[], + const int winOrderSet[], + const int ubound, + const int lbound, + const char bestMoveSuit, + const char bestMoveRank, + posSearchTypeSmall * nodep, + bool& result) +{ + /* 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 */ + + bool found; + winCardType * np, *p2, *nprev; + nodeCardsType *p; + + 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 = &(winCards[winSetSize]); + AddWinSet(); + p2->next = NULL; + p2->nextWin = NULL; + p2->prevWin = NULL; + nodep->posSearchPoint = p2; + p2->winMask = winMask[suit]; + p2->orderSet = winOrderSet[suit]; + p2->first = NULL; + np = p2; /* Latest winning node */ + suit++; + while (suit < DDS_SUITS) + { + p2 = &(winCards[winSetSize]); + AddWinSet(); + np->nextWin = p2; + p2->prevWin = np; + p2->next = NULL; + p2->nextWin = NULL; + p2->winMask = winMask[suit]; + p2->orderSet = winOrderSet[suit]; + p2->first = NULL; + np = p2; /* Latest winning node */ + suit++; + } + p = &(nodeCards[nodeSetSize]); + AddNodeSet(); + 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 == winMask[suit]) && + (np->orderSet == 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 >= DDS_SUITS) + { + result = false; + return UpdateSOP(ubound, lbound, bestMoveSuit, bestMoveRank, + np->first); + } + 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 = &(winCards[winSetSize]); + AddWinSet(); + 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 = winMask[suit]; + p2->orderSet = winOrderSet[suit]; + p2->first = NULL; + np = p2; /* Latest winning node */ + suit++; + + /* Rest of path must be created */ + while (suit < 4) + { + p2 = &(winCards[winSetSize]); + AddWinSet(); + np->nextWin = p2; + p2->prevWin = np; + p2->next = NULL; + p2->winMask = winMask[suit]; + p2->orderSet = 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 = &(nodeCards[nodeSetSize]); + AddNodeSet(); + np->first = p; + result = true; + return p; + } +} + +TransTableS::posSearchTypeSmall * TransTableS::SearchLenAndInsert( + posSearchTypeSmall * rootp, + const long long key, + const bool insertNode, + const int trick, + const int firstHand, + bool& result) +{ + /* 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. */ + + posSearchTypeSmall * np, *p, *sp; + + sp = NULL; + if (insertNode) + sp = &(posSearch[trick][firstHand][lenSetInd[trick][firstHand]]); + + 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(trick, firstHand); + 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(trick, firstHand); + np->right = p; + p->posSearchPoint = NULL; + p->suitLengths = key; + p->left = NULL; + p->right = NULL; + result = true; + return p; + } + else + { + result = false; + return NULL; + } + } + } +} + + +nodeCardsType * TransTableS::UpdateSOP( + int ubound, + int lbound, + char bestMoveSuit, + char bestMoveRank, + nodeCardsType * nodep) +{ + /* Update SOP node with new values for upper and lower + bounds. */ + if (lbound > nodep->lbound) + nodep->lbound = static_cast(lbound); + if (ubound < nodep->ubound) + nodep->ubound = static_cast(ubound); + + nodep->bestMoveSuit = bestMoveSuit; + nodep->bestMoveRank = bestMoveRank; + + return nodep; +} + + +nodeCardsType const * TransTableS::FindSOP( + const int orderSet[], + const int limit, + winCardType * nodeP, + bool& lowerFlag) +{ + winCardType * np; + + np = nodeP; + int s = 0; + + while (np) + { + if ((np->winMask & orderSet[s]) == np->orderSet) + { + /* Winning rank set fits position */ + if (s != 3) + { + np = np->nextWin; + s++; + continue; + } + + if (np->first->lbound > limit) + { + lowerFlag = true; + return np->first; + } + else if (np->first->ubound <= limit) + { + lowerFlag = false; + return np->first; + } + } + + while (np->next == NULL) + { + np = np->prevWin; + s--; + if (np == NULL) /* Previous node is header node? */ + return NULL; + } + np = np->next; + } + return NULL; +} + + +void TransTableS::PrintNodeStats(ofstream& fout) const +{ + fout << "Report of generated PosSearch nodes per trick level.\n"; + fout << "Trick level 13 is highest level with all 52 cards.\n"; + fout << string(51, '-') << "\n"; + + fout << setw(5) << "Trick" << + setw(14) << right << "Created nodes" << "\n"; + + for (int k = 13; k > 0; k--) + fout << setw(5) << k << setw(14) << aggrLenSets[k-1] << "\n"; + + fout << endl; +} + + +void TransTableS::PrintResetStats(ofstream& fout) const +{ + fout << "Total no. of resets: " << statsResets.noOfResets << "\n" << endl; + + fout << setw(18) << left << "Reason" << + setw(6) << right << "Count" << "\n"; + + for (unsigned k = 0; k < TT_RESET_SIZE; k++) + fout << setw(18) << left << resetText[k] << + setw(6) << right << statsResets.aggrResets[k] << "\n"; +} + diff --git a/src/TransTableS.h b/src/TransTableS.h new file mode 100644 index 00000000..85990b70 --- /dev/null +++ b/src/TransTableS.h @@ -0,0 +1,196 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_TRANSTABLES_H +#define DDS_TRANSTABLES_H + +/* + This is an object for managing transposition tables and the + associated memory. Compared to TransTableL it uses a lot less + memory and takes somewhat longer time. +*/ + + +#include +#include + +#include "TransTable.h" + +using namespace std; + + +class TransTableS: public TransTable +{ + private: + + // Structures for the small memory option. + + struct winCardType + { + int orderSet; + int winMask; + nodeCardsType * first; + winCardType * prevWin; + winCardType * nextWin; + winCardType * next; + }; + + struct posSearchTypeSmall + { + winCardType * posSearchPoint; + long long suitLengths; + posSearchTypeSmall * left; + posSearchTypeSmall * right; + }; + + struct ttAggrType + { + int aggrRanks[DDS_SUITS]; + int winMask[DDS_SUITS]; + }; + + struct statsResetsType + { + int noOfResets; + int aggrResets[TT_RESET_SIZE]; + }; + + + long long aggrLenSets[14]; + statsResetsType statsResets; + + winCardType temp_win[5]; + int nodeSetSizeLimit; + int winSetSizeLimit; + unsigned long long maxmem; + unsigned long long allocmem; + unsigned long long summem; + int wmem; + int nmem; + int maxIndex; + int wcount; + int ncount; + bool clearTTflag; + int windex; + ttAggrType * aggp; + + posSearchTypeSmall * rootnp[14][DDS_HANDS]; + winCardType ** pw; + nodeCardsType ** pn; + posSearchTypeSmall ** pl[14][DDS_HANDS]; + nodeCardsType * nodeCards; + winCardType * winCards; + posSearchTypeSmall * posSearch[14][DDS_HANDS]; + int nodeSetSize; /* Index with range 0 to nodeSetSizeLimit */ + int winSetSize; /* Index with range 0 to winSetSizeLimit */ + int lenSetInd[14][DDS_HANDS]; + int lcount[14][DDS_HANDS]; + + vector resetText; + + long long suitLengths[14]; + + int TTInUse; + + void SetConstants(); + + void Wipe(); + + void InitTT(); + + void AddWinSet(); + + void AddNodeSet(); + + void AddLenSet( + const int trick, + const int firstHand); + + void BuildSOP( + const unsigned short ourWinRanks[DDS_SUITS], + const unsigned short aggr[DDS_SUITS], + const nodeCardsType& first, + const long long suitLengths, + const int tricks, + const int firstHand, + const bool flag); + + nodeCardsType * BuildPath( + const int winMask[], + const int winOrderSet[], + const int ubound, + const int lbound, + const char bestMoveSuit, + const char bestMoveRank, + posSearchTypeSmall * node, + bool& result); + + struct posSearchTypeSmall * SearchLenAndInsert( + posSearchTypeSmall * rootp, + const long long key, + const bool insertNode, + const int trick, + const int firstHand, + bool& result); + + nodeCardsType * UpdateSOP( + const int ubound, + const int lbound, + const char bestMoveSuit, + const char bestMoveRank, + nodeCardsType * nodep); + + nodeCardsType const * FindSOP( + const int orderSet[], + const int limit, + winCardType * nodeP, + bool& lowerFlag); + + public: + + TransTableS(); + + ~TransTableS(); + + void Init(const int handLookup[][15]); + + void SetMemoryDefault(const int megabytes); + + void SetMemoryMaximum(const int megabytes); + + void MakeTT(); + + void ResetMemory(const TTresetReason reason); + + void ReturnAllMemory(); + + double MemoryInUse() const; + + nodeCardsType const * Lookup( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const int handDist[], + const int limit, + bool& lowerFlag); + + void Add( + const int trick, + const int hand, + const unsigned short aggrTarget[], + const unsigned short winRanksArg[], + const nodeCardsType& first, + const bool flag); + + void PrintNodeStats(ofstream& fout) const; + + void PrintResetStats(ofstream& fout) const; +}; + +#endif diff --git a/src/dds.cpp b/src/dds.cpp index 7cc34340..fad30225 100644 --- a/src/dds.cpp +++ b/src/dds.cpp @@ -2,18 +2,15 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ - #include "../include/dll.h" -#include "dds.h" #include "Init.h" - #ifdef _MANAGED #pragma managed(push, off) #endif diff --git a/src/dds.h b/src/dds.h index e59804b9..dddab1a8 100644 --- a/src/dds.h +++ b/src/dds.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -10,19 +10,8 @@ #ifndef DDS_DDS_H #define DDS_DDS_H -#include -#include -#include -#include -#include -#include - -#include "debug.h" #include "../include/portab.h" - -#include "TransTable.h" -#include "Timer.h" -#include "ABstats.h" +#include "../include/dll.h" #if defined(DDS_MEMORY_LEAKS) && defined(_MSC_VER) @@ -32,28 +21,17 @@ #endif -#if defined(SMALL_MEMORY_OPTION) - #define THREADMEM_MAX_MB 30 - #define THREADMEM_DEF_MB 20 -#else - #define THREADMEM_MAX_MB 160 - #define THREADMEM_DEF_MB 95 -#endif - -#define MAXNOOFTHREADS 16 +#define THREADMEM_SMALL_MAX_MB 30 +#define THREADMEM_SMALL_DEF_MB 20 +#define THREADMEM_LARGE_MAX_MB 160 +#define THREADMEM_LARGE_DEF_MB 95 #define MAXNODE 1 #define MINNODE 0 -#define MOVESVALID 1 -#define MOVESLOCKED 2 - #define SIMILARDEALLIMIT 5 #define SIMILARMAXWINNODES 700000 -#define Max(x, y) (((x) >= (y)) ? (x) : (y)) -#define Min(x, y) (((x) <= (y)) ? (x) : (y)) - #define DDS_NOTRUMP 4 /* "hand" is leading hand, "relative" is hand relative leading @@ -84,16 +62,6 @@ extern char relRank[8192][15]; extern unsigned short int winRanks[8192][14]; -extern int noOfThreads; - -struct playparamType -{ - int noOfBoards; - struct playTracesBin * plp; - struct solvedPlays * solvedp; -}; - - struct moveGroupType { // There are at most 7 groups of bit "runs" in a 13-bit vector @@ -107,8 +75,6 @@ struct moveGroupType extern moveGroupType groupData[8192]; -extern int stat_contr[DDS_STRAINS]; - struct moveType { int suit; @@ -120,7 +86,7 @@ struct moveType struct movePlyType { - struct moveType move[14]; + moveType move[14]; int current; int last; }; @@ -143,15 +109,15 @@ struct pos /* Cards that win by rank, firstindex is depth. */ int first[50]; /* Hand that leads the trick for each ply */ - struct moveType move[50]; + moveType move[50]; /* Presently winning move */ int handRelFirst; /* The current hand, relative first hand */ int tricksMAX; /* Aggregated tricks won by MAX */ - struct highCardType winner[DDS_SUITS]; + highCardType winner[DDS_SUITS]; /* Winning rank of trick. */ - struct highCardType secondBest[DDS_SUITS]; + highCardType secondBest[DDS_SUITS]; /* Second best rank. */ }; @@ -175,26 +141,31 @@ struct extCard int sequence; }; -struct paramType -{ - int noOfBoards; - struct boards * bop; - struct solvedBoards * solvedp; - int error; -}; - struct absRankType // 2 bytes { char rank; - char hand; + signed char hand; }; struct relRanksType // 120 bytes { - struct absRankType absRank[15][DDS_SUITS]; + absRankType absRank[15][DDS_SUITS]; }; -#include "Moves.h" -#include "Scheduler.h" +struct paramType +{ + int noOfBoards; + boards * bop; + solvedBoards * solvedp; + int error; +}; + +enum RunMode +{ + DDS_RUN_SOLVE = 0, + DDS_RUN_CALC = 1, + DDS_RUN_TRACE = 2, + DDS_RUN_SIZE = 3 +}; #endif diff --git a/src/dds.rc b/src/dds.rc index 464df709..7b27b734 100644 --- a/src/dds.rc +++ b/src/dds.rc @@ -1,6 +1,6 @@ 1 VERSIONINFO - FILEVERSION 2,8,4,0 - PRODUCTVERSION 2,8,4,0 + FILEVERSION 2,9,0,0 + PRODUCTVERSION 2,9,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -13,12 +13,12 @@ BEGIN BEGIN VALUE "CompanyName", "http://privat.bahnhof.se/wb758135/" VALUE "FileDescription", "dds MinGW" - VALUE "FileVersion", "2.8.4.0" + VALUE "FileVersion", "2.9.0.0" VALUE "InternalName", "dds.dll" - VALUE "LegalCopyright", "Copyright © 2006-2014 Bo Haglund / 2014-16 Bo Haglund Soren Hein" + VALUE "LegalCopyright", "Copyright © 2006-2014 Bo Haglund / 2014-18 Bo Haglund Soren Hein" VALUE "OriginalFilename", "dds.dll" VALUE "ProductName", "Bridge double dummy solver" - VALUE "ProductVersion", "2.8.4.0" + VALUE "ProductVersion", "2.9.0.0" END END BLOCK "VarFileInfo" diff --git a/src/debug.h b/src/debug.h index d246e7fe..929575b3 100644 --- a/src/debug.h +++ b/src/debug.h @@ -2,7 +2,7 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ @@ -88,15 +88,10 @@ // #define DDS_TIMING #define DDS_TIMING_PREFIX "timer" -// Enables extra detail. -#define DDS_TIMING_DETAILS - // Enables statistics on move generation quality. // #define DDS_MOVES #define DDS_MOVES_PREFIX "movestats" -// #define DDS_MOVES_DETAILS - // Enables timing in the scheduler. // #define DDS_SCHEDULER #define DDS_SCHEDULER_PREFIX "sched" @@ -136,9 +131,6 @@ // #define DDS_MEMORY_LEAKS -// Maximum number of characters in a debug file name. -#define DDS_FNAME_LEN 20 - #define COUNTER_SLOTS 200 extern long long counter[COUNTER_SLOTS]; diff --git a/src/dump.cpp b/src/dump.cpp new file mode 100644 index 00000000..10ee266b --- /dev/null +++ b/src/dump.cpp @@ -0,0 +1,362 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#include +#include +#include +#include + +#include "dump.h" + + +string PrintSuit(const unsigned short suitCode); +string PrintSuit( + const unsigned short suitCode, + const char leastWin); + +string PrintDeal( + const unsigned short ranks[][DDS_SUITS], + const int spacing); + +string RankToDiagrams( + const unsigned short ranks[DDS_HANDS][DDS_SUITS], + const nodeCardsType& node); + +string WinnersToText(const unsigned short winRanks[]); + +string NodeToText(const nodeCardsType& node); + +string FullNodeToText(const nodeCardsType& node); + +string PosToText( + const pos& tpos, + const int target, + const int depth); + +string TopMove( + const bool val, + const moveType& bestMove); + +string DumpTopHeader( + const ThreadData& thrd, + const int tricks, + const int lower, + const int upper, + const int printMode); + + +string PrintSuit(const unsigned short suitCode) +{ + if (! suitCode) + return "--"; + + string st; + for (int r = 14; r >= 2; r--) + if ((suitCode & bitMapRank[r])) + st += static_cast(cardRank[r]); + return st; +} + + +string PrintSuit( + const unsigned short suitCode, + const char leastWin) +{ + if (! suitCode) + return "--"; + + string st; + for (int r = 14; r >= 2; r--) + { + if ((suitCode & bitMapRank[r])) + { + if (r >= 15 - leastWin) + st += static_cast(cardRank[r]); + else + st += "x"; + } + } + return st; +} + + +string PrintDeal( + const unsigned short ranks[][DDS_SUITS], + const int spacing) +{ + stringstream ss; + for (int s = 0; s < DDS_SUITS; s++) + { + ss << setw(spacing) << "" << + cardSuit[s] << " " << + PrintSuit(ranks[0][s]) << "\n"; + } + + for (int s = 0; s < DDS_SUITS; s++) + { + ss << cardSuit[s] << " " << + setw(2*spacing - 2) << left << PrintSuit(ranks[3][s]) << + cardSuit[s] << " " << + PrintSuit(ranks[1][s]) << "\n"; + } + + for (int s = 0; s < DDS_SUITS; s++) + { + ss << setw(spacing) << "" << + cardSuit[s] << " " << + PrintSuit(ranks[2][s]) << "\n"; + } + + return ss.str() + "\n"; +} + + +string RankToDiagrams( + const unsigned short ranks[DDS_HANDS][DDS_SUITS], + const nodeCardsType& node) +{ + stringstream ss; + for (int s = 0; s < DDS_SUITS; s++) + { + ss << setw(12) << left << + (s == 0 ? "Sought" : "") << + cardSuit[s] << " " << setw(20) << PrintSuit(ranks[0][s]) << "| " << + setw(12) << (s == 0 ? "Found" : "") << + cardSuit[s] << " " << + PrintSuit(ranks[0][s], node.leastWin[s]) << "\n"; + } + + for (int s = 0; s < DDS_SUITS; s++) + { + ss << + cardSuit[s] << " " << setw(22) << left << PrintSuit(ranks[3][s]) << + cardSuit[s] << " " << setw(8) << PrintSuit(ranks[1][s]) << "| " << + cardSuit[s] << " " << + setw(22) << PrintSuit(ranks[3][s], node.leastWin[s]) << + cardSuit[s] << " " << + PrintSuit(ranks[1][s], node.leastWin[s]) << "\n"; + } + + for (int s = 0; s < DDS_SUITS; s++) + { + ss << setw(12) << left << "" << + cardSuit[s] << " " << setw(20) << PrintSuit(ranks[0][s]) << "| " << + setw(12) << "" << cardSuit[s] << " " << + PrintSuit(ranks[0][s], node.leastWin[s]) << "\n"; + } + return ss.str(); +} + + +string WinnersToText(const unsigned short ourWinRanks[]) +{ + stringstream ss; + for (int s = 0; s < DDS_SUITS; s++) + ss << cardSuit[s] << " " << PrintSuit(ourWinRanks[s]) << "\n"; + + return ss.str(); +} + + +string NodeToText(const nodeCardsType& node) +{ + stringstream ss; + ss << setw(16) << left << "Address" << + static_cast(&node) << "\n"; + + ss << setw(16) << left << "Bounds" << + static_cast(node.lbound) << " to " << + static_cast(node.ubound) << " tricks\n"; + + ss << setw(16) << left << "Best move" << + cardSuit[ static_cast(node.bestMoveSuit) ] << + cardRank[ static_cast(node.bestMoveRank) ] << "\n"; + + return ss.str(); +} + + +string FullNodeToText(const nodeCardsType& node) + +{ + stringstream ss; + vector v(DDS_SUITS); + for (unsigned i = 0; i < DDS_SUITS; i++) + v[i] = 15 - static_cast(node.leastWin[i]); + + ss << setw(16) << left << "Lowest used" << + cardSuit[0] << cardRank[v[0]] << ", " << + cardSuit[1] << cardRank[v[1]] << ", " << + cardSuit[2] << cardRank[v[2]] << ", " << + cardSuit[3] << cardRank[v[3]] << "\n"; + + return NodeToText(node) + ss.str(); +} + + +string PosToText( + const pos& tpos, + const int target, + const int depth) +{ + stringstream ss; + ss << setw(16) << left << "Target" << target << "\n"; + ss << setw(16) << "Depth" << depth << "\n"; + ss << setw(16) << "tricksMAX" << tpos.tricksMAX << "\n"; + ss << setw(16) << "First hand" << cardHand[tpos.first[depth]] << "\n"; + ss << setw(16) << "Next first" << cardHand[tpos.first[depth - 1]] << "\n"; + return ss.str(); +} + + +string DumpTopHeader( + const ThreadData& thrd, + const int tricks, + const int lower, + const int upper, + const int printMode) +{ + string stext; + if (printMode == 0) + { + // Trying just one target. + stext = "Single target " + to_string(tricks) + ", " + "achieved"; + } + else if (printMode == 1) + { + // Looking for best score. + stext = "Loop target " + to_string(tricks) + ", " + + "bounds " + to_string(lower) + " .. " + to_string(upper) + ", " + + TopMove(thrd.val, thrd.bestMove[thrd.iniDepth]) + ""; + } + else if (printMode == 2) + { + // Looking for other moves with best score. + stext = "Loop for cards with score " + to_string(tricks) + ", " + + TopMove(thrd.val, thrd.bestMove[thrd.iniDepth]); + } + return stext + "\n" + string(stext.size(), '-') + "\n"; +} + + +string TopMove( + const bool val, + const moveType& bestMove) +{ + if (val) + { + stringstream ss; + ss << "achieved with move " << + cardSuit[ bestMove.suit ] << + cardRank[ bestMove.rank ]; + return ss.str(); + } + else + return "failed"; +} + + +int DumpInput( + const int errCode, + const deal& dl, + const int target, + const int solutions, + const int mode) +{ + ofstream fout; + fout.open("dump.txt"); + + fout << "Error code=" << errCode << "\n\n"; + fout << "Deal data:\n"; + fout << "trump="; + + if (dl.trump == DDS_NOTRUMP) + fout << "N\n"; + else + fout << cardSuit[dl.trump] << "\n"; + fout << "first=" << cardHand[dl.first] << "\n"; + + unsigned short ranks[4][4]; + + for (int k = 0; k <= 2; k++) + if (dl.currentTrickRank[k] != 0) + { + fout << "index=" << k << + " currentTrickSuit=" << cardSuit[dl.currentTrickSuit[k]] << + " currentTrickRank= " << cardRank[dl.currentTrickRank[k]] << "\n"; + } + + for (int h = 0; h < DDS_HANDS; h++) + for (int s = 0; s < DDS_SUITS; s++) + { + fout << "index1=" << h << " index2=" << s << + " remainCards=" << dl.remainCards[h][s] << "\n"; + ranks[h][s] = static_cast + (dl.remainCards[h][s] >> 2); + } + + fout << "\ntarget=" << target << "\n"; + fout << "solutions=" << solutions << "\n"; + fout << "mode=" << mode << "\n\n\n"; + fout << PrintDeal(ranks, 8); + + fout.close(); + return 0; +} + + +void DumpRetrieved( + ofstream& fout, + const pos& tpos, + const nodeCardsType& node, + const int target, + const int depth) +{ + fout << "Retrieved entry\n"; + fout << string(15, '-') << "\n"; + fout << PosToText(tpos, target, depth) << "\n"; + fout << FullNodeToText(node) << "\n"; + fout << RankToDiagrams(tpos.rankInSuit, node) << "\n"; +} + + +void DumpStored( + ofstream& fout, + const pos& tpos, + const Moves& moves, + const nodeCardsType& node, + const int target, + const int depth) +{ + fout << "Stored entry\n"; + fout << string(12, '-') << "\n"; + fout << PosToText(tpos, target, depth) << "\n"; + fout << NodeToText(node); + fout << moves.TrickToText((depth >> 2) + 1) << "\n"; + fout << PrintDeal(tpos.rankInSuit, 16); +} + + +void DumpTopLevel( + ofstream& fout, + const ThreadData& thrd, + const int tricks, + const int lower, + const int upper, + const int printMode) +{ + const pos& tpos = thrd.lookAheadPos; + + fout << DumpTopHeader(thrd, tricks, lower, upper, printMode) << "\n"; + fout << PrintDeal(tpos.rankInSuit, 16); + fout << WinnersToText(tpos.winRanks[thrd.iniDepth]) << "\n"; + fout << thrd.nodes << " AB nodes, " << + thrd.trickNodes << " trick nodes\n\n"; +} + diff --git a/src/dump.h b/src/dump.h new file mode 100644 index 00000000..f6a35736 --- /dev/null +++ b/src/dump.h @@ -0,0 +1,48 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_DUMP_H +#define DDS_DUMP_H + +#include "dds.h" +#include "Moves.h" +#include "Memory.h" + +int DumpInput( + const int errCode, + const deal& dl, + const int target, + const int solutions, + const int mode); + +void DumpTopLevel( + ofstream& fout, + const ThreadData& thrd, + const int tricks, + const int lower, + const int upper, + const int printMode); + +void DumpRetrieved( + ofstream& fout, + const pos& tpos, + const nodeCardsType& node, + const int target, + const int depth); + +void DumpStored( + ofstream& fout, + const pos& tpos, + const Moves& moves, + const nodeCardsType& node, + const int target, + const int depth); + +#endif + diff --git a/src/parallel.h b/src/parallel.h new file mode 100644 index 00000000..62dada55 --- /dev/null +++ b/src/parallel.h @@ -0,0 +1,75 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DDS_PARALLEL_H +#define DDS_PARALLEL_H + +// Boost: Disable some header warnings. + +#ifdef DDS_THREADS_BOOST + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4061 4191 4619 4623 5031) + #endif + + #include + + #ifdef _MSC_VER + #pragma warning(pop) + #endif +#endif + +#ifdef DDS_THREADS_GCD + #include +#endif + +#ifdef DDS_THREADS_STL + #include +#endif + +#ifdef DDS_THREADS_STLIMPL + #include +#endif + +#ifdef DDS_THREADS_PPLIMPL + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4355 4619 5038) + #endif + + #include "ppl.h" + + #ifdef _MSC_VER + #pragma warning(pop) + #endif +#endif + +#ifdef DDS_THREADS_TBB + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4574) + #endif + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wold-style-cast" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + + #include "tbb/tbb.h" + #include "tbb/tbb_thread.h" + + #pragma GCC diagnostic pop + + #ifdef _MSC_VER + #pragma warning(pop) + #endif +#endif + +#endif + diff --git a/src/threadmem.h b/src/threadmem.h deleted file mode 100644 index 243a00ab..00000000 --- a/src/threadmem.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - -#ifndef DDS_THREADMEM_H -#define DDS_THREADMEM_H - -struct WinnerEntryType -{ - int suit; - int winnerRank; - int winnerHand; - int secondRank; - int secondHand; -}; - -struct WinnersType -{ - int number; - WinnerEntryType winner[4]; -}; - - -struct localVarType -{ - int nodeTypeStore[DDS_HANDS]; - int iniDepth; - bool val; - - unsigned short int suit[DDS_HANDS][DDS_SUITS]; - int trump; - - struct pos lookAheadPos; // Recursive alpha-beta data - bool analysisFlag; - unsigned short int lowestWin[50][DDS_SUITS]; - WinnersType winners[13]; - struct moveType forbiddenMoves[14]; - struct moveType bestMove[50]; - struct moveType bestMoveTT[50]; - - double memUsed; - int nodes; - int trickNodes; - - // Constant for a given hand. - // 960 KB - struct relRanksType rel[8192]; - - TransTable transTable; // Object - - Moves moves; // Object - -#ifdef DDS_AB_STATS - ABstats ABStats; // Object -#endif - -#ifdef DDS_TIMING - Timer timer; // Object -#endif - -#ifdef DDS_TOP_LEVEL - FILE * fpTopLevel; -#endif - -#ifdef DDS_AB_HITS - FILE * fpRetrieved; - FILE * fpStored; -#endif - -}; - -extern Scheduler scheduler; - -extern struct localVarType localVar[MAXNOOFTHREADS]; - -#endif diff --git a/test/Makefiles/Makefile_Mac_clang b/test/Makefiles/Makefile_Mac_clang index 3bb75c59..a07fa370 100644 --- a/test/Makefiles/Makefile_Mac_clang +++ b/test/Makefiles/Makefile_Mac_clang @@ -1,9 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Mac and the clang compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for MacOS and the clang compiler. +# It assumes a Unix-like setup for some commands. + +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -11,15 +12,32 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. +# If you need to add something for the threading system, this is +# the place. + +# This is only necessary for the .a static library, actually. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_LINK = $(CC_BOOST_LINK) + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt # If your compiler name is not given here, change it. CC = g++ -# Use this one to get single-threading -CC_FLAGS = -O3 -flto -mtune=generic +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -43,150 +61,55 @@ WARN_FLAGS = \ -Wno-long-long \ -Wno-format -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = -O3 -flto -mtune=generic \ + $(WARN_FLAGS) -std=c++11 DLLBASE = dds STATIC_LIB = lib$(DLLBASE).a DLIB = $(DLLBASE).lib +LINK1_FLAGS = +LINK2_FLAGS = $(THREAD_LINK) \ + -L. -l$(DLLBASE) +LINK3_FLAGS = $(THREAD_LINK) + # This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp -LIB_FLAGS = -L. -l$(DLLBASE) +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.o,$(DTEST_SOURCE_FILES)) $(DTEST).o +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.o,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(DTEST_OBJ_FILES) $(LIB_FLAGS) -o $(DTEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(DTEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(DTEST) itest: $(ITEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(ITEST_OBJ_FILES) -o $(ITEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK3_FLAGS) -o $(ITEST) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + $(CC) $(COMPILE_FLAGS) -c $< -o $*.o depend: makedepend -Y -- $(ITEST_SOURCE_FILES) $(DTEST).cpp clean: - rm -f $(ITEST_OBJ_FILES) $(DTEST).o $(DTEST) $(ITEST) $(STATIC_LIB) - - -# DO NOT DELETE - -../src/dds.o: ../include/dll.h ../src/dds.h ../src/debug.h ../include/portab.h -../src/dds.o: ../src/TransTable.h ../src/Timer.h ../src/ABstats.h -../src/dds.o: ../src/Moves.h ../src/Stats.h ../src/Scheduler.h ../src/Init.h -../src/ABsearch.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.o: ../src/Scheduler.h ../src/threadmem.h ../src/QuickTricks.h -../src/ABsearch.o: ../src/LaterTricks.h ../src/ABsearch.h -../src/ABstats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.o: ../src/Scheduler.h -../src/CalcTables.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.o: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.o: ../src/Scheduler.h -../src/Init.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.o: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.o: ../src/ABsearch.h -../src/LaterTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.o: ../src/LaterTricks.h -../src/Moves.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.o: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.o: ../src/dds.h ../src/debug.h ../include/portab.h ../src/TransTable.h -../src/Par.o: ../include/dll.h ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Par.o: ../src/Stats.h ../src/Scheduler.h -../src/PlayAnalyser.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.o: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.o: ../src/SolverIF.h ../src/PBN.h -../src/PBN.o: ../src/dds.h ../src/debug.h ../include/portab.h ../src/TransTable.h -../src/PBN.o: ../include/dll.h ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/PBN.o: ../src/Stats.h ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.o: ../src/QuickTricks.h -../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.o: ../include/portab.h ../src/TransTable.h ../include/dll.h -../src/Scheduler.o: ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Scheduler.o: ../src/Stats.h -../src/SolveBoard.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.o: ../src/Scheduler.h ../src/threadmem.h ../src/SolverIF.h -../src/SolveBoard.o: ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.o: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.o: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.o: ../src/Scheduler.h -../src/Timer.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.o: ../src/Scheduler.h -../src/TransTable.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.o: ../src/Scheduler.h -testcommon.o: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.o: ../include/portab.h testStats.h -itest.o: ../include/dll.h testcommon.h -dtest.o: ../include/dll.h testcommon.h + rm -f $(ITEST_OBJ_FILES) $(DTEST).o \ + $(DTEST) $(ITEST) $(STATIC_LIB) + +include $(INCL_DEPENDS) + diff --git a/test/Makefiles/Makefile_Mac_gcc b/test/Makefiles/Makefile_Mac_gcc index 598f88d6..835f8a9c 100644 --- a/test/Makefiles/Makefile_Mac_gcc +++ b/test/Makefiles/Makefile_Mac_gcc @@ -1,12 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Mac and the GNU g++ compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for MacOS and the GNU g++ compiler. +# It assumes a Unix-like setup for some commands. -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -14,17 +12,30 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. +# If you need to add something for the threading system, this is +# the place. + +CC_BOOST = /usr/local/Cellar/boost/1.56.0 +CC_BOOST_LINK = -L$(CC_BOOST)/lib -lboost_system -lboost_thread-mt + +THREAD_LINK = $(CC_BOOST_LINK) + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt # If your compiler name is not given here, change it. CC = gcc-4.9 -# Use this one to get single-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -50,151 +61,55 @@ WARN_FLAGS = \ -Wno-long-long \ -Wno-format -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic \ + $(WARN_FLAGS) -std=c++11 DLLBASE = dds STATIC_LIB = lib$(DLLBASE).a +SHARED_LIB = lib$(DLLBASE).so DLIB = $(DLLBASE).lib +LINK1_FLAGS = +LINK2_FLAGS = $(THREAD_LINK) \ + -L. -l$(DLLBASE) \ + -lgomp -lstdc++ + # This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp -LIB_FLAGS = -L. -l$(DLLBASE) -LD_FLAGS = -lgomp -lstdc++ +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.o,$(DTEST_SOURCE_FILES)) $(DTEST).o +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.o,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(DTEST_OBJ_FILES) $(LIB_FLAGS) $(LD_FLAGS) -o $(DTEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(DTEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(DTEST) itest: $(ITEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(ITEST_OBJ_FILES) $(LD_FLAGS) -o $(ITEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(ITEST) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + $(CC) $(COMPILE_FLAGS) -c $< -o $*.o depend: makedepend -Y -- $(ITEST_SOURCE_FILES) $(DTEST).cpp clean: - rm -f *.o $(DTEST) $(ITEST) $(STATIC_LIB) - - -# DO NOT DELETE - -../src/dds.o: ../include/dll.h ../src/dds.h ../src/debug.h ../include/portab.h -../src/dds.o: ../src/TransTable.h ../src/Timer.h ../src/ABstats.h -../src/dds.o: ../src/Moves.h ../src/Stats.h ../src/Scheduler.h ../src/Init.h -../src/ABsearch.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.o: ../src/Scheduler.h ../src/threadmem.h ../src/QuickTricks.h -../src/ABsearch.o: ../src/LaterTricks.h ../src/ABsearch.h -../src/ABstats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.o: ../src/Scheduler.h -../src/CalcTables.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.o: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.o: ../src/Scheduler.h -../src/Init.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.o: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.o: ../src/ABsearch.h -../src/LaterTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.o: ../src/LaterTricks.h -../src/Moves.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.o: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.o: ../src/dds.h ../src/debug.h ../include/portab.h ../src/TransTable.h -../src/Par.o: ../include/dll.h ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Par.o: ../src/Stats.h ../src/Scheduler.h -../src/PlayAnalyser.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.o: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.o: ../src/SolverIF.h ../src/PBN.h -../src/PBN.o: ../src/dds.h ../src/debug.h ../include/portab.h ../src/TransTable.h -../src/PBN.o: ../include/dll.h ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/PBN.o: ../src/Stats.h ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.o: ../src/QuickTricks.h -../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.o: ../include/portab.h ../src/TransTable.h ../include/dll.h -../src/Scheduler.o: ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Scheduler.o: ../src/Stats.h -../src/SolveBoard.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.o: ../src/Scheduler.h ../src/threadmem.h ../src/SolverIF.h -../src/SolveBoard.o: ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.o: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.o: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.o: ../src/Scheduler.h -../src/Timer.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.o: ../src/Scheduler.h -../src/TransTable.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.o: ../src/Scheduler.h -testcommon.o: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.o: ../include/portab.h testStats.h -itest.o: ../include/dll.h testcommon.h -dtest.o: ../include/dll.h testcommon.h + rm -f *.o $(DTEST) $(ITEST) $(STATIC_LIB) $(SHARED_LIB) + +include $(INCL_DEPENDS) + diff --git a/test/Makefiles/Makefile_Visual b/test/Makefiles/Makefile_Visual index 06a692d1..08aeb834 100644 --- a/test/Makefiles/Makefile_Visual +++ b/test/Makefiles/Makefile_Visual @@ -1,12 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Windows and the Microsoft Visual C++ compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for Windows and the Microsoft Visual C++ +# compiler. It assumes a Unix-like setup for some commands. -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -14,175 +12,111 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. -# If your Microsoft compiler is not called cl, change it here. +# If you need to add something for the threading system, this is +# the place. + +BOOST32_PATH1 = \User\sheins\boost_1_66_0_x32_new +BOOST32_LIB1 = $(BOOST32_PATH1)\lib32-msvc-14.1 + +BOOST32_PATH2 = \Users\s.hein\Documents\Programs\boost_1_66_0_x32_14_1 +BOOST32_LIB2 = $(BOOST32_PATH2)\lib32-msvc-14.1 + +CC_BOOST_INCL = /I$(BOOST32_PATH1) /I$(BOOST32_PATH2) +CC_BOOST_LINK = /LIBPATH:$(BOOST32_LIB1) /LIBPATH:$(BOOST32_LIB2) + +THREAD_LINK = $(CC_BOOST_LINK) + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_obj.txt + +# If your compiler name is not given here, change it. CC = cl -CC_FLAGS = /O2 /Oi /Ot /Oy /GL -LINK_FLAGS = /LTCG -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... + WARN_FLAGS = \ /Wall \ /wd4127 \ + /wd4242 \ + /wd4244 \ + /wd4365 \ + /wd4464 \ /wd4514 \ + /wd4530 \ /wd4555 \ + /wd4577 \ + /wd4592 \ + /wd4625 \ + /wd4626 \ /wd4668 \ /wd4701 \ + /wd4710 \ /wd4711 \ + /wd4774 \ /wd4820 \ /wd4986 \ /wd4987 \ /wd4996 \ + /wd5026 \ + /wd5027 \ /WX -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = /O2 /Oi /Ot /Oy /GL $(WARN_FLAGS) DLLBASE = dds DLL = $(DLLBASE).dll DLIB = $(DLLBASE).lib EXPORTER = Exports.def +LINK1_FLAGS = /LTCG +LINK2_FLAGS = $(THREAD_LINK) + # This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.obj,$(DTEST_SOURCE_FILES)) $(DTEST).obj +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.obj,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - link $(DTEST_OBJ_FILES) $(DLIB) /out:$(DTEST).exe + link $(LINK1_FLAGS) $(DTEST_OBJ_FILES) $(DLIB) \ + $(LINK2_FLAGS) /out:$(DTEST).exe itest: $(ITEST_OBJ_FILES) - link /LTCG $(ITEST_OBJ_FILES) /out:$(ITEST).exe + link $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK2_FLAGS) /out:$(ITEST).exe %.obj: %.cpp - $(CC) $(CC_FULL_FLAGS) /c $< /Fo$*.obj + $(CC) $(COMPILE_FLAGS) $(CC_BOOST_INCL) /c $< /Fo$*.obj depend: makedepend -Y -o.obj -- $(ITEST_SOURCE_FILES) $(DTEST).cpp clean: - rm -f $(ITEST_OBJ_FILES) $(DTEST).{obj,exe} $(ITEST).{exe,exp,lib} $(DLL) $(DLIB) - - -# DO NOT DELETE - -../src/dds.obj: ../include/dll.h ../src/dds.h ../src/debug.h -../src/dds.obj: ../include/portab.h ../src/TransTable.h ../src/Timer.h -../src/dds.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/dds.obj: ../src/Scheduler.h ../src/Init.h -../src/ABsearch.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.obj: ../src/Scheduler.h ../src/threadmem.h -../src/ABsearch.obj: ../src/QuickTricks.h ../src/LaterTricks.h -../src/ABsearch.obj: ../src/ABsearch.h -../src/ABstats.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.obj: ../src/Scheduler.h -../src/CalcTables.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.obj: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.obj: ../src/Scheduler.h -../src/Init.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.obj: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.obj: ../src/ABsearch.h -../src/LaterTricks.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.obj: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.obj: ../src/LaterTricks.h -../src/Moves.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.obj: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Par.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Par.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Par.obj: ../src/Scheduler.h -../src/PlayAnalyser.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.obj: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.obj: ../src/SolverIF.h ../src/PBN.h -../src/PBN.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PBN.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PBN.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PBN.obj: ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.obj: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.obj: ../src/QuickTricks.h -../src/Scheduler.obj: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.obj: ../include/portab.h ../src/TransTable.h -../src/Scheduler.obj: ../include/dll.h ../src/Timer.h ../src/ABstats.h -../src/Scheduler.obj: ../src/Moves.h ../src/Stats.h -../src/SolveBoard.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.obj: ../src/Scheduler.h ../src/threadmem.h -../src/SolveBoard.obj: ../src/SolverIF.h ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.obj: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.obj: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.obj: ../src/Scheduler.h -../src/Timer.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.obj: ../src/Scheduler.h -../src/TransTable.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.obj: ../src/Scheduler.h -testcommon.obj: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.obj: ../include/portab.h testStats.h -itest.obj: ../include/dll.h testcommon.h -dtest.obj: ../include/dll.h testcommon.h + rm -f $(ITEST_OBJ_FILES) $(DTEST).{obj,exe} \ + $(ITEST).{exe,exp,lib} $(DLL) $(DLIB) + +# If you don't have a Linux-like setup, use "del" instead of "rm". + +include $(INCL_DEPENDS) diff --git a/test/Makefiles/Makefile_Visual_Windows b/test/Makefiles/Makefile_Visual_Windows deleted file mode 100644 index 2c74d36c..00000000 --- a/test/Makefiles/Makefile_Visual_Windows +++ /dev/null @@ -1,209 +0,0 @@ -# This is a Makefile for the dtest test program, -# for Windows and the Microsoft Visual C++ compiler. -# Unlike the other Makefiles, it does not assume a Unix-like setup. -# Contributed by Philippe Capron in Dec. 2014. - -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. - -# The Makefile also allows an "un-official" and ugly, but -# sometimes practical compilation of a directly integrated -# executable (i.e. not using the DLL). For this the Makefile -# uses the source and object files in the src directory... -# Use "make itest" at your own risk. - -# If your Microsoft compiler is not called cl, change it here. -CC = cl -CC_FLAGS = /O2 /Oi /Ot /Oy /GL -LINK_FLAGS = /LTCG - -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. -WARN_FLAGS = \ - /Wall \ - /wd4127 \ - /wd4514 \ - /wd4555 \ - /wd4668 \ - /wd4701 \ - /wd4711 \ - /wd4820 \ - /wd4986 \ - /wd4987 \ - /wd4996 \ - /WX - -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest - -DLLBASE = dds -DLL = $(DLLBASE).dll -DLIB = $(DLLBASE).lib -EXPORTER = Exports.def - -# This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp - -DTEST_OBJ_FILES = \ - testcommon.obj \ - testStats.obj \ - $(DTEST).obj - -# These are the files that we steal from the src directory. -SRC = ..\src -STOLEN_SOURCE_FILES = \ - $(SRC)\dds.cpp \ - $(SRC)\ABsearch.cpp \ - $(SRC)\ABstats.cpp \ - $(SRC)\CalcTables.cpp \ - $(SRC)\DealerPar.cpp \ - $(SRC)\Init.cpp \ - $(SRC)\LaterTricks.cpp \ - $(SRC)\Moves.cpp \ - $(SRC)\Par.cpp \ - $(SRC)\PlayAnalyser.cpp \ - $(SRC)\PBN.cpp \ - $(SRC)\QuickTricks.cpp \ - $(SRC)\Scheduler.cpp \ - $(SRC)\SolveBoard.cpp \ - $(SRC)\SolverIF.cpp \ - $(SRC)\Stats.cpp \ - $(SRC)\Timer.cpp \ - $(SRC)\TransTable.cpp - -ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ - $(DTEST_SOURCE_FILES) \ - itest.cpp - -ITEST_OBJ_FILES = \ - $(SRC)\dds.obj \ - $(SRC)\ABsearch.obj \ - $(SRC)\ABstats.obj \ - $(SRC)\CalcTables.obj \ - $(SRC)\DealerPar.obj \ - $(SRC)\Init.obj \ - $(SRC)\LaterTricks.obj \ - $(SRC)\Moves.obj \ - $(SRC)\Par.obj \ - $(SRC)\PlayAnalyser.obj \ - $(SRC)\PBN.obj \ - $(SRC)\QuickTricks.obj \ - $(SRC)\Scheduler.obj \ - $(SRC)\SolveBoard.obj \ - $(SRC)\SolverIF.obj \ - $(SRC)\Stats.obj \ - $(SRC)\Timer.obj \ - $(SRC)\TransTable.obj \ - testcommon.obj \ - testStats.obj \ - itest.obj - -dtest: $(DTEST_OBJ_FILES) - link $(DTEST_OBJ_FILES) $(DLIB) /out:$(DTEST).exe - -itest: $(ITEST_OBJ_FILES) - link /LTCG $(ITEST_OBJ_FILES) /out:$(ITEST).exe - -%.obj: %.cpp - $(CC) $(CC_FULL_FLAGS) /c $< /Fo$*.obj - -clean: - del $(ITEST_OBJ_FILES) \ - $(DTEST).obj $(DTEST).exe \ - $(ITEST).exe $(ITEST).exp $(ITEST).lib \ - $(DLL) $(DLIB) - - -# DO NOT DELETE - -../src/dds.obj: ../include/dll.h ../src/dds.h ../src/debug.h -../src/dds.obj: ../include/portab.h ../src/TransTable.h ../src/Timer.h -../src/dds.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/dds.obj: ../src/Scheduler.h ../src/Init.h -../src/ABsearch.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.obj: ../src/Scheduler.h ../src/threadmem.h -../src/ABsearch.obj: ../src/QuickTricks.h ../src/LaterTricks.h -../src/ABsearch.obj: ../src/ABsearch.h -../src/ABstats.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.obj: ../src/Scheduler.h -../src/CalcTables.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.obj: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.obj: ../src/Scheduler.h -../src/Init.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.obj: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.obj: ../src/ABsearch.h -../src/LaterTricks.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.obj: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.obj: ../src/LaterTricks.h -../src/Moves.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.obj: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Par.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Par.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Par.obj: ../src/Scheduler.h -../src/PlayAnalyser.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.obj: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.obj: ../src/SolverIF.h ../src/PBN.h -../src/PBN.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PBN.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PBN.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PBN.obj: ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.obj: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.obj: ../src/QuickTricks.h -../src/Scheduler.obj: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.obj: ../include/portab.h ../src/TransTable.h -../src/Scheduler.obj: ../include/dll.h ../src/Timer.h ../src/ABstats.h -../src/Scheduler.obj: ../src/Moves.h ../src/Stats.h -../src/SolveBoard.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.obj: ../src/Scheduler.h ../src/threadmem.h -../src/SolveBoard.obj: ../src/SolverIF.h ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.obj: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.obj: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.obj: ../src/Scheduler.h -../src/Timer.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.obj: ../src/Scheduler.h -../src/TransTable.obj: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.obj: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.obj: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.obj: ../src/Scheduler.h -testcommon.obj: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.obj: ../include/portab.h testStats.h -itest.obj: ../include/dll.h testcommon.h -dtest.obj: ../include/dll.h testcommon.h diff --git a/test/Makefiles/Makefile_cygwin b/test/Makefiles/Makefile_cygwin index 06cf9f1a..7657432c 100644 --- a/test/Makefiles/Makefile_cygwin +++ b/test/Makefiles/Makefile_cygwin @@ -1,12 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Cygwin under Windows and the GNU g++ compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for Windows and the Cygwin GNU g++ +# compiler. It assumes a Unix-like setup for some commands. -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -14,17 +12,29 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. +# If you need to add something for the threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_LINK = $(CC_BOOST_LINK) + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt # If your compiler name is not given here, change it. CC = g++ -# Use this one to get Windows multi-threading -# CC_FLAGS = -O3 -flto -mtune=generic -fno-use-linker-plugin -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic -fno-use-linker-plugin +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -32,13 +42,13 @@ WARN_FLAGS = \ -Wcast-align -Wcast-qual \ -Wctor-dtor-privacy \ -Wdisabled-optimization \ + -Wformat=2 \ -Winit-self \ -Wlogical-op \ -Wmissing-declarations \ -Wmissing-include-dirs \ -Wnoexcept \ -Wold-style-cast \ - -Wformat=2 \ -Woverloaded-virtual \ -Wredundant-decls \ -Wsign-promo \ @@ -50,162 +60,65 @@ WARN_FLAGS = \ -Wno-unknown-pragmas \ -Wno-long-long -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic \ + -fno-use-linker-plugin \ + $(WARN_FLAGS) DLLBASE = dds DLL = $(DLLBASE).dll DLIB = $(DLLBASE).lib EXPORTER = Exports.def -# This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp - -LD_FLAGS = \ +LINK1_FLAGS = +LINK2_FLAGS = \ -Wl,--subsystem,windows \ -Wl,--output-def,$(DLLBASE).def \ -Wl,--dynamicbase \ -Wl,--nxcompat \ -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup + -Wl,--enable-stdcall-fixup \ + $(THREAD_LINK) \ + -L. -l$(DLLBASE) -LIB_FLAGS = -L. -l$(DLLBASE) +# This is in addition to $(DTEST).cpp + +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.o,$(DTEST_SOURCE_FILES)) $(DTEST).o +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.o,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(DTEST_OBJ_FILES) $(LD_FLAGS) $(LIB_FLAGS) -o $(DTEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(DTEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(DTEST) itest: $(ITEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(ITEST_OBJ_FILES) $(LD_FLAGS) -o $(ITEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(ITEST) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + $(CC) $(COMPILE_FLAGS) -c $< -o $*.o depend: makedepend -Y -- $(ITEST_SOURCE_FILES) $(DTEST).cpp clean: - rm -f $(ITEST_OBJ_FILES) $(DTEST).{o,exe} $(ITEST).exe $(DLL) $(DLLBASE).def - - -# DO NOT DELETE - -../src/dds.o: ../include/dll.h ../src/dds.h ../src/debug.h -../src/dds.o: ../include/portab.h ../src/TransTable.h ../src/Timer.h -../src/dds.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/dds.o: ../src/Scheduler.h ../src/Init.h -../src/ABsearch.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.o: ../src/Scheduler.h ../src/threadmem.h ../src/QuickTricks.h -../src/ABsearch.o: ../src/LaterTricks.h ../src/ABsearch.h -../src/ABstats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.o: ../src/Scheduler.h -../src/CalcTables.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.o: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.o: ../src/Scheduler.h -../src/Init.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.o: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.o: ../src/ABsearch.h -../src/LaterTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.o: ../src/LaterTricks.h -../src/Moves.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.o: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Par.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Par.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Par.o: ../src/Scheduler.h -../src/PlayAnalyser.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.o: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.o: ../src/SolverIF.h ../src/PBN.h -../src/PBN.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PBN.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PBN.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PBN.o: ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.o: ../src/QuickTricks.h -../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.o: ../include/portab.h ../src/TransTable.h ../include/dll.h -../src/Scheduler.o: ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Scheduler.o: ../src/Stats.h -../src/SolveBoard.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.o: ../src/Scheduler.h ../src/threadmem.h ../src/SolverIF.h -../src/SolveBoard.o: ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.o: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.o: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.o: ../src/Scheduler.h -../src/Timer.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.o: ../src/Scheduler.h -../src/TransTable.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.o: ../src/Scheduler.h -testcommon.o: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.o: ../include/portab.h testStats.h -itest.o: ../include/dll.h testcommon.h -dtest.o: ../include/dll.h testcommon.h + rm -f $(ITEST_OBJ_FILES) $(DTEST).{o,exe} $(ITEST).exe \ + $(DLL) $(DLLBASE).def + +# If you don't have a Linux-like setup, use "del" instead of "rm". + +include $(INCL_DEPENDS) + diff --git a/test/Makefiles/Makefile_linux b/test/Makefiles/Makefile_linux index d036f65d..55f42cd4 100644 --- a/test/Makefiles/Makefile_linux +++ b/test/Makefiles/Makefile_linux @@ -1,12 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Linux and the GNU g++ compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for Linux and the GNU g++ compiler. +# It assumes a Unix-like setup for some commands. -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -14,17 +12,29 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. +# If you need to add something for the threading system, this is +# the place. + +CC_BOOST_LINK = -lboost_system -lboost_thread + +THREAD_LINK = $(CC_BOOST_LINK) + +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt # If your compiler name is not given here, change it. CC = g++ -# Use this one to get single-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -48,157 +58,60 @@ WARN_FLAGS = \ -Wno-unused \ -Wno-unknown-pragmas \ -Wno-long-long \ + -Wno-odr \ -Wno-format -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = -O3 -flto -fopenmp -mtune=generic \ + $(WARN_FLAGS) DLLBASE = dds STATIC_LIB = lib$(DLLBASE).a DLIB = $(DLLBASE).lib -# This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp +LINK1_FLAGS = +LINK2_FLAGS = -Wl,-rpath=. \ + $(THREAD_LINK) \ + -L. -l$(DLLBASE) +LINK3_FLAGS = -Wl,-rpath=. \ + $(THREAD_LINK) -LD_FLAGS = +# This is in addition to $(DTEST).cpp -LIB_FLAGS = -L. -l$(DLLBASE) +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.o,$(DTEST_SOURCE_FILES)) $(DTEST).o +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.o,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(DTEST_OBJ_FILES) $(LD_FLAGS) $(LIB_FLAGS) -o $(DTEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(DTEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(DTEST) itest: $(ITEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(ITEST_OBJ_FILES) $(LD_FLAGS) -o $(ITEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK3_FLAGS) -o $(ITEST) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + $(CC) $(COMPILE_FLAGS) -c $< -o $*.o depend: makedepend -Y -- $(ITEST_SOURCE_FILES) $(DTEST).cpp clean: - rm -f $(ITEST_OBJ_FILES) $(DTEST).o $(DTEST) $(ITEST) $(STATIC_LIB) - - -# DO NOT DELETE - -../src/dds.o: ../include/dll.h ../src/dds.h ../src/debug.h -../src/dds.o: ../include/portab.h ../src/TransTable.h ../src/Timer.h -../src/dds.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/dds.o: ../src/Scheduler.h ../src/Init.h -../src/ABsearch.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.o: ../src/Scheduler.h ../src/threadmem.h ../src/QuickTricks.h -../src/ABsearch.o: ../src/LaterTricks.h ../src/ABsearch.h -../src/ABstats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.o: ../src/Scheduler.h -../src/CalcTables.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.o: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.o: ../src/Scheduler.h -../src/Init.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.o: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.o: ../src/ABsearch.h -../src/LaterTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.o: ../src/LaterTricks.h -../src/Moves.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.o: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Par.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Par.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Par.o: ../src/Scheduler.h -../src/PlayAnalyser.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.o: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.o: ../src/SolverIF.h ../src/PBN.h -../src/PBN.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PBN.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PBN.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PBN.o: ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.o: ../src/QuickTricks.h -../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.o: ../include/portab.h ../src/TransTable.h ../include/dll.h -../src/Scheduler.o: ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Scheduler.o: ../src/Stats.h -../src/SolveBoard.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.o: ../src/Scheduler.h ../src/threadmem.h ../src/SolverIF.h -../src/SolveBoard.o: ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.o: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.o: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.o: ../src/Scheduler.h -../src/Timer.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.o: ../src/Scheduler.h -../src/TransTable.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.o: ../src/Scheduler.h -testcommon.o: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.o: ../include/portab.h testStats.h -itest.o: ../include/dll.h testcommon.h -dtest.o: ../include/dll.h testcommon.h + rm -f $(ITEST_OBJ_FILES) $(DTEST).o \ + $(DTEST) $(ITEST) $(STATIC_LIB) + +include $(INCL_DEPENDS) + diff --git a/test/Makefiles/Makefile_mingw b/test/Makefiles/Makefile_mingw index 70c7ad95..8738dc6e 100644 --- a/test/Makefiles/Makefile_mingw +++ b/test/Makefiles/Makefile_mingw @@ -1,12 +1,10 @@ -# This is a Makefile for the dtest test program, -# for Windows and the minGW compiler. +# --------------------- INFORMATION -------------------------------- -# It does assume a Unix-like setup for some commands, -# but if you only want to call "make" with the default target, -# you should be OK. +# This the test Makefile for Windows and the mingw GNU g++ +# compiler. It assumes a Unix-like setup for some commands. -# The test program itself does not use multi-threading, -# but the DLL might, depending on how it was compiled. +# The dtest program itself does not use multi-threading, +# but the library might, depending on how it was compiled. # The Makefile also allows an "un-official" and ugly, but # sometimes practical compilation of a directly integrated @@ -14,18 +12,27 @@ # uses the source and object files in the src directory... # Use "make itest" at your own risk. +# If you need to add something for the threading system, this is +# the place. -# If your exact compiler name is not given here, change it. -# CC = mingw32-g++ -CC = i686-w64-mingw32-g++ +THREAD_LINK = -lboost_system -lboost_thread -lgomp -# Use this one to get Windows multi-threading -# CC_FLAGS = -O3 -flto -mtune=generic -# Use this one to get OpenMP multi-threading -CC_FLAGS = -O3 -flto -fopenmp -mtune=generic +# ----------------------- OFTEN OK ------------------------------ + +# From here on you you don't have to change anything to CONFIGURE +# the compilation. But you may well have to change something to +# get it to compile. + +INCL_DDS_SOURCE = Makefiles/dds_sources.txt +INCL_OWN_SOURCE = Makefiles/own_sources.txt +INCL_DEPENDS = Makefiles/depends_o.txt + +# If your compiler name is not given here, change it. +CC = g++ + +# We compile with aggressive warnings, but we have to turn off some +# of them as they appear in libraries in great numbers... -# These flags are not turned on by default, but DDS should pass them. -# Turn them on below. WARN_FLAGS = \ -Wshadow \ -Wsign-conversion \ @@ -51,72 +58,52 @@ WARN_FLAGS = \ -Wno-long-long \ -Wno-format -# Here you can turn on warnings. -# CC_FULL_FLAGS = $(CC_FLAGS) -CC_FULL_FLAGS = $(CC_FLAGS) $(WARN_FLAGS) - -DTEST = dtest -ITEST = itest +COMPILE_FLAGS = -O3 $(WARN_FLAGS) DLLBASE = dds DLL = $(DLLBASE).dll DLIB = $(DLLBASE).lib EXPORTER = Exports.def -# This is in addition to $(DTEST).cpp -DTEST_SOURCE_FILES = \ - testcommon.cpp \ - testStats.cpp - -LD_FLAGS = \ - -Wl,--subsystem,windows \ - -Wl,--output-def,$(DLLBASE).def \ +LINK1_FLAGS = +LINK2_FLAGS = \ -Wl,--dynamicbase \ -Wl,--nxcompat \ -Wl,--no-seh \ - -Wl,--enable-stdcall-fixup + -Wl,--enable-stdcall-fixup \ + $(THREAD_LINK) \ + -L. -l$(DLLBASE) + +# This is in addition to $(DTEST).cpp -LIB_FLAGS = -L. -l$(DLLBASE) +include $(INCL_OWN_SOURCE) DTEST_OBJ_FILES = $(subst .cpp,.o,$(DTEST_SOURCE_FILES)) $(DTEST).o +DTEST = dtest +ITEST = itest + # These are the files that we steal from the src directory. -SRC = ../src -STOLEN_SOURCE_FILES = \ - $(SRC)/dds.cpp \ - $(SRC)/ABsearch.cpp \ - $(SRC)/ABstats.cpp \ - $(SRC)/CalcTables.cpp \ - $(SRC)/DealerPar.cpp \ - $(SRC)/Init.cpp \ - $(SRC)/LaterTricks.cpp \ - $(SRC)/Moves.cpp \ - $(SRC)/Par.cpp \ - $(SRC)/PlayAnalyser.cpp \ - $(SRC)/PBN.cpp \ - $(SRC)/QuickTricks.cpp \ - $(SRC)/Scheduler.cpp \ - $(SRC)/SolveBoard.cpp \ - $(SRC)/SolverIF.cpp \ - $(SRC)/Stats.cpp \ - $(SRC)/Timer.cpp \ - $(SRC)/TransTable.cpp + +include $(INCL_DDS_SOURCE) ITEST_SOURCE_FILES = \ - $(STOLEN_SOURCE_FILES) \ + $(DDS_SOURCE_FILES) \ $(DTEST_SOURCE_FILES) \ itest.cpp ITEST_OBJ_FILES = $(subst .cpp,.o,$(ITEST_SOURCE_FILES)) dtest: $(DTEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(DTEST_OBJ_FILES) $(LD_FLAGS) $(LIB_FLAGS) -o $(DTEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(DTEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(DTEST) itest: $(ITEST_OBJ_FILES) - $(CC) $(CC_FULL_FLAGS) $(ITEST_OBJ_FILES) $(LD_FLAGS) -o $(ITEST) + $(CC) $(COMPILE_FLAGS) $(LINK1_FLAGS) $(ITEST_OBJ_FILES) \ + $(LINK2_FLAGS) -o $(ITEST) %.o: %.cpp - $(CC) $(CC_FULL_FLAGS) -c $< -o $*.o + $(CC) $(COMPILE_FLAGS) -c $< -o $*.o depend: makedepend -Y -- $(ITEST_SOURCE_FILES) $(DTEST).cpp @@ -124,89 +111,9 @@ depend: clean: rm -f *.o *.exe $(DLLBASE).def $(DLL) +# If you don't have a Linux-like setup, use "del" instead of "rm". + +include $(INCL_DEPENDS) # DO NOT DELETE -../src/dds.o: ../include/dll.h ../src/dds.h ../src/debug.h -../src/dds.o: ../include/portab.h ../src/TransTable.h ../src/Timer.h -../src/dds.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/dds.o: ../src/Scheduler.h ../src/Init.h -../src/ABsearch.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABsearch.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABsearch.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABsearch.o: ../src/Scheduler.h ../src/threadmem.h ../src/QuickTricks.h -../src/ABsearch.o: ../src/LaterTricks.h ../src/ABsearch.h -../src/ABstats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/ABstats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/ABstats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/ABstats.o: ../src/Scheduler.h -../src/CalcTables.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/CalcTables.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/CalcTables.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/CalcTables.o: ../src/Scheduler.h ../src/SolveBoard.h ../src/PBN.h -../src/DealerPar.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/DealerPar.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/DealerPar.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/DealerPar.o: ../src/Scheduler.h -../src/Init.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Init.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Init.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Init.o: ../src/Scheduler.h ../src/threadmem.h ../src/Init.h -../src/Init.o: ../src/ABsearch.h -../src/LaterTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/LaterTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/LaterTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/LaterTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/LaterTricks.o: ../src/LaterTricks.h -../src/Moves.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Moves.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Moves.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Moves.o: ../src/Scheduler.h ../src/ABsearch.h -../src/Par.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Par.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Par.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Par.o: ../src/Scheduler.h -../src/PlayAnalyser.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PlayAnalyser.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PlayAnalyser.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PlayAnalyser.o: ../src/Scheduler.h ../src/threadmem.h -../src/PlayAnalyser.o: ../src/SolverIF.h ../src/PBN.h -../src/PBN.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/PBN.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/PBN.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/PBN.o: ../src/Scheduler.h ../src/PBN.h -../src/QuickTricks.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/QuickTricks.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/QuickTricks.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/QuickTricks.o: ../src/Scheduler.h ../src/threadmem.h -../src/QuickTricks.o: ../src/QuickTricks.h -../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../src/debug.h -../src/Scheduler.o: ../include/portab.h ../src/TransTable.h ../include/dll.h -../src/Scheduler.o: ../src/Timer.h ../src/ABstats.h ../src/Moves.h -../src/Scheduler.o: ../src/Stats.h -../src/SolveBoard.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolveBoard.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolveBoard.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolveBoard.o: ../src/Scheduler.h ../src/threadmem.h ../src/SolverIF.h -../src/SolveBoard.o: ../src/SolveBoard.h ../src/PBN.h -../src/SolverIF.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/SolverIF.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/SolverIF.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/SolverIF.o: ../src/Scheduler.h ../src/Init.h ../src/threadmem.h -../src/SolverIF.o: ../src/ABsearch.h ../src/SolverIF.h -../src/Stats.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Stats.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Stats.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Stats.o: ../src/Scheduler.h -../src/Timer.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/Timer.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/Timer.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/Timer.o: ../src/Scheduler.h -../src/TransTable.o: ../src/dds.h ../src/debug.h ../include/portab.h -../src/TransTable.o: ../src/TransTable.h ../include/dll.h ../src/Timer.h -../src/TransTable.o: ../src/ABstats.h ../src/Moves.h ../src/Stats.h -../src/TransTable.o: ../src/Scheduler.h -testcommon.o: ../include/dll.h ../include/portab.h testStats.h dtest.h -testStats.o: ../include/portab.h testStats.h -itest.o: ../include/dll.h testcommon.h -dtest.o: ../include/dll.h testcommon.h diff --git a/test/Makefiles/dds_sources.txt b/test/Makefiles/dds_sources.txt new file mode 100644 index 00000000..51c4b447 --- /dev/null +++ b/test/Makefiles/dds_sources.txt @@ -0,0 +1,27 @@ +DDS_SOURCE_FILES = \ + ../src/dds.cpp \ + ../src/dump.cpp \ + ../src/ABsearch.cpp \ + ../src/ABstats.cpp \ + ../src/CalcTables.cpp \ + ../src/DealerPar.cpp \ + ../src/File.cpp \ + ../src/Init.cpp \ + ../src/LaterTricks.cpp \ + ../src/Memory.cpp \ + ../src/Moves.cpp \ + ../src/Par.cpp \ + ../src/PlayAnalyser.cpp \ + ../src/PBN.cpp \ + ../src/QuickTricks.cpp \ + ../src/Scheduler.cpp \ + ../src/SolveBoard.cpp \ + ../src/SolverIF.cpp \ + ../src/System.cpp \ + ../src/Timer.cpp \ + ../src/TimerGroup.cpp \ + ../src/TimerList.cpp \ + ../src/TimeStat.cpp \ + ../src/TimeStatList.cpp \ + ../src/TransTableS.cpp \ + ../src/TransTableL.cpp diff --git a/test/Makefiles/depends_o.txt b/test/Makefiles/depends_o.txt new file mode 100644 index 00000000..06db08a2 --- /dev/null +++ b/test/Makefiles/depends_o.txt @@ -0,0 +1,96 @@ +../src/dds.o: ../include/dll.h ../src/Init.h ../src/dds.h ../include/portab.h +../src/dds.o: ../src/Memory.h ../src/TransTable.h ../src/TransTableS.h +../src/dds.o: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/dds.o: ../src/debug.h +../src/dump.o: ../src/dump.h ../src/dds.h ../include/portab.h +../src/dump.o: ../include/dll.h ../src/Moves.h ../src/Memory.h +../src/dump.o: ../src/TransTable.h ../src/TransTableS.h ../src/TransTableL.h +../src/dump.o: ../src/File.h ../src/debug.h +../src/ABsearch.o: ../src/TransTable.h ../src/dds.h ../include/portab.h +../src/ABsearch.o: ../include/dll.h ../src/Moves.h ../src/QuickTricks.h +../src/ABsearch.o: ../src/Memory.h ../src/TransTableS.h ../src/TransTableL.h +../src/ABsearch.o: ../src/File.h ../src/debug.h ../src/LaterTricks.h +../src/ABsearch.o: ../src/ABsearch.h ../src/ABstats.h ../src/TimerList.h +../src/ABsearch.o: ../src/TimerGroup.h ../src/Timer.h ../src/dump.h +../src/ABstats.o: ../src/ABstats.h ../src/debug.h +../src/CalcTables.o: ../src/CalcTables.h ../src/dds.h ../include/portab.h +../src/CalcTables.o: ../include/dll.h ../src/SolverIF.h ../src/Memory.h +../src/CalcTables.o: ../src/TransTable.h ../src/TransTableS.h +../src/CalcTables.o: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/CalcTables.o: ../src/debug.h ../src/SolveBoard.h ../src/System.h +../src/CalcTables.o: ../src/Scheduler.h ../src/TimeStatList.h +../src/CalcTables.o: ../src/TimeStat.h ../src/Timer.h ../src/PBN.h +../src/DealerPar.o: ../src/dds.h ../include/portab.h ../include/dll.h +../src/File.o: ../src/File.h +../src/Init.o: ../src/Init.h ../src/dds.h ../include/portab.h +../src/Init.o: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/Init.o: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/Init.o: ../src/File.h ../src/debug.h ../src/System.h +../src/Init.o: ../src/Scheduler.h ../src/TimeStatList.h ../src/TimeStat.h +../src/Init.o: ../src/Timer.h +../src/LaterTricks.o: ../src/LaterTricks.h ../src/dds.h ../include/portab.h +../src/LaterTricks.o: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/LaterTricks.o: ../src/TransTableS.h ../src/TransTableL.h +../src/LaterTricks.o: ../src/Moves.h ../src/File.h ../src/debug.h +../src/Memory.o: ../src/Memory.h ../src/TransTable.h ../src/dds.h +../src/Memory.o: ../include/portab.h ../include/dll.h ../src/TransTableS.h +../src/Memory.o: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/Memory.o: ../src/debug.h +../src/Moves.o: ../src/Moves.h ../src/dds.h ../include/portab.h +../src/Moves.o: ../include/dll.h ../src/debug.h +../src/Par.o: ../src/dds.h ../include/portab.h ../include/dll.h ../src/PBN.h +../src/PlayAnalyser.o: ../src/PlayAnalyser.h ../src/dds.h ../include/portab.h +../src/PlayAnalyser.o: ../include/dll.h ../src/SolverIF.h ../src/Memory.h +../src/PlayAnalyser.o: ../src/TransTable.h ../src/TransTableS.h +../src/PlayAnalyser.o: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/PlayAnalyser.o: ../src/debug.h ../src/System.h ../src/Scheduler.h +../src/PlayAnalyser.o: ../src/TimeStatList.h ../src/TimeStat.h ../src/Timer.h +../src/PlayAnalyser.o: ../src/PBN.h +../src/PBN.o: ../src/dds.h ../include/portab.h ../include/dll.h ../src/PBN.h +../src/QuickTricks.o: ../src/QuickTricks.h ../src/dds.h ../include/portab.h +../src/QuickTricks.o: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/QuickTricks.o: ../src/TransTableS.h ../src/TransTableL.h +../src/QuickTricks.o: ../src/Moves.h ../src/File.h ../src/debug.h +../src/Scheduler.o: ../src/Scheduler.h ../src/dds.h ../include/portab.h +../src/Scheduler.o: ../include/dll.h ../src/TimeStatList.h ../src/TimeStat.h +../src/Scheduler.o: ../src/Timer.h +../src/SolveBoard.o: ../src/SolverIF.h ../src/dds.h ../include/portab.h +../src/SolveBoard.o: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/SolveBoard.o: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/SolveBoard.o: ../src/File.h ../src/debug.h ../src/SolveBoard.h +../src/SolveBoard.o: ../src/System.h ../src/Scheduler.h ../src/TimeStatList.h +../src/SolveBoard.o: ../src/TimeStat.h ../src/Timer.h ../src/PBN.h +../src/SolverIF.o: ../src/SolverIF.h ../src/dds.h ../include/portab.h +../src/SolverIF.o: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/SolverIF.o: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/SolverIF.o: ../src/File.h ../src/debug.h ../src/Init.h +../src/SolverIF.o: ../src/ABsearch.h ../src/TimerList.h ../src/TimerGroup.h +../src/SolverIF.o: ../src/Timer.h ../src/System.h ../src/Scheduler.h +../src/SolverIF.o: ../src/TimeStatList.h ../src/TimeStat.h ../src/dump.h +../src/System.o: ../src/SolveBoard.h ../src/dds.h ../include/portab.h +../src/System.o: ../include/dll.h ../src/CalcTables.h ../src/PlayAnalyser.h +../src/System.o: ../src/parallel.h ../src/System.h ../src/Memory.h +../src/System.o: ../src/TransTable.h ../src/TransTableS.h +../src/System.o: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/System.o: ../src/debug.h ../src/Scheduler.h ../src/TimeStatList.h +../src/System.o: ../src/TimeStat.h ../src/Timer.h +../src/Timer.o: ../src/Timer.h +../src/TimerGroup.o: ../src/TimerGroup.h ../src/Timer.h +../src/TimerList.o: ../src/TimerList.h ../src/TimerGroup.h ../src/Timer.h +../src/TimerList.o: ../src/debug.h +../src/TimeStat.o: ../src/TimeStat.h +../src/TimeStatList.o: ../src/TimeStatList.h ../src/TimeStat.h +../src/TransTableS.o: ../src/TransTableS.h ../src/TransTable.h ../src/dds.h +../src/TransTableS.o: ../include/portab.h ../include/dll.h ../src/debug.h +../src/TransTableL.o: ../src/TransTableL.h ../include/dll.h ../src/dds.h +../src/TransTableL.o: ../include/portab.h ../src/TransTable.h ../src/debug.h +args.o: args.h cst.h +compare.o: compare.h ../include/dll.h +loop.o: loop.h ../include/dll.h TestTimer.h compare.h print.h +parse.o: ../include/portab.h parse.h ../include/dll.h +print.o: print.h ../include/dll.h cst.h +testcommon.o: ../include/dll.h ../include/portab.h testcommon.h TestTimer.h +testcommon.o: parse.h loop.h compare.h print.h cst.h +TestTimer.o: TestTimer.h +itest.o: ../include/dll.h testcommon.h args.h cst.h +dtest.o: ../include/dll.h testcommon.h args.h cst.h diff --git a/test/Makefiles/depends_obj.txt b/test/Makefiles/depends_obj.txt new file mode 100644 index 00000000..6b696a68 --- /dev/null +++ b/test/Makefiles/depends_obj.txt @@ -0,0 +1,102 @@ +../src/dds.obj: ../include/dll.h ../src/Init.h ../src/dds.h +../src/dds.obj: ../include/portab.h ../src/Memory.h ../src/TransTable.h +../src/dds.obj: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/dds.obj: ../src/File.h ../src/debug.h +../src/dump.obj: ../src/dump.h ../src/dds.h ../include/portab.h +../src/dump.obj: ../include/dll.h ../src/Moves.h ../src/Memory.h +../src/dump.obj: ../src/TransTable.h ../src/TransTableS.h +../src/dump.obj: ../src/TransTableL.h ../src/File.h ../src/debug.h +../src/ABsearch.obj: ../src/TransTable.h ../src/dds.h ../include/portab.h +../src/ABsearch.obj: ../include/dll.h ../src/Moves.h ../src/QuickTricks.h +../src/ABsearch.obj: ../src/Memory.h ../src/TransTableS.h +../src/ABsearch.obj: ../src/TransTableL.h ../src/File.h ../src/debug.h +../src/ABsearch.obj: ../src/LaterTricks.h ../src/ABsearch.h ../src/ABstats.h +../src/ABsearch.obj: ../src/TimerList.h ../src/TimerGroup.h ../src/Timer.h +../src/ABsearch.obj: ../src/dump.h +../src/ABstats.obj: ../src/ABstats.h ../src/debug.h +../src/CalcTables.obj: ../src/CalcTables.h ../src/dds.h ../include/portab.h +../src/CalcTables.obj: ../include/dll.h ../src/SolverIF.h ../src/Memory.h +../src/CalcTables.obj: ../src/TransTable.h ../src/TransTableS.h +../src/CalcTables.obj: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/CalcTables.obj: ../src/debug.h ../src/SolveBoard.h ../src/System.h +../src/CalcTables.obj: ../src/Scheduler.h ../src/TimeStatList.h +../src/CalcTables.obj: ../src/TimeStat.h ../src/Timer.h ../src/PBN.h +../src/DealerPar.obj: ../src/dds.h ../include/portab.h ../include/dll.h +../src/File.obj: ../src/File.h +../src/Init.obj: ../src/Init.h ../src/dds.h ../include/portab.h +../src/Init.obj: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/Init.obj: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/Init.obj: ../src/File.h ../src/debug.h ../src/System.h +../src/Init.obj: ../src/Scheduler.h ../src/TimeStatList.h ../src/TimeStat.h +../src/Init.obj: ../src/Timer.h +../src/LaterTricks.obj: ../src/LaterTricks.h ../src/dds.h ../include/portab.h +../src/LaterTricks.obj: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/LaterTricks.obj: ../src/TransTableS.h ../src/TransTableL.h +../src/LaterTricks.obj: ../src/Moves.h ../src/File.h ../src/debug.h +../src/Memory.obj: ../src/Memory.h ../src/TransTable.h ../src/dds.h +../src/Memory.obj: ../include/portab.h ../include/dll.h ../src/TransTableS.h +../src/Memory.obj: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/Memory.obj: ../src/debug.h +../src/Moves.obj: ../src/Moves.h ../src/dds.h ../include/portab.h +../src/Moves.obj: ../include/dll.h ../src/debug.h +../src/Par.obj: ../src/dds.h ../include/portab.h ../include/dll.h +../src/Par.obj: ../src/PBN.h +../src/PlayAnalyser.obj: ../src/PlayAnalyser.h ../src/dds.h +../src/PlayAnalyser.obj: ../include/portab.h ../include/dll.h +../src/PlayAnalyser.obj: ../src/SolverIF.h ../src/Memory.h +../src/PlayAnalyser.obj: ../src/TransTable.h ../src/TransTableS.h +../src/PlayAnalyser.obj: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/PlayAnalyser.obj: ../src/debug.h ../src/System.h ../src/Scheduler.h +../src/PlayAnalyser.obj: ../src/TimeStatList.h ../src/TimeStat.h +../src/PlayAnalyser.obj: ../src/Timer.h ../src/PBN.h +../src/PBN.obj: ../src/dds.h ../include/portab.h ../include/dll.h +../src/PBN.obj: ../src/PBN.h +../src/QuickTricks.obj: ../src/QuickTricks.h ../src/dds.h ../include/portab.h +../src/QuickTricks.obj: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/QuickTricks.obj: ../src/TransTableS.h ../src/TransTableL.h +../src/QuickTricks.obj: ../src/Moves.h ../src/File.h ../src/debug.h +../src/Scheduler.obj: ../src/Scheduler.h ../src/dds.h ../include/portab.h +../src/Scheduler.obj: ../include/dll.h ../src/TimeStatList.h +../src/Scheduler.obj: ../src/TimeStat.h ../src/Timer.h +../src/SolveBoard.obj: ../src/SolverIF.h ../src/dds.h ../include/portab.h +../src/SolveBoard.obj: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/SolveBoard.obj: ../src/TransTableS.h ../src/TransTableL.h +../src/SolveBoard.obj: ../src/Moves.h ../src/File.h ../src/debug.h +../src/SolveBoard.obj: ../src/SolveBoard.h ../src/System.h ../src/Scheduler.h +../src/SolveBoard.obj: ../src/TimeStatList.h ../src/TimeStat.h ../src/Timer.h +../src/SolveBoard.obj: ../src/PBN.h +../src/SolverIF.obj: ../src/SolverIF.h ../src/dds.h ../include/portab.h +../src/SolverIF.obj: ../include/dll.h ../src/Memory.h ../src/TransTable.h +../src/SolverIF.obj: ../src/TransTableS.h ../src/TransTableL.h ../src/Moves.h +../src/SolverIF.obj: ../src/File.h ../src/debug.h ../src/Init.h +../src/SolverIF.obj: ../src/ABsearch.h ../src/TimerList.h ../src/TimerGroup.h +../src/SolverIF.obj: ../src/Timer.h ../src/System.h ../src/Scheduler.h +../src/SolverIF.obj: ../src/TimeStatList.h ../src/TimeStat.h ../src/dump.h +../src/System.obj: ../src/SolveBoard.h ../src/dds.h ../include/portab.h +../src/System.obj: ../include/dll.h ../src/CalcTables.h ../src/PlayAnalyser.h +../src/System.obj: ../src/parallel.h ../src/System.h ../src/Memory.h +../src/System.obj: ../src/TransTable.h ../src/TransTableS.h +../src/System.obj: ../src/TransTableL.h ../src/Moves.h ../src/File.h +../src/System.obj: ../src/debug.h ../src/Scheduler.h ../src/TimeStatList.h +../src/System.obj: ../src/TimeStat.h ../src/Timer.h +../src/Timer.obj: ../src/Timer.h +../src/TimerGroup.obj: ../src/TimerGroup.h ../src/Timer.h +../src/TimerList.obj: ../src/TimerList.h ../src/TimerGroup.h ../src/Timer.h +../src/TimerList.obj: ../src/debug.h +../src/TimeStat.obj: ../src/TimeStat.h +../src/TimeStatList.obj: ../src/TimeStatList.h ../src/TimeStat.h +../src/TransTableS.obj: ../src/TransTableS.h ../src/TransTable.h ../src/dds.h +../src/TransTableS.obj: ../include/portab.h ../include/dll.h ../src/debug.h +../src/TransTableL.obj: ../src/TransTableL.h ../include/dll.h ../src/dds.h +../src/TransTableL.obj: ../include/portab.h ../src/TransTable.h +../src/TransTableL.obj: ../src/debug.h +args.obj: args.h cst.h +compare.obj: compare.h ../include/dll.h +loop.obj: loop.h ../include/dll.h TestTimer.h compare.h print.h +parse.obj: ../include/portab.h parse.h ../include/dll.h +print.obj: print.h ../include/dll.h cst.h +testcommon.obj: ../include/dll.h ../include/portab.h testcommon.h TestTimer.h +testcommon.obj: parse.h loop.h compare.h print.h cst.h +TestTimer.obj: TestTimer.h +itest.obj: ../include/dll.h testcommon.h args.h cst.h +dtest.obj: ../include/dll.h testcommon.h args.h cst.h diff --git a/test/Makefiles/own_sources.txt b/test/Makefiles/own_sources.txt new file mode 100644 index 00000000..5b9e6072 --- /dev/null +++ b/test/Makefiles/own_sources.txt @@ -0,0 +1,8 @@ +DTEST_SOURCE_FILES = \ + args.cpp \ + compare.cpp \ + loop.cpp \ + parse.cpp \ + print.cpp \ + testcommon.cpp \ + TestTimer.cpp diff --git a/test/TestTimer.cpp b/test/TestTimer.cpp new file mode 100644 index 00000000..210cc187 --- /dev/null +++ b/test/TestTimer.cpp @@ -0,0 +1,163 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include + +#include "TestTimer.h" + +using std::chrono::duration_cast; +using std::chrono::milliseconds; + + +TestTimer::TestTimer() +{ + TestTimer::reset(); +} + + +TestTimer::~TestTimer() +{ +} + + +void TestTimer::reset() +{ + name = ""; + count = 0; + userCum = 0; + userCumOld = 0; + sysCum = 0; +} + + +void TestTimer::setname(const string& s) +{ + name = s; +} + + +void TestTimer::start(const int number) +{ + count += number; + user0 = Clock::now(); + sys0 = clock(); +} + + +void TestTimer::end() +{ + time_point user1 = Clock::now(); + clock_t sys1 = clock(); + + chrono::duration d = user1 - user0; + int tuser = static_cast(1000. * d.count()); + + userCum += tuser; + sysCum += static_cast((1000 * (sys1 - sys0)) / + static_cast(CLOCKS_PER_SEC)); +} + + +void TestTimer::printRunning( + const int reached, + const int divisor) +{ + if (count == 0) + return; + + cout << setw(8) << reached << " (" << + setw(6) << setprecision(1) << right << fixed << + 100. * reached / + static_cast(divisor) << "%)" << + setw(15) << right << fixed << setprecision(0) << + (userCum - userCumOld) / 1000. << endl; + + userCumOld = userCum; +} + + +void TestTimer::printBasic() const +{ + if (count == 0) + return; + + if (name != "") + cout << setw(19) << left << "Timer name" << ": " << name << "\n"; + + cout << setw(19) << left << "Number of calls" << ": " << count << "\n"; + + if (userCum == 0) + cout << setw(19) << left << "User time" << ": " << "zero" << "\n"; + else + { + cout << setw(19) << left << "User time/ticks" << ": " << + userCum << "\n"; + cout << setw(19) << left << "User per call" << ": " << + setprecision(2) << userCum / static_cast(count) << "\n"; + } + + if (sysCum == 0) + cout << setw(19) << left << "Sys time" << ": " << "zero" << "\n"; + else + { + cout << setw(19) << left << "Sys time/ticks" << ": " << + sysCum << "\n"; + cout << setw(19) << left << "Sys per call" << ": " << + setprecision(2) << sysCum / static_cast(count) << "\n"; + cout << setw(19) << left << "Ratio" << ": " << + setprecision(2) << sysCum / static_cast(userCum); + } + cout << endl; +} + + +void TestTimer::printHands() const +{ + if (name != "") + cout << setw(21) << left << "Timer name" << + setw(12) << right << name << "\n"; + + cout << setw(21) << left << "Number of hands" << + setw(12) << right << count << "\n"; + + if (count == 0) + return; + + if (userCum == 0) + cout << setw(21) << left << "User time (ms)" << + setw(12) << right << "zero" << "\n"; + else + { + cout << setw(21) << left << "User time (ms)" << + setw(12) << right << fixed << + setprecision(0) << userCum / 1000. << "\n"; + cout << setw(21) << left << "Avg user time (ms)" << + setw(12) << right << fixed << setprecision(2) << userCum / + static_cast(1000. * count) << "\n"; + } + + if (sysCum == 0) + cout << setw(21) << left << "Sys time" << + setw(12) << right << "zero" << "\n"; + else + { + cout << setw(21) << left << "Sys time (ms)" << + setw(12) << right << fixed << setprecision(0) << sysCum << "\n"; + cout << setw(21) << left << "Avg sys time (ms)" << + setw(12) << right << fixed << setprecision(2) << sysCum / + static_cast(count) << "\n"; + cout << setw(21) << left << "Ratio" << + setw(12) << right << fixed << setprecision(2) << + 1000. * sysCum / static_cast(userCum); + } + cout << endl; +} + diff --git a/test/TestTimer.h b/test/TestTimer.h new file mode 100644 index 00000000..7dd3add8 --- /dev/null +++ b/test/TestTimer.h @@ -0,0 +1,53 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DTEST_TESTTIMER_H +#define DTEST_TESTTIMER_H + +#include +#include + +using Clock = std::chrono::steady_clock; +using std::chrono::time_point; + +using namespace std; + + +class TestTimer +{ + private: + string name; + long count; + long userCum; + long userCumOld; + long sysCum; + + time_point user0; + clock_t sys0; + + public: + + TestTimer(); + ~TestTimer(); + + void reset(); + + void setname(const string& s); + + void start(const int number = 1); + void end(); + + void printRunning( + const int reached, + const int number); + void printBasic() const; + void printHands() const; +}; + +#endif diff --git a/test/args.cpp b/test/args.cpp new file mode 100644 index 00000000..5769cc14 --- /dev/null +++ b/test/args.cpp @@ -0,0 +1,332 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +// These functions parse the command line for options. + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "args.h" +#include "cst.h" + +using namespace std; + + +extern OptionsType options; + +struct optEntry +{ + string shortName; + string longName; + unsigned numArgs; +}; + +#define DTEST_NUM_OPTIONS 5 + +const optEntry optList[DTEST_NUM_OPTIONS] = +{ + {"f", "file", 1}, + {"s", "solver", 1}, + {"t", "threading", 1}, + {"n", "numthr", 1}, + {"m", "memory", 1} +}; + +const vector solverList = +{ + "solve", + "calc", + "play", + "par", + "dealerpar" +}; + +const vector threadingList = +{ + "none", + "WinAPI", + "OpenMP", + "GCD", + "Boost", + "STL", + "TBB", + "STLIMPL", + "PPLIMPL", + "default" +}; + +string shortOptsAll, shortOptsWithArg; + +int GetNextArgToken( + int argc, + char * argv[]); + +void SetDefaults(); + +bool ParseRound(); + + +void Usage( + const char base[]) +{ + string basename(base); + const size_t l = basename.find_last_of("\\/"); + if (l != string::npos) + basename.erase(0, l+1); + + cout << + "Usage: " << basename << " [options]\n\n" << + "-f, --file s Input file, or the number n;\n" << + " '100' means ../hands/list100.txt).\n" << + " (Default: input.txt)\n" << + "\n" << + "-s, --solver One of: solve, calc, play, par, dealerpar.\n" << + " (Default: solve)\n" << + "\n" << + "-t, --threading t Currently one of (case-insensitive):\n" << + " default, none, winapi, openmp, gcd, boost,\n" << + " stl, tbb, stlimpl, pplimpl.\n" << + " (Default: default meaning that DDS decides)\n" << + "\n" << + "-n, --numthr n Maximum number of threads.\n" << + " (Default: 0 meaning that DDS decides)\n" << + "\n" << + "-m, --memory n Total DDS memory size in MB.\n" << + " (Default: 0 meaning that DDS decides)\n" << + "\n" << + endl; +} + + +int nextToken = 1; +char * optarg; + +int GetNextArgToken( + int argc, + char * argv[]) +{ + // 0 means done, -1 means error. + + if (nextToken >= argc) + return 0; + + string str(argv[nextToken]); + if (str[0] != '-' || str.size() == 1) + return -1; + + if (str[1] == '-') + { + if (str.size() == 2) + return -1; + str.erase(0, 2); + } + else if (str.size() == 2) + str.erase(0, 1); + else + return -1; + + for (unsigned i = 0; i < DTEST_NUM_OPTIONS; i++) + { + if (str == optList[i].shortName || str == optList[i].longName) + { + if (optList[i].numArgs == 1) + { + if (nextToken+1 >= argc) + return -1; + + optarg = argv[nextToken+1]; + nextToken += 2; + } + else + nextToken++; + + return str[0]; + } + } + + return -1; +} + + +void SetDefaults() +{ + options.fname = "input.txt"; + options.solver = DTEST_SOLVER_SOLVE; + options.threading = DTEST_THREADING_DEFAULT; + options.numThreads = 0; + options.memoryMB = 0; +} + + +void PrintOptions() +{ + cout << left; + cout << setw(12) << "file" << + setw(12) << options.fname << "\n"; + cout << setw(12) << "solver" << setw(12) << + solverList[options.solver] << "\n"; + cout << setw(12) << "threading" << setw(12) << + threadingList[options.threading] << "\n"; + cout << setw(12) << "threads" << setw(12) << + options.numThreads << "\n"; + cout << setw(12) << "memory" << setw(12) << + options.memoryMB << " MB\n"; + cout << "\n" << right; +} + + +void ReadArgs( + int argc, + char * argv[]) +{ + for (unsigned i = 0; i < DTEST_NUM_OPTIONS; i++) + { + shortOptsAll += optList[i].shortName; + if (optList[i].numArgs) + shortOptsWithArg += optList[i].shortName; + } + + if (argc == 1) + { + Usage(argv[0]); + exit(0); + } + + SetDefaults(); + + int c, m = 0; + bool errFlag = false, matchFlag; + string stmp; + char * ctmp; + struct stat buffer; + + while ((c = GetNextArgToken(argc, argv)) > 0) + { + switch(c) + { + case 'f': + if (stat(optarg, &buffer) == 0) + { + options.fname = string(optarg); + break; + } + + stmp = "../hands/list" + string(optarg) + ".txt"; + if (stat(stmp.c_str(), &buffer) == 0) + { + options.fname = stmp; + break; + } + + cout << "Input file '" << optarg << "' not found\n"; + cout << "Input file '" << stmp << "' not found\n"; + nextToken -= 2; + errFlag = true; + break; + + case 's': + matchFlag = false; + stmp = optarg; + transform(stmp.begin(), stmp.end(), stmp.begin(), ::tolower); + + for (unsigned i = 0; i < DTEST_SOLVER_SIZE && ! matchFlag; i++) + { + string s = solverList[i]; + transform(s.begin(), s.end(), s.begin(), ::tolower); + if (stmp == s) + { + m = static_cast(i); + matchFlag = true; + } + } + + if (matchFlag) + options.solver = static_cast(m); + else + { + cout << "Solver '" << optarg << "' not found\n"; + nextToken -= 2; + errFlag = true; + } + break; + + case 't': + matchFlag = false; + stmp = optarg; + transform(stmp.begin(), stmp.end(), stmp.begin(), ::tolower); + + for (unsigned i = 0; i < DTEST_THREADING_SIZE && ! matchFlag; i++) + { + string s = threadingList[i]; + transform(s.begin(), s.end(), s.begin(), ::tolower); + if (stmp == s) + { + m = static_cast(i); + matchFlag = true; + } + } + + if (matchFlag) + options.threading = static_cast(m); + else + { + cout << "Threading '" << optarg << "' not found\n"; + nextToken -= 2; + errFlag = true; + } + break; + + case 'n': + m = static_cast(strtol(optarg, &ctmp, 0)); + if (m < 0) + { + cout << "Number of threads must be >= 0\n\n"; + nextToken -= 2; + errFlag = true; + } + options.numThreads = m; + break; + + case 'm': + m = static_cast(strtol(optarg, &ctmp, 0)); + if (m < 0) + { + cout << "Memory in MB must be >= 0\n\n"; + nextToken -= 2; + errFlag = true; + } + options.memoryMB = m; + break; + + default: + cout << "Unknown option\n"; + errFlag = true; + break; + } + if (errFlag) + break; + } + + if (errFlag || c == -1) + { + cout << "Error while parsing option '" << argv[nextToken] << "'\n"; + cout << "Invoke the program without arguments for help" << endl; + exit(0); + } +} + diff --git a/test/args.h b/test/args.h new file mode 100644 index 00000000..46006d1c --- /dev/null +++ b/test/args.h @@ -0,0 +1,24 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#ifndef DTEST_ARGS_H +#define DTEST_ARGS_H + +void Usage( + const char base[]); + +void PrintOptions(); + +void ReadArgs( + int argc, + char * argv[]); + +#endif + diff --git a/test/compare.cpp b/test/compare.cpp new file mode 100644 index 00000000..e5e1d684 --- /dev/null +++ b/test/compare.cpp @@ -0,0 +1,125 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include + +#include "compare.h" + +using namespace std; + + +bool compare_PBN( + const dealPBN& dl1, + const dealPBN& dl2) +{ + if (dl1.trump != dl2.trump) + return false; + if (dl1.first != dl2.first) + return false; + if (strcmp(dl1.remainCards, dl2.remainCards)) + return false; + + return true; +} + + +bool compare_FUT( + const futureTricks& fut1, + const futureTricks& fut2) +{ + if (fut1.cards != fut2.cards) + return false; + + for (int i = 0; i < fut1.cards; i++) + { + if (fut1.suit[i] != fut2.suit[i]) + return false; + if (fut1.rank[i] != fut2.rank[i]) + return false; + if (fut1.equals[i] != fut2.equals[i]) + return false; + if (fut1.score[i] != fut2.score[i]) + return false; + } + + return true; +} + + +bool compare_TABLE( + const ddTableResults& table1, + const ddTableResults& table2) +{ + for (int suit = 0; suit < DDS_SUITS; suit++) + { + for (int pl = 0; pl < DDS_HANDS; pl++) + if (table1.resTable[suit][pl] != table2.resTable[suit][pl]) + return false; + } + + return true; +} + + +bool compare_PAR( + const parResults& par1, + const parResults& par2) +{ + if (strcmp(par1.parScore[0], par2.parScore[0])) + return false; + if (strcmp(par1.parScore[1], par2.parScore[1])) + return false; + if (strcmp(par1.parContractsString[0], par2.parContractsString[0])) + return false; + if (strcmp(par1.parContractsString[1], par2.parContractsString[1])) + return false; + + return true; +} + + +bool compare_DEALERPAR( + const parResultsDealer& par1, + const parResultsDealer& par2) +{ + if (par1.score != par2.score) + return false; + + for (int i = 0; i < par1.number; i++) + if (strcmp(par1.contracts[i], par2.contracts[i])) + return false; + + return true; +} + + +bool compare_TRACE( + const solvedPlay& trace1, + const solvedPlay& trace2) +{ + // In a buglet, Trace returned trace1 == -3 if there is + // no input at all (trace2 is then 0). + if (trace1.number != trace2.number && trace2.number > 0) + return false; + + // Once that was fixed, the input file had length 0, not 1. + if (trace1.number == 1 && trace2.number == 0) + return true; + + for (int i = 0; i < trace1.number; i++) + { + if (trace1.tricks[i] != trace2.tricks[i]) + return false; + } + + return true; +} + diff --git a/test/compare.h b/test/compare.h new file mode 100644 index 00000000..7e8bc3dc --- /dev/null +++ b/test/compare.h @@ -0,0 +1,41 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DTEST_COMPARE_H +#define DTEST_COMPARE_H + +#include "../include/dll.h" + + +bool compare_PBN( + const dealPBN& dl1, + const dealPBN& dl2); + +bool compare_FUT( + const futureTricks& fut1, + const futureTricks& fut2); + +bool compare_TABLE( + const ddTableResults& table1, + const ddTableResults& table2); + +bool compare_PAR( + const parResults& par1, + const parResults& par2); + +bool compare_DEALERPAR( + const parResultsDealer& par1, + const parResultsDealer& par2); + +bool compare_TRACE( + const solvedPlay& trace1, + const solvedPlay& trace2); + +#endif + diff --git a/test/cst.h b/test/cst.h new file mode 100644 index 00000000..5c0b8e43 --- /dev/null +++ b/test/cst.h @@ -0,0 +1,53 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DTEST_CST_H +#define DTEST_CST_H + +#include + +using namespace std; + + +enum Solver +{ + DTEST_SOLVER_SOLVE = 0, + DTEST_SOLVER_CALC = 1, + DTEST_SOLVER_PLAY = 2, + DTEST_SOLVER_PAR = 3, + DTEST_SOLVER_DEALERPAR = 4, + DTEST_SOLVER_SIZE = 5 +}; + +enum Threading +{ + DTEST_THREADING_NONE = 0, + DTEST_THREADING_WINAPI = 1, + DTEST_THREADING_OPENMP = 2, + DTEST_THREADING_GCD = 3, + DTEST_THREADING_BOOST = 4, + DTEST_THREADING_STL = 5, + DTEST_THREADING_TBB = 6, + DTEST_THREADING_STLIMPL = 7, + DTEST_THREADING_PPLIMPL = 8, + DTEST_THREADING_DEFAULT = 9, + DTEST_THREADING_SIZE = 10 +}; + +struct OptionsType +{ + string fname; + Solver solver; + Threading threading; + int numThreads; + int memoryMB; +}; + +#endif + diff --git a/test/dtest.cpp b/test/dtest.cpp index d5afac30..44e23b49 100644 --- a/test/dtest.cpp +++ b/test/dtest.cpp @@ -2,30 +2,36 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include -#include +#include + #include "../include/dll.h" #include "testcommon.h" +#include "args.h" +#include "cst.h" + +using namespace std; + +OptionsType options; + int main(int argc, char * argv[]) { - int ncores = 0; - if (argc == 4) - ncores = atoi(argv[3]); + ReadArgs(argc, argv); + + if (options.threading != DTEST_THREADING_DEFAULT) + SetThreading(static_cast(options.threading)); - SetMaxThreads(ncores); + SetResources(options.memoryMB, options.numThreads); DDSInfo info; GetDDSInfo(&info); - printf("%s", info.systemString); - printf("%-12s %20s\n\n", "Version", info.versionString); - fflush(stdout); + cout << info.systemString << endl; realMain(argc, argv); diff --git a/test/dtest.h b/test/dtest.h deleted file mode 100644 index 78cfa64d..00000000 --- a/test/dtest.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - - -void print_rank_count(); -unsigned short int dbitMapRank[16]; -unsigned char dcardRank[16]; -unsigned char dcardSuit[5]; - -void main_identify(); - -void set_constants(); - -bool read_file( - char * fname, - int * number, - int ** dealer_list, - int ** vul_list, - struct dealPBN ** deal_list, - struct futureTricks ** fut_list, - struct ddTableResults ** table_list, - struct parResults ** par_list, - struct parResultsDealer ** dealerpar_list, - struct playTracePBN ** play_list, - struct solvedPlay ** trace_list); - -bool parse_NUMBER( - char * line, - int * number); - -bool parse_PBN( - char * line, - int * dealer, - int * vul, - struct dealPBN * dl); - -bool parse_FUT( - char * line, - struct futureTricks * fut); - -bool parse_TABLE( - char * line, - struct ddTableResults * table); - -bool parse_PAR( - char * line, - struct parResults * par); - -bool parse_DEALERPAR( - char * line, - struct parResultsDealer * par); - -bool parse_PLAY( - char * line, - struct playTracePBN * playp); - -bool parse_TRACE( - char * line, - struct solvedPlay * solvedp); - -bool parseable_GIB( - char line[]); - -bool parse_GIB( - char line[], - dealPBN * dl, - ddTableResults * table); - -bool compare_PBN( - struct dealPBN * dl1, - struct dealPBN * dl2); - -bool compare_FUT( - struct futureTricks * fut1, - struct futureTricks * fut2); - -bool compare_TABLE( - struct ddTableResults * table1, - struct ddTableResults * table2); - -bool compare_PAR( - struct parResults * par1, - struct parResults * par2); - -bool compare_DEALERPAR( - struct parResultsDealer * par1, - struct parResultsDealer * par2); - -bool compare_TRACE( - struct solvedPlay * trace1, - struct solvedPlay * trace2); - -bool print_PBN( - struct dealPBN * dl); - -bool print_FUT( - struct futureTricks * fut); - -void equals_to_string( - int equals, - char * res); - -bool print_TABLE( - struct ddTableResults * table); - -bool print_PAR( - struct parResults * par); - -bool print_DEALERPAR( - struct parResultsDealer * par); - -bool print_PLAY( - struct playTracePBN * play); - -bool print_TRACE( - struct solvedPlay * solvedp); - -void loop_solve( - struct boardsPBN * bop, - struct solvedBoards * solvedbdp, - struct dealPBN * deal_list, - struct futureTricks * fut_list, - int number); - -bool loop_calc( - struct ddTableDealsPBN * dealsp, - struct ddTablesRes * resp, - struct allParResults * parp, - struct dealPBN * deal_list, - struct ddTableResults * table_list, - int number); - -bool loop_par( - int * vul_list, - struct ddTableResults * table_list, - struct parResults * par_list, - int number); - -bool loop_dealerpar( - int * dealer_list, - int * vul_list, - struct ddTableResults * table_list, - struct parResultsDealer * dealerpar_list, - int number); - -bool loop_play( - struct boardsPBN * bop, - struct playTracesPBN * playsp, - struct solvedPlays * solvedplp, - struct dealPBN * deal_list, - struct playTracePBN * play_list, - struct solvedPlay * trace_list, - int number); - -void print_times( - int number); - -#ifndef _WIN32 -int timeval_diff( - timeval x, - timeval y); -#endif - -void timer_start(); - -int timer_end(); - -bool consume_int( - char * line, - int * pos, - int * res); - -bool consume_string( - char * line, - int * pos, - char * res); - -bool consume_tag( - char * line, - int * pos, - const char * tag); - -void dump_string( - const char * line); - -void set_complexity(); - -void set_weight(); diff --git a/test/itest.cpp b/test/itest.cpp index 0b5c685a..386a96a1 100644 --- a/test/itest.cpp +++ b/test/itest.cpp @@ -2,32 +2,38 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include -#include +#include +#include +#include + #include "../include/dll.h" #include "testcommon.h" +#include "args.h" +#include "cst.h" + +using namespace std; +OptionsType options; int main(int argc, char * argv[]) { - int ncores = 0; - if (argc == 4) - ncores = atoi(argv[3]); + ReadArgs(argc, argv); + + if (options.threading != DTEST_THREADING_DEFAULT) + SetThreading(static_cast(options.threading)); - SetMaxThreads(ncores); + SetResources(options.memoryMB, options.numThreads); DDSInfo info; GetDDSInfo(&info); - printf("%s", info.systemString); - printf("%-12s %20s\n\n", "Version", info.versionString); - fflush(stdout); + cout << info.systemString << endl; realMain(argc, argv); diff --git a/test/loop.cpp b/test/loop.cpp new file mode 100644 index 00000000..e94ae6cd --- /dev/null +++ b/test/loop.cpp @@ -0,0 +1,300 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include + +#include "loop.h" +#include "TestTimer.h" +#include "compare.h" +#include "print.h" + +using namespace std; + +#define BATCHTIMES + +extern TestTimer timer; + + +void loop_solve( + boardsPBN * bop, + solvedBoards * solvedbdp, + dealPBN * deal_list, + futureTricks * fut_list, + const int number, + const int stepsize) +{ +#ifdef BATCHTIMES + cout << setw(8) << left << "Hand no." << + setw(25) << right << "Time" << "\n"; +#endif + + for (int i = 0; i < number; i += stepsize) + { + int count = (i + stepsize > number ? number - i : stepsize); + + bop->noOfBoards = count; + for (int j = 0; j < count; j++) + { + bop->deals[j] = deal_list[i + j]; + bop->target[j] = -1; + bop->solutions[j] = 3; + bop->mode[j] = 1; + } + + timer.start(count); + int ret; + if ((ret = SolveAllChunks(bop, solvedbdp, 1)) != RETURN_NO_FAULT) + { + cout << "loop_solve: i " << i << ", return " << ret << "\n"; + exit(0); + } + timer.end(); + +#ifdef BATCHTIMES + timer.printRunning(i+count, number); +#endif + + for (int j = 0; j < count; j++) + { + if (compare_FUT(solvedbdp->solvedBoard[j], fut_list[i + j])) + continue; + + cout << "loop_solve: i " << i << ", j " << j << ": " << + "Difference\n\n"; + print_FUT(solvedbdp->solvedBoard[j]); + cout << "\n"; + print_FUT(fut_list[i+j]); + cout << "\n"; + } + } + +#ifdef BATCHTIMES + cout << "\n"; +#endif + +} + + +bool loop_calc( + ddTableDealsPBN * dealsp, + ddTablesRes * resp, + allParResults * parp, + dealPBN * deal_list, + ddTableResults * table_list, + const int number, + const int stepsize) +{ +#ifdef BATCHTIMES + cout << setw(8) << left << "Hand no." << + setw(25) << right << "Time" << "\n"; +#endif + + int filter[5] = {0, 0, 0, 0, 0}; + + for (int i = 0; i < number; i += stepsize) + { + int count = (i + stepsize > number ? number - i : stepsize); + dealsp->noOfTables = count; + for (int j = 0; j < count; j++) + strcpy(dealsp->deals[j].cards, deal_list[i+j].remainCards); + + timer.start(count); + int ret; + if ((ret = CalcAllTablesPBN(dealsp, -1, filter, resp, parp)) + != RETURN_NO_FAULT) + { + cout << "loop_calc: i " << i << ", return " << ret << "\n"; + exit(0); + } + timer.end(); + +#ifdef BATCHTIMES + timer.printRunning(i+count, number); +#endif + + for (int j = 0; j < count; j++) + { + if (compare_TABLE(resp->results[j], table_list[i + j])) + continue; + + cout << "loop_calc: i " << i << ", j " << j << ": " << + "Difference\n\n"; + print_TABLE(resp->results[j] ); + cout << "\n"; + print_TABLE(table_list[i + j]) ; + cout << "\n"; + } + } + +#ifdef BATCHTIMES + cout << "\n"; +#endif + + return true; +} + + + +bool loop_par( + int * vul_list, + ddTableResults * table_list, + parResults * par_list, + const int number, + const int stepsize) +{ + // This is so fast that there is no batch or multi-threaded + // version. We run it many times just to get meaningful times. + + parResults presp; + + for (int i = 0; i < number; i++) + { + for (int j = 0; j < stepsize; j++) + { + int ret; + if ((ret = Par(&table_list[i], &presp, vul_list[i])) + != RETURN_NO_FAULT) + { + cout << "loop_par: i " << i << ", j " << j << ": " << + "return " << ret << "\n"; + exit(0); + } + } + + if (compare_PAR(presp, par_list[i])) + continue; + + cout << "loop_par i " << i << ": Difference\n\n"; + print_PAR(presp); + cout << "\n"; + print_PAR(par_list[i]); + cout << "\n"; + } + + return true; +} + + +bool loop_dealerpar( + int * dealer_list, + int * vul_list, + ddTableResults * table_list, + parResultsDealer * dealerpar_list, + const int number, + const int stepsize) +{ + // This is so fast that there is no batch or multi-threaded + // version. We run it many times just to get meaningful times. + + parResultsDealer presp; + + timer.start(number); + for (int i = 0; i < number; i++) + { + for (int j = 0; j < stepsize; j++) + { + int ret; + if ((ret = DealerPar(&table_list[i], &presp, + dealer_list[i], vul_list[i])) != RETURN_NO_FAULT) + { + cout << "loop_dealerpar: i " << i << ", j " << j << ": " << + "return " << ret << "\n"; + exit(0); + } + } + + if (compare_DEALERPAR(presp, dealerpar_list[i])) + continue; + + cout << "loop_dealerpar i " << i << ": Difference\n\n"; + print_DEALERPAR(presp); + cout << "\n"; + print_DEALERPAR(dealerpar_list[i]); + cout << "\n"; + } + timer.end(); + +#ifdef BATCHTIMES + timer.printRunning(number, number); +#endif + + return true; +} + + +bool loop_play( + boardsPBN * bop, + playTracesPBN * playsp, + solvedPlays * solvedplp, + dealPBN * deal_list, + playTracePBN * play_list, + solvedPlay * trace_list, + const int number, + const int stepsize) +{ +#ifdef BATCHTIMES + cout << setw(8) << left << "Hand no." << + setw(25) << right << "Time" << "\n"; +#endif + + for (int i = 0; i < number; i += stepsize) + { + int count = (i + stepsize > number ? number - i : stepsize); + + bop->noOfBoards = count; + playsp->noOfBoards = count; + + for (int j = 0; j < count; j++) + { + bop->deals[j] = deal_list[i + j]; + bop->target[j] = 0; + bop->solutions[j] = 3; + bop->mode[j] = 1; + + playsp->plays[j] = play_list[i + j]; + } + + timer.start(count); + int ret; + if ((ret = AnalyseAllPlaysPBN(bop, playsp, solvedplp, 1)) + != RETURN_NO_FAULT) + { + printf("loop_play i %i: Return %d\n", i, ret); + cout << "loop_play: i " << i << ": " << "return " << ret << "\n"; + exit(0); + } + timer.end(); + +#ifdef BATCHTIMES + timer.printRunning(i+count, number); +#endif + + for (int j = 0; j < count; j++) + { + if (compare_TRACE(solvedplp->solved[j], trace_list[i+j])) + continue; + + printf("loop_play i %d, j %d: Difference\n", i, j); + cout << "loop_play: i " << i << ", j " << j << ": " << + "Difference\n\n"; + print_double_TRACE(solvedplp->solved[j], trace_list[i+j]); + cout << "\n"; + } + } + +#ifdef BATCHTIMES + printf("\n"); +#endif + + return true; +} + diff --git a/test/loop.h b/test/loop.h new file mode 100644 index 00000000..f69ba019 --- /dev/null +++ b/test/loop.h @@ -0,0 +1,59 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DTEST_LOOP_H +#define DTEST_LOOP_H + +#include "../include/dll.h" + + +void loop_solve( + boardsPBN * bop, + solvedBoards * solvedbdp, + dealPBN * deal_list, + futureTricks * fut_list, + const int number, + const int stepsize); + +bool loop_calc( + ddTableDealsPBN * dealsp, + ddTablesRes * resp, + allParResults * parp, + dealPBN * deal_list, + ddTableResults * table_list, + const int number, + const int stepsize); + +bool loop_par( + int * vul_list, + ddTableResults * table_list, + parResults * par_list, + const int number, + const int stepsize); + +bool loop_dealerpar( + int * dealer_list, + int * vul_list, + ddTableResults * table_list, + parResultsDealer * dealerpar_list, + const int number, + const int stepsize); + +bool loop_play( + boardsPBN * bop, + playTracesPBN * playsp, + solvedPlays * solvedplp, + dealPBN * deal_list, + playTracePBN * play_list, + solvedPlay * trace_list, + const int number, + const int stepsize); + +#endif + diff --git a/test/parse.cpp b/test/parse.cpp new file mode 100644 index 00000000..d119f9f8 --- /dev/null +++ b/test/parse.cpp @@ -0,0 +1,719 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#include +#include +#include +#include +#include +#include + +#include "../include/portab.h" +#include "parse.h" + +using namespace std; + + +bool parse_PBN( + const vector& list, + int& dealer, + int& vul, + dealPBN * dl); + +bool parse_FUT( + const vector& list, + futureTricks * fut); + +bool parse_TABLE( + const vector& list, + ddTableResults * table); + +bool parse_PAR( + const vector& list, + parResults * par); + +bool parse_DEALERPAR( + const vector& list, + parResultsDealer * par); + +bool parse_PLAY( + const vector& list, + playTracePBN * play); + +bool parse_TRACE( + const vector& list, + solvedPlay * solved); + +bool parseable_GIB(const string& line); + +bool parse_GIB( + const string& line, + dealPBN * dl, + ddTableResults * table); + +bool get_any_line( + ifstream& fin, + vector& list, + const string& tag, + const int n); + +bool get_head_element( + const string& elem, + const string& expected); + +bool get_int_element( + const string& elem, + int& res, + const string& errtext); + +bool strip_quotes( + const string& st, + char * cstr, + const string& errtag); + +bool strip_quotes( + const string& st, + int& res, + const string& errtag); + +string trimTrailing( + const string& st, + const char c); + +void splitIntoWords( + const string& text, + vector& words); + +bool str2int( + const string& text, + int& res); + + +bool read_file( + const string& fname, + int& number, + bool& GIBmode, + int ** dealer_list, + int ** vul_list, + dealPBN ** deal_list, + futureTricks ** fut_list, + ddTableResults ** table_list, + parResults ** par_list, + parResultsDealer ** dealerpar_list, + playTracePBN ** play_list, + solvedPlay ** trace_list) +{ + ifstream fin; + fin.open(fname); + + string line; + if (! getline(fin, line)) + { + cout << "First line bad: '" << line << "'" << endl; + return false; + } + + vector list; + list.clear(); + splitIntoWords(line, list); + + if (list.size() == 2 && get_head_element(list[0], "NUMBER")) + { + // Hopefully a txt-style file. + if (! str2int(list[1], number)) + { + cout << "Not a number of hands: '" << list[1] << "'" << endl; + return false; + } + else if (number <= 0 || number > 100000) + { + cout << "Suspect number of hands: " << number << endl; + return false; + } + } + else if (! parseable_GIB(line)) + { + cout << "Not a GIB-style start: '" << line << "'" << endl; + return false; + } + else + { + // Count the lines, then start over. + GIBmode = 1; + number = 1; + while (1) + { + if (! getline(fin, line)) + break; + number++; + } + fin.close(); + fin.open(fname); + } + + + // Make enough room for the hands. + + const size_t number_t = static_cast(number); + + if ((*dealer_list = static_cast + (calloc(number_t, sizeof(int)))) == NULL) + return false; + + if ((*vul_list = static_cast + (calloc(number_t, sizeof(int)))) == NULL) + return false; + + if ((*deal_list = static_cast + (calloc(number_t, sizeof(dealPBN)))) == NULL) + return false; + + if ((*fut_list = static_cast + (calloc(number_t, sizeof(futureTricks)))) == NULL) + return false; + + if ((*table_list = static_cast + (calloc(number_t, sizeof(ddTableResults)))) == NULL) + return false; + + if ((*par_list = static_cast + (calloc(number_t, sizeof(parResults)))) == NULL) + return false; + + if ((*dealerpar_list = static_cast + (calloc(number_t, sizeof(parResultsDealer)))) == NULL) + return false; + + if ((*play_list = static_cast + (calloc(number_t, sizeof(playTracePBN)))) == NULL) + return false; + + if ((*trace_list = static_cast + (calloc(number_t, sizeof(solvedPlay)))) == NULL) + return false; + + if (GIBmode) + { + for (int n = 0; n < number; n++) + { + if (! getline(fin, line)) + { + cout << "Expected GIB line " << n << endl; + return false; + } + if (! parse_GIB(line, &(*deal_list)[n], &(*table_list)[n])) + return false; + } + } + else + { + for (int n = 0; n < number; n++) + { + if (! get_any_line(fin, list, "PBN", n)) + return false; + if (! parse_PBN(list, (*dealer_list)[n], + (*vul_list)[n], &(*deal_list)[n])) + return false; + + if (! get_any_line(fin, list, "FUT", n)) + return false; + if (! parse_FUT(list, &(*fut_list)[n])) + return false; + + if (! get_any_line(fin, list, "TABLE", n)) + return false; + if (! parse_TABLE(list, &(*table_list)[n])) + return false; + + if (! get_any_line(fin, list, "PAR", n)) + return false; + if (! parse_PAR(list, &(*par_list)[n])) + return false; + + if (! get_any_line(fin, list, "DEALERPAR", n)) + return false; + if (! parse_DEALERPAR(list, &(*dealerpar_list)[n])) + return false; + + if (! get_any_line(fin, list, "PLAY", n)) + return false; + if (! parse_PLAY(list, &(*play_list)[n])) + return false; + + if (! get_any_line(fin, list, "TRACE", n)) + return false; + if (! parse_TRACE(list, &(*trace_list)[n])) + return false; + } + } + + fin.close(); + return true; +} + + +bool parse_PBN( + const vector& list, + int& dealer, + int& vul, + dealPBN * dl) +{ + if (list.size() != 9) + { + cout << "PBN list does not have 9 elements: " << list.size() << "\n"; + return false; + } + + if (! get_head_element(list[0], "PBN")) + return false; + if (! get_int_element(list[1], dealer, "PBN dealer failed")) + return false; + if (! get_int_element(list[2], vul, "PBN vul failed")) + return false; + if (! get_int_element(list[3], dl->trump, "PBN trump failed")) + return false; + if (! get_int_element(list[4], dl->first, "PBN trump failed")) + return false; + + for (int i = 0; i < 3; i++) + { + dl->currentTrickSuit[i] = 0; + dl->currentTrickRank[i] = 0; + } + + if (! strip_quotes( + list[5] + " " + list[6] + " " + list[7] + " " + list[8], + dl->remainCards, "PBN string")) + return false; + + return true; +} + + +bool parse_FUT( + const vector& list, + futureTricks * fut) +{ + if (list.size() < 2) + { + cout << "PBN list does not have 2+ elements: " << list.size() << endl; + return false; + } + + if (! get_head_element(list[0], "FUT")) + return false; + if (! get_int_element(list[1], fut->cards, "FUT cards")) + return false; + + if (static_cast(list.size()) != 4 * fut->cards + 2) + { + cout << "PBN list does not have right length: " << list.size() << endl; + return false; + } + + const int n = fut->cards; + const unsigned nu = static_cast(fut->cards); + for (unsigned c = 0; c < nu; c++) + if (! get_int_element(list[c+2], fut->suit[c], "FUT suit")) + return false; + + for (unsigned c = 0; c < nu; c++) + if (! get_int_element(list[c+nu+2], fut->rank[c], "FUT rank")) + return false; + + for (unsigned c = 0; c < nu; c++) + if (! get_int_element(list[c+2*nu+2], fut->equals[c], "FUT equals")) + return false; + + for (unsigned c = 0; c < nu; c++) + if (! get_int_element(list[c+3*nu+2], fut->score[c], "FUT score")) + return false; + + return true; +} + + +bool parse_TABLE( + const vector& list, + ddTableResults * table) +{ + if (list.size() != 21) + { + cout << "Table list does not have 21 elements: " << list.size() << endl; + return false; + } + + if (! get_head_element(list[0], "TABLE")) + return false; + + for (unsigned suit = 0; suit < DDS_STRAINS; suit++) + { + for (unsigned pl = 0; pl < DDS_HANDS; pl++) + { + if (! get_int_element(list[DDS_HANDS * suit + pl + 1], + table->resTable[suit][pl], "TABLE entry")) + return false; + } + } + + return true; +} + + +bool parse_PAR( + const vector& list, + parResults * par) +{ + if (list.size() < 9) + { + cout << "PAR list does not have 9+ elements: " << list.size() << endl; + return false; + } + + if (! get_head_element(list[0], "PAR")) + return false; + + if (! strip_quotes(list[1] + " " + list[2], par->parScore[0], + "PAR score 0")) + return false; + + if (! strip_quotes(list[3] + " " + list[4], par->parScore[1], + "PAR score 1")) + return false; + + unsigned i = 5; + string st = ""; + while (i < list.size()) + { + st += " " + list[i++]; + if (st.back() == '"') + break; + } + + if (! strip_quotes(st.substr(1), par->parContractsString[0], + "PAR contract 0")) + return false; + + st = ""; + while (i < list.size()) + { + st += " " + list[i++]; + if (st.back() == '"') + break; + } + + if (! strip_quotes(st.substr(1), par->parContractsString[1], + "PAR contract 1")) + return false; + + return true; +} + + +bool parse_DEALERPAR( + const vector& list, + parResultsDealer * par) +{ + const unsigned l = list.size(); + if (l < 3) + { + cout << "PAR2 list does not have 3+ elements: " << l << endl; + return false; + } + + if (! get_head_element(list[0], "PAR2")) + return false; + + if (! strip_quotes(list[1], par->score, "PBN string")) + return false; + + unsigned no = 0; + while (no+2 < l) + { + if (! strip_quotes(list[no+2], par->contracts[no], "PAR2 contract")) + break; + no++; + } + + par->number = static_cast(no); + return true; +} + + +bool parse_PLAY( + const vector& list, + playTracePBN * playp) +{ + if (list.size() != 3) + { + cout << "PLAY list does not have 3 elements: " << list.size() << endl; + return false; + } + + if (! get_head_element(list[0], "PLAY")) + return false; + + if (! get_int_element(list[1], playp->number, "PLAY number")) + return false; + + if (! strip_quotes(list[2], playp->cards, "PLAY string")) + return false; + + return true; +} + + +bool parse_TRACE( + const vector& list, + solvedPlay * solvedp) +{ + if (list.size() < 2) + { + cout << "TRACE list does not have 2+ elements: " << list.size() << endl; + return false; + } + + if (! get_head_element(list[0], "TRACE")) + return false; + + if (! get_int_element(list[1], solvedp->number, "TRACE number")) + return false; + + for (unsigned i = 0; i < static_cast(solvedp->number); i++) + if (! get_int_element(list[2+i], solvedp->tricks[i], "TRACE element")) + return false; + + return true; +} + + +bool parseable_GIB(const string& line) +{ + if (line.size() != 88) + return false; + + if (line.substr(67, 1) != ":") + return false; + + return true; +} + +int GIB_TO_DDS[4] = {1, 0, 3, 2}; + +bool parse_GIB( + const string& line, + dealPBN * dl, + ddTableResults * table) +{ + string st = "W:" + line.substr(0, 67); + strcpy(dl->remainCards, st.c_str()); + + int dds_strain, dds_hand; + for (int s = 0; s < DDS_STRAINS; s++) + { + dds_strain = (s == 0 ? 4 : s - 1); + for (unsigned h = 0; h < DDS_HANDS; h++) + { + dds_hand = GIB_TO_DDS[h]; + char const c = (line.substr( + 68 + 4*static_cast(s) + h, 1).c_str())[0]; + int d; + if (c >= 48 && c <= 57) // 0, 9 + d = c-48; + else if (c >= 65 && c <= 70) // A, F + d = c-55; + else + return false; + + if (dds_hand & 1) + d = 13 - d; + + table->resTable[dds_strain][dds_hand] = d; + } + } + return true; +} + + +bool get_any_line( + ifstream& fin, + vector& list, + const string& tag, + const int n) +{ + string line; + if (! getline(fin, line)) + { + cout << "Expected txt " << tag << " line " << n << endl; + return false; + } + + list.clear(); + splitIntoWords(line, list); + return true; +} + + +bool get_head_element( + const string& elem, + const string& expected) +{ + if (elem != expected) + { + cout << "PBN list does not start with " << expected << + ": '" << elem << "'" << endl; + return false; + } + else + return true; +} + + +bool get_int_element( + const string& elem, + int& res, + const string& errtext) +{ + if (! str2int(elem, res)) + { + cout << errtext << ": '" << elem << "'\n"; + return false; + } + else + return true; +} + + +bool strip_quotes( + const string& st, + char * cstr, + const string& errtag) +{ + // Could just be past the last one. + if (st.size() == 0) + return false; + + if (st.front() != '\"' || st.back() != '\"') + { + cout << errtag << " not in quotations: '" << st << "'\n"; + return false; + } + strcpy(cstr, st.substr(1, st.size()-2).c_str()); + return true; +} + + +bool strip_quotes( + const string& st, + int& res, + const string& errtag) +{ + if (st.front() != '\"' || st.back() != '\"') + { + cout << errtag << " not in quotations: '" << st << "'" << endl; + return false; + } + + if (! str2int(st.substr(1, st.size()-2).c_str(), res)) + { + cout << st << " not an int" << endl; + return false; + } + + return true; +} + + +string trimTrailing( + const string& text, + const char c) +{ + unsigned pos = static_cast(text.length()); + while (pos >= 1 && text.at(pos-1) == c) + pos--; + + if (pos == 0) + return ""; + else + return text.substr(0, pos); +} + + +void splitIntoWords( + const string& text, + vector& words) +{ + // Split into words (split on \s+, effectively). + unsigned pos = 0; + unsigned startPos = 0; + bool isSpace = true; + + // It seems compilers have different ideas about files. + const unsigned tl = text.length(); + string ttext; + if (text.back() == ' ') + ttext = text.substr(0, tl-1); + else if (text.at(tl-2) == ' ') + ttext = text.substr(0, tl-2); + else + ttext = text; + + const unsigned l = static_cast(ttext.length()); + + while (pos < l) + { + if (ttext.at(pos) == ' ') + { + if (! isSpace) + { + words.push_back(ttext.substr(startPos, pos-startPos)); + isSpace = true; + } + } + else if (isSpace) + { + isSpace = false; + startPos = pos; + } + pos++; + } + + if (! isSpace) + words.push_back(ttext.substr(startPos, pos-startPos)); +} + + +bool str2int( + const string& text, + int& res) +{ + int i; + size_t pos; + try + { + i = stoi(text, &pos); + if (pos != text.size()) + return false; + + } + catch (const invalid_argument& ia) + { + UNUSED(ia); + return false; + } + catch (const out_of_range& ia) + { + UNUSED(ia); + return false; + } + + res = i; + return true; +} + diff --git a/test/parse.h b/test/parse.h new file mode 100644 index 00000000..3512faa2 --- /dev/null +++ b/test/parse.h @@ -0,0 +1,33 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + +#ifndef DTEST_PARSE_H +#define DTEST_PARSE_H + +#include "../include/dll.h" + +using namespace std; + + +bool read_file( + const string& fname, + int& number, + bool& GIBmode, + int ** dealer_list, + int ** vul_list, + dealPBN ** deal_list, + futureTricks ** fut_list, + ddTableResults ** table_list, + parResults ** par_list, + parResultsDealer ** dealerpar_list, + playTracePBN ** play_list, + solvedPlay ** trace_list); + +#endif + diff --git a/test/print.cpp b/test/print.cpp new file mode 100644 index 00000000..fcaccb03 --- /dev/null +++ b/test/print.cpp @@ -0,0 +1,201 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#include +#include +#include + +#include "print.h" +#include "cst.h" + + +static unsigned short dbitMapRank[16]; +static unsigned char dcardRank[16]; +static unsigned char dcardSuit[5]; + +string equals_to_string(const int equals); + + +void set_constants() +{ + dbitMapRank[15] = 0x2000; + dbitMapRank[14] = 0x1000; + dbitMapRank[13] = 0x0800; + dbitMapRank[12] = 0x0400; + dbitMapRank[11] = 0x0200; + dbitMapRank[10] = 0x0100; + dbitMapRank[ 9] = 0x0080; + dbitMapRank[ 8] = 0x0040; + dbitMapRank[ 7] = 0x0020; + dbitMapRank[ 6] = 0x0010; + dbitMapRank[ 5] = 0x0008; + dbitMapRank[ 4] = 0x0004; + dbitMapRank[ 3] = 0x0002; + dbitMapRank[ 2] = 0x0001; + dbitMapRank[ 1] = 0; + dbitMapRank[ 0] = 0; + + dcardRank[ 2] = '2'; + dcardRank[ 3] = '3'; + dcardRank[ 4] = '4'; + dcardRank[ 5] = '5'; + dcardRank[ 6] = '6'; + dcardRank[ 7] = '7'; + dcardRank[ 8] = '8'; + dcardRank[ 9] = '9'; + dcardRank[10] = 'T'; + dcardRank[11] = 'J'; + dcardRank[12] = 'Q'; + dcardRank[13] = 'K'; + dcardRank[14] = 'A'; + dcardRank[15] = '-'; + + dcardSuit[0] = 'S'; + dcardSuit[1] = 'H'; + dcardSuit[2] = 'D'; + dcardSuit[3] = 'C'; + dcardSuit[4] = 'N'; +} + + +void print_PBN(const dealPBN& dl) +{ + cout << setw(10) << left << "trump" << dl.trump << "\n"; + cout << setw(10) << "first" << dl.first << "\n"; + cout << setw(10) << "cards" << dl.remainCards << "\n"; +} + + +void print_FUT(const futureTricks& fut) +{ + cout << setw(6) << left << "cards" << fut.cards << "\n"; + cout << setw(6) << right << "No." << + setw(7) << "suit" << + setw(7) << "rank" << + setw(7) << "equals" << + setw(7) << "score" << "\n"; + + for (int i = 0; i < fut.cards; i++) + { + cout << setw(6) << right << i << + setw(7) << dcardSuit[ fut.suit[i] ] << + setw(7) << dcardRank[ fut.rank[i] ] << + setw(7) << equals_to_string(fut.equals[i]) << + setw(7) << fut.score[i] << "\n"; + } +} + + +string equals_to_string(const int equals) +{ + string st = ""; + for (unsigned i = 15; i >= 2; i--) + { + if (equals & dbitMapRank[i]) + st += static_cast(dcardRank[i]); + } + return (st == "" ? "-" : st); +} + + +void print_TABLE(const ddTableResults& table) +{ + cout << setw(5) << right << "" << + setw(6) << "North" << + setw(6) << "South" << + setw(6) << "East" << + setw(6) << "West" << "\n"; + + cout << setw(5) << right << "NT" << + setw(6) << table.resTable[4][0] << + setw(6) << table.resTable[4][2] << + setw(6) << table.resTable[4][1] << + setw(6) << table.resTable[4][3] << "\n"; + + for (int suit = 0; suit <= 3; suit++) + { + cout << setw(5) << right << dcardSuit[suit] << + setw(6) << table.resTable[suit][0] << + setw(6) << table.resTable[suit][2] << + setw(6) << table.resTable[suit][1] << + setw(6) << table.resTable[suit][3] << "\n"; + } +} + + +void print_PAR(const parResults& par) +{ + cout << setw(9) << left << "NS score" << par.parScore[0] << "\n"; + cout << setw(9) << "EW score" << par.parScore[1] << "\n"; + cout << setw(9) << "NS list" << par.parContractsString[0] << "\n"; + cout << setw(9) << "EW list" << par.parContractsString[1] << "\n"; +} + + +void print_DEALERPAR(const parResultsDealer& par) +{ + cout << setw(6) << left << "Score" << par.score << "\n"; + cout << setw(6) << left << "Pars" << par.number << "\n"; + + for (int i = 0; i < par.number; i++) + cout << left << "Par " << setw(2) << i << par.contracts[i] << "\n"; +} + + +void print_PLAY(const playTracePBN& play) +{ + cout << setw(6) << right << "Number" << + setw(5) << play.number << "\n"; + + for (int i = 0; i < play.number; i++) + cout << setw(6) << i << " " << + play.cards[2*i] << play.cards[2*i+1] << "\n"; +} + + +void print_TRACE(const solvedPlay& solved) +{ + cout << setw(6) << right << "Number" << + setw(5) << solved.number << "\n"; + + for (int i = 0; i < solved.number; i++) + cout << setw(6) << i << + setw(5) << solved.tricks[i] << "\n"; +} + + +void print_double_TRACE( + const solvedPlay& solved, + const solvedPlay& ref) +{ + cout << "Number solved vs ref: " << solved.number << " vs. " << + ref.number << "\n"; + + const int m = min(solved.number, ref.number); + for (int i = 0; i < m; i++) + { + cout << "Trick " << i << ": " << + solved.tricks[i] << " vs " << + ref.tricks[i] << + (solved.tricks[i] == ref.tricks[i] ? "" : " ERROR") << "\n"; + } + + if (solved.number > m) + { + for (int i = m; i < solved.number; i++) + cout << "Solved " << i << ": " << solved.tricks[i] << "\n"; + } + else if (ref.number > m) + { + for (int i = m; i < ref.number; i++) + cout << "Ref " << i << ": " << ref.tricks[i] << "\n"; + } +} + diff --git a/test/print.h b/test/print.h new file mode 100644 index 00000000..98ccc154 --- /dev/null +++ b/test/print.h @@ -0,0 +1,42 @@ +/* + DDS, a bridge double dummy solver. + + Copyright (C) 2006-2014 by Bo Haglund / + 2014-2018 by Bo Haglund & Soren Hein. + + See LICENSE and README. +*/ + + +#ifndef DTEST_PRINT_H +#define DTEST_PRINT_H + +#include + +#include "../include/dll.h" + +using namespace std; + + +void set_constants(); + +void print_PBN(const dealPBN& dl); + +void print_FUT(const futureTricks& fut); + +void print_TABLE(const ddTableResults& table); + +void print_PAR(const parResults& par); + +void print_DEALERPAR(const parResultsDealer& par); + +void print_PLAY(const playTracePBN& play); + +void print_TRACE(const solvedPlay& solved); + +void print_double_TRACE( + const solvedPlay& solved, + const solvedPlay& ref); + +#endif + diff --git a/test/testStats.cpp b/test/testStats.cpp deleted file mode 100644 index 029debc5..00000000 --- a/test/testStats.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - - -#include -#include -#include -#include - -#include "../include/portab.h" -#include "testStats.h" - -#define NUM_TIMERS 2000 -#define COUNTER_SLOTS 200 - - -#ifdef _WIN32 - LARGE_INTEGER ttimerFreq; - LARGE_INTEGER ttimerUser0; - LARGE_INTEGER ttimerUser1; - LARGE_INTEGER ttimerListUser0[NUM_TIMERS]; - LARGE_INTEGER ttimerListUser1[NUM_TIMERS]; -#else - #include - - int TesttimevalDiff(timeval x, timeval y); - - timeval ttimerUser0; - timeval ttimerUser1; - timeval ttimerListUser0[NUM_TIMERS]; - timeval ttimerListUser1[NUM_TIMERS]; -#endif - -clock_t ttimerSys0; -clock_t ttimerSys1; -clock_t ttimerListSys0[NUM_TIMERS]; -clock_t ttimerListSys1[NUM_TIMERS]; - -int ttimerCount; -int ttimerListCount[NUM_TIMERS]; - -int ttimerNameSet; - -char ttimerName[80]; - -long long ttimerUserCum; -long long ttimerSysCum; -long long ttimerListUserCum[NUM_TIMERS]; -long long ttimerListSysCum[NUM_TIMERS]; -long long tpredError; -long long tpredAbsError; - - -void TestInitTimer() -{ - ttimerCount = 0; - ttimerUserCum = 0; - ttimerSysCum = 0; - ttimerNameSet = 0; - - tpredError = 0; - tpredAbsError = 0; -} - - -void TestSetTimerName(const char * name) -{ - strcpy(ttimerName, name); - ttimerNameSet = 1; -} - - -void TestStartTimer() -{ - ttimerCount++; - ttimerSys0 = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&ttimerUser0); -#else - gettimeofday(&ttimerUser0, nullptr); -#endif -} - - -void TestEndTimer() -{ - ttimerSys1 = clock(); - -#ifdef _WIN32 - // To get "real" seconds we would have to divide by - // timerFreq.QuadPart which needs to be initialized. - QueryPerformanceCounter(&ttimerUser1); - int ttimeUser = static_cast - ((ttimerUser1.QuadPart - ttimerUser0.QuadPart)); -#else - gettimeofday(&ttimerUser1, nullptr); - int ttimeUser = TesttimevalDiff(ttimerUser1, ttimerUser0); -#endif - - ttimerUserCum += ttimeUser; - - ttimerSysCum += static_cast((1000 * (ttimerSys1 - ttimerSys0)) / - static_cast(CLOCKS_PER_SEC)); -} - - -void TestPrintTimer() -{ - if (ttimerCount == 0) return; - - if (ttimerNameSet) - printf("%-18s : %s\n", "Timer name", ttimerName); - - printf("%-18s : %10d\n", "Number of calls", ttimerCount); - - if (ttimerUserCum == 0) - printf("%-18s : %s\n", "User time", "zero"); - else - { - printf("%-18s : %10lld\n", "User time/ticks", ttimerUserCum); - printf("%-18s : %10.2f\n", "User per call", - static_cast(ttimerUserCum / ttimerCount)); - } - - if (ttimerSysCum == 0) - printf("%-18s : %s\n", "Sys time", "zero"); - else - { - printf("%-18s : %10lld\n", "Sys time/ticks", ttimerSysCum); - printf("%-18s : %10.2f\n", "Sys per call", - static_cast(ttimerSysCum / ttimerCount)); - printf("%-18s : %10.2f\n", "Ratio", - static_cast(ttimerSysCum / ttimerUserCum)); - } - printf("\n"); -} - - -void TestInitTimerList() -{ - for (int i = 0; i < NUM_TIMERS; i++) - { - ttimerListCount [i] = 0; - ttimerListUserCum[i] = 0; - ttimerListSysCum [i] = 0; - } -} - - -void TestStartTimerNo(int no) -{ - ttimerListCount[no]++; - ttimerListSys0[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&ttimerListUser0[no]); -#else - gettimeofday(&ttimerListUser0[no], nullptr); -#endif -} - - -void TestEndTimerNo(int no) -{ - ttimerListSys1[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&ttimerListUser1[no]); - int timeUser = static_cast - ((ttimerListUser1[no].QuadPart - ttimerListUser0[no].QuadPart)); -#else - gettimeofday(&ttimerListUser1[no], nullptr); - int timeUser = TesttimevalDiff(ttimerListUser1[no], - ttimerListUser0[no]); -#endif - - ttimerListUserCum[no] += static_cast(timeUser); - - ttimerListSysCum[no] += - static_cast((1000 * - (ttimerListSys1[no] - ttimerListSys0[no])) / - static_cast(CLOCKS_PER_SEC)); -} - - -void TestEndTimerNoAndComp(int no, int pred) -{ - ttimerListSys1[no] = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&ttimerListUser1[no]); - int timeUser = static_cast - ((ttimerListUser1[no].QuadPart - ttimerListUser0[no].QuadPart)); -#else - gettimeofday(&ttimerListUser1[no], nullptr); - int timeUser = TesttimevalDiff(ttimerListUser1[no], - ttimerListUser0[no]); -#endif - - ttimerListUserCum[no] += static_cast(timeUser); - - tpredError += timeUser - pred; - - tpredAbsError += (timeUser >= pred ? - timeUser - pred : pred - timeUser); - - ttimerListSysCum[no] += - static_cast( - (1000 * (ttimerListSys1[no] - ttimerListSys0[no])) / - static_cast(CLOCKS_PER_SEC)); -} - - -void TestPrintTimerList() -{ - int totNum = 0; - for (int no = 0; no < NUM_TIMERS; no++) - { - if (ttimerListCount[no] == 0) - continue; - - totNum += ttimerListCount[no]; - } - - if (totNum == 0) - return; - - printf("%5s %10s %12s %10s %10s\n", - "n", "Number", "User ticks", "Avg", "Syst time"); - - for (int no = 0; no < NUM_TIMERS; no++) - { - double avg = static_cast(ttimerListUserCum[no]) / - static_cast(ttimerListCount[no]); - - // For some reason I have trouble when putting it on one line... - printf("%5d %10d %12lld ", - no, - ttimerListCount[no], - ttimerListUserCum[no]); - printf(" %10.2f %10lld\n", - avg, - ttimerListSysCum[no]); - } - printf("\n"); - if (tpredError != 0) - { - printf("Total number %10d\n", totNum); - printf("Prediction mean %10.0f\n", - static_cast(tpredError) / - static_cast(totNum)); - printf("Prediction abs mean %10.0f\n", - static_cast(tpredAbsError) / - static_cast(totNum)); - printf("\n"); - } -} - - -#ifndef _WIN32 -int TesttimevalDiff(timeval x, timeval y) -{ - /* Elapsed time, x-y, in milliseconds */ - return 1000 * (x.tv_sec - y.tv_sec ) - + (x.tv_usec - y.tv_usec) / 1000; -} -#endif - - -long long tcounter[COUNTER_SLOTS]; - -void TestInitCounter() -{ - for (int i = 0; i < COUNTER_SLOTS; i++) - tcounter[i] = 0; -} - - -void TestPrintCounter() -{ - for (int i = 0; i < COUNTER_SLOTS; i++) - { - if (tcounter[i]) - printf("%d\t%12lld\n", i, tcounter[i]); - } - printf("\n"); -} - - diff --git a/test/testStats.h b/test/testStats.h deleted file mode 100644 index 80a23160..00000000 --- a/test/testStats.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - DDS, a bridge double dummy solver. - - Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. - - See LICENSE and README. -*/ - - -#ifndef DDS_STATSH -#define DDS_STATSH - -void TestInitTimer(); - -void TestSetTimerName(const char * name); - -void TestStartTimer(); - -void TestEndTimer(); - -void TestPrintTimer(); - -void TestInitTimerList(); - -void TestStartTimerNo(int n); - -void TestEndTimerNo(int n); - -void TestEndTimerNoAndComp(int n, int pred); - -void TestPrintTimerList(); - -void TestInitCounter(); - -void TestPrintCounter(); - -#endif diff --git a/test/testcommon.cpp b/test/testcommon.cpp index 35dcdb91..18b3a3ef 100644 --- a/test/testcommon.cpp +++ b/test/testcommon.cpp @@ -2,98 +2,82 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ -#include -#include -#include -#include +#include +#include +#include + #include "../include/dll.h" #include "../include/portab.h" -#include "testStats.h" - -#ifdef _WIN32 - LARGE_INTEGER frequency, tu0, tu1; -#else -#include - timeval tu0, tu1; -#endif +#include "testcommon.h" +#include "TestTimer.h" +#include "parse.h" +#include "loop.h" +#include "compare.h" +#include "print.h" +#include "cst.h" -#include "dtest.h" +using namespace std; +string GetSystem(); +string GetBits(); +string GetCompiler(); -#define SOLVE_SIZE MAXNOOFBOARDS -#define BOARD_SIZE MAXNOOFTABLES -#define TRACE_SIZE MAXNOOFBOARDS -#define PAR_REPEAT 1 - -int input_number; -bool GIBmode = false; +const vector DDS_SYSTEM_PLATFORM = +{ + "", + "Windows", + "Cygwin", + "Linux", + "Apple" +}; -// #define DEBUG -#define BATCHTIMES -#define ZERO (static_cast('0')) -#define NINE (static_cast('9')) -#define SPACE (static_cast(' ')) -#define QUOTE (static_cast('"')) +const vector DDS_SYSTEM_COMPILER = +{ + "", + "Microsoft Visual C++", + "MinGW", + "GNU g++", + "clang" +}; +extern OptionsType options; +TestTimer timer; -clock_t ts0, ts1; -int tu , ts, ctu, cts; +void main_identify(); -int realMain(int argc, char * argv[]); int realMain(int argc, char * argv[]) { - input_number = 0; - ctu = 0; - cts = 0; - - TestSetTimerName("Timer title"); - - if (argc != 3 && argc != 4) - { - printf( - "Usage: dtest file.txt solve|calc|par|dealerpar|play [ncores]\n"); - return 1; - } - - char * fname = argv[1]; - char * type = argv[2]; - - if (! strcmp(type, "solve")) - input_number = SOLVE_SIZE; - else if (! strcmp(type, "calc")) - input_number = BOARD_SIZE; - else if (! strcmp(type, "par")) - input_number = PAR_REPEAT; - else if (! strcmp(type, "dealerpar")) - input_number = PAR_REPEAT; - else if (! strcmp(type, "play")) - input_number = TRACE_SIZE; + UNUSED(argc); + UNUSED(argv); + bool GIBmode = false; + + int stepsize = 0; + if (options.solver == DTEST_SOLVER_SOLVE) + stepsize = MAXNOOFBOARDS; + else if (options.solver == DTEST_SOLVER_CALC) + stepsize = MAXNOOFTABLES; + else if (options.solver == DTEST_SOLVER_PLAY) + stepsize = MAXNOOFBOARDS; + else if (options.solver == DTEST_SOLVER_PAR) + stepsize = 1; + else if (options.solver == DTEST_SOLVER_DEALERPAR) + stepsize = 1; set_constants(); main_identify(); -#ifdef _WIN32 - QueryPerformanceFrequency(&frequency); -#endif - - boardsPBN bop; - solvedBoards solvedbdp; - ddTableDealsPBN dealsp; - ddTablesRes resp; - allParResults parp; - playTracesPBN playsp; - solvedPlays solvedplp; + int number; int * dealer_list; int * vul_list; dealPBN * deal_list; @@ -103,69 +87,62 @@ int realMain(int argc, char * argv[]) parResultsDealer * dealerpar_list; playTracePBN * play_list; solvedPlay * trace_list; - int number; - - if (read_file(fname, &number, &dealer_list, &vul_list, + if (read_file(options.fname, number, GIBmode, &dealer_list, &vul_list, &deal_list, &fut_list, &table_list, &par_list, &dealerpar_list, &play_list, &trace_list) == false) { - printf("read_file failed.\n"); + cout << "read_file failed\n"; exit(0); } - if (! strcmp(type, "solve")) + if (GIBmode && options.solver != DTEST_SOLVER_CALC) { - if (GIBmode) - { - printf("GIB file does not work with solve\n"); - exit(0); - } - loop_solve(&bop, &solvedbdp, deal_list, fut_list, number); + cout << "GIB file only works works with calc\n"; + exit(0); } - else if (! strcmp(type, "calc")) + + timer.reset(); + timer.setname("Hand stats"); + + boardsPBN bop; + solvedBoards solvedbdp; + ddTableDealsPBN dealsp; + ddTablesRes resp; + allParResults parp; + playTracesPBN playsp; + solvedPlays solvedplp; + + if (options.solver == DTEST_SOLVER_SOLVE) + { + loop_solve(&bop, &solvedbdp, deal_list, fut_list, number, stepsize); + } + else if (options.solver == DTEST_SOLVER_CALC) { - loop_calc(&dealsp, &resp, &parp, - deal_list, table_list, number); + loop_calc(&dealsp, &resp, &parp, deal_list, table_list, + number, stepsize); } - else if (! strcmp(type, "par")) + else if (options.solver == DTEST_SOLVER_PLAY) { - if (GIBmode) - { - printf("GIB file does not work with solve\n"); - exit(0); - } - loop_par(vul_list, table_list, par_list, number); + loop_play(&bop, &playsp, &solvedplp, deal_list, play_list, trace_list, + number, stepsize); } - else if (! strcmp(type, "dealerpar")) + else if (options.solver == DTEST_SOLVER_PAR) { - if (GIBmode) - { - printf("GIB file does not work with solve\n"); - exit(0); - } - loop_dealerpar(dealer_list, vul_list, table_list, - dealerpar_list, number); + loop_par(vul_list, table_list, par_list, number, stepsize); } - else if (! strcmp(type, "play")) + else if (options.solver == DTEST_SOLVER_DEALERPAR) { - if (GIBmode) - { - printf("GIB file does not work with solve\n"); - exit(0); - } - loop_play(&bop, &playsp, &solvedplp, - deal_list, play_list, trace_list, number); + loop_dealerpar(dealer_list, vul_list, table_list, dealerpar_list, + number, stepsize); } else { - printf("Unknown type %s\n", type); + cout << "Unknown type " << + static_cast(options.solver) << "\n"; exit(0); } - print_times(number); - TestPrintTimer(); - TestPrintTimerList(); - TestPrintCounter(); + timer.printHands(); free(dealer_list); free(vul_list); @@ -181,1205 +158,77 @@ int realMain(int argc, char * argv[]) } -void main_identify() -{ - printf("dtest main\n----------\n"); - -#if defined(_WIN32) || defined(__CYGWIN__) - printf("%-12s %20s\n", "System", "Windows"); -#if defined(_MSC_VER) - printf("%-12s %20s\n", "Compiler", "Microsoft Visual C++"); -#elif defined(__MINGW32__) - printf("%-12s %20s\n", "Compiler", "MinGW"); -#else - printf("%-12s %20s\n", "Compiler", "GNU g++"); -#endif +////////////////////////////////////////////////////////////////////// +// Self-identification // +////////////////////////////////////////////////////////////////////// +string GetSystem() +{ + unsigned sys; +#if defined(_WIN32) + sys = 1; +#elif defined(__CYGWIN__) + sys = 2; #elif defined(__linux) - printf("%-12s %20s\n", "System", "Linux"); - printf("%-12s %20s\n", "Compiler", "GNU g++"); - + sys = 3; #elif defined(__APPLE__) - printf("%-12s %20s\n", "System", "Apple"); -#if defined(__clang__) - printf("%-12s %20s\n", "Compiler", "clang"); + sys = 4; #else - printf("%-12s %20s\n", "Compiler", "GNU g++"); -#endif -#endif - -#if defined(__cplusplus) - printf("%-12s %20ld\n", "Dialect", __cplusplus); -#endif - - printf("\n"); -} - - -void set_constants() -{ - dbitMapRank[15] = 0x2000; - dbitMapRank[14] = 0x1000; - dbitMapRank[13] = 0x0800; - dbitMapRank[12] = 0x0400; - dbitMapRank[11] = 0x0200; - dbitMapRank[10] = 0x0100; - dbitMapRank[ 9] = 0x0080; - dbitMapRank[ 8] = 0x0040; - dbitMapRank[ 7] = 0x0020; - dbitMapRank[ 6] = 0x0010; - dbitMapRank[ 5] = 0x0008; - dbitMapRank[ 4] = 0x0004; - dbitMapRank[ 3] = 0x0002; - dbitMapRank[ 2] = 0x0001; - dbitMapRank[ 1] = 0; - dbitMapRank[ 0] = 0; - - dcardRank[ 2] = '2'; - dcardRank[ 3] = '3'; - dcardRank[ 4] = '4'; - dcardRank[ 5] = '5'; - dcardRank[ 6] = '6'; - dcardRank[ 7] = '7'; - dcardRank[ 8] = '8'; - dcardRank[ 9] = '9'; - dcardRank[10] = 'T'; - dcardRank[11] = 'J'; - dcardRank[12] = 'Q'; - dcardRank[13] = 'K'; - dcardRank[14] = 'A'; - dcardRank[15] = '-'; - - dcardSuit[0] = 'S'; - dcardSuit[1] = 'H'; - dcardSuit[2] = 'D'; - dcardSuit[3] = 'C'; - dcardSuit[4] = 'N'; -} - - -bool read_file( - char * fname, - int * number, - int ** dealer_list, - int ** vul_list, - dealPBN ** deal_list, - futureTricks ** fut_list, - ddTableResults ** table_list, - parResults ** par_list, - parResultsDealer ** dealerpar_list, - playTracePBN ** play_list, - solvedPlay ** trace_list) -{ - char line[256]; - char * name; - - FILE * fp; - fp = fopen(fname, "r"); - if (fp == nullptr) - { - char backup[80]; - sprintf(backup, "../hands/%s", fname); - fp = fopen(backup, "r"); - name = backup; - if (fp == nullptr) - return false; - } - else - name = fname; - - if (! fgets(line, sizeof(line), fp)) - return false; - if (parse_NUMBER(line, number) == false) - { - if (parseable_GIB(line)) - { - GIBmode = true; - - * number = 1; - // Count lines, then start over. - while (1) - { - if (! fgets(line, sizeof(line), fp)) - break; - (*number)++; - } - - fclose(fp); - fp = fopen(name, "r"); - if (fp == nullptr) - return false; - } - else - return false; - } - - if (*number < 0 || *number > 100000) - { - printf("Suspect number %d\n", *number); - return false; - } - - size_t number_t = static_cast(* number); - - if ((*dealer_list = static_cast - (calloc(number_t, sizeof(int)))) == nullptr) - return false; - - if ((*vul_list = static_cast - (calloc(number_t, sizeof(int)))) == nullptr) - return false; - - if ((*deal_list = static_cast - (calloc(number_t, sizeof(dealPBN)))) == nullptr) - return false; - - if ((*fut_list = static_cast - (calloc(number_t, sizeof(futureTricks)))) == nullptr) - return false; - - if ((*table_list = static_cast - (calloc(number_t, sizeof(ddTableResults)))) == nullptr) - return false; - - if ((*par_list = static_cast - (calloc(number_t, sizeof(parResults)))) == nullptr) - return false; - - if ((*dealerpar_list = static_cast - (calloc(number_t, sizeof(parResultsDealer)))) == nullptr) - return false; - - if ((*play_list = static_cast - (calloc(number_t, sizeof(playTracePBN)))) == nullptr) - return false; - - if ((*trace_list = static_cast - (calloc(number_t, sizeof(solvedPlay)))) == nullptr) - return false; - - if (GIBmode) - { - int n = 0; - while (fgets(line, sizeof(line), fp)) - { - if (parse_GIB(line, &(*deal_list)[n], &(*table_list)[n]) - == false) - return false; - n++; - } - } - else - { - for (int n = 0; n < *number; n++) - { -#ifdef DEBUG - printf("Starting to read hand number %d\n", n); - printf("-------------------------------\n"); - printf("play_list[%d].number = %d\n", n, (*play_list)[n].number); -#endif - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_PBN(line, &(*dealer_list)[n], &(*vul_list)[n], - &(*deal_list)[n]) == false) return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_FUT(line, &(*fut_list)[n]) == false) return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_TABLE(line, &(*table_list)[n]) == false) return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_PAR(line, &(*par_list)[n]) == false) return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_DEALERPAR(line, &(*dealerpar_list)[n]) == false) - return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_PLAY(line, &(*play_list)[n]) == false) return false; - - if (! fgets(line, sizeof(line), fp)) return false; - if (parse_TRACE(line, &(*trace_list)[n]) == false) return false; - - /* - print_PBN (&(*deal_list )[n]); - print_FUT (&(*fut_list )[n]); - print_TABLE (&(*table_list )[n]); - print_PAR (&(*par_list )[n]); - print_DEALERPAR(&(*dealerpar_list)[n]); - print_PLAY (&(*play_list )[n]); - print_TRACE (&(*trace_list )[n]); - */ - } - } - - fclose(fp); - return 1; -} - - -bool parse_NUMBER(char * line, int * number) -{ -#ifdef DEBUG - printf("parse_NUMBER: Got line '%s'\n", line); -#endif - int pos = 0; - if (consume_tag(line, &pos, "NUMBER") == false) return false; -#ifdef DEBUG - printf("parse_NUMBER: Got tag 'NUMBER'\n"); -#endif - - if (consume_int(line, &pos, number) == false) return false; -#ifdef DEBUG - printf("parse_NUMBER: Read number %d\n", * number); -#endif - return true; -} - - -bool parse_PBN( - char * line, - int * dealer, - int * vul, - dealPBN * dl) -{ -#ifdef DEBUG - printf("parse_PBN: Got line '%s'\n", line); -#endif - int pos = 0; - if (consume_tag(line, &pos, "PBN") == false) return false; -#ifdef DEBUG - printf("parse_PBN: Got tag 'PBN'\n"); -#endif - - if (consume_int(line, &pos, dealer) == false) return false; -#ifdef DEBUG - printf("parse_PBN: Read dealer %d\n", * dealer); -#endif - - if (consume_int(line, &pos, vul) == false) return false; -#ifdef DEBUG - printf("parse_PBN: Read vul %d\n", * dealer); -#endif - - if (consume_int(line, &pos, &dl->trump) == false) return false; -#ifdef DEBUG - printf("parse_PBN: Read trump %d\n", dl->trump); -#endif - - if (consume_int(line, &pos, &dl->first) == false) return false; -#ifdef DEBUG - printf("parse_PBN: Read first %d\n", dl->first); -#endif - - if (consume_string(line, &pos, dl->remainCards) == false) - return false; -#ifdef DEBUG - printf("parse_PBN: Read string '%s'\n", dl->remainCards); -#endif - - return true; -} - - -bool parse_FUT(char * line, futureTricks * fut) -{ -#ifdef DEBUG - printf("parse_FUT: Got line '%s'\n", line); -#endif - int pos = 0; - if (consume_tag(line, &pos, "FUT") == false) return false; -#ifdef DEBUG - printf("parse_FUT: Got tag 'FUT'\n"); -#endif - - if (consume_int(line, &pos, &fut->cards) == false) return false; -#ifdef DEBUG - printf("parse_FUT: Read cards %d\n", fut->cards); -#endif - - for (int c = 0; c < fut->cards; c++) - { - if (consume_int(line, &pos, &fut->suit[c]) == false) return false; -#ifdef DEBUG - printf("parse_FUT: Read suit[%d]: %d\n", c, fut->suit[c]); -#endif - } - - for (int c = 0; c < fut->cards; c++) - { - if (consume_int(line, &pos, &fut->rank[c]) == false) return false; -#ifdef DEBUG - printf("parse_FUT: Read rank[%d]: %d\n", c, fut->rank[c]); -#endif - } - - for (int c = 0; c < fut->cards; c++) - { - if (consume_int(line, &pos, &fut->equals[c]) == false) return false; -#ifdef DEBUG - printf("parse_FUT: Read equals[%d]: %d\n", c, fut->equals[c]); -#endif - } - - for (int c = 0; c < fut->cards; c++) - { - if (consume_int(line, &pos, &fut->score[c]) == false) return false; -#ifdef DEBUG - printf("parse_FUT: Read score[%d]: %d\n", c, fut->score[c]); -#endif - } - - return true; -} - - -bool parse_TABLE(char * line, ddTableResults * table) -{ - int pos = 0; - if (consume_tag(line, &pos, "TABLE") == false) return false; -#ifdef DEBUG - printf("parse_FUT: Got tag 'TABLE'\n"); -#endif - - for (int suit = 0; suit <= 4; suit++) - { - for (int pl = 0; pl <= 3; pl++) - { - if (consume_int(line, &pos, &table->resTable[suit][pl]) == false) - return false; -#ifdef DEBUG - printf("parse_TABLE: Read table[%d][%d] = %d\n", - suit, pl, table->resTable[suit][pl]); -#endif - } - } - return true; -} - - -bool parse_PAR(char * line, parResults * par) -{ -#ifdef DEBUG - printf("parse_PAR: Got line '%s'\n", line); -#endif - - int pos = 0; - if (consume_tag(line, &pos, "PAR") == false) return false; -#ifdef DEBUG - printf("parse_PAR: Got tag 'PAR'\n"); -#endif - - if (consume_string(line, &pos, par->parScore[0]) == false) - return false; -#ifdef DEBUG - printf("parse_PAR: Read string '%s'\n", par->parScore[0]); -#endif - - if (consume_string(line, &pos, par->parScore[1]) == false) - return false; -#ifdef DEBUG - printf("parse_PAR: Read string '%s'\n", par->parScore[1]); -#endif - - if (consume_string(line, &pos, par->parContractsString[0]) == false) - return false; -#ifdef DEBUG - printf("parse_PAR: Read string '%s'\n", par->parContractsString[0]); -#endif - - if (consume_string(line, &pos, par->parContractsString[1]) == false) - return false; -#ifdef DEBUG - printf("parse_PAR: Read string '%s'\n", par->parContractsString[1]); -#endif - - return true; -} - - -bool parse_DEALERPAR(char * line, parResultsDealer * par) -{ -#ifdef DEBUG - printf("parse_DEALERPAR: Got line '%s'\n", line); -#endif - - int pos = 0; - if (consume_tag(line, &pos, "PAR2") == false) return false; -#ifdef DEBUG - printf("parse_DEALERPAR: Got tag 'PAR2'\n"); -#endif - - char str[256]; - if (consume_string(line, &pos, str) == false) - return false; -#ifdef DEBUG - printf("parse_DEALERPAR: Read string '%s'\n", str); -#endif - if (sscanf(str, "%d", &par->score) != 1) - return false; -#ifdef DEBUG - printf("parse_DEALERPAR: Read string '%s', number %d\n", - str, par->score); -#endif - - int no = 0; - while (1) - { - if (consume_string(line, &pos, par->contracts[no]) == false) - break; -#ifdef DEBUG - printf("parse_DEALERPAR: Read string number %d, '%s'\n", - no, par->contracts[no]); -#endif - no++; - } - - par->number = no; -#ifdef DEBUG - printf("parse_DEALERPAR: Read to number incl %d\n", no - 1); -#endif - - return true; -} - - -bool parse_PLAY(char * line, playTracePBN * playp) -{ -#ifdef DEBUG - printf("parse_PLAY: Got line '%s'\n", line); -#endif - - int pos = 0; - if (consume_tag(line, &pos, "PLAY") == false) return false; -#ifdef DEBUG - printf("parse_PLAY: Got tag 'PLAY', pos now %d\n", pos); -#endif - - if (consume_int(line, &pos, &playp->number) == false) return false; -#ifdef DEBUG - printf("parse_PLAY: Read number %d\n", playp->number); -#endif - - if (consume_string(line, &pos, playp->cards) == false) - return false; -#ifdef DEBUG - printf("parse_PLAY: Read cards '%s'\n", playp->cards); -#endif - - return true; -} - - -bool parse_TRACE(char * line, solvedPlay * solvedp) -{ -#ifdef DEBUG - printf("parse_TRACE: Got line '%s'\n", line); -#endif - - int pos = 0; - if (consume_tag(line, &pos, "TRACE") == false) return false; -#ifdef DEBUG - printf("parse_TRACE: Got tag 'TRACE'\n"); -#endif - - if (consume_int(line, &pos, &solvedp->number) == false) return false; -#ifdef DEBUG - printf("parse_TRACE: Read number %d\n", solvedp->number); -#endif - - for (int i = 0; i < solvedp->number; i++) - { - if (consume_int(line, &pos, &solvedp->tricks[i]) == false) - return false; -#ifdef DEBUG - printf("parse_TRACE: Read tricks[%d] = %d\n", i, solvedp->tricks[i]); -#endif - } - return true; -} - - -bool parseable_GIB(char line[]) -{ - if (strlen(line) != 89) - return false; - - if (line[67] != ':') - return false; - - return true; -} - -int GIB_TO_DDS[4] = {1, 0, 3, 2}; - -bool parse_GIB(char line[], dealPBN * dl, ddTableResults * table) -{ - strcpy(dl->remainCards, "W:"); - strncpy(dl->remainCards + 2, line, 67); - dl->remainCards[69] = '\0'; - - int zero = static_cast('0'); - int leta = static_cast('A') - 10; - int dds_strain, dds_hand; - - for (int s = 0; s < DDS_STRAINS; s++) - { - dds_strain = (s == 0 ? 4 : s - 1); - for (int h = 0; h < DDS_HANDS; h++) - { - dds_hand = GIB_TO_DDS[h]; - char c = line[68 + 4 * s + h]; - int d; - if (c >= '0' && c <= '9') - d = static_cast (line[68 + 4 * s + h] - zero); - else if (c >= 'A' && c <= 'F') - d = static_cast (line[68 + 4 * s + h] - leta); - else - return false; - - if (dds_hand & 1) - d = 13 - d; - - table->resTable[dds_strain][dds_hand] = d; - } - } - return true; -} - - -bool compare_PBN(dealPBN * dl1, dealPBN * dl2) -{ - if (dl1->trump != dl2->trump) return false; - if (dl1->first != dl2->first) return false; - if (strcmp(dl1->remainCards, dl2->remainCards)) return false; - return true; -} - - -bool compare_FUT(futureTricks * fut1, futureTricks * fut2) -{ - if (fut1->cards != fut2->cards) - return false; - -// TEMPNODE -// printf(" %8d\n", fut1->nodes); - for (int i = 0; i < fut1->cards; i++) - { - if (fut1->suit [i] != fut2->suit [i]) return false; - if (fut1->rank [i] != fut2->rank [i]) return false; - if (fut1->equals[i] != fut2->equals[i]) return false; - if (fut1->score [i] != fut2->score [i]) return false; - } - return true; -} - - -bool compare_TABLE(ddTableResults * table1, ddTableResults * table2) -{ - for (int suit = 0; suit <= 4; suit++) - { - for (int pl = 0; pl <= 3; pl++) - { - if (table1->resTable[suit][pl] != table2->resTable[suit][pl]) - return false; - } - } - return true; -} - - -bool compare_PAR( - parResults * par1, - parResults * par2) -{ - if (strcmp(par1->parScore[0], par2->parScore[0])) return false; - if (strcmp(par1->parScore[1], par2->parScore[1])) return false; - - if (strcmp(par1->parContractsString[0], - par2->parContractsString[0])) - return false; - if (strcmp(par1->parContractsString[1], - par2->parContractsString[1])) - return false; - return true; -} - - -bool compare_DEALERPAR( - parResultsDealer * par1, - parResultsDealer * par2) -{ - if (par1->score != par2->score) return false; - - for (int i = 0; i < par1->number; i++) - { - if (strcmp(par1->contracts[i], par2->contracts[i])) - return false; - } - return true; -} - - -bool compare_TRACE( - solvedPlay * trace1, - solvedPlay * trace2) -{ - // In a buglet, Trace returned trace1 == -3 if there is - // no input at all (trace2 is then 0). - if (trace1->number != trace2->number && - trace2->number > 0) - { - printf("number %d != %d\n", trace1->number, trace2->number); - return true; - } - - // Once that was fixed, the input file had length 0, not 1. - if (trace1->number == 1 && trace2->number == 0) - return true; - - for (int i = 0; i < trace1->number; i++) - { - if (trace1->tricks[i] != trace2->tricks[i]) - { - printf("i %d: %d != %d\n", i, trace1->tricks[i], - trace2->tricks[i]); - return false; - } - } - return true; -} - - -bool print_PBN(dealPBN * dl) -{ - printf("%10s %d\n", "trump", dl->trump); - printf("%10s %d\n", "first", dl->first); - printf("%10s %s\n", "cards", dl->remainCards); - return true; -} - - -bool print_FUT(futureTricks * fut) -{ - printf("%6s %d\n", "cards", fut->cards); - printf("%6s %-6s %-6s %-6s %-6s\n", - "", "suit", "rank", "equals", "score"); - - for (int i = 0; i < fut->cards; i++) - { - char res[15] = ""; - equals_to_string(fut->equals[i], res); - printf("%6d %-6c %-6c %-6s %-6d\n", - i, - dcardSuit[ fut->suit[i] ], - dcardRank[ fut->rank[i] ], - res, - fut->score[i]); - } - return true; -} - - -void equals_to_string(int equals, char * res) -{ - int p = 0; - for (int i = 15; i >= 2; i--) - { - if (equals & dbitMapRank[i]) - res[p++] = static_cast(dcardRank[i]); - } - res[p] = 0; -} - - -bool print_TABLE(ddTableResults * table) -{ - printf("%5s %-5s %-5s %-5s %-5s\n", - "", "North", "South", "East", "West"); - - printf("%5s %5d %5d %5d %5d\n", - "NT", - table->resTable[4][0], - table->resTable[4][2], - table->resTable[4][1], - table->resTable[4][3]); - - for (int suit = 0; suit <= 3; suit++) - { - printf("%5c %5d %5d %5d %5d\n", - dcardSuit[suit], - table->resTable[suit][0], - table->resTable[suit][2], - table->resTable[suit][1], - table->resTable[suit][3]); - } - return true; -} - - -bool print_PAR(parResults * par) -{ - printf("NS score: %s\n", par->parScore[0]); - printf("EW score: %s\n", par->parScore[1]); - printf("NS list : %s\n", par->parContractsString[0]); - printf("EW list : %s\n", par->parContractsString[1]); - return true; -} - - -bool print_DEALERPAR(parResultsDealer * par) -{ - printf("Score : %d\n", par->score); - printf("Pars : %d\n", par->number); - - for (int i = 0; i < par->number; i++) - { - printf("Par %d: %s\n", i, par->contracts[i]); - } - return true; -} - - -bool print_PLAY(playTracePBN * play) -{ - printf("Number : %d\n", play->number); - - for (int i = 0; i < play->number; i++) - { - printf("Play %d: %c%c\n", i, play->cards[2 * i], play->cards[2 * i + 1]); - } - return true; -} - - -bool print_TRACE(solvedPlay * solvedp) -{ - printf("Number : %d\n", solvedp->number); - - for (int i = 0; i < solvedp->number; i++) - { - printf("Trick %d: %d\n", i, solvedp->tricks[i]); - } - return true; -} - - -void loop_solve( - boardsPBN * bop, - solvedBoards * solvedbdp, - dealPBN * deal_list, - futureTricks * fut_list, - int number) -{ -#ifdef BATCHTIMES - printf("%8s %24s\n", "Hand no.", "Time"); -#endif - - for (int i = 0; i < number; i += input_number) - { - int count = (i + input_number > number ? number - i : input_number); - - bop->noOfBoards = count; - for (int j = 0; j < count; j++) - { - bop->deals[j] = deal_list[i + j]; - bop->target[j] = -1; - bop->solutions[j] = 3; - bop->mode[j] = 1; - } - - timer_start(); - int ret; - if ((ret = SolveAllChunks(bop, solvedbdp, 1)) - != RETURN_NO_FAULT) - { - printf("loop_solve i %i: Return %d\n", i, ret); - exit(0); - } - tu = timer_end(); - -#ifdef BATCHTIMES - printf("%8d (%5.1f%%) %15d\n", - i + count, - 100. * (i + count) / static_cast(number), - tu); - fflush(stdout); -#endif - - for (int j = 0; j < count; j++) - { - if (! compare_FUT(&solvedbdp->solvedBoard[j], &fut_list[i + j])) - { - printf("loop_solve i %d, j %d: Difference\n", i, j); - } - } - } - -#ifdef BATCHTIMES - printf("\n"); -#endif - -} - - -bool loop_calc( - ddTableDealsPBN * dealsp, - ddTablesRes * resp, - allParResults * parp, - dealPBN * deal_list, - ddTableResults * table_list, - int number) -{ -#ifdef BATCHTIMES - printf("%8s %24s\n", "Hand no.", "Time"); -#endif - - int filter[5] = {0, 0, 0, 0, 0}; - - for (int i = 0; i < number; i += input_number) - { - int count = (i + input_number > number ? number - i : input_number); - dealsp->noOfTables = count; - for (int j = 0; j < count; j++) - { - strcpy(dealsp->deals[j].cards, deal_list[i + j].remainCards); - } - - timer_start(); - int ret; - if ((ret = CalcAllTablesPBN(dealsp, -1, filter, resp, parp)) - != RETURN_NO_FAULT) - { - printf("loop_solve i %i: Return %d\n", i, ret); - exit(0); - } - tu = timer_end(); - -#ifdef BATCHTIMES - printf("%8d (%5.1f%%) %15d\n", - i + count, - 100. * (i + count) / static_cast(number), - tu); - fflush(stdout); + sys = 0; #endif - - for (int j = 0; j < count; j++) - if (! compare_TABLE(&resp->results[j], &table_list[i + j])) - { - printf("loop_calc table i %d, j %d: Difference\n", i, j); - print_TABLE( &resp->results[j] ); - print_TABLE( &table_list[i + j]) ; - } - } - -#ifdef BATCHTIMES - printf("\n"); -#endif - - return true; + + return DDS_SYSTEM_PLATFORM[sys]; } - -bool loop_par( - int * vul_list, - ddTableResults * table_list, - parResults * par_list, - int number) +string GetBits() { - /* This is so fast that there is no batch or multi-threaded - version. We run it many times just to get meaningful times. */ - - parResults presp; - - for (int i = 0; i < number; i++) - { - for (int j = 0; j < input_number; j++) - { - int ret; - if ((ret = Par(&table_list[i], &presp, vul_list[i])) - != RETURN_NO_FAULT) - { - printf("loop_par i %i, j %d: Return %d\n", i, j, ret); - exit(0); - } - } - - if (! compare_PAR(&presp, &par_list[i])) - { - printf("loop_par i %d: Difference\n", i); - } - } - - return true; -} - - -bool loop_dealerpar( - int * dealer_list, - int * vul_list, - ddTableResults * table_list, - parResultsDealer * dealerpar_list, - int number) -{ - /* This is so fast that there is no batch or multi-threaded - version. We run it many times just to get meaningful times. */ - - parResultsDealer presp; - - for (int i = 0; i < number; i++) - { - for (int j = 0; j < input_number; j++) - { - int ret; - if ((ret = DealerPar(&table_list[i], &presp, - dealer_list[i], vul_list[i])) - != RETURN_NO_FAULT) - { - printf("loop_dealerpar i %i, j %d: Return %d\n", i, j, ret); - exit(0); - } - } - - if (! compare_DEALERPAR(&presp, &dealerpar_list[i])) - { - printf("loop_dealerpar i %d: Difference\n", i); - } - } - - return true; -} - - -bool loop_play( - boardsPBN * bop, - playTracesPBN * playsp, - solvedPlays * solvedplp, - dealPBN * deal_list, - playTracePBN * play_list, - solvedPlay * trace_list, - int number) -{ -#ifdef BATCHTIMES - printf("%8s %24s\n", "Hand no.", "Time"); -#endif - - for (int i = 0; i < number; i += input_number) - { - int count = (i + input_number > number ? number - i : input_number); - - bop->noOfBoards = count; - playsp->noOfBoards = count; - - for (int j = 0; j < count; j++) - { - bop->deals[j] = deal_list[i + j]; - bop->target[j] = 0; - bop->solutions[j] = 3; - bop->mode[j] = 1; - - playsp->plays[j] = play_list[i + j]; - } - - timer_start(); - int ret; - if ((ret = AnalyseAllPlaysPBN(bop, playsp, solvedplp, 1)) - != RETURN_NO_FAULT) - { - printf("loop_play i %i: Return %d\n", i, ret); - exit(0); - } - tu = timer_end(); - -#ifdef BATCHTIMES - printf("%8d (%5.1f%%) %15d\n", - i + count, - 100. * (i + count) / static_cast(number), - tu); - fflush(stdout); -#endif - - for (int j = 0; j < count; j++) - { - if (! compare_TRACE(&solvedplp->solved[j], &trace_list[i + j])) - { - printf("loop_play i %d, j %d: Difference\n", i, j); - // printf("trace_list[%d]: \n", i+j); - // print_TRACE(&trace_list[i+j]); - // printf("solvedplp[%d]: \n", j); - // print_TRACE(&solvedplp->solved[j]); - } - } - } - -#ifdef BATCHTIMES - printf("\n"); -#endif - - return true; -} - - -void print_times(int number) -{ - printf("%-20s %12d\n", "Number of hands", number); - if (number == 0) return; - - if (ctu == 0) - printf("%-20s %12s\n", "User time (ms)", "zero"); + if (sizeof(void *) == 4) + return "32 bits"; + else if (sizeof(void *) == 8) + return "64 bits"; else - { - printf("%-20s %12d\n", "User time (ms)", ctu); - printf("%-20s %12.2f\n", "Avg user time (ms)", - ctu / static_cast(number)); - } - - if (cts == 0) - printf("%-20s %12s\n", "Syst time", "zero"); - else - { - printf("%-20s %12d\n", "Syst time (ms)", cts); - printf("%-20s %12.2f\n", "Avg syst time (ms)", - cts / static_cast(number)); - printf("%-20s %12.2f\n", "Ratio", - cts / static_cast(ctu)); - } - printf("\n"); -} - - -#ifndef _WIN32 -int timeval_diff(timeval x, timeval y) -{ - /* Elapsed time, x-y, in milliseconds */ - return 1000 * (x.tv_sec - y.tv_sec ) - + (x.tv_usec - y.tv_usec) / 1000; -} -#endif - - -void timer_start() -{ - ts0 = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&tu0); -#else - gettimeofday(&tu0, nullptr); -#endif + return "unknown"; } -int timer_end() +string GetCompiler() { - ts1 = clock(); - -#ifdef _WIN32 - QueryPerformanceCounter(&tu1); - tu = static_cast - ((tu1.QuadPart - tu0.QuadPart) * 1000. / frequency.QuadPart); + unsigned comp; +#if defined(_MSC_VER) + comp = 1; +#elif defined(__MINGW32__) + comp = 2; +#elif defined(__clang__) + comp = 4; // Out-of-order on purpose +#elif defined(__GNUC__) + comp = 3; #else - gettimeofday(&tu1, nullptr); - tu = timeval_diff(tu1, tu0); + comp = 0; #endif - ctu += tu; - ts = static_cast - ( (1000 * - static_cast(ts1 - ts0) / - static_cast(CLOCKS_PER_SEC))); -// TEMPNODE -// printf("%8d", ts); - cts += ts; - return tu; + return DDS_SYSTEM_COMPILER[comp]; } -bool consume_int( - char * line, - int * pos, - int * res) -{ - /* Too much Perl programming spoils one... No doubt there - is a good way to do this in C. */ - - int len = static_cast(strlen(line)); - int i = * pos; - int value = 0; - while (i < len && - static_cast(line[i]) >= ZERO && - static_cast(line[i]) <= NINE) - { - value = 10 * value + static_cast(line[i++]) - ZERO; - } - if (static_cast(line[i]) != SPACE) - { - printf("Doesn't end on space\n"); - return false; - } - *pos = i + 1; - *res = value; - return true; -} - -bool consume_string( - char * line, - int * pos, - char * res) +void main_identify() { - int len = static_cast(strlen(line)); - int i = * pos; + cout << "test program\n"; + cout << string(13, '-') << "\n"; - if (static_cast(line[i]) != QUOTE) return false; - i++; + const string strSystem = GetSystem(); + cout << left << setw(13) << "System" << + setw(20) << right << strSystem << "\n"; - while (i < len && static_cast(line[i]) != QUOTE) - i++; + const string strBits = GetBits(); + cout << left << setw(13) << "Word size" << + setw(20) << right << strBits << "\n"; - if (static_cast(line[i] ) != QUOTE) return false; - if (static_cast(line[i + 1]) != SPACE) return false; - i += 2; - - strncpy(res, line + *pos + 1, static_cast(i - *pos - 3)); - res[i - *pos - 3] = '\0'; - *pos = i; - return true; + const string strCompiler = GetCompiler(); + cout << left << setw(13) << "Compiler" << + setw(20) << right << strCompiler << "\n\n"; } -bool consume_tag( - char * line, - int * pos, - const char * tag) -{ - int len = static_cast(strlen(line)); - int i = * pos; - char read[80] = ""; - while (i < len && static_cast(line[i]) != SPACE) - { - i++; - } - i++; - - strncpy(read, line + *pos, static_cast(i - *pos - 1)); - if (strcmp(read, tag)) return false; - - *pos = i; - return true; -} - - -void dump_string( - const char * line) -{ - int len = static_cast(strlen(line)); - printf("Dumping len %d\n", len); - for (int i = 0; i <= len; i++) - { - printf("%2d %c %d\n", i, line[i], static_cast(line[i])); - } -} diff --git a/test/testcommon.h b/test/testcommon.h index a8e0cf95..7413eb24 100644 --- a/test/testcommon.h +++ b/test/testcommon.h @@ -2,11 +2,15 @@ DDS, a bridge double dummy solver. Copyright (C) 2006-2014 by Bo Haglund / - 2014-2016 by Bo Haglund & Soren Hein. + 2014-2018 by Bo Haglund & Soren Hein. See LICENSE and README. */ +#ifndef DTEST_TESTCOMMON_H +#define DTEST_TESTCOMMON_H int realMain(int argc, char * argv[]); +#endif +